Skip to Content
OWL data_display

Control Panel

Odoo 19 OWL component — Control Panel (search)

Live preview Interactive
Source excerpt web/static/src/search/control_panel/control_panel.js
import { _t } from "@web/core/l10n/translation";
import { browser } from "@web/core/browser/browser";
import { getActiveHotkey } from "@web/core/hotkeys/hotkey_service";
import { Pager } from "@web/core/pager/pager";
import { useService } from "@web/core/utils/hooks";
import { Dropdown } from "@web/core/dropdown/dropdown";
import { useCommand } from "@web/core/commands/command_hook";
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
import { useHotkey } from "@web/core/hotkeys/hotkey_hook";
import { useSortable } from "@web/core/utils/sortable_owl";
import { user } from "@web/core/user";
import { AccordionItem } from "@web/core/dropdown/accordion_item";
import { CheckBox } from "@web/core/checkbox/checkbox";
import { makeContext } from "@web/core/context";
import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
import { Transition } from "@web/core/transition";
import { Breadcrumbs } from "../breadcrumbs/breadcrumbs";
import { SearchBar } from "../search_bar/search_bar";

import { Component, useState, onMounted, useRef, useEffect } from "@odoo/owl";

const STICKY_CLASS = "o_mobile_sticky";

/**
 * @typedef EmbeddedAction
 * @property {number} id
 * @property {[number, string]} parent_action_id
 * @property {string} name
 * @property {number} sequence
 * @property {number} parent_res_id
 * @property {string} parent_res_model
 * @property {[number, string]} action_id
 * @property {string} python_method
 * @property {number} user_id
 * @property {boolean} is_deletable
 * @property {string} default_view_mode
 * @property {string} filter_ids
 * @property {string} domain
 * @property {string} context
 */

class EmbeddedActionsConfigHandler {
    constructor(parentActionId, currentActiveId, parentResModel, ormService) {
        this.parentActionId = parentActionId;
        this.currentActiveId = currentActiveId;
        this.parentResModel = parentResModel;
        this.embeddedActionsKey = `${this.parentActionId}+${this.currentActiveId || ""}`;
        this.embeddedActionsConfig = user.settings.embedded_actions_config_ids || {};
        this.orm = ormService;
    }

    setEmbeddedActionsConfig(config) {
        if (this.embeddedActionsKey in this.embeddedActionsConfig) {
            Object.assign(this.embeddedActionsConfig[this.embeddedActionsKey], config);
        } else {
            this.embeddedActionsConfig[this.embeddedActionsKey] = config;
        }
        this.orm.call("res.users.settings", "set_embedded_actions_setting", [
            user.settings.id,
            this.parentActionId,
            this.currentActiveId,
            config,
        ]);
    }

    getEmbeddedActionsConfig(key) {
        return this.embeddedActionsConfig[this.embeddedActionsKey]?.[key];
    }

    hasEmbeddedActionsConfig() {
        return this.embeddedActionsKey in this.embeddedActionsConfig;
    }

    async fetchEmbeddedActionsConfig() {
        return await this.orm.call(
            "res.users.settings",
            "get_embedded_actions_settings",
            [user.settings.id],
            { context: { res_model: this.parentResModel, res_id: this.currentActiveId } }
        );
    }

    updateEmbeddedActionsConfig(newSettings) {
        for (const key in newSettings) {
            this.embeddedActionsConfig[key] = newSettings[key];
        }
    }
}

export class ControlPanel extends Component {
    static template = "web.ControlPanel";
    static components = {
        Pager,
        SearchBar,
        Dropdown,
        DropdownItem,
        Breadcrumbs,
        AccordionItem,
        CheckBox,
        Transition,
    };
    static props = {
        display: { type: Object, optional: true },
        slots: { type: Object, optional: true },
    };

    setup() {
        this.actionService = useService("action");
        this.pagerProps = this.env.config.pagerProps
            ? useState(this.env.config.pagerProps)
            : undefined;
        this.notificationService = useService("notification");
        this.breadcrumbs = useState(this.env.config.breadcrumbs);
        this.orm = useService("orm");
        this.dialogService = useService("dialog");

        this.root = useRef("root");
        this.newActionNameRef = useRef("newActionNameRef");
        this.defaultEmbeddedActions = this.env.config.embeddedActions;
        if (this.env.config.embeddedActions?.length > 0 && !this.env.config.parentActionId) {
Registry / API
Registry name
ControlPanel
Category
Module
web
Slug
control-panel
Nav group
data_display