Skip to content

Commit

Permalink
feat: support for search in pivot data store (#6172)
Browse files Browse the repository at this point in the history
* Move config out

* Add support for search in pivot data store
  • Loading branch information
djbarnwal authored Nov 26, 2024
1 parent f85c640 commit a3de19c
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 139 deletions.
2 changes: 1 addition & 1 deletion web-common/src/features/dashboards/pivot/PivotTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import { onMount } from "svelte";
import type { Readable } from "svelte/motion";
import { derived } from "svelte/store";
import { getPivotConfig } from "./pivot-data-store";
import { getPivotConfig } from "./pivot-data-config";
import type { PivotDataRow, PivotDataStore } from "./types";
// Distance threshold (in pixels) for triggering data fetch
Expand Down
152 changes: 152 additions & 0 deletions web-common/src/features/dashboards/pivot/pivot-data-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { mergeMeasureFilters } from "@rilldata/web-common/features/dashboards/filters/measure-filters/measure-filter-utils";
import { allDimensions } from "@rilldata/web-common/features/dashboards/state-managers/selectors/dimensions";
import { allMeasures } from "@rilldata/web-common/features/dashboards/state-managers/selectors/measures";
import type { StateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers";
import {
dimensionSearchText,
metricsExplorerStore,
} from "@rilldata/web-common/features/dashboards/stores/dashboard-stores";
import { timeControlStateSelector } from "@rilldata/web-common/features/dashboards/time-controls/time-control-store";
import type { TimeRangeString } from "@rilldata/web-common/lib/time/types";
import { type Readable, derived } from "svelte/store";
import { canEnablePivotComparison, getPivotConfigKey } from "./pivot-utils";
import {
COMPARISON_DELTA,
COMPARISON_PERCENT,
PivotChipType,
type PivotDataStoreConfig,
type PivotTimeConfig,
} from "./types";

let lastKey: string | undefined = undefined;

/**
* Extract out config relevant to pivot from dashboard and meta store
*/
export function getPivotConfig(
ctx: StateManagers,
): Readable<PivotDataStoreConfig> {
return derived(
[
ctx.validSpecStore,
ctx.timeRangeSummaryStore,
ctx.dashboardStore,
dimensionSearchText,
],
([validSpec, timeRangeSummary, dashboardStore, searchText]) => {
if (
!validSpec?.data?.metricsView ||
!validSpec?.data?.explore ||
timeRangeSummary.isFetching
) {
return {
measureNames: [],
rowDimensionNames: [],
colDimensionNames: [],
allMeasures: [],
allDimensions: [],
whereFilter: dashboardStore.whereFilter,
pivot: dashboardStore.pivot,
time: {} as PivotTimeConfig,
comparisonTime: undefined,
enableComparison: false,
searchText,
};
}

const { metricsView, explore } = validSpec.data;

// This indirection makes sure only one update of dashboard store triggers this
const timeControl = timeControlStateSelector([
metricsView,
explore,
timeRangeSummary,
dashboardStore,
]);

const time: PivotTimeConfig = {
timeStart: timeControl.timeStart,
timeEnd: timeControl.timeEnd,
timeZone: dashboardStore?.selectedTimezone || "UTC",
timeDimension: metricsView.timeDimension || "",
};

const enableComparison =
canEnablePivotComparison(
dashboardStore.pivot,
timeControl.comparisonTimeStart,
) && !!timeControl.showTimeComparison;

let comparisonTime: TimeRangeString | undefined = undefined;
if (enableComparison) {
comparisonTime = {
start: timeControl.comparisonTimeStart,
end: timeControl.comparisonTimeEnd,
};
}

const measureNames = dashboardStore.pivot.columns.measure.flatMap((m) => {
const measureName = m.id;
const group = [measureName];

if (enableComparison) {
group.push(
`${measureName}${COMPARISON_DELTA}`,
`${measureName}${COMPARISON_PERCENT}`,
);
}
return group;
});

// This is temporary until we have a better way to handle time grains
const rowDimensionNames = dashboardStore.pivot.rows.dimension.map((d) => {
if (d.type === PivotChipType.Time) {
return `${time.timeDimension}_rill_${d.id}`;
}
return d.id;
});

const colDimensionNames = dashboardStore.pivot.columns.dimension.map(
(d) => {
if (d.type === PivotChipType.Time) {
return `${time.timeDimension}_rill_${d.id}`;
}
return d.id;
},
);

const config: PivotDataStoreConfig = {
measureNames,
rowDimensionNames,
colDimensionNames,
allMeasures: allMeasures({
validMetricsView: metricsView,
validExplore: explore,
}),
allDimensions: allDimensions({
validMetricsView: metricsView,
validExplore: explore,
}),
whereFilter: mergeMeasureFilters(dashboardStore),
pivot: dashboardStore.pivot,
enableComparison,
comparisonTime,
time,
searchText,
};

const currentKey = getPivotConfigKey(config);

if (lastKey !== currentKey) {
// Reset rowPage when pivot config changes
lastKey = currentKey;
if (config.pivot.rowPage !== 1) {
metricsExplorerStore.setPivotRowPage(dashboardStore.name, 1);
config.pivot.rowPage = 1;
}
}

return config;
},
);
}
151 changes: 14 additions & 137 deletions web-common/src/features/dashboards/pivot/pivot-data-store.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { mergeMeasureFilters } from "@rilldata/web-common/features/dashboards/filters/measure-filters/measure-filter-utils";
import { getDimensionFilterWithSearch } from "@rilldata/web-common/features/dashboards/dimension-table/dimension-table-utils";
import { mergeFilters } from "@rilldata/web-common/features/dashboards/pivot/pivot-merge-filters";
import { memoizeMetricsStore } from "@rilldata/web-common/features/dashboards/state-managers/memoize-metrics-store";
import { allDimensions } from "@rilldata/web-common/features/dashboards/state-managers/selectors/dimensions";
import { allMeasures } from "@rilldata/web-common/features/dashboards/state-managers/selectors/measures";
import type { StateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers";
import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores";
import { createAndExpression } from "@rilldata/web-common/features/dashboards/stores/filter-utils";
import { timeControlStateSelector } from "@rilldata/web-common/features/dashboards/time-controls/time-control-store";
import type { TimeRangeString } from "@rilldata/web-common/lib/time/types";
import type {
V1Expression,
V1MetricsViewAggregationResponse,
V1MetricsViewAggregationResponseDataItem,
} from "@rilldata/web-common/runtime-client";
Expand All @@ -17,6 +14,7 @@ import type { CreateQueryResult } from "@tanstack/svelte-query";
import type { ColumnDef } from "@tanstack/svelte-table";
import { type Readable, derived, readable } from "svelte/store";
import { getColumnDefForPivot } from "./pivot-column-definition";
import { getPivotConfig } from "./pivot-data-config";
import {
addExpandedDataToPivot,
getExpandedQueryErrors,
Expand All @@ -40,7 +38,6 @@ import {
reduceTableCellDataIntoRows,
} from "./pivot-table-transformations";
import {
canEnablePivotComparison,
getErrorFromResponses,
getErrorState,
getFilterForPivotTable,
Expand All @@ -54,142 +51,12 @@ import {
isTimeDimension,
} from "./pivot-utils";
import {
COMPARISON_DELTA,
COMPARISON_PERCENT,
PivotChipType,
type PivotDataRow,
type PivotDataStore,
type PivotDataStoreConfig,
type PivotFilter,
type PivotTimeConfig,
} from "./types";

let lastKey: string | undefined = undefined;

/**
* Extract out config relevant to pivot from dashboard and meta store
*/
export function getPivotConfig(
ctx: StateManagers,
): Readable<PivotDataStoreConfig> {
return derived(
[ctx.validSpecStore, ctx.timeRangeSummaryStore, ctx.dashboardStore],
([validSpec, timeRangeSummary, dashboardStore]) => {
if (
!validSpec?.data?.metricsView ||
!validSpec?.data?.explore ||
timeRangeSummary.isFetching
) {
return {
measureNames: [],
rowDimensionNames: [],
colDimensionNames: [],
allMeasures: [],
allDimensions: [],
whereFilter: dashboardStore.whereFilter,
pivot: dashboardStore.pivot,
time: {} as PivotTimeConfig,
comparisonTime: undefined,
enableComparison: false,
};
}

const { metricsView, explore } = validSpec.data;

// This indirection makes sure only one update of dashboard store triggers this
const timeControl = timeControlStateSelector([
metricsView,
explore,
timeRangeSummary,
dashboardStore,
]);

const time: PivotTimeConfig = {
timeStart: timeControl.timeStart,
timeEnd: timeControl.timeEnd,
timeZone: dashboardStore?.selectedTimezone || "UTC",
timeDimension: metricsView.timeDimension || "",
};

const enableComparison =
canEnablePivotComparison(
dashboardStore.pivot,
timeControl.comparisonTimeStart,
) && !!timeControl.showTimeComparison;

let comparisonTime: TimeRangeString | undefined = undefined;
if (enableComparison) {
comparisonTime = {
start: timeControl.comparisonTimeStart,
end: timeControl.comparisonTimeEnd,
};
}

const measureNames = dashboardStore.pivot.columns.measure.flatMap((m) => {
const measureName = m.id;
const group = [measureName];

if (enableComparison) {
group.push(
`${measureName}${COMPARISON_DELTA}`,
`${measureName}${COMPARISON_PERCENT}`,
);
}
return group;
});

// This is temporary until we have a better way to handle time grains
const rowDimensionNames = dashboardStore.pivot.rows.dimension.map((d) => {
if (d.type === PivotChipType.Time) {
return `${time.timeDimension}_rill_${d.id}`;
}
return d.id;
});

const colDimensionNames = dashboardStore.pivot.columns.dimension.map(
(d) => {
if (d.type === PivotChipType.Time) {
return `${time.timeDimension}_rill_${d.id}`;
}
return d.id;
},
);

const config: PivotDataStoreConfig = {
measureNames,
rowDimensionNames,
colDimensionNames,
allMeasures: allMeasures({
validMetricsView: metricsView,
validExplore: explore,
}),
allDimensions: allDimensions({
validMetricsView: metricsView,
validExplore: explore,
}),
whereFilter: mergeMeasureFilters(dashboardStore),
pivot: dashboardStore.pivot,
enableComparison,
comparisonTime,
time,
};

const currentKey = getPivotConfigKey(config);

if (lastKey !== currentKey) {
// Reset rowPage when pivot config changes
lastKey = currentKey;
if (config.pivot.rowPage !== 1) {
metricsExplorerStore.setPivotRowPage(dashboardStore.name, 1);
config.pivot.rowPage = 1;
}
}

return config;
},
);
}

/**
* Returns a query for cell data for the initial table.
* The table cell is sorted by the anchor dimension irrespective
Expand Down Expand Up @@ -375,13 +242,23 @@ export function createPivotDataStore(
const rowPage = config.pivot.rowPage;
const rowOffset = (rowPage - 1) * NUM_ROWS_PER_PAGE;

let whereFilter: V1Expression = config.whereFilter;
if (config.searchText) {
whereFilter =
getDimensionFilterWithSearch(
whereFilter,
config.searchText,
anchorDimension,
) || config.whereFilter;
}

// Get sort order for the anchor dimension
const rowDimensionAxisQuery = getAxisForDimensions(
ctx,
config,
rowDimensionNames.slice(0, 1),
sortFilteredMeasureBody,
config.whereFilter,
whereFilter,
sortPivotBy,
timeRange,
NUM_ROWS_PER_PAGE.toString(),
Expand Down
2 changes: 1 addition & 1 deletion web-common/src/features/dashboards/pivot/pivot-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { derived, get } from "svelte/store";
import { runtime } from "../../../runtime-client/runtime-store";
import type { StateManagers } from "../state-managers/state-managers";
import { getPivotConfig } from "./pivot-data-store";
import { getPivotConfig } from "./pivot-data-config";
import { prepareMeasureForComparison } from "./pivot-utils";
import {
COMPARISON_DELTA,
Expand Down
1 change: 1 addition & 0 deletions web-common/src/features/dashboards/pivot/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export interface PivotDataStoreConfig {
time: PivotTimeConfig;
enableComparison: boolean;
comparisonTime: TimeRangeString | undefined;
searchText: string | undefined;
}

export interface PivotAxesData {
Expand Down
1 change: 1 addition & 0 deletions web-common/src/features/templates/table/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export function getTableConfig(
allMeasures: metricsView.data?.measures || [],
allDimensions: metricsView.data?.dimensions || [],
whereFilter: createAndExpression([]),
searchText: "",
pivot: pivotState,
enableComparison,
comparisonTime: {
Expand Down

1 comment on commit a3de19c

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.