Skip to content

Commit 4240bc5

Browse files
committed
[IMP] pivot: add support for date(time) measures
With this commit, date and datetime fields are now supported as measures for pivots. closes #5302 Task: 3989393 Signed-off-by: Pierre Rousseau (pro) <[email protected]>
1 parent 361330e commit 4240bc5

File tree

5 files changed

+55
-7
lines changed

5 files changed

+55
-7
lines changed

src/components/side_panel/pivot/pivot_side_panel/pivot_side_panel_store.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,14 @@ export class PivotSidePanelStore extends SpreadsheetStore {
263263
fields: PivotFields,
264264
definition: PivotCoreDefinition
265265
): Record<string, Set<string>> {
266-
const { columns, rows } = definition;
267-
const dateFields = columns.concat(rows).filter((dimension) => {
268-
const fieldType = fields[dimension.fieldName]?.type;
269-
return fieldType === "date" || fieldType === "datetime";
270-
});
266+
const { columns, rows, measures } = definition;
267+
const dateFields = columns
268+
.concat(rows)
269+
.concat(measures)
270+
.filter((dimension) => {
271+
const fieldType = fields[dimension.fieldName]?.type;
272+
return fieldType === "date" || fieldType === "datetime";
273+
});
271274
const granularitiesPerFields = {};
272275
for (const field of dateFields) {
273276
granularitiesPerFields[field.fieldName] = new Set(

src/helpers/pivot/pivot_helpers.ts

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const AGGREGATORS_BY_FIELD_TYPE = {
4343
integer: NUMBER_CHAR_AGGREGATORS,
4444
char: NUMBER_CHAR_AGGREGATORS,
4545
boolean: ["count_distinct", "count", "bool_and", "bool_or"],
46+
datetime: ["max", "min", "count_distinct", "count"],
4647
};
4748

4849
export const AGGREGATORS = {};

src/helpers/pivot/pivot_registry.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,6 @@ pivotRegistry.add("SPREADSHEET", {
5555
onIterationEndEvaluation: (pivot: SpreadsheetPivot) => pivot.markAsDirtyForEvaluation(),
5656
dateGranularities: [...dateGranularities],
5757
datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
58-
isMeasureCandidate: (field: PivotField) => !["datetime", "boolean"].includes(field.type),
58+
isMeasureCandidate: (field: PivotField) => field.type !== "boolean",
5959
isGroupable: () => true,
6060
});

tests/pivots/spreadsheet_pivot/spreadsheet_pivot.test.ts

+29
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,35 @@ describe("Spreadsheet Pivot", () => {
16151615
);
16161616
});
16171617

1618+
test("Pivot with date and datetime measures", () => {
1619+
const model = createModelFromGrid({
1620+
A1: "Date",
1621+
B1: "Datetime",
1622+
A2: "2024/02/03",
1623+
B2: "2024/02/03 12:34:56",
1624+
A3: "2022/04/14",
1625+
B3: "2022/04/14 01:02:03",
1626+
});
1627+
addPivot(model, "A1:B3", {
1628+
columns: [],
1629+
rows: [],
1630+
measures: [
1631+
{ id: "Date:max", fieldName: "Date", aggregator: "max" },
1632+
{ id: "Datetime:max", fieldName: "Datetime", aggregator: "max" },
1633+
{ id: "Date:min", fieldName: "Date", aggregator: "min" },
1634+
{ id: "Datetime:min", fieldName: "Datetime", aggregator: "min" },
1635+
],
1636+
});
1637+
setCellContent(model, "A26", '=PIVOT.VALUE(1,"Date:max")');
1638+
setCellContent(model, "B26", '=PIVOT.VALUE(1,"Datetime:max")');
1639+
setCellContent(model, "A27", '=PIVOT.VALUE(1,"Date:min")');
1640+
setCellContent(model, "B27", '=PIVOT.VALUE(1,"Datetime:min")');
1641+
expect(getEvaluatedCell(model, "A26").formattedValue).toBe("2024/02/03");
1642+
expect(getEvaluatedCell(model, "B26").formattedValue).toBe("2024/02/03 12:34:56");
1643+
expect(getEvaluatedCell(model, "A27").formattedValue).toBe("2022/04/14");
1644+
expect(getEvaluatedCell(model, "B27").formattedValue).toBe("2022/04/14 01:02:03");
1645+
});
1646+
16181647
test("Pivot with measure AVG on text values does not crash", () => {
16191648
const model = createModelFromGrid({ A1: "Customer", A2: "Jean", A3: "Marc" });
16201649
addPivot(model, "A1:A3", {

tests/pivots/spreadsheet_pivot/spreadsheet_pivot_side_panel.test.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ describe("Spreadsheet pivot side panel", () => {
390390
const measures = [...fixture.querySelectorAll(".o-autocomplete-value")].map(
391391
(el) => el.textContent
392392
);
393-
expect(measures).toEqual(["Count", "float", "integer", "text"]);
393+
expect(measures).toEqual(["Count", "date", "datetime", "float", "integer", "text"]);
394394
});
395395

396396
test("defer update option is persistent", async () => {
@@ -431,6 +431,21 @@ describe("Spreadsheet pivot side panel", () => {
431431
]);
432432
});
433433

434+
test("can add a datetime measure", async () => {
435+
setCellContent(model, "A1", "name");
436+
setCellContent(model, "A2", "Alice");
437+
setCellContent(model, "B1", "birthdate");
438+
setCellContent(model, "B2", "1995/12/15");
439+
addPivot(model, "A1:B2", {}, "3");
440+
env.openSidePanel("PivotSidePanel", { pivotId: "3" });
441+
await nextTick();
442+
await click(fixture.querySelector(".o-pivot-measure .add-dimension")!);
443+
await click(fixture.querySelectorAll(".o-autocomplete-value")[0]);
444+
expect(model.getters.getPivotCoreDefinition("3").measures).toEqual([
445+
{ id: "birthdate:count", fieldName: "birthdate", aggregator: "count" },
446+
]);
447+
});
448+
434449
test("should preserve the sorting of the dimension after ordering is changed", async () => {
435450
mockGetBoundingClientRect({
436451
/**

0 commit comments

Comments
 (0)