summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/chrome/action_mixin.js
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/src/js/chrome/action_mixin.js
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (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.js235
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;
+});