Commit 9dcbc756 authored by Romain Courteaud's avatar Romain Courteaud

[erp5_hal_json_style] Remove support for uids and query parameters

Remove related scripts.

Module action is not a template anymore.
parent 8cf6c1d8
...@@ -207,28 +207,6 @@ if len(listbox_id_list): ...@@ -207,28 +207,6 @@ if len(listbox_id_list):
kw.update(**extra_param) kw.update(**extra_param)
kw.update(keep_items=extra_param) # better backward compatibility kw.update(keep_items=extra_param) # better backward compatibility
# early-stop if user selected all or too many documents
if len(extra_param.get("uids", ())) >= DOCUMENT_COUNT_LIMIT or extra_param.get("query", MARKER) == "":
if dialog_method == update_method:
pass # do not interrupt on UPDATE
elif extra_param.get("basedialog_force_submit", 0) == 0:
extra_param["basedialog_force_submit"] = 1
if len(extra_param.get("uids", ())) >= DOCUMENT_COUNT_LIMIT:
translated_message=translate("Too many documents selected! Submit again to proceed with the first ${limit} or Cancel and narrow down your search.",
mapping={'limit': DOCUMENT_COUNT_LIMIT})
else:
translated_message=translate("All documents are selected! Submit again to proceed or Cancel and narrow down your search.")
return context.Base_renderForm(
dialog_id,
message=translated_message,
level=WARNING,
keep_items=extra_param,
form_data=form_data)
elif len(extra_param.get("uids", ())) >= DOCUMENT_COUNT_LIMIT:
# remove UIDS from the extra_param to force re-computation because the
# query will be the same but UIDS should change
del extra_param['uids']
# if dialog_category is object_search, then edit the selection # if dialog_category is object_search, then edit the selection
if dialog_category == "object_search" : if dialog_category == "object_search" :
portal.portal_selections.setSelectionParamsFor(kw['selection_name'], kw) portal.portal_selections.setSelectionParamsFor(kw['selection_name'], kw)
......
...@@ -37,9 +37,6 @@ Traverse renders arbitrary View. It can be a Form or a Script. ...@@ -37,9 +37,6 @@ Traverse renders arbitrary View. It can be a Form or a Script.
:param relative_url: string, MANDATORY for obtaining the traversed_document. Calling this script directly on an object should be :param relative_url: string, MANDATORY for obtaining the traversed_document. Calling this script directly on an object should be
forbidden in code (but it is not now). forbidden in code (but it is not now).
:param view: {str} mandatory. the view reference as defined on a Portal Type (e.g. "view" or "publish_view") :param view: {str} mandatory. the view reference as defined on a Portal Type (e.g. "view" or "publish_view")
:param query: {str} optional, is a remaining from the search on a previous view. Query is used to replace selections.
It provides complete information together with listbox configuration so we are able to pass a list of UIDs
to methods which require it. This allows dialogs to show selection from previous view.
:param extra_param_json: {str} BASE64 encoded JSON with parameters for getHateoas script. Content will be put to the REQUEST so :param extra_param_json: {str} BASE64 encoded JSON with parameters for getHateoas script. Content will be put to the REQUEST so
it is accessible to all Scripts and TALES expressions. If view contains embedded **dialog** form then it is accessible to all Scripts and TALES expressions. If view contains embedded **dialog** form then
fields will be added to that form to preserve the values for the next step. fields will be added to that form to preserve the values for the next step.
...@@ -67,7 +64,6 @@ from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery ...@@ -67,7 +64,6 @@ from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery
from collections import OrderedDict from collections import OrderedDict
MARKER = [] MARKER = []
DOCUMENT_COUNT_LIMIT = 50
if REQUEST is None: if REQUEST is None:
REQUEST = context.REQUEST REQUEST = context.REQUEST
...@@ -460,8 +456,6 @@ url_template_dict = { ...@@ -460,8 +456,6 @@ url_template_dict = {
"&relative_url=%(relative_url)s&view=%(view)s", "&relative_url=%(relative_url)s&view=%(view)s",
"traverse_generator_action": "%(root_url)s/%(script_id)s?mode=traverse" + \ "traverse_generator_action": "%(root_url)s/%(script_id)s?mode=traverse" + \
"&relative_url=%(relative_url)s&view=%(view)s&extra_param_json=%(extra_param_json)s", "&relative_url=%(relative_url)s&view=%(view)s&extra_param_json=%(extra_param_json)s",
"traverse_generator_action_module": "%(root_url)s/%(script_id)s?mode=traverse" + \
"&relative_url=%(relative_url)s&view=%(view)s&extra_param_json=%(extra_param_json)s{&query}",
"traverse_template": "%(root_url)s/%(script_id)s?mode=traverse" + \ "traverse_template": "%(root_url)s/%(script_id)s?mode=traverse" + \
"{&relative_url,view}", "{&relative_url,view}",
...@@ -1102,17 +1096,6 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti ...@@ -1102,17 +1096,6 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti
if REQUEST.get('cancel_url', None): if REQUEST.get('cancel_url', None):
renderHiddenField(response_dict, "cancel_url", REQUEST.get('cancel_url')) renderHiddenField(response_dict, "cancel_url", REQUEST.get('cancel_url'))
# Let's support Selections!
# If extra_param_json already contains necessary arrtibutes: mandatory `query` and optional `uids`
# then our job is done! If not we need to generate them to become parameters for Dialog method.
if "uids" not in extra_param_json:
method_args = selectKwargsForCallable(getattr(traversed_document, form.action), {}, {'uids': None})
if "uids" in method_args:
extra_param_json["uids"] = [int(getattr(document, "uid"))
for document in traversed_document.Base_searchUsingListbox(
last_listbox, query or extra_param_json.get("query", None), limit=DOCUMENT_COUNT_LIMIT)]
if query is not None:
extra_param_json["query"] = query
else: else:
# In form_view we place only form_id in the request form # In form_view we place only form_id in the request form
renderHiddenField(response_dict, 'form_id', form.id) renderHiddenField(response_dict, 'form_id', form.id)
...@@ -1271,8 +1254,8 @@ def statusLevelToString(level): ...@@ -1271,8 +1254,8 @@ def statusLevelToString(level):
def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, REQUEST=None, def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, REQUEST=None,
response=None, view=None, mode=None, query=None, response=None, view=None, mode=None,
select_list=None, limit=None, form=None, query=None, select_list=None, limit=None, form=None,
relative_url=None, restricted=None, list_method=None, relative_url=None, restricted=None, list_method=None,
default_param_json=None, form_relative_url=None, extra_param_json=None): default_param_json=None, form_relative_url=None, extra_param_json=None):
...@@ -1483,18 +1466,11 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -1483,18 +1466,11 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
# select correct URL template based on action_type and form page template # select correct URL template based on action_type and form page template
url_template_key = "traverse_generator" url_template_key = "traverse_generator"
# Modify Actions on Module - they need access to current form_id and runtime
# information such as `query` in case they operate on selections!
if erp5_action_key not in ("view", "object_view", "object_jio_view"): if erp5_action_key not in ("view", "object_view", "object_jio_view"):
url_template_key = "traverse_generator_action" url_template_key = "traverse_generator_action"
if traversed_document.getPortalType() in portal.getPortalModuleTypeList():
url_template_key = "traverse_generator_action_module"
erp5_action_list[-1]['templated'] = True
# but when we do not have the last form id we do not pass is of course # but when we do not have the last form id we do not pass is of course
if not (current_action.get('view_id', '') or last_form_id): if not (current_action.get('view_id', '') or last_form_id):
url_template_key = "traverse_generator" url_template_key = "traverse_generator"
if 'templated' in erp5_action_list[-1]:
del erp5_action_list[-1]['templated']
# some dialogs need previous form_id when rendering to pass UID to embedded Listbox # some dialogs need previous form_id when rendering to pass UID to embedded Listbox
extra_param_json['form_id'] = current_action['view_id'] \ extra_param_json['form_id'] = current_action['view_id'] \
...@@ -1713,17 +1689,9 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -1713,17 +1689,9 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
ensureDeserialized( ensureDeserialized(
byteify( byteify(
json.loads(urlsafe_b64decode(default_param_json))))) json.loads(urlsafe_b64decode(default_param_json)))))
if query:
if catalog_kw.get("uid", MARKER) is None and extra_param_json.get("form_id", MARKER) is not MARKER:
# a UID == None is a bit hack-ish way of signaling that the list_method
# needs list of UID instead of a regular query
catalog_kw["uid"] = [int(getattr(document, "uid"))
for document in traversed_document.Base_searchUsingListbox(
context.Base_getListbox(extra_param_json["form_id"]), query, limit=DOCUMENT_COUNT_LIMIT, **catalog_kw)]
elif query:
catalog_kw["full_text"] = query catalog_kw["full_text"] = query
# add limit after resolving possible UID because that call (unfortunately) must be unrestricted
if limit: if limit:
catalog_kw["limit"] = limit catalog_kw["limit"] = limit
......
...@@ -960,29 +960,6 @@ class TestERP5Document_getHateoas_mode_traverse(ERP5HALJSONStyleSkinsMixin): ...@@ -960,29 +960,6 @@ class TestERP5Document_getHateoas_mode_traverse(ERP5HALJSONStyleSkinsMixin):
self.assertEqual(result_dict['group_list'][0][1][0], ['my_id', {'meta_type': 'ProxyField'}]) self.assertEqual(result_dict['group_list'][0][1][0], ['my_id', {'meta_type': 'ProxyField'}])
self.assertEqual(result_dict['_debug'], "traverse") self.assertEqual(result_dict['_debug'], "traverse")
@simulate('Base_getRequestUrl', '*args, **kwargs',
'return "http://example.org/bar"')
@simulate('Base_getRequestHeader', '*args, **kwargs',
'return "application/hal+json"')
@changeSkin('Hal')
def test_getHateoasForm_action_module(self):
fake_request = do_fake_request("GET")
result = self.portal.web_site_module.hateoas.ERP5Document_getHateoas(REQUEST=fake_request, mode="traverse", relative_url="foo_module", view='view')
self.assertEquals(fake_request.RESPONSE.status, 200)
self.assertEquals(fake_request.RESPONSE.getHeader('Content-Type'),
"application/hal+json"
)
result_dict = json.loads(result)
if isinstance(result_dict['_links']['action_object_jio_action'], dict):
object_jio_action = result_dict['_links']['action_object_jio_action']
self.assertTrue(object_jio_action['templated'])
self.assertTrue("{&" in object_jio_action['href'])
else:
for object_jio_action in result_dict['_links']['action_object_jio_action']:
# the link is a template
self.assertTrue(object_jio_action['templated'])
self.assertTrue("{&" in object_jio_action['href'])
class TestERP5Document_getHateoas_mode_search(ERP5HALJSONStyleSkinsMixin): class TestERP5Document_getHateoas_mode_search(ERP5HALJSONStyleSkinsMixin):
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>dialog_id, form_id, uids, donothing_confirmation=0, **kwargs</string> </value> <value> <string>dialog_id, form_id, listbox_uid, donothing_confirmation=0, **kwargs</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
"""Return an Iterator over database result from `form_id`'s listbox and optional `query`.
This script is intended to be used only internally.
"""
form = getattr(context, form_id)
listbox = form.Base_getListbox()
return context.Base_searchUsingListbox(listbox, query, sort_on=sort_on, limit=limit)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>form_id, query=\'\', sort_on=(), limit=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_searchUsingFormIdAndQuery</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
"""Extract search settings from a listbox and issue search using `query`.
Listbox is a search-capable component but searching using it is not straightforward. This
script solves exactly that.
Returns an iterable (most likely SearchResult instance depending on list_method definition)
"""
list_method_kwargs = dict(listbox.get_value('default_params')) or {}
# Listbox contraints portal types
if portal_types is not None:
list_method_kwargs.update(portal_types=portal_types)
else:
if "portal_type" in list_method_kwargs:
if isinstance(list_method_kwargs['portal_type'], str):
list_method_kwargs['portal_type'] = [list_method_kwargs['portal_type'], ]
elif listbox.get_value("portal_types"):
list_method_kwargs['portal_type'] = [portal_type_name for portal_type_name, _ in listbox.get_value("portal_types")]
# query is provided by the caller because it is a runtime information
if query or full_text:
list_method_kwargs.update(full_text=query or full_text) # second overwrite the query
if limit:
list_method_kwargs.update(limit=limit)
if sort_on:
list_method_kwargs.update(sort_on=sort_on)
list_method_name = listbox.get_value('list_method').getMethodName()
list_method = getattr(context, list_method_name) # get the list_method with correct context
return list_method(**list_method_kwargs)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>listbox, query=\'\', full_text=\'\', sort_on=(), limit=None, portal_types=None, **kwargs</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_searchUsingListbox</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
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