Skip to content

Commit dee6a4a

Browse files
hokolomopopro-odoo
authored andcommitted
[FIX] clickable cells: prevent overlap with grid icons
If a cell has both a clickable cell and a clickable grid icon (eg. a link in a cell with a filter icon), clicking the icon would click the clickable cell. With this commit, we reduce the clickable cell size based on the position of the icons on the cell to prevent any overlap. closes #7570 Task: 4930803 X-original-commit: 645e850 Signed-off-by: Pierre Rousseau (pro) <pro@odoo.com>
1 parent 8722bda commit dee6a4a

File tree

2 files changed

+109
-4
lines changed

2 files changed

+109
-4
lines changed

src/components/dashboard/clickable_cell_store.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,18 @@ export class ClickableCellsStore extends SpreadsheetStore {
6060
get clickableCells(): ClickableCell[] {
6161
const cells: ClickableCell[] = [];
6262
const getters = this.getters;
63-
const sheetId = getters.getActiveSheetId();
6463
for (const position of this.getters.getVisibleCellPositions()) {
6564
const item = this.getClickableItem(position);
6665
if (!item) {
6766
continue;
6867
}
6968
const title = typeof item.title === "function" ? item.title(position, getters) : item.title;
70-
const zone = getters.expandZone(sheetId, positionToZone(position));
69+
const rect = this.getClickableCellRect(position);
70+
if (!rect) {
71+
continue;
72+
}
7173
cells.push({
72-
coordinates: getters.getVisibleRect(zone),
74+
coordinates: rect,
7375
position,
7476
action: item.execute,
7577
title: title || "",
@@ -79,4 +81,32 @@ export class ClickableCellsStore extends SpreadsheetStore {
7981
}
8082
return cells;
8183
}
84+
85+
private getClickableCellRect(position: CellPosition): Rect | undefined {
86+
const zone = this.getters.expandZone(position.sheetId, positionToZone(position));
87+
const clickableRect = this.getters.getVisibleRect(zone);
88+
89+
const icons = this.getters.getCellIcons(position);
90+
const iconsAtPosition = {
91+
center: icons.find((icon) => icon.horizontalAlign === "center"),
92+
left: icons.find((icon) => icon.horizontalAlign === "left"),
93+
right: icons.find((icon) => icon.horizontalAlign === "right"),
94+
};
95+
if (iconsAtPosition.center?.onClick) {
96+
return undefined;
97+
}
98+
if (iconsAtPosition.right?.onClick) {
99+
const cellRect = this.getters.getRect(zone);
100+
const iconRect = this.getters.getCellIconRect(iconsAtPosition.right, cellRect);
101+
clickableRect.width -= iconRect.width + iconsAtPosition.right.margin;
102+
}
103+
if (iconsAtPosition.left?.onClick) {
104+
const cellRect = this.getters.getRect(zone);
105+
const iconRect = this.getters.getCellIconRect(iconsAtPosition.left, cellRect);
106+
clickableRect.x += iconRect.width + iconsAtPosition.left.margin;
107+
clickableRect.width -= iconRect.width + iconsAtPosition.left.margin;
108+
}
109+
110+
return clickableRect;
111+
}
82112
}

tests/grid/dashboard_grid_component.test.ts

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { CHECKBOX_CHECKED } from "@odoo/o-spreadsheet-engine/components/icons/icons";
12
import {
23
DEFAULT_CELL_HEIGHT,
34
DEFAULT_CELL_WIDTH,
@@ -6,7 +7,11 @@ import {
67
MIN_CELL_TEXT_MARGIN,
78
} from "@odoo/o-spreadsheet-engine/constants";
89
import { Model } from "@odoo/o-spreadsheet-engine/model";
9-
import { Spreadsheet } from "../../src";
10+
import {
11+
GridIcon,
12+
iconsOnCellRegistry,
13+
} from "@odoo/o-spreadsheet-engine/registries/icons_on_cell_registry";
14+
import { Align, Spreadsheet } from "../../src";
1015
import { toZone } from "../../src/helpers";
1116
import { clickableCellRegistry } from "../../src/registries/cell_clickable_registry";
1217
import {
@@ -221,4 +226,74 @@ describe("Grid component in dashboard mode", () => {
221226
"hello Magical Françoise"
222227
);
223228
});
229+
230+
const TEST_GRID_ICON: GridIcon = {
231+
horizontalAlign: "left",
232+
size: 20,
233+
margin: 2,
234+
type: "debug_icon",
235+
position: { sheetId: "s1", col: 0, row: 0 },
236+
priority: 1,
237+
svg: CHECKBOX_CHECKED,
238+
onClick: () => {},
239+
};
240+
241+
test("Clickable cell size is reduced based on the icon on the cell", async () => {
242+
let horizontalAlign: Exclude<Align, undefined> = "center";
243+
244+
addToRegistry(clickableCellRegistry, "fake", {
245+
condition: (position, getters) => position.row === 0 && position.col === 0,
246+
execute: () => () => {},
247+
sequence: 5,
248+
});
249+
addToRegistry(iconsOnCellRegistry, "test_icon", (getters, position) =>
250+
position.col === 0 && position.row === 0 ? { ...TEST_GRID_ICON, horizontalAlign } : undefined
251+
);
252+
253+
model.updateMode("dashboard");
254+
await nextTick();
255+
256+
expect("div.o-dashboard-clickable-cell").toHaveCount(0); // because center icon => no clickable cell
257+
258+
horizontalAlign = "right";
259+
model.dispatch("EVALUATE_CELLS");
260+
await nextTick();
261+
expect("div.o-dashboard-clickable-cell").toHaveStyle({
262+
left: "0px",
263+
width: DEFAULT_CELL_WIDTH - TEST_GRID_ICON.size - TEST_GRID_ICON.margin + "px",
264+
height: DEFAULT_CELL_HEIGHT + "px",
265+
});
266+
267+
horizontalAlign = "left";
268+
model.dispatch("EVALUATE_CELLS");
269+
await nextTick();
270+
expect("div.o-dashboard-clickable-cell").toHaveStyle({
271+
left: 20 + 2 + "px",
272+
width: DEFAULT_CELL_WIDTH - TEST_GRID_ICON.size - TEST_GRID_ICON.margin + "px",
273+
height: DEFAULT_CELL_HEIGHT + "px",
274+
});
275+
});
276+
277+
test("Clickable cell size is not reduced if the icon has no onClick action", async () => {
278+
addToRegistry(clickableCellRegistry, "fake", {
279+
condition: (position, getters) => position.row === 0 && position.col === 0,
280+
execute: () => () => {},
281+
sequence: 5,
282+
});
283+
addToRegistry(iconsOnCellRegistry, "test_icon", (getters, position) =>
284+
position.col === 0 && position.row === 0
285+
? { ...TEST_GRID_ICON, onClick: undefined }
286+
: undefined
287+
);
288+
289+
model.updateMode("dashboard");
290+
await nextTick();
291+
await nextTick(); // Need to wait one render to have correct grid position with the resize observers
292+
293+
expect("div.o-dashboard-clickable-cell").toHaveStyle({
294+
left: "0px",
295+
width: DEFAULT_CELL_WIDTH + "px",
296+
height: DEFAULT_CELL_HEIGHT + "px",
297+
});
298+
});
224299
});

0 commit comments

Comments
 (0)