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
from Products.ERP5Type.Utils import UpperCase
from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery
from collections import OrderedDict
from Products.ERP5Form.Selection import Selection
MARKER = []
COUNT_LIMIT = 1000
......@@ -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
# the form_id in query string and hidden fields
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
renderHiddenField(response_dict, 'dialog_id', form.id)
# some dialog actions use custom cancel_url
......@@ -1121,6 +1132,7 @@ def renderFormDefinition(form, response_dict):
if form.pt == "form_dialog":
# every form dialog has its dialog_id and meta (control) attributes in extra_param_json
group_list[-1][1].extend([
('selection_name', {'meta_type': 'StringField'}),
('dialog_id', {'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,
byteify(json.loads(selection_domain)))
category_tool = portal.portal_categories
domain_tool = portal.portal_domains
if is_rendering_listbox:
new_selection_dict = {}
for domain_root_id in selection_domain_dict:
domain_root = category_tool.restrictedTraverse(domain_root_id, None)
selection_path = selection_domain_dict[domain_root_id]
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]))
else:
selection_root = 'portal_categories'
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
if sort_on is not None:
......@@ -1700,6 +1723,41 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
# by fetching more documents than requested
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
# instead of being nice and specify them as their input parameters.
#
......
......@@ -16,6 +16,9 @@ import json
import re
import urllib
from Products.ERP5Form.Selection import Selection, DomainSelection
def changeSkin(skin_name):
"""Change skin for following commands and attribute resolution.
......@@ -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(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):
"""Test HAL_JSON operations on cataloged Persons and other allowed content types of Person Module."""
......
......@@ -941,6 +941,29 @@ class SelectionTool( BaseTool, SimpleItem ):
selection = self.getSelectionFor(selection_name, REQUEST)
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')
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