Commit 2ca416d4 authored by Romain Courteaud's avatar Romain Courteaud

erp5_*: add full compatibility to jump action in ERP5JS

Introduce the object_jio_jump action category to mark all compatible actions.

erp5_xhtml_style supports object_jio_jump.

A correct redirection is needed to jump in both UI.

ERP5JS will display modules on the current document context,
as if the jump was instead a object_view action.
parent 06c79fa4
......@@ -1327,6 +1327,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
# Try to embed the form in the result
if (view == view_action['id']):
current_action = parseActionUrl('%s' % view_action['url']) # current action/view being rendered
current_action['category_type'] = erp5_action_key
if view and (view != 'view') and (current_action.get('view_id', None) is None):
# XXX Allow to directly render a form
......@@ -1357,7 +1358,10 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
# (e.g. function or bound class method will) not have .meta_type thus be considered a Script
# then we execute it directly
if "Script" in getattr(view_instance, "meta_type", "Script"):
view_instance = getattr(traversed_document, 'Base_viewFakePythonScriptActionForm')
if current_action.get('category_type', None) == 'object_jio_jump':
view_instance = getattr(traversed_document, 'Base_viewFakeJumpForm')
else:
view_instance = getattr(traversed_document, 'Base_viewFakePythonScriptActionForm')
if view_instance.pt == "form_dialog":
# If there is a "form_id" in the REQUEST then it means that last view was actually a form
......@@ -1371,7 +1375,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
renderForm(traversed_document, view_instance, embedded_dict,
selection_params=extra_param_json, extra_param_json=extra_param_json)
if view_instance.pt == "form_python_action":
if view_instance.pt in ["form_python_action", "form_jump"]:
for k, v in current_action['params'].items():
renderHiddenField(embedded_dict, k, v)
embedded_dict['_embedded']['form_definition']['group_list'][-1][1].append((k, {'meta_type': 'StringField'}))
......@@ -1406,7 +1410,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
global_action_type = ("view", "workflow", "object_new_content_action",
"object_clone_action", "object_delete_action",
"object_list_action")
"object_list_action", "object_jio_jump")
if (erp5_action_key == view_action_type or
erp5_action_key in global_action_type or
"_jio" in erp5_action_key):
......@@ -1432,31 +1436,6 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
"extra_param_json": urlsafe_b64encode(json.dumps(ensureSerializable(extra_param_json)))
}
if erp5_action_key == 'object_jump':
if 'Base_jumpToRelatedObject?' in view_action['url']:
# Fetch the URL arguments
# XXX Correctly unquote arguments
argument_dict = dict([x.split('=') for x in view_action['url'].split('?', 1)[1].split("&")])
jump_portal_type = argument_dict.pop('portal_type', None)
if (jump_portal_type is not None):
jump_portal_type = jump_portal_type.replace('+', ' ')
final_argument_dict = {'portal_type': jump_portal_type}
jump_related = argument_dict.pop('related', 1)
if (jump_related):
jump_related_suffix = ''
else:
jump_related_suffix = 'related_'
jump_uid = portal.restrictedTraverse(argument_dict.pop('jump_from_relative_url', getRealRelativeUrl(traversed_document))).getUid()
final_argument_dict['default_%s_%suid' % (argument_dict.pop('base_category'), jump_related_suffix)] = jump_uid
erp5_action_list[-1]['href'] = url_template_dict["jio_search_template"] % {
"query": make_query({"query": sql_catalog.buildQuery(final_argument_dict).asSearchTextExpression(sql_catalog)})
}
else:
# XXX How to handle all custom jump actions?
erp5_action_list.pop(-1)
if erp5_action_list:
if len(erp5_action_list) == 1:
erp5_action_list = erp5_action_list[0]
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>action_title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_viewFakeJumpForm</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>Base_viewFakePythonScriptActionForm</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_jump</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -603,11 +603,12 @@ class TestERP5Document_getHateoas_mode_traverse(ERP5HALJSONStyleSkinsMixin):
self.assertEqual(result_dict['_links']['action_workflow'][0]['title'], "Custom Action No Dialog")
self.assertEqual(result_dict['_links']['action_workflow'][0]['name'], "custom_action_no_dialog")
self.assertEqual(result_dict['_links']['action_object_jump']['href'],
"urn:jio:allDocs?query=portal_type%%3A%%22Query%%22%%20AND%%20default_agent_uid%%3A%sL" %
document.getUid())
self.assertEqual(result_dict['_links']['action_object_jump']['title'], "Queries")
self.assertEqual(result_dict['_links']['action_object_jump']['name'], "jump_query")
self.assertEqual(result_dict['_links']['action_object_jio_jump']['href'],
"%s/web_site_module/hateoas/ERP5Document_getHateoas?mode=traverse&relative_url=%s&view=jump_query&extra_param_json=eyJmb3JtX2lkIjogIkZvb192aWV3In0=" % (
self.portal.absolute_url(),
urllib.quote_plus(document.getRelativeUrl())))
self.assertEqual(result_dict['_links']['action_object_jio_jump']['title'], "Queries")
self.assertEqual(result_dict['_links']['action_object_jio_jump']['name'], "jump_query")
self.assertEqual(result_dict['_links']['portal']['href'], 'urn:jio:get:%s' % document.getPortalObject().getId())
self.assertEqual(result_dict['_links']['portal']['name'], document.getPortalObject().getTitle())
......@@ -959,11 +960,12 @@ class TestERP5Document_getHateoas_mode_traverse(ERP5HALJSONStyleSkinsMixin):
self.assertEqual(result_dict['_links']['action_workflow'][0]['title'], "Custom Action No Dialog")
self.assertEqual(result_dict['_links']['action_workflow'][0]['name'], "custom_action_no_dialog")
self.assertEqual(result_dict['_links']['action_object_jump']['href'],
"urn:jio:allDocs?query=portal_type%%3A%%22Query%%22%%20AND%%20default_agent_uid%%3A%sL" %
document.getUid())
self.assertEqual(result_dict['_links']['action_object_jump']['title'], "Queries")
self.assertEqual(result_dict['_links']['action_object_jump']['name'], "jump_query")
self.assertEqual(result_dict['_links']['action_object_jio_jump']['href'],
"%s/web_site_module/hateoas/ERP5Document_getHateoas?mode=traverse&relative_url=%s&view=jump_query&extra_param_json=eyJmb3JtX2lkIjogIkJhc2Vfdmlld01ldGFkYXRhIn0=" % (
self.portal.absolute_url(),
urllib.quote_plus(document.getRelativeUrl())))
self.assertEqual(result_dict['_links']['action_object_jio_jump']['title'], "Queries")
self.assertEqual(result_dict['_links']['action_object_jio_jump']['name'], "jump_query")
self.assertEqual(result_dict['_links']['portal']['href'], 'urn:jio:get:%s' % document.getPortalObject().getId())
self.assertEqual(result_dict['_links']['portal']['name'], document.getPortalObject().getTitle())
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_jump</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_jump</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>jump_to_related_bar</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>1.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Related Bar</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string encoding="cdata"><![CDATA[
string:${object_url}/Base_jumpToRelatedObject?base_category=successor&portal_type=Bar
]]></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
Bar Module | multi_form_dialog
Bar Module | view
Bar | jump_to_related_bar
Bar | list
Bar | performance
Bar | view
......
......@@ -104,7 +104,7 @@
<item>
<key> <string>text_content</string> </key>
<value> <string>CACHE MANIFEST\n
# generated on Thu, 19 Sep 2019 00:00:00 GMT+0100\n
# generated on Thu, 07 Jan 2020 00:00:00 GMT+0100\n
# XXX + fonts\n
# images/ajax-loader.gif\n
CACHE:\n
......@@ -210,6 +210,8 @@ gadget_erp5_pt_embedded_form_render.html\n
gadget_erp5_pt_embedded_form_render.js\n
gadget_erp5_pt_form_dialog.html\n
gadget_erp5_pt_form_dialog.js\n
gadget_erp5_pt_form_jump.html\n
gadget_erp5_pt_form_jump.js\n
gadget_erp5_pt_form_python_action.html\n
gadget_erp5_pt_form_python_action.js\n
gadget_erp5_pt_form_list.html\n
......@@ -254,7 +256,8 @@ jiodev.js\n
renderjs.js\n
rsvp.js\n
NETWORK:\n
*</string> </value>
*\n
</string> </value>
</item>
<item>
<key> <string>title</string> </key>
......@@ -303,114 +306,122 @@ NETWORK:\n
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>publish_alive</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1465381395.69</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>published_alive</string> </value>
</item>
</dictionary>
</list>
</tuple>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>publish_alive</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1465381395.69</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>published_alive</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>978.35229.31566.53742</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1568879864.85</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>981.438.11963.4386</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1578416140.21</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -5,36 +5,20 @@
<meta name="viewport" content="width=device-width" />
<title>ERP5 Page Jump</title>
<link rel="http://www.renderjs.org/rel/interface" href="interface_page.html">
<link rel="http://www.renderjs.org/rel/interface" href="interface_erp5_form_content_provider.html">
<!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<script src="handlebars.js" type="text/javascript"></script>
<script src="jiodev.js" type="text/javascript"></script>
<!-- custom script -->
<script src="jiodev.js" type="text/javascript"></script>
<script src="gadget_global.js" type="text/javascript"></script>
<script src="gadget_erp5_global.js" type="text/javascript"></script>
<script src="gadget_erp5_page_jump.js" type="text/javascript"></script>
<!-- XXX need theme here currently -->
<script id="table-template" type="text/x-handlebars-template">
<section class="ui-content-header-plain">
<h3 data-i18n="[last]{{definition_i18n}}">
<span class="ui-icon ui-icon-plane">&nbsp;</span>
{{definition_title}}
</h3>
</section>
<ul class="document-listview">
{{#each documentlist}}
<li><a data-i18n="{{i18n}}" href="{{link}}">{{title}}</a></li>
{{/each}}
</ul>
</script>
</head>
<body>
<div data-gadget-url="gadget_erp5_page_form.html" data-gadget-scope="page_form"></div>
</body>
</html>
\ No newline at end of file
/*global window, rJS, renderFormViewHeader, RSVP */
/*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, renderFormViewHeader, RSVP) {
"use strict";
var gadget_klass = rJS(window),
method_list = ['triggerSubmit', 'checkValidity', 'getContent'],
i;
function propagateMethod(method_name) {
return function callMethod() {
var argument_list = arguments;
return this.getDeclaredGadget('page_form')
.push(function (g) {
return g[method_name].apply(g, argument_list);
});
};
}
function disable() {
return;
}
for (i = 0; i < method_list.length; i += 1) {
gadget_klass.declareMethod(method_list[i], propagateMethod(method_list[i]));
}
gadget_klass
.declareMethod('render', function (options) {
var argument_list = arguments,
gadget = this;
return RSVP.all([
// Render the form_list...
gadget.getDeclaredGadget('page_form')
.push(function (g) {
return g.render.apply(g, argument_list);
}),