Commit cbfb6ccb authored by Romain Courteaud's avatar Romain Courteaud

[erp5_web_renderjs_ui] Editable parameter is now sticky

Allow to switch from editable/viewable mode directly from the panel.
Drop editable/viewable button on tabpage.

The editable parameter is propagated by all links.
parent 4469fdaf
......@@ -498,6 +498,19 @@ div[data-gadget-scope='panel'] img {
text-align: left;
height: 100%;
}
div[data-gadget-scope='panel'] div[data-gadget-scope="erp5_checkbox"] {
padding: 3pt;
padding-left: 12pt;
}
div[data-gadget-scope='panel'] div[data-gadget-scope="erp5_checkbox"] label,
div[data-gadget-scope='panel'] div[data-gadget-scope="erp5_checkbox"] span,
div[data-gadget-scope='panel'] div[data-gadget-scope="erp5_checkbox"] input {
cursor: pointer;
}
div[data-gadget-scope='panel'] div[data-gadget-scope="erp5_checkbox"] span {
width: 24pt;
display: inline-block;
}
div[data-gadget-scope='panel'] ul:first-child {
margin-top: 30pt;
}
......
......@@ -242,7 +242,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>958.22948.35082.52087</string> </value>
<value> <string>958.38697.56980.48179</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -260,7 +260,7 @@
</tuple>
<state>
<tuple>
<float>1490947545.17</float>
<float>1491827283.31</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -4,6 +4,9 @@
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>ERP5 Panel</title>
<!--
data-i18n=Editable
-->
<!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script>
......@@ -35,17 +38,22 @@
data-gadget-sandbox="public"></div>
</form>
<ul data-role="listview" class="ui-listview" data-enhanced="true">
<li class="ui-first-child"><a href="#" class="ui-btn ui-btn-icon-left ui-icon-home" data-i18n="Home">Home</a></li>
<ul data-role="listview" class="ui-listview" data-enhanced="true"></ul>
<div data-gadget-url="gadget_erp5_field_checkbox.html"
data-gadget-scope="erp5_checkbox"
data-gadget-sandbox="public"></div>
<dl></dl>
</div>
</script>
<script id="panel-template-body-list" type="text/x-handlebars-template">
<li class="ui-first-child"><a href="{{front_href}}" class="ui-btn ui-btn-icon-left ui-icon-home" data-i18n="Home">Home</a></li>
<li><a href="{{module_href}}" class="ui-btn ui-btn-icon-left ui-icon-puzzle-piece" data-i18n="Modules" accesskey="m">Modules</a></li>
<li><a href="{{worklist_href}}" class="ui-btn ui-btn-icon-left ui-icon-clipboard" data-i18n="Worklists" accesskey="w">Worklists</a></li>
<li><a href="{{history_href}}" class="ui-btn ui-btn-icon-left ui-icon-history" data-i18n="History" accesskey="h">History</a></li>
<li><a href="{{search_href}}" class="ui-btn ui-btn-icon-left ui-icon-search" data-i18n="Search" accesskey="s">Search</a></li>
<li><a href="{{preference_href}}" class="ui-btn ui-btn-icon-left ui-icon-gear" data-i18n="Preferences">Preferences</a></li>
<li class="ui-last-child"><a href="{{logout_href}}" class="ui-btn ui-btn-icon-left ui-icon-power-off" data-i18n="Logout" accesskey="o">Logout</a></li>
</ul>
<dl></dl>
</div>
</script>
<script id="panel-template-body-desktop" type="text/x-handlebars-template">
......
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>957.46848.56526.7116</string> </value>
<value> <string>958.33121.48203.5614</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1488384141.54</float>
<float>1491822419.47</float>
<string>UTC</string>
</tuple>
</state>
......
/*jslint nomen: true, indent: 2, maxerr: 3 */
/*jslint nomen: true, indent: 2, maxerr: 3, unparam: true */
/*global window, document, rJS, Handlebars, RSVP, Node, loopEventListener */
(function (window, document, rJS, Handlebars, RSVP, Node, loopEventListener) {
"use strict";
......@@ -15,6 +15,9 @@
panel_template_body = Handlebars.compile(template_element
.getElementById("panel-template-body")
.innerHTML),
panel_template_body_list = Handlebars.compile(template_element
.getElementById("panel-template-body-list")
.innerHTML),
panel_template_body_desktop = Handlebars.compile(template_element
.getElementById("panel-template-body-desktop")
.innerHTML);
......@@ -29,7 +32,9 @@
//////////////////////////////////////////////
.declareAcquiredMethod("getUrlFor", "getUrlFor")
.declareAcquiredMethod("translateHtml", "translateHtml")
.declareAcquiredMethod("translate", "translate")
.declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("getUrlParameter", "getUrlParameter")
/////////////////////////////////////////////////////////////////
// declared methods
......@@ -48,7 +53,8 @@
.declareMethod('render', function (options) {
var erp5_document = options.erp5_document,
workflow_list,
view_list;
view_list,
context = this;
if (erp5_document !== undefined) {
workflow_list = erp5_document._links.action_workflow || [];
view_list = erp5_document._links.action_object_view || [];
......@@ -63,12 +69,15 @@
workflow_list = JSON.stringify(workflow_list);
view_list = JSON.stringify(view_list);
}
return this.changeState({
workflow_list: workflow_list,
view_list: view_list,
global: true,
editable: options.editable
});
return context.getUrlParameter('editable')
.push(function (editable) {
return context.changeState({
workflow_list: workflow_list,
view_list: view_list,
global: true,
editable: options.editable || editable || false
});
});
})
.onStateChange(function (modification_dict) {
......@@ -92,32 +101,16 @@
if (modification_dict.hasOwnProperty("global")) {
queue
.push(function () {
return RSVP.all([
context.getUrlFor({command: 'display', options: {page: "front"}}),
context.getUrlFor({command: 'display', options: {page: "history"}}),
context.getUrlFor({command: 'display', options: {page: "preference"}}),
context.getUrlFor({command: 'display', options: {page: "logout"}}),
context.getUrlFor({command: 'display', options: {page: "search"}}),
context.getUrlFor({command: 'display', options: {page: "worklist"}})
]);
})
.push(function (result_list) {
// XXX: Customize panel header!
return context.translateHtml(
panel_template_header() +
panel_template_body({
"module_href": result_list[0],
"history_href": result_list[1],
"preference_href": result_list[2],
"logout_href": result_list[3],
"search_href": result_list[4],
"worklist_href": result_list[5]
})
panel_template_body()
);
})
.push(function (my_translated_or_plain_html) {
tmp_element = document.createElement('div');
tmp_element.innerHTML = my_translated_or_plain_html;
return context.declareGadget('gadget_erp5_searchfield.html', {
scope: "erp5_searchfield",
element: tmp_element.querySelector('[data-gadget-scope="erp5_searchfield"]')
......@@ -128,12 +121,75 @@
focus: false
});
})
.push(function () {
return context.declareGadget('gadget_erp5_field_multicheckbox.html', {
scope: "erp5_checkbox",
element: tmp_element.querySelector('[data-gadget-scope="erp5_checkbox"]')
});
})
.push(function () {
context.element.querySelector("div").appendChild(tmp_element);
return context.listenResize();
});
}
if (modification_dict.hasOwnProperty("editable")) {
queue
// Update the global links
.push(function () {
return RSVP.all([
context.getUrlFor({command: 'display', options: {page: "front"}}),
context.getUrlFor({command: 'display', options: {page: "history"}}),
context.getUrlFor({command: 'display', options: {page: "preference"}}),
context.getUrlFor({command: 'display', options: {page: "logout"}}),
context.getUrlFor({command: 'display', options: {page: "search"}}),
context.getUrlFor({command: 'display', options: {page: "worklist"}}),
context.getUrlFor({command: 'display'})
]);
})
.push(function (result_list) {
return context.translateHtml(
panel_template_body_list({
"module_href": result_list[0],
"history_href": result_list[1],
"preference_href": result_list[2],
"logout_href": result_list[3],
"search_href": result_list[4],
"worklist_href": result_list[5],
"front_href": result_list[6]
})
);
})
.push(function (result) {
context.element.querySelector("ul").innerHTML = result;
// Update the checkbox field value
return RSVP.all([
context.getDeclaredGadget("erp5_checkbox"),
context.translate("Editable")
]);
})
.push(function (result_list) {
var value = [],
search_gadget = result_list[0],
title = result_list[1];
if (context.state.editable) {
value = ['editable'];
}
return search_gadget.render({field_json: {
editable: true,
name: 'editable',
key: 'editable',
hidden: false,
items: [[title, 'editable']],
default: value
}});
});
}
if ((this.state.global === true) &&
(modification_dict.hasOwnProperty("desktop") ||
modification_dict.hasOwnProperty("editable") ||
......@@ -240,10 +296,29 @@
return result;
})
.allowPublicAcquisition('notifyChange', function () {
.allowPublicAcquisition('notifyChange', function (argument_list, scope) {
if (scope === 'erp5_checkbox') {
var context = this;
return context.getDeclaredGadget('erp5_checkbox')
.push(function (gadget) {
return gadget.getContent();
})
.push(function (result) {
var options = {editable: undefined};
if (result.editable.length === 1) {
options.editable = true;
}
return context.redirect({command: 'change', options: options});
});
}
// Typing a search query should not modify the header status
return;
})
.allowPublicAcquisition('notifyValid', function () {
// Typing a search query should not modify the header status
return;
})
.onEvent('submit', function () {
var gadget = this;
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>958.19723.40120.16469</string> </value>
<value> <string>958.33121.48203.5614</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1490688736.61</float>
<float>1491816291.84</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -52,8 +52,7 @@
command: 'change',
options: {
view: view_list[i].href,
page: undefined,
editable: options.editable
page: undefined
}
})
);
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>955.29509.41156.45721</string> </value>
<value> <string>956.58742.58866.48708</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1479825199.32</float>
<float>1491225034.71</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>957.40691.44097.35481</string> </value>
<value> <string>958.28347.56387.25600</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1488273849.34</float>
<float>1491225124.12</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, rJS, RSVP, calculatePageTitle */
/*global window, rJS, RSVP, calculatePageTitle, jIO */
/*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, RSVP, calculatePageTitle) {
(function (window, rJS, RSVP, calculatePageTitle, jIO) {
"use strict";
rJS(window)
......@@ -71,13 +71,13 @@
}
if (delete_action !== undefined) {
delete_action = form_gadget.getUrlFor({command: 'change', options: {view: delete_action.href, editable: undefined}});
delete_action = form_gadget.getUrlFor({command: 'change', options: {view: delete_action.href}});
} else {
delete_action = "";
}
return RSVP.all([
form_gadget.getUrlFor({command: 'change', options: {page: "tab"}}),
form_gadget.getUrlFor({command: 'change', options: {page: "action", editable: true}}),
form_gadget.getUrlFor({command: 'change', options: {page: "action"}}),
new_content_action,
form_gadget.getUrlFor({command: 'history_previous'}),
delete_action,
......@@ -137,9 +137,8 @@
.push(function (result_list) {
if (result_list[1].target.responseType === "blob") {
return jIO.util.readBlobAsText(result_list[1].target.response);
} else {
return {target: {result: result_list[1].target.response}};
}
return {target: {result: result_list[1].target.response}};
})
.push(function (event) {
var message;
......@@ -171,9 +170,8 @@
.push(function () {
if (error.target.responseType === "blob") {
return jIO.util.readBlobAsText(error.target.response);
} else {
return {target: {result: error.target.response}};
}
return {target: {result: error.target.response}};
})
.push(function (event) {
return form_gadget.displayFormulatorValidationError(JSON.parse(event.target.result));
......@@ -187,4 +185,4 @@
}, false, true);
}(window, rJS, RSVP, calculatePageTitle));
\ No newline at end of file
}(window, rJS, RSVP, calculatePageTitle, jIO));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>957.33876.27734.63044</string> </value>
<value> <string>958.31331.40640.10291</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1490373394.35</float>
<float>1491385195.38</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -62,7 +62,6 @@
.push(function (result2) {
return gadget.redirect({command: 'change', options: {
view: result2._links.view[0].href,
editable: undefined,
page: undefined
}});
});
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>958.2825.24067.48281</string> </value>
<value> <string>958.28347.56387.25600</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1489674820.97</float>
<float>1491391860.07</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -33,7 +33,7 @@
gadget = this,
erp5_document,
tab_title = "Views",
tab_icon = options.editable ? "pencil" : "eye",
tab_icon = "eye",
jump_list;
function handleParent(parent_link) {
......@@ -88,7 +88,6 @@
for (i = 0; i < view_list.length; i += 1) {
promise_list.push(gadget.getUrlFor({command: 'change', options: {
view: view_list[i].href,
editable: options.editable,
page: undefined
}}));
}
......@@ -147,10 +146,7 @@
gadget.getUrlFor({command: 'change', options: {
page: undefined
}}),
calculatePageTitle(gadget, erp5_document),
gadget.getUrlFor({command: 'change', options: {
editable: options.editable ? undefined : true
}})
calculatePageTitle(gadget, erp5_document)
]);
})
.push(function (url_list) {
......@@ -158,11 +154,6 @@
back_url: url_list[0],
page_title: url_list[1]
};
if (options.editable) {
dict.view_url = url_list[2];
} else {
dict.edit_url = url_list[2];
}
return gadget.updateHeader(dict);
});
});
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>955.29510.26421.23705</string> </value>
<value> <string>958.28347.56387.25600</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1479825091.01</float>
<float>1491225418.18</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -15,20 +15,36 @@
PREFIX_DISPLAY = "/",
PREFIX_COMMAND = "!",
// PREFIX_ERROR = "?",
// Display a jio document with only the passed parameters
COMMAND_DISPLAY_STATE = "display",
// Store the jio key for the person document of the user
COMMAND_LOGIN = "login",
// Display a raw string URL
COMMAND_RAW = "raw",
// Redisplay the page with the same parameters
COMMAND_RELOAD = "reload",
// Display the latest state stored for a jio document
COMMAND_DISPLAY_STORED_STATE = "display_stored_state",
// Display the current jio document, but change some URL parameters
COMMAND_CHANGE_STATE = "change",
// Like change, but also store the current jio document display state
COMMAND_STORE_AND_CHANGE_STATE = "store_and_change",
// Display one entry index from a selection
COMMAND_INDEX_STATE = "index",
// Display previous entry index from a selection
COMMAND_SELECTION_PREVIOUS = "selection_previous",
// Display next entry index from a selection
COMMAND_SELECTION_NEXT = "selection_next",
// Display previously accessed document
COMMAND_HISTORY_PREVIOUS = "history_previous",
// Store the current document in history and display the next one
COMMAND_PUSH_HISTORY = "push_history",
// Change UI language
COMMAND_CHANGE_LANGUAGE = "change_language",
VALID_URL_COMMAND_DICT = {};
VALID_URL_COMMAND_DICT = {},
STICKY_PARAMETER_LIST = ['editable'];
VALID_URL_COMMAND_DICT[COMMAND_DISPLAY_STATE] = null;
VALID_URL_COMMAND_DICT[COMMAND_DISPLAY_STORED_STATE] = null;
VALID_URL_COMMAND_DICT[COMMAND_CHANGE_STATE] = null;
......@@ -43,6 +59,32 @@
VALID_URL_COMMAND_DICT[COMMAND_RELOAD] = null;
VALID_URL_COMMAND_DICT[COMMAND_CHANGE_LANGUAGE] = null;
function dropStickyParameterEntry(options) {
// Drop sticky parameters from an options dict
// Do not modify the options parameters, to prevent any unexpected side effect
var i,
result = JSON.parse(JSON.stringify(options));
for (i = 0; i < STICKY_PARAMETER_LIST.length; i += 1) {
delete result[STICKY_PARAMETER_LIST[i]];
}
return result;
}
function copyStickyParameterDict(previous_options, next_options, drop_options) {
var i,
key;
// Keep sticky parameters if they are currently defined in URL
if (drop_options === undefined) {
drop_options = {};
}
for (i = 0; i < STICKY_PARAMETER_LIST.length; i += 1) {
key = STICKY_PARAMETER_LIST[i];
// Check that sticky parameter previously exist and that it was not modified
if (previous_options.hasOwnProperty(key) && (!(next_options.hasOwnProperty(key) || drop_options.hasOwnProperty(key)))) {
next_options[key] = previous_options[key];
}
}
}
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
......@@ -68,6 +110,9 @@
}
function addHistory(gadget, options, previous_selection_id) {
// Drop sticky parameters
options = dropStickyParameterEntry(options);
var options_blob = {
type: "options",
data: options
......@@ -242,6 +287,8 @@
if (jio_key) {
queue = gadget.props.jio_state_gadget.get(jio_key)
.push(function (options) {
// Keep the sticky parameters
copyStickyParameterDict(next_options, options);
next_options = options;
}, function (error) {
if ((error instanceof jIO.util.jIOError) &&
......@@ -291,23 +338,24 @@
function execStoreAndChangeCommand(gadget, previous_options, next_options, drop_options) {
var options,
jio_key,
queue;
queue,
display_url;
options = calculateChangeOptions(previous_options, next_options, drop_options);
jio_key = options.jio_key;
delete options.jio_key;
display_url = getDisplayUrlFor(jio_key, options);
if (jio_key) {
queue = gadget.props.jio_state_gadget.put(jio_key, options);
queue = gadget.props.jio_state_gadget.put(jio_key, dropStickyParameterEntry(options));
} else {
queue = new RSVP.Queue();
}
return queue
.push(function () {
return synchronousChangeState(
getDisplayUrlFor(jio_key, options)
);
return synchronousChangeState(display_url);
});
}
......@@ -376,14 +424,16 @@
getCommandUrlFor(gadget, COMMAND_HISTORY_PREVIOUS, previous_options)
);
}
var options = {
selection: previous_options.selection,
selection_index: parseInt(previous_options.selection_index || '0', 10) + 1,
history: previous_options.history
};
copyStickyParameterDict(previous_options, options);
return addNavigationHistoryAndDisplay(
gadget,
result.data.rows[0].id,
{
selection: previous_options.selection,
selection_index: parseInt(previous_options.selection_index || '0', 10) + 1,
history: previous_options.history
}
options
);
});
}, function (error) {
......@@ -425,14 +475,16 @@
getCommandUrlFor(gadget, COMMAND_HISTORY_PREVIOUS, previous_options)