[IMP] web: allow custom state in action mixin
Sometimes, it might be useful for an action (e.g. a client action, although this may be used by standard views as well) to include custom values in its state. Since the state of a 'fullscreen' action is pushed in the URL, this means that it is possible for the action to resume its state properly upon refresh of the page (before this commit, only some standard information were pushed to the state - action_id, menu_id, etc. for window actions and action's name, active_id, active_ids for client actions). By implementing the `getState` method, an extension of the action mixin can thus push any state it wishes to the URL. closes odoo/odoo#39529 Signed-off-by: Damien Bouvy (dbo) <dbo@odoo.com>
This commit is contained in:
@@ -450,9 +450,6 @@ var ActionManager = Widget.extend({
|
||||
action.controllerID = controllerID;
|
||||
var prom = this._executeAction(action, options);
|
||||
prom.then(function () {
|
||||
// AAB: this should be done automatically in AbstractAction, so that
|
||||
// it can be overridden by actions that have specific stuff to push
|
||||
// (e.g. Discuss, Views)
|
||||
self._pushState(controllerID, {});
|
||||
});
|
||||
return prom;
|
||||
@@ -625,6 +622,7 @@ var ActionManager = Widget.extend({
|
||||
state.active_ids = action.context.active_ids.join(',');
|
||||
}
|
||||
}
|
||||
state = _.extend({}, controller.widget.getState(), state);
|
||||
return state;
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -119,7 +119,6 @@ ActionManager.include({
|
||||
return this.doAction(action, options);
|
||||
}
|
||||
return _super.apply(this, arguments);
|
||||
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -141,6 +141,19 @@ var ActionMixin = {
|
||||
getTitle: function () {
|
||||
return this._title;
|
||||
},
|
||||
/**
|
||||
* Returns a serializable state that will be pushed in the URL by
|
||||
* the action manager, allowing the action to be restarted correctly
|
||||
* upon refresh. This function should be overriden to add extra information.
|
||||
* Note that some keys are reserved by the framework and will thus be
|
||||
* ignored ('action', 'active_id', 'active_ids' and 'title', for all
|
||||
* actions, and 'model' and 'view_type' for act_window actions).
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
getState: function () {
|
||||
return {};
|
||||
},
|
||||
/**
|
||||
* Gives the focus to the action
|
||||
*/
|
||||
|
||||
@@ -331,13 +331,11 @@ var AbstractController = mvc.Controller.extend(ActionMixin, {
|
||||
* example with a new id.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} [state] information that will be pushed to the outside
|
||||
* world
|
||||
*/
|
||||
_pushState: function (state) {
|
||||
_pushState: function () {
|
||||
this.trigger_up('push_state', {
|
||||
controllerID: this.controllerID,
|
||||
state: state || {},
|
||||
state: this.getState(),
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -125,6 +125,17 @@ var FormController = BasicController.extend({
|
||||
getTitle: function () {
|
||||
return this.model.getName(this.handle);
|
||||
},
|
||||
/**
|
||||
* Add the current ID to the state pushed in the url.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
getState: function () {
|
||||
const state = this._super.apply(this, arguments);
|
||||
const env = this.model.get(this.handle, {env: true});
|
||||
state.id = env.currentId;
|
||||
return state;
|
||||
},
|
||||
/**
|
||||
* Render buttons for the control panel. The form view can be rendered in
|
||||
* a dialog, and in that case, if we have buttons defined in the footer, we
|
||||
@@ -421,20 +432,6 @@ var FormController = BasicController.extend({
|
||||
this._super.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* We just add the current ID to the state pushed. This allows the web
|
||||
* client to add it in the url, for example.
|
||||
*
|
||||
* @override method from AbstractController
|
||||
* @private
|
||||
* @param {Object} [state]
|
||||
*/
|
||||
_pushState: function (state) {
|
||||
state = state || {};
|
||||
var env = this.model.get(this.handle, {env: true});
|
||||
state.id = env.currentId;
|
||||
this._super(state);
|
||||
},
|
||||
/**
|
||||
* Overrides to reload the form when saving failed in readonly (e.g. after
|
||||
* a change on a widget like priority or statusbar).
|
||||
|
||||
@@ -1847,12 +1847,22 @@ QUnit.module('ActionManager', {
|
||||
});
|
||||
|
||||
QUnit.test('state is pushed for client actions', async function (assert) {
|
||||
assert.expect(2);
|
||||
assert.expect(3);
|
||||
|
||||
var ClientAction = AbstractAction.extend({});
|
||||
var actionManager = await createActionManager({
|
||||
const ClientAction = AbstractAction.extend({
|
||||
getTitle: function () {
|
||||
return 'a title';
|
||||
},
|
||||
getState: function () {
|
||||
return {foo: 'baz'};
|
||||
}
|
||||
});
|
||||
const actionManager = await createActionManager({
|
||||
intercepts: {
|
||||
push_state: function () {
|
||||
push_state: function (ev) {
|
||||
const expectedState = {action: 'HelloWorldTest', foo: 'baz', title: 'a title'};
|
||||
assert.deepEqual(ev.data.state, expectedState,
|
||||
"should include a complete state description, including custom state");
|
||||
assert.step('push state');
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user