Commit a23e6d78 authored by Noah Brackenbury's avatar Noah Brackenbury

Merge branch 'master' of https://lab.nexedi.com/nexedi/erp5 into business_bot

parents 0900d7fe 09a0443d
......@@ -51,7 +51,8 @@ except FormValidationError as validation_errors:
value = request.get(field_id)
if callable(value):
value(request)
if silent_mode: return context.ERP5Document_getHateoas(form=form, REQUEST=request, mode='form'), 'form'
if silent_mode:
return context.ERP5Document_getHateoas(form=form, REQUEST=request, mode='form'), 'form'
request.RESPONSE.setStatus(400)
return context.ERP5Document_getHateoas(form=form, REQUEST=request, mode='form')
......@@ -92,103 +93,109 @@ def editListBox(listbox_field, listbox):
def editMatrixBox(matrixbox_field, matrixbox):
""" Function called to edit a Matrix box
"""
if matrixbox is not None:
cell_base_id = matrixbox_field.get_value('cell_base_id')
portal_type = matrixbox_field.get_value('cell_portal_type')
getter_method = matrixbox_field.get_value('getter_method')
if getter_method not in (None, ''):
matrix_context = getattr(context,getter_method)()
if matrixbox is None:
return
cell_base_id = matrixbox_field.get_value('cell_base_id')
portal_type = matrixbox_field.get_value('cell_portal_type')
getter_method = matrixbox_field.get_value('getter_method')
if getter_method not in (None, ''):
matrix_context = getattr(context,getter_method)()
else:
matrix_context = context
if matrix_context is None:
return
kd = {}
kd['portal_type'] = portal_type
kd['base_id'] = cell_base_id
gv = {}
if matrixbox_field.has_value('global_attributes'):
hidden_attributes = [x[0] for x in matrixbox_field.get_value('global_attributes')]
for k in hidden_attributes:
gv[k] = getattr(request, k, None)
if matrixbox_field.get_value('update_cell_range'):
as_cell_range_script_id = matrixbox_field.get_value(
'as_cell_range_script_id')
lines = []
columns = []
tabs = []
extra_dimension_list_list = []
if as_cell_range_script_id:
cell_range = getattr(matrix_context,
as_cell_range_script_id)(matrixbox=True, base_id=cell_base_id)
if len(cell_range) == 1:
lines, = cell_range
elif len(cell_range) == 2:
lines, columns = cell_range
elif len(cell_range) == 3:
lines, columns, tabs = cell_range
elif len(cell_range) > 3:
lines = cell_range[0]
columns = cell_range[1]
tabs = cell_range[2]
extra_dimension_list_list = cell_range[3:]
else:
lines = matrixbox_field.get_value('lines')
columns = matrixbox_field.get_value('columns')
tabs = matrixbox_field.get_value('tabs')
column_ids = map(lambda x: x[0], columns)
line_ids = map(lambda x: x[0], lines)
tab_ids = map(lambda x: x[0], tabs)
extra_dimension_category_list_list = [[category for category, label in dimension_list] for dimension_list in extra_dimension_list_list]
# There are 3 cases
# Case 1: we do 1 dimensional matrix
# Case 2: we do 2 dimensional matrix
# Case 3: we do 2 dimensional matrix + tabs
# Case 4: we do 2 dimensional matrix + tabs + extra
cell_range = matrix_context.getCellRange(base_id = cell_base_id)
if (len(column_ids) == 0) or (column_ids[0] is None):
matrixbox_cell_range = [line_ids]
if cell_range != matrixbox_cell_range:
matrix_context.setCellRange(line_ids, base_id=cell_base_id)
elif (len(tab_ids) == 0) or (tab_ids[0] is None):
matrixbox_cell_range = [line_ids, column_ids]
if cell_range != matrixbox_cell_range:
matrix_context.setCellRange(line_ids, column_ids, base_id=cell_base_id)
else:
matrix_context = context
if matrix_context is not None:
kd = {}
kd['portal_type'] = portal_type
kd['base_id'] = cell_base_id
gv = {}
if matrixbox_field.has_value('global_attributes'):
hidden_attributes = [x[0] for x in matrixbox_field.get_value('global_attributes')]
for k in hidden_attributes:
gv[k] = getattr(request, k, None)
if matrixbox_field.get_value('update_cell_range'):
as_cell_range_script_id = matrixbox_field.get_value(
'as_cell_range_script_id')
lines = []
columns = []
tabs = []
extra_dimension_list_list = []
if as_cell_range_script_id:
cell_range = getattr(matrix_context,
as_cell_range_script_id)(matrixbox=True, base_id=cell_base_id)
if len(cell_range) == 1:
lines, = cell_range
elif len(cell_range) == 2:
lines, columns = cell_range
elif len(cell_range) == 3:
lines, columns, tabs = cell_range
elif len(cell_range) > 3:
lines = cell_range[0]
columns = cell_range[1]
tabs = cell_range[2]
extra_dimension_list_list = cell_range[3:]
else:
lines = matrixbox_field.get_value('lines')
columns = matrixbox_field.get_value('columns')
tabs = matrixbox_field.get_value('tabs')
column_ids = map(lambda x: x[0], columns)
line_ids = map(lambda x: x[0], lines)
tab_ids = map(lambda x: x[0], tabs)
extra_dimension_category_list_list = [[category for category, label in dimension_list] for dimension_list in extra_dimension_list_list]
# There are 3 cases
# Case 1: we do 1 dimensional matrix
# Case 2: we do 2 dimensional matrix
# Case 3: we do 2 dimensional matrix + tabs
# Case 4: we do 2 dimensional matrix + tabs + extra
cell_range = matrix_context.getCellRange(base_id = cell_base_id)
if (len(column_ids) == 0) or (column_ids[0] is None):
matrixbox_cell_range = [line_ids]
if cell_range != matrixbox_cell_range:
matrix_context.setCellRange(line_ids, base_id=cell_base_id)
elif (len(tab_ids) == 0) or (tab_ids[0] is None):
matrixbox_cell_range = [line_ids, column_ids]
if cell_range != matrixbox_cell_range:
matrix_context.setCellRange(line_ids, column_ids, base_id=cell_base_id)
else:
matrixbox_cell_range = [line_ids, column_ids, tab_ids]
if extra_dimension_category_list_list:
matrixbox_cell_range = matrixbox_cell_range + extra_dimension_category_list_list
if cell_range != matrixbox_cell_range:
matrix_context.setCellRange(base_id=cell_base_id, *matrixbox_cell_range)
for k,v in matrixbox.items():
# Only update cells which still exist
if matrix_context.hasInRange(*k, **kd):
c = matrix_context.newCell(*k, **kd)
if c is not None:
c.edit(edit_order=edit_order, **gv) # First update globals which include the def. of property_list
if v.has_key('variated_property'):
# For Variated Properties
value = v['variated_property']
del v['variated_property']
if gv.has_key('mapped_value_property_list'):
# Change the property which is defined by the
# first element of mapped_value_property_list
# XXX May require some changes with Sets
key = gv['mapped_value_property_list'][0]
v[key] = value
# Form: '' -> ERP5: None
cleaned_v = v.copy()
for key, value in cleaned_v.items():
if value == '':
cleaned_v[key] = None
c.edit(edit_order=edit_order, **cleaned_v) # and update the cell specific values
else:
return "Could not create cell %s" % str(k)
else:
return "Cell %s does not exist" % str(k)
matrixbox_cell_range = [line_ids, column_ids, tab_ids]
if extra_dimension_category_list_list:
matrixbox_cell_range = matrixbox_cell_range + extra_dimension_category_list_list
if cell_range != matrixbox_cell_range:
matrix_context.setCellRange(base_id=cell_base_id, *matrixbox_cell_range)
for cell_index_tuple, cell_value_dict in matrixbox.items():
# Only update cells which still exist
if not matrix_context.hasInRange(*cell_index_tuple, **kd):
return "Cell %s does not exist" % str(cell_index_tuple)
cell = matrix_context.newCell(*cell_index_tuple, **kd)
if cell is None:
return "Could not create cell %s" % str(cell_index_tuple)
cell.edit(edit_order=edit_order, **gv) # First update globals which include the def. of property_list
if cell_value_dict.has_key('variated_property'):
# For Variated Properties
value = cell_value_dict['variated_property']
del cell_value_dict['variated_property']
if gv.has_key('mapped_value_property_list'):
# Change the property which is defined by the
# first element of mapped_value_property_list
# XXX Kato: What? Why?
# XXX May require some changes with Sets
key = gv['mapped_value_property_list'][0]
cell_value_dict[key] = value
# Form: '' -> ERP5: None
cleaned_v = cell_value_dict.copy()
for key, value in cleaned_v.items():
if value == '':
cleaned_v[key] = None
cell.edit(edit_order=edit_order, **cleaned_v) # and update the cell specific values
edit_kwargs = {} # keyword arguments for `edit` function on context
......@@ -220,7 +227,8 @@ try:
editMatrixBox(field, request.get(field.id))
# Return parsed values
if silent_mode: return (edit_kwargs, encapsulated_editor_list), 'edit'
if silent_mode:
return (edit_kwargs, encapsulated_editor_list), 'edit'
# Maybe we should build a list of objects we need
# Update basic attributes
......
......@@ -94,7 +94,7 @@ def getFieldDefault(traversed_document, field, key, value=None):
return result
def renderField(traversed_document, field, form_relative_url, value=None, meta_type=None, key=None, key_prefix=None, selection_params=None):
def renderField(traversed_document, field, form, value=None, meta_type=None, key=None, key_prefix=None, selection_params=None):
"""Extract important field's attributes into `result` dictionary."""
if meta_type is None:
......@@ -120,7 +120,7 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t
})
if meta_type == "ProxyField":
return renderField(traversed_document, field, form_relative_url, value,
return renderField(traversed_document, field, form, value,
meta_type=field.getRecursiveTemplateField().meta_type,
key=key, key_prefix=key_prefix,
selection_params=selection_params)
......@@ -151,7 +151,10 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t
"LinesField", "ImageField", "FileField", "IntegerField",
"PasswordField", "EditorField"):
if meta_type == "FloatField":
result["precision"] = field.get_value("precision")
result.update({
"precision": field.get_value("precision"),
"input_style": field.get_value("input_style"),
})
if meta_type == "ImageField":
options = {
'display': field.get_value('image_display'),
......@@ -231,7 +234,7 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t
# find listbox field
listbox_form_field = filter(lambda f: f.getId() == listbox_field_name, form.get_fields())[0]
# get original definition
subfield = renderField(context, listbox_form_field, getFormRelativeUrl(form))
subfield = renderField(context, listbox_form_field, form)
# overwrite, like Base_getRelatedObjectParameter does
if subfield["portal_type"] == []:
subfield["portal_type"] = field.get_value('portal_type')
......@@ -331,7 +334,7 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t
"root_url": site_root.absolute_url(),
"script_id": script.id,
"relative_url": traversed_document.getRelativeUrl().replace("/", "%2F"),
"form_relative_url": "%s/%s" % (form_relative_url, field.id),
"form_relative_url": "%s/%s" % (getFormRelativeUrl(form), field.id),
"list_method": list_method_name,
"default_param_json": urlsafe_b64encode(json.dumps(list_method_query_dict))
}
......@@ -416,13 +419,24 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t
}
return result
if meta_type == "MatrixBox":
# data are generated by python code for MatrixBox.py
# template_fields are better rendered here because they can be part of "hidden"
# group which is not rendered in form by default. Including
# those fields directly here saves a lot of headache later
template_field_names = ["{}_{}".format(field.id, editable_attribute)
for editable_attribute, _ in field.get_value('editable_attributes')]
result.update({
'data': field.render(key=key, value=value, REQUEST=REQUEST, render_format='list'),
'template_field_dict': {template_field: renderField(traversed_document, getattr(form, template_field), form)
for template_field in template_field_names
if template_field in form},
})
return result
# All other fields are not implemented and we'll return only basic info about them
return {
"type": meta_type,
"_debug": "Unsupported field type",
"title": Base_translateString(field.get_value("title")),
"key": key,
}
result["_debug"] = "Unknown field type " + meta_type
return result
def renderForm(traversed_document, form, response_dict, key_prefix=None, selection_params=None):
......@@ -475,30 +489,22 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti
'name': form.id
}
# Go through all groups ("left", "bottom", "hidden" etc.) and add fields from
# them into form.
for group in form.Form_getGroupTitleAndId():
if group['gid'].find('hidden') < 0:
# field_list = []
for field in form.get_fields_in_group(group['goid']):
# field_list.append((field.id, renderRawField(field)))
if field.get_value("enabled"):
try:
response_dict[field.id] = renderField(traversed_document, field, form_relative_url, key_prefix=key_prefix, selection_params=selection_params)
if field_errors.has_key(field.id):
response_dict[field.id]["error_text"] = field_errors[field.id].error_text
except AttributeError:
# Do not crash if field configuration is wrong.
pass
# for field_group in field.form.get_groups():
# traversed_document.log("Field group: " + field_group)
# traversed_document.log(field_group)
# for field_property in field.form.get_fields_in_group(field_group):
# # traversed_document.log("Field attribute: " + field_property.id)
# # field.get_value(field_property.id)
# traversed_document.log(field_property)
# group_list.append((group['gid'], field_list))
# Skipping hidden group could be problematic but see MatrixBox Field above
if 'hidden' in group['gid']:
continue
for field in form.get_fields_in_group(group['goid']):
if not field.get_value("enabled"):
continue
try:
response_dict[field.id] = renderField(traversed_document, field, form, key_prefix=key_prefix, selection_params=selection_params)
if field_errors.has_key(field.id):
response_dict[field.id]["error_text"] = field_errors[field.id].error_text
except AttributeError:
# Do not crash if field configuration is wrong.
pass
response_dict["form_id"] = {
"type": "StringField",
......@@ -1079,7 +1085,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
else:
tmp_value = getProtectedProperty(document, select)
property_value = renderField(traversed_document, editable_field_dict[select], form_relative_url,
property_value = renderField(traversed_document, editable_field_dict[select], form,
tmp_value,
key='field_%s_%s' % (editable_field_dict[select].id,
document_uid))
......
<?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_view</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</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>view_contentlist</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>ListBox</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>string:${object_url}/Folder_viewContentList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?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_view</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</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>view_dynamic_matrixbox</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>Dynamic MatrixBox</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>string:${object_url}/FooLine_viewDynamicMatrixBox</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?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_view</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</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>view_matrixbox</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>MatrixBox</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>string:${object_url}/FooLine_viewMatrixBox</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -154,6 +154,10 @@
<key> <string>input_style</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>precision</string> </key>
<value> <string></string> </value>
......@@ -211,7 +215,9 @@
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>extra</string> </key>
......@@ -225,9 +231,13 @@
<key> <string>input_style</string> </key>
<value> <string>-1 234.5</string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string>text</string> </value>
</item>
<item>
<key> <string>precision</string> </key>
<value> <string></string> </value>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>required</string> </key>
......@@ -249,10 +259,7 @@
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
<tuple/>
</tuple>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
......@@ -263,4 +270,17 @@
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Method" module="Products.Formulator.MethodField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>method_name</string> </key>
<value> <string>Validator_positiveNumber</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -211,7 +211,9 @@
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>extra</string> </key>
......@@ -225,9 +227,13 @@
<key> <string>input_style</string> </key>
<value> <string>-1 234.5</string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string>text</string> </value>
</item>
<item>
<key> <string>precision</string> </key>
<value> <string></string> </value>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>required</string> </key>
......@@ -263,4 +269,17 @@
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Method" module="Products.Formulator.MethodField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>method_name</string> </key>
<value> <string>Validator_positiveNumber</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
if value:
try:
return float(value) > 0
except ValueError:
# conversion error - not a number
return True
return True
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Python Script" module="erp5.portal_type"/>
</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>value, REQUEST</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Validator_positiveNumber</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Python Script</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -5,6 +5,9 @@ Bar | view
Bar | view_datetime_field
Foo Bar Module | view
Foo Line | view
Foo Line | view_contentlist
Foo Line | view_dynamic_matrixbox
Foo Line | view_matrixbox
Foo Module | do_nothing_report_jio
Foo Module | list
Foo Module | list_ui
......
......@@ -108,7 +108,7 @@
<value> <string encoding="cdata"><![CDATA[
CACHE MANIFEST\n
# generated on Mon, 19 Jun 2017 12:00:00 GMT+0200\n
# generated on Mon, 27 Aug 2017 16:00:00 GMT+0200\n
# XXX + fonts\n
# images/ajax-loader.gif\n
CACHE:\n
......@@ -136,6 +136,8 @@ gadget_erp5_field_file.html\n
gadget_erp5_field_file.js\n
gadget_erp5_field_float.html\n
gadget_erp5_field_float.js\n
gadget_erp5_field_formbox.html\n
gadget_erp5_field_formbox.js\n
gadget_erp5_field_gadget.html\n
gadget_erp5_field_gadget.js\n
gadget_erp5_field_image.html\n
......@@ -144,8 +146,12 @@ gadget_erp5_field_integer.html\n
gadget_erp5_field_integer.js\n
gadget_erp5_field_list.html\n
gadget_erp5_field_list.js\n
gadget_erp5_field_lines.html\n
gadget_erp5_field_lines.js\n
gadget_erp5_field_listbox.html\n
gadget_erp5_field_listbox.js\n
gadget_erp5_field_matrixbox.html\n
gadget_erp5_field_matrixbox.js\n
gadget_erp5_field_multicheckbox.html\n
gadget_erp5_field_multicheckbox.js\n
gadget_erp5_field_multilist.html\n
......@@ -201,6 +207,8 @@ gadget_erp5_page_worklist.js\n
gadget_erp5_panel.html\n
gadget_erp5_panel.js\n
gadget_erp5_panel.png?format=png\n
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_list.html\n
......@@ -372,7 +380,7 @@ NETWORK:\n
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>960.9595.29464.53282</string> </value>
<value> <string>961.46731.40234.57975</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -390,7 +398,7 @@ NETWORK:\n
</tuple>
<state>
<tuple>
<float>1497860105.36</float>
<float>1503932860.56</float>
<string>UTC</string>
</tuple>
</state>
......
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>ERP5 MatrixBox Field</title>
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<script src="gadget_erp5_field_matrixbox.js" type="text/javascript"></script>
<script id="table-template" type="text/x-handlebars-template">
<thead>
<tr>
<th>{{table_title}}</th>
{{#each header}}
<th>{{this}}</th>
{{/each}}
</tr>
</thead>
</script>
</head>
<body>
<div class="document_table"></div>
</body>
</html>
\ No newline at end of file
/*global window, rJS */
/*global window, rJS, Math */
/*jslint indent: 2, maxerr: 3 */
(function (window, rJS) {
(function (window, rJS, Math) {
"use strict";
rJS(window)
......@@ -13,6 +13,7 @@
.declareMethod('render', function (options) {
var field_json = options.field_json || {},
value = field_json.value || field_json.default || "",
percents = (field_json.input_style || "").endsWith("%"),
state_dict = {
editable: field_json.editable,
required: field_json.required,
......@@ -21,14 +22,34 @@
precision: field_json.precision,
hidden: field_json.hidden
};
// if value is 0.0 we assign empty instead - so we fix it here
if (field_json.value !== undefined && field_json.value !== '') {
value = field_json.value;
} else if (field_json.default !== undefined && field_json.default !== '') {
value = field_json.default;
}
value = window.parseFloat(value); // at this step we finished joggling with value
if (field_json.precision) {
state_dict.step = 1 / Math.pow(10, field_json.precision);
value = parseFloat(value || "0").toFixed(field_json.precision);
state_dict.step = Math.pow(10, -field_json.precision);
value = value.toFixed(field_json.precision);
} else {
state_dict.step = 0.00000001;
// XXX did previous default step value make sense? 0.00000001
state_dict.step = 1.0;
}
if (percents) {
// ERP5 always devides the value by 10 if it is set to pe percentages
// thus we have to mitigate that in javascript here
value *= 100.0;
state_dict.append = "%";
}
state_dict.value = value;
state_dict.text_content = value;
if (window.isNaN(value)) {
state_dict.text_content = "";
} else {
state_dict.text_content = value.toString();
}
return this.changeState(state_dict);
})
......@@ -82,4 +103,4 @@
return true;
});
}(window, rJS));
\ No newline at end of file
}(window, rJS, Math));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>956.15742.1027.50705</string> </value>
<value> <string>961.41941.4473.55415</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1482844714.9</float>
<float>1503645555.71</float>
<string>UTC</string>
</tuple>
</state>
......
/*jslint nomen: true, indent: 2, maxerr: 3 */
/*global window, document, rJS, RSVP*/
/** Form is one of a complicated gadget!
*
* Editability - the form overrides editability of its fields. Editability is
* hard-coded changed either in Page Templates or soft-coded
* changed in FormBox gadget which renders form as a subgadget
**/
(function (window, document, rJS, RSVP) {
"use strict";
/** Form is one of a complicated gadget!
*
* Editability - the form overrides editability of its fields. Editability is
* hard-coded changed either in Page Templates or soft-coded
* changed in FormBox gadget which renders form as a subgadget
**/
function getFieldTypeGadgetUrl(type) {
var field_url = 'gadget_erp5_field_readonly.html';
if (type === 'ListField') {
field_url = 'gadget_erp5_field_list.html';
} else if ((type === 'ParallelListField') ||
(type === 'MultiListField')) {
field_url = 'gadget_erp5_field_multilist.html';
} else if (type === 'CheckBoxField') {
field_url = 'gadget_erp5_field_checkbox.html';
} else if (type === 'MultiCheckBoxField') {
field_url = 'gadget_erp5_field_multicheckbox.html';
} else if (type === 'StringField') {
field_url = 'gadget_erp5_field_string.html';
} else if (type === 'PasswordField') {
field_url = 'gadget_erp5_field_password.html';
} else if (type === 'RelationStringField') {
field_url = 'gadget_erp5_field_relationstring.html';
} else if (type === 'MultiRelationStringField') {
field_url = 'gadget_erp5_field_multirelationstring.html';
} else if (type === 'TextAreaField') {
field_url = 'gadget_erp5_field_textarea.html';
} else if (type === 'DateTimeField') {
field_url = 'gadget_erp5_field_datetime.html';
} else if (type === 'FloatField') {
field_url = 'gadget_erp5_field_float.html';
} else if (type === 'FileField') {
field_url = 'gadget_erp5_field_file.html';
} else if (type === 'IntegerField') {
field_url = 'gadget_erp5_field_integer.html';
} else if (type === 'ListBox') {
field_url = 'gadget_erp5_field_listbox.html';
} else if (type === 'EditorField') {
field_url = 'gadget_erp5_field_editor.html';
// field_url = 'gadget_codemirror.html';
// sandbox = 'iframe';
} else if (type === 'GadgetField') {
field_url = 'gadget_erp5_field_gadget.html';
} else if (type === 'RadioField') {
field_url = 'gadget_erp5_field_radio.html';
} else if (type === 'ImageField') {
field_url = 'gadget_erp5_field_image.html';
} else if (type === 'EmailField') {
field_url = 'gadget_erp5_field_email.html';
} else if (type === 'FormBox') {
field_url = 'gadget_erp5_field_formbox.html';
}
return field_url;
}
/**
* Physically append rendered field to DOM.
*
......@@ -79,7 +30,7 @@
suboptions = {
hide_enabled: form_definition.hide_enabled, // listbox specific
extended_search: form_definition.extended_search, // searchfield specific
field_url: getFieldTypeGadgetUrl(rendered_document[field_name].type),
field_type: rendered_document[field_name].type,
label: ((group_name !== "bottom") && (rendered_document[field_name].title.length > 0)), // no label for bottom group and field without title
field_json: rendered_document[field_name] // pass
};
......@@ -111,9 +62,11 @@
// XXX Hardcoded to get one listbox gadget
//pt form list gadget will get this listbox's info
//then pass to search field gadget
if (suboptions.field_url === "gadget_erp5_field_listbox.html") {
if (suboptions.field_type === 'ListBox') {
form_gadget.props.listbox_gadget = label_gadget;
}
// gadget_list hold references to all created gadgets
form_gadget.props.gadget_list.push(label_gadget);
}
return label_gadget.render(suboptions);
......@@ -169,9 +122,6 @@
editable: undefined
})
.allowPublicAcquisition("getFieldTypeGadgetUrl", function (param_list) {
return getFieldTypeGadgetUrl(param_list[0]);
})
.allowPublicAcquisition("getFormContent", function (param_list) {
return this.getContent(param_list[0]);
})
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>961.18982.46006.23483</string> </value>
<value> <string>961.37896.39526.64290</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1502268077.5</float>
<float>1503478842.83</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -12,7 +12,7 @@
</head>
<body>
<div class="ui-field-contain">
<label> <span></span></label>
<label></label>
<div></div>
</div>
</body>
......
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>954.24197.36337.41506</string> </value>
<value> <string>961.42413.53044.57736</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1475585351.18</float>
<float>1503674612.29</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -16,20 +16,71 @@
var SCOPE = 'field';
function getFieldTypeGadgetUrl(field_type) {
var field_url = 'gadget_erp5_field_readonly.html';
if (field_type === 'ListField') {
field_url = 'gadget_erp5_field_list.html';
} else if ((field_type === 'ParallelListField') ||
(field_type === 'MultiListField')) {
field_url = 'gadget_erp5_field_multilist.html';
} else if (field_type === 'CheckBoxField') {
field_url = 'gadget_erp5_field_checkbox.html';
} else if (field_type === 'MultiCheckBoxField') {
field_url = 'gadget_erp5_field_multicheckbox.html';
} else if (field_type === 'StringField') {
field_url = 'gadget_erp5_field_string.html';
} else if (field_type === 'LinesField') {
field_url = 'gadget_erp5_field_lines.html';
} else if (field_type === 'PasswordField') {
field_url = 'gadget_erp5_field_password.html';
} else if (field_type === 'RelationStringField') {
field_url = 'gadget_erp5_field_relationstring.html';
} else if (field_type === 'MultiRelationStringField') {
field_url = 'gadget_erp5_field_multirelationstring.html';
} else if (field_type === 'TextAreaField') {
field_url = 'gadget_erp5_field_textarea.html';
} else if (field_type === 'DateTimeField') {
field_url = 'gadget_erp5_field_datetime.html';
} else if (field_type === 'FloatField') {
field_url = 'gadget_erp5_field_float.html';
} else if (field_type === 'FileField') {
field_url = 'gadget_erp5_field_file.html';
} else if (field_type === 'IntegerField') {
field_url = 'gadget_erp5_field_integer.html';
} else if (field_type === 'ListBox') {
field_url = 'gadget_erp5_field_listbox.html';
} else if (field_type === 'EditorField') {
field_url = 'gadget_erp5_field_editor.html';
// field_url = 'gadget_codemirror.html';
// sandbox = 'iframe';
} else if (field_type === 'GadgetField') {
field_url = 'gadget_erp5_field_gadget.html';
} else if (field_type === 'RadioField') {
field_url = 'gadget_erp5_field_radio.html';
} else if (field_type === 'ImageField') {
field_url = 'gadget_erp5_field_image.html';
} else if (field_type === 'EmailField') {
field_url = 'gadget_erp5_field_email.html';
} else if (field_type === 'FormBox') {
field_url = 'gadget_erp5_field_formbox.html';
} else if (field_type === 'MatrixBox') {
field_url = 'gadget_erp5_field_matrixbox.html';
}
return field_url;
}
rJS(window)
.setState({
label_text: '',
error_text: '',
label: true,
label: true, // the label element is already present in the HTML template
css_class: ''
})
.ready(function () {
return this.changeState({
label_element: this.element.querySelector('label'),
label_text_element: this.element.querySelector('label').firstChild,
error_element: this.element.querySelector('span'),
container_element: this.element.querySelector('div')
container_element: this.element.querySelector('div'), // matches the closest div
label_element: this.element.querySelector('label')
});
})
......@@ -37,13 +88,18 @@
var state_dict = {
label_text: options.field_json.title || '',
label: options.label,
field_url: options.field_url,
field_url: getFieldTypeGadgetUrl(options.field_type),
error_text: options.field_json.error_text || '',
options: options,
scope: options.field_json.key,
hidden: options.field_json.hidden,
css_class: options.field_json.css_class
};
// RenderJS would overwrite default value with empty variables :-(
// So we have to mitigate this behaviour
if (state_dict.label === undefined) {
state_dict.label = true;
}
return this.changeState(state_dict);
})
......@@ -58,7 +114,7 @@
}
if (modification_dict.hasOwnProperty('label_text')) {
this.state.label_text_element.textContent = this.state.label_text;
this.state.label_element.textContent = this.state.label_text;
}
this.state.label_element.setAttribute('for', gadget.state.scope);
......@@ -67,11 +123,16 @@
}
if (modification_dict.hasOwnProperty('error_text')) {
this.state.error_element.textContent = "";
// first remove old errors
span = this.state.container_element.querySelector('span');
if (span) {
this.state.container_element.removeChild(span);
}
// display new error if present
if (this.state.error_text) {
span = document.createElement('span');
span.textContent = this.state.error_text;
this.state.error_element.appendChild(span);
this.state.container_element.appendChild(span);
}
}
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>961.17833.11141.14523</string> </value>
<value> <string>961.46539.43459.6519</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1502198959.61</float>
<float>1503932157.58</float>
<string>UTC</string>
</tuple>
</state>
......
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>ERP5 Linesfield</title>
<!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_erp5_field_lines.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
\ No newline at end of file
/*global window, rJS */
/*jslint indent: 2, maxerr: 3 */
(function (window, rJS) {
"use strict";
function listToNewlines(list) {
if (list.constructor === Array) {return list.join("\n"); }
return list;
}
function listToBR(list) {
if (list.constructor === Array) {return list.join("<br/>\n"); }
return list;
}
rJS(window)
.declareMethod('render', function (options) {
return this.changeState(options.field_json);
})
.onStateChange(function (modification_dict) {
var gadget = this,
url,
value;
if (modification_dict.hasOwnProperty('editable')) {
if (gadget.state.editable) {
url = 'gadget_html5_textarea.html';
value = listToNewlines(gadget.state.value || gadget.state.default || []);
} else {
url = 'gadget_html5_element.html';
value = listToBR(gadget.state.value || gadget.state.default || []);
}
return this.declareGadget(url, {scope: 'sub'})
.push(function (sub_gadget) {
// Clear first to DOM, append after to reduce flickering/manip
while (gadget.element.firstChild) {
gadget.element.removeChild(gadget.element.firstChild);
}
gadget.element.appendChild(sub_gadget.element);
// Use full-blown render when the widget is new
return sub_gadget.render({
value: value,
name: gadget.state.key,
editable: gadget.state.editable,
required: gadget.state.required,
title: gadget.state.title,
hidden: gadget.state.hidden
});
});
}
return gadget.getDeclaredGadget('sub')
.push(function (input) {
if (modification_dict.hasOwnProperty("value")) {
if (gadget.state.editable) {
modification_dict.value = listToNewlines(modification_dict.value);
} else {
modification_dict.value = listToBR(modification_dict.value);
}
}
// when we only receive changes we can simply pass (minimaly modified) modification dictionary
input.render(modification_dict);
});
})
.declareMethod('getContent', function () {
var gadget = this;
return gadget.getDeclaredGadget('sub')
.push(function (sub_gadget) {
return sub_gadget.getContent();
});
})
.declareMethod('checkValidity', function () {
if (this.state.editable) {
return this.getDeclaredGadget('sub')
.push(function (gadget) {
return gadget.checkValidity();
});
}
return true;
});
}(window, rJS));
\ No newline at end of file
......@@ -50,13 +50,13 @@
gadget.props.cell_gadget_list = [];
function renderSubCell(element, sub_field_json) {
sub_field_json.editable = sub_field_json.editable && gadget.state.editable; // XXX
return gadget.getFieldTypeGadgetUrl(sub_field_json.type)
.push(function (gadget_url) {
return gadget.declareGadget(gadget_url, {element: element});
})
return gadget.declareGadget('gadget_erp5_label_field.html', {element: element, scope: sub_field_json.key})
.push(function (cell_gadget) {
gadget.props.cell_gadget_list.push(cell_gadget);
return cell_gadget.render({field_json: sub_field_json});
return cell_gadget.render({
field_type: sub_field_json.type,
field_json: sub_field_json,
label: false});
});
}
for (i = 0; i < element_list.length; i += 1) {
......@@ -144,7 +144,6 @@
.declareAcquiredMethod("translateHtml", "translateHtml")
.declareAcquiredMethod("getUrlFor", "getUrlFor")
.declareAcquiredMethod("getUrlParameter", "getUrlParameter")
.declareAcquiredMethod("getFieldTypeGadgetUrl", "getFieldTypeGadgetUrl")
.declareAcquiredMethod("renderEditorPanel", "renderEditorPanel")
.declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("translate", "translate")
......
......@@ -236,7 +236,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>960.57664.50157.3293</string> </value>
<value> <string>961.37896.32571.61832</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -254,7 +254,7 @@
</tuple>
<state>
<tuple>
<float>1500656708.46</float>
<float>1503406544.43</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -932,7 +932,6 @@ div[data-gadget-scope='header'] .ui-header ul {
}
}
*/
/* form validation (assuming label>span is used) */
}
.gadget-content div[data-gadget-scope='m'] {
animation: fadein 0.2s ease-out;
......@@ -1069,26 +1068,26 @@ div[data-gadget-scope='header'] .ui-header ul {
flex: 7;
}
}
.gadget-content form label {
.gadget-content form .ui-field-contain {
position: relative;
}
.gadget-content form label span span {
.gadget-content form .ui-field-contain > span {
animation: fadein 0.2s ease-out;
}
@media not screen and (max-width: 85em), only screen and (min-width: 45em) and (max-width: 85em) {
.gadget-content form label span span {
.gadget-content form .ui-field-contain > span {
background-color: #FF6600;
color: #f8fff3;
left: 110%;
left: 25%;
position: absolute;
bottom: 130%;
bottom: 110%;
white-space: pre;
padding: 6pt;
border-radius: 0.325em;
width: auto;
z-index: 1001;
}
.gadget-content form label span span:before {
.gadget-content form .ui-field-contain > span:before {
position: absolute;
top: 100%;
left: 2em;
......@@ -1100,12 +1099,26 @@ div[data-gadget-scope='header'] .ui-header ul {
}
}
@media not screen and (min-width: 45em) {
.gadget-content form label span span {
.gadget-content form .ui-field-contain > span {
margin-left: 6pt;
color: #FF6600;
}
}
/**********************************************
* Gadget: HTML5 input field
**********************************************/
.gadget-content .ui-field-contain .ui-input-has-appendinx,
.gadget-content .ui-field-contain .ui-input-has-prependinx {
display: flex;
}
.gadget-content .ui-field-contain .ui-input-has-appendinx i,
.gadget-content .ui-field-contain .ui-input-has-prependinx i {
display: block;
padding: 3pt;
color: #777777;
font-weight: 400;
}
/**********************************************
* Gadget: relation field
**********************************************/
.relation-input {
......
......@@ -242,7 +242,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>961.19210.8471.60620</string> </value>
<value> <string>961.42445.27813.34781</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -260,7 +260,7 @@
</tuple>
<state>
<tuple>
<float>1502444264.19</float>
<float>1503676812.98</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -52,14 +52,12 @@
});
})
/** Return content even for non-editable cells - be backward compatible! */
.declareMethod('getContent', function () {
if (this.state.editable) {
return this.getDeclaredGadget('sub')
.push(function (gadget) {
return gadget.getContent();
});
}
return {};
return this.getDeclaredGadget('sub')
.push(function (gadget) {
return gadget.getContent();
});
})
.declareMethod('checkValidity', function () {
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>955.60919.29957.58146</string> </value>
<value> <string>960.5523.58984.43537</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1482843372.92</float>
<float>1503499581.59</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -6,7 +6,13 @@
rJS(window)
.setState({
tag: 'div',
text_content: ''
text_content: '',
inner_html: '',
name: undefined,
src: undefined,
alt: undefined,
append: '',
prepend: ''
})
.declareMethod('render', function (options) {
......@@ -15,16 +21,27 @@
inner_html: options.inner_html || "",
tag: options.tag || 'div',
src: options.src,
alt: options.alt
alt: options.alt,
name: options.name,
append: options.append || '',
prepend: options.prepend || ''
};
return this.changeState(state_dict);
})
.onStateChange(function () {
var element = this.element,
new_element = document.createElement(this.state.tag);
new_element = document.createElement(this.state.tag),
content = this.state.text_content;
if (this.state.text_content) {
new_element.textContent = this.state.text_content;
if (this.state.prepend) {
content = this.state.prepend + "&nbsp;" + content;
}
if (this.state.append) {
content = content + "&nbsp;" + this.state.append;
}
new_element.textContent = content;
} else if (this.state.inner_html) {
new_element.innerHTML = this.state.inner_html;
}
......@@ -39,6 +56,19 @@
element.removeChild(element.firstChild);
}
element.appendChild(new_element);
})
/** Because of meta-fields (controlling MatrixBox for example) we need to
* obtain value of readonly fields.
* In order to make it more developer-friendly, only named fields return their values.
*/
.declareMethod("getContent", function () {
var data = {};
if (!this.state.name) {
return data;
}
data[this.state.name] = this.state.text_content || this.state.inner_html || "";
return data;
});
}(window, document, rJS));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>955.51162.4768.35123</string> </value>
<value> <string>961.46335.40182.23005</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1482843300.9</float>
<float>1503909097.14</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -9,10 +9,13 @@
value: undefined,
checked: undefined,
title: '',
name: '',
type: 'text',
required: false,
trim: false,
focus: undefined
required: false, // mandatory field
trim: false, // trim content for spaces
focus: undefined, // has focus by default
prepend: undefined, // text to prepend infront the field
append: undefined // text to apend after the field
})
.declareMethod('render', function (options) {
......@@ -27,13 +30,17 @@
focus: options.focus,
step: options.step,
hidden: options.hidden,
trim: options.trim || false
trim: options.trim || false,
append: options.append,
prepend: options.prepend
};
return this.changeState(state_dict);
})
.onStateChange(function () {
var textarea = this.element.querySelector('input');
.onStateChange(function (modification_dict) {
var textarea = this.element.querySelector('input'),
tmp; // general use short-scope variable
if (this.state.type === 'checkbox') {
textarea.checked = this.state.checked;
} else {
......@@ -81,6 +88,22 @@
textarea.autofocus = false;
textarea.blur();
}
if (modification_dict.append) {
this.element.classList.add('ui-input-has-appendinx');
tmp = document.createElement('i');
tmp.appendChild(document.createTextNode(modification_dict.append));
this.element.appendChild(tmp);
tmp = undefined;
}
if (modification_dict.prepend) {
this.element.classList.add('ui-input-has-prependinx');
tmp = document.createElement('i');
tmp.appendChild(document.createTextNode(modification_dict.append));
this.element.insertBefore(tmp, textarea);
tmp = undefined;
}
})
.declareService(function () {
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>961.1644.62757.27801</string> </value>
<value> <string>961.40519.18664.56814</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1501232763.54</float>
<float>1503560196.31</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -21,24 +21,24 @@
})
.declareMethod('render', function (options) {
var state_dict = {
value: options.value,
editable: options.editable,
name: options.name,
title: options.title,
hidden: options.hidden
};
return this.changeState(state_dict);
return this.changeState(options);
})
.onStateChange(function () {
.onStateChange(function (modification_dict) {
var textarea = this.element.querySelector('textarea');
// textarea.setAttribute('value', this.state.value);
textarea.value = this.state.value;
textarea.setAttribute('name', this.state.name);
textarea.setAttribute('id', this.state.name);
textarea.setAttribute('title', this.state.title);
if (modification_dict.hasOwnProperty("value")) {
textarea.value = modification_dict.value;
}
if (modification_dict.hasOwnProperty("name")) {
textarea.setAttribute('name', modification_dict.name);
textarea.setAttribute('id', modification_dict.name);
}
if (modification_dict.hasOwnProperty("title")) {
textarea.setAttribute('title', modification_dict.title);
}
if (this.state.required) {
textarea.setAttribute('required', 'required');
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>956.58742.58866.48708</string> </value>
<value> <string>961.46307.16912.53794</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1490622800.75</float>
<float>1503932678.28</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -1247,19 +1247,19 @@ div[data-gadget-scope='header'] .ui-header {
}
*/
/* form validation (assuming label>span is used) */
form label {
form .ui-field-contain {
// relative for displaying popups with errors
position: relative;
span span {
& > span {
animation: fadein @transition-timing;
@media @desktop, @tablet {
background-color: @coloraccent;
color: @colorsubheaderlink;
left: 110%;
left: 25%;
position: absolute;
bottom: 130%;
bottom: 110%;
white-space: pre;
padding: @margin-size;
border-radius: @border-radius;
......@@ -1285,6 +1285,21 @@ div[data-gadget-scope='header'] .ui-header {
}
}
/**********************************************
* Gadget: HTML5 input field
**********************************************/
.gadget-content .ui-field-contain {
.ui-input-has-appendinx,
.ui-input-has-prependinx {
display: flex;
i {
display: block;
padding: 3pt;
color: #777777;
font-weight: 400;
}
}
}
/**********************************************
* Gadget: relation field
**********************************************/
......
......@@ -96,11 +96,10 @@
<td>field_my_title</td>
<td>FooObject</td></tr>
<!-- Verify values rendered in ListBox this time -->
<tr><td>verifyElementPresent</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_listbox.html"]//table/tbody/tr[1]//input[@value="2016-12-24" and @type="date"]</td><td></td></tr>
<tr><td>verifyValue</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_listbox.html"]//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_datetime.html" and @line="0"]//input</td>
<td>2016-12-24</td></tr>
<tr><td>verifyValue</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_listbox.html"]//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_string.html" and @line="0"]//input[@title="Title"]</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_listbox.html"]//table/tbody/tr[1]//input[@title="Title"]</td>
<td>FooLine</td></tr>
</tbody></table>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Zuite" module="Products.Zelenium.zuite"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>renderjs_ui_lines_field_zuite</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<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_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testDialogLinesField</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Dialog Main</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test that the content of LinesField textarea doesn't change when sort button in sub document list is clicked</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/PTZuite_CommonTemplate/macros/init" />
<!-- Shortcut for full renderjs url -->
<tr><td>store</td>
<td>${base_url}/web_site_module/renderjs_runner</td>
<td>renderjs_url</td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_lines.html"]//textarea</td><td></td></tr>
<tr><td>type</td>
<td>field_my_lines_list</td>
<td>foo<br/>bar</td></tr>
<!-- Change sorting of the listbox -->
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_listbox.html"]//table/thead/tr/th/a[@data-i18n='Title']</td><td></td></tr>
<tr><td>click</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_listbox.html"]//table/thead/tr/th/a[@data-i18n='Title']</td><td></td></tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr><td>assertValue</td>
<td>//textarea[@name='field_my_lines_list']</td>
<td>foo<br/>bar</td></tr>
<!-- Save and force unloading of Form and its content from the memory by going back -->
<tr><td>waitForElementPresent</td>
<td>//button[@data-i18n='Save']</td><td></td></tr>
<tr><td>click</td>
<td>//button[@data-i18n='Save']</td><td></td></tr>
<tr><td>waitForTextPresent</td>
<td>Data updated.</td><td></td></tr>
<tr><td>click</td>
<td>//div[@data-role='header']//h1/a</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_field_listbox.html']//table/tbody/tr</td><td></td></tr>
<tr><td>click</td>
<td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_field_listbox.html']//table/tbody/tr[1]//a</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_lines.html"]//textarea</td><td></td></tr>
<!-- Assert value still holds and change it -->
<tr><td>assertValue</td>
<td>//textarea[@name='field_my_lines_list']</td>
<td>foo<br/>bar</td></tr>
<tr><td>assertValue</td>
<td>//textarea[@name='field_my_lines_list']</td>
<td>foo<br/>bar</td></tr>
<tr><td>type</td>
<td>//textarea[@name='field_my_lines_list']</td>
<td>foo bar</td></tr>
<tr><td>click</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_listbox.html"]//table/thead/tr/th/a[@data-i18n='Title']</td>
<td></td></tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr><td>assertValue</td>
<td>//textarea[@name='field_my_lines_list']</td>
<td>foo bar</td></tr>
<!-- Save and force unloading of Form and its content from the memory by going back -->
<tr><td>waitForElementPresent</td>
<td>//button[@data-i18n='Save']</td><td></td></tr>
<tr><td>click</td>
<td>//button[@data-i18n='Save']</td><td></td></tr>
<tr><td>waitForTextPresent</td>
<td>Data updated.</td><td></td></tr>
<tr><td>click</td>
<td>//div[@data-role='header']//h1/a</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_field_listbox.html']//table/tbody/tr</td><td></td></tr>
<tr><td>click</td>
<td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_field_listbox.html']//table/tbody/tr[1]//a</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_lines.html"]//textarea</td><td></td></tr>
<tr><td>assertValue</td>
<td>//textarea[@name='field_my_lines_list']</td>
<td>foo bar</td></tr>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<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_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testEmptyLine</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test first empty line on lines field</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test first empty line on lines field</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/PTZuite_CommonTemplate/macros/init" />
<!-- Shortcut for full renderjs url -->
<tr><td>store</td>
<td>${base_url}/web_site_module/renderjs_runner</td>
<td>renderjs_url</td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_lines.html"]//textarea</td><td></td></tr>
<tr><td>type</td>
<td>field_my_lines_list</td>
<td>javascript{"\na\nb\n"}</td></tr>
<tr><td>waitForElementPresent</td>
<td>//button[@data-i18n='Save']</td><td></td></tr>
<tr><td>click</td>
<td>//button[@data-i18n='Save']</td><td></td></tr>
<tr><td>waitForTextPresent</td>
<td>Data updated.</td><td></td></tr>
<!-- Force unloading of Form and its content from the memory by going back -->
<tr><td>click</td>
<td>//div[@data-role='header']//h1/a</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_field_listbox.html']//table/tbody/tr</td><td></td></tr>
<tr><td>click</td>
<td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_field_listbox.html']//table/tbody/tr[1]//a</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_lines.html"]//textarea</td><td></td></tr>
<tr><td>assertEval</td>
<td>this.browserbot.findElement('field_my_lines_list').value</td>
<td>javascript{"\na\nb\n"}</td></tr>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Zuite" module="Products.Zelenium.zuite"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>renderjs_ui_matrixbox_zuite</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<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_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testColumnTitle</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<!-- Test MatrixBox functionality to
- render correct header
- render correct column names
-->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test MatrixBox Column Title</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test MatrixBox Column Title</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/MatrixBoxZuite_CommonTemplate/macros/init" />
<!-- Shortcut for full renderjs url -->
<tr><td>store</td>
<td>${base_url}/web_site_module/renderjs_runner</td>
<td>renderjs_url</td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/FooModule_createObjects?create_line:int=1</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Created Successfully.</td><td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/Zuite_waitForActivities</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/0/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="MatrixBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="MatrixBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-scope="field_matrixbox"]//tbody/tr/th</td><td></td></tr>
<!-- Verify presence of header and column texts -->
<tr><td>verifyText</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_matrixbox.html"]//thead/tr/th[2]</td>
<td>One</td></tr>
<tr><td>verifyText</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_matrixbox.html"]//thead/tr/th[3]</td>
<td>Two</td></tr>
<tr><td>verifyText</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_matrixbox.html"]//tbody/tr[1]/th</td>
<td>A</td></tr>
<tr><td>verifyText</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_matrixbox.html"]//tbody/tr[2]/th</td>
<td>B</td></tr>
</tbody>
</table>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<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_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testCreateCell</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<!-- Test MatrixBox functionality to
- create one embedded Cell Line
- create second embedded Cell Line
-->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test MatrixBox Column Title</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test MatrixBox Column Title</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/MatrixBoxZuite_CommonTemplate/macros/init" />
<!-- Shortcut for full renderjs url and matrixbox gadget -->
<tr><td>store</td>
<td>${base_url}/web_site_module/renderjs_runner</td>
<td>renderjs_url</td></tr>
<tr><td>store</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_listbox.html"]//table</td>
<td>listbox_table</td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/FooModule_createObjects?create_line:int=1</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Created Successfully.</td><td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/Zuite_waitForActivities</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/0/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="MatrixBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="MatrixBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_matrixbox.html"]//input[@name="field_matrixbox_quantity_cell_0_0_0"]</td><td></td></tr>
<tr><td>type</td>
<td>field_matrixbox_quantity_cell_0_0_0</td>
<td>1.0</td></tr>
<tr><td>click</td>
<td>//button[@data-i18n="Save"]</td><td></td></tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr><td>waitForTextPresent</td>
<td>Data updated.</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_0_0_0</td>
<td>1.0</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_0_1_0</td>
<td></td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_1_0_0</td>
<td></td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_1_1_0</td>
<td></td></tr>
<!-- Test that exactly one record was created using general-purpose ListBox -->
<tr><td>open</td>
<td>${base_url}/foo_module/Zuite_waitForActivities</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/0/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="ListBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="ListBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>${listbox_table}/tbody/tr</td><td></td></tr>
<tr><td>verifyElementNotPresent</td>
<td>${listbox_table}/tbody/tr[2]</td><td></td></tr>
<tr><td>goBack</td><td></td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="MatrixBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="MatrixBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_matrixbox.html"]//input[@name="field_matrixbox_quantity_cell_0_1_0"]</td><td></td></tr>
<tr><td>type</td>
<td>field_matrixbox_quantity_cell_0_1_0</td>
<td>2.0</td></tr>
<tr><td>click</td>
<td>//button[@data-i18n="Save"]</td><td></td></tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr><td>waitForTextPresent</td>
<td>Data updated.</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_0_0_0</td>
<td>1.0</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_0_1_0</td>
<td>2.0</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_1_0_0</td>
<td></td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_1_1_0</td>
<td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/Zuite_waitForActivities</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/0/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="ListBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="ListBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>${listbox_table}/tbody/tr</td><td></td></tr>
<tr><td>verifyElementPresent</td>
<td>${listbox_table}/tbody/tr[2]</td><td></td></tr>
<tr><td>verifyElementNotPresent</td>
<td>${listbox_table}/tbody/tr[3]</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>2 Records</td><td></td></tr>
<!-- Matrix box editable fields can use the cell coordinates as "cell_index" in their TALES-->
<tr><td>open</td>
<td>${base_url}/foo_module/0/1/cell_0_0/getTitle</td><td></td></tr>
<tr><td>verifyTextPresent</td>
<td>a,one</td><td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/0/1/cell_0_1/getTitle</td><td></td></tr>
<tr><td>verifyTextPresent</td>
<td>a,two</td><td></td></tr>
<!-- Matrix box global properties fields can be used to edit all cells with the
same values. The field must be in the 'bottom' group for this to work.
Kato: I don't understand this part of the test - just copy&pasted from the old test.
-->
<tr><td>open</td>
<td>${base_url}/foo_module/0/1/cell_0_0/getFooCategoryTitleList</td><td></td></tr>
<tr><td>verifyTextPresent</td>
<td>['a', 'b']</td><td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/0/1/cell_0_1/getFooCategoryTitleList</td><td></td></tr>
<tr><td>verifyTextPresent</td>
<td>['a', 'b']</td><td></td></tr>
</tbody>
</table>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<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_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testDynamicColumnTitle</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<!-- Test verify that Dynamic MatrixBox has
- correct header
- correct row titles
-->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Dynamic MatrixBox Column Title</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test Dynamic MatrixBox Column Title</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/MatrixBoxZuite_CommonTemplate/macros/init" />
<!-- Shortcut for full renderjs url -->
<tr><td>store</td>
<td>${base_url}/web_site_module/renderjs_runner</td>
<td>renderjs_url</td></tr>
<tr><td>store</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_matrixbox.html"]//table</td>
<td>matrixbox_table</td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/FooModule_createObjects?create_line:int=1</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Created Successfully.</td><td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/Zuite_waitForActivities</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/0/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Dynamic MatrixBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Dynamic MatrixBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>${matrixbox_table}/tbody/tr/th</td><td></td></tr>
<tr><td>verifyText</td>
<td>${matrixbox_table}/thead/tr/th[2]</td>
<td>Three</td></tr>
<tr><td>verifyText</td>
<td>${matrixbox_table}/thead/tr/th[3]</td>
<td>Four</td></tr>
<tr><td>verifyText</td>
<td>${matrixbox_table}/tbody/tr[1]/th</td>
<td>C</td></tr>
<tr><td>verifyText</td>
<td>${matrixbox_table}/tbody/tr[2]/th</td>
<td>D</td></tr>
</tbody>
</table>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<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_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testDynamicCreateCell</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Dynamic MatrixBox Cell Creation</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test Dynamic MatrixBox Cell Creation</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/MatrixBoxZuite_CommonTemplate/macros/init" />
<!-- Shortcut for full renderjs url -->
<tr><td>store</td>
<td>${base_url}/web_site_module/renderjs_runner</td>
<td>renderjs_url</td></tr>
<tr><td>store</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_matrixbox.html"]//table</td>
<td>matrixbox_table</td></tr>
<tr><td>store</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_listbox.html"]//table</td>
<td>listbox_table</td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/FooModule_createObjects?create_line:int=1</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Created Successfully.</td><td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/Zuite_waitForActivities</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/0/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Dynamic MatrixBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Dynamic MatrixBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>${matrixbox_table}//input[@name="field_matrixbox_quantity_cell_0_0_0"]</td><td></td></tr>
<tr><td>type</td>
<td>field_matrixbox_quantity_cell_0_0_0</td>
<td>1.0</td></tr>
<tr><td>click</td>
<td>//button[@data-i18n="Save"]</td><td></td></tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr><td>waitForTextPresent</td>
<td>Data updated.</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_0_0_0</td>
<td>1.0</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_0_1_0</td>
<td></td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_1_0_0</td>
<td></td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_1_1_0</td>
<td></td></tr>
<!-- Test that exactly one record was created using general-purpose ListBox -->
<tr><td>open</td>
<td>${base_url}/foo_module/Zuite_waitForActivities</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/0/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="ListBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="ListBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>${listbox_table}/tbody/tr</td><td></td></tr>
<tr><td>verifyElementNotPresent</td>
<td>${listbox_table}/tbody/tr[2]</td><td></td></tr>
<tr><td>goBack</td><td></td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Dynamic MatrixBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Dynamic MatrixBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_matrixbox.html"]//input[@name="field_matrixbox_quantity_cell_0_1_0"]</td><td></td></tr>
<tr><td>type</td>
<td>field_matrixbox_quantity_cell_0_1_0</td>
<td>2.0</td></tr>
<tr><td>click</td>
<td>//button[@data-i18n="Save"]</td><td></td></tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr><td>waitForTextPresent</td>
<td>Data updated.</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_0_0_0</td>
<td>1.0</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_0_1_0</td>
<td>2.0</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_1_0_0</td>
<td></td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_1_1_0</td>
<td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/Zuite_waitForActivities</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/0/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="ListBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="ListBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>${listbox_table}/tbody/tr</td><td></td></tr>
<tr><td>verifyElementPresent</td>
<td>${listbox_table}/tbody/tr[2]</td><td></td></tr>
<tr><td>verifyElementNotPresent</td>
<td>${listbox_table}/tbody/tr[3]</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>2 Records</td><td></td></tr>
<!-- Matrix box editable fields can use the cell coordinates as "cell_index" in their TALES-->
<tr><td>open</td>
<td>${base_url}/foo_module/0/1/cell_0_0/getTitle</td><td></td></tr>
<tr><td>verifyTextPresent</td>
<td>c,four</td><td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/0/1/cell_0_1/getTitle</td><td></td></tr>
<tr><td>verifyTextPresent</td>
<td>c,three</td><td></td></tr>
<!-- Matrix box global properties fields can be used to edit all cells with the
same values. The field must be in the 'bottom' group for this to work.
Kato: I don't understand this part of the test - just copy&pasted from the old test.
-->
<tr><td>open</td>
<td>${base_url}/foo_module/0/1/cell_0_0/getFooCategoryTitleList</td><td></td></tr>
<tr><td>verifyTextPresent</td>
<td>['a', 'b']</td><td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/0/1/cell_0_1/getFooCategoryTitleList</td><td></td></tr>
<tr><td>verifyTextPresent</td>
<td>['a', 'b']</td><td></td></tr>
</tbody>
</table>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<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_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testValidationOnEditableCell</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Validation on editable cells</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test validation on editable cells</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/MatrixBoxZuite_CommonTemplate/macros/init" />
<!-- Shortcut for full renderjs url -->
<tr><td>store</td>
<td>${base_url}/web_site_module/renderjs_runner</td>
<td>renderjs_url</td></tr>
<tr><td>store</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_matrixbox.html"]//table</td>
<td>matrixbox_table</td></tr>
<tr><td>store</td>
<td>//div[@data-gadget-url="${renderjs_url}/gadget_erp5_field_listbox.html"]//table</td>
<td>listbox_table</td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/FooModule_createObjects?create_line:int=1</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Created Successfully.</td><td></td></tr>
<tr><td>open</td>
<td>${base_url}/foo_module/Zuite_waitForActivities</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr>
<tr><td>open</td>
<td>${renderjs_url}/#/foo_module/0/1?editable=1</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Views"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>//a[@data-i18n="Dynamic MatrixBox"]</td><td></td></tr>
<tr><td>click</td>
<td>//a[@data-i18n="Dynamic MatrixBox"]</td><td></td></tr>
<tr><td>waitForElementPresent</td>
<td>${matrixbox_table}//input[@name="field_matrixbox_quantity_cell_0_0_0"]</td><td></td></tr>
<!-- We cannot just type garbage like in XHTML skin because we are using proper
number fields. Thus there is an external validator which raises when the
value is < 0 -->
<tr><td>type</td>
<td>field_matrixbox_quantity_cell_0_0_0</td>
<td>-2.0</td></tr>
<tr><td>type</td>
<td>field_matrixbox_quantity_cell_0_1_0</td>
<td>2.0</td></tr>
<tr><td>click</td>
<td>//button[@data-i18n="Save"]</td><td></td></tr>
<tr><td>waitForTextPresent</td>
<td>Input data has errors.</td><td></td></tr>
<!-- Verify no data loss (and correct formating with precision=1)-->
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_0_0_0</td>
<td>-2.0</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_0_1_0</td>
<td>2.0</td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_1_0_0</td>
<td></td></tr>
<tr><td>verifyValue</td>
<td>field_matrixbox_quantity_cell_1_1_0</td>
<td></td></tr>
<!-- create cells -->
<tr><td>type</td>
<td>field_matrixbox_quantity_cell_0_0_0</td>
<td>1.0</td></tr>
<tr><td>type</td>
<td>field_matrixbox_quantity_cell_0_1_0</td>
<td>2.0</td></tr>
<tr><td>click</td>
<td>//button[@data-i18n="Save"]</td><td></td></tr>
<tr><td>waitForTextPresent</td>
<td>Data updated.</td><td></td></tr>
</tbody>
</table>
</body>
</html>
\ No newline at end of file
......@@ -55,12 +55,12 @@
<!-- There is a form_view gadget containing the main fields -->
<tr>
<td>assertElementPresent</td>
<td>waitForElementPresent</td>
<td>//div[@class='form_view']//div[@data-gadget-url='${base_url}/web_site_module/renderjs_runner/gadget_erp5_pt_form_view_editable.html']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>waitForElementPresent</td>
<td>//div[@class='form_view']//div[@data-gadget-url='${base_url}/web_site_module/renderjs_runner/gadget_erp5_pt_form_view_editable.html']//label[@for='field_your_zodb_history']</td>
<td></td>
</tr>
......
......@@ -53,6 +53,12 @@
</tr>
<!-- Header has a link to the action page -->
<tr>
<td>waitForElementPresent</td>
<td>//div[@data-gadget-scope='header']//a[text()='Add']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[@data-gadget-scope='header']//a[text()='Add' and contains(@href, '#!change') and contains(@href, 'view%3Dcreate_a_document')]</td>
......
......@@ -106,7 +106,7 @@
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[@data-gadget-scope='panel' and contains(@class, 'visible')]</td>
<td>//div[@data-gadget-scope='panel' and contains(@class, 'visible')]//a[text()='lishi']</td>
<td></td>
</tr>
<tr>
......
......@@ -207,13 +207,13 @@
<tal:block metal:define-macro="check_search_in_form_list">
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url, 'gadget_erp5_pt_form_list.html')]//input[@name='search']</td>
<td>//div[contains(@data-gadget-url, 'gadget_erp5_pt_form_list.html')]//div[@data-gadget-scope='erp5_searchfield']//input[@name='search']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td tal:content="python: &quot;//div[contains(@data-gadget-url, 'gadget_erp5_pt_form_list.html')]//div[@data-gadget-scope='erp5_searchfield']//input[@value='%s' and @type='search' and @name='search']&quot; % search_query"></td>
<td></td>
<td>assertValue</td>
<td>//div[contains(@data-gadget-url, 'gadget_erp5_pt_form_list.html')]//div[@data-gadget-scope='erp5_searchfield']//input[@name='search' and @type='search']</td>
<td tal:content="search_query"></td>
</tr>
</tal:block>
......
##############################################################################
#
# Copyright (c) 2011 Nexedi SARL and Contributors. All Rights Reserved.
# Kazuhiko <kazuhiko@nexedi.com>
# Rafael Monnerat <rafael@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import unittest
from Products.ERP5Type.tests.ERP5TypeFunctionalTestCase import ERP5TypeFunctionalTestCase
class TestRenderJSUILinesField(ERP5TypeFunctionalTestCase):
foreground = 0
run_only = "renderjs_ui_lines_field_zuite"
def getBusinessTemplateList(self):
return (
'erp5_web_renderjs_ui',
'erp5_web_renderjs_ui_test',
'erp5_ui_test_core',
)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestRenderJSUILinesField))
return suite
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testFunctionalRJSLinesField</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testFunctionalRJSLinesField</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData>
##############################################################################
#
# Copyright (c) 2011 Nexedi SARL and Contributors. All Rights Reserved.
# Kazuhiko <kazuhiko@nexedi.com>
# Rafael Monnerat <rafael@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import unittest
from Products.ERP5Type.tests.ERP5TypeFunctionalTestCase import ERP5TypeFunctionalTestCase
class TestRenderJSUIMatrixbox(ERP5TypeFunctionalTestCase):
foreground = 0
run_only = "renderjs_ui_matrixbox_zuite"
def getBusinessTemplateList(self):
return (
'erp5_web_renderjs_ui',
'erp5_web_renderjs_ui_test',
'erp5_ui_test_core',
)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestRenderJSUIMatrixbox))
return suite
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testFunctionalRJSMatrixbox</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testFunctionalRJSMatrixbox</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData>
......@@ -4,6 +4,8 @@ portal_tests/renderjs_ui_date_time_field_zuite
portal_tests/renderjs_ui_date_time_field_zuite/**
portal_tests/renderjs_ui_form_box_zuite
portal_tests/renderjs_ui_form_box_zuite/**
portal_tests/renderjs_ui_lines_field_zuite
portal_tests/renderjs_ui_lines_field_zuite/**
portal_tests/renderjs_ui_list_field_zuite
portal_tests/renderjs_ui_list_field_zuite/**
portal_tests/renderjs_ui_listbox_zuite
......@@ -12,6 +14,8 @@ portal_tests/renderjs_ui_logout_translate_zuite
portal_tests/renderjs_ui_logout_translate_zuite/**
portal_tests/renderjs_ui_logout_zuite
portal_tests/renderjs_ui_logout_zuite/**
portal_tests/renderjs_ui_matrixbox_zuite
portal_tests/renderjs_ui_matrixbox_zuite/**
portal_tests/renderjs_ui_multi_check_box_field_zuite
portal_tests/renderjs_ui_multi_check_box_field_zuite/**
portal_tests/renderjs_ui_multi_list_field_zuite
......
test.erp5.testFunctionalRJSCore
test.erp5.testFunctionalRJSCheckBoxField
test.erp5.testFunctionalRJSLinesField
test.erp5.testFunctionalRJSListField
test.erp5.testFunctionalRJSMultiCheckBoxField
test.erp5.testFunctionalRJSMultiListField
......@@ -14,4 +15,5 @@ test.erp5.testFunctionalRJSFormbox
test.erp5.testFunctionalRJSLogout
test.erp5.testFunctionalRJSTranslation
test.erp5.testFunctionalRJSLogoutTranslation
test.erp5.testFunctionalRJSNotification
\ No newline at end of file
test.erp5.testFunctionalRJSNotification
test.erp5.testFunctionalRJSMatrixbox
\ No newline at end of file
......@@ -390,20 +390,16 @@ class MatrixBoxWidget(Widget.Widget):
if form.has_field(my_field_id):
my_field = form.get_field(my_field_id)
key = my_field.id + '_cell_%s_%s_%s%s' % (i,j,k,extra_dimension_index)
if cell is not None:
attribute_value = my_field.get_value('default',
cell=cell, cell_index=kw, cell_position = ((i,j,k)+extra_dimension_position))
default_value = my_field.get_value(
'default', cell=cell, cell_index=kw, cell_position=((i,j,k)+extra_dimension_position))
display_value = default_value
if field_errors:
# Display previous value in case of any error in this form because
# we have no cell to get value from
display_value = REQUEST.get('field_%s' % key, default_value)
if cell is not None:
if render_format=='html':
display_value = attribute_value
if field_errors:
# Display previous value in case of any error
# in this form because we have no cell to get
# value from
display_value = REQUEST.get('field_%s' % key,
attribute_value)
else:
display_value = attribute_value
cell_html = my_field.render(value=display_value,
REQUEST=REQUEST,
key=key)
......@@ -422,23 +418,8 @@ class MatrixBoxWidget(Widget.Widget):
else:
cell_body += '<span class="input">%s</span>' % (
cell_html )
elif render_format == 'list':
if not my_field.get_value('hidden'):
list_result_lines.append(attribute_value)
else:
attribute_value = my_field.get_value('default', cell=None,
cell_index=kw, cell_position=((i,j,k)+extra_dimension_position))
if render_format == 'html':
if field_errors:
# Display previous value in case of any error
# in this form because we have no cell to get
# value from
display_value = REQUEST.get('field_%s' % key,
attribute_value)
else:
display_value = attribute_value
if key in field_errors:
# Display error message if this cell has an error
has_error = True
......@@ -453,8 +434,17 @@ class MatrixBoxWidget(Widget.Widget):
value=display_value,
REQUEST=REQUEST,
key=key)
elif render_format == 'list':
list_result_lines.append(None)
if render_format == 'list':
# list rendering doesn't make difference when cell exists or not
list_result_lines.append({
'default': default_value,
'value': display_value,
'key': key,
'type': my_field.meta_type if my_field.meta_type != "ProxyField" else my_field.getRecursiveTemplateField().meta_type,
'field_id': my_field.id,
'error_text': u"%s" % (translateString(field_errors[key].error_text) if key in field_errors else '')
})
css = td_css
if has_error:
......@@ -601,8 +591,15 @@ class MatrixBoxValidator(Validator.Validator):
cell=cell, cell_index=kw, cell_position = ((i,j,k)+extra_dimension_position))
value = None
try :
value = my_field.validator.validate(
my_field, key, REQUEST)
# We call directly Validator's validate method to pass our own key
# because Field.validate always computes the key from field properties
value = my_field.validator.validate(my_field, key, REQUEST)
# Unfortunately the call to external validator is implemented within
# field's `validate` method. Since we call the validator's validate
# directly, we need to copy&paste call to external validator from Field's validate here
external_validator = my_field.get_value('external_validator')
if external_validator and not external_validator(value, REQUEST):
my_field.validator.raise_error('external_validator_failed', my_field)
except ValidationError, err :
err.field_id = my_field.id + '_cell_%s_%s_%s%s' % (i,j,k,extra_dimension_index)
error_list.append(err)
......
......@@ -194,7 +194,7 @@ class Field:
return "Unknown error: %s" % name
security.declarePrivate('_render_helper')
def _render_helper(self, key, value, REQUEST, render_prefix=None, editable=None):
def _render_helper(self, key, value, REQUEST, render_prefix=None, editable=None, **kw):
value = self._get_default(key, value, REQUEST)
__traceback_info__ = ('key=%s value=%r' % (key, value))
if self.get_value('hidden', REQUEST=REQUEST):
......@@ -204,10 +204,10 @@ class Field:
editable = self.get_value('editable', REQUEST=REQUEST)
if not editable:
return self.widget.render_view(self, value, REQUEST=REQUEST,
render_prefix=render_prefix)
render_prefix=render_prefix, **kw)
else:
return self.widget.render(self, key, value, REQUEST,
render_prefix=render_prefix)
render_prefix=render_prefix, **kw)
security.declarePrivate('_render_odt_helper')
def _render_odt_helper(self, key, value, as_string, ooo_builder,
......@@ -261,7 +261,7 @@ class Field:
return REQUEST.form[key]
security.declareProtected('View', 'render')
def render(self, value=None, REQUEST=None, key=None, render_prefix=None, key_prefix=None, editable=None):
def render(self, value=None, REQUEST=None, key=None, render_prefix=None, key_prefix=None, editable=None, **kw):
"""Render the field widget.
value -- the value the field should have (for instance
from validation).
......@@ -279,6 +279,7 @@ class Field:
REQUEST,
render_prefix=render_prefix,
editable=editable,
**kw
)
security.declareProtected('View', 'render_view')
......
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