From ca9aebf8c2fcf242fd3be2489d374509dc1ffdb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9mon=20van=20Helden?= Date: Mon, 5 Jul 2021 14:26:33 +0000 Subject: [PATCH] [IMP] web_editor, *: add btn to form editor to redirect in the backend * website, website_form_project In master, there was an error when adding a form to a website and selecting "Create a Task" with no active projects. This issue was solved in PR #73269, by allowing tasks without a project associated. This introduces a new problem: if a user wants to create a project (e.g. if there is no active project), they will have to save their changes, close the editor, navigate to Project, and only then will they be able to do it. This issue could happen for other modules, so the solution has to be generic. In this commit, we add the possibility to add a button to the form editor, next to a we-select item, which will redirect the user to a specified action after prompting them to save their work. This button can be added by specifying an action window in the corresponding registry. We also add the action window to the website form project editor, so that the user can be redirected towards the Project app if they want to create a project to select in their form. task-2580436 closes odoo/odoo#76772 X-original-commit: e4233643b93b521454cc146c6a2ae876781fb9ba Signed-off-by: Romain Derie (rde) --- .../static/src/scss/wysiwyg_snippets.scss | 5 ++ .../src/snippets/s_website_form/options.js | 86 +++++++++++++++++++ .../src/js/website_form_project_editor.js | 1 + 3 files changed, 92 insertions(+) diff --git a/addons/web_editor/static/src/scss/wysiwyg_snippets.scss b/addons/web_editor/static/src/scss/wysiwyg_snippets.scss index 52be5b79c15..3bc87f18f83 100644 --- a/addons/web_editor/static/src/scss/wysiwyg_snippets.scss +++ b/addons/web_editor/static/src/scss/wysiwyg_snippets.scss @@ -883,6 +883,11 @@ body.editor_enable.editor_has_snippets { } } + // Buttons with an icon but no text, so no possible overflow + we-button.o_we_button_icon { + flex: 0 0 auto; + } + // Checkboxes we-button.o_we_checkbox_wrapper.o_we_user_value_widget { min-width: $o-we-sidebar-content-field-toggle-width; diff --git a/addons/website/static/src/snippets/s_website_form/options.js b/addons/website/static/src/snippets/s_website_form/options.js index 81949c1ec78..1106892db7f 100644 --- a/addons/website/static/src/snippets/s_website_form/options.js +++ b/addons/website/static/src/snippets/s_website_form/options.js @@ -4,6 +4,8 @@ odoo.define('website.form_editor', function (require) { const core = require('web.core'); const FormEditorRegistry = require('website.form_editor_registry'); const options = require('web_editor.snippets.options'); +const Dialog = require('web.Dialog'); +const dom = require('web.dom'); require('website.editor.snippets.options'); const qweb = core.qweb; @@ -450,6 +452,55 @@ options.registry.WebsiteFormEditor = FormEditor.extend({ } this._addHiddenField(value, fieldName); }, + /** + * Prompts the user to save changes before being redirected + * towards an action specified in value. + * + * @see this.selectClass for parameters + */ + promptSaveRedirect: function (name, value, widgetValue) { + return new Promise((resolve, reject) => { + const message = _t("Would you like to save before being redirected? Unsaved changes will be discarded."); + Dialog.confirm(this, message, { + cancel_callback: () => resolve(), + buttons: [ + { + text: _t("Save"), + classes: 'btn-primary', + click: (ev) => { + const restore = dom.addButtonLoadingEffect(ev.currentTarget); + this.trigger_up('request_save', { + reload: false, + onSuccess: () => { + this._redirectToAction(value); + }, + onFailure: () => { + restore(); + this.displayNotification({ + message: _t("Something went wrong."), + type: 'danger', + sticky: true, + }); + reject(); + }, + }); + resolve(); + }, + }, { + text: _t("Discard"), + click: (ev) => { + dom.addButtonLoadingEffect(ev.currentTarget); + this._redirectToAction(value); + }, + }, { + text: _t("Cancel"), + close: true, + click: () => resolve(), + }, + ], + }); + }); + }, /** * Changes the onSuccess event. */ @@ -636,8 +687,34 @@ options.registry.WebsiteFormEditor = FormEditor.extend({ button.dataset.addActionField = el.id; selectEl.append(button); }); + if (field.createAction) { + return this._addCreateButton(selectEl, field.createAction); + } return selectEl; }, + /** + * Wraps an HTML element in a we-row element, and adds a + * we-button linking to the given action. + * + * @private + * @param {HTMLElement} element + * @param {String} action + * @returns {HTMLElement} + */ + _addCreateButton: function (element, action) { + const iconEl = document.createElement('i'); + iconEl.classList.add('fa', 'fa-fw', 'fa-plus'); + const linkButtonEl = document.createElement('we-button'); + linkButtonEl.title = _t("Create new"); + linkButtonEl.dataset.noPreview = 'true'; + linkButtonEl.dataset.promptSaveRedirect = action; + linkButtonEl.classList.add('o_we_button_icon'); + linkButtonEl.append(iconEl); + const projectRowEl = document.createElement('we-row'); + projectRowEl.append(element); + projectRowEl.append(linkButtonEl); + return projectRowEl; + }, /** * Apply the model on the form changing it's fields * @@ -706,6 +783,15 @@ options.registry.WebsiteFormEditor = FormEditor.extend({ field.querySelector('.s_website_form_label').appendChild(span); }); }, + /** + * Redirects the user to the page of a specified action. + * + * @private + * @param {string} action + */ + _redirectToAction: function (action) { + window.location.replace(`/web#action=${action}`); + }, //-------------------------------------------------------------------------- // Handlers diff --git a/addons/website_form_project/static/src/js/website_form_project_editor.js b/addons/website_form_project/static/src/js/website_form_project_editor.js index 92b523251f4..df3f9514558 100644 --- a/addons/website_form_project/static/src/js/website_form_project_editor.js +++ b/addons/website_form_project/static/src/js/website_form_project_editor.js @@ -28,6 +28,7 @@ FormEditorRegistry.add('create_task', { type: 'many2one', relation: 'project.project', string: _t('Project'), + createAction: 'project.open_view_project_all', }], });