Skip to content

Commit

Permalink
Make collabora save and exit actions more intuitive xwikisas#12
Browse files Browse the repository at this point in the history
* add 2 new buttons in the editor menu: save and exit + close editor and use the postMesage API to handle the events
  • Loading branch information
oanalavinia committed Mar 28, 2023
1 parent 9f6f132 commit 14e82ad
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.json.JSONObject;
import org.restlet.Request;
import org.slf4j.Logger;
import org.xwiki.component.annotation.Component;
import org.xwiki.model.reference.AttachmentReference;
Expand Down Expand Up @@ -101,6 +102,8 @@ public Response get(String fileId, String token, String userCanWrite) throws XWi
message.put("Size", String.valueOf(attachment.getLongSize()));
message.put("UserCanWrite", userCanWrite);
message.put(LAST_MODIFIED_TIME, dateFormat.format(attachment.getDate()));
// Needed for using the PostMessage API.
message.put("PostMessageOrigin", Request.getCurrent().getHostRef().toString());

return Response.status(Response.Status.OK).entity(message.toString()).type(MediaType.APPLICATION_JSON)
.build();
Expand Down
161 changes: 142 additions & 19 deletions application-collabora-ui/src/main/resources/Collabora/Code/Main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,50 @@
<syntaxId>xwiki/2.1</syntaxId>
<hidden>true</hidden>
<content>{{velocity output="false"}}
#macro (renderCollaboraContent $mode)
## Display logo and some information about the currently edited file. Show Cancel action on the right.
## Save action is included in Collabora editor.
&lt;div class="actionMenu"&gt;
&lt;div&gt;
&lt;a href="${xwiki.getURL('Main.WebHome')}"&gt;&lt;img src="$xwiki.getSkinFile('logo.svg')"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;strong&gt;$currentAction&lt;/strong&gt;
&lt;em&gt;$escapetool.xml($request.filename)&lt;/em&gt;
$escapetool.xml($services.localization.render('collabora.editor.onPage'))
&lt;a href="${fileDoc.URL}#Attachments" title="$escapetool.xml($services.localization.render('cancel'))"&gt;
$escapetool.xml($fileDoc.displayTitle)
&lt;/a&gt;
#macro (unsavedChangesModal)
&lt;div class="modal fade" id="editUnsavedChanges" tabindex="-1" role="dialog" aria-hidden="true"
aria-label="$escapetool.xml($services.localization.render('collabora.editor.unsaved.label'))"&gt;
&lt;div class="modal-dialog modal-sm"&gt;
&lt;div class="modal-content"&gt;
&lt;div class="modal-body"&gt;
$escapetool.xml($services.localization.render('collabora.editor.unsaved.info'))
&lt;/div&gt;
&lt;div&gt;
&lt;a href="${fileDoc.URL}#Attachments" class="btn btn-default"
title="$escapetool.xml($services.localization.render('cancel'))"&gt;
$escapetool.xml($services.localization.render('cancel'))
&lt;/a&gt;
&lt;div class="modal-footer"&gt;
&lt;input type="submit" class="btn btn-danger"
value="$escapetool.xml($services.localization.render('collabora.editor.unsaved.submit'))"&gt;
&lt;input type="button" class="btn btn-default" data-dismiss="modal"
value="$escapetool.xml($services.localization.render('collabora.editor.unsaved.close'))"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
#end
#macro (renderCollaboraContent $mode)
## Display logo and some information about the currently edited file. Save, Save and exit and Close actions are
## included in Collabora editor.
&lt;div class="actionMenu"&gt;
&lt;div&gt;
&lt;a href="${xwiki.getURL('Main.WebHome')}"&gt;&lt;img src="$xwiki.getSkinFile('logo.svg')"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;strong&gt;$currentAction&lt;/strong&gt;
&lt;em&gt;$escapetool.xml($request.filename)&lt;/em&gt;
$escapetool.xml($services.localization.render('collabora.editor.onPage'))
&lt;a id='fileHomePage' href="${fileDoc.URL}#Attachments"
title="$escapetool.xml($services.localization.render('cancel'))"&gt;
$escapetool.xml($fileDoc.displayTitle)
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
#set ($saveAndExitIconURL = $xwiki.getDocument('Collabora.Code.UI').getAttachmentURL('saveAndExit.png'))
#set ($closeIconURL = $xwiki.getDocument('Collabora.Code.UI').getAttachmentURL('close.png'))
#set ($saveAndExitMessage = $escapetool.xml($services.localization.render('collabora.editor.saveAndExit')))
#set ($closeMessage = $escapetool.xml($services.localization.render('collabora.editor.close')))
## TODO: The translations are added for now as a data attribute. This should be changed once the application starts
## depending on a XWiki version &gt;= 13.8 to include XWIKI-18973: Simplify the way JavaScript code loads translation
## messages.
&lt;span id="collaboraConfig" data-save-exit-icon="$saveAndExitIconURL" data-close-icon="$closeIconURL"
data-save-exit-message="$saveAndExitMessage" data-close-message="$closeMessage"&gt;&lt;/span&gt;
## Information needed by collabora to be able to edit the current file.
#set ($fileId = $escapetool.xml($services.model.serialize($attachment.getReference(), 'default')))
#set ($errorMessage = $escapetool.xml($services.localization.render('collabora.editor.error')))
Expand All @@ -70,6 +92,7 @@
&lt;/form&gt;
## Where the document will be displayed.
&lt;iframe id="collaboraViewer" name="collaboraViewer"&gt;&lt;/iframe&gt;
#unsavedChangesModal()
#end
{{/velocity}}

