mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-29 11:23:54 +01:00
W.I.P collab Editor:
- Migrate collab editor parts to its own module - Add dojo configuration, neccessary for running wodocollabtexteditor
This commit is contained in:
parent
a64adb19e6
commit
e8a0028cf8
@ -17,7 +17,7 @@ use EGroupware\Api\Egw;
|
|||||||
use EGroupware\Api\Etemplate;
|
use EGroupware\Api\Etemplate;
|
||||||
|
|
||||||
use EGroupware\Api\Vfs;
|
use EGroupware\Api\Vfs;
|
||||||
|
use filemanager_collab_bo;
|
||||||
/**
|
/**
|
||||||
* Filemanage user interface class
|
* Filemanage user interface class
|
||||||
*/
|
*/
|
||||||
@ -1489,6 +1489,7 @@ class filemanager_ui
|
|||||||
Api\Framework::includeCSS('/api/js/webodf/collab/app/resources/app.css');
|
Api\Framework::includeCSS('/api/js/webodf/collab/app/resources/app.css');
|
||||||
Api\Framework::includeCSS('/api/js/webodf/collab/wodocollabpane.css');
|
Api\Framework::includeCSS('/api/js/webodf/collab/wodocollabpane.css');
|
||||||
Api\Framework::includeCSS('/api/js/webodf/collab/wodotexteditor.css');
|
Api\Framework::includeCSS('/api/js/webodf/collab/wodotexteditor.css');
|
||||||
|
Api\Framework::includeJS('/filemanager/js/collab.js',null, 'filemanager');
|
||||||
|
|
||||||
$tmpl->setElementAttribute('tools', 'actions', self::getActions_edit());
|
$tmpl->setElementAttribute('tools', 'actions', self::getActions_edit());
|
||||||
$preserve = $content = array('file_path' => $file_path);
|
$preserve = $content = array('file_path' => $file_path);
|
||||||
|
@ -9,12 +9,6 @@
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*egw:uses
|
|
||||||
/api/js/webodf/collab/webodf.js;
|
|
||||||
/api/js/webodf/collab/wodocollabtexteditor.js;
|
|
||||||
/api/js/webodf/collab/dojo-amalgamation.js;
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI for filemanager
|
* UI for filemanager
|
||||||
*
|
*
|
||||||
@ -32,12 +26,6 @@ app.classes.filemanager = AppJS.extend(
|
|||||||
*/
|
*/
|
||||||
clipboard_is_cut: false,
|
clipboard_is_cut: false,
|
||||||
|
|
||||||
/*
|
|
||||||
* odf editor object
|
|
||||||
*/
|
|
||||||
editor: {},
|
|
||||||
|
|
||||||
editor_mime: RegExp(/application\/vnd\.oasis\.opendocument\.text/),
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -67,7 +55,6 @@ app.classes.filemanager = AppJS.extend(
|
|||||||
{
|
{
|
||||||
delete this.et2;
|
delete this.et2;
|
||||||
|
|
||||||
delete this.editor;
|
|
||||||
// call parent
|
// call parent
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
},
|
},
|
||||||
@ -115,15 +102,6 @@ app.classes.filemanager = AppJS.extend(
|
|||||||
this.set_readonly.apply(this, this.readonly);
|
this.set_readonly.apply(this, this.readonly);
|
||||||
delete this.readonly;
|
delete this.readonly;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name == "filemanager.editor")
|
|
||||||
{
|
|
||||||
// need to make body rock solid to avoid extra scrollbars
|
|
||||||
jQuery('body').css({overflow:'hidden'});
|
|
||||||
var self = this;
|
|
||||||
jQuery(window).on('unload', function(){self.editor.leaveSession()});
|
|
||||||
this._init_odf_collab_editor ();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1032,400 +1010,18 @@ app.classes.filemanager = AppJS.extend(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Initiate odf editor popup & load given file_path
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
_init_odf_editor: function ()
|
|
||||||
{
|
|
||||||
var widgetFilePath = this.et2.getWidgetById('file_path'),
|
|
||||||
file_path = widgetFilePath.value,
|
|
||||||
isNew = file_path == '/api/js/webodf/template.odt'? true: false,
|
|
||||||
self = this;
|
|
||||||
|
|
||||||
var onEditorCreated = function (err ,editor)
|
|
||||||
{
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
console.log('Something went wrong whilst loading editor.'+ err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.editor = editor;
|
|
||||||
self.editor.openDocumentFromUrl(egw.webserverUrl+file_path);
|
|
||||||
if (isNew) {
|
|
||||||
widgetFilePath.set_value('');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var editorOptions = {
|
|
||||||
allFeaturesEnabled: true,
|
|
||||||
userData: {
|
|
||||||
fullName: egw.user('account_fullName'),
|
|
||||||
color: 'blue'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var editor = this.et2.getWidgetById('odfEditor');
|
|
||||||
if (editor)
|
|
||||||
{
|
|
||||||
Wodo.createTextEditor('filemanager-editor_odfEditor', editorOptions, onEditorCreated);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initiate odf collab editor popup & load given file_path as active session
|
|
||||||
*/
|
|
||||||
_init_odf_collab_editor: function ()
|
|
||||||
{
|
|
||||||
|
|
||||||
var widgetFilePath = this.et2.getWidgetById('file_path'),
|
|
||||||
file_path = widgetFilePath.value;
|
|
||||||
|
|
||||||
|
|
||||||
var serverOptions = {
|
|
||||||
"serverParams": {
|
|
||||||
url:egw.link('/index.php?', {
|
|
||||||
menuaction: 'filemanager.filemanager_collab.poll'
|
|
||||||
}),
|
|
||||||
genesisUrl:egw.webserverUrl+file_path
|
|
||||||
},
|
|
||||||
"sessionId": this.editor_getSessionId(),
|
|
||||||
editorOptions: {
|
|
||||||
allFeaturesEnabled: true,
|
|
||||||
userData: {
|
|
||||||
fullName: egw.user('account_fullName'),
|
|
||||||
color: 'blue'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var editor = this.et2.getWidgetById('odfEditor');
|
|
||||||
if (editor)
|
|
||||||
{
|
|
||||||
this.create_collab_editor(serverOptions);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to close an opened document
|
|
||||||
*
|
|
||||||
* @param {object} _egwAction egw action object
|
|
||||||
* @param {function} _callback callback function gets called after close operation
|
|
||||||
*/
|
|
||||||
editor_close: function (_egwAction, _callback) {
|
|
||||||
var self = this,
|
|
||||||
action = _egwAction.id,
|
|
||||||
callback = _callback;
|
|
||||||
|
|
||||||
if (this.editor)
|
|
||||||
{
|
|
||||||
var closeFn = function ()
|
|
||||||
{
|
|
||||||
self.editor.leaveSession(function(){});
|
|
||||||
if (action != 'new')
|
|
||||||
{
|
|
||||||
window.close();
|
|
||||||
}
|
|
||||||
callback.call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
// warn user about unsaved changes
|
|
||||||
if (this.editor.isDocumentModified())
|
|
||||||
{
|
|
||||||
et2_dialog.show_dialog(
|
|
||||||
function(_btn)
|
|
||||||
{
|
|
||||||
if (_btn == 2)
|
|
||||||
{
|
|
||||||
closeFn();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'There are unsaved changes. Are you sure you want to close this document without saving them?',
|
|
||||||
'unsaved changes',
|
|
||||||
null,
|
|
||||||
et2_dialog.BUTTONS_YES_NO,
|
|
||||||
et2_dialog.WARNING_MESSAGE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
closeFn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to create a new document
|
* Method to create a new document
|
||||||
* @param {object} _egwAction egw action object
|
* @param {object} _egwAction egw action object
|
||||||
*
|
*
|
||||||
* @todo: creating new empty odt file
|
* @todo: creating new empty odt file
|
||||||
*/
|
*/
|
||||||
editor_new: function (_egwAction) {
|
list_editor_new: function (_egwAction) {
|
||||||
var self = this,
|
var self = this,
|
||||||
template_url = '/api/js/webodf/template.odt';
|
template_url = '/api/js/webodf/template.odt';
|
||||||
|
|
||||||
if (Object.keys(this.editor).length > 0)
|
|
||||||
{
|
|
||||||
this.editor_close(_egwAction, function(){
|
|
||||||
self.editor.openDocumentFromUrl(egw.webserverUrl+template_url);
|
|
||||||
self.et2.getWidgetById('file_path').set_value('');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
egw.open_link(egw.link('/index.php', {
|
egw.open_link(egw.link('/index.php', {
|
||||||
menuaction: 'filemanager.filemanager_ui.editor',
|
menuaction: 'filemanager.filemanager_ui.editor',
|
||||||
path: template_url
|
path: template_url
|
||||||
}), '', egw.link_get_registry('filemanager','view_popup'));
|
}), '', egw.link_get_registry('filemanager','view_popup'));
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method call for saving edited document
|
|
||||||
*
|
|
||||||
* @param {object} _egwAction egw action object
|
|
||||||
*/
|
|
||||||
editor_save: function (_egwAction) {
|
|
||||||
var self = this,
|
|
||||||
widgetFilePath = this.et2.getWidgetById('file_path'),
|
|
||||||
file_path = widgetFilePath.value;
|
|
||||||
|
|
||||||
if (this.editor)
|
|
||||||
{
|
|
||||||
function saveByteArrayLocally(err, data) {
|
|
||||||
if (err) {
|
|
||||||
alert(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var filename = file_path.split('/webdav.php'),
|
|
||||||
blob = new Blob([data.buffer], {type: self.editor_mime});
|
|
||||||
|
|
||||||
self.editor_file_operation({
|
|
||||||
url: egw.webserverUrl+file_path,
|
|
||||||
method: 'PUT',
|
|
||||||
processData: false,
|
|
||||||
success: function(data) {
|
|
||||||
egw(window).message(egw.lang('Document %1 successfully has been saved.', filename[1]));
|
|
||||||
self.editor.setDocumentModified(false);
|
|
||||||
},
|
|
||||||
error: function () {},
|
|
||||||
data: blob,
|
|
||||||
mimeType: self.editor_mime
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//existed file
|
|
||||||
if (file_path != '' && _egwAction.id != 'saveas') {
|
|
||||||
this.editor.getDocumentAsByteArray(saveByteArrayLocally);
|
|
||||||
}
|
|
||||||
// new file
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create file selector
|
|
||||||
var vfs_select = et2_createWidget('vfs-select', {
|
|
||||||
id:'savefile',
|
|
||||||
mode: 'saveas',
|
|
||||||
button_caption:"",
|
|
||||||
button_label:_egwAction.id == 'saveas'?"save as":"save",
|
|
||||||
value: "doc.odt"
|
|
||||||
}, this.et2);
|
|
||||||
|
|
||||||
// bind change handler for setting the selected path and calling save
|
|
||||||
jQuery(vfs_select.getDOMNode()).on('change', function (){
|
|
||||||
file_path = '/webdav.php'+vfs_select.get_value();
|
|
||||||
if (vfs_select.get_value())
|
|
||||||
{
|
|
||||||
// Add odt extension if not exist
|
|
||||||
if (!file_path.match(/\.odt$/,'ig')) file_path += '.odt';
|
|
||||||
widgetFilePath.set_value(file_path);
|
|
||||||
self.editor.leaveSession(function(){});
|
|
||||||
self.editor.getDocumentAsByteArray(saveByteArrayLocally);
|
|
||||||
self._init_odf_collab_editor();
|
|
||||||
egw.refresh('','filemanager');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// start the file selector dialog
|
|
||||||
jQuery(vfs_select.getDOMNode()).click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to delete loaded file in editor
|
|
||||||
* @param {type} _egwAction
|
|
||||||
*/
|
|
||||||
editor_delete: function (_egwAction) {
|
|
||||||
var fullpath = this.et2.getWidgetById('file_path').value;
|
|
||||||
fullpath = fullpath.split('/webdav.php')[1];
|
|
||||||
var selected = fullpath.split('/');
|
|
||||||
selected.pop();
|
|
||||||
var path = selected.join('/');
|
|
||||||
var self =this;
|
|
||||||
|
|
||||||
et2_dialog.show_dialog(
|
|
||||||
function(_btn)
|
|
||||||
{
|
|
||||||
if (_btn == 2)
|
|
||||||
{
|
|
||||||
self._do_action('delete', [fullpath], false, path);
|
|
||||||
self.editor_close(_egwAction);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
egw.lang('Delete file %1?', path),
|
|
||||||
'Delete file',
|
|
||||||
null,
|
|
||||||
et2_dialog.BUTTONS_YES_NO,
|
|
||||||
et2_dialog.WARNING_MESSAGE
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to handle file operations (PGD) for editor
|
|
||||||
*
|
|
||||||
* @param {object} _params jquery ajax parameters
|
|
||||||
*/
|
|
||||||
editor_file_operation: function (_params)
|
|
||||||
{
|
|
||||||
var ajaxObj = {
|
|
||||||
url: egw.webserverUrl+'/webdav.php?/home/'+egw.user('account_lid')+'/default.odt'
|
|
||||||
};
|
|
||||||
jQuery.extend(ajaxObj, _params);
|
|
||||||
switch (ajaxObj && ajaxObj.cmd)
|
|
||||||
{
|
|
||||||
case 'PUT':
|
|
||||||
jQuery.extend({},ajaxObj, {
|
|
||||||
data: JSON.stringify(ajaxObj.data),
|
|
||||||
contentType: 'application/json'
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'GET':
|
|
||||||
jQuery.extend({},ajaxObj, {
|
|
||||||
dataType: 'json'
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'DELETE':
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
jQuery.ajax(ajaxObj);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to check wheter selected file is editable. ATM only .odt is supported.
|
|
||||||
*
|
|
||||||
* @param {object} _egwAction egw action object
|
|
||||||
* @param {object} _senders object of selected row
|
|
||||||
*
|
|
||||||
* @returns {boolean} returns true if is editable otherwise false
|
|
||||||
*/
|
|
||||||
isEditable: function (_egwAction, _senders) {
|
|
||||||
var data = egw.dataGetUIDdata(_senders[0].id),
|
|
||||||
mime = this.et2._inst.widgetContainer.getWidgetById('$row');
|
|
||||||
|
|
||||||
return data.data.mime.match(mime.mime_odf_regex)?true:false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to generate session id
|
|
||||||
*
|
|
||||||
* @returns {String} retruns session id
|
|
||||||
*/
|
|
||||||
editor_getSessionId: function ()
|
|
||||||
{
|
|
||||||
var widgetFilePath = this.et2.getWidgetById('file_path'),
|
|
||||||
file_path = widgetFilePath.value,
|
|
||||||
es_id = egw.webserverUrl+file_path;
|
|
||||||
return es_id;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to create collab editor
|
|
||||||
*
|
|
||||||
* @param {type} _args parameteres to be set for server factory and texteditor
|
|
||||||
*/
|
|
||||||
create_collab_editor: function (_args)
|
|
||||||
{
|
|
||||||
|
|
||||||
var serverFactory,
|
|
||||||
server,
|
|
||||||
serverParams = _args.serverParams,
|
|
||||||
sessionId = _args.sessionId,
|
|
||||||
editorOptions = jQuery.extend(_args.editorOptions,{networkSecurityToken:'', closeCallback:this.editor_close}),
|
|
||||||
userId = egw.user('account_id'),
|
|
||||||
memberId,
|
|
||||||
self = this;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Editor error handler function
|
|
||||||
* @param {type} e
|
|
||||||
*/
|
|
||||||
function handleEditingError (e)
|
|
||||||
{
|
|
||||||
console.log(e)
|
|
||||||
};
|
|
||||||
|
|
||||||
function onEditing ()
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback function which gets called after the collab editor is created
|
|
||||||
*
|
|
||||||
* @param {string} _err
|
|
||||||
* @param {object} _editor webodf collabtexteditor object
|
|
||||||
*
|
|
||||||
* @return {undefined} return undefined if something goes wrong
|
|
||||||
*/
|
|
||||||
function onEditorCreated (_err, _editor)
|
|
||||||
{
|
|
||||||
if (_err)
|
|
||||||
{
|
|
||||||
console.log('Something went wrong whilst loading editor.'+ _err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.editor = _editor;
|
|
||||||
self.editor.addEventListener(Wodo.EVENT_UNKNOWNERROR, handleEditingError);
|
|
||||||
self.editor.joinSession(serverFactory.createSessionBackend(sessionId, memberId, server), onEditing);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to join a doc session
|
|
||||||
*
|
|
||||||
* @param {type} _sessionId session id of the opened document
|
|
||||||
*/
|
|
||||||
function joinSession(_sessionId)
|
|
||||||
{
|
|
||||||
var sid = _sessionId;
|
|
||||||
server.joinSession(userId, sid, function (_memberId) {
|
|
||||||
memberId = _memberId;
|
|
||||||
if (Object.keys(self.editor).length == 0) {
|
|
||||||
Wodo.createCollabTextEditor('filemanager-editor_odfEditor', editorOptions, onEditorCreated);
|
|
||||||
} else {
|
|
||||||
self.editor.joinSession(serverFactory.createSessionBackend(sid, _memberId, server), onEditing);
|
|
||||||
}
|
|
||||||
}, function(err) {
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
require(["egwCollab/ServerFactory"], function (ServerFactory) {
|
|
||||||
serverFactory = new ServerFactory();
|
|
||||||
server = serverFactory.createServer(serverParams);
|
|
||||||
server.connect(8000, function (state) {
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case "ready":
|
|
||||||
joinSession(sessionId);
|
|
||||||
break;
|
|
||||||
case "timeout":
|
|
||||||
console.log('did not connect to server because of timeout.')
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log('server is not available.')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
464
filemanager/js/collab.js
Normal file
464
filemanager/js/collab.js
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
/**
|
||||||
|
* EGroupware - Filemanager - Collab editor application object
|
||||||
|
*
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @package filemanager
|
||||||
|
* @author Hadi Nategh <hn-AT-stylite.de>
|
||||||
|
* @copyright (c) 2016 Stylite AG
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
/*egw:uses
|
||||||
|
/filemanager/js/collab_config.js;
|
||||||
|
/api/js/webodf/collab/dojo-amalgamation.js;
|
||||||
|
/api/js/webodf/collab/webodf.js;
|
||||||
|
/api/js/webodf/collab/wodocollabtexteditor.js;
|
||||||
|
/filemanager/js/app.js;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI for filemanager collab
|
||||||
|
*
|
||||||
|
* @augments AppJS
|
||||||
|
*/
|
||||||
|
app.classes.filemanager = app.classes.filemanager.extend({
|
||||||
|
/*
|
||||||
|
* odf editor object
|
||||||
|
*/
|
||||||
|
editor: {},
|
||||||
|
|
||||||
|
editor_mime: RegExp(/application\/vnd\.oasis\.opendocument\.text/),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
destroy: function()
|
||||||
|
{
|
||||||
|
delete this.editor;
|
||||||
|
delete editor_mime;
|
||||||
|
// call parent
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called when the etemplate2 object is loaded
|
||||||
|
* and ready. If you must store a reference to the et2 object,
|
||||||
|
* make sure to clean it up in destroy().
|
||||||
|
*
|
||||||
|
* @param et2 etemplate2 Newly ready object
|
||||||
|
* @param {string} name template name
|
||||||
|
*/
|
||||||
|
et2_ready: function(et2,name)
|
||||||
|
{
|
||||||
|
// call parent
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
if (name == "filemanager.editor")
|
||||||
|
{
|
||||||
|
// need to make body rock solid to avoid extra scrollbars
|
||||||
|
jQuery('body').css({overflow:'hidden'});
|
||||||
|
var self = this;
|
||||||
|
jQuery(window).on('unload', function(){self.editor.leaveSession()});
|
||||||
|
this._init_odf_collab_editor ();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiate odf editor popup & load given file_path
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
_init_odf_editor: function ()
|
||||||
|
{
|
||||||
|
var widgetFilePath = this.et2.getWidgetById('file_path'),
|
||||||
|
file_path = widgetFilePath.value,
|
||||||
|
isNew = file_path == '/api/js/webodf/template.odt'? true: false,
|
||||||
|
self = this;
|
||||||
|
|
||||||
|
var onEditorCreated = function (err ,editor)
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
console.log('Something went wrong whilst loading editor.'+ err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.editor = editor;
|
||||||
|
self.editor.openDocumentFromUrl(egw.webserverUrl+file_path);
|
||||||
|
if (isNew) {
|
||||||
|
widgetFilePath.set_value('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var editorOptions = {
|
||||||
|
allFeaturesEnabled: true,
|
||||||
|
userData: {
|
||||||
|
fullName: egw.user('account_fullName'),
|
||||||
|
color: 'blue'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var editor = this.et2.getWidgetById('odfEditor');
|
||||||
|
if (editor)
|
||||||
|
{
|
||||||
|
Wodo.createTextEditor('filemanager-editor_odfEditor', editorOptions, onEditorCreated);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiate odf collab editor popup & load given file_path as active session
|
||||||
|
*/
|
||||||
|
_init_odf_collab_editor: function ()
|
||||||
|
{
|
||||||
|
|
||||||
|
var widgetFilePath = this.et2.getWidgetById('file_path'),
|
||||||
|
file_path = widgetFilePath.value;
|
||||||
|
|
||||||
|
|
||||||
|
var serverOptions = {
|
||||||
|
"serverParams": {
|
||||||
|
url:egw.link('/index.php?', {
|
||||||
|
menuaction: 'filemanager.filemanager_collab.poll'
|
||||||
|
}),
|
||||||
|
genesisUrl:egw.webserverUrl+file_path
|
||||||
|
},
|
||||||
|
"sessionId": this.editor_getSessionId(),
|
||||||
|
editorOptions: {
|
||||||
|
allFeaturesEnabled: true,
|
||||||
|
userData: {
|
||||||
|
fullName: egw.user('account_fullName'),
|
||||||
|
color: 'blue'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var editor = this.et2.getWidgetById('odfEditor');
|
||||||
|
if (editor)
|
||||||
|
{
|
||||||
|
this.create_collab_editor(serverOptions);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to close an opened document
|
||||||
|
*
|
||||||
|
* @param {object} _egwAction egw action object
|
||||||
|
* @param {function} _callback callback function gets called after close operation
|
||||||
|
*/
|
||||||
|
editor_close: function (_egwAction, _callback) {
|
||||||
|
var self = this,
|
||||||
|
action = _egwAction.id,
|
||||||
|
callback = _callback;
|
||||||
|
|
||||||
|
if (this.editor)
|
||||||
|
{
|
||||||
|
var closeFn = function ()
|
||||||
|
{
|
||||||
|
self.editor.leaveSession(function(){});
|
||||||
|
if (action != 'new')
|
||||||
|
{
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
callback.call(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
// warn user about unsaved changes
|
||||||
|
if (this.editor.isDocumentModified())
|
||||||
|
{
|
||||||
|
et2_dialog.show_dialog(
|
||||||
|
function(_btn)
|
||||||
|
{
|
||||||
|
if (_btn == 2)
|
||||||
|
{
|
||||||
|
closeFn();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'There are unsaved changes. Are you sure you want to close this document without saving them?',
|
||||||
|
'unsaved changes',
|
||||||
|
null,
|
||||||
|
et2_dialog.BUTTONS_YES_NO,
|
||||||
|
et2_dialog.WARNING_MESSAGE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
closeFn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create a new document
|
||||||
|
* @param {object} _egwAction egw action object
|
||||||
|
*
|
||||||
|
* @todo: creating new empty odt file
|
||||||
|
*/
|
||||||
|
editor_new: function (_egwAction) {
|
||||||
|
var self = this,
|
||||||
|
template_url = '/api/js/webodf/template.odt';
|
||||||
|
|
||||||
|
if (Object.keys(this.editor).length > 0)
|
||||||
|
{
|
||||||
|
this.editor_close(_egwAction, function(){
|
||||||
|
|
||||||
|
// TODO create new temp file
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
egw.open_link(egw.link('/index.php', {
|
||||||
|
menuaction: 'filemanager.filemanager_ui.editor',
|
||||||
|
path: template_url
|
||||||
|
}), '', egw.link_get_registry('filemanager','view_popup'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method call for saving edited document
|
||||||
|
*
|
||||||
|
* @param {object} _egwAction egw action object
|
||||||
|
*/
|
||||||
|
editor_save: function (_egwAction) {
|
||||||
|
var self = this,
|
||||||
|
widgetFilePath = this.et2.getWidgetById('file_path'),
|
||||||
|
file_path = widgetFilePath.value;
|
||||||
|
|
||||||
|
if (this.editor)
|
||||||
|
{
|
||||||
|
function saveByteArrayLocally(err, data) {
|
||||||
|
if (err) {
|
||||||
|
alert(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var filename = file_path.split('/webdav.php'),
|
||||||
|
blob = new Blob([data.buffer], {type: self.editor_mime});
|
||||||
|
|
||||||
|
self.editor_file_operation({
|
||||||
|
url: egw.webserverUrl+file_path,
|
||||||
|
method: 'PUT',
|
||||||
|
processData: false,
|
||||||
|
success: function(data) {
|
||||||
|
egw(window).message(egw.lang('Document %1 successfully has been saved.', filename[1]));
|
||||||
|
self.editor.setDocumentModified(false);
|
||||||
|
},
|
||||||
|
error: function () {},
|
||||||
|
data: blob,
|
||||||
|
mimeType: self.editor_mime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//existed file
|
||||||
|
if (file_path != '' && _egwAction.id != 'saveas') {
|
||||||
|
this.editor.getDocumentAsByteArray(saveByteArrayLocally);
|
||||||
|
}
|
||||||
|
// new file
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// create file selector
|
||||||
|
var vfs_select = et2_createWidget('vfs-select', {
|
||||||
|
id:'savefile',
|
||||||
|
mode: 'saveas',
|
||||||
|
button_caption:"",
|
||||||
|
button_label:_egwAction.id == 'saveas'?"save as":"save",
|
||||||
|
value: "doc.odt"
|
||||||
|
}, this.et2);
|
||||||
|
|
||||||
|
// bind change handler for setting the selected path and calling save
|
||||||
|
jQuery(vfs_select.getDOMNode()).on('change', function (){
|
||||||
|
file_path = '/webdav.php'+vfs_select.get_value();
|
||||||
|
if (vfs_select.get_value())
|
||||||
|
{
|
||||||
|
// Add odt extension if not exist
|
||||||
|
if (!file_path.match(/\.odt$/,'ig')) file_path += '.odt';
|
||||||
|
widgetFilePath.set_value(file_path);
|
||||||
|
self.editor.leaveSession(function(){});
|
||||||
|
self.editor.getDocumentAsByteArray(saveByteArrayLocally);
|
||||||
|
self._init_odf_collab_editor();
|
||||||
|
egw.refresh('','filemanager');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// start the file selector dialog
|
||||||
|
jQuery(vfs_select.getDOMNode()).click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to delete loaded file in editor
|
||||||
|
* @param {type} _egwAction
|
||||||
|
*/
|
||||||
|
editor_delete: function (_egwAction) {
|
||||||
|
var fullpath = this.et2.getWidgetById('file_path').value;
|
||||||
|
fullpath = fullpath.split('/webdav.php')[1];
|
||||||
|
var selected = fullpath.split('/');
|
||||||
|
selected.pop();
|
||||||
|
var path = selected.join('/');
|
||||||
|
var self =this;
|
||||||
|
|
||||||
|
et2_dialog.show_dialog(
|
||||||
|
function(_btn)
|
||||||
|
{
|
||||||
|
if (_btn == 2)
|
||||||
|
{
|
||||||
|
self._do_action('delete', [fullpath], false, path);
|
||||||
|
self.editor_close(_egwAction);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
egw.lang('Delete file %1?', path),
|
||||||
|
'Delete file',
|
||||||
|
null,
|
||||||
|
et2_dialog.BUTTONS_YES_NO,
|
||||||
|
et2_dialog.WARNING_MESSAGE
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to handle file operations (PGD) for editor
|
||||||
|
*
|
||||||
|
* @param {object} _params jquery ajax parameters
|
||||||
|
*/
|
||||||
|
editor_file_operation: function (_params)
|
||||||
|
{
|
||||||
|
var ajaxObj = {
|
||||||
|
url: egw.webserverUrl+'/webdav.php?/home/'+egw.user('account_lid')+'/default.odt'
|
||||||
|
};
|
||||||
|
jQuery.extend(ajaxObj, _params);
|
||||||
|
switch (ajaxObj && ajaxObj.cmd)
|
||||||
|
{
|
||||||
|
case 'PUT':
|
||||||
|
jQuery.extend({},ajaxObj, {
|
||||||
|
data: JSON.stringify(ajaxObj.data),
|
||||||
|
contentType: 'application/json'
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'GET':
|
||||||
|
jQuery.extend({},ajaxObj, {
|
||||||
|
dataType: 'json'
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'DELETE':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
jQuery.ajax(ajaxObj);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to check wheter selected file is editable. ATM only .odt is supported.
|
||||||
|
*
|
||||||
|
* @param {object} _egwAction egw action object
|
||||||
|
* @param {object} _senders object of selected row
|
||||||
|
*
|
||||||
|
* @returns {boolean} returns true if is editable otherwise false
|
||||||
|
*/
|
||||||
|
isEditable: function (_egwAction, _senders) {
|
||||||
|
var data = egw.dataGetUIDdata(_senders[0].id),
|
||||||
|
mime = this.et2._inst.widgetContainer.getWidgetById('$row');
|
||||||
|
|
||||||
|
return data.data.mime.match(mime.mime_odf_regex)?true:false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to generate session id
|
||||||
|
*
|
||||||
|
* @returns {String} retruns session id
|
||||||
|
*/
|
||||||
|
editor_getSessionId: function ()
|
||||||
|
{
|
||||||
|
var widgetFilePath = this.et2.getWidgetById('file_path'),
|
||||||
|
file_path = widgetFilePath.value,
|
||||||
|
es_id = egw.webserverUrl+file_path;
|
||||||
|
return es_id;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to create collab editor
|
||||||
|
*
|
||||||
|
* @param {type} _args parameteres to be set for server factory and texteditor
|
||||||
|
*/
|
||||||
|
create_collab_editor: function (_args)
|
||||||
|
{
|
||||||
|
|
||||||
|
var serverFactory,
|
||||||
|
server,
|
||||||
|
serverParams = _args.serverParams,
|
||||||
|
sessionId = _args.sessionId,
|
||||||
|
editorOptions = jQuery.extend(_args.editorOptions,{networkSecurityToken:'', closeCallback:this.editor_close}),
|
||||||
|
userId = egw.user('account_id'),
|
||||||
|
memberId,
|
||||||
|
self = this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor error handler function
|
||||||
|
* @param {type} e
|
||||||
|
*/
|
||||||
|
function handleEditingError (e)
|
||||||
|
{
|
||||||
|
console.log(e)
|
||||||
|
};
|
||||||
|
|
||||||
|
function onEditing ()
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function which gets called after the collab editor is created
|
||||||
|
*
|
||||||
|
* @param {string} _err
|
||||||
|
* @param {object} _editor webodf collabtexteditor object
|
||||||
|
*
|
||||||
|
* @return {undefined} return undefined if something goes wrong
|
||||||
|
*/
|
||||||
|
function onEditorCreated (_err, _editor)
|
||||||
|
{
|
||||||
|
if (_err)
|
||||||
|
{
|
||||||
|
console.log('Something went wrong whilst loading editor.'+ _err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.editor = _editor;
|
||||||
|
self.editor.addEventListener(Wodo.EVENT_UNKNOWNERROR, handleEditingError);
|
||||||
|
self.editor.joinSession(serverFactory.createSessionBackend(sessionId, memberId, server), onEditing);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to join a doc session
|
||||||
|
*
|
||||||
|
* @param {type} _sessionId session id of the opened document
|
||||||
|
*/
|
||||||
|
function joinSession(_sessionId)
|
||||||
|
{
|
||||||
|
var sid = _sessionId;
|
||||||
|
server.joinSession(userId, sid, function (_memberId) {
|
||||||
|
memberId = _memberId;
|
||||||
|
if (Object.keys(self.editor).length == 0) {
|
||||||
|
Wodo.createCollabTextEditor('filemanager-editor_odfEditor', editorOptions, onEditorCreated);
|
||||||
|
} else {
|
||||||
|
self.editor.joinSession(serverFactory.createSessionBackend(sid, _memberId, server), onEditing);
|
||||||
|
}
|
||||||
|
}, function(err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
require(["egwCollab/ServerFactory"], function (ServerFactory) {
|
||||||
|
serverFactory = new ServerFactory();
|
||||||
|
server = serverFactory.createServer(serverParams);
|
||||||
|
server.connect(8000, function (state) {
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case "ready":
|
||||||
|
joinSession(sessionId);
|
||||||
|
break;
|
||||||
|
case "timeout":
|
||||||
|
console.log('did not connect to server because of timeout.')
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('server is not available.')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
32
filemanager/js/collab_config.js
Normal file
32
filemanager/js/collab_config.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* EGroupware - Filemanager - Collab editor - dojo configuration
|
||||||
|
*
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @package filemanager
|
||||||
|
* @author Hadi Nategh <hn-AT-stylite.de>
|
||||||
|
* @copyright (c) 2016 Stylite AG
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
(function(){
|
||||||
|
// Dojo configuration needed for filemanager collab editor and
|
||||||
|
// it should be load before app.js
|
||||||
|
var basedir = egw.webserverUrl+'/api/js/webodf/collab';
|
||||||
|
var usedLocale = "C";
|
||||||
|
if (navigator && navigator.language && navigator.language.match(/^(de)/)) {
|
||||||
|
usedLocale = navigator.language.substr(0,2);
|
||||||
|
}
|
||||||
|
// dojo Lib configuration needs to be set before dojo.js is loaded
|
||||||
|
window.dojoConfig = {
|
||||||
|
locale: usedLocale,
|
||||||
|
baseUrl: basedir,
|
||||||
|
paths: {
|
||||||
|
"webodf/editor": basedir,
|
||||||
|
"dijit": basedir + "/dijit",
|
||||||
|
"dojo": basedir + "/dojo",
|
||||||
|
"dojox": basedir + "/dojox",
|
||||||
|
"resources": basedir + "/resources",
|
||||||
|
"egwCollab": basedir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
@ -54,7 +54,7 @@
|
|||||||
<buttononly statustext="Tile view" id="button[change_view]" onclick="app.filemanager.change_view" image="list_tile" background_image="true"/>
|
<buttononly statustext="Tile view" id="button[change_view]" onclick="app.filemanager.change_view" image="list_tile" background_image="true"/>
|
||||||
</template>
|
</template>
|
||||||
<template id="filemanager.index.header_right" template="" lang="" group="0" version="1.9.003">
|
<template id="filemanager.index.header_right" template="" lang="" group="0" version="1.9.003">
|
||||||
<buttononly statustext="Create new open document file" id="button[new_doc]" onclick="app.filemanager.editor_new();" image="new" background_image="true"/>
|
<buttononly statustext="Create new open document file" id="button[new_doc]" onclick="app.filemanager.list_editor_new();" image="new" background_image="true"/>
|
||||||
<buttononly statustext="Rename, change permissions or ownership" id="button[edit]" onclick="app.filemanager.editprefs();" image="edit" background_image="true"/>
|
<buttononly statustext="Rename, change permissions or ownership" id="button[edit]" onclick="app.filemanager.editprefs();" image="edit" background_image="true"/>
|
||||||
<buttononly statustext="Create directory" id="button[createdir]" onclick="app.filemanager.createdir();" image="button_createdir" ro_image="createdir_disabled" background_image="true"/>
|
<buttononly statustext="Create directory" id="button[createdir]" onclick="app.filemanager.createdir();" image="button_createdir" ro_image="createdir_disabled" background_image="true"/>
|
||||||
<buttononly statustext="Create a link" id="button[symlink]" onclick="app.filemanager.symlink();" image="link" ro_image="link_disabled" background_image="true"/>
|
<buttononly statustext="Create a link" id="button[symlink]" onclick="app.filemanager.symlink();" image="link" ro_image="link_disabled" background_image="true"/>
|
||||||
|
Loading…
Reference in New Issue
Block a user