summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2018-03-08 10:02:45 +0100
committerGéry Debongnie <ged@odoo.com>2018-03-08 16:48:54 +0100
commitb17ba359db785899d8a219b480f3209a5a2147f4 (patch)
tree2768621aee2662adcddd130aa3d0dfdb6a522c18 /addons/web/static/src/js
parent7ca93cd916a13ee8d46c1685454ae63b606ab547 (diff)
[REF] web,*: introduce the concept of AbstractAction
Before this commit, a client action was simply a subclass of Widget. This is quite simple, but not really enough for the ActionManager. The ActionManager needs to handle client actions in a different way that view actions. Sometimes, it needs to check if a method exists before calling it. With this commit, we introduce a new abstraction: the AbstractAction class, which defines a common API for all actions managed by the web client. Note that the API proposed in this commit is just the beginning. We will introduce other methods in the future, to manage the focus, or the scroll position, for example.
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/apps.js4
-rw-r--r--addons/web/static/src/js/chrome/abstract_action.js67
-rw-r--r--addons/web/static/src/js/chrome/action_manager.js23
-rw-r--r--addons/web/static/src/js/report/client_action.js4
-rw-r--r--addons/web/static/src/js/views/abstract_controller.js20
-rw-r--r--addons/web/static/src/js/widgets/change_password.js4
6 files changed, 91 insertions, 31 deletions
diff --git a/addons/web/static/src/js/apps.js b/addons/web/static/src/js/apps.js
index fa513372269..c49e4741093 100644
--- a/addons/web/static/src/js/apps.js
+++ b/addons/web/static/src/js/apps.js
@@ -1,16 +1,16 @@
odoo.define('web.Apps', function (require) {
"use strict";
+var AbstractAction = require('web.AbstractAction');
var core = require('web.core');
var framework = require('web.framework');
var session = require('web.session');
-var Widget = require('web.Widget');
var _t = core._t;
var apps_client = null;
-var Apps = Widget.extend({
+var Apps = AbstractAction.extend({
template: 'EmptyComponent',
remote_action_tag: 'loempia.embed',
failback_action_id: 'base.open_module_tree',
diff --git a/addons/web/static/src/js/chrome/abstract_action.js b/addons/web/static/src/js/chrome/abstract_action.js
new file mode 100644
index 00000000000..eb305b3a0d0
--- /dev/null
+++ b/addons/web/static/src/js/chrome/abstract_action.js
@@ -0,0 +1,67 @@
+odoo.define('web.AbstractAction', function (require) {
+"use strict";
+
+/**
+ * We define here the generic notion of Action (from the point of view of the
+ * web client). In short, an action is a widget which controls the main part
+ * of the screen (everything below the control panel).
+ *
+ * More precisely, the action manager is the component that coordinates a stack
+ * of actions. Whenever the user navigates in the interface, switches views,
+ * open different menus, the action manager creates/updates/destroys special
+ * widgets which are actions. These actions need to answer to a standardised
+ * API, which is the reason this AbstractAction class.
+ *
+ * In practice, most actions are view controllers (coming from a
+ * ir.action.act_window). However, some actions are 'client actions'. They
+ * also need to be an AbstractAction for a better cooperation with the action
+ * manager.
+ *
+ * @module web.AbstractAction
+ */
+
+var Widget = require('web.Widget');
+
+var AbstractAction = Widget.extend({
+
+ /**
+ * Called each time the action is attached into the DOM.
+ */
+ on_attach_callback: function () {},
+ /**
+ * Called each time the action is detached from the DOM.
+ */
+ on_detach_callback: function () {},
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * In some situations, we need confirmation from the controller that the
+ * current state can be destroyed without prejudice to the user. For
+ * example, if the user has edited a form, maybe we should ask him if we
+ * can discard all his changes when we switch to another action. In that
+ * case, the action manager will call this method. If the returned
+ * deferred is succesfully resolved, then we can destroy the current action,
+ * otherwise, we need to stop.
+ *
+ * @returns {Deferred} resolved if the action can be removed, rejected otherwise
+ */
+ canBeRemoved: function () {
+ return $.when();
+ },
+ /**
+ * Renders the buttons to append, in most cases, to the control panel (in
+ * the bottom left corner). When the action is rendered in a dialog, those
+ * buttons might be moved to the dialog's footer.
+ *
+ * @param {jQuery Node} $node
+ */
+ renderButtons: function ($node) {
+ },
+});
+
+return AbstractAction;
+
+});
diff --git a/addons/web/static/src/js/chrome/action_manager.js b/addons/web/static/src/js/chrome/action_manager.js
index 1651e5d72d9..e213b55189d 100644
--- a/addons/web/static/src/js/chrome/action_manager.js
+++ b/addons/web/static/src/js/chrome/action_manager.js
@@ -9,6 +9,7 @@ odoo.define('web.ActionManager', function (require) {
* coordinated.
*/
+var AbstractAction = require('web.AbstractAction');
var Bus = require('web.Bus');
var concurrency = require('web.concurrency');
var Context = require('web.Context');
@@ -79,7 +80,7 @@ var ActionManager = Widget.extend({
on_attach_callback: function() {
this.isInDOM = true;
var currentController = this.getCurrentController();
- if (currentController && currentController.widget.on_attach_callback) {
+ if (currentController) {
currentController.widget.on_attach_callback();
}
},
@@ -89,7 +90,7 @@ var ActionManager = Widget.extend({
on_detach_callback: function() {
this.isInDOM = false;
var currentController = this.getCurrentController();
- if (currentController && currentController.widget.on_detach_callback) {
+ if (currentController) {
currentController.widget.on_detach_callback();
}
},
@@ -109,13 +110,8 @@ var ActionManager = Widget.extend({
*/
clearUncommittedChanges: function () {
var currentController = this.getCurrentController();
- // AAB: with AbstractAction, the second part of the condition won't be
- // necessary anymore, as there will be such a function it its API
- if (currentController && currentController.widget.discardChanges) {
- return currentController.widget.discardChanges(undefined, {
- // AAB: get rid of this option when on_hashchange mechanism is improved
- readonlyIfRealDiscard: true,
- });
+ if (currentController) {
+ return currentController.widget.canBeRemoved();
}
return $.when();
},
@@ -405,11 +401,7 @@ var ActionManager = Widget.extend({
in_DOM: true,
callbacks: [{widget: dialog}],
});
- // AAB: renderButtons will be a function of AbstractAction, so this
- // test won't be necessary anymore
- if (widget.renderButtons) {
- widget.renderButtons(dialog.$footer);
- }
+ widget.renderButtons(dialog.$footer);
self.currentDialogController = controller;
@@ -435,6 +427,9 @@ var ActionManager = Widget.extend({
console.error("Could not find client action " + action.tag, action);
return $.Deferred().reject();
}
+ if (!(ClientAction.prototype instanceof AbstractAction)) {
+ console.warn('The client action ' + action.tag + ' should be an instance of AbstractAction!');
+ }
if (!(ClientAction.prototype instanceof Widget)) {
// the client action might be a function, which is executed and
// whose returned value might be another action to execute
diff --git a/addons/web/static/src/js/report/client_action.js b/addons/web/static/src/js/report/client_action.js
index 2fd2ccd44b3..7041913c286 100644
--- a/addons/web/static/src/js/report/client_action.js
+++ b/addons/web/static/src/js/report/client_action.js
@@ -1,11 +1,11 @@
odoo.define('report.client_action', function (require) {
'use strict';
+var AbstractAction = require('web.AbstractAction');
var config = require('web.config');
var core = require('web.core');
var ControlPanelMixin = require('web.ControlPanelMixin');
var session = require('web.session');
-var Widget = require('web.Widget');
var utils = require('report.utils');
var QWeb = core.qweb;
@@ -17,7 +17,7 @@ var AUTHORIZED_MESSAGES = [
'report:do_action',
];
-var ReportAction = Widget.extend(ControlPanelMixin, {
+var ReportAction = AbstractAction.extend(ControlPanelMixin, {
template: 'report.client_action',
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js
index f1356f72a81..995a5102c37 100644
--- a/addons/web/static/src/js/views/abstract_controller.js
+++ b/addons/web/static/src/js/views/abstract_controller.js
@@ -14,11 +14,11 @@ odoo.define('web.AbstractController', function (require) {
var ControlPanelMixin = require('web.ControlPanelMixin');
var core = require('web.core');
-var Widget = require('web.Widget');
+var AbstractAction = require('web.AbstractAction');
var QWeb = core.qweb;
-var AbstractController = Widget.extend(ControlPanelMixin, {
+var AbstractController = AbstractAction.extend(ControlPanelMixin, {
custom_events: {
open_record: '_onOpenRecord',
switch_view: '_onSwitchView',
@@ -108,6 +108,13 @@ var AbstractController = Widget.extend(ControlPanelMixin, {
//--------------------------------------------------------------------------
/**
+ * @override
+ */
+ canBeRemoved: function () {
+ // AAB: get rid of this option when on_hashchange mechanism is improved
+ return this.discardChanges(undefined, {readonlyIfRealDiscard: true});
+ },
+ /**
* Discards the changes made on the record associated to the given ID, or
* all changes made by the current controller if no recordID is given. For
* example, when the user opens the 'home' screen, the action manager calls
@@ -168,15 +175,6 @@ var AbstractController = Widget.extend(ControlPanelMixin, {
return this.update(params || {});
},
/**
- * Renders the buttons to append, in most cases, to the control panel (in
- * the bottom left corner). When the view is rendered in a dialog, those
- * buttons might be moved to the dialog's footer.
- *
- * @param {jQuery Node} $node
- */
- renderButtons: function ($node) {
- },
- /**
* For views that require a pager, this method will be called to allow the
* controller to instantiate and render a pager. Note that in theory, the
* controller can actually render whatever he wants in the pager zone. If
diff --git a/addons/web/static/src/js/widgets/change_password.js b/addons/web/static/src/js/widgets/change_password.js
index b71ae4aaf4b..c05fa30408b 100644
--- a/addons/web/static/src/js/widgets/change_password.js
+++ b/addons/web/static/src/js/widgets/change_password.js
@@ -6,14 +6,14 @@ odoo.define('web.ChangePassword', function (require) {
* allows the user to change his password.
*/
+var AbstractAction = require('web.AbstractAction');
var core = require('web.core');
var Dialog = require('web.Dialog');
-var Widget = require('web.Widget');
var web_client = require('web.web_client');
var _t = core._t;
-var ChangePassword = Widget.extend({
+var ChangePassword = AbstractAction.extend({
template: "ChangePassword",
/**