Expand Down Expand Up @@ -197,6 +220,99 @@
<property>
<code>require(['jquery'], function($) {
const collaboraPath ='/rest/collabora/files/';
const iframeWindow = document.getElementById('collaboraViewer').contentWindow;
var isDocModified = false;

var getSaveAndExitButtonMessage = function() {
return JSON.stringify({
'MessageId': 'Insert_Button',
'SendTime': Date.now(),
'Values': {
'id': 'saveAndExitEditor',
'imgurl': window.location.origin + $("#collaboraConfig").data('saveExitIcon'),
'hint': $("#collaboraConfig").data('saveExitMessage'),
'mobile': true,
'label': $("#collaboraConfig").data('saveExitMessage')
}
});
};

var getCloseButtonMessage = function() {
return JSON.stringify({
'MessageId': 'Insert_Button',
'SendTime': Date.now(),
'Values': {
'id': 'closeEditor',
'imgurl': window.location.origin + $("#collaboraConfig").data('closeIcon'),
'hint': $("#collaboraConfig").data('closeMessage'),
'mobile': true,
'label': $("#collaboraConfig").data('closeMessage')
}
});
};

var getSaveDocumentMessage = function() {
return JSON.stringify({
"MessageId" : "Action_Save",
"SendTime": Date.now(),
"Values" : {
"DontTerminateEdit" : true,
"DontSaveIfUnmodified": true,
"Notify" : true
}
});
}

/**
* If there are unsaved changes, ask the user if these should be discarded. Otherwise, go to the file home page.
*/
var onCloseEditor = function() {
if (isDocModified) {
$('#editUnsavedChanges').modal('show');
} else {
window.location.href = $('#fileHomePage').attr('href');
}
};

var onDocumentLoaded = function() {
// Notify the server that postMessage is going to be used.
iframeWindow.postMessage(JSON.stringify({ 'MessageId': 'Host_PostmessageReady' }), '*');
// Add the saveAndExit and close custom buttons.
iframeWindow.postMessage(getSaveAndExitButtonMessage(), '*');
iframeWindow.postMessage(getCloseButtonMessage(), '*');
};

var receiveMessage = function(event) {
// Skip messages that are not from this iframe.
if (event.source !== iframeWindow) {
return;
}
var msg = JSON.parse(event.data);
if (!msg) {
return;
}

if (msg.MessageId == 'App_LoadingStatus' &amp;&amp; msg.Values &amp;&amp; msg.Values.Status == 'Document_Loaded') {
onDocumentLoaded();
} else if (msg.MessageId == 'Doc_ModifiedStatus') {
isDocModified = msg.Values &amp;&amp; msg.Values.Modified;
} else if (msg.MessageId == 'Clicked_Button') {
if (msg.Values &amp;&amp; msg.Values.Id == 'saveAndExitEditor') {
// Save the file and let the editor close action be handleded after this is finished, on Action_Save_Resp.
iframeWindow.postMessage(getSaveDocumentMessage(), '*');
} else if (msg.Values &amp;&amp; msg.Values.Id == 'closeEditor') {
onCloseEditor();
}
} else if (msg.MessageId == 'Action_Save_Resp') {
// This event is send when Action_Save or Action_Save_As are triggered from our code, and UI_Save when using the
// editor's default save button. Right now, we only fire Action_Save on the custom saveAndExit button. So after
// this save is succesfull, a redirect to the file home page is required.
if (msg.Values &amp;&amp; msg.Values.success) {
window.location.href = $('#fileHomePage').attr('href');
}
}
}

$(function() {
const fileId = $("#collaboraServer").data('fileId');
const userCanWrite = $("#collaboraServer").data('mode') === 'edit';
Expand All @@ -219,6 +335,13 @@
}).fail(function(jqxhr, textStatus, error) {
new XWiki.widgets.Notification(errorMessage + error, 'error');
});

// Listen to messages send by Collabora server.
window.addEventListener("message", receiveMessage, false);
});

