W.I.P. collab editor:

- Implement discard changes action
This commit is contained in:
Hadi Nategh 2016-08-22 17:46:48 +02:00
parent 7abf44c6a3
commit 6d80f6c351
4 changed files with 177 additions and 5 deletions

View File

@ -60,7 +60,7 @@ class filemanager_collab extends filemanager_collab_bo {
*/
function leave_session ($es_id, $member_id)
{
if (!$this->is_sessionValid($es_id)) throw new Exception ('Session is not valid!');
if (!$this->is_sessionValid($es_id) || !$this->is_memberValid($es_id, $member_id)) throw new Exception ('Session is not valid!');
return array (
'session_id' => $es_id,
'memberid' => $member_id,
@ -95,6 +95,17 @@ class filemanager_collab extends filemanager_collab_bo {
$memberid = $params['args']['member_id']? $params['args']['member_id']: '';
$es_id = $params['args']['es_id'];
$seq_head = (string) isset($params['args']['seq_head'])? $params['args']['seq_head']: null;
// we need to inform clients about session changes to update themselves
// based on that. For instance, after discarding changes other participants
// should get notified to reload their session.
if (!$this->is_memberValid($es_id, $memberid)) {
$response = array (
'result' => 'error',
'error' => 'ENOSESSION'
);
throw new Exception('Session is not valid!');
}
if(!is_null($seq_head))
{
$client_ops = $params['args']['client_ops']? $params['args']['client_ops']: [];
@ -163,6 +174,8 @@ class filemanager_collab extends filemanager_collab_bo {
}
/**
* Ajax function to handle actions called by client-side
* types: save, delete, discard
*
* @param type $es_id
* @param type $action
@ -177,6 +190,11 @@ class filemanager_collab extends filemanager_collab_bo {
case 'delete':
$this->SESSION_cleanup($es_id);
break;
case 'discard':
$this->OP_Discard($es_id);
break;
default:
//
}
}
@ -211,6 +229,20 @@ class filemanager_collab extends filemanager_collab_bo {
return $session? true : false;
}
/**
* Check if the member id of the session has valid status
* status: 1 is valid 0 is invalid
*
* @param type $es_id
* @param type $member_id
* @return boolean returns true if it's valid
*/
function is_memberValid ($es_id, $member_id)
{
$member = $this->MEMBER_getMember($es_id, $member_id);
return $member && $member['status'] != 0 ? true: false;
}
/**
* Function to get genesis url by generating a temp genesis temp file
* out of given path, and returnig es_id md5 hash and genesis url to

View File

@ -231,6 +231,35 @@ class filemanager_collab_bo
$this->OP_add2Db($op, $es_id);
}
/**
* Function to discard all changes applied to a session
* @param type $es_id
*/
public function OP_Discard ($es_id)
{
$this->db->update(
self::MEMBER_TABLE,
array('collab_status' => 0),
array('collab_es_id' => $es_id),
__LINE__,
__FILE__,
'filemanager'
);
$this->db->delete(
self::OP_TABLE,
array('collab_es_id' => $es_id),
__LINE__,
__FILE__,
'filemanager'
);
$this->db->delete(
self::SESSION_TABLE,
array('collab_es_id' => $es_id),
__LINE__,
__FILE__
);
}
/**
* Function to remove member from list
*
@ -405,6 +434,28 @@ class filemanager_collab_bo
return is_array($member)? $member['collab_member_id']: null;
}
/**
* Function to get member record of a session
*
* @param string $es_id session id
*
* @return array array of records or null
* @throws Exception throws exception if no member id is given
*/
protected function MEMBER_getMember ($es_id, $member_id)
{
if (!$es_id) throw new Exception (self::EXCEPTION_MESSAGE_NO_SESSION);
$query = $this->db->select(
self::MEMBER_TABLE,
'*',
array('collab_es_id' => $es_id, 'collab_member_id' => $member_id),
__LINE__,
__FILE__
);
$member = $query->fetchRow();
return is_array($member)? self::db2id($member): null;
}
/**
* Utility function to map DB fields to ids
*

View File

@ -1505,6 +1505,7 @@ class filemanager_ui
if (!Api\Vfs::check_access($paths[1], Api\Vfs::WRITABLE))
{
unset ($actions['save']);
unset ($actions['discard']);
unset ($actions['delete']);
}
$tmpl->setElementAttribute('tools', 'actions', $actions);
@ -1558,6 +1559,14 @@ class filemanager_ui
'onExecute' => 'javaScript:app.filemanager.editor_delete',
'allowOnMultiple' => false,
'toolbarDefault' => false
),
'discard' => array(
'caption' => 'Discard',
'icon' => 'delete',
'group' => ++$group,
'onExecute' => 'javaScript:app.filemanager.editor_discard',
'allowOnMultiple' => false,
'toolbarDefault' => false
)
);
return $actions;

View File

@ -365,6 +365,39 @@ app.classes.filemanager = app.classes.filemanager.extend({
return path;
},
/**
* This function gets called after discard action to
* notify particioant to join to the new session or
* save as the document to not lose changes.
*
*/
editor_discarded: function ()
{
var self = this;
var buttons = [
{"button_id": 1,"text": 'reload', id: 'reload', image: 'check' },
{"button_id": 0,"text": 'save as', id: 'save', image: 'cancel', "default":true}
]
et2_dialog.show_dialog(
function(_btn)
{
if (_btn == 'save')
{
self.editor_save({id:'saveas'});
}
else if (_btn == 'reload')
{
window.location.reload();
}
},
egw.lang('All the changes has been discarded and new session created! Save as your local changes if you need them or reload to join new session.'),
'Delete file',
null,
buttons,
et2_dialog.WARNING_MESSAGE
);
},
/**
* Function to create collab editor
*
@ -384,11 +417,24 @@ app.classes.filemanager = app.classes.filemanager.extend({
/**
* Editor error handler function
* @param {type} e
*
* this function also been used in order to notify
* participant about session changes.
*
* @param {string} e
*/
function handleEditingError (e)
{
switch (e)
{
// This type of error happens when the session is discarded or
// the document has been deleted and all records in database's been removed.
case 'sessionDoesNotExist':
this.editor_discarded();
break;
default:
console.log(e)
}
};
function onEditing ()
@ -412,7 +458,7 @@ app.classes.filemanager = app.classes.filemanager.extend({
return;
}
self.editor = _editor;
self.editor.addEventListener(Wodo.EVENT_UNKNOWNERROR, handleEditingError);
self.editor.addEventListener(Wodo.EVENT_UNKNOWNERROR, jQuery.proxy(handleEditingError, self));
self.editor.joinSession(serverFactory.createSessionBackend(sessionId, memberId, server), onEditing);
};
@ -467,8 +513,42 @@ app.classes.filemanager = app.classes.filemanager.extend({
switch(_data.action)
{
case 'delete':
if (!_data.errs) egw.json('filemanager.filemanager_collab.ajax_actions', [this.collab_server.es_id, 'delete']).sendRequest();
if (!_data.errs) egw.json('filemanager.filemanager_collab.ajax_actions', [this.collab_server.es_id, 'delete'], function(){window.close();}).sendRequest();
}
},
/**
* Discard stacked modification in session from all participants
* it will warn user about the consequences which would be removing
* all stored OP modfifications in DB. Then as result it will notify
* other participants about the action and prompt them to reload the
* session or save as the current session if they want to keep their
* changes.
*
*/
editor_discard: function ()
{
var self = this;
var buttons = [
{"button_id": 1,"text": 'discard', id: 'discard', image: 'check' },
{"button_id": 0,"text": 'cancel', id: 'cancel', image: 'cancel', "default":true}
]
et2_dialog.show_dialog(
function(_btn)
{
if (_btn == 'discard')
{
egw.json('filemanager.filemanager_collab.ajax_actions',[self.collab_server.es_id, 'discard'], function(){
window.location.reload();
}).sendRequest();
}
},
egw.lang('You are about to discard all modifications applied to this document by you and other participants. Be aware this will affect all participants and their changes on this document too.'),
'Discard all changes',
null,
buttons,
et2_dialog.WARNING_MESSAGE
);
}
});