Skip to content

Commit

Permalink
[IMP] pivot: select pivot cells in composer
Browse files Browse the repository at this point in the history
With the composer, in selecting mode (=1+ in the composer), clicking on a
cell which is part of a dynamic pivot insert the corresponding pivot
function instead of the reference to the cell.

The rationale is that the pivot is dynamic. Groups can change overtime.
What a cell represent at one moment might be different later.
Let's say you want to reference B2 which contains the total sales of
department A. Later, B2 might be the total sales of department B because
that department is new.

With this commit, instead of directly referencing B2, the formula
=PIVOT.VALUE(1,"sales","Department", "A") is inserted, which specifically
targets the value.

closes #4445

Task: 3899474
Signed-off-by: Pierre Rousseau (pro) <[email protected]>
  • Loading branch information
LucasLefevre authored and pro-odoo committed Jun 19, 2024
1 parent 8a35866 commit 6c4a8e7
Show file tree
Hide file tree
Showing 4 changed files with 309 additions and 9 deletions.
57 changes: 50 additions & 7 deletions src/components/composer/composer/composer_store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
getDateTimeFormat,
localizeFormula,
} from "../../../helpers/locale";
import { makePivotFormulaFromPivotCell } from "../../../helpers/pivot/pivot_helpers";
import { cycleFixedReference } from "../../../helpers/reference_type";
import {
AutoCompleteProvider,
Expand Down Expand Up @@ -583,8 +584,22 @@ export class ComposerStore extends SpreadsheetStore {
private replaceSelectedRange(zone: Zone | UnboundedZone) {
const ref = this.getZoneReference(zone);
const currentToken = this.tokenAtCursor;
const start = currentToken?.type === "REFERENCE" ? currentToken.start : this.selectionStart;
this.replaceText(ref, start, this.selectionEnd);

let replaceStart = this.selectionStart;
if (currentToken?.type === "REFERENCE") {
replaceStart = currentToken.start;
} else if (currentToken?.type === "RIGHT_PAREN") {
// match left parenthesis
const leftParenthesisIndex = this.currentTokens.findIndex(
(token) => token.type === "LEFT_PAREN" && token.parenIndex === currentToken.parenIndex
);
const functionToken = this.currentTokens[leftParenthesisIndex - 1];
if (functionToken === undefined) {
return;
}
replaceStart = functionToken.start;
}
this.replaceText(ref, replaceStart, this.selectionEnd);
}

/**
Expand Down Expand Up @@ -624,6 +639,17 @@ export class ComposerStore extends SpreadsheetStore {
private getZoneReference(zone: Zone | UnboundedZone): string {
const inputSheetId = this.currentEditedCell.sheetId;
const sheetId = this.getters.getActiveSheetId();
if (zone.top === zone.bottom && zone.left === zone.right) {
const position = { sheetId, col: zone.left, row: zone.top };
const pivotId = this.getters.getPivotIdFromPosition(position);
const pivotCell = this.getters.getPivotCellFromPosition(position);
const cell = this.getters.getCell(position);
if (pivotId && pivotCell.type !== "EMPTY" && !cell?.isFormula) {
const formulaPivotId = this.getters.getPivotFormulaId(pivotId);
const formula = makePivotFormulaFromPivotCell(formulaPivotId, pivotCell);
return formula.slice(1); // strip leading =
}
}
const range = this.getters.getRangeFromZone(sheetId, zone);
return this.getters.getSelectionRangeString(range, inputSheetId);
}
Expand Down Expand Up @@ -738,21 +764,38 @@ export class ComposerStore extends SpreadsheetStore {
const colorIndex = this.colorIndexByRange[rangeString];
return colors[colorIndex % colors.length];
};
return this.getReferencedRanges().map((range) => {
const highlights: Highlight[] = [];
for (const range of this.getReferencedRanges()) {
const rangeString = this.getters.getRangeString(range, editionSheetId);
const { numberOfRows, numberOfCols } = zoneToDimension(range.zone);
const zone =
numberOfRows * numberOfCols === 1
? this.getters.expandZone(range.sheetId, range.zone)
: range.zone;

return {
highlights.push({
zone,
color: rangeColor(rangeString),
sheetId: range.sheetId,
interactive: true,
};
});
});
}
const activeSheetId = this.getters.getActiveSheetId();
const selectionZone = this.model.selection.getAnchor().zone;
const isSelectionHightlighted = highlights.find(
(highlight) => highlight.sheetId === activeSheetId && isEqual(highlight.zone, selectionZone)
);
if (this.editionMode === "selecting" && !isSelectionHightlighted) {
highlights.push({
zone: selectionZone,
color: "#445566",
sheetId: activeSheetId,
dashed: true,
interactive: false,
noFill: true,
thinLine: true,
});
}
return highlights;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/helpers/rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export function drawHighlight(
const color = highlight.color || HIGHLIGHT_COLOR;

const { ctx } = renderingContext;
ctx.save();
if (!highlight.noBorder) {
if (highlight.dashed) {
ctx.setLineDash([5, 3]);
Expand All @@ -34,4 +35,5 @@ export function drawHighlight(
ctx.fillStyle = setColorAlpha(toHex(color), highlight.fillAlpha ?? 0.12);
ctx.fillRect(x, y, width, height);
}
ctx.restore();
}
7 changes: 6 additions & 1 deletion src/selection_stream/selection_stream_processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
Zone,
} from "../types";
import { SelectionEvent, SelectionEventOptions } from "../types/event_stream";
import { CellPosition, Dimension, HeaderIndex } from "./../types/misc";
import { CellPosition, Dimension, HeaderIndex, Immutable } from "./../types/misc";
import { EventStream, StreamCallbacks } from "./event_stream";

type Delta = [number, number];
Expand All @@ -39,6 +39,7 @@ type StatefulStream<Event, State> = {
* Allows to select cells in the grid and update the selection
*/
interface SelectionProcessor {
getAnchor(): Immutable<AnchorZone>;
selectZone(anchor: AnchorZone, options?: SelectionEventOptions): DispatchResult;
selectCell(col: number, row: number): DispatchResult;
moveAnchorCell(direction: Direction, step: SelectionStep): DispatchResult;
Expand Down Expand Up @@ -124,6 +125,10 @@ export class SelectionStreamProcessorImpl implements SelectionStreamProcessor {
this.stream.getBackToDefault();
}

getAnchor() {
return this.anchor;
}

private modifyAnchor(
anchor: AnchorZone,
mode: SelectionEvent["mode"],
Expand Down
Loading

0 comments on commit 6c4a8e7

Please sign in to comment.