$(document).on('click', '#editUnsavedChanges input.btn-danger', function(e) {
window.location.href = $('#fileHomePage').attr('href');
});

$(window).unload(function() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ collabora.attachment.view.title=View using Collabora
## Editor
collabora.editor.onPage=on page
collabora.editor.error=Error while loading this file. Cause:
collabora.editor.close=Close editor
collabora.editor.saveAndExit=Save and exit
collabora.editor.unsaved.close=Keep editing
collabora.editor.unsaved.info=There are unsaved changes. Are you sure you want to exit without saving?
collabora.editor.unsaved.label=Unsaved changes
collabora.editor.unsaved.submit=Close without saving
collabora.validation.attachmentMissing=Document or attachment not found!
collabora.validation.documentMissing=Document parameter required!
collabora.validation.filenameMissing=Filename parameter required!</content>
Expand Down
20 changes: 20 additions & 0 deletions application-collabora-ui/src/main/resources/Collabora/Code/UI.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@
<syntaxId>xwiki/2.1</syntaxId>
<hidden>true</hidden>
<content/>
<attachment>
<filename>close.png</filename>
<mimetype>image/png</mimetype>
<charset>UTF-8</charset>
<author>xwiki:XWiki.Admin</author>
<version>1.1</version>
<comment/>
<content>iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAAMFBMVEUAAADkLx/iMCDiMCDjMSDkMCDiLx/iMCDiLx/iMCDiMB/////iMB/iLx/iMCDiMR8QM5r+AAAAEHRSTlMAYJ/P/19Q35CP4P/woO/Q9/WoOgAAAKVJREFUeJxjYMALhEycVWHsdBcgKIOwOVzAYAKY0wLheIDYbC5QkADkcLl473FxOb3FpQDIEXHx5j7is3uLixuQc8XFb8Oe07ufuPgCOV9cXF7v3r3PxcUZyAFq9dsNlHBxgXB8du8+AuEAlZ3evQFooD/YAJ/d+15zHwEbADR69xM/qNFAS4FGvd7isgDdOSgOhXmhAeKhLBB7Gcyrsl/8L+IPGABYMkPB47UBjQAAAABJRU5ErkJggg==</content>
<filesize>310</filesize>
</attachment>
<attachment>
<filename>collabora-symbol.svg</filename>
<mimetype>image/svg+xml</mimetype>
Expand All @@ -47,6 +57,16 @@
<content>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTJweCIgaGVpZ2h0PSIxMnB4IiB2aWV3Qm94PSIwIDAgMTIgMTIiIHZlcnNpb249IjEuMSI+CjxnIGlkPSJzdXJmYWNlMSI+CjxwYXRoIHN0eWxlPSIgc3Ryb2tlOm5vbmU7ZmlsbC1ydWxlOm5vbnplcm87ZmlsbDpyZ2IoMTAwJSwxMDAlLDEwMCUpO2ZpbGwtb3BhY2l0eToxOyIgZD0iTSAwIDAgTCAxMS45ODQzNzUgMCBMIDExLjk4NDM3NSAxMS45ODQzNzUgTCAwIDExLjk4NDM3NSBaIE0gMCAwICIvPgo8cGF0aCBzdHlsZT0iIHN0cm9rZTpub25lO2ZpbGwtcnVsZTpub256ZXJvO2ZpbGw6cmdiKDEwMCUsMTAwJSwxMDAlKTtmaWxsLW9wYWNpdHk6MTsiIGQ9Ik0gMy40NDUzMTIgMy43MzQzNzUgTCAzLjU4OTg0NCAzLjU4OTg0NCBMIDUuOTkyMTg4IDUuOTkyMTg4IEwgMy41ODk4NDQgOC4zOTQ1MzEgTCAzLjQ0NTMxMiA4LjI1IEwgNS43MDMxMjUgNS45OTIxODggWiBNIDMuNDQ1MzEyIDMuNzM0Mzc1ICIvPgo8cGF0aCBzdHlsZT0iIHN0cm9rZTpub25lO2ZpbGwtcnVsZTpub256ZXJvO2ZpbGw6cmdiKDc4LjQzMTM3MyUsNzguNDMxMzczJSw3OC40MzEzNzMlKTtmaWxsLW9wYWNpdHk6MTsiIGQ9Ik0gMy40NDUzMTIgMy43MzQzNzUgTCAzLjQ0NTMxMiA4LjI1IEwgNS43MDMxMjUgNS45OTIxODggWiBNIDMuNDQ1MzEyIDMuNzM0Mzc1ICIvPgo8cGF0aCBzdHlsZT0iIHN0cm9rZTpub25lO2ZpbGwtcnVsZTpub256ZXJvO2ZpbGw6cmdiKDMxLjM3MjU0OSUsMjguNjI3NDUxJSw2MCUpO2ZpbGwtb3BhY2l0eToxOyIgZD0iTSA1LjQ5MjE4OCAxLjY4NzUgTCAzLjU4OTg0NCAzLjU4OTg0NCBMIDUuOTkyMTg4IDUuOTkyMTg4IEwgMy41ODk4NDQgOC4zOTQ1MzEgTCA1LjQ5MjE4OCAxMC4yOTY4NzUgTCA5Ljc5Njg3NSA1Ljk5MjE4OCBaIE0gNS40OTIxODggMS42ODc1ICIvPgo8cGF0aCBzdHlsZT0iIHN0cm9rZTpub25lO2ZpbGwtcnVsZTpub256ZXJvO2ZpbGw6cmdiKDIxLjk2MDc4NCUsMTQuNTA5ODA0JSw0Ny44NDMxMzclKTtmaWxsLW9wYWNpdHk6MTsiIGQ9Ik0gNS40MDIzNDQgNi41ODIwMzEgTCAzLjgxMjUgOC4xNjc5NjkgTCA2LjE2MDE1NiA3LjY1MjM0NCBaIE0gNS40MDIzNDQgNi41ODIwMzEgIi8+CjwvZz4KPC9zdmc+Cg==</content>
<filesize>1225</filesize>
</attachment>
<attachment>
<filename>saveAndExit.png</filename>
<mimetype>image/png</mimetype>
<charset>UTF-8</charset>
<author>xwiki:XWiki.Admin</author>
<version>1.1</version>
<comment/>
<content>iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAmVBMVEUAAAA6Ojg6Ojg6Ojh5d3T6+vr5+Pj129vvvbvusrCoNi6famZ7dnOPODHYMiTjMSDZQDWPODK3XVjjMiHlMCGlZ2LjMSDlMh/aPzT////jMSCgamanNi7tsbCFODNBOjjmbGfjNCXjMCA7OzlXV1Tz1dTlMCBISEg6Ojnwvr3jMyJFRUXWMiTWMSSYNzH/fwDnMiLkMx/lMiI9Pt+zAAAAM3RSTlMAxf/D/////////////////////3n//lH//97/////////3cv//08V0v94Fv//1QRCe40eLfJ5AAAArElEQVR4nMXS1w6CMBQGYKzUiR6xrrqwgnsAvv/D2Z62WCR64Y1/Agn/F9LpeT+kRiqpIxDfJ9SJ+v4LNJqtdqcbvMCk1weVQWjBZMjAZFSCMQMtDCZTB4IZMM5lr15zBxbYcXwADKiRl6AF+wLkVFdgBMrw8Q+yVj19H0NCtAFRzGorIU40kJ0AYdexl3A4JhroSdiVn3FPLrHdq/CK9e1eOf80yx95ln67Ik+P+BKgdL3gCAAAAABJRU5ErkJggg==</content>
<filesize>457</filesize>
</attachment>
<object>
<name>Collabora.Code.UI</name>
<number>0</number>
Expand Down

0 comments on commit 14e82ad

Please sign in to comment.