Commit d3550bda authored by Jérome Perrin's avatar Jérome Perrin

Merge !504 Do not save documents when there are pending activities

When document has pending activities, we refuse changing ID ( because there might be pending `updateRelatedContent` activities if I remember correctly ), but it's done in a way that breaks the "atomic" aspect of the transaction a bit, because we

As a result, this happens sometimes that not all properties user changed are modified. In the example below, the change to *Include Documents in Site Map* is not saved (and also change to *ID*):

![erp5-sorryPendingActivitiesSavePartially](/uploads/ff4bfd6ad0e8a42ba3684cccdc450e21/erp5-sorryPendingActivitiesSavePartially.gif)

The changed here is to use a field validator that refused editing when there are pending activities, so that user gets a:

![erp5-pending-activiities](/uploads/bfe825560bdee34f0443e8e36884f21c/erp5-pending-activiities.png)

and the result is either all changes are applied or no change is applied at all.

This is done by:
 * introducing a new `my_view_mode_id` field in `erp5_core`'s `Base_viewFieldLibrary`
 * using this field as proxy field of all editable `my_id` fields. Maybe I forgot some business templates, I changed only the most common ones. I intentionally did not change all fields of `erp5_ui_test` because I think they are used to compare speed of proxy fields vs traditional fields.

0352f50fd543fda2712bb8ca93d8a8814f975a26 introduces a Zelenium test exercising this new behavior.

