Odoo18-Base/addons/board/static/src/board_controller.js
2025-01-06 10:57:38 +07:00

136 lines
5.2 KiB
JavaScript

/** @odoo-module **/
import { _t } from "@web/core/l10n/translation";
import { browser } from "@web/core/browser/browser";
import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
import { Dropdown } from "@web/core/dropdown/dropdown";
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
import { rpc } from "@web/core/network/rpc";
import { useService } from "@web/core/utils/hooks";
import { renderToString } from "@web/core/utils/render";
import { useSortable } from "@web/core/utils/sortable_owl";
import { standardViewProps } from "@web/views/standard_view_props";
import { BoardAction } from "./board_action";
import { blockDom, Component, useState, useRef } from "@odoo/owl";
export class BoardController extends Component {
static template = "board.BoardView";
static components = { BoardAction, Dropdown, DropdownItem };
static props = {
...standardViewProps,
board: Object,
};
setup() {
this.board = useState(this.props.board);
this.dialogService = useService("dialog");
if (this.env.isSmall) {
this.selectLayout("1", false);
} else {
const mainRef = useRef("main");
useSortable({
ref: mainRef,
elements: ".o-dashboard-action",
handle: ".o-dashboard-action-header",
cursor: "move",
groups: ".o-dashboard-column",
connectGroups: true,
onDrop: ({ element, previous, parent }) => {
const fromColIdx = parseInt(element.parentElement.dataset.idx, 10);
const fromActionIdx = parseInt(element.dataset.idx, 10);
const toColIdx = parseInt(parent.dataset.idx, 10);
const toActionIdx = previous ? parseInt(previous.dataset.idx, 10) + 1 : 0;
if (fromColIdx !== toColIdx) {
// to reduce visual flickering
element.classList.add("d-none");
}
this.moveAction(fromColIdx, fromActionIdx, toColIdx, toActionIdx);
},
});
}
}
moveAction(fromColIdx, fromActionIdx, toColIdx, toActionIdx) {
const action = this.board.columns[fromColIdx].actions[fromActionIdx];
if (fromColIdx !== toColIdx) {
// action moving from a column to another
this.board.columns[fromColIdx].actions.splice(fromActionIdx, 1);
this.board.columns[toColIdx].actions.splice(toActionIdx, 0, action);
} else {
// move inside a column
if (fromActionIdx === toActionIdx) {
return;
}
const actions = this.board.columns[fromColIdx].actions;
if (fromActionIdx < toActionIdx) {
actions.splice(toActionIdx + 1, 0, action);
actions.splice(fromActionIdx, 1);
} else {
actions.splice(fromActionIdx, 1);
actions.splice(toActionIdx, 0, action);
}
}
this.saveBoard();
}
selectLayout(layout, save = true) {
const currentColNbr = this.board.colNumber;
const nextColNbr = layout.split("-").length;
if (nextColNbr < currentColNbr) {
// need to move all actions in last cols in the last visible col
const cols = this.board.columns;
const lastVisibleCol = cols[nextColNbr - 1];
for (let i = nextColNbr; i < currentColNbr; i++) {
lastVisibleCol.actions.push(...cols[i].actions);
cols[i].actions = [];
}
}
this.board.layout = layout;
this.board.colNumber = nextColNbr;
if (save) {
this.saveBoard();
}
if (document.querySelector("canvas")) {
// horrible hack to force charts to be recreated so they pick up the
// proper size. also, no idea why raf is needed :(
browser.requestAnimationFrame(() => this.render(true));
}
}
closeAction(column, action) {
this.dialogService.add(ConfirmationDialog, {
body: _t("Are you sure that you want to remove this item?"),
confirm: () => {
const index = column.actions.indexOf(action);
column.actions.splice(index, 1);
this.saveBoard();
},
cancel: () => {},
});
}
toggleAction(action, save = true) {
action.isFolded = !action.isFolded;
if (save) {
this.saveBoard();
}
}
saveBoard() {
const templateFn = renderToString.app.getTemplate("board.arch");
const bdom = templateFn(this.board, {});
const root = document.createElement("rendertostring");
blockDom.mount(bdom, root);
const result = xmlSerializer.serializeToString(root);
const arch = result.slice(result.indexOf("<", 1), result.indexOf("</rendertostring>"));
rpc("/web/view/edit_custom", {
custom_id: this.board.customViewId,
arch,
});
this.env.bus.trigger("CLEAR-CACHES");
}
}
const xmlSerializer = new XMLSerializer();