[FIX] spreadsheet, spreadsheet_dashboard: adapt to spreadsheet last update
closes odoo/odoo#102358 Related: odoo/enterprise#32366 Signed-off-by: Lucas Lefèvre (lul) <lul@odoo.com>
This commit is contained in:
@@ -37,8 +37,14 @@ readonlyAllowedCommands.add("ADD_LIST_DOMAIN");
|
||||
cellMenuRegistry.add("list_see_record", {
|
||||
name: _lt("See record"),
|
||||
sequence: 200,
|
||||
action: SEE_RECORD_LIST,
|
||||
isVisible: SEE_RECORD_LIST_VISIBLE,
|
||||
action: async (env) => {
|
||||
const cell = env.model.getters.getActiveCell();
|
||||
await SEE_RECORD_LIST(cell, env);
|
||||
},
|
||||
isVisible: (env) => {
|
||||
const cell = env.model.getters.getActiveCell();
|
||||
return SEE_RECORD_LIST_VISIBLE(cell);
|
||||
},
|
||||
});
|
||||
|
||||
inverseCommandRegistry
|
||||
|
||||
@@ -5,8 +5,7 @@ import { getFirstListFunction, getNumberOfListFormulas } from "./list_helpers";
|
||||
|
||||
const { astToFormula } = spreadsheet;
|
||||
|
||||
export const SEE_RECORD_LIST = async (env) => {
|
||||
const cell = env.model.getters.getActiveCell();
|
||||
export const SEE_RECORD_LIST = async (cell, env) => {
|
||||
const { col, row, sheetId } = env.model.getters.getCellPosition(cell.id);
|
||||
if (!cell) {
|
||||
return;
|
||||
@@ -31,7 +30,12 @@ export const SEE_RECORD_LIST = async (env) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const SEE_RECORD_LIST_VISIBLE = (env) => {
|
||||
const cell = env.model.getters.getActiveCell();
|
||||
return cell && getNumberOfListFormulas(cell.content) === 1;
|
||||
export const SEE_RECORD_LIST_VISIBLE = (cell) => {
|
||||
return (
|
||||
cell &&
|
||||
cell.evaluated.value !== "" &&
|
||||
!cell.evaluated.error &&
|
||||
getNumberOfListFormulas(cell.content) === 1 &&
|
||||
getFirstListFunction(cell.content).functionName === "ODOO.LIST"
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,47 +14,9 @@ export default class ListUIPlugin extends spreadsheet.UIPlugin {
|
||||
super(getters, history, dispatch, config, selection);
|
||||
/** @type {string} */
|
||||
this.selectedListId = undefined;
|
||||
this.selection.observe(this, {
|
||||
handleEvent: this.handleEvent.bind(this),
|
||||
});
|
||||
this.env = config.evalContext.env;
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "ZonesSelected":
|
||||
if (this.getters.isDashboard()) {
|
||||
const sheetId = this.getters.getActiveSheetId();
|
||||
const { col, row } = event.anchor.cell;
|
||||
const cell = this.getters.getCell(sheetId, col, row);
|
||||
if (cell && cell.content.startsWith("=ODOO.LIST(")) {
|
||||
const { args } = getFirstListFunction(cell.content);
|
||||
const evaluatedArgs = args
|
||||
.map(astToFormula)
|
||||
.map((arg) => this.getters.evaluateFormula(arg));
|
||||
if (evaluatedArgs.length < 3) {
|
||||
return;
|
||||
}
|
||||
const listId = this.getters.getListIdFromPosition(sheetId, col, row);
|
||||
const { model } = this.getters.getListDefinition(listId);
|
||||
const dataSource = this.getters.getListDataSource(listId);
|
||||
const recordId = dataSource.getIdFromPosition(evaluatedArgs[1] - 1);
|
||||
if (!recordId) {
|
||||
return;
|
||||
}
|
||||
this.env.services.action.doAction({
|
||||
type: "ir.actions.act_window",
|
||||
res_model: model,
|
||||
res_id: recordId,
|
||||
views: [[false, "form"]],
|
||||
view_mode: "form",
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a spreadsheet command
|
||||
* @param {Object} cmd Command
|
||||
|
||||
@@ -36,8 +36,14 @@ readonlyAllowedCommands.add("ADD_PIVOT_DOMAIN");
|
||||
cellMenuRegistry.add("pivot_see_records", {
|
||||
name: _lt("See records"),
|
||||
sequence: 175,
|
||||
action: SEE_RECORDS_PIVOT,
|
||||
isVisible: SEE_RECORDS_PIVOT_VISIBLE,
|
||||
action: async (env) => {
|
||||
const cell = env.model.getters.getActiveCell();
|
||||
await SEE_RECORDS_PIVOT(cell, env);
|
||||
},
|
||||
isVisible: (env) => {
|
||||
const cell = env.model.getters.getActiveCell();
|
||||
return SEE_RECORDS_PIVOT_VISIBLE(cell);
|
||||
},
|
||||
});
|
||||
|
||||
inverseCommandRegistry
|
||||
|
||||
@@ -4,8 +4,7 @@ import { getFirstPivotFunction, getNumberOfPivotFormulas } from "./pivot_helpers
|
||||
|
||||
const { astToFormula } = spreadsheet;
|
||||
|
||||
export const SEE_RECORDS_PIVOT = async (env) => {
|
||||
const cell = env.model.getters.getActiveCell();
|
||||
export const SEE_RECORDS_PIVOT = async (cell, env) => {
|
||||
const { col, row, sheetId } = env.model.getters.getCellPosition(cell.id);
|
||||
const { args, functionName } = getFirstPivotFunction(cell.content);
|
||||
const evaluatedArgs = args
|
||||
@@ -36,8 +35,7 @@ export const SEE_RECORDS_PIVOT = async (env) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const SEE_RECORDS_PIVOT_VISIBLE = (env) => {
|
||||
const cell = env.model.getters.getActiveCell();
|
||||
export const SEE_RECORDS_PIVOT_VISIBLE = (cell) => {
|
||||
return (
|
||||
cell &&
|
||||
cell.evaluated.value !== "" &&
|
||||
|
||||
@@ -415,25 +415,6 @@ QUnit.module("spreadsheet > list plugin", {}, () => {
|
||||
assert.deepEqual(model.exportData().lists["1"].domain, [["foo", "in", [55]]]);
|
||||
});
|
||||
|
||||
QUnit.test("Can see record of a list in dashboard mode", async function (assert) {
|
||||
const fakeActionService = {
|
||||
dependencies: [],
|
||||
start: (env) => ({
|
||||
doAction: (params) => {
|
||||
assert.step(params.res_model);
|
||||
assert.step(params.res_id.toString());
|
||||
},
|
||||
}),
|
||||
};
|
||||
registry.category("services").add("action", fakeActionService);
|
||||
const { model } = await createSpreadsheetWithList();
|
||||
model.updateMode("dashboard");
|
||||
const listId = model.getters.getListIds()[0];
|
||||
const dataSource = model.getters.getListDataSource(listId);
|
||||
selectCell(model, "A2");
|
||||
assert.verifySteps(["partner", dataSource.getIdFromPosition(0).toString()]);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Cannot see record of a list in dashboard mode if wrong list formula",
|
||||
async function (assert) {
|
||||
|
||||
@@ -76,13 +76,6 @@ export class SpreadsheetDashboardAction extends Component {
|
||||
this.state = useState({ activeDashboard: undefined });
|
||||
}
|
||||
|
||||
getStyle(model) {
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const { right } = model.getters.getSheetZone(sheetId);
|
||||
const { end } = model.getters.getColDimensions(sheetId, right);
|
||||
return `max-width: ${end}px;`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {number | undefined}
|
||||
*/
|
||||
|
||||
+4
-1
@@ -26,11 +26,14 @@
|
||||
|
||||
.o_renderer {
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
|
||||
.o-spreadsheet {
|
||||
height: 100%;
|
||||
|
||||
.o-grid {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
canvas {
|
||||
border-top: 0px;
|
||||
}
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
<t t-else="">
|
||||
<MobileFigureContainer t-if="env.isSmall" spreadsheetModel="dashboard.model" t-key="dashboard.id"/>
|
||||
<div t-else="" class="o_renderer" t-att-style="getStyle(dashboard.model)">
|
||||
<div t-else="" class="o_renderer">
|
||||
<Spreadsheet
|
||||
model="dashboard.model"
|
||||
t-key="dashboard.id"/>
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { getNumberOfListFormulas } from "@spreadsheet/list/list_helpers";
|
||||
import spreadsheet from "@spreadsheet/o_spreadsheet/o_spreadsheet_extended";
|
||||
import { getNumberOfPivotFormulas } from "@spreadsheet/pivot/pivot_helpers";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
const { Grid } = spreadsheet.components;
|
||||
|
||||
function positionToZone(position) {
|
||||
return { left: position.col, right: position.col, top: position.row, bottom: position.row };
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef ClickableCell
|
||||
* @property {number} left Left position of the cell
|
||||
* @property {number} top Top position of the cell
|
||||
* @property {number} width Width of the cell
|
||||
* @property {number} height Height of the cell
|
||||
* @property {number} key Unique identifier
|
||||
*/
|
||||
|
||||
/* Used for t-key */
|
||||
let key = 0;
|
||||
|
||||
patch(Grid.prototype, "spreadsheet_dashboard_grid_cursor", {
|
||||
getCellClickableStyle(coordinates) {
|
||||
return `
|
||||
top: ${coordinates.top}px;
|
||||
left: ${coordinates.left}px;
|
||||
width: ${coordinates.width}px;
|
||||
height: ${coordinates.height}px;
|
||||
`;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all the boxes for the cell in the sheet view that are clickable.
|
||||
* This function is used to render an overlay over each clickable cell in
|
||||
* order to display a pointer cursor.
|
||||
*
|
||||
* @returns {Array<ClickableCell>}
|
||||
*/
|
||||
getClickableCells() {
|
||||
const cells = [];
|
||||
const sheetId = this.env.model.getters.getActiveSheetId();
|
||||
for (const col of this.env.model.getters.getSheetViewVisibleCols()) {
|
||||
for (const row of this.env.model.getters.getSheetViewVisibleRows()) {
|
||||
const cell = this.env.model.getters.getCell(sheetId, col, row);
|
||||
if (this.isClickable(cell)) {
|
||||
let zone;
|
||||
if (this.env.model.getters.isInMerge(sheetId, col, row)) {
|
||||
zone = this.env.model.getters.getMerge(sheetId, col, row);
|
||||
} else {
|
||||
zone = positionToZone({ col, row });
|
||||
}
|
||||
const rect = this.env.model.getters.getVisibleRect(zone);
|
||||
cells.push({
|
||||
left: rect.x,
|
||||
top: rect.y,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
key: ++key,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return cells;
|
||||
},
|
||||
|
||||
isClickable(cell) {
|
||||
if (!cell) {
|
||||
return false;
|
||||
}
|
||||
// Links
|
||||
if (cell.isLink()) {
|
||||
return true;
|
||||
}
|
||||
// Pivot / Lists
|
||||
if (
|
||||
cell.isFormula() &&
|
||||
cell.evaluated.value !== "" &&
|
||||
!cell.evaluated.error &&
|
||||
(getNumberOfPivotFormulas(cell.content) === 1 ||
|
||||
getNumberOfListFormulas(cell.content) === 1)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
.o-dashboard-clickable-cell {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<odoo>
|
||||
<t t-name="spreadsheet_dashboard.o-spreadsheet-Grid" t-inherit="spreadsheet.o-spreadsheet-Grid" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//div[hasclass('o-grid-overlay')]" position="inside">
|
||||
<div t-if="env.model.getters.isDashboard()"
|
||||
t-foreach="getClickableCells()"
|
||||
t-as="cell"
|
||||
class="o-dashboard-clickable-cell"
|
||||
t-att-style="getCellClickableStyle(cell)"
|
||||
t-key="cell.key"/>
|
||||
</xpath>
|
||||
</t>
|
||||
</odoo>
|
||||
@@ -0,0 +1,12 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { SEE_RECORD_LIST, SEE_RECORD_LIST_VISIBLE } from "@spreadsheet/list/list_actions";
|
||||
import spreadsheet from "@spreadsheet/o_spreadsheet/o_spreadsheet_extended";
|
||||
|
||||
const { clickableCellRegistry } = spreadsheet.registries;
|
||||
|
||||
clickableCellRegistry.add("list", {
|
||||
condition: SEE_RECORD_LIST_VISIBLE,
|
||||
action: SEE_RECORD_LIST,
|
||||
sequence: 10,
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
/** @odoo-module */
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
|
||||
import { SEE_RECORD_LIST, SEE_RECORD_LIST_VISIBLE } from "@spreadsheet/list/list_actions";
|
||||
import spreadsheet from "@spreadsheet/o_spreadsheet/o_spreadsheet_extended";
|
||||
|
||||
const { dashboardMenuRegistry } = spreadsheet.registries;
|
||||
|
||||
dashboardMenuRegistry.add("see_records_list", {
|
||||
name: _lt("See record"),
|
||||
sequence: 20,
|
||||
action: SEE_RECORD_LIST,
|
||||
isReadonlyAllowed: true,
|
||||
isVisible: SEE_RECORD_LIST_VISIBLE,
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import spreadsheet from "@spreadsheet/o_spreadsheet/o_spreadsheet_extended";
|
||||
import { SEE_RECORDS_PIVOT, SEE_RECORDS_PIVOT_VISIBLE } from "@spreadsheet/pivot/pivot_actions";
|
||||
import { getFirstPivotFunction } from "@spreadsheet/pivot/pivot_helpers";
|
||||
|
||||
const { clickableCellRegistry } = spreadsheet.registries;
|
||||
|
||||
clickableCellRegistry.add("pivot", {
|
||||
condition: SEE_RECORDS_PIVOT_VISIBLE,
|
||||
action: SEE_RECORDS_PIVOT,
|
||||
sequence: 3,
|
||||
});
|
||||
|
||||
clickableCellRegistry.add("pivot_set_filter_matching", {
|
||||
condition: (cell, env) => {
|
||||
return (
|
||||
SEE_RECORDS_PIVOT_VISIBLE(cell) &&
|
||||
getFirstPivotFunction(cell.content).functionName === "ODOO.PIVOT.HEADER" &&
|
||||
env.model.getters.getFiltersMatchingPivot(cell.content).length > 0
|
||||
);
|
||||
},
|
||||
action: (cell, env) => {
|
||||
const filters = env.model.getters.getFiltersMatchingPivot(cell.content);
|
||||
env.model.dispatch("SET_MANY_GLOBAL_FILTER_VALUE", { filters });
|
||||
},
|
||||
sequence: 2,
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
/** @odoo-module */
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
|
||||
import { SEE_RECORDS_PIVOT, SEE_RECORDS_PIVOT_VISIBLE } from "@spreadsheet/pivot/pivot_actions";
|
||||
import spreadsheet from "@spreadsheet/o_spreadsheet/o_spreadsheet_extended";
|
||||
|
||||
const { dashboardMenuRegistry } = spreadsheet.registries;
|
||||
|
||||
dashboardMenuRegistry.add("see_records_pivot", {
|
||||
name: _lt("See records"),
|
||||
sequence: 10,
|
||||
action: SEE_RECORDS_PIVOT,
|
||||
isReadonlyAllowed: true,
|
||||
isVisible: SEE_RECORDS_PIVOT_VISIBLE,
|
||||
});
|
||||
+1
-1
@@ -24,7 +24,7 @@ async function createDashboardWithModel(model) {
|
||||
return getFixture();
|
||||
}
|
||||
|
||||
QUnit.module("spreadsheet_dashboard > grid cursor");
|
||||
QUnit.module("spreadsheet_dashboard > clickable cells");
|
||||
|
||||
QUnit.test("A link in a dashboard should be clickable", async (assert) => {
|
||||
const data = {
|
||||
@@ -1,13 +1,10 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { getFixture, click, triggerEvent, legacyExtraNextTick } from "@web/../tests/helpers/utils";
|
||||
import spreadsheet from "@spreadsheet/o_spreadsheet/o_spreadsheet_extended";
|
||||
import { getFixture, click, legacyExtraNextTick } from "@web/../tests/helpers/utils";
|
||||
import { getDashboardServerData } from "../utils/data";
|
||||
import { getBasicData, getBasicListArchs } from "@spreadsheet/../tests/utils/data";
|
||||
import { createSpreadsheetDashboard } from "../utils/dashboard_action";
|
||||
|
||||
const { dashboardMenuRegistry } = spreadsheet.registries;
|
||||
|
||||
QUnit.module("spreadsheet_dashboard > Dashboard > Dashboard action");
|
||||
|
||||
QUnit.test("display available spreadsheets", async (assert) => {
|
||||
@@ -90,15 +87,6 @@ QUnit.test("display error message", async (assert) => {
|
||||
assert.containsNone(fixture, ".o_renderer .error", "It should not display an error");
|
||||
});
|
||||
|
||||
QUnit.test("Dashboard registry contains see records of pivots and lists", (assert) => {
|
||||
const records = dashboardMenuRegistry.getAll();
|
||||
assert.strictEqual(records.length, 2);
|
||||
assert.strictEqual(records[0].id, "see_records_pivot");
|
||||
assert.ok(records[0].isReadonlyAllowed);
|
||||
assert.strictEqual(records[1].id, "see_records_list");
|
||||
assert.ok(records[1].isReadonlyAllowed);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Last selected spreadsheet is kept when go back from breadcrumb",
|
||||
async function (assert) {
|
||||
@@ -145,14 +133,7 @@ QUnit.test(
|
||||
const fixture = getFixture();
|
||||
await createSpreadsheetDashboard({ serverData });
|
||||
await click(fixture, ".o_search_panel li:last-child");
|
||||
const rect = fixture
|
||||
.querySelector(".o-spreadsheet .o-grid-overlay")
|
||||
.getBoundingClientRect();
|
||||
await triggerEvent(fixture, ".o-spreadsheet .o-grid-overlay", "contextmenu", {
|
||||
pageX: 5 + rect.left,
|
||||
pageY: 5 + rect.top,
|
||||
});
|
||||
await click(fixture, ".o-menu-item[data-name='see_records_pivot']");
|
||||
await click(fixture, ".o-dashboard-clickable-cell");
|
||||
await legacyExtraNextTick();
|
||||
assert.containsOnce(fixture, ".o_list_view");
|
||||
await click(document.body.querySelector(".o_back_button"));
|
||||
|
||||
Reference in New Issue
Block a user