From 1dedc50d1a175c9140d78ef0f30bf297c2ccef00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Lef=C3=A8vre=20=28lul=29?= Date: Thu, 21 Nov 2024 13:21:26 +0100 Subject: [PATCH] [REF] pivot: extract groupable fields logic --- .../pivot_side_panel_store.ts | 84 ++++--------------- src/helpers/pivot/groupable_fields.ts | 70 ++++++++++++++++ src/index.ts | 2 + 3 files changed, 89 insertions(+), 67 deletions(-) create mode 100644 src/helpers/pivot/groupable_fields.ts diff --git a/src/components/side_panel/pivot/pivot_side_panel/pivot_side_panel_store.ts b/src/components/side_panel/pivot/pivot_side_panel/pivot_side_panel_store.ts index a5fa62d4dd..5c228d8e53 100644 --- a/src/components/side_panel/pivot/pivot_side_panel/pivot_side_panel_store.ts +++ b/src/components/side_panel/pivot/pivot_side_panel/pivot_side_panel_store.ts @@ -1,5 +1,5 @@ -import { deepCopy, deepEquals } from "../../../../helpers"; -import { isDateOrDatetimeField } from "../../../../helpers/pivot/pivot_helpers"; +import { deepEquals } from "../../../../helpers"; +import { GroupableFields } from "../../../../helpers/pivot/groupable_fields"; import { pivotRegistry } from "../../../../helpers/pivot/pivot_registry"; import { Get } from "../../../../store_engine"; import { NotificationStore } from "../../../../stores/notification_store"; @@ -11,7 +11,6 @@ import { PivotCoreMeasure, PivotDimension, PivotField, - PivotFields, PivotMeasure, } from "../../../../types/pivot"; @@ -22,9 +21,16 @@ export class PivotSidePanelStore extends SpreadsheetStore { private draft: PivotCoreDefinition | null = null; private notification = this.get(NotificationStore); private alreadyNotified = false; + private groupableFields: GroupableFields; constructor(get: Get, private pivotId: UID) { super(get); + this.groupableFields = new GroupableFields( + this.fields, + this.dateGranularities, + this.datetimeGranularities, + pivotRegistry.get(this.pivot.type).isGroupable + ); this.updatesAreDeferred = this.getters.getPivotCoreDefinition(this.pivotId).deferUpdates ?? false; } @@ -80,31 +86,9 @@ export class PivotSidePanelStore extends SpreadsheetStore { } get unusedGroupableFields() { - const groupableFields: PivotField[] = []; - const fields = this.fields; - for (const fieldName in fields) { - const field = fields[fieldName]; - if (!field) { - continue; - } - if (pivotRegistry.get(this.pivot.type).isGroupable(field)) { - groupableFields.push(field); - } - } const { columns, rows, measures } = this.definition; - const currentlyUsed = (measures as (PivotMeasure | PivotDimension)[]) - .concat(rows) - .concat(columns) - .map((field) => field.fieldName); - const unusedGranularities = this.unusedGranularities; - return groupableFields - .filter((field) => { - if (isDateOrDatetimeField(field)) { - return !currentlyUsed.includes(field.name) || unusedGranularities[field.name].size > 0; - } - return !currentlyUsed.includes(field.name); - }) - .sort((a, b) => a.string.localeCompare(b.string)); + const dimensions = (measures as (PivotMeasure | PivotDimension)[]).concat(rows).concat(columns); + return this.groupableFields.getUnusedGroupableFields(dimensions); } get datetimeGranularities() { @@ -117,7 +101,6 @@ export class PivotSidePanelStore extends SpreadsheetStore { get unusedGranularities() { return this.getUnusedGranularities( - this.fields, this.draft ?? this.getters.getPivotCoreDefinition(this.pivotId) ); } @@ -199,10 +182,7 @@ export class PivotSidePanelStore extends SpreadsheetStore { if (!this.draft && deepEquals(coreDefinition, cleanedDefinition)) { return; } - const cleanedWithGranularity = this.addDefaultDateTimeGranularity( - this.fields, - cleanedDefinition - ); + const cleanedWithGranularity = this.addDefaultDateTimeGranularity(cleanedDefinition); this.draft = cleanedWithGranularity; if (!this.updatesAreDeferred) { this.applyUpdate(); @@ -222,47 +202,17 @@ export class PivotSidePanelStore extends SpreadsheetStore { return false; } - private addDefaultDateTimeGranularity(fields: PivotFields, definition: PivotCoreDefinition) { + private addDefaultDateTimeGranularity(definition: PivotCoreDefinition) { const { columns, rows } = definition; - const columnsWithGranularity = deepCopy(columns); - const rowsWithGranularity = deepCopy(rows); - const unusedGranularities = this.getUnusedGranularities(fields, definition); - for (const dimension of columnsWithGranularity.concat(rowsWithGranularity)) { - const fieldType = fields[dimension.fieldName]?.type; - if ((fieldType === "date" || fieldType === "datetime") && !dimension.granularity) { - const granularity = - unusedGranularities[dimension.fieldName]?.values().next().value || "year"; - unusedGranularities[dimension.fieldName]?.delete(granularity); - dimension.granularity = granularity; - } - } return { ...definition, - columns: columnsWithGranularity, - rows: rowsWithGranularity, + columns: this.groupableFields.addDefaultDateTimeGranularity(columns), + rows: this.groupableFields.addDefaultDateTimeGranularity(rows), }; } - private getUnusedGranularities( - fields: PivotFields, - definition: PivotCoreDefinition - ): Record> { + private getUnusedGranularities(definition: PivotCoreDefinition): Record> { const { columns, rows } = definition; - const dateFields = columns.concat(rows).filter((dimension) => { - const fieldType = fields[dimension.fieldName]?.type; - return fieldType === "date" || fieldType === "datetime"; - }); - const granularitiesPerFields = {}; - for (const field of dateFields) { - granularitiesPerFields[field.fieldName] = new Set( - fields[field.fieldName]?.type === "date" - ? this.dateGranularities - : this.datetimeGranularities - ); - } - for (const field of dateFields) { - granularitiesPerFields[field.fieldName].delete(field.granularity); - } - return granularitiesPerFields; + return this.groupableFields.getUnusedGranularities(columns.concat(rows)); } } diff --git a/src/helpers/pivot/groupable_fields.ts b/src/helpers/pivot/groupable_fields.ts new file mode 100644 index 0000000000..a9cf61335e --- /dev/null +++ b/src/helpers/pivot/groupable_fields.ts @@ -0,0 +1,70 @@ +import { PivotCoreDimension, PivotField, PivotFields } from "../../types"; +import { deepCopy } from "../misc"; +import { isDateOrDatetimeField } from "./pivot_helpers"; + +export class GroupableFields { + constructor( + private fields: PivotFields, + private dateGranularities: string[], + private datetimeGranularities: string[], + private isGroupable: (field: PivotField) => boolean + ) {} + + getUnusedGroupableFields(dimensions: PivotCoreDimension[]): PivotField[] { + const groupableFields: PivotField[] = []; + const fields = this.fields; + for (const fieldName in fields) { + const field = fields[fieldName]; + if (!field) { + continue; + } + if (this.isGroupable(field)) { + groupableFields.push(field); + } + } + const currentlyUsed = dimensions.map((field) => field.fieldName); + const unusedGranularities = this.getUnusedGranularities(dimensions); + return groupableFields + .filter((field) => { + if (isDateOrDatetimeField(field)) { + return !currentlyUsed.includes(field.name) || unusedGranularities[field.name].size > 0; + } + return !currentlyUsed.includes(field.name); + }) + .sort((a, b) => a.string.localeCompare(b.string)); + } + + getUnusedGranularities(dimensions: PivotCoreDimension[]): Record> { + const dateFields = dimensions.filter((dimension) => { + const fieldType = this.fields[dimension.fieldName]?.type; + return fieldType === "date" || fieldType === "datetime"; + }); + const granularitiesPerFields = {}; + for (const field of dateFields) { + granularitiesPerFields[field.fieldName] = new Set( + this.fields[field.fieldName]?.type === "date" + ? this.dateGranularities + : this.datetimeGranularities + ); + } + for (const field of dateFields) { + granularitiesPerFields[field.fieldName].delete(field.granularity); + } + return granularitiesPerFields; + } + + addDefaultDateTimeGranularity(dimensions: PivotCoreDimension[]) { + const dimensionsWithGranularity = deepCopy(dimensions); + const unusedGranularities = this.getUnusedGranularities(dimensions); + for (const dimension of dimensionsWithGranularity) { + const fieldType = this.fields[dimension.fieldName]?.type; + if ((fieldType === "date" || fieldType === "datetime") && !dimension.granularity) { + const granularity = + unusedGranularities[dimension.fieldName]?.values().next().value || "year"; + unusedGranularities[dimension.fieldName]?.delete(granularity); + dimension.granularity = granularity; + } + } + return dimensionsWithGranularity; + } +} diff --git a/src/index.ts b/src/index.ts index 92d9f87e87..31cb31674a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -115,6 +115,7 @@ import { PivotMeasureDisplayPanelStore } from "./components/side_panel/pivot/piv import { TextInput } from "./components/text_input/text_input"; import * as CHART_HELPERS from "./helpers/figures/charts"; import * as CHART_RUNTIME_HELPERS from "./helpers/figures/charts/runtime"; +import { GroupableFields } from "./helpers/pivot/groupable_fields"; import { areDomainArgsFieldsValid, createPivotFormula, @@ -333,6 +334,7 @@ export const helpers = { insertTokenAfterLeftParenthesis, mergeContiguousZones, getPivotHighlights, + GroupableFields, pivotTimeAdapter, UNDO_REDO_PIVOT_COMMANDS, createPivotFormula,