Commit bd798008 authored by Romain Courteaud's avatar Romain Courteaud

[erp5_web_renderjs_ui] Add context links in panel

The links are only visible in desktop display.
Links are only calculated for non module document in form_view/dialog
parent d2f55319
...@@ -42,6 +42,10 @@ ...@@ -42,6 +42,10 @@
}; };
} }
function initPanelOptions(gadget) {
gadget.props.panel_argument_list = {};
}
function route(my_root_gadget, my_scope, my_method, argument_list) { function route(my_root_gadget, my_scope, my_method, argument_list) {
return RSVP.Queue() return RSVP.Queue()
.push(function () { .push(function () {
...@@ -67,6 +71,13 @@ ...@@ -67,6 +71,13 @@
}); });
} }
function updatePanel(gadget) {
return gadget.getDeclaredGadget("panel")
.push(function (panel_gadget) {
return panel_gadget.render(gadget.props.panel_argument_list);
});
}
function increaseLoadingCounter(gadget) { function increaseLoadingCounter(gadget) {
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
...@@ -148,6 +159,10 @@ ...@@ -148,6 +159,10 @@
if (error instanceof Error) { if (error instanceof Error) {
console.error(error.stack); console.error(error.stack);
} }
if (gadget.props === undefined) {
// Gadget has not yet been correctly initialized
throw error;
}
// XXX Improve error rendering // XXX Improve error rendering
gadget.props.content_element.innerHTML = "<br/><br/><br/><pre></pre>"; gadget.props.content_element.innerHTML = "<br/><br/><br/><pre></pre>";
gadget.props.content_element.querySelector('pre').textContent = gadget.props.content_element.querySelector('pre').textContent =
...@@ -235,13 +250,11 @@ ...@@ -235,13 +250,11 @@
return jio_gadget.createJio(setting.jio_storage_description); return jio_gadget.createJio(setting.jio_storage_description);
}) })
.push(function () { .push(function () {
return gadget.getDeclaredGadget('panel'); return gadget.getDeclaredGadget('panel');
}) })
.push(function (panel_gadget) { .push(function (panel_gadget) {
return panel_gadget.render(); return panel_gadget.render({});
}) })
.push(function () { .push(function () {
return gadget.getDeclaredGadget('router'); return gadget.getDeclaredGadget('router');
}) })
...@@ -407,6 +420,12 @@ ...@@ -407,6 +420,12 @@
}); });
}) })
.allowPublicAcquisition("updatePanel", function (param_list) {
var gadget = this;
initPanelOptions(gadget);
gadget.props.panel_argument_list = param_list[0];
})
.allowPublicAcquisition('triggerPanel', function () { .allowPublicAcquisition('triggerPanel', function () {
return route(this, "panel", "toggle"); return route(this, "panel", "toggle");
}) })
...@@ -487,7 +506,10 @@ ...@@ -487,7 +506,10 @@
content_container.appendChild(main_gadget.element); content_container.appendChild(main_gadget.element);
element.appendChild(content_container); element.appendChild(content_container);
return updateHeader(gadget); return RSVP.all([
updateHeader(gadget),
updatePanel(gadget)
]);
// XXX Drop notification // XXX Drop notification
// return header_gadget.notifyLoaded(); // return header_gadget.notifyLoaded();
} }
...@@ -500,7 +522,10 @@ ...@@ -500,7 +522,10 @@
return page_gadget.render(gadget.state.options); return page_gadget.render(gadget.state.options);
}) })
.push(function () { .push(function () {
return updateHeader(gadget); return RSVP.all([
updateHeader(gadget),
updatePanel(gadget)
]);
}); });
}) })
// Render the page // Render the page
...@@ -512,6 +537,7 @@ ...@@ -512,6 +537,7 @@
// By default, init the header options to be empty // By default, init the header options to be empty
// (ERP5 title by default + sidebar) // (ERP5 title by default + sidebar)
initHeaderOptions(gadget); initHeaderOptions(gadget);
initPanelOptions(gadget);
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
return increaseLoadingCounter(gadget); return increaseLoadingCounter(gadget);
......
...@@ -230,7 +230,7 @@ ...@@ -230,7 +230,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>956.5832.50053.43878</string> </value> <value> <string>957.35152.14703.9045</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1482250162.82</float> <float>1487941504.18</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -488,25 +488,62 @@ div[data-gadget-scope='panel'] img { ...@@ -488,25 +488,62 @@ div[data-gadget-scope='panel'] img {
text-align: left; text-align: left;
height: 100%; height: 100%;
} }
div[data-gadget-scope='panel'] ul { div[data-gadget-scope='panel'] ul:first-child {
margin-top: 30pt; margin-top: 30pt;
} }
div[data-gadget-scope='panel'] ul li a { div[data-gadget-scope='panel'] ul li a {
color: #FFFFFF; color: #FFFFFF;
display: block;
padding: 3pt; padding: 3pt;
padding-left: 12pt; padding-left: 12pt;
display: block;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
} }
div[data-gadget-scope='panel'] ul li a:hover,
div[data-gadget-scope='panel'] ul li a:active {
background-color: #2b2b2b;
}
div[data-gadget-scope='panel'] ul li a::before { div[data-gadget-scope='panel'] ul li a::before {
width: 24pt; width: 24pt;
} }
div[data-gadget-scope='panel'] ul li a:hover, div[data-gadget-scope='panel'] dl {
div[data-gadget-scope='panel'] ul li a:active { background-color: #777777;
color: #1F1F1F;
transform-origin: 50% 0;
transform: scaleY(0);
transition: transform 0.2s ease-out;
}
div[data-gadget-scope='panel'] dl:not(:empty) {
transform: scaleY(1);
}
div[data-gadget-scope='panel'] dl dt {
padding: 3pt;
padding-left: 12pt;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
div[data-gadget-scope='panel'] dl dt::before {
width: 24pt;
}
div[data-gadget-scope='panel'] dl dd a {
color: #FFFFFF;
display: block;
padding: 3pt;
padding-left: 12pt;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
padding-left: 36pt;
}
div[data-gadget-scope='panel'] dl dd a:hover,
div[data-gadget-scope='panel'] dl dd a:active {
background-color: #2b2b2b; background-color: #2b2b2b;
} }
div[data-gadget-scope='panel'] dl dd a::before {
width: 24pt;
}
/********************************************** /**********************************************
* Gadget: editor panel * Gadget: editor panel
**********************************************/ **********************************************/
......
...@@ -242,7 +242,7 @@ ...@@ -242,7 +242,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>956.58713.6703.47906</string> </value> <value> <string>957.39714.21193.35498</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -260,7 +260,7 @@ ...@@ -260,7 +260,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1485423923.88</float> <float>1488215480.92</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -35,9 +35,25 @@ ...@@ -35,9 +35,25 @@
<li><a href="{{preference_href}}" class="ui-btn ui-btn-icon-left ui-icon-gear" data-i18n="Preferences">Preferences</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> <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> </ul>
<dl></dl>
</div> </div>
</script> </script>
<script id="panel-template-body-desktop" type="text/x-handlebars-template">
<dt class="ui-content-title ui-body-c ui-btn ui-btn-icon-left ui-icon-eye" data-i18n="Views">Views</dt>
{{#each view_list}}
<dd data-role="listview" data-theme="c" data-inset="true" class="document-listview">
<a data-i18n="{{title}}" class="ui-body-inherit" href="{{href}}">{{title}}</a>
</dd>
{{/each}}
<dt class="ui-content-title ui-body-c ui-btn ui-btn-icon-left ui-icon-cogs" data-i18n="Decisions">Decisions</dt>
{{#each workflow_list}}
<dd data-role="listview" data-theme="c" data-inset="true" class="document-listview">
<a data-i18n="{{title}}" class="ui-body-inherit" href="{{href}}">{{title}}</a>
</dd>
{{/each}}
</script>
<!-- custom script --> <!-- custom script -->
<script src="gadget_erp5_panel.js" type="text/javascript"></script> <script src="gadget_erp5_panel.js" type="text/javascript"></script>
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>957.20614.31452.4437</string> </value> <value> <string>957.39718.21180.26828</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1487069250.39</float> <float>1488215553.05</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*jslint nomen: true, indent: 2, maxerr: 3 */ /*jslint nomen: true, indent: 2, maxerr: 3 */
/*global window, rJS, Handlebars, RSVP, Node */ /*global window, document, rJS, Handlebars, RSVP, Node, loopEventListener */
(function (window, rJS, Handlebars, RSVP, Node) { (function (window, document, rJS, Handlebars, RSVP, Node, loopEventListener) {
"use strict"; "use strict";
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -14,11 +14,15 @@ ...@@ -14,11 +14,15 @@
.innerHTML), .innerHTML),
panel_template_body = Handlebars.compile(template_element panel_template_body = Handlebars.compile(template_element
.getElementById("panel-template-body") .getElementById("panel-template-body")
.innerHTML),
panel_template_body_desktop = Handlebars.compile(template_element
.getElementById("panel-template-body-desktop")
.innerHTML); .innerHTML);
gadget_klass gadget_klass
.setState({ .setState({
visible: false visible: false,
desktop: false
}) })
////////////////////////////////////////////// //////////////////////////////////////////////
// acquired method // acquired method
...@@ -40,48 +44,151 @@ ...@@ -40,48 +44,151 @@
}); });
}) })
.declareMethod('render', function () { .declareMethod('render', function (options) {
var g = this; var erp5_document = options.erp5_document,
return new RSVP.Queue() workflow_list,
view_list;
if (erp5_document !== undefined) {
workflow_list = erp5_document._links.action_workflow || [];
view_list = erp5_document._links.action_object_view || [];
if (workflow_list.constructor !== Array) {
workflow_list = [workflow_list];
}
if (view_list.constructor !== Array) {
view_list = [view_list];
}
// Prevent has much as possible to modify the DOM panel
// stateChange prefer to compare strings
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
});
})
.onStateChange(function (modification_dict) {
var context = this,
gadget = this,
queue = new RSVP.Queue();
if (modification_dict.hasOwnProperty("visible")) {
if (this.state.visible) {
if (!this.element.classList.contains('visible')) {
this.element.classList.toggle('visible');
}
} else {
if (this.element.classList.contains('visible')) {
this.element.classList.remove('visible');
}
}
}
if (modification_dict.hasOwnProperty("global")) {
queue
.push(function () { .push(function () {
return RSVP.all([ return RSVP.all([
g.getUrlFor({command: 'display', options: {page: "front"}}), context.getUrlFor({command: 'display', options: {page: "front"}}),
g.getUrlFor({command: 'display', options: {page: "history"}}), context.getUrlFor({command: 'display', options: {page: "history"}}),
g.getUrlFor({command: 'display', options: {page: "preference"}}), context.getUrlFor({command: 'display', options: {page: "preference"}}),
g.getUrlFor({command: 'display', options: {page: "logout"}}), context.getUrlFor({command: 'display', options: {page: "logout"}}),
g.getUrlFor({command: 'display', options: {page: "search"}}), context.getUrlFor({command: 'display', options: {page: "search"}}),
g.getUrlFor({command: 'display', options: {page: "worklist"}}) context.getUrlFor({command: 'display', options: {page: "worklist"}})
]); ]);
}) })
.push(function (all_result) { .push(function (result_list) {
// XXX: Customize panel header! // XXX: Customize panel header!
return g.translateHtml( return context.translateHtml(
panel_template_header() + panel_template_header() +
panel_template_body({ panel_template_body({
"module_href": all_result[0], "module_href": result_list[0],
"history_href": all_result[1], "history_href": result_list[1],
"preference_href": all_result[2], "preference_href": result_list[2],
"logout_href": all_result[3], "logout_href": result_list[3],
"search_href": all_result[4], "search_href": result_list[4],
"worklist_href": all_result[5] "worklist_href": result_list[5]
}) })
); );
}) })
.push(function (my_translated_or_plain_html) { .push(function (my_translated_or_plain_html) {
g.element.querySelector("div").innerHTML = my_translated_or_plain_html; context.element.querySelector("div").innerHTML = my_translated_or_plain_html;
return context.listenResize();
}); });
}
if ((this.state.global === true) &&
(modification_dict.hasOwnProperty("desktop") ||
modification_dict.hasOwnProperty("editable") ||
modification_dict.hasOwnProperty("workflow_list") ||
modification_dict.hasOwnProperty("view_list"))) {
if (!(this.state.desktop && (this.state.view_list !== undefined))) {
queue
.push(function () {
gadget.element.querySelector("dl").textContent = '';
});
} else {
queue
.push(function () {
var i = 0,
promise_list = [],
workflow_list = JSON.parse(gadget.state.workflow_list),
view_list = JSON.parse(gadget.state.view_list);
for (i = 0; i < workflow_list.length; i += 1) {
promise_list.push(
gadget.getUrlFor({
command: 'change',
options: {
view: workflow_list[i].href,
page: undefined
}
})
);
}
for (i = 0; i < view_list.length; i += 1) {
promise_list.push(
gadget.getUrlFor({
command: 'change',
options: {
view: view_list[i].href,
page: undefined
}
})
);
}
return RSVP.all(promise_list);
}) })
.push(function (result_list) {
var i,
result_workflow_list = [],
result_view_list = [],
workflow_list = JSON.parse(gadget.state.workflow_list),
view_list = JSON.parse(gadget.state.view_list);
.onStateChange(function () { for (i = 0; i < workflow_list.length; i += 1) {
if (this.state.visible) { result_workflow_list.push({
if (!this.element.classList.contains('visible')) { title: workflow_list[i].title,
this.element.classList.toggle('visible'); href: result_list[i]
});
} }
} else { for (i = 0; i < view_list.length; i += 1) {
if (this.element.classList.contains('visible')) { result_view_list.push({
this.element.classList.remove('visible'); title: view_list[i].title,
href: result_list[i + workflow_list.length]
});
}
gadget.element.querySelector("dl").innerHTML = panel_template_body_desktop({
workflow_list: result_workflow_list,
view_list: result_view_list
});
});
} }
} }
return queue;
}) })
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -92,6 +199,30 @@ ...@@ -92,6 +199,30 @@
(evt.target.tagName === 'BUTTON')) { (evt.target.tagName === 'BUTTON')) {
return this.toggle(); return this.toggle();
} }
}, false, false); }, false, false)
.declareJob('listenResize', function () {
// resize should be only trigger after the render method
// as displaying the panel rely on external gadget (for translation for example)
var result,
event,
context = this;
function extractSizeAndDispatch() {
if (window.matchMedia("(min-width: 90em)").matches) {
return context.changeState({
desktop: true
});
}
return context.changeState({
desktop: false
});
}
result = loopEventListener(window, 'resize', false,
extractSizeAndDispatch);
event = document.createEvent("Event");
event.initEvent('resize', true, true);
window.dispatchEvent(event);
return result;
});
}(window, rJS, Handlebars, RSVP, Node)); }(window, document, rJS, Handlebars, RSVP, Node, loopEventListener));
...@@ -230,7 +230,7 @@ ...@@ -230,7 +230,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>955.32296.8972.20241</string> </value> <value> <string>957.41111.56434.58897</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1479992698.26</float> <float>1488299408.27</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
.declareAcquiredMethod("jio_getAttachment", "jio_getAttachment") .declareAcquiredMethod("jio_getAttachment", "jio_getAttachment")
.declareAcquiredMethod("redirect", "redirect") .declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("jio_allDocs", "jio_allDocs") .declareAcquiredMethod("jio_allDocs", "jio_allDocs")
.declareAcquiredMethod("updatePanel", "updatePanel")
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// declared methods // declared methods
...@@ -131,6 +132,17 @@ ...@@ -131,6 +132,17 @@
element.appendChild(fragment); element.appendChild(fragment);
}); });
} }
})
.push(function () {
var jio_key = gadget.state.options.jio_key;
/*jslint regexp: true*/
if (/^[^\/]+_module\/.+$/.test(jio_key)) {
/*jslint regexp: false*/
return gadget.updatePanel({
erp5_document: JSON.parse(gadget.state.erp5_document),
editable: gadget.state.options.editable
});
}
}); });
}) })
.allowPublicAcquisition("displayFormulatorValidationError", function (param_list) { .allowPublicAcquisition("displayFormulatorValidationError", function (param_list) {
......
...@@ -230,7 +230,7 @@ ...@@ -230,7 +230,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>954.44527.39200.57275</string> </value> <value> <string>958.2825.24067.48281</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1476793905.11</float> <float>1489674820.97</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -582,15 +582,9 @@ div[data-gadget-scope='panel'] { ...@@ -582,15 +582,9 @@ div[data-gadget-scope='panel'] {
} }
.alignwithicon() {
ul {
margin-top: @headerheight;
li {
a {
color: @white;
padding: @half-margin-size; padding: @half-margin-size;
padding-left: @double-margin-size; padding-left: @double-margin-size;
display: block;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
...@@ -600,10 +594,54 @@ div[data-gadget-scope='panel'] { ...@@ -600,10 +594,54 @@ div[data-gadget-scope='panel'] {
// To keep text aligned // To keep text aligned
width: @quadruple-margin-size; width: @quadruple-margin-size;
} }
}
.alignwithouticon() {
.alignwithicon();
padding-left: @double-margin-size + @quadruple-margin-size;
}
.linkpanel() {
color: @white;
display: block;
&:hover, &:active { &:hover, &:active {
background-color: darken(@panelbackgroundcolor, 10%); background-color: darken(@panelbackgroundcolor, 10%);
} }
} }
ul {
&:first-child {
margin-top: @headerheight;
}
li {
a {
.linkpanel();
.alignwithicon();
}
}
}
dl {
background-color: @grey;
color: @black;
// Animate when content is added
transform-origin: 50% 0;
transform: scaleY(0);
&:not(:empty) {
transform: scaleY(1);
}
transition: transform @transition-timing;
dt {
.alignwithicon();
}
dd {
a {
.linkpanel();
.alignwithouticon();
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment