Skip to content

Commit

Permalink
[REF] pivot: extract groupable fields logic
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasLefevre committed Nov 21, 2024
1 parent 66e50f9 commit 1dedc50
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -11,7 +11,6 @@ import {
PivotCoreMeasure,
PivotDimension,
PivotField,
PivotFields,
PivotMeasure,
} from "../../../../types/pivot";

Expand All @@ -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;
}
Expand Down Expand Up @@ -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() {
Expand All @@ -117,7 +101,6 @@ export class PivotSidePanelStore extends SpreadsheetStore {

get unusedGranularities() {
return this.getUnusedGranularities(
this.fields,
this.draft ?? this.getters.getPivotCoreDefinition(this.pivotId)
);
}
Expand Down Expand Up @@ -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();
Expand All @@ -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<string, Set<string>> {
private getUnusedGranularities(definition: PivotCoreDefinition): Record<string, Set<string>> {
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));
}
}
70 changes: 70 additions & 0 deletions src/helpers/pivot/groupable_fields.ts
Original file line number Diff line number Diff line change
@@ -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<string, Set<string>> {
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;
}
}
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -333,6 +334,7 @@ export const helpers = {
insertTokenAfterLeftParenthesis,
mergeContiguousZones,
getPivotHighlights,
GroupableFields,
pivotTimeAdapter,
UNDO_REDO_PIVOT_COMMANDS,
createPivotFormula,
Expand Down

0 comments on commit 1dedc50

Please sign in to comment.