From 555356ced901976b4645daa3f894fb44143ee803 Mon Sep 17 00:00:00 2001 From: Romain Courteaud <romain@nexedi.com> Date: Mon, 17 Sep 2018 10:39:27 +0200 Subject: [PATCH] [erp5_web_renderjs_ui] RelationField: add checkValidity method Prevent submitting the form if the relation field contains an unknown search string. --- ...gadget_erp5_multirelationstringfield_js.js | 46 ++++++++++++++++- ...adget_erp5_multirelationstringfield_js.xml | 4 +- .../rjs_gadget_erp5_relation_input_js.js | 17 +++++-- .../rjs_gadget_erp5_relation_input_js.xml | 4 +- .../rjs_gadget_erp5_relationstringfield_js.js | 7 +++ ...rjs_gadget_erp5_relationstringfield_js.xml | 4 +- .../testFormViewEditableSaveFail.zpt | 51 +++---------------- .../testFormViewEditablePersistent.zpt | 46 ++++++++--------- ...testRelationFieldNothingSelectedInList.zpt | 34 +++---------- .../Zuite_CommonTemplateForRenderjsUi.zpt | 10 +++- 10 files changed, 114 insertions(+), 109 deletions(-) diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_multirelationstringfield_js.js b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_multirelationstringfield_js.js index 8810e748fd..9775daad15 100644 --- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_multirelationstringfield_js.js +++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_multirelationstringfield_js.js @@ -58,7 +58,7 @@ url: field_json.url, allow_creation: field_json.allow_creation, portal_types: field_json.portal_types, - translated_portal_types: field_json.translated_portal_types, + translated_portal_types: field_json.translated_portal_types, relation_field_id: field_json.relation_field_id, hidden: field_json.hidden, // Force calling subfield render @@ -234,7 +234,8 @@ } } //user remove all data - if (options.format === "erp5" && result[gadget.state.key].length === 0) { + if (options.format === "erp5" && + result[gadget.state.key].length === 0) { result[gadget.state.key] = ""; } return result; @@ -242,6 +243,47 @@ }); } return final_result; + }, {mutex: 'changestate'}) + + .declareMethod('checkValidity', function () { + var context = this; + + function checkSubContentValidity(node) { + var scope = node.getAttribute('data-gadget-scope'); + if (scope !== null) { + return context.getDeclaredGadget( + node.getAttribute('data-gadget-scope') + ) + .push(function (result) { + return result.checkValidity(); + }); + } + } + + if (this.state.editable) { + return new RSVP.Queue() + .push(function () { + var promise_list = [], + i; + for (i = 0; i < context.element.childNodes.length; i += 1) { + promise_list.push( + checkSubContentValidity(context.element.childNodes[i]) + ); + } + return RSVP.all(promise_list); + }) + .push(function (validity_list) { + var i; + for (i = 0; i < validity_list.length; i += 1) { + if (!validity_list[i]) { + return false; + } + } + return true; + }); + } + return true; + }, {mutex: 'changestate'}); }(window, rJS, RSVP, document)); diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_multirelationstringfield_js.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_multirelationstringfield_js.xml index d6a96f3b29..980c3ad92b 100644 --- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_multirelationstringfield_js.xml +++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_multirelationstringfield_js.xml @@ -230,7 +230,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>965.241.13759.3805</string> </value> + <value> <string>970.11252.5060.21026</string> </value> </item> <item> <key> <string>state</string> </key> @@ -248,7 +248,7 @@ </tuple> <state> <tuple> - <float>1517321450.32</float> + <float>1536588738.44</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relation_input_js.js b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relation_input_js.js index b9072f774c..e697a5946a 100644 --- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relation_input_js.js +++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relation_input_js.js @@ -445,8 +445,18 @@ }, true, false) .declareMethod('checkValidity', function () { + if ((this.state.value_text) && ( + (this.state.value_relative_url === null) && + (this.state.value_uid === null) && + (this.state.value_portal_type === null) + )) { + return this.notifyInvalid("No such document was found") + .push(function () { + return false; + }); + } return true; - }) + }, {mutex: 'changestate'}) // XXX Use html5 input .onEvent('invalid', function (evt) { @@ -455,10 +465,7 @@ }, true, false) .onEvent('change', function () { - return RSVP.all([ - this.checkValidity(), - this.notifyChange() - ]); + return this.notifyChange(); }, false, false) diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relation_input_js.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relation_input_js.xml index afc7910653..3f112e364b 100644 --- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relation_input_js.xml +++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relation_input_js.xml @@ -236,7 +236,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>966.58749.49498.3481</string> </value> + <value> <string>970.16829.43481.45789</string> </value> </item> <item> <key> <string>state</string> </key> @@ -254,7 +254,7 @@ </tuple> <state> <tuple> - <float>1523882792.37</float> + <float>1536923390.01</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relationstringfield_js.js b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relationstringfield_js.js index 0c5815b06a..3874a6a6bf 100644 --- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relationstringfield_js.js +++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relationstringfield_js.js @@ -85,6 +85,13 @@ } return result; }); + }, {mutex: 'changestate'}) + + .declareMethod('checkValidity', function () { + return this.getDeclaredGadget("relation_input") + .push(function (input_gadget) { + return input_gadget.checkValidity(); + }); }, {mutex: 'changestate'}); }(window, rJS)); \ No newline at end of file diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relationstringfield_js.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relationstringfield_js.xml index fbe669e8b7..35cc8a2915 100644 --- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relationstringfield_js.xml +++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_relationstringfield_js.xml @@ -230,7 +230,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>963.11788.48702.26146</string> </value> + <value> <string>970.11323.28526.22766</string> </value> </item> <item> <key> <string>state</string> </key> @@ -248,7 +248,7 @@ </tuple> <state> <tuple> - <float>1516352110.99</float> + <float>1536593071.17</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_notification_zuite/testFormViewEditableSaveFail.zpt b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_notification_zuite/testFormViewEditableSaveFail.zpt index a3fa4dae0c..dc2e105e4c 100644 --- a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_notification_zuite/testFormViewEditableSaveFail.zpt +++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_notification_zuite/testFormViewEditableSaveFail.zpt @@ -17,60 +17,25 @@ <td></td> </tr> -<!-- Wait for gadget to be loaded --> -<tr> - <td>waitForElementPresent</td> - <td>//div[@data-gadget-url='${base_url}/web_site_module/renderjs_runner/gadget_erp5_pt_form_view_editable.html']</td> - <td></td> -</tr> -<tr> - <td>waitForTextPresent</td> - <td>Title 1</td> - <td></td> -</tr> +<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_app_loaded" /> -<!-- Header has a save button --> -<tr> - <td>assertElementPresent</td> - <td>//div[@data-gadget-scope='header']//button[text()='Save' and @type='submit']</td> - <td></td> -</tr> +<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/go_to_foo_relation_field_view" /> <tr> <td>type</td> - <td>field_my_foo_category_title</td> - <td>QWERTY</td> -</tr> -<tr> - <td>fireEvent</td> - <td>//input[@name='field_my_foo_category_title']</td> - <td>input</td> -</tr> -<tr> - <td>pause</td> - <td>1000</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>//div[@data-gadget-scope='header']//button[text()='Save' and @type='submit']</td> - <td></td> + <td>field_my_title</td> + <td>Foo Title 123</td> </tr> +<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_save" /> - -<!--tr> - <td>waitForElementPresent</td> - <td>//div[@data-gadget-scope='header']//button[text()='Save' and @type='submit' and contains(@class, 'ui-icon-spinner')]</td> - <td></td> -</tr--> <tr> <td>waitForTextPresent</td> - <td>No such document was found</td> + <td>Input is required but no input given.</td> <td></td> </tr> <tr> <td>verifyValue</td> - <td>//input[@name='field_my_foo_category_title']</td> - <td>QWERTY</td> + <td>//input[@name='field_my_title']</td> + <td>Foo Title 123</td> </tr> <tal:block tal:define="notification_configuration python: {'class': 'error', diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_page_templates_zuite/testFormViewEditablePersistent.zpt b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_page_templates_zuite/testFormViewEditablePersistent.zpt index 055f93506b..53bff83c13 100644 --- a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_page_templates_zuite/testFormViewEditablePersistent.zpt +++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_page_templates_zuite/testFormViewEditablePersistent.zpt @@ -21,27 +21,24 @@ <td>renderjs_url</td></tr> <tr><td>open</td> <td>${renderjs_url}/#/foo_module/1?editable=true</td><td></td></tr> +<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_app_loaded" /> <tr><td>waitForElementPresent</td> <td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_pt_form_view_editable.html']</td><td></td></tr> <tr><td>verifyElementNotPresent</td> <td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_pt_form_view.html']</td><td></td></tr> -<!-- Unsuccessful save does not mingle with editability --> +<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/go_to_foo_relation_field_view" /> <tr><td>waitForElementPresent</td> - <td>//input[@name='field_my_foo_category_title']</td><td></td></tr> -<tr><td>type</td> - <td>//input[@name='field_my_foo_category_title']</td> - <td>QWERTY</td></tr> -<tr><td>fireEvent</td> - <td>//input[@name='field_my_foo_category_title']</td> - <td>input</td></tr> -<tr><td>waitForElementPresent</td> - <td>//div[@data-gadget-scope='header']//button[text()='Save' and @type='submit']</td><td></td></tr> -<tr><td>click</td> - <td>//div[@data-gadget-scope='header']//button[text()='Save' and @type='submit']</td><td></td></tr> -<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" /> -<tr><td>waitForTextPresent</td> - <td>Input data has errors.</td><td></td></tr> + <td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_pt_form_view_editable.html']</td><td></td></tr> +<tr><td>verifyElementNotPresent</td> + <td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_pt_form_view.html']</td><td></td></tr> + +<!-- Unsuccessful save does not mingle with editability --> +<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_save" /> +<tal:block tal:define="notification_configuration python: {'class': 'error', + 'text': 'Input data has errors.'}"> + <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_notification" /> +</tal:block> <tr><td>waitForElementPresent</td> <td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_pt_form_view_editable.html']</td><td></td></tr> @@ -54,22 +51,23 @@ <tr><td>fireEvent</td> <td>//input[@name='field_my_foo_category_title']</td> <td>focus</td></tr> -<tr><td>waitForElementPresent</td> - <td>//div[@data-gadget-scope='field_my_foo_category_title']//li</td><td></td></tr> <tr><td>type</td> <td>//input[@name='field_my_foo_category_title']</td> - <td></td></tr> + <td>object_exchange</td></tr> <tr><td>fireEvent</td> <td>//input[@name='field_my_foo_category_title']</td> <td>input</td></tr> -<tr><td>fireEvent</td> - <td>//input[@name='field_my_foo_category_title']</td> - <td>blur</td></tr> <tr> <td>waitForElementPresent</td> - <td>//button[@data-i18n='Save'][contains(@class, 'ui-icon-warning')]</td> + <td>//li[@data-relative-url='portal_categories/action_type/object_exchange']</td> <td></td> </tr> +<tr> + <td>click</td> + <td>//li[@data-relative-url='portal_categories/action_type/object_exchange']</td> + <td></td> +</tr> + <tr><td>waitForElementPresent</td> <td>//input[@name='field_my_title']</td><td></td></tr> <tr><td>type</td> @@ -98,8 +96,8 @@ <tr><td>type</td> <td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_pt_form_dialog.html']//textarea</td> <td>QWERTY</td></tr> -<tr><td>click</td> - <td>//div[@data-gadget-url='${renderjs_url}/gadget_erp5_pt_form_dialog.html']//input[@type='submit']</td><td></td></tr> +<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/submit_dialog" /> + <tal:block tal:define="notification_configuration python: {'class': 'success', 'text': 'Status changed.'}"> <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_notification" /> diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_relation_field_zuite/testRelationFieldNothingSelectedInList.zpt b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_relation_field_zuite/testRelationFieldNothingSelectedInList.zpt index 6f887b2b34..ec63c3eab5 100644 --- a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_relation_field_zuite/testRelationFieldNothingSelectedInList.zpt +++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_relation_field_zuite/testRelationFieldNothingSelectedInList.zpt @@ -29,8 +29,10 @@ <td>${base_url}/web_site_module/renderjs_runner/#/foo_module</td> <td></td> </tr> +<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_app_loaded" /> + <tr> - <td>waitForElementPresent</td> + <td>assertElementPresent</td> <td>//a[@data-i18n='Add']</td> <td></td> </tr> @@ -47,26 +49,8 @@ </tal:block> <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" /> -<tr> - <td>waitForTextPresent</td> - <td>Save</td> - <td></td> -</tr> -<tr> - <td>assertTextPresent</td> - <td>Quantity</td> - <td></td> -</tr> - <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/go_to_foo_relation_field_view" /> - -<tr> - <td>waitForElementPresent</td> - <td>//input[@name='field_my_successor_title']</td> - <td></td> -</tr> - <tr> <td>type</td> <td>//input[@name='field_my_successor_title']</td> @@ -108,19 +92,15 @@ <td>A new foo</td> </tr> +<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_save" /> -<tr> - <td>click</td> - <td>//button[@data-i18n='Save']</td> - <td></td> -</tr> -<tal:block tal:define="notification_configuration python: {'class': 'error', +<!--tal:block tal:define="notification_configuration python: {'class': 'error', 'text': 'Input data has errors.'}"> <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_notification" /> -</tal:block> +</tal:block--> <tr> <td>assertElementPresent</td> - <td>//div[@data-gadget-scope='field_my_successor_title']//span[text()='No such document was found.']</td> + <td>//div[@data-gadget-scope='field_my_successor_title']//span[text()='No such document was found']</td> <td></td> </tr> diff --git a/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUi.zpt b/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUi.zpt index 3273dfeaa3..75d7a46a7f 100644 --- a/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUi.zpt +++ b/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUi.zpt @@ -1,8 +1,8 @@ <tal:block xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal"> - <tal:block metal:define-macro="save"> + <tal:block metal:define-macro="click_save"> <tr> - <td colspan="3"><b>Save</b></td> + <td colspan="3"><b>Click on Save</b></td> </tr> <tr> <td>waitForElementPresent</td> @@ -29,6 +29,12 @@ <td>//button[@data-i18n='Save']</td> <td></td> </tr> + </tal:block> + <tal:block metal:define-macro="save"> + <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_save" /> + <tr> + <td colspan="3"><b>Save</b></td> + </tr> <!-- First loader while calling Base_edit --> <tr> <td>waitForElementPresent</td> -- 2.30.9