/reviewed-on nexedi/erp5!504
parents 39ebb00b 6c44fa17
......@@ -6,6 +6,12 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_id</string> </value>
......@@ -69,7 +75,7 @@
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewAccountingFieldLibrary</string> </value>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
......
......@@ -9,12 +9,7 @@
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>description</string>
<string>title</string>
<string>required</string>
<string>display_width</string>
</list>
<list/>
</value>
</item>
<item>
......@@ -74,34 +69,18 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string>Identification</string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ID</string> </value>
</item>
</dictionary>
</value>
</item>
......
......@@ -9,9 +9,7 @@
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
</list>
<list/>
</value>
</item>
<item>
......@@ -73,7 +71,7 @@
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
......@@ -83,10 +81,6 @@
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ID</string> </value>
</item>
</dictionary>
</value>
</item>
......
......@@ -792,7 +792,7 @@ class TestERP5Document_getHateoas_mode_traverse(ERP5HALJSONStyleSkinsMixin):
self.assertEqual(result_dict['pt'], 'form_view')
self.assertEqual(result_dict['action'], 'Base_edit')
self.assertEqual(result_dict['group_list'][0][0], 'left')
self.assertEqual(result_dict['group_list'][0][1][0], ['my_id', {'meta_type': 'StringField'}])
self.assertEqual(result_dict['group_list'][0][1][0], ['my_id', {'meta_type': 'ProxyField'}])
self.assertEqual(result_dict['_debug'], "traverse")
class TestERP5Document_getHateoas_mode_search(ERP5HALJSONStyleSkinsMixin):
......
......@@ -9,10 +9,7 @@
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>required</string>
<string>title</string>
</list>
<list/>
</value>
</item>
<item>
......@@ -74,24 +71,16 @@
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ID</string> </value>
</item>
</dictionary>
</value>
</item>
......
......@@ -9,10 +9,7 @@
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>display_width</string>
<string>title</string>
</list>
<list/>
</value>
</item>
<item>
......@@ -72,13 +69,9 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
......@@ -88,10 +81,6 @@
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ID</string> </value>
</item>
</dictionary>
</value>
</item>
......
......@@ -9,10 +9,7 @@
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>display_width</string>
<string>title</string>
</list>
<list/>
</value>
</item>
<item>
......@@ -72,13 +69,9 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
......@@ -88,10 +81,6 @@
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ID</string> </value>
</item>
</dictionary>
</value>
</item>
......
<?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>testChangeIdWithPendingActivities</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 Change Id with pending activities</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test Change Id with pending activities</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/ListBoxZuite_CommonTemplate/macros/init" />
<tr>
<td>open</td>
<td>${base_url}/foo_module/FooModule_createObjects?num: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>${base_url}/foo_module/view</td>
<td></td>
</tr>
<tr>
<td>clickAndWait</td>
<td>link=0</td>
<td></td>
</tr>
<tr>
<td>assertTitle</td>
<td>Foo - Title 0*</td>
<td></td>
</tr>
<tr>
<td>assertValue</td>
<td>field_my_id</td>
<td>0</td>
</tr>
<tr>
<td>type</td>
<td>field_my_title</td>
<td>Change title (to have an activity)</td>
</tr>
<tr>
<td>clickAndWait</td>
<td>Base_edit:method</td>
<td></td>
</tr>
<tr>
<td>verifyPortalStatusMessage</td>
<td>Data updated.</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>field_my_id</td>
<td>new_id</td>
</tr>
<tr>
<td>clickAndWait</td>
<td>Base_edit:method</td>
<td></td>
</tr><tr>
<td>verifyText</td>
<td>//div[@id="information_area"]</td>
<td>Input data has errors. Please look at the error messages below.</td>
</tr>
<tr>
<td>verifyText</td>
<td>//span[@class="error"]</td>
<td>Document has pending activities.</td>
</tr>
</tbody></table>
</body>
</html>
\ No newline at end of file
......@@ -9,10 +9,7 @@
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>description</string>
<string>title</string>
</list>
<list/>
</value>
</item>
<item>
......@@ -72,26 +69,18 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string>Identification</string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewWebFieldLibrary</string> </value>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ID</string> </value>
</item>
</dictionary>
</value>
</item>
......
......@@ -9,12 +9,7 @@
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>description</string>
<string>title</string>
<string>required</string>
<string>display_width</string>
</list>
<list/>
</value>
</item>
<item>
......@@ -74,34 +69,18 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string>Identification</string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewWebFieldLibrary</string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>1</int> </value>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ID</string> </value>
</item>
</dictionary>
</value>
</item>
......
......@@ -9,10 +9,7 @@
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
<string>required</string>
</list>
<list/>
</value>
</item>
<item>
......@@ -72,30 +69,18 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string>Identification</string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ID</string> </value>
</item>
</dictionary>
</value>
</item>
......
......@@ -10,7 +10,7 @@
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
<string>external_validator</string>
</list>
</value>
</item>
......@@ -71,9 +71,15 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
......@@ -83,14 +89,23 @@
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ID</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Method" module="Products.Formulator.MethodField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>method_name</string> </key>
<value> <string>Base_validateDocumentHasNoActivity</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -8,7 +8,6 @@
from the context update logic
"""
from Products.Formulator.Errors import FormValidationError
from Products.CMFActivity.Errors import ActivityPendingError
request=container.REQUEST
portal = context.getPortalObject()
......@@ -215,11 +214,11 @@ encapsulated_editor_list = []
MARKER = []
message = Base_translateString("Data updated.")
try:
# We process all the field in form and
# we check if they are in the request,
# then we edit them
for field in form.get_fields():
# We process all the field in form and
# we check if they are in the request,
# then we edit them
for field in form.get_fields():
parseField(field)
## XXX We need to find a way not to use meta_type.
......@@ -232,16 +231,14 @@ try:
elif(field_meta_type == 'MatrixBox'):
editMatrixBox(field, request.get(field.id))
# Return parsed values
if silent_mode: return (kw, encapsulated_editor_list), 'edit'
# Return parsed values
if silent_mode: return (kw, encapsulated_editor_list), 'edit'
# Maybe we should build a list of objects we need
# Update basic attributes
context.edit(REQUEST=request, edit_order=edit_order, **kw)
for encapsulated_editor in encapsulated_editor_list:
# Maybe we should build a list of objects we need
# Update basic attributes
context.edit(REQUEST=request, edit_order=edit_order, **kw)
for encapsulated_editor in encapsulated_editor_list:
encapsulated_editor.edit(context)
except ActivityPendingError,e:
message = Base_translateString("%s" % e)
if message_only:
return message
......
"""Refuse changing the id of an object with pending activities.
"""
document = context.aq_parent.aq_parent.aq_parent
if editor != document.getId():
return not document.hasActivity()
return True
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>editor, request</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_validateDocumentHasNoActivity</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -161,6 +161,7 @@
<string>my_view_mode_text_content</string>
<string>my_core_mode_text_content_validator</string>
<string>my_dialog_mode_text_content</string>
<string>my_view_mode_id</string>
</list>
</value>
</item>
......
......@@ -78,7 +78,7 @@
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
......
......@@ -9,9 +9,7 @@
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
</list>
<list/>
</value>
</item>
<item>
......@@ -73,7 +71,7 @@
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
......@@ -83,10 +81,6 @@
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ID</string> </value>
</item>
</dictionary>
</value>
</item>
......
......@@ -78,7 +78,7 @@
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>my_view_mode_id</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
......
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