Commit 4db520c1 authored by Tomáš Peterka's avatar Tomáš Peterka

[hal_json] Merge Listbox URL Columns properly from semantical point of view

parent 2fdd5a01
...@@ -573,7 +573,7 @@ def getFieldDefault(form, field, key, value=None): ...@@ -573,7 +573,7 @@ def getFieldDefault(form, field, key, value=None):
return value return value
def renderField(traversed_document, field, form, value=None, meta_type=None, key=None, key_prefix=None, selection_params=None, request_field=True, extra_param_json=None): def renderField(traversed_document, field, form, value=None, meta_type=None, key=None, key_prefix=None, selection_params=None, request_field=True):
"""Extract important field's attributes into `result` dictionary.""" """Extract important field's attributes into `result` dictionary."""
if selection_params is None: if selection_params is None:
selection_params = {} selection_params = {}
...@@ -851,10 +851,6 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key ...@@ -851,10 +851,6 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
# listbox's default parameters # listbox's default parameters
default_params.update(selection_params) default_params.update(selection_params)
if extra_param_json is not None:
default_params.update(ensureDeserialized(byteify(
json.loads(urlsafe_b64decode(extra_param_json)))))
# ListBoxes in report view has portal_type defined already in default_params # ListBoxes in report view has portal_type defined already in default_params
# in that case we prefer non_empty version # in that case we prefer non_empty version
list_method_query_dict = default_params.copy() list_method_query_dict = default_params.copy()
...@@ -1132,12 +1128,12 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti ...@@ -1132,12 +1128,12 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti
if not field.get_value("enabled"): if not field.get_value("enabled"):
continue continue
try: try:
response_dict[field.id] = renderField(traversed_document, field, form, key_prefix=key_prefix, selection_params=selection_params, extra_param_json=extra_param_json) response_dict[field.id] = renderField(traversed_document, field, form, key_prefix=key_prefix, selection_params=selection_params)
if field_errors.has_key(field.id): if field_errors.has_key(field.id):
response_dict[field.id]["error_text"] = field_errors[field.id].error_text response_dict[field.id]["error_text"] = field_errors[field.id].error_text
except AttributeError: except AttributeError as error:
# Do not crash if field configuration is wrong. # Do not crash if field configuration is wrong.
pass log("Field {} rendering failed because of {!s}".format(field.id, error), level=800)
# Form Edit handler uses form_id to recover the submitted form and to control its # Form Edit handler uses form_id to recover the submitted form and to control its
# properties like editability # properties like editability
...@@ -1516,7 +1512,12 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -1516,7 +1512,12 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
return traversed_document.Base_redirect(keep_items={ return traversed_document.Base_redirect(keep_items={
'portal_status_message': status_message}) 'portal_status_message': status_message})
renderForm(traversed_document, view_instance, embedded_dict, extra_param_json=extra_param_json) # Sometimes callables (form dialog's method, listbox's list method...) do not touch
# REQUEST but expect all (formerly) URL query parameters to appear in their **kw
# thus we send extra_param_json (=rjs way of passing parameters to REQUEST) as
# selection_params so they get into callable's **kw.
renderForm(traversed_document, view_instance, embedded_dict,
selection_params=extra_param_json, extra_param_json=extra_param_json)
result_dict['_embedded'] = { result_dict['_embedded'] = {
'_view': embedded_dict '_view': embedded_dict
...@@ -1956,7 +1957,9 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -1956,7 +1957,9 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
# if there is no tales expr (or is empty) we extract the value from search result # if there is no tales expr (or is empty) we extract the value from search result
default_field_value = getAttrFromAnything(search_result, select, property_getter, {}) default_field_value = getAttrFromAnything(search_result, select, property_getter, {})
contents_item[select] = renderField( # If the contents_item has field rendering in it, better is to add an
# extra layer of abstraction to not get conflicts
contents_item[select]['field_gadget_param'] = renderField(
traversed_document, traversed_document,
editable_field_dict[select], editable_field_dict[select],
listbox_form, listbox_form,
...@@ -1969,103 +1972,64 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -1969,103 +1972,64 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
# a key name to Python Script with variable number of input parameters. # a key name to Python Script with variable number of input parameters.
contents_item[select] = getAttrFromAnything(search_result, select, property_getter, {'brain': search_result}) contents_item[select] = getAttrFromAnything(search_result, select, property_getter, {'brain': search_result})
# If the contents_item has field rendering in it, better is to add an
# extra layer of abstraction to not get conflicts
if isinstance(contents_item[select], dict):
contents_item[select] = {
'field_gadget_param': contents_item[select],
}
# By default, we won't be generating views in the URL # By default, we won't be generating views in the URL
url_parameter_dict = {} url_parameter_dict = {}
if select in url_column_dict: if url_column_dict.get(select, None):
# Check if we get URL parameters using listbox field `url_columns` # Check if we get URL parameters using listbox field `url_columns`
url_column_method = getattr(search_result, url_column_dict[select], None) url_column_method = getattr(search_result, url_column_dict[select], None)
# If there is empty url_column_method, do nothing and continue. This # Result of `url_column_method` must be a dictionary in the format
# will create no URL in these cases # {'command': <command_name, ex: 'raw', 'push_history'>,
if url_column_method is None: # 'options': {'url': <Absolute URL>, 'jio_key': <Relative URL of object>, 'view': <id of the view>}}
continue url_parameter_dict = url_column_method(url_dict=True,
url_parameter_dict = url_column_method(
url_dict=True,
brain=search_result, brain=search_result,
selection=catalog_kw['selection'], selection=catalog_kw['selection'],
selection_name=catalog_kw['selection_name'], selection_name=catalog_kw['selection_name'],
column_id=select) column_id=select)
# Since, now we are using url_columns for both XHTML UI and renderJS UI,
# its normal to get string as a result of the `url_column_method`
# function call. In that cases, we will do nothing. Take note, the
# result of `url_column_method` function call which is usable here should
# be dictionary in the format :-
# {
# 'command': <command_name, ex: 'raw', 'push_history'>,
# 'options': {
# 'url': <Absolute URL>,
# 'jio_key': <Relative URL of object>,
# 'view': <id of the view>,
# }
# }
if isinstance(url_parameter_dict, str):
continue
elif getattr(search_result, 'getListItemUrlDict', None) is not None: elif getattr(search_result, 'getListItemUrlDict', None) is not None:
# Check if we can get URL result from the brain # Check if we can get URL result from the brain
try: try:
url_parameter_dict = search_result.getListItemUrlDict( url_parameter_dict = search_result.getListItemUrlDict(
select, select, result_index, catalog_kw['selection_name']
result_index,
catalog_kw['selection_name']
) )
except (ConflictError, RuntimeError): except (ConflictError, RuntimeError):
raise raise
except: except:
log('could not evaluate the url method getListItemUrlDict with %r' % search_result, log('could not evaluate the url method getListItemUrlDict with %r' % search_result,
level=800) level=800)
continue
else:
# Continue in case there is no url_column_dict or brain to get URL
continue
url_result_dict = { if url_parameter_dict and isinstance(url_parameter_dict, dict):
select: url_parameter_dict # We need to put URL into rendered field so just ensure it is a dict
}
# If contents item don't have `field_gadget_param` in it, then add it
# to default
if not isinstance(contents_item[select], dict): if not isinstance(contents_item[select], dict):
contents_item[select] = { contents_item[select] = {
'default': contents_item[select], 'default': contents_item[select],
} }
contents_item[select].update({'url_value': url_result_dict[select]})
if contents_item[select]['url_value']:
# We should be generating view if there is extra params for view in # We should be generating view if there is extra params for view in
# view_kw. These parameters are required to create url at hateoas side # view_kw. These parameters are required to create url at hateoas side
# using the URL template as necessary # using the URL template as necessary
if 'view_kw' in contents_item[select]['url_value']: if 'view_kw' not in url_parameter_dict:
contents_item[select]['url_value'] = url_parameter_dict
else:
# Get extra parameters either from url_result_dict or from brain # Get extra parameters either from url_result_dict or from brain
extra_url_param_dict = contents_item[select]['url_value']['view_kw'].get('extra_param_json', {}) extra_url_param_dict = url_parameter_dict['view_kw'].get('extra_param_json', {})
url_template_id = 'traverse_generator' url_template_id = 'traverse_generator'
if extra_url_param_dict: if extra_url_param_dict:
url_template_id = 'traverse_generator_action' url_template_id = 'traverse_generator_action'
contents_item[select]['url_value']['options']['view'] =\ contents_item[select]['url_value'] = {
url_template_dict[url_template_id] % { 'command': url_parameter_dict['command'],
'options': {
'jio_key': url_parameter_dict['view_kw']['jio_key'],
'view': url_template_dict[url_template_id] % {
"root_url": site_root.absolute_url(), "root_url": site_root.absolute_url(),
"script_id": script.id, "script_id": script.id,
"relative_url": contents_item[select]['url_value']['view_kw']['jio_key'].replace("/", "%2F"), "relative_url": url_parameter_dict['view_kw']['jio_key'].replace("/", "%2F"),
"view": contents_item[select]['url_value']['view_kw']['view'], "view": url_parameter_dict['view_kw']['view'],
"extra_param_json": urlsafe_b64encode( "extra_param_json": urlsafe_b64encode(
json.dumps(ensureSerializable(extra_url_param_dict))) json.dumps(ensureSerializable(extra_url_param_dict)))
} }
}
# Its better to remove the 'view_kw' from the dictionary as it doesn't }
# serve any purpose further in the result_dict
if 'view_kw' in contents_item[select]['url_value']:
del contents_item[select]['url_value']['view_kw']
# endfor select # endfor select
REQUEST.other.pop('cell', None) REQUEST.other.pop('cell', None)
...@@ -2097,12 +2061,8 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -2097,12 +2061,8 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
if source_field is not None and source_field_meta_type == "ListBox": if source_field is not None and source_field_meta_type == "ListBox":
# Trigger count method if exist # Trigger count method if exist
# XXX No need to count if no pagination # XXX No need to count if no pagination
count_method = source_field.get_value('count_method') or None count_method = source_field.get_value('count_method')
count_method_name = count_method.getMethodName() if count_method is not None else "" if count_method != "" and count_method.getMethodName() != list_method:
# Only try to get count method results in case method name exists, in all
# other cases, just pass.
if count_method_name != "" and count_method_name != list_method:
count_kw = dict(catalog_kw) count_kw = dict(catalog_kw)
# Drop not needed parameters # Drop not needed parameters
count_kw.pop('selection', None) count_kw.pop('selection', None)
...@@ -2110,7 +2070,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -2110,7 +2070,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
count_kw.pop("sort_on", None) count_kw.pop("sort_on", None)
count_kw.pop("limit", None) count_kw.pop("limit", None)
try: try:
count_method = getattr(traversed_document, count_method_name) count_method = getattr(traversed_document, count_method.getMethodName())
count_method_result = count_method(REQUEST=REQUEST, **count_kw) count_method_result = count_method(REQUEST=REQUEST, **count_kw)
result_dict['_embedded']['count'] = ensureSerializable(count_method_result[0][0]) result_dict['_embedded']['count'] = ensureSerializable(count_method_result[0][0])
except AttributeError as error: except AttributeError as error:
...@@ -2119,7 +2079,6 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -2119,7 +2079,6 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
# and just pass. This also ensures we have compatibilty with how old # and just pass. This also ensures we have compatibilty with how old
# UI behave in these cases. # UI behave in these cases.
log('Invalid count method %s' % error, level=800) log('Invalid count method %s' % error, level=800)
pass
contents_stat_list = [] contents_stat_list = []
# in case the search was issued by listbox we can provide results of # in case the search was issued by listbox we can provide results of
......
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