summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
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",
/**