Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions src/components/figures/figure/figure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
SELECTION_BORDER_COLOR,
} from "../../../constants";
import { figureRegistry } from "../../../registries/index";
import { Store, useStore } from "../../../store_engine";
import { DOMFocusableElementStore } from "../../../stores/DOM_focus_store";
import {
CSSProperties,
DOMCoordinates,
Expand Down Expand Up @@ -115,7 +117,6 @@ css/*SCSS*/ `
interface Props {
figure: Figure;
style: string;
onFigureDeleted: () => void;
onMouseDown: (ev: MouseEvent) => void;
onClickAnchor(dirX: ResizeDirection, dirY: ResizeDirection, ev: MouseEvent): void;
}
Expand All @@ -125,17 +126,16 @@ export class FigureComponent extends Component<Props, SpreadsheetChildEnv> {
static props = {
figure: Object,
style: { type: String, optional: true },
onFigureDeleted: { type: Function, optional: true },
onMouseDown: { type: Function, optional: true },
onClickAnchor: { type: Function, optional: true },
};
static components = { Menu };
static defaultProps = {
onFigureDeleted: () => {},
onMouseDown: () => {},
onClickAnchor: () => {},
};

private DOMFocusableElementStore!: Store<DOMFocusableElementStore>;
private menuState: MenuState = useState({ isOpen: false, position: null, menuItems: [] });

private figureRef = useRef("figure");
Expand Down Expand Up @@ -196,6 +196,7 @@ export class FigureComponent extends Component<Props, SpreadsheetChildEnv> {
}

setup() {
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
const borderWidth = figureRegistry.get(this.props.figure.tag).borderWidth;
this.borderWidth = borderWidth !== undefined ? borderWidth : BORDER_WIDTH;
useEffect(
Expand All @@ -216,7 +217,7 @@ export class FigureComponent extends Component<Props, SpreadsheetChildEnv> {
);

onWillUnmount(() => {
this.props.onFigureDeleted();
this.onFigureDeleted();
});
}

Expand All @@ -239,7 +240,7 @@ export class FigureComponent extends Component<Props, SpreadsheetChildEnv> {
sheetId: this.env.model.getters.getActiveSheetId(),
id: figure.id,
});
this.props.onFigureDeleted();
this.onFigureDeleted();
ev.preventDefault();
ev.stopPropagation();
break;
Expand Down Expand Up @@ -304,6 +305,12 @@ export class FigureComponent extends Component<Props, SpreadsheetChildEnv> {
this.menuState.position = position;
this.menuState.menuItems = figureRegistry
.get(this.props.figure.tag)
.menuBuilder(this.props.figure.id, this.props.onFigureDeleted, this.env);
.menuBuilder(this.props.figure.id, this.onFigureDeleted.bind(this), this.env);
}

private onFigureDeleted() {
if (document.activeElement === this.figureRef.el) {
this.DOMFocusableElementStore.focus();
}
}
}
1 change: 0 additions & 1 deletion src/components/figures/figure/figure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<t
t-component="figureRegistry.get(props.figure.tag).Component"
t-key="props.figure.id"
onFigureDeleted="props.onFigureDeleted"
figure="props.figure"
/>
<div class="o-figure-menu position-absolute m-2" t-if="!env.isDashboard()">
Expand Down
2 changes: 0 additions & 2 deletions src/components/figures/figure_chart/figure_chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@ interface Props {
// props figure is currently necessary scorecards, we need the chart dimension at render to avoid having to force the
// style by hand in the useEffect()
figure: Figure;
onFigureDeleted: () => void;
}

export class ChartFigure extends Component<Props, SpreadsheetChildEnv> {
static template = "o-spreadsheet-ChartFigure";
static props = {
figure: Object,
onFigureDeleted: Function,
};
static components = {};

Expand Down
8 changes: 2 additions & 6 deletions src/components/figures/figure_container/figure_container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ import { FigureComponent } from "../figure/figure";

type ContainerType = "topLeft" | "topRight" | "bottomLeft" | "bottomRight" | "dnd";

interface Props {
onFigureDeleted: () => void;
}
interface Props {}

interface Container {
type: ContainerType;
Expand Down Expand Up @@ -127,9 +125,7 @@ css/*SCSS*/ `
*/
export class FiguresContainer extends Component<Props, SpreadsheetChildEnv> {
static template = "o-spreadsheet-FiguresContainer";
static props = {
onFigureDeleted: Function,
};
static props = {};
static components = { FigureComponent };

dnd = useState<DndState>({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
t-att-style="container.inverseViewportStyle">
<t t-foreach="container.figures" t-as="figure" t-key="figure.id">
<FigureComponent
onFigureDeleted="this.props.onFigureDeleted"
figure="figure"
style="getFigureStyle(figure)"
onMouseDown="(ev) => this.startDraggingFigure(figure, ev)"
Expand Down
2 changes: 0 additions & 2 deletions src/components/figures/figure_image/figure_image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ import { Figure, SpreadsheetChildEnv, UID } from "../../../types";

interface Props {
figure: Figure;
onFigureDeleted: () => void;
}

export class ImageFigure extends Component<Props, SpreadsheetChildEnv> {
static template = "o-spreadsheet-ImageFigure";
static props = {
figure: Object,
onFigureDeleted: Function,
};
static components = {};

Expand Down
1 change: 0 additions & 1 deletion src/components/grid/grid.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
onGridResized.bind="onGridResized"
onGridMoved.bind="moveCanvas"
gridOverlayDimensions="gridOverlayDimensions"
onFigureDeleted.bind="focusDefaultElement"
/>
<HeadersOverlay onOpenContextMenu="(type, x, y) => this.toggleContextMenu(type, x, y)"/>
<GridComposer
Expand Down
26 changes: 17 additions & 9 deletions src/components/grid_add_rows_footer/grid_add_rows_footer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Component, useExternalListener, useRef, useState } from "@odoo/owl";
import { Store, useStore } from "../../store_engine";
import { DOMFocusableElementStore } from "../../stores/DOM_focus_store";
import { _t } from "../../translation";
import { SpreadsheetChildEnv } from "../../types";
import { css, cssPropertiesToCss } from "../helpers";
Expand All @@ -20,23 +22,23 @@ css/* scss */ `
}
`;

interface Props {
focusGrid: () => void;
}
interface Props {}

export class GridAddRowsFooter extends Component<Props, SpreadsheetChildEnv> {
static template = "o-spreadsheet-GridAddRowsFooter";
static props = {
focusGrid: Function,
};
static props = {};
static components = { ValidationMessages };

private DOMFocusableElementStore!: Store<DOMFocusableElementStore>;

inputRef = useRef<HTMLInputElement>("inputRef");
state = useState({
inputValue: "100",
errorFlag: false,
});

setup() {
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
useExternalListener(window, "click", this.onExternalClick, { capture: true });
}

Expand All @@ -58,7 +60,7 @@ export class GridAddRowsFooter extends Component<Props, SpreadsheetChildEnv> {

onKeydown(ev: KeyboardEvent) {
if (ev.key.toUpperCase() === "ESCAPE") {
this.props.focusGrid();
this.focusDefaultElement();
} else if (ev.key.toUpperCase() === "ENTER") {
this.onConfirm();
}
Expand All @@ -85,7 +87,7 @@ export class GridAddRowsFooter extends Component<Props, SpreadsheetChildEnv> {
quantity,
dimension: "ROW",
});
this.props.focusGrid();
this.focusDefaultElement();

// After adding new rows, scroll down to the new last row
const { scrollX } = this.env.model.getters.getActiveSheetDOMScrollInfo();
Expand All @@ -103,6 +105,12 @@ export class GridAddRowsFooter extends Component<Props, SpreadsheetChildEnv> {
if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
return;
}
this.props.focusGrid();
this.focusDefaultElement();
}

private focusDefaultElement() {
if (document.activeElement === this.inputRef.el) {
this.DOMFocusableElementStore.focus();
}
}
}
3 changes: 0 additions & 3 deletions src/components/grid_overlay/grid_overlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ interface Props {
onGridResized: (dimension: Rect) => void;
onGridMoved: (deltaX: Pixel, deltaY: Pixel) => void;
gridOverlayDimensions: string;
onFigureDeleted: () => void;
}

export class GridOverlay extends Component<Props, SpreadsheetChildEnv> {
Expand All @@ -140,7 +139,6 @@ export class GridOverlay extends Component<Props, SpreadsheetChildEnv> {
onCellClicked: { type: Function, optional: true },
onCellRightClicked: { type: Function, optional: true },
onGridResized: { type: Function, optional: true },
onFigureDeleted: { type: Function, optional: true },
onGridMoved: Function,
gridOverlayDimensions: String,
};
Expand All @@ -156,7 +154,6 @@ export class GridOverlay extends Component<Props, SpreadsheetChildEnv> {
onCellClicked: () => {},
onCellRightClicked: () => {},
onGridResized: () => {},
onFigureDeleted: () => {},
};
private gridOverlay: Ref<HTMLElement> = useRef("gridOverlay");
private gridOverlayRect = useAbsoluteBoundingRect(this.gridOverlay);
Expand Down
3 changes: 1 addition & 2 deletions src/components/grid_overlay/grid_overlay.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
t-on-pointerdown="onMouseDown"
t-on-dblclick.self="onDoubleClick"
t-on-contextmenu.stop.prevent="onContextMenu">
<FiguresContainer onFigureDeleted="props.onFigureDeleted"/>
<FiguresContainer/>
<DataValidationOverlay/>
<FilterIconsOverlay/>
<GridAddRowsFooter
t-if="!env.model.getters.isReadonly()"
t-key="env.model.getters.getActiveSheetId()"
focusGrid="props.onFigureDeleted"
/>
</div>
</t>
Expand Down
17 changes: 17 additions & 0 deletions tests/figures/figure_component.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,23 @@ describe("figures", () => {
expect(bottomRightContainerStyle.height).toEqual(`${height - 2 * DEFAULT_CELL_HEIGHT}px`);
});

test("Deleting a figure does not change the DOM focus if the figure was not focused", async () => {
createFigure(model);
await nextTick();
env.openSidePanel("FindAndReplace");
await nextTick();

const panelInput = fixture.querySelector<HTMLElement>(".o-sidePanel input");
panelInput?.focus();
expect(document.activeElement).toBe(panelInput);

const figureId = model.getters.getFigures(sheetId)[0].id;
model.dispatch("DELETE_FIGURE", { sheetId, id: figureId });
await nextTick();

expect(document.activeElement).toBe(panelInput);
});

describe("Figure drag & drop snap", () => {
describe("Move figure", () => {
test.each([
Expand Down