Commit c2c2cf41 authored by Romain Courteaud's avatar Romain Courteaud

[erp5_hal_json_style] Add selection compatibility required by somes actions

Store a new Selection everytime a Listbox content is calculated.
This will allow actions checking the selection params to get expected results.

Propagate selection_name in dialog if the dialog doesn't contain a listbox itself.
parent a4d35fe4
...@@ -62,6 +62,7 @@ from Products.ERP5Type.Message import Message ...@@ -62,6 +62,7 @@ from Products.ERP5Type.Message import Message
from Products.ERP5Type.Utils import UpperCase from Products.ERP5Type.Utils import UpperCase
from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery
from collections import OrderedDict from collections import OrderedDict
from Products.ERP5Form.Selection import Selection
MARKER = [] MARKER = []
COUNT_LIMIT = 1000 COUNT_LIMIT = 1000
...@@ -985,6 +986,16 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti ...@@ -985,6 +986,16 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti
# overwrite "form_id" field's value because old UI does that by passing # overwrite "form_id" field's value because old UI does that by passing
# the form_id in query string and hidden fields # the form_id in query string and hidden fields
renderHiddenField(response_dict, "form_id", last_form_id) renderHiddenField(response_dict, "form_id", last_form_id)
if (last_listbox is not None):
try:
current_listbox = form.Base_getListbox()
except AttributeError:
current_listbox = None
if (current_listbox is None):
# If dialog has a listbox, do not return selection name
# or it will lead to unexpected selection name
last_selection_name = last_listbox.get_value('selection_name')
renderHiddenField(response_dict, "selection_name", last_selection_name)
# dialog_id is a mandatory field in any form_dialog # dialog_id is a mandatory field in any form_dialog
renderHiddenField(response_dict, 'dialog_id', form.id) renderHiddenField(response_dict, 'dialog_id', form.id)
# some dialog actions use custom cancel_url # some dialog actions use custom cancel_url
...@@ -1121,6 +1132,7 @@ def renderFormDefinition(form, response_dict): ...@@ -1121,6 +1132,7 @@ def renderFormDefinition(form, response_dict):
if form.pt == "form_dialog": if form.pt == "form_dialog":
# every form dialog has its dialog_id and meta (control) attributes in extra_param_json # every form dialog has its dialog_id and meta (control) attributes in extra_param_json
group_list[-1][1].extend([ group_list[-1][1].extend([
('selection_name', {'meta_type': 'StringField'}),
('dialog_id', {'meta_type': 'StringField'}), ('dialog_id', {'meta_type': 'StringField'}),
('extra_param_json', {'meta_type': 'StringField'}) ('extra_param_json', {'meta_type': 'StringField'})
]) ])
...@@ -1655,12 +1667,23 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -1655,12 +1667,23 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
byteify(json.loads(selection_domain))) byteify(json.loads(selection_domain)))
category_tool = portal.portal_categories category_tool = portal.portal_categories
domain_tool = portal.portal_domains domain_tool = portal.portal_domains
if is_rendering_listbox:
new_selection_dict = {}
for domain_root_id in selection_domain_dict: for domain_root_id in selection_domain_dict:
domain_root = category_tool.restrictedTraverse(domain_root_id, None) domain_root = category_tool.restrictedTraverse(domain_root_id, None)
selection_path = selection_domain_dict[domain_root_id]
if domain_root is None: if domain_root is None:
selection_root = 'portal_domains'
selection_domain_dict[domain_root_id] = domain_tool.getDomainByPath('%s/%s' % (domain_root_id, selection_domain_dict[domain_root_id])) selection_domain_dict[domain_root_id] = domain_tool.getDomainByPath('%s/%s' % (domain_root_id, selection_domain_dict[domain_root_id]))
else: else:
selection_root = 'portal_categories'
selection_domain_dict[domain_root_id] = domain_root.restrictedTraverse(selection_domain_dict[domain_root_id]) selection_domain_dict[domain_root_id] = domain_root.restrictedTraverse(selection_domain_dict[domain_root_id])
if is_rendering_listbox:
new_selection_dict[domain_root_id] = (selection_root, '%s/%s' % (domain_root_id, selection_path), )
catalog_kw["selection_domain"] = selection_domain_dict catalog_kw["selection_domain"] = selection_domain_dict
if sort_on is not None: if sort_on is not None:
...@@ -1700,6 +1723,41 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -1700,6 +1723,41 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
# by fetching more documents than requested # by fetching more documents than requested
catalog_kw["limit"] = [0, COUNT_LIMIT] catalog_kw["limit"] = [0, COUNT_LIMIT]
if is_rendering_listbox:
# Store the current search parameters in the listbox selection
# This is done to improve compatibility with existing actions (ODS style for example)
# No need to edit current selection. Replace it with a new one
selection_tool = portal.portal_selections
selection_name = source_field.get_value('selection_name')
selection_kw = {}
selection_kw['method_path'] = '%s/%s' % (traversed_document.getPath(), list_method)
selection_kw['params'] = {}
if default_param_json is not None:
selection_kw['params'].update(
ensureDeserialized(
byteify(
json.loads(urlsafe_b64decode(default_param_json)))))
selection_kw['params']['limit'] = COUNT_LIMIT
selection_kw['params']['local_roles'] = catalog_kw["local_roles"]
if 'full_text' in catalog_kw:
selection_kw['params']['full_text'] = catalog_kw["full_text"]
if 'sort_on' in catalog_kw:
selection_kw['sort_on'] = catalog_kw['sort_on']
if select_list:
column_list = [(name, title) for name, title in source_field.get_value("columns") if name in select_list]
all_column_list = [(name, title) for name, title in source_field.get_value("all_columns") if name in select_list]
selection_kw['columns'] = [(name, Base_translateString(title))
for name, title in OrderedDict(column_list + all_column_list).items()]
else:
selection_kw['columns'] = []
selection_tool.setSelectionFor(selection_name, Selection(selection_name, **selection_kw))
if 'selection_domain' in catalog_kw:
selection_tool.setDomainDictFromParam(selection_name, new_selection_dict)
# Some search scripts impertinently grab their arguments from REQUEST # Some search scripts impertinently grab their arguments from REQUEST
# instead of being nice and specify them as their input parameters. # instead of being nice and specify them as their input parameters.
# #
......
...@@ -16,6 +16,9 @@ import json ...@@ -16,6 +16,9 @@ import json
import re import re
import urllib import urllib
from Products.ERP5Form.Selection import Selection, DomainSelection
def changeSkin(skin_name): def changeSkin(skin_name):
"""Change skin for following commands and attribute resolution. """Change skin for following commands and attribute resolution.
...@@ -2085,6 +2088,63 @@ return context.getPortalObject().portal_catalog(portal_type='Foo', sort_on=[('id ...@@ -2085,6 +2088,63 @@ return context.getPortalObject().portal_catalog(portal_type='Foo', sort_on=[('id
self.assertEqual(len(result_dict['_embedded']['contents']), 1) self.assertEqual(len(result_dict['_embedded']['contents']), 1)
self.assertEqual(result_dict['_embedded']['count'], 1) self.assertEqual(result_dict['_embedded']['count'], 1)
@simulate('Base_getRequestUrl', '*args, **kwargs', 'return "http://example.org/bar"')
@simulate('Base_getRequestHeader', '*args, **kwargs', 'return "application/hal+json"')
@simulate('Test_listCatalog', '*args, **kwargs', "return []")
@changeSkin('Hal')
def test_getHateoas_selection_compatibility(self, **kw):
"""Check that listbox line calculation modify the selection
"""
self.portal.foo_module.FooModule_viewFooList.listbox.ListBox_setPropertyList(
field_count_method = '')
selection_tool = self.portal.portal_selections
selection_name = self.portal.foo_module.FooModule_viewFooList.listbox.get_value('selection_name')
selection_tool.setSelectionFor(selection_name, Selection(selection_name))
# Create the listbox selection
fake_request = do_fake_request("GET")
result = self.portal.web_site_module.hateoas.ERP5Document_getHateoas(
REQUEST=fake_request,
mode="search",
local_roles=["Manager"],
query='bar:"foo"',
list_method='Test_listCatalog',
select_list=['title', 'uid'],
selection_domain=json.dumps({'foo_domain': 'a/a1', 'foo_category': 'a/a2'}),
relative_url='foo_module',
form_relative_url='portal_skins/erp5_ui_test/FooModule_viewFooList/listbox',
default_param_json='eyJwb3J0YWxfdHlwZSI6IFsiRm9vIl0sICJpZ25vcmVfdW5rbm93bl9jb2x1bW5zIjogdHJ1ZX0=',
sort_on=json.dumps(["title","descending"])
)
self.assertEquals(fake_request.RESPONSE.status, 200)
self.assertEquals(fake_request.RESPONSE.getHeader('Content-Type'),
"application/hal+json"
)
selection = selection_tool.getSelectionFor(selection_name)
self.assertEquals(selection.method_path, '/%s/foo_module/Test_listCatalog' % self.portal.getId())
self.assertEquals(
selection.getParams(), {
'local_roles': ['Manager'],
'full_text': 'bar:"foo"',
'ignore_unknown_columns': True,
'portal_type': ['Foo'],
'limit': 1000
})
self.assertEquals(selection.getSortOrder(), [('title', 'DESC')])
self.assertEquals(selection.columns, [('title', 'Title')])
self.assertEquals(selection.getDomainPath(), ['foo_domain', 'foo_category'])
self.assertEquals(selection.getDomainList(), ['foo_domain/a', 'foo_domain/a/a1', 'foo_category/a', 'foo_category/a/a2'])
self.assertEquals(selection.flat_list_mode, 0)
self.assertEquals(selection.domain_tree_mode, 1)
self.assertEquals(selection.report_tree_mode, 0)
self.assertTrue(isinstance(selection.domain, DomainSelection))
self.assertEquals(selection.domain.domain_dict,
{'foo_category': ('portal_categories', 'foo_category/a/a2'),
'foo_domain': ('portal_domains', 'foo_domain/a/a1')})
class TestERP5Person_getHateoas_mode_search(ERP5HALJSONStyleSkinsMixin): class TestERP5Person_getHateoas_mode_search(ERP5HALJSONStyleSkinsMixin):
"""Test HAL_JSON operations on cataloged Persons and other allowed content types of Person Module.""" """Test HAL_JSON operations on cataloged Persons and other allowed content types of Person Module."""
......
...@@ -941,6 +941,29 @@ class SelectionTool( BaseTool, SimpleItem ): ...@@ -941,6 +941,29 @@ class SelectionTool( BaseTool, SimpleItem ):
selection = self.getSelectionFor(selection_name, REQUEST) selection = self.getSelectionFor(selection_name, REQUEST)
selection.edit(domain_path=domain_root, domain_list=()) selection.edit(domain_path=domain_root, domain_list=())
security.declareProtected(ERP5Permissions.View, 'setDomainDictFromParam')
def setDomainDictFromParam(self, selection_name, domain_dict):
domain_list = []
domain_path = []
for key, value in domain_dict.items():
domain_path.append(key)
splitted_domain_list = value[1].split('/')[1:]
for i in range(len(splitted_domain_list)):
domain_list.append('%s/%s' % (key, '/'.join(splitted_domain_list[:i + 1])))
if len(domain_path) == 1:
domain_path = domain_path[0]
selection = self.getSelectionFor(selection_name)
selection.edit(
domain_list=domain_list,
domain_path=domain_path,
domain=DomainSelection(domain_dict=domain_dict),
flat_list_mode=0,
domain_tree_mode=1,
report_tree_mode=0,
)
security.declareProtected(ERP5Permissions.View, 'unfoldDomain') security.declareProtected(ERP5Permissions.View, 'unfoldDomain')
def unfoldDomain(self, REQUEST, form_id=None, query_string=None): def unfoldDomain(self, REQUEST, form_id=None, query_string=None):
""" """
......
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