diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/src/js/chrome/action_mixin.js | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/web/static/src/js/chrome/action_mixin.js')
| -rw-r--r-- | addons/web/static/src/js/chrome/action_mixin.js | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/addons/web/static/src/js/chrome/action_mixin.js b/addons/web/static/src/js/chrome/action_mixin.js new file mode 100644 index 00000000..82feba04 --- /dev/null +++ b/addons/web/static/src/js/chrome/action_mixin.js @@ -0,0 +1,235 @@ +odoo.define('web.ActionMixin', function (require) { + "use strict"; + + /** + * We define here the ActionMixin, 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 navbar). + * + * 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 implements the ActionMixin. These actions need to answer to a + * standardised API, which is the reason for this mixin. + * + * In practice, most actions are view controllers (coming from an + * ir.action.act_window). However, some actions are 'client actions'. They + * also need to implement the ActionMixin for a better cooperation with the + * action manager. + * + * @module web.ActionMixin + * @extends WidgetAdapterMixin + */ + + const core = require('web.core'); + const { WidgetAdapterMixin } = require('web.OwlCompatibility'); + + const ActionMixin = Object.assign({}, WidgetAdapterMixin, { + template: 'Action', + + /** + * The action mixin assumes that it is rendered with the 'Action' template. + * This template has a special zone ('.o_content') where the content should + * be added. Actions that want to automatically render a template there + * should define the contentTemplate key. In short, client actions should + * probably define a contentTemplate key, and not a template key. + */ + contentTemplate: null, + + /** + * Events built by and managed by Odoo Framework + * + * It is expected that any Widget Class implementing this mixin + * will also implement the ParentedMixin which actually manages those + */ + custom_events: { + get_controller_query_params: '_onGetOwnedQueryParams', + }, + + /** + * If an action wants to use a control panel, it will be created and + * registered in this _controlPanel key (the widget). The way this control + * panel is created is up to the implementation (so, view controllers or + * client actions may have different needs). + * + * Note that most of the time, this key should be set by the framework, not + * by the code of the client action. + */ + _controlPanel: null, + + /** + * String containing the title of the client action (which may be needed to + * display in the breadcrumbs zone of the control panel). + * + * @see _setTitle + */ + _title: '', + + /** + * @override + */ + renderElement: function () { + this._super.apply(this, arguments); + if (this.contentTemplate) { + const content = core.qweb.render(this.contentTemplate, { widget: this }); + this.$('.o_content').append(content); + } + }, + + /** + * Called by the action manager when action is restored (typically, when + * the user clicks on the action in the breadcrumb) + * + * @returns {Promise|undefined} + */ + willRestore: 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 + * promise is successfully resolved, then we can destroy the current action, + * otherwise, we need to stop. + * + * @returns {Promise} resolved if the action can be removed, rejected + * otherwise + */ + canBeRemoved: function () { + return Promise.resolve(); + }, + + /** + * This function is called when the current state of the action + * should be known. For instance, if the action is a view controller, + * this may be useful to reinstantiate a view in the same state. + * + * Typically the state can (and should) be encoded in a query object of + * the form:: + * + * { + * context: {...}, + * groupBy: [...], + * domain = [...], + * orderedBy = [...], + * } + * + * where the context key can contain many information. + * This method is mainly called during the creation of a custom filter. + * + * @returns {Object} + */ + getOwnedQueryParams: function () { + return {}; + }, + + /** + * 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 {}; + }, + + /** + * Returns a title that may be displayed in the breadcrumb area. For + * example, the name of the record (for a form view). This is actually + * important for the action manager: this is the way it is able to give + * the proper titles for other actions. + * + * @returns {string} + */ + getTitle: function () { + return this._title; + }, + + /** + * 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) { }, + + /** + * Method used to update the widget buttons state. + */ + updateButtons: function () { }, + + /** + * The parameter newProps is used to update the props of + * the controlPanelWrapper before render it. The key 'cp_content' + * is not a prop of the control panel itself. One should if possible use + * the slot mechanism. + * + * @param {Object} [newProps={}] + * @returns {Promise} + */ + updateControlPanel: async function (newProps = {}) { + if (!this.withControlPanel && !this.hasControlPanel) { + return; + } + const props = Object.assign({}, newProps); // Work with a clean new object + if ('title' in props) { + this._setTitle(props.title); + this.controlPanelProps.title = this.getTitle(); + delete props.title; + } + if ('cp_content' in props) { + // cp_content has been updated: refresh it. + this.controlPanelProps.cp_content = Object.assign({}, + this.controlPanelProps.cp_content, + props.cp_content, + ); + delete props.cp_content; + } + // Update props state + Object.assign(this.controlPanelProps, props); + return this._controlPanelWrapper.update(this.controlPanelProps); + }, + + //--------------------------------------------------------------------- + // Private + //--------------------------------------------------------------------- + + /** + * @private + * @param {string} title + */ + _setTitle: function (title) { + this._title = title; + }, + + //--------------------------------------------------------------------- + // Handlers + //--------------------------------------------------------------------- + + /** + * FIXME: this logic should be rethought + * + * Handles a context request: provides to the caller the state of the + * current controller. + * + * @private + * @param {function} callback used to send the requested state + */ + _onGetOwnedQueryParams: function (callback) { + const state = this.getOwnedQueryParams(); + callback(state || {}); + }, + }); + + return ActionMixin; +}); |
