summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorJulien Mougenot <jum@odoo.com>2019-09-18 10:25:59 +0000
committerAaron Bohy <aab@odoo.com>2019-09-25 07:20:36 +0000
commitf328b9ca8ce9ef3a8aaa4ce7c513ba7c01929e62 (patch)
tree1008549f4a98cf229dff6498ad0d36f71322a10a /addons/web/static/src
parent6fea5b42d6ddabb83daf95b8d68021b05144cf42 (diff)
[IMP] web: list multi edition confirmation modal
Changed the information dipslayed by the confirmation modal in multi edition in list views. Before this commit, the modal simply showed a one-line message with the amount of valid records. Now, there are 3 elements: - If all of the fields cannot be changed, a first line warns the amount of valid records. - A second (or first if all fields can be updated) line ensuring that the user is aware of the occuring changes. - A table displaying the affected field and the updated value (readonly widget with the new value). Part of task 1967602
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/views/list/list_confirm_dialog.js78
-rw-r--r--addons/web/static/src/js/views/list/list_controller.js69
-rw-r--r--addons/web/static/src/scss/modal.scss11
-rw-r--r--addons/web/static/src/xml/base.xml28
4 files changed, 148 insertions, 38 deletions
diff --git a/addons/web/static/src/js/views/list/list_confirm_dialog.js b/addons/web/static/src/js/views/list/list_confirm_dialog.js
new file mode 100644
index 00000000000..8ed07a73ca0
--- /dev/null
+++ b/addons/web/static/src/js/views/list/list_confirm_dialog.js
@@ -0,0 +1,78 @@
+odoo.define('web.ListConfirmDialog', function (require) {
+"use strict";
+
+const core = require('web.core');
+const Dialog = require('web.Dialog');
+
+const _t = core._t;
+const qweb = core.qweb;
+
+/**
+ * Multi edition confirmation modal for list views.
+ *
+ * Handles the display of the amount of changed records (+ valid ones) and
+ * of the widget representing the new value.
+ *
+ * @class
+ */
+const ListConfirmDialog = Dialog.extend({
+ /**
+ * @constructor
+ * @override
+ * @param {Widget} parent
+ * @param {Object} record edited record with updated value
+ * @param {Object} changes changes registered by the list controller
+ * @param {string} changes.fieldLabel label of the changed field
+ * @param {string} changes.fieldName technical name of the changed field
+ * @param {number} changes.nbRecords number of records (total)
+ * @param {number} changes.nbValidRecords number of valid records
+ * @param {Object} [options]
+ */
+ init: function (parent, record, changes, options) {
+ options = Object.assign({}, options, {
+ $content: $(qweb.render('ListView.confirmModal', { changes })),
+ buttons: options.buttons || [{
+ text: _t("Ok"),
+ classes: 'btn-primary',
+ close: true,
+ click: options.confirm_callback,
+ }, {
+ text: _t("Cancel"),
+ close: true,
+ click: options.cancel_callback,
+ }],
+ onForceClose: options.cancel_callback,
+ size: options.size || 'medium',
+ title: options.title || _t("Confirmation"),
+ });
+
+ this._super(parent, options);
+
+ const Widget = record.fieldsInfo.list[changes.fieldName].Widget;
+ this.fieldWidget = new Widget(this, changes.fieldName, record, {
+ mode: 'readonly',
+ viewType: 'list',
+ noOpen: true,
+ });
+ },
+ /**
+ * @override
+ */
+ willStart: function () {
+ return Promise.all([
+ this.fieldWidget.appendTo(document.createDocumentFragment()),
+ this._super.apply(this, arguments)
+ ]);
+ },
+ /**
+ * @override
+ */
+ start: function () {
+ this.$content.find('.o_changes_widget').replaceWith(this.fieldWidget.$el);
+ return this._super.apply(this, arguments);
+ },
+});
+
+return ListConfirmDialog;
+
+});
diff --git a/addons/web/static/src/js/views/list/list_controller.js b/addons/web/static/src/js/views/list/list_controller.js
index 9921b52b52c..309550e86bb 100644
--- a/addons/web/static/src/js/views/list/list_controller.js
+++ b/addons/web/static/src/js/views/list/list_controller.js
@@ -11,6 +11,7 @@ var core = require('web.core');
var BasicController = require('web.BasicController');
var DataExport = require('web.DataExport');
var Dialog = require('web.Dialog');
+var ListConfirmDialog = require('web.ListConfirmDialog');
var Sidebar = require('web.Sidebar');
var _t = core._t;
@@ -396,62 +397,54 @@ var ListController = BasicController.extend({
* @returns {Promise}
*/
_saveMultipleRecords: function (recordId, node, changes) {
- var self = this;
var fieldName = Object.keys(changes)[0];
var value = Object.values(changes)[0];
var recordIds = _.union([recordId], this.selectedRecords);
- var validRecordIds = recordIds.reduce(function (result, nextRecordId) {
- var record = self.model.get(nextRecordId);
- var modifiers = self.renderer._registerModifiers(node, record);
+ var validRecordIds = recordIds.reduce((result, nextRecordId) => {
+ var record = this.model.get(nextRecordId);
+ var modifiers = this.renderer._registerModifiers(node, record);
if (!modifiers.readonly && (!modifiers.required || value)) {
result.push(nextRecordId);
}
return result;
}, []);
- const nbInvalid = recordIds.length - validRecordIds.length;
-
return new Promise((resolve, reject) => {
- const rejectAndDiscard = () => {
+ const discardAndReject = () => {
this.model.discardChanges(recordId);
- return this._confirmSave(recordId).then(reject);
+ this._confirmSave(recordId).then(() => {
+ this.renderer.focusCell(recordId, node);
+ reject();
+ });
};
- let dialog;
if (validRecordIds.length > 0) {
- let message;
- if (nbInvalid === 0) {
- message = _.str.sprintf(
- _t("Do you want to set the value on the %d selected records?"),
- validRecordIds.length);
- } else {
- message = _.str.sprintf(
- _t("Do you want to set the value on the %d valid selected records? (%d invalid)"),
- validRecordIds.length, nbInvalid);
- }
- dialog = Dialog.confirm(this, message, {
+ const dialogOptions = {
confirm_callback: () => {
- return this.model.saveRecords(recordId, validRecordIds, fieldName)
+ this.model.saveRecords(recordId, validRecordIds, fieldName)
.then(async () => {
this._updateButtons('readonly');
const state = this.model.get(this.handle);
- await this.renderer.updateState(state, {keepWidths: true});
+ await this.renderer.updateState(state, { keepWidths: true });
+ await this.renderer.focusCell(recordId, node);
resolve(Object.keys(changes));
})
- .guardedCatch(rejectAndDiscard);
+ .guardedCatch(discardAndReject);
},
- cancel_callback: rejectAndDiscard,
- });
+ cancel_callback: discardAndReject,
+ };
+ const record = this.model.get(recordId);
+ const dialogChanges = {
+ fieldLabel: node.attrs.string || record.fields[fieldName].string,
+ fieldName: node.attrs.name,
+ nbRecords: recordIds.length,
+ nbValidRecords: validRecordIds.length,
+ };
+ new ListConfirmDialog(this, record, dialogChanges, dialogOptions)
+ .open({ shouldFocusButtons: true });
} else {
- dialog = Dialog.alert(this, _t("No valid record to save"), {
- confirm_callback: rejectAndDiscard,
+ Dialog.alert(this, _t("No valid record to save"), {
+ confirm_callback: discardAndReject,
});
}
- dialog.on('closed', this, async () => {
- // we need to wait for the dialog to be actually closed, but
- // the 'closed' event is triggered just before, and it prevents
- // from focussing the cell
- await Promise.resolve();
- this.renderer.focusCell(recordId, node);
- });
});
},
/**
@@ -750,14 +743,14 @@ var ListController = BasicController.extend({
* @param {OdooEvent} ev
*/
_onSetDirty: function (ev) {
- var self = this;
var recordId = ev.data.dataPointID;
if (this.renderer.inMultipleRecordEdition(recordId)) {
ev.stopPropagation();
Dialog.alert(this, _t("No valid record to save"), {
- confirm_callback: function () {
- self.model.discardChanges(recordId);
- self._confirmSave(recordId);
+ confirm_callback: async () => {
+ this.model.discardChanges(recordId);
+ await this._confirmSave(recordId);
+ this.renderer.focusCell(recordId, ev.target.__node);
},
});
} else {
diff --git a/addons/web/static/src/scss/modal.scss b/addons/web/static/src/scss/modal.scss
index e7243042d35..3463d9e20ac 100644
--- a/addons/web/static/src/scss/modal.scss
+++ b/addons/web/static/src/scss/modal.scss
@@ -27,6 +27,17 @@
.o_view_nocontent {
position: unset;
}
+
+ .o_modal_changes td {
+ &:first-child {
+ padding-right: 10px;
+ vertical-align: top;
+ white-space: nowrap;
+ }
+ &:not(:first-child) {
+ width: 100%;
+ }
+ }
}
.modal-footer {
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 5ea1a8e535c..bd4284b0b07 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -281,6 +281,34 @@
</div>
</t>
+<t t-name="ListView.confirmModal">
+ <main role="alert">
+ <p>
+ <t t-if="changes.nbRecords != changes.nbValidRecords">
+ Among the <t t-raw="changes.nbRecords"/> selected records,
+ <t t-raw="changes.nbValidRecords"/> are valid for this update.<br/>
+ </t>
+ Are you sure you want to perform the following update on those <t t-raw="changes.nbValidRecords"/> records ?
+ </p>
+ <div class="table-responsive">
+ <table class="o_modal_changes">
+ <tbody>
+ <tr>
+ <td>Field:</td>
+ <td><t t-raw="changes.fieldLabel"/></td>
+ </tr>
+ <tr>
+ <td>Update to:</td>
+ <td>
+ <div class="o_changes_widget"/>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </main>
+</t>
+
<t t-name="FormView.buttons">
<div class="o_form_buttons_view" role="toolbar" aria-label="Main actions">
<button t-if="widget.is_action_enabled('edit')" type="button"