From 818ad9acc69e8654f970e4645e96fad98ffe1f36 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Wed, 18 Sep 2024 17:57:48 +0530 Subject: [PATCH 01/48] Refactor StateManagers to use explore --- .../selectors/active-measure.ts | 7 +- .../selectors/dashboard-queries.ts | 4 +- .../selectors/dimension-table.ts | 2 +- .../state-managers/selectors/dimensions.ts | 16 ++-- .../state-managers/selectors/index.ts | 13 ++-- .../state-managers/selectors/measures.ts | 34 ++++---- .../state-managers/selectors/pivot.ts | 4 +- .../state-managers/selectors/time-range.ts | 11 ++- .../state-managers/selectors/types.ts | 5 +- .../state-managers/state-managers.ts | 44 ++++------- .../time-controls/time-control-store.ts | 57 +++++++------- .../time-controls/time-range-store.ts | 44 ++++++----- web-common/src/features/explores/selectors.ts | 47 +++++++++++ .../workspace/PreviewButton.svelte | 2 +- .../routes/(viz)/explore/[name]/+page.svelte | 78 +++++++++++++++++++ .../src/routes/(viz)/explore/[name]/+page.ts | 52 +++++++++++++ 16 files changed, 304 insertions(+), 116 deletions(-) create mode 100644 web-common/src/features/explores/selectors.ts create mode 100644 web-local/src/routes/(viz)/explore/[name]/+page.svelte create mode 100644 web-local/src/routes/(viz)/explore/[name]/+page.ts diff --git a/web-common/src/features/dashboards/state-managers/selectors/active-measure.ts b/web-common/src/features/dashboards/state-managers/selectors/active-measure.ts index b8e6c1ade36..b691da0cfca 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/active-measure.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/active-measure.ts @@ -5,13 +5,12 @@ import { isSummableMeasure } from "../../dashboard-utils"; export const activeMeasure = ( dashData: DashboardDataSources, ): MetricsViewSpecMeasureV2 | undefined => { - const measures = dashData.metricsSpecQueryResult.data?.measures; - if (!measures) { + if (!dashData.validMetricsView?.measures) { return undefined; } - const activeMeasure = measures.find( - (measure) => measure.name === activeMeasureName(dashData), + const activeMeasure = dashData.validMetricsView.measures.find( + (measure) => measure === activeMeasureName(dashData), ); return activeMeasure; }; diff --git a/web-common/src/features/dashboards/state-managers/selectors/dashboard-queries.ts b/web-common/src/features/dashboards/state-managers/selectors/dashboard-queries.ts index c606934a9ee..31c8d66d505 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/dashboard-queries.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/dashboard-queries.ts @@ -53,7 +53,7 @@ function measuresForDimensionTable(dashData: DashboardDataSources) { ...selectedMeasureNames(dashData), ...additionalMeasures(dashData), ]); - return getIndependentMeasures(dashData.metricsSpecQueryResult.data ?? {}, [ + return getIndependentMeasures(dashData.validMetricsView ?? {}, [ ...allMeasures, ]); } @@ -79,7 +79,7 @@ export function leaderboardSortedQueryBody( prepareSortedQueryBody( dimensionName, getIndependentMeasures( - dashData.metricsSpecQueryResult.data ?? {}, + dashData.validMetricsView ?? {}, additionalMeasures(dashData), ), timeControlsState(dashData), diff --git a/web-common/src/features/dashboards/state-managers/selectors/dimension-table.ts b/web-common/src/features/dashboards/state-managers/selectors/dimension-table.ts index d80d37c51dd..c7f06d451b4 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/dimension-table.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/dimension-table.ts @@ -30,7 +30,7 @@ export const primaryDimension = ( dashData: DashboardDataSources, ): MetricsViewSpecDimensionV2 | undefined => { const dimName = dashData.dashboard.selectedDimensionName; - return dashData.metricsSpecQueryResult.data?.dimensions?.find( + return dashData.validMetricsView?.dimensions?.find( (dim) => dim.name === dimName, ); }; diff --git a/web-common/src/features/dashboards/state-managers/selectors/dimensions.ts b/web-common/src/features/dashboards/state-managers/selectors/dimensions.ts index 1be2b364b3f..5a0024cd40c 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/dimensions.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/dimensions.ts @@ -2,19 +2,23 @@ import type { MetricsViewSpecDimensionV2 } from "@rilldata/web-common/runtime-cl import type { DashboardDataSources } from "./types"; export const allDimensions = ({ - metricsSpecQueryResult, + validExplore, + validMetricsView, }: DashboardDataSources): MetricsViewSpecDimensionV2[] | undefined => { - return metricsSpecQueryResult.data?.dimensions; + return validMetricsView?.dimensions?.filter((d) => + validExplore?.dimensions?.includes(d.name ?? ""), + ); }; export const visibleDimensions = ({ - metricsSpecQueryResult, + validMetricsView, dashboard, }: DashboardDataSources): MetricsViewSpecDimensionV2[] => { - const dimensions = metricsSpecQueryResult.data?.dimensions?.filter( - (d) => d.name && dashboard.visibleDimensionKeys.has(d.name), + return ( + validMetricsView?.dimensions?.filter( + (d) => d.name && dashboard.visibleDimensionKeys.has(d.name), + ) ?? [] ); - return dimensions === undefined ? [] : dimensions; }; export const dimensionTableDimName = ({ diff --git a/web-common/src/features/dashboards/state-managers/selectors/index.ts b/web-common/src/features/dashboards/state-managers/selectors/index.ts index 9c3e5326df6..2fdac73c802 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/index.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/index.ts @@ -1,8 +1,8 @@ import { chartSelectors } from "@rilldata/web-common/features/dashboards/state-managers/selectors/charts"; import { measureFilterSelectors } from "@rilldata/web-common/features/dashboards/state-managers/selectors/measure-filters"; +import { ValidExploreResponse } from "@rilldata/web-common/features/explores/selectors"; import type { RpcStatus, - V1MetricsViewSpec, V1MetricsViewTimeRangeResponse, } from "@rilldata/web-common/runtime-client"; import type { QueryClient, QueryObserverResult } from "@tanstack/svelte-query"; @@ -24,8 +24,8 @@ import type { ReadablesObj, SelectorFnsObj } from "./types"; export type DashboardDataReadables = { dashboardStore: Readable; - metricsSpecQueryResultStore: Readable< - QueryObserverResult + validSpecStore: Readable< + QueryObserverResult >; timeRangeSummaryStore: Readable< QueryObserverResult @@ -174,13 +174,14 @@ function createReadablesFromSelectors( // selectorFnArgs object. [ readables.dashboardStore, - readables.metricsSpecQueryResultStore, + readables.validSpecStore, readables.timeRangeSummaryStore, ], - ([dashboard, metricsSpecQueryResult, timeRangeSummary]) => + ([dashboard, validSpec, timeRangeSummary]) => selectorFn({ dashboard, - metricsSpecQueryResult, + validMetricsView: validSpec.data?.metricsView, + validExplore: validSpec.data?.explore, timeRangeSummary, queryClient: readables.queryClient, }), diff --git a/web-common/src/features/dashboards/state-managers/selectors/measures.ts b/web-common/src/features/dashboards/state-managers/selectors/measures.ts index 778643fa690..3476b2138a6 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/measures.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/measures.ts @@ -8,20 +8,25 @@ import { import type { DashboardDataSources } from "./types"; export const allMeasures = ({ - metricsSpecQueryResult, + validMetricsView, + validExplore, }: DashboardDataSources): MetricsViewSpecMeasureV2[] => { - const measures = metricsSpecQueryResult.data?.measures; - return measures === undefined ? [] : measures; + return ( + validMetricsView?.measures?.filter((m) => + validExplore?.measures?.includes(m.name ?? ""), + ) ?? [] + ); }; export const visibleMeasures = ({ - metricsSpecQueryResult, + validMetricsView, dashboard, }: DashboardDataSources): MetricsViewSpecMeasureV2[] => { - const measures = metricsSpecQueryResult.data?.measures?.filter( - (d) => d.name && dashboard.visibleMeasureKeys.has(d.name), + return ( + validMetricsView?.measures?.filter( + (m) => m.name && dashboard.visibleMeasureKeys.has(m.name), + ) ?? [] ); - return measures === undefined ? [] : measures; }; export const getMeasureByName = ( @@ -33,31 +38,32 @@ export const getMeasureByName = ( }; export const measureLabel = ({ - metricsSpecQueryResult, + validMetricsView, }: DashboardDataSources): ((m: string) => string) => { return (measureName) => { - const measure = metricsSpecQueryResult.data?.measures?.find( + const measure = validMetricsView?.measures?.find( (d) => d.name === measureName, ); return measure?.label ?? measureName; }; }; export const isMeasureValidPercentOfTotal = ({ - metricsSpecQueryResult, + validMetricsView, }: DashboardDataSources): ((measureName: string) => boolean) => { return (measureName: string) => { - const measures = metricsSpecQueryResult.data?.measures; - const selectedMeasure = measures?.find((m) => m.name === measureName); + const selectedMeasure = validMetricsView?.measures?.find( + (m) => m.name === measureName, + ); return selectedMeasure?.validPercentOfTotal ?? false; }; }; export const filteredSimpleMeasures = ({ - metricsSpecQueryResult, + validMetricsView, }: DashboardDataSources) => { return () => { return ( - metricsSpecQueryResult.data?.measures?.filter( + validMetricsView?.measures?.filter( (m) => !m.window && m.type !== MetricsViewSpecMeasureType.MEASURE_TYPE_TIME_COMPARISON, diff --git a/web-common/src/features/dashboards/state-managers/selectors/pivot.ts b/web-common/src/features/dashboards/state-managers/selectors/pivot.ts index a44d7f8eac6..ee4cca7079a 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/pivot.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/pivot.ts @@ -18,9 +18,9 @@ export const pivotSelectors = { type: PivotChipType.Measure, })); }, - dimensions: ({ metricsSpecQueryResult, dashboard }: DashboardDataSources) => { + dimensions: ({ validMetricsView, dashboard }: DashboardDataSources) => { { - const dimensions = metricsSpecQueryResult.data?.dimensions ?? []; + const dimensions = validMetricsView?.dimensions ?? []; const columns = dashboard.pivot.columns; const rows = dashboard.pivot.rows; diff --git a/web-common/src/features/dashboards/state-managers/selectors/time-range.ts b/web-common/src/features/dashboards/state-managers/selectors/time-range.ts index babfc5f4df4..cb3231ac0ca 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/time-range.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/time-range.ts @@ -14,7 +14,8 @@ import type { DashboardDataSources } from "./types"; export const timeControlsState = (dashData: DashboardDataSources) => timeControlStateSelector([ - dashData.metricsSpecQueryResult, + dashData.validMetricsView, + dashData.validExplore, dashData.timeRangeSummary, dashData.dashboard, ]); @@ -28,14 +29,16 @@ export const isTimeComparisonActive = ( export const timeRangeSelectorState = (dashData: DashboardDataSources) => timeRangeSelectionsSelector([ - dashData.metricsSpecQueryResult, + dashData.validMetricsView, + dashData.validExplore, dashData.timeRangeSummary, dashData.dashboard, ]); export const timeComparisonOptionsState = (dashData: DashboardDataSources) => timeComparisonOptionsSelector([ - dashData.metricsSpecQueryResult, + dashData.validMetricsView, + dashData.validExplore, dashData.timeRangeSummary, dashData.dashboard, selectedTimeRangeState(dashData), @@ -44,7 +47,7 @@ export const timeComparisonOptionsState = (dashData: DashboardDataSources) => // TODO: use this in place of timeControlStore export const selectedTimeRangeState = (dashData: DashboardDataSources) => selectedTimeRangeSelector([ - dashData.metricsSpecQueryResult, + dashData.validExplore, dashData.timeRangeSummary, dashData.dashboard, ]); diff --git a/web-common/src/features/dashboards/state-managers/selectors/types.ts b/web-common/src/features/dashboards/state-managers/selectors/types.ts index d862567f42a..ffa56f4615b 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/types.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/types.ts @@ -1,5 +1,5 @@ import type { - RpcStatus, + V1ExploreSpec, V1MetricsViewSpec, V1MetricsViewTimeRangeResponse, } from "@rilldata/web-common/runtime-client"; @@ -23,7 +23,8 @@ import type { Expand } from "../types"; */ export type DashboardDataSources = { dashboard: MetricsExplorerEntity; - metricsSpecQueryResult: QueryObserverResult; + validMetricsView: V1MetricsViewSpec | undefined; + validExplore: V1ExploreSpec | undefined; timeRangeSummary: QueryObserverResult< V1MetricsViewTimeRangeResponse, unknown diff --git a/web-common/src/features/dashboards/state-managers/state-managers.ts b/web-common/src/features/dashboards/state-managers/state-managers.ts index e0e915da4cb..79d31b78852 100644 --- a/web-common/src/features/dashboards/state-managers/state-managers.ts +++ b/web-common/src/features/dashboards/state-managers/state-managers.ts @@ -7,11 +7,14 @@ import { getPersistentDashboardStore, initPersistentDashboardStore, } from "@rilldata/web-common/features/dashboards/stores/persistent-dashboard-state"; +import { + useValidExplore, + ValidExploreResponse, +} from "@rilldata/web-common/features/explores/selectors"; import { V1MetricsViewTimeRangeResponse, createQueryServiceMetricsViewTimeRange, type RpcStatus, - type V1MetricsViewSpec, } from "@rilldata/web-common/runtime-client"; import type { Runtime } from "@rilldata/web-common/runtime-client/runtime-store"; import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; @@ -24,10 +27,6 @@ import { updateMetricsExplorerByName, useDashboardStore, } from "web-common/src/features/dashboards/stores/dashboard-stores"; -import { - ResourceKind, - useResource, -} from "../../entity-management/resource-selectors"; import { createStateManagerActions, type StateManagerActions } from "./actions"; import type { DashboardCallbackExecutor } from "./actions/types"; import { @@ -43,6 +42,9 @@ export type StateManagers = { timeRangeSummaryStore: Readable< QueryObserverResult >; + validSpecStore: Readable< + QueryObserverResult + >; queryClient: QueryClient; updateDashboard: DashboardCallbackExecutor; /** @@ -86,30 +88,17 @@ export function createStateManagers({ }, ); - // Note: this is equivalent to `useMetricsView` - const metricsSpecStore: Readable< - QueryObserverResult - > = derived([runtime, metricsViewNameStore], ([r, metricViewName], set) => { - useResource(r.instanceId, metricViewName, ResourceKind.MetricsView, { - queryClient, - }).subscribe((result) => { - // In case the store was created with a name that has incorrect casing - if (result.data?.meta?.name?.name) { - metricsViewNameStore.set(result.data.meta.name.name); - } - - return set({ - ...result, - data: result.data?.metricsView?.state?.validSpec, - }); - }); - }); + const validSpecStore: Readable< + QueryObserverResult + > = derived([runtime, metricsViewNameStore], ([r, metricViewName], set) => + useValidExplore(r.instanceId, metricViewName).subscribe(set), + ); const timeRangeSummaryStore: Readable< QueryObserverResult > = derived( - [runtime, metricsViewNameStore, metricsSpecStore], - ([runtime, mvName, metricsView], set) => + [runtime, metricsViewNameStore, validSpecStore], + ([runtime, mvName, validSpec], set) => createQueryServiceMetricsViewTimeRange( runtime.instanceId, mvName, @@ -117,7 +106,7 @@ export function createStateManagers({ { query: { queryClient: queryClient, - enabled: !!metricsView.data?.timeDimension, + enabled: !!validSpec?.data?.metricsView?.timeDimension, }, }, ).subscribe(set), @@ -144,6 +133,7 @@ export function createStateManagers({ metricsViewName: metricsViewNameStore, metricsStore: metricsExplorerStore, timeRangeSummaryStore, + validSpecStore, queryClient, dashboardStore, @@ -153,7 +143,7 @@ export function createStateManagers({ */ selectors: createStateManagerReadables({ dashboardStore, - metricsSpecQueryResultStore: metricsSpecStore, + validSpecStore, timeRangeSummaryStore, queryClient, }), diff --git a/web-common/src/features/dashboards/time-controls/time-control-store.ts b/web-common/src/features/dashboards/time-controls/time-control-store.ts index 57ab72d2288..8d7aabec019 100644 --- a/web-common/src/features/dashboards/time-controls/time-control-store.ts +++ b/web-common/src/features/dashboards/time-controls/time-control-store.ts @@ -1,7 +1,3 @@ -import { - createTimeRangeSummary, - useMetricsView, -} from "@rilldata/web-common/features/dashboards/selectors/index"; import type { StateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers"; import type { MetricsExplorerEntity } from "@rilldata/web-common/features/dashboards/stores/metrics-explorer-entity"; import { getOrderedStartEnd } from "@rilldata/web-common/features/dashboards/time-series/utils"; @@ -29,7 +25,7 @@ import { TimeRangePreset, } from "@rilldata/web-common/lib/time/types"; import { - RpcStatus, + V1ExploreSpec, V1MetricsViewSpec, V1MetricsViewTimeRangeResponse, V1TimeGrain, @@ -73,26 +69,28 @@ export type TimeControlStore = Readable; export const timeControlStateSelector = ([ metricsView, + explore, timeRangeResponse, metricsExplorer, ]: [ - QueryObserverResult, + V1MetricsViewSpec | undefined, + V1ExploreSpec | undefined, QueryObserverResult, MetricsExplorerEntity, ]): TimeControlState => { - const hasTimeSeries = Boolean(metricsView.data?.timeDimension); - const timeDimension = metricsView.data?.timeDimension; + const hasTimeSeries = Boolean(metricsView?.timeDimension); + const timeDimension = metricsView?.timeDimension; if ( - !metricsView.data || + !metricsView || + !explore || !metricsExplorer || - !metricsView.data || !timeRangeResponse || !timeRangeResponse.isSuccess || !timeRangeResponse.data.timeRangeSummary?.min || !timeRangeResponse.data.timeRangeSummary?.max ) { return { - isFetching: metricsView.isFetching || timeRangeResponse.isRefetching, + isFetching: timeRangeResponse.isRefetching, ready: !metricsExplorer || !hasTimeSeries, } as TimeControlState; } @@ -103,10 +101,10 @@ export const timeControlStateSelector = ([ end: new Date(timeRangeResponse.data.timeRangeSummary.max), }; const minTimeGrain = - (metricsView.data.smallestTimeGrain as V1TimeGrain) || + (metricsView.smallestTimeGrain as V1TimeGrain) || V1TimeGrain.TIME_GRAIN_UNSPECIFIED; const defaultTimeRange = isoDurationToFullTimeRange( - metricsView.data.defaultTimeRange, + explore.presets?.[0]?.timeRange, allTimeRange.start, allTimeRange.end, metricsExplorer.selectedTimezone, @@ -126,7 +124,7 @@ export const timeControlStateSelector = ([ } const comparisonTimeRangeState = calculateComparisonTimeRangePartial( - metricsView.data, + explore, metricsExplorer, allTimeRange, timeRangeState, @@ -148,8 +146,14 @@ export const timeControlStateSelector = ([ export function createTimeControlStore(ctx: StateManagers) { return derived( - [useMetricsView(ctx), createTimeRangeSummary(ctx), ctx.dashboardStore], - timeControlStateSelector, + [ctx.validSpecStore, ctx.timeRangeSummaryStore, ctx.dashboardStore], + ([validSpecResp, timeRangeSummaryResp, dashboardStore]) => + timeControlStateSelector([ + validSpecResp.data?.metricsView, + validSpecResp.data?.explore, + timeRangeSummaryResp, + dashboardStore, + ]), ); } @@ -216,14 +220,13 @@ function calculateTimeRangePartial( * Also adds start, end and their adjusted counterparts as strings ready to use in requests. */ function calculateComparisonTimeRangePartial( - metricsView: V1MetricsViewSpec, + explore: V1ExploreSpec, metricsExplorer: MetricsExplorerEntity, allTimeRange: DashboardTimeControls, timeRangeState: TimeRangeState, ): ComparisonTimeRangeState { const selectedComparisonTimeRange = getComparisonTimeRange( - metricsView, - metricsExplorer, + explore, allTimeRange, timeRangeState.selectedTimeRange, metricsExplorer.selectedComparisonTimeRange, @@ -352,8 +355,7 @@ function getTimeGrain( } function getComparisonTimeRange( - metricsView: V1MetricsViewSpec, - metricsExplorer: MetricsExplorerEntity, + explore: V1ExploreSpec, allTimeRange: DashboardTimeControls | undefined, timeRange: DashboardTimeControls | undefined, comparisonTimeRange: DashboardTimeControls | undefined, @@ -366,9 +368,8 @@ function getComparisonTimeRange( ]?.defaultComparison as TimeComparisonOption; const range = getTimeComparisonParametersForComponent( comparisonOption ?? - metricsView.availableTimeRanges?.find( - (tr) => tr.range === timeRange.name, - )?.comparisonOffsets?.[0]?.offset ?? + explore.timeRanges?.find((tr) => tr.range === timeRange.name) + ?.comparisonTimeRanges?.[0]?.offset ?? TimeComparisonOption.CONTIGUOUS, allTimeRange.start, allTimeRange.end, @@ -405,16 +406,16 @@ function getComparisonTimeRange( * Fills in start and end dates based on selected time range and all time range. */ export function selectedTimeRangeSelector([ - metricsView, + exploreSpec, timeRangeResponse, explorer, ]: [ - QueryObserverResult, + V1ExploreSpec | undefined, QueryObserverResult, MetricsExplorerEntity, ]) { if ( - !metricsView.data || + !exploreSpec || !timeRangeResponse.data?.timeRangeSummary || !timeRangeResponse.data.timeRangeSummary.min || !timeRangeResponse.data.timeRangeSummary.max @@ -428,7 +429,7 @@ export function selectedTimeRangeSelector([ end: new Date(timeRangeResponse.data.timeRangeSummary.max), }; const defaultTimeRange = isoDurationToFullTimeRange( - metricsView.data.defaultTimeRange, + exploreSpec.presets?.[0]?.timeRange, allTimeRange.start, allTimeRange.end, explorer.selectedTimezone, diff --git a/web-common/src/features/dashboards/time-controls/time-range-store.ts b/web-common/src/features/dashboards/time-controls/time-range-store.ts index 47fdc9bfeda..552523a9440 100644 --- a/web-common/src/features/dashboards/time-controls/time-range-store.ts +++ b/web-common/src/features/dashboards/time-controls/time-range-store.ts @@ -25,7 +25,7 @@ import { TimeRangePreset, } from "@rilldata/web-common/lib/time/types"; import { - RpcStatus, + V1ExploreSpec, V1MetricsViewSpec, V1MetricsViewTimeRangeResponse, V1TimeGrain, @@ -41,14 +41,16 @@ export type TimeRangeControlsState = { export function timeRangeSelectionsSelector([ metricsView, + explore, timeRangeResponse, explorer, ]: [ - QueryObserverResult, + V1MetricsViewSpec | undefined, + V1ExploreSpec | undefined, QueryObserverResult, MetricsExplorerEntity, ]): TimeRangeControlsState { - if (!metricsView.data || !timeRangeResponse?.data?.timeRangeSummary) + if (!metricsView || !explore || !timeRangeResponse?.data?.timeRangeSummary) return { latestWindowTimeRanges: [], periodToDateRanges: [], @@ -62,7 +64,7 @@ export function timeRangeSelectionsSelector([ end: new Date(timeRangeResponse.data.timeRangeSummary.max ?? 0), }; const minTimeGrain = - (metricsView.data.smallestTimeGrain as V1TimeGrain) || + (metricsView.smallestTimeGrain as V1TimeGrain) || V1TimeGrain.TIME_GRAIN_UNSPECIFIED; let latestWindowTimeRanges: TimeRangeMetaSet = {}; @@ -70,13 +72,14 @@ export function timeRangeSelectionsSelector([ let previousCompleteDateRanges: TimeRangeMetaSet = {}; let hasDefaultInRanges = false; - if (metricsView.data.availableTimeRanges?.length) { - for (const availableTimeRange of metricsView.data.availableTimeRanges) { + const defaultTimeRange = explore.presets?.[0]?.timeRange; + if (explore.timeRanges?.length) { + for (const availableTimeRange of explore.timeRanges) { if (!availableTimeRange.range) continue; // default time range is part of availableTimeRanges. // this is used to not show a separate selection for the default - if (metricsView.data.defaultTimeRange === availableTimeRange.range) { + if (defaultTimeRange === availableTimeRange.range) { hasDefaultInRanges = true; } if (availableTimeRange.range in LATEST_WINDOW_TIME_RANGES) { @@ -92,7 +95,7 @@ export function timeRangeSelectionsSelector([ latestWindowTimeRanges[availableTimeRange.range] = isoDurationToTimeRangeMeta( availableTimeRange.range, - availableTimeRange.comparisonOffsets?.[0] + availableTimeRange.comparisonTimeRanges?.[0] ?.offset as TimeComparisonOption, ); } @@ -102,10 +105,10 @@ export function timeRangeSelectionsSelector([ periodToDateRanges = PERIOD_TO_DATE_RANGES; previousCompleteDateRanges = PREVIOUS_COMPLETE_DATE_RANGES; hasDefaultInRanges = - !!metricsView.data.defaultTimeRange && - (metricsView.data.defaultTimeRange in LATEST_WINDOW_TIME_RANGES || - metricsView.data.defaultTimeRange in PERIOD_TO_DATE_RANGES || - metricsView.data.defaultTimeRange in PREVIOUS_COMPLETE_DATE_RANGES); + !!defaultTimeRange && + (defaultTimeRange in LATEST_WINDOW_TIME_RANGES || + defaultTimeRange in PERIOD_TO_DATE_RANGES || + defaultTimeRange in PREVIOUS_COMPLETE_DATE_RANGES); } return { @@ -130,17 +133,19 @@ export function timeRangeSelectionsSelector([ minTimeGrain, explorer.selectedTimezone, ), - showDefaultItem: !!metricsView.data.defaultTimeRange && !hasDefaultInRanges, + showDefaultItem: !!defaultTimeRange && !hasDefaultInRanges, }; } export function timeComparisonOptionsSelector([ metricsView, + explore, timeRangeResponse, explorer, selectedTimeRange, ]: [ - QueryObserverResult, + V1MetricsViewSpec | undefined, + V1ExploreSpec | undefined, QueryObserverResult, MetricsExplorerEntity, DashboardTimeControls | undefined, @@ -151,7 +156,8 @@ export function timeComparisonOptionsSelector([ end: Date; }> { if ( - !metricsView.data || + !metricsView || + !explore || !timeRangeResponse?.data?.timeRangeSummary || !explorer.selectedTimeRange || !selectedTimeRange || @@ -169,13 +175,13 @@ export function timeComparisonOptionsSelector([ let allOptions = [...Object.values(TimeComparisonOption)]; - if (metricsView.data.availableTimeRanges?.length) { - const timeRange = metricsView.data.availableTimeRanges.find( + if (explore.timeRanges?.length) { + const timeRange = explore.timeRanges.find( (tr) => tr.range === explorer.selectedTimeRange?.name, ); - if (timeRange?.comparisonOffsets?.length) { + if (timeRange?.comparisonTimeRanges?.length) { allOptions = - timeRange.comparisonOffsets?.map( + timeRange.comparisonTimeRanges?.map( (co) => co.offset as TimeComparisonOption, ) ?? []; allOptions.push(TimeComparisonOption.CUSTOM); diff --git a/web-common/src/features/explores/selectors.ts b/web-common/src/features/explores/selectors.ts new file mode 100644 index 00000000000..b076586498a --- /dev/null +++ b/web-common/src/features/explores/selectors.ts @@ -0,0 +1,47 @@ +import type { CreateQueryOptions } from "@rilldata/svelte-query"; +import { + createRuntimeServiceGetExplore, + RpcStatus, + V1ExploreSpec, + V1GetExploreResponse, + type V1MetricsViewSpec, +} from "@rilldata/web-common/runtime-client"; +import { ErrorType } from "@rilldata/web-common/runtime-client/http-client"; + +export function useExplore( + instanceId: string, + exploreName: string, + queryOptions?: CreateQueryOptions< + V1GetExploreResponse, + ErrorType, + V1GetExploreResponse + >, +) { + return createRuntimeServiceGetExplore( + instanceId, + { name: exploreName }, + { + query: queryOptions, + }, + ); +} + +export type ValidExploreResponse = { + explore: V1ExploreSpec | undefined; + metricsView: V1MetricsViewSpec | undefined; +}; +export function useValidExplore(instanceId: string, exploreName: string) { + return createRuntimeServiceGetExplore( + instanceId, + { name: exploreName }, + { + query: { + select: (data) => + { + explore: data.explore?.explore?.state?.validSpec, + metricsView: data.metricsView?.metricsView?.state?.validSpec, + }, + }, + }, + ); +} diff --git a/web-common/src/features/metrics-views/workspace/PreviewButton.svelte b/web-common/src/features/metrics-views/workspace/PreviewButton.svelte index e878dc4611d..9d90e90750a 100644 --- a/web-common/src/features/metrics-views/workspace/PreviewButton.svelte +++ b/web-common/src/features/metrics-views/workspace/PreviewButton.svelte @@ -14,7 +14,7 @@ export let disabled: boolean; export let status: string[] = []; export let dashboardName: string | undefined; - export let type: "dashboard" | "custom" = "dashboard"; + export let type: "dashboard" | "explore" | "custom" = "explore"; const viewDashboard = () => { if (!dashboardName) return; diff --git a/web-local/src/routes/(viz)/explore/[name]/+page.svelte b/web-local/src/routes/(viz)/explore/[name]/+page.svelte new file mode 100644 index 00000000000..6af79955de6 --- /dev/null +++ b/web-local/src/routes/(viz)/explore/[name]/+page.svelte @@ -0,0 +1,78 @@ + + + + Rill Developer | {exploreName} + + +{#if measures.length === 0 && $selectedMockUserStore !== null} + + +{:else if dashboardFileHasParseError && dashboardFileHasParseError.length > 0} + +{:else if mockUserHasNoAccess} + +{:else} + {#key exploreName} + + + + + + + + + + {/key} +{/if} diff --git a/web-local/src/routes/(viz)/explore/[name]/+page.ts b/web-local/src/routes/(viz)/explore/[name]/+page.ts new file mode 100644 index 00000000000..dc8cee4e97c --- /dev/null +++ b/web-local/src/routes/(viz)/explore/[name]/+page.ts @@ -0,0 +1,52 @@ +import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient.js"; +import { + getRuntimeServiceGetExploreQueryKey, + runtimeServiceGetExplore, +} from "@rilldata/web-common/runtime-client"; +import { error } from "@sveltejs/kit"; +import type { QueryFunction } from "@tanstack/svelte-query"; +import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; +import { get } from "svelte/store"; + +export const load = async ({ params, depends }) => { + const { instanceId } = get(runtime); + + const exploreName = params.name; + + depends(exploreName, "explore"); + + const queryParams = { + name: exploreName, + }; + + const queryKey = getRuntimeServiceGetExploreQueryKey(instanceId, queryParams); + + const queryFunction: QueryFunction< + Awaited> + > = ({ signal }) => runtimeServiceGetExplore(instanceId, queryParams, signal); + + try { + const response = await queryClient.fetchQuery({ + queryFn: queryFunction, + queryKey, + }); + + const exploreResource = response.explore; + const metricsViewResource = response.metricsView; + + if (!exploreResource?.explore) { + throw error(404, "Explore not found"); + } + if (!metricsViewResource?.metricsView) { + throw error(404, "Metrics view not found"); + } + + return { + explore: exploreResource, + metricsView: metricsViewResource, + }; + } catch (e) { + console.error(e); + throw error(404, "Explore not found"); + } +}; From 27499d23b3d533b53bc4b246e06b821a9d55b091 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Wed, 18 Sep 2024 20:08:30 +0530 Subject: [PATCH 02/48] Replace useMetricsView - Pass 1 --- .../dashboards/DashboardThemeProvider.svelte | 5 ++-- .../dimension-table-export-utils.ts | 13 ++++++---- .../dashboards/filters/FilterChips.svelte | 9 +++---- .../dashboards/filters/Filters.svelte | 8 +++--- .../dashboards/pivot/pivot-data-store.ts | 26 +++++++++++++------ .../features/dashboards/pivot/pivot-export.ts | 10 +++---- .../selectors/active-measure.ts | 2 +- .../state-managers/selectors/dimensions.ts | 13 +++++++--- .../state-managers/selectors/measures.ts | 5 +++- .../stores/AdvancedMeasureCorrector.ts | 2 ++ .../comparison-pill/ComparisonPill.svelte | 5 ++-- .../time-controls/super-pill/SuperPill.svelte | 14 +++++----- .../time-controls/time-range-mappers.ts | 6 ++--- .../time-controls/time-range-store.ts | 12 ++++----- .../time-dimension-details/TDDHeader.svelte | 13 ++++------ .../TimeDimensionDisplay.svelte | 12 +++------ .../getTDDExportArgs.ts | 13 ++++++---- .../time-dimension-data-store.ts | 8 +++--- .../time-series/timeseries-data-store.ts | 17 ++++++------ web-common/src/features/explores/selectors.ts | 2 ++ 20 files changed, 105 insertions(+), 90 deletions(-) diff --git a/web-common/src/features/dashboards/DashboardThemeProvider.svelte b/web-common/src/features/dashboards/DashboardThemeProvider.svelte index e9fdc74d1cb..b5cd253678a 100644 --- a/web-common/src/features/dashboards/DashboardThemeProvider.svelte +++ b/web-common/src/features/dashboards/DashboardThemeProvider.svelte @@ -1,17 +1,16 @@ diff --git a/web-common/src/features/dashboards/time-series/BackToOverview.svelte b/web-common/src/features/dashboards/time-series/BackToOverview.svelte index 0f002e4a412..df2777e4dce 100644 --- a/web-common/src/features/dashboards/time-series/BackToOverview.svelte +++ b/web-common/src/features/dashboards/time-series/BackToOverview.svelte @@ -4,11 +4,11 @@ import Spinner from "@rilldata/web-common/features/entity-management/Spinner.svelte"; import { EntityStatus } from "@rilldata/web-common/features/entity-management/types"; - export let metricViewName; + export let exploreName: string; export let isFetching = false; function goBackToOverview() { - metricsExplorerStore.setExpandedMeasureName(metricViewName, undefined); + metricsExplorerStore.setExpandedMeasureName(exploreName, undefined); } diff --git a/web-common/src/features/dashboards/time-series/ChartInteractions.svelte b/web-common/src/features/dashboards/time-series/ChartInteractions.svelte index 316dd39b395..576dd30770a 100644 --- a/web-common/src/features/dashboards/time-series/ChartInteractions.svelte +++ b/web-common/src/features/dashboards/time-series/ChartInteractions.svelte @@ -1,7 +1,6 @@ + + + { + // Remove the explorer entity so that everything is reset to defaults next time user navigates to it + metricsExplorerStore.remove(exploreName); + // Reset local persisted dashboard state for the metrics view + createPersistentDashboardStore(exploreName).reset(); + + if (!content?.length) { + setLineStatuses([], editor); + } + }} + {fileArtifact} + extensions={[placeholderElements.extension]} + /> + diff --git a/web-common/src/features/workspaces/ExploreWorkspace.svelte b/web-common/src/features/workspaces/ExploreWorkspace.svelte new file mode 100644 index 00000000000..a1ef9eef38b --- /dev/null +++ b/web-common/src/features/workspaces/ExploreWorkspace.svelte @@ -0,0 +1,95 @@ + + + + +
+ + + +
+
+ + + + +
diff --git a/web-local/src/routes/(application)/files/[...file]/+page.svelte b/web-local/src/routes/(application)/files/[...file]/+page.svelte index 0af7a430888..3b9437d1c7f 100644 --- a/web-local/src/routes/(application)/files/[...file]/+page.svelte +++ b/web-local/src/routes/(application)/files/[...file]/+page.svelte @@ -9,6 +9,7 @@ import { directoryState } from "@rilldata/web-common/features/file-explorer/directory-store"; import CanvasDashboardWorkspace from "@rilldata/web-common/features/workspaces/CanvasDashboardWorkspace.svelte"; import ComponentWorkspace from "@rilldata/web-common/features/workspaces/ComponentWorkspace.svelte"; + import ExploreWorkspace from "@rilldata/web-common/features/workspaces/ExploreWorkspace.svelte"; import MetricsWorkspace from "@rilldata/web-common/features/workspaces/MetricsWorkspace.svelte"; import ModelWorkspace from "@rilldata/web-common/features/workspaces/ModelWorkspace.svelte"; import SourceWorkspace from "@rilldata/web-common/features/workspaces/SourceWorkspace.svelte"; @@ -20,9 +21,9 @@ [ResourceKind.Source, SourceWorkspace], [ResourceKind.Model, ModelWorkspace], [ResourceKind.MetricsView, MetricsWorkspace], + [ResourceKind.Explore, ExploreWorkspace], [ResourceKind.Component, ComponentWorkspace], [ResourceKind.Dashboard, CanvasDashboardWorkspace], - [null, null], [undefined, null], ]); diff --git a/web-local/src/routes/(viz)/+layout.svelte b/web-local/src/routes/(viz)/+layout.svelte index 69532fa680c..a28b6017268 100644 --- a/web-local/src/routes/(viz)/+layout.svelte +++ b/web-local/src/routes/(viz)/+layout.svelte @@ -65,7 +65,7 @@ PREVIEW {#if route.id?.includes("dashboard") && metricsViewName} - + {/if} diff --git a/web-local/src/routes/(viz)/explore/[name]/+page.svelte b/web-local/src/routes/(viz)/explore/[name]/+page.svelte index 6af79955de6..1fe845efdae 100644 --- a/web-local/src/routes/(viz)/explore/[name]/+page.svelte +++ b/web-local/src/routes/(viz)/explore/[name]/+page.svelte @@ -20,6 +20,7 @@ resetSelectedMockUserAfterNavigate(queryClient); $: exploreName = data.explore.meta?.name?.name as string; + $: metricsViewName = data.metricsView?.meta?.name?.name as string; $: ({ instanceId } = $runtime); @@ -65,11 +66,11 @@ /> {:else} {#key exploreName} - + - + - + From fb830055ccc01786cff288f88a19eb895c8b2a5d Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Thu, 19 Sep 2024 14:52:07 +0530 Subject: [PATCH 05/48] Replace metricViewName with exploreName where applicable in rill dev --- .../big-number/MeasuresContainer.svelte | 15 +++++----- .../GlobalDimensionSearch.svelte | 3 -- .../GlobalDimensionSearchResults.svelte | 11 ++++--- .../dashboards/show-hide-selectors.ts | 18 +++++------ .../stores/DashboardStateProvider.svelte | 4 +-- .../time-controls/ComparisonSelector.svelte | 30 +++++++++---------- .../time-controls/TimeGrainSelector.svelte | 21 +++++-------- .../TDDExportButton.svelte | 4 +-- .../time-dimension-details/TDDHeader.svelte | 23 +++++--------- .../TimeDimensionDisplay.svelte | 8 ++--- .../dashboards/workspace/Dashboard.svelte | 5 ++-- .../dashboards/workspace/DashboardCTAs.svelte | 8 ++--- .../routes/(viz)/explore/[name]/+page.svelte | 2 +- 13 files changed, 67 insertions(+), 85 deletions(-) diff --git a/web-common/src/features/dashboards/big-number/MeasuresContainer.svelte b/web-common/src/features/dashboards/big-number/MeasuresContainer.svelte index 1d68ef1aeb1..abf9f7a1520 100644 --- a/web-common/src/features/dashboards/big-number/MeasuresContainer.svelte +++ b/web-common/src/features/dashboards/big-number/MeasuresContainer.svelte @@ -1,5 +1,4 @@ {#if $dashboardStoreReady.isFetching} diff --git a/web-common/src/features/dashboards/time-controls/ComparisonSelector.svelte b/web-common/src/features/dashboards/time-controls/ComparisonSelector.svelte index 1d154b3e6c8..c7210dff65b 100644 --- a/web-common/src/features/dashboards/time-controls/ComparisonSelector.svelte +++ b/web-common/src/features/dashboards/time-controls/ComparisonSelector.svelte @@ -16,27 +16,27 @@ This component needs to do the following: import { Search } from "@rilldata/web-common/components/search"; import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte"; import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte"; - import { useMetricsView } from "@rilldata/web-common/features/dashboards/selectors"; - import { - metricsExplorerStore, - useDashboardStore, - } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; + import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers"; + import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; import { NO_COMPARISON_LABEL } from "@rilldata/web-common/lib/time/config"; import type { MetricsViewSpecDimensionV2 } from "@rilldata/web-common/runtime-client"; - import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; import { matchSorter } from "match-sorter"; - export let metricViewName: string; + export let exploreName: string; export let chipStyle = false; - let dimensions: MetricsViewSpecDimensionV2[] | undefined = []; + const { + dashboardStore, + selectors: { + dimensions: { allDimensions }, + }, + } = getStateManagers(); - $: dashboardStore = useDashboardStore(metricViewName); - $: metricsView = useMetricsView($runtime.instanceId, metricViewName); + let dimensions: MetricsViewSpecDimensionV2[] | undefined = []; $: showTimeComparison = $dashboardStore?.showTimeComparison; $: selectedDimension = $dashboardStore?.selectedComparisonDimension; - $: dimensions = $metricsView?.data?.dimensions; + $: dimensions = $allDimensions; let searchText = ""; @@ -64,16 +64,16 @@ This component needs to do the following: function enableComparison(type: string, name = "") { if (type === "time") { - metricsExplorerStore.displayTimeComparison(metricViewName, true); + metricsExplorerStore.displayTimeComparison(exploreName, true); } else { // Temporary until these are not mutually exclusive - metricsExplorerStore.displayTimeComparison(metricViewName, false); - metricsExplorerStore.setComparisonDimension(metricViewName, name); + metricsExplorerStore.displayTimeComparison(exploreName, false); + metricsExplorerStore.setComparisonDimension(exploreName, name); } } function disableAllComparisons() { - metricsExplorerStore.disableAllComparisons(metricViewName); + metricsExplorerStore.disableAllComparisons(exploreName); } diff --git a/web-common/src/features/dashboards/time-controls/TimeGrainSelector.svelte b/web-common/src/features/dashboards/time-controls/TimeGrainSelector.svelte index 8cb7585db04..fa6655cdcbc 100644 --- a/web-common/src/features/dashboards/time-controls/TimeGrainSelector.svelte +++ b/web-common/src/features/dashboards/time-controls/TimeGrainSelector.svelte @@ -10,31 +10,24 @@ DashboardTimeControls, TimeGrain, } from "@rilldata/web-common/lib/time/types"; - import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; import type { V1TimeGrain } from "../../../runtime-client"; - import { - metricsExplorerStore, - useDashboardStore, - } from "../stores/dashboard-stores"; + import { metricsExplorerStore } from "../stores/dashboard-stores"; import { getAllowedTimeGrains } from "@rilldata/web-common/lib/time/grains"; import Chip from "@rilldata/web-common/components/chip/core/Chip.svelte"; import { timeChipColors } from "@rilldata/web-common/components/chip/chip-types"; import type { TimeRange } from "@rilldata/web-common/lib/time/types"; - import { useMetricsView } from "../selectors"; - export let metricViewName: string; + export let exploreName: string; export let pill = false; - const timeControlsStore = useTimeControlStore(getStateManagers()); + const ctx = getStateManagers(); + const { dashboardStore, validSpecStore } = ctx; + const timeControlsStore = useTimeControlStore(ctx); let timeGrainOptions: TimeGrain[]; let open = false; - $: ({ instanceId } = $runtime); - - $: dashboardStore = useDashboardStore(metricViewName); - $: metricsViewQuery = useMetricsView(instanceId, metricViewName); - $: metricsView = $metricsViewQuery.data ?? {}; + $: metricsView = $validSpecStore.data?.metricsView ?? {}; $: ({ minTimeGrain, timeStart, timeEnd, selectedTimeRange } = $timeControlsStore); @@ -93,7 +86,7 @@ comparisonTimeRange: DashboardTimeControls | undefined, ) { metricsExplorerStore.selectTimeRange( - metricViewName, + exploreName, timeRange, timeGrain, comparisonTimeRange, diff --git a/web-common/src/features/dashboards/time-dimension-details/TDDExportButton.svelte b/web-common/src/features/dashboards/time-dimension-details/TDDExportButton.svelte index 3d910742255..cc03cbe4a7e 100644 --- a/web-common/src/features/dashboards/time-dimension-details/TDDExportButton.svelte +++ b/web-common/src/features/dashboards/time-dimension-details/TDDExportButton.svelte @@ -13,7 +13,7 @@ import exportTDD from "./export-tdd"; export let includeScheduledReport: boolean; - export let metricViewName: string; + export let exploreName: string; let exportMenuOpen = false; let showScheduledReportDialog = false; @@ -21,7 +21,7 @@ const ctx = getStateManagers(); const { runtime, dashboardStore } = ctx; $: metricsViewProto = $dashboardStore.proto; - const metricsView = useDashboard($runtime.instanceId, metricViewName); + const metricsView = useDashboard($runtime.instanceId, exploreName); const exportDash = createQueryServiceExport(); const handleExportTDD = async (format: V1ExportFormat) => { diff --git a/web-common/src/features/dashboards/time-dimension-details/TDDHeader.svelte b/web-common/src/features/dashboards/time-dimension-details/TDDHeader.svelte index c45c42e105a..de02774668b 100644 --- a/web-common/src/features/dashboards/time-dimension-details/TDDHeader.svelte +++ b/web-common/src/features/dashboards/time-dimension-details/TDDHeader.svelte @@ -15,10 +15,7 @@ import SelectAllButton from "@rilldata/web-common/features/dashboards/dimension-table/SelectAllButton.svelte"; import ReplacePivotDialog from "@rilldata/web-common/features/dashboards/pivot/ReplacePivotDialog.svelte"; import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers"; - import { - metricsExplorerStore, - useDashboardStore, - } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; + import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; import ComparisonSelector from "@rilldata/web-common/features/dashboards/time-controls/ComparisonSelector.svelte"; import DelayedSpinner from "@rilldata/web-common/features/entity-management/DelayedSpinner.svelte"; import { TIME_GRAIN } from "@rilldata/web-common/lib/time/config"; @@ -32,7 +29,7 @@ import type { TDDComparison } from "./types"; import TimeGrainSelector from "../time-controls/TimeGrainSelector.svelte"; - export let metricViewName: string; + export let exploreName: string; export let dimensionName: string; export let isFetching = false; export let comparing: TDDComparison | undefined; @@ -50,10 +47,9 @@ actions: { dimensionsFilter: { toggleDimensionFilterMode }, }, + dashboardStore, } = getStateManagers(); - $: dashboardStore = useDashboardStore(metricViewName); - $: expandedMeasureName = $dashboardStore?.tdd.expandedMeasureName; $: selectableMeasures = $allMeasures @@ -105,7 +101,7 @@ } function switchMeasure(event) { - metricsExplorerStore.setExpandedMeasureName(metricViewName, event.detail); + metricsExplorerStore.setExpandedMeasureName(exploreName, event.detail); } let showReplacePivotModal = false; @@ -139,7 +135,7 @@ ] : []; metricsExplorerStore.createPivot( - metricViewName, + exploreName, { dimension: rowDimensions }, { dimension: [ @@ -168,7 +164,7 @@ Rows - +
@@ -176,7 +172,7 @@ Columns
- + {#if $exports} - + {/if}
diff --git a/web-admin/src/features/bookmarks/BookmarkDialog.svelte b/web-admin/src/features/bookmarks/BookmarkDialog.svelte index 4f366317e01..3bfc81794a8 100644 --- a/web-admin/src/features/bookmarks/BookmarkDialog.svelte +++ b/web-admin/src/features/bookmarks/BookmarkDialog.svelte @@ -22,6 +22,7 @@ import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers"; export let metricsViewName: string; + export let exploreName: string; export let bookmark: BookmarkEntry | null = null; export let onClose = () => {}; @@ -65,8 +66,8 @@ displayName: values.displayName, description: values.description, projectId: $projectId.data ?? "", - resourceKind: ResourceKind.MetricsView, - resourceName: metricsViewName, + resourceKind: ResourceKind.Explore, + resourceName: exploreName, shared: values.shared === "true", data: getBookmarkDataForDashboard( $dashboardStore, @@ -83,8 +84,8 @@ await queryClient.refetchQueries( getAdminServiceListBookmarksQueryKey({ projectId: $projectId.data ?? "", - resourceKind: ResourceKind.MetricsView, - resourceName: metricsViewName, + resourceKind: ResourceKind.Explore, + resourceName: exploreName, }), ); eventBus.emit("notification", { @@ -96,7 +97,7 @@ const { handleSubmit, handleReset } = formState; $: ({ params } = $page); - $: dashboardStore = useDashboardStore(metricsViewName); + $: dashboardStore = useDashboardStore(exploreName); $: projectId = useProjectId(params.organization, params.project); @@ -113,7 +114,7 @@ - +
diff --git a/web-admin/src/features/bookmarks/BookmarkFiltersFormSection.svelte b/web-admin/src/features/bookmarks/BookmarkFiltersFormSection.svelte index f8e7ec98d12..facb022405b 100644 --- a/web-admin/src/features/bookmarks/BookmarkFiltersFormSection.svelte +++ b/web-admin/src/features/bookmarks/BookmarkFiltersFormSection.svelte @@ -4,9 +4,9 @@ import { useDashboardStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; import type { V1TimeRange } from "@rilldata/web-common/runtime-client"; - export let metricsViewName: string; + export let exploreName: string; - $: dashboardStore = useDashboardStore(metricsViewName); + $: dashboardStore = useDashboardStore(exploreName); let timeRange: V1TimeRange; $: timeRange = { @@ -24,7 +24,7 @@ diff --git a/web-admin/src/features/bookmarks/BookmarkTimeRangeSwitch.svelte b/web-admin/src/features/bookmarks/BookmarkTimeRangeSwitch.svelte index bb755d86a04..86d2686f49e 100644 --- a/web-admin/src/features/bookmarks/BookmarkTimeRangeSwitch.svelte +++ b/web-admin/src/features/bookmarks/BookmarkTimeRangeSwitch.svelte @@ -6,6 +6,7 @@ import { runtime } from "@rilldata/web-common/runtime-client/runtime-store.js"; export let metricsViewName: string; + export let exploreName: string; export let checked: boolean; const queryClient = useQueryClient(); @@ -13,6 +14,7 @@ queryClient, $runtime?.instanceId, metricsViewName, + exploreName, ); diff --git a/web-admin/src/features/bookmarks/Bookmarks.svelte b/web-admin/src/features/bookmarks/Bookmarks.svelte index bf12d462ad5..9642ba20c19 100644 --- a/web-admin/src/features/bookmarks/Bookmarks.svelte +++ b/web-admin/src/features/bookmarks/Bookmarks.svelte @@ -24,20 +24,22 @@ import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus"; export let metricsViewName: string; + export let exploreName: string; let showDialog = false; let bookmark: BookmarkEntry | null = null; - $: bookmarkApplier = createBookmarkApplier( - $runtime?.instanceId, - metricsViewName, - ); + $: bookmarkApplier = createBookmarkApplier($runtime?.instanceId, exploreName); - $: dashboardStore = useDashboardStore(metricsViewName); + $: dashboardStore = useDashboardStore(exploreName); $: projectId = useProjectId($page.params.organization, $page.params.project); const queryClient = useQueryClient(); - $: homeBookmarkModifier = createHomeBookmarkModifier($runtime?.instanceId); + $: homeBookmarkModifier = createHomeBookmarkModifier( + $runtime?.instanceId, + metricsViewName, + exploreName, + ); const bookmarkDeleter = createAdminServiceRemoveBookmark(); function selectBookmark(bookmark: BookmarkEntry) { @@ -52,8 +54,8 @@ return queryClient.refetchQueries( getAdminServiceListBookmarksQueryKey({ projectId: $projectId.data ?? "", - resourceKind: ResourceKind.MetricsView, - resourceName: metricsViewName, + resourceKind: ResourceKind.Explore, + resourceName: exploreName, }), ); } @@ -98,6 +100,7 @@ }} on:select={({ detail }) => selectBookmark(detail)} {metricsViewName} + {exploreName} /> @@ -105,6 +108,7 @@ { showDialog = false; bookmark = null; diff --git a/web-admin/src/features/bookmarks/BookmarksDropdownMenuContent.svelte b/web-admin/src/features/bookmarks/BookmarksDropdownMenuContent.svelte index 1959e67d9c3..ffad6412388 100644 --- a/web-admin/src/features/bookmarks/BookmarksDropdownMenuContent.svelte +++ b/web-admin/src/features/bookmarks/BookmarksDropdownMenuContent.svelte @@ -21,6 +21,7 @@ import HomeBookmarkPlus from "@rilldata/web-common/components/icons/HomeBookmarkPlus.svelte"; export let metricsViewName: string; + export let exploreName: string; const dispatch = createEventDispatcher(); const queryClient = useQueryClient(); @@ -36,6 +37,7 @@ organization, project, metricsViewName, + exploreName, ); $: filteredBookmarks = searchBookmarks($bookmarks.data, searchText); diff --git a/web-admin/src/features/bookmarks/applyBookmark.ts b/web-admin/src/features/bookmarks/applyBookmark.ts index de23149485b..6315a12fc5c 100644 --- a/web-admin/src/features/bookmarks/applyBookmark.ts +++ b/web-admin/src/features/bookmarks/applyBookmark.ts @@ -1,33 +1,32 @@ import type { V1Bookmark } from "@rilldata/web-admin/client"; -import { useMetricsView } from "@rilldata/web-common/features/dashboards/selectors"; import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; +import { useValidExplore } from "@rilldata/web-common/features/explores/selectors"; import { createQueryServiceMetricsViewSchema } from "@rilldata/web-common/runtime-client"; import { get } from "svelte/store"; -export function createBookmarkApplier( - instanceId: string, - metricsViewName: string, -) { - const metricsViewSpec = useMetricsView(instanceId, metricsViewName); +export function createBookmarkApplier(instanceId: string, exploreName: string) { + const validExploreSpec = useValidExplore(instanceId, exploreName); const metricsSchema = createQueryServiceMetricsViewSchema( instanceId, - metricsViewName, + exploreName, ); return (bookmark: V1Bookmark) => { - const metricsViewSpecResp = get(metricsViewSpec); + const validExploreSpecResp = get(validExploreSpec); const metricsSchemaResp = get(metricsSchema); if ( !bookmark.data || - !metricsViewSpecResp.data || + !validExploreSpecResp.data?.metricsView || + !validExploreSpecResp.data?.explore || !metricsSchemaResp.data?.schema ) { return; } metricsExplorerStore.syncFromUrl( - metricsViewName, + exploreName, decodeURIComponent(bookmark.data), - metricsViewSpecResp.data, + validExploreSpecResp.data.metricsView, + validExploreSpecResp.data.explore, metricsSchemaResp.data.schema, ); }; diff --git a/web-admin/src/features/bookmarks/createOrUpdateHomeBookmark.ts b/web-admin/src/features/bookmarks/createOrUpdateHomeBookmark.ts index 19b9842a4f6..8b6f1a6968c 100644 --- a/web-admin/src/features/bookmarks/createOrUpdateHomeBookmark.ts +++ b/web-admin/src/features/bookmarks/createOrUpdateHomeBookmark.ts @@ -9,7 +9,11 @@ import { ResourceKind } from "@rilldata/web-common/features/entity-management/re import { useQueryClient } from "@tanstack/svelte-query"; import { get } from "svelte/store"; -export function createHomeBookmarkModifier(instanceId: string) { +export function createHomeBookmarkModifier( + instanceId: string, + metricsViewName: string, + exploreName: string, +) { const bookmarkCreator = createAdminServiceCreateBookmark(); const bookmarkUpdater = createAdminServiceUpdateBookmark(); const projectIdRes = useProjectId( @@ -21,7 +25,8 @@ export function createHomeBookmarkModifier(instanceId: string) { instanceId, get(page).params.organization, get(page).params.project, - get(page).params.dashboard, + metricsViewName, + exploreName, ); return (data: string) => { @@ -48,8 +53,8 @@ export function createHomeBookmarkModifier(instanceId: string) { displayName: "Home", description: "Main view For this dashboard", projectId: projectId.data, - resourceKind: ResourceKind.MetricsView, - resourceName: get(page).params.dashboard, + resourceKind: ResourceKind.Explore, + resourceName: exploreName, shared: true, default: true, data, diff --git a/web-admin/src/features/bookmarks/selectors.ts b/web-admin/src/features/bookmarks/selectors.ts index f0d372311b2..2d1eba4fee4 100644 --- a/web-admin/src/features/bookmarks/selectors.ts +++ b/web-admin/src/features/bookmarks/selectors.ts @@ -6,17 +6,16 @@ import { import { useProjectId } from "@rilldata/web-admin/features/projects/selectors"; import type { CompoundQueryResult } from "@rilldata/web-common/features/compound-query-result"; import { getDashboardStateFromUrl } from "@rilldata/web-common/features/dashboards/proto-state/fromProto"; -import { - useMetricsView, - useMetricsViewTimeRange, -} from "@rilldata/web-common/features/dashboards/selectors"; +import { useMetricsViewTimeRange } from "@rilldata/web-common/features/dashboards/selectors"; import { useDashboardStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; import { timeControlStateSelector } from "@rilldata/web-common/features/dashboards/time-controls/time-control-store"; import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors"; +import { useValidExplore } from "@rilldata/web-common/features/explores/selectors"; import { prettyFormatTimeRange } from "@rilldata/web-common/lib/time/ranges"; import { TimeRangePreset } from "@rilldata/web-common/lib/time/types"; import { createQueryServiceMetricsViewSchema, + type V1ExploreSpec, type V1MetricsViewSpec, type V1StructType, } from "@rilldata/web-common/runtime-client"; @@ -41,27 +40,29 @@ export function getBookmarks( orgName: string, projectName: string, metricsViewName: string, + exploreName: string, ): CreateQueryResult { return derived( [ useProjectId(orgName, projectName), - useMetricsView(instanceId, metricsViewName), + useValidExplore(instanceId, exploreName), createQueryServiceMetricsViewSchema(instanceId, metricsViewName), createAdminServiceGetCurrentUser(), ], - ([projectId, metricsViewResp, schemaResp, userResp], set) => + ([projectId, validSpec, schemaResp, userResp], set) => createAdminServiceListBookmarks( { projectId: projectId.data, - resourceKind: ResourceKind.MetricsView, - resourceName: metricsViewName, + resourceKind: ResourceKind.Explore, + resourceName: exploreName, }, { query: { enabled: !!projectId?.data && !!metricsViewName && - !metricsViewResp.isFetching && + !!exploreName && + !validSpec.isFetching && !schemaResp.isFetching && userResp.isSuccess && !!userResp.data.user, @@ -74,8 +75,9 @@ export function getBookmarks( resp.bookmarks?.forEach((bookmarkResource) => { const bookmark = parseBookmarkEntry( bookmarkResource, - metricsViewResp.data as V1MetricsViewSpec, - schemaResp.data?.schema as V1StructType, + validSpec.data.metricsView, + validSpec.data.explore, + schemaResp.data?.schema, ); if (bookmarkResource.default) { bookmarks.home = bookmark; @@ -116,6 +118,7 @@ export function getHomeBookmarkData( orgName: string, projectName: string, metricsViewName: string, + exploreName: string, ): CompoundQueryResult { return derived( getBookmarks( @@ -124,6 +127,7 @@ export function getHomeBookmarkData( orgName, projectName, metricsViewName, + exploreName, ), (bookmarks) => { if (bookmarks.isFetching || !bookmarks.data) { @@ -150,18 +154,20 @@ export function getPrettySelectedTimeRange( queryClient: QueryClient, instanceId: string, metricsViewName: string, + exploreName: string, ): Readable { return derived( [ - useMetricsView(instanceId, metricsViewName), + useValidExplore(instanceId, exploreName), useMetricsViewTimeRange(instanceId, metricsViewName, { query: { queryClient }, }), useDashboardStore(metricsViewName), ], - ([metricViewSpec, timeRangeSummary, metricsExplorerEntity]) => { + ([validSpec, timeRangeSummary, metricsExplorerEntity]) => { const timeRangeState = timeControlStateSelector([ - metricViewSpec, + validSpec.data.metricsView, + validSpec.data.explore, timeRangeSummary, metricsExplorerEntity, ]); @@ -179,11 +185,13 @@ export function getPrettySelectedTimeRange( function parseBookmarkEntry( bookmarkResource: V1Bookmark, metricsViewSpec: V1MetricsViewSpec, + exploreSpec: V1ExploreSpec, schema: V1StructType, ): BookmarkEntry { const metricsEntity = getDashboardStateFromUrl( bookmarkResource.data ?? "", metricsViewSpec, + exploreSpec, schema, ); return { diff --git a/web-admin/src/routes/[organization]/[project]/[dashboard]/+page.svelte b/web-admin/src/routes/[organization]/[project]/explore/[name]/+page.svelte similarity index 78% rename from web-admin/src/routes/[organization]/[project]/[dashboard]/+page.svelte rename to web-admin/src/routes/[organization]/[project]/explore/[name]/+page.svelte index deb8e73a131..6d7c9640dc8 100644 --- a/web-admin/src/routes/[organization]/[project]/[dashboard]/+page.svelte +++ b/web-admin/src/routes/[organization]/[project]/explore/[name]/+page.svelte @@ -5,15 +5,15 @@ import DashboardBookmarksStateProvider from "@rilldata/web-admin/features/dashboards/DashboardBookmarksStateProvider.svelte"; import DashboardBuilding from "@rilldata/web-admin/features/dashboards/DashboardBuilding.svelte"; import DashboardErrored from "@rilldata/web-admin/features/dashboards/DashboardErrored.svelte"; + import { errorStore } from "@rilldata/web-admin/features/errors/error-store"; import { viewAsUserStore } from "@rilldata/web-admin/features/view-as-user/viewAsUserStore"; import { Dashboard } from "@rilldata/web-common/features/dashboards"; import DashboardThemeProvider from "@rilldata/web-common/features/dashboards/DashboardThemeProvider.svelte"; import DashboardURLStateProvider from "@rilldata/web-common/features/dashboards/proto-state/DashboardURLStateProvider.svelte"; - import { useDashboard } from "@rilldata/web-common/features/dashboards/selectors"; import StateManagersProvider from "@rilldata/web-common/features/dashboards/state-managers/StateManagersProvider.svelte"; import DashboardStateProvider from "@rilldata/web-common/features/dashboards/stores/DashboardStateProvider.svelte"; + import { useExplore } from "@rilldata/web-common/features/explores/selectors"; import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; - import { errorStore } from "../../../../features/errors/error-store"; const user = createAdminServiceGetCurrentUser(); @@ -26,10 +26,10 @@ $: ({ organization: orgName, project: projectName, - dashboard: dashboardName, + name: exploreName, } = $page.params); - $: dashboard = useDashboard(instanceId, dashboardName, { + $: explore = useExplore(instanceId, exploreName, { refetchInterval: () => { if (isDashboardReconcilingForFirstTime) { return PollIntervalWhenDashboardFirstReconciling; @@ -42,19 +42,20 @@ }); $: isDashboardNotFound = - !$dashboard.data && - $dashboard.isError && - $dashboard.error?.response?.status === 404; + !$explore.data && + $explore.isError && + $explore.error?.response?.status === 404; + // TODO: should these be checking metricsView or explore? $: isDashboardReconcilingForFirstTime = - $dashboard?.data?.metricsView?.state?.validSpec === null && - !$dashboard?.data?.meta?.reconcileError; + $explore?.data?.metricsView?.metricsView?.state?.validSpec === null && + !$explore?.data?.metricsView?.meta?.reconcileError; // We check for metricsView.state.validSpec instead of meta.reconcileError. validSpec persists // from previous valid dashboards, allowing display even when the current dashboard spec is invalid // and a meta.reconcileError exists. $: isDashboardErrored = - $dashboard?.data?.metricsView?.state?.validSpec === null && - !!$dashboard?.data?.meta?.reconcileError; - $: metricViewName = $dashboard.data?.meta.name.name; + $explore?.data?.metricsView?.metricsView?.state?.validSpec === null && + !!$explore?.data?.metricsView?.meta?.reconcileError; + $: metricViewName = $explore.data?.metricsView?.meta?.name?.name; // If no dashboard is found, show a 404 page $: if (isDashboardNotFound) { @@ -74,30 +75,30 @@ - {dashboardName} - Rill + {exploreName} - Rill -{#if $dashboard.isSuccess} +{#if $explore.isSuccess} {#if isDashboardReconcilingForFirstTime} {:else if isDashboardErrored} {:else if metricViewName} {#key metricViewName} - + {#if $user.isSuccess && $user.data.user} - + {:else} - + - + diff --git a/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte b/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte index 1e2a8acebe0..e151701706d 100644 --- a/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte +++ b/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte @@ -3,7 +3,10 @@ The main feature-set component for dashboard filters --> diff --git a/web-admin/src/features/dashboards/listing/selectors.ts b/web-admin/src/features/dashboards/listing/selectors.ts index 73060be731d..fd114b6c0a8 100644 --- a/web-admin/src/features/dashboards/listing/selectors.ts +++ b/web-admin/src/features/dashboards/listing/selectors.ts @@ -1,5 +1,6 @@ import { createAdminServiceGetProject } from "@rilldata/web-admin/client"; import { useValidDashboards } from "@rilldata/web-common/features/dashboards/selectors"; +import { getMapFromArray } from "@rilldata/web-common/lib/arrayUtils"; import type { V1Resource } from "@rilldata/web-common/runtime-client"; import { createRuntimeServiceListResources } from "@rilldata/web-common/runtime-client"; import type { CreateQueryResult } from "@tanstack/svelte-query"; @@ -47,19 +48,36 @@ export interface DashboardResource { function getDashboardRefreshedOn( dashboard: V1Resource, - allResources: V1Resource[], + allResources: Map, ): string | undefined { if (!dashboard) return undefined; - const refName = dashboard.meta.refs[0]; - const refTable = allResources.find( - (r) => r.meta?.name?.name === refName?.name, + const metricsViewRefName = dashboard.meta.refs[0]; + const refTable = allResources.get( + `${metricsViewRefName?.kind}_${metricsViewRefName?.name}`, ); return ( refTable?.model?.state.refreshedOn || refTable?.source?.state.refreshedOn ); } +function getExploreRefreshedOn( + explore: V1Resource, + allResources: Map, +): string | undefined { + if (!explore) return undefined; + + // 1st get the metrics view for the explore + const exploreRefName = explore.meta.refs[0]; + const metricsView = allResources.get( + `${exploreRefName?.kind}_${exploreRefName?.name}`, + ); + if (!metricsView) return undefined; + + // next get the referenced table resource + return getDashboardRefreshedOn(metricsView, allResources); +} + // This iteration of `useDashboards` returns the above `DashboardResource` type, which includes `refreshedOn` export function useDashboardsV2( instanceId: string, @@ -67,15 +85,31 @@ export function useDashboardsV2( return createRuntimeServiceListResources(instanceId, undefined, { query: { select: (data) => { - // Filter for Metrics Explorers and Custom Dashboards - const resources = data.resources.filter( - (res) => res.metricsView || res.dashboard, + // create a map since we are potentially looking up twice per explore + const allResources = getMapFromArray( + data.resources, + (r) => `${r.meta.name.kind}_${r.meta.name.name}`, ); - // Add `refreshedOn` to each resource - return resources.map((resource) => { - const refreshedOn = getDashboardRefreshedOn(resource, data.resources); - return { resource, refreshedOn }; - }); + const allDashboards: DashboardResource[] = []; + // filter canvas dashboards + const canvasDashboards = data.resources.filter((res) => res.dashboard); + allDashboards.push( + ...canvasDashboards.map((resource) => { + // Add `refreshedOn` to each resource + const refreshedOn = getDashboardRefreshedOn(resource, allResources); + return { resource, refreshedOn }; + }), + ); + // filter explores + const explores = data.resources.filter((res) => res.explore); + allDashboards.push( + ...explores.map((resource) => { + // Add `refreshedOn` to each resource + const refreshedOn = getExploreRefreshedOn(resource, allResources); + return { resource, refreshedOn }; + }), + ); + return allDashboards; }, }, }); @@ -92,11 +126,22 @@ export function useDashboardV2( select: (data) => { if (!name) return; - const dashboard = data.resources.find( + const resource = data.resources.find( (res) => res.meta.name.name.toLowerCase() === name.toLowerCase(), ); - const refreshedOn = getDashboardRefreshedOn(dashboard, data.resources); - return { resource: dashboard, refreshedOn }; + // create a map since we are potentially looking up twice per explore + const allResources = getMapFromArray( + data.resources, + (r) => `${r.meta.name.kind}_${r.meta.name.name}`, + ); + + if (resource.dashboard) { + const refreshedOn = getDashboardRefreshedOn(resource, allResources); + return { resource, refreshedOn }; + } + + const refreshedOn = getExploreRefreshedOn(resource, allResources); + return { resource, refreshedOn }; }, }, }); diff --git a/web-admin/src/features/navigation/TopNavigationBar.svelte b/web-admin/src/features/navigation/TopNavigationBar.svelte index ffa51b19f28..963f33600af 100644 --- a/web-admin/src/features/navigation/TopNavigationBar.svelte +++ b/web-admin/src/features/navigation/TopNavigationBar.svelte @@ -9,6 +9,7 @@ import GlobalDimensionSearch from "@rilldata/web-common/features/dashboards/dimension-search/GlobalDimensionSearch.svelte"; import { useDashboard } from "@rilldata/web-common/features/dashboards/selectors"; import StateManagersProvider from "@rilldata/web-common/features/dashboards/state-managers/StateManagersProvider.svelte"; + import { useExplore } from "@rilldata/web-common/features/explores/selectors"; import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; import { createAdminServiceGetCurrentUser, @@ -103,13 +104,13 @@ $: visualizationPaths = visualizations.reduce((map, { resource }) => { const name = resource.meta.name.name; - const isMetricsExplorer = !!resource?.metricsView; + const isMetricsExplorer = !!resource?.explore; return map.set(name.toLowerCase(), { label: (isMetricsExplorer - ? resource?.metricsView?.spec?.title + ? resource?.explore?.spec?.title : resource?.dashboard?.spec?.title) || name, - section: isMetricsExplorer ? undefined : "-/dashboards", + section: isMetricsExplorer ? "/explore" : "-/dashboards", }); }, new Map()); @@ -136,10 +137,11 @@ report ? reportPaths : alert ? alertPaths : null, ]; - $: dashboardQuery = useDashboard(instanceId, dashboardParam, { + $: dashboardQuery = useExplore(instanceId, dashboardParam, { enabled: !!instanceId && onMetricsExplorerPage, }); - $: isDashboardValid = !!$dashboardQuery.data?.metricsView?.state?.validSpec; + $: exploreSpec = $dashboardQuery.data?.explore?.explore?.state?.validSpec; + $: isDashboardValid = !!exploreSpec; // Public URLs do not have the metrics view name in the URL. However, the magic token's metadata includes the metrics view name. $: tokenQuery = createAdminServiceGetMagicAuthToken(token); @@ -186,12 +188,18 @@ {/if} {#if (onMetricsExplorerPage && isDashboardValid) || onPublicURLPage} {#key dashboard} - + - + {#if $user.isSuccess && $user.data.user && !onPublicURLPage} - + {/if} diff --git a/web-admin/src/features/navigation/nav-utils.ts b/web-admin/src/features/navigation/nav-utils.ts index 9a208b4359c..1c726979dc5 100644 --- a/web-admin/src/features/navigation/nav-utils.ts +++ b/web-admin/src/features/navigation/nav-utils.ts @@ -25,7 +25,7 @@ export function withinProject(page: Page): boolean { export function isMetricsExplorerPage(page: Page): boolean { return ( - page.route.id === "/[organization]/[project]/[dashboard]" || + page.route.id === "/[organization]/[project]/explore/[dashboard]" || page.route.id === "/-/embed" ); } diff --git a/web-admin/src/routes/[organization]/[project]/explore/[name]/+page.svelte b/web-admin/src/routes/[organization]/[project]/explore/[dashboard]/+page.svelte similarity index 97% rename from web-admin/src/routes/[organization]/[project]/explore/[name]/+page.svelte rename to web-admin/src/routes/[organization]/[project]/explore/[dashboard]/+page.svelte index 6d7c9640dc8..dfd562e9d11 100644 --- a/web-admin/src/routes/[organization]/[project]/explore/[name]/+page.svelte +++ b/web-admin/src/routes/[organization]/[project]/explore/[dashboard]/+page.svelte @@ -26,7 +26,7 @@ $: ({ organization: orgName, project: projectName, - name: exploreName, + dashboard: exploreName, } = $page.params); $: explore = useExplore(instanceId, exploreName, { @@ -87,7 +87,7 @@ {#key metricViewName} {#if $user.isSuccess && $user.data.user} - + diff --git a/web-common/src/features/dashboards/filters/Filters.svelte b/web-common/src/features/dashboards/filters/Filters.svelte index 702406889be..e831b815ae5 100644 --- a/web-common/src/features/dashboards/filters/Filters.svelte +++ b/web-common/src/features/dashboards/filters/Filters.svelte @@ -25,6 +25,7 @@ const StateManagers = getStateManagers(); const { metricsViewName, + exploreName, actions: { dimensionsFilter: { toggleDimensionValueSelection, @@ -107,7 +108,7 @@ {selectedComparisonTimeRange} /> {#if !$showPivot && minTimeGrain} - + {/if} {/if}
diff --git a/web-common/src/features/dashboards/time-controls/super-pill/SuperPill.svelte b/web-common/src/features/dashboards/time-controls/super-pill/SuperPill.svelte index 25904328eae..469675726c6 100644 --- a/web-common/src/features/dashboards/time-controls/super-pill/SuperPill.svelte +++ b/web-common/src/features/dashboards/time-controls/super-pill/SuperPill.svelte @@ -32,6 +32,7 @@ const ctx = getStateManagers(); const { metricsViewName, + exploreName, selectors: { timeRangeSelectors: { timeRangeSelectorState }, charts: { canPanLeft, canPanRight, getNewPanRange }, @@ -39,7 +40,7 @@ validSpecStore, } = ctx; - $: localUserPreferences = initLocalUserPreferenceStore(metricViewName); + $: localUserPreferences = initLocalUserPreferenceStore($exploreName); $: metricViewName = $metricsViewName; $: metricsViewSpec = $validSpecStore.data?.metricsView ?? {}; From 01944a0be29a0ffc3f825ddfdddda86105d6cb20 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Mon, 23 Sep 2024 11:55:41 +0530 Subject: [PATCH 08/48] Fix alerts and reports --- .../alerts/metadata/AlertMetadata.svelte | 16 ++++++---- web-admin/src/features/alerts/selectors.ts | 11 +++++-- .../getDashboardFromAggregationRequest.ts | 5 +++ .../query-mappers/mapQueryToDashboard.ts | 32 ++++++++++++------- .../dashboards/query-mappers/types.ts | 2 ++ .../dashboards/query-mappers/utils.ts | 20 ++++++++++++ .../metadata/ReportMetadata.svelte | 9 +++--- .../-/alerts/[alert]/open/+page.svelte | 18 +++++++++-- .../-/reports/[report]/open/+page.svelte | 18 +++++++++-- .../features/alerts/CreateAlertForm.svelte | 3 ++ .../src/features/alerts/EditAlertForm.svelte | 5 +++ .../alerts/data-tab/AlertDialogDataTab.svelte | 2 +- web-common/src/features/alerts/form-utils.ts | 1 + .../ExportDimensionTableDataButton.svelte | 3 +- .../dashboards/pivot/PivotExportButton.svelte | 3 +- .../TDDExportButton.svelte | 6 ++-- .../time-dimension-details/TDDHeader.svelte | 2 +- web-common/src/features/explores/selectors.ts | 1 + .../CreateScheduledReportDialog.svelte | 2 ++ .../EditScheduledReportDialog.svelte | 3 ++ .../src/features/scheduled-reports/utils.ts | 4 +++ 21 files changed, 130 insertions(+), 36 deletions(-) diff --git a/web-admin/src/features/alerts/metadata/AlertMetadata.svelte b/web-admin/src/features/alerts/metadata/AlertMetadata.svelte index 3d06e885798..6cc65b86ceb 100644 --- a/web-admin/src/features/alerts/metadata/AlertMetadata.svelte +++ b/web-admin/src/features/alerts/metadata/AlertMetadata.svelte @@ -22,7 +22,7 @@ import ThreeDot from "@rilldata/web-common/components/icons/ThreeDot.svelte"; import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte"; import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte"; - import { useDashboard } from "@rilldata/web-common/features/dashboards/selectors"; + import { useValidExplore } from "@rilldata/web-common/features/explores/selectors"; import { getRuntimeServiceListResourcesQueryKey, type V1MetricsViewAggregationRequest, @@ -39,9 +39,9 @@ // Get dashboard $: dashboardName = useAlertDashboardName($runtime.instanceId, alert); - $: dashboard = useDashboard($runtime.instanceId, $dashboardName.data); - $: dashboardTitle = - $dashboard.data?.metricsView.spec.title || $dashboardName.data; + $: dashboard = useValidExplore($runtime.instanceId, $dashboardName.data); + $: metricsViewName = $dashboard.data?.explore?.metricsView; + $: dashboardTitle = $dashboard.data?.explore?.title || $dashboardName.data; $: dashboardDoesNotExist = $dashboard.error?.response?.status === 404; $: alertSpec = $alertQuery.data?.resource?.alert?.spec; @@ -99,7 +99,7 @@
{#if !$isAlertCreatedByCode.data} - + @@ -134,7 +134,9 @@
{:else} - + {dashboardTitle} {/if} @@ -170,7 +172,7 @@ { + const alertSpec = data.resource?.alert?.spec; + if (!alertSpec) return ""; + + if (alertSpec.annotations.web_open_path) + return getExploreName(alertSpec.annotations.web_open_path); + const queryArgsJson = JSON.parse( - data.resource.alert.spec.resolverProperties.query_args_json || - data.resource.alert.spec.queryArgsJson || + alertSpec.resolverProperties.query_args_json || + alertSpec.queryArgsJson || "{}", ); diff --git a/web-admin/src/features/dashboards/query-mappers/getDashboardFromAggregationRequest.ts b/web-admin/src/features/dashboards/query-mappers/getDashboardFromAggregationRequest.ts index e0f1d9c4352..c46174a728b 100644 --- a/web-admin/src/features/dashboards/query-mappers/getDashboardFromAggregationRequest.ts +++ b/web-admin/src/features/dashboards/query-mappers/getDashboardFromAggregationRequest.ts @@ -26,6 +26,7 @@ import { DashboardState_ActivePage } from "@rilldata/web-common/proto/gen/rill/u import { getQueryServiceMetricsViewSchemaQueryKey, queryServiceMetricsViewSchema, + type V1ExploreSpec, type V1Expression, type V1MetricsViewAggregationRequest, type V1MetricsViewSpec, @@ -40,6 +41,7 @@ export async function getDashboardFromAggregationRequest({ timeRangeSummary, executionTime, metricsView, + explore, annotations, }: QueryMapperArgs) { let loadedFromState = false; @@ -49,6 +51,7 @@ export async function getDashboardFromAggregationRequest({ instanceId, dashboard, metricsView, + explore, annotations["web_open_state"], ); loadedFromState = true; @@ -166,6 +169,7 @@ async function mergeDashboardFromUrlState( instanceId: string, dashboard: MetricsExplorerEntity, metricsViewSpec: V1MetricsViewSpec, + exploreSpec: V1ExploreSpec, urlState: string, ) { const schemaResp = await queryClient.fetchQuery({ @@ -180,6 +184,7 @@ async function mergeDashboardFromUrlState( const parsedDashboard = getDashboardStateFromUrl( urlState, metricsViewSpec, + exploreSpec, schemaResp.schema, ); for (const k in parsedDashboard) { diff --git a/web-admin/src/features/dashboards/query-mappers/mapQueryToDashboard.ts b/web-admin/src/features/dashboards/query-mappers/mapQueryToDashboard.ts index 16874fc7212..a61c1a72b9d 100644 --- a/web-admin/src/features/dashboards/query-mappers/mapQueryToDashboard.ts +++ b/web-admin/src/features/dashboards/query-mappers/mapQueryToDashboard.ts @@ -6,10 +6,10 @@ import type { } from "@rilldata/web-admin/features/dashboards/query-mappers/types"; import type { CompoundQueryResult } from "@rilldata/web-common/features/compound-query-result"; import { getProtoFromDashboardState } from "@rilldata/web-common/features/dashboards/proto-state/toProto"; -import { useMetricsView } from "@rilldata/web-common/features/dashboards/selectors"; import { getDefaultMetricsExplorerEntity } from "@rilldata/web-common/features/dashboards/stores/dashboard-store-defaults"; import type { MetricsExplorerEntity } from "@rilldata/web-common/features/dashboards/stores/metrics-explorer-entity"; import { initLocalUserPreferenceStore } from "@rilldata/web-common/features/dashboards/user-preferences"; +import { useValidExplore } from "@rilldata/web-common/features/explores/selectors"; import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient"; import { createQueryServiceMetricsViewTimeRange, @@ -21,7 +21,7 @@ import { derived, get, readable } from "svelte/store"; type DashboardStateForQuery = { state?: string; - metricsView?: string; + exploreName?: string; }; /** @@ -29,6 +29,7 @@ type DashboardStateForQuery = { * Used to show the relevant dashboard for a report/alert. */ export function mapQueryToDashboard( + exploreName: string, queryName: string | undefined, queryArgsJson: string | undefined, executionTime: string | undefined, @@ -76,12 +77,14 @@ export function mapQueryToDashboard( "Failed to find metrics view name. Please check the format of the report.", }); } + // backwards compatibility for older alerts created on metrics explore directly + if (!exploreName) exploreName = metricsViewName; const instanceId = get(runtime).instanceId; return derived( [ - useMetricsView(instanceId, metricsViewName), + useValidExplore(instanceId, exploreName), // TODO: handle non-timestamp dashboards createQueryServiceMetricsViewTimeRange( get(runtime).instanceId, @@ -89,8 +92,12 @@ export function mapQueryToDashboard( {}, ), ], - ([metricsViewResource, timeRangeSummary], set) => { - if (!metricsViewResource.data || !timeRangeSummary.data) { + ([validSpecResp, timeRangeSummary], set) => { + if ( + !validSpecResp.data?.metricsView || + !validSpecResp.data?.explore || + !timeRangeSummary.data + ) { set({ isFetching: true, error: "", @@ -98,21 +105,23 @@ export function mapQueryToDashboard( return; } - if (metricsViewResource.error || timeRangeSummary.error) { + if (validSpecResp.error || timeRangeSummary.error) { // error state set({ isFetching: false, error: - metricsViewResource.error?.message ?? - timeRangeSummary.error?.message, + validSpecResp.error?.message ?? timeRangeSummary.error?.message, }); return; } + const { metricsView, explore } = validSpecResp.data; + initLocalUserPreferenceStore(metricsViewName); const defaultDashboard = getDefaultMetricsExplorerEntity( metricsViewName, - metricsViewResource.data, + metricsView, + explore, timeRangeSummary.data, ); getDashboardState({ @@ -120,7 +129,8 @@ export function mapQueryToDashboard( instanceId, dashboard: defaultDashboard, req, - metricsView: metricsViewResource.data, + metricsView, + explore, timeRangeSummary: timeRangeSummary.data.timeRangeSummary, executionTime, annotations, @@ -131,7 +141,7 @@ export function mapQueryToDashboard( error: "", data: { state: getProtoFromDashboardState(newDashboard), - metricsView: metricsViewName, + exploreName, }, }); }) diff --git a/web-admin/src/features/dashboards/query-mappers/types.ts b/web-admin/src/features/dashboards/query-mappers/types.ts index 549c85cd662..4e1c329752b 100644 --- a/web-admin/src/features/dashboards/query-mappers/types.ts +++ b/web-admin/src/features/dashboards/query-mappers/types.ts @@ -1,5 +1,6 @@ import type { MetricsExplorerEntity } from "@rilldata/web-common/features/dashboards/stores/metrics-explorer-entity"; import type { + V1ExploreSpec, V1MetricsViewAggregationRequest, V1MetricsViewComparisonRequest, V1MetricsViewRowsRequest, @@ -23,6 +24,7 @@ export type QueryMapperArgs = { dashboard: MetricsExplorerEntity; req: R; metricsView: V1MetricsViewSpec; + explore: V1ExploreSpec; timeRangeSummary: V1TimeRangeSummary; executionTime: string; annotations: Record; diff --git a/web-admin/src/features/dashboards/query-mappers/utils.ts b/web-admin/src/features/dashboards/query-mappers/utils.ts index 8e497ae911b..861f607abac 100644 --- a/web-admin/src/features/dashboards/query-mappers/utils.ts +++ b/web-admin/src/features/dashboards/query-mappers/utils.ts @@ -201,3 +201,23 @@ export async function convertExprToToplist( toplist.data.map((t) => t[dimensionName]), ); } + +const ExploreNameRegex = /\/explore\/((?:\w|-)+)/; +export function getExploreName(webOpenPath: string) { + const matches = ExploreNameRegex.exec(webOpenPath); + if (!matches || matches.length < 1) return ""; + return matches[1]; +} + +export function getExplorePageUrl( + curPageUrl: URL, + organization: string, + project: string, + exploreName: string, + state: string, +) { + const url = new URL(`${curPageUrl.protocol}//${curPageUrl.host}`); + url.pathname = `/${organization}/${project}/explore/${exploreName}`; + url.searchParams.set("state", state); + return url.toString(); +} diff --git a/web-admin/src/features/scheduled-reports/metadata/ReportMetadata.svelte b/web-admin/src/features/scheduled-reports/metadata/ReportMetadata.svelte index a8f73c78e61..759270af2b7 100644 --- a/web-admin/src/features/scheduled-reports/metadata/ReportMetadata.svelte +++ b/web-admin/src/features/scheduled-reports/metadata/ReportMetadata.svelte @@ -5,7 +5,7 @@ import IconButton from "@rilldata/web-common/components/button/IconButton.svelte"; import * as DropdownMenu from "@rilldata/web-common/components/dropdown-menu"; import ThreeDot from "@rilldata/web-common/components/icons/ThreeDot.svelte"; - import { useDashboard } from "@rilldata/web-common/features/dashboards/selectors"; + import { useValidExplore } from "@rilldata/web-common/features/explores/selectors"; import EditScheduledReportDialog from "@rilldata/web-common/features/scheduled-reports/EditScheduledReportDialog.svelte"; import { getRuntimeServiceListResourcesQueryKey } from "@rilldata/web-common/runtime-client"; import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; @@ -36,9 +36,8 @@ // Get dashboard $: dashboardName = useReportDashboardName($runtime.instanceId, report); - $: dashboard = useDashboard($runtime.instanceId, $dashboardName.data); - $: dashboardTitle = - $dashboard.data?.metricsView.spec.title || $dashboardName.data; + $: dashboard = useValidExplore($runtime.instanceId, $dashboardName.data); + $: dashboardTitle = $dashboard.data?.explore?.title || $dashboardName.data; // Get human-readable frequency $: humanReadableFrequency = @@ -140,7 +139,7 @@
Dashboard - {dashboardTitle} diff --git a/web-admin/src/routes/[organization]/[project]/-/alerts/[alert]/open/+page.svelte b/web-admin/src/routes/[organization]/[project]/-/alerts/[alert]/open/+page.svelte index c38eb72797e..5b957edd53a 100644 --- a/web-admin/src/routes/[organization]/[project]/-/alerts/[alert]/open/+page.svelte +++ b/web-admin/src/routes/[organization]/[project]/-/alerts/[alert]/open/+page.svelte @@ -3,6 +3,10 @@ import { page } from "$app/stores"; import { useAlert } from "@rilldata/web-admin/features/alerts/selectors"; import { mapQueryToDashboard } from "@rilldata/web-admin/features/dashboards/query-mappers/mapQueryToDashboard"; + import { + getExploreName, + getExplorePageUrl, + } from "@rilldata/web-admin/features/dashboards/query-mappers/utils.js"; import CtaButton from "@rilldata/web-common/components/calls-to-action/CTAButton.svelte"; import CtaContentContainer from "@rilldata/web-common/components/calls-to-action/CTAContentContainer.svelte"; import CtaLayoutContainer from "@rilldata/web-common/components/calls-to-action/CTALayoutContainer.svelte"; @@ -17,6 +21,9 @@ $: executionTime = $page.url.searchParams.get("execution_time"); $: alert = useAlert($runtime.instanceId, alertId); + $: exploreName = getExploreName( + $alert.data?.resource?.alert?.spec?.annotations?.web_open_path, + ); let dashboardStateForAlert: ReturnType; $: queryName = @@ -28,6 +35,7 @@ $alert.data?.resource?.alert?.spec?.queryArgsJson ?? ""; $: dashboardStateForAlert = mapQueryToDashboard( + exploreName, queryName, queryArgsJson, executionTime, @@ -39,8 +47,14 @@ } $: if ($dashboardStateForAlert.data) { - goto( - `/${organization}/${project}/${$dashboardStateForAlert.data.metricsView}?state=${encodeURIComponent($dashboardStateForAlert.data.state)}`, + void goto( + getExplorePageUrl( + $page.url, + organization, + project, + $dashboardStateForAlert.data.exploreName, + $dashboardStateForAlert.data.state, + ), ); } diff --git a/web-admin/src/routes/[organization]/[project]/-/reports/[report]/open/+page.svelte b/web-admin/src/routes/[organization]/[project]/-/reports/[report]/open/+page.svelte index a72a679082d..af8ab1f76b5 100644 --- a/web-admin/src/routes/[organization]/[project]/-/reports/[report]/open/+page.svelte +++ b/web-admin/src/routes/[organization]/[project]/-/reports/[report]/open/+page.svelte @@ -2,6 +2,10 @@ import { goto } from "$app/navigation"; import { page } from "$app/stores"; import { mapQueryToDashboard } from "@rilldata/web-admin/features/dashboards/query-mappers/mapQueryToDashboard"; + import { + getExploreName, + getExplorePageUrl, + } from "@rilldata/web-admin/features/dashboards/query-mappers/utils"; import { useReport } from "@rilldata/web-admin/features/scheduled-reports/selectors"; import CtaButton from "@rilldata/web-common/components/calls-to-action/CTAButton.svelte"; import CtaContentContainer from "@rilldata/web-common/components/calls-to-action/CTAContentContainer.svelte"; @@ -17,9 +21,13 @@ $: executionTime = $page.url.searchParams.get("execution_time"); $: report = useReport($runtime.instanceId, reportId); + $: exploreName = getExploreName( + $report.data?.resource?.report?.spec?.annotations?.web_open_path, + ); let dashboardStateForReport: ReturnType; $: dashboardStateForReport = mapQueryToDashboard( + exploreName, $report.data?.resource?.report?.spec?.queryName, $report.data?.resource?.report?.spec?.queryArgsJson, executionTime, @@ -27,8 +35,14 @@ ); $: if ($dashboardStateForReport.data) { - goto( - `/${organization}/${project}/${$dashboardStateForReport.data.metricsView}?state=${encodeURIComponent($dashboardStateForReport.data.state)}`, + void goto( + getExplorePageUrl( + $page.url, + organization, + project, + $dashboardStateForReport.data.exploreName, + $dashboardStateForReport.data.state, + ), ); } diff --git a/web-common/src/features/alerts/CreateAlertForm.svelte b/web-common/src/features/alerts/CreateAlertForm.svelte index c8e20d2e7b1..dfc6ca02fbb 100644 --- a/web-common/src/features/alerts/CreateAlertForm.svelte +++ b/web-common/src/features/alerts/CreateAlertForm.svelte @@ -38,6 +38,7 @@ const { metricsViewName, + exploreName, dashboardStore, selectors: { timeRangeSelectors: { timeControlsState }, @@ -98,6 +99,7 @@ // The remaining fields are not editable in the form, but it's helpful to have access to them throughout the alert dialog // Also, in the future, they might even be editable. metricsViewName: $metricsViewName, + exploreName: $exploreName, whereFilter: $dashboardStore.whereFilter, dimensionThresholdFilters: $dashboardStore.dimensionThresholdFilters, timeRange: timeRange @@ -138,6 +140,7 @@ : undefined, renotify: !!values.snooze, renotifyAfterSeconds: values.snooze ? Number(values.snooze) : 0, + webOpenPath: `/explore/${$exploreName}`, }, }, }); diff --git a/web-common/src/features/alerts/EditAlertForm.svelte b/web-common/src/features/alerts/EditAlertForm.svelte index 860b41a3545..a809960dfb8 100644 --- a/web-common/src/features/alerts/EditAlertForm.svelte +++ b/web-common/src/features/alerts/EditAlertForm.svelte @@ -1,6 +1,7 @@ @@ -187,23 +186,25 @@ {/if} {#if (onMetricsExplorerPage && isDashboardValid) || onPublicURLPage} - {#key dashboard} - - - - {#if $user.isSuccess && $user.data.user && !onPublicURLPage} - - - - {/if} - - {/key} + {#if exploreSpec} + {#key dashboard} + + + + {#if $user.isSuccess && $user.data.user && !onPublicURLPage} + + + + {/if} + + {/key} + {/if} {/if} {#if $user.isSuccess} {#if $user.data && $user.data.user} diff --git a/web-admin/src/features/public-urls/CreatePublicURLForm.svelte b/web-admin/src/features/public-urls/CreatePublicURLForm.svelte index f4dc18ede75..e48c9bce7b3 100644 --- a/web-admin/src/features/public-urls/CreatePublicURLForm.svelte +++ b/web-admin/src/features/public-urls/CreatePublicURLForm.svelte @@ -9,15 +9,16 @@ import Switch from "@rilldata/web-common/components/forms/Switch.svelte"; import FilterChipsReadOnly from "@rilldata/web-common/features/dashboards/filters/FilterChipsReadOnly.svelte"; import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers"; + import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors"; import { copyToClipboard } from "@rilldata/web-common/lib/actions/copy-to-clipboard"; import type { HTTPError } from "@rilldata/web-common/runtime-client/fetchWrapper"; + import { useQueryClient } from "@tanstack/svelte-query"; import { defaults, superForm } from "sveltekit-superforms"; import { yup } from "sveltekit-superforms/adapters"; import { object, string } from "yup"; - import { useQueryClient } from "@tanstack/svelte-query"; import { convertDateToMinutes, - getMetricsViewFields, + getExploreFields, getSanitizedDashboardStateParam, hasDashboardWhereFilter, } from "./form-utils"; @@ -25,18 +26,17 @@ const queryClient = useQueryClient(); const { dashboardStore, - metricsViewName, selectors: { measures: { visibleMeasures }, dimensions: { visibleDimensions }, }, } = getStateManagers(); - $: ({ organization, project } = $page.params); + $: ({ organization, project, dashboard } = $page.params); $: isTitleEmpty = $form.title.trim() === ""; - $: metricsViewFields = getMetricsViewFields( + $: exploreFields = getExploreFields( $dashboardStore, $visibleDimensions, $visibleMeasures, @@ -44,7 +44,7 @@ $: sanitizedState = getSanitizedDashboardStateParam( $dashboardStore, - metricsViewFields, + exploreFields, ); let token: string; @@ -78,11 +78,10 @@ organization, project, data: { - metricsView: $metricsViewName, - metricsViewFilter: hasWhereFilter - ? $dashboardStore.whereFilter - : undefined, - metricsViewFields, + resourceType: ResourceKind.Explore as string, + resourceName: dashboard, + filter: hasWhereFilter ? $dashboardStore.whereFilter : undefined, + fields: exploreFields, ttlMinutes: setExpiration ? convertDateToMinutes(values.expiresAt).toString() : undefined, @@ -146,7 +145,7 @@ {#if hasWhereFilter}
data?.resource, - enabled: !!instanceId && !!metricsViewName && enabled, + enabled: !!instanceId && !!exploreName && enabled, }, }, ); diff --git a/web-admin/src/routes/[organization]/[project]/-/settings/public-urls/+page.svelte b/web-admin/src/routes/[organization]/[project]/-/settings/public-urls/+page.svelte index d7ffff7dfe6..df767eb829b 100644 --- a/web-admin/src/routes/[organization]/[project]/-/settings/public-urls/+page.svelte +++ b/web-admin/src/routes/[organization]/[project]/-/settings/public-urls/+page.svelte @@ -1,18 +1,18 @@ -{#key metricsView} - - - - - - - - - +{#key resourceName} + {#if explore?.metricsView} + + + + + + + + + + {/if} {/key} From b15e819815ac102a47a7d7b51103a3ca977e0806 Mon Sep 17 00:00:00 2001 From: Eric P Green Date: Mon, 23 Sep 2024 16:20:41 -0400 Subject: [PATCH 10/48] Redirect old Explore URLs to `.../explore/[name]` --- .../[organization]/[project]/[dashboard]/+page.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 web-admin/src/routes/[organization]/[project]/[dashboard]/+page.ts diff --git a/web-admin/src/routes/[organization]/[project]/[dashboard]/+page.ts b/web-admin/src/routes/[organization]/[project]/[dashboard]/+page.ts new file mode 100644 index 00000000000..239c61d4db8 --- /dev/null +++ b/web-admin/src/routes/[organization]/[project]/[dashboard]/+page.ts @@ -0,0 +1,13 @@ +import { redirect } from "@sveltejs/kit"; +import type { PageLoad } from "./$types"; + +/** + * Previously, Explores were located at `/[organization]/[project]/[dashboard]`. + * Now we redirect this route to `/[organization]/[project]/explore/[dashboard]`. + */ +export const load: PageLoad = ({ params }) => { + throw redirect( + 307, + `/${params.organization}/${params.project}/explore/${params.dashboard}`, + ); +}; From 5147c0b9a34e7b83ba53770b1344b4a415e3e302 Mon Sep 17 00:00:00 2001 From: Eric P Green Date: Mon, 23 Sep 2024 16:47:42 -0400 Subject: [PATCH 11/48] Migrate embeds --- ...shboardEmbed.svelte => CanvasEmbed.svelte} | 0 .../src/features/embeds/ExploreEmbed.svelte | 51 +++++++++++++++++++ .../embeds/MetricsExplorerEmbed.svelte | 47 ----------------- .../features/embeds/UnsupportedKind.svelte | 7 +++ web-admin/src/routes/-/embed/+page.svelte | 20 +++++--- 5 files changed, 70 insertions(+), 55 deletions(-) rename web-admin/src/features/embeds/{CanvasDashboardEmbed.svelte => CanvasEmbed.svelte} (100%) create mode 100644 web-admin/src/features/embeds/ExploreEmbed.svelte delete mode 100644 web-admin/src/features/embeds/MetricsExplorerEmbed.svelte create mode 100644 web-admin/src/features/embeds/UnsupportedKind.svelte diff --git a/web-admin/src/features/embeds/CanvasDashboardEmbed.svelte b/web-admin/src/features/embeds/CanvasEmbed.svelte similarity index 100% rename from web-admin/src/features/embeds/CanvasDashboardEmbed.svelte rename to web-admin/src/features/embeds/CanvasEmbed.svelte diff --git a/web-admin/src/features/embeds/ExploreEmbed.svelte b/web-admin/src/features/embeds/ExploreEmbed.svelte new file mode 100644 index 00000000000..572d8f69566 --- /dev/null +++ b/web-admin/src/features/embeds/ExploreEmbed.svelte @@ -0,0 +1,51 @@ + + +{#if isSuccess} + {#if isExploreErrored} +
Explore Error
+ {:else if data} + {#key exploreName} + + + + + + + + + + {/key} + {/if} +{/if} diff --git a/web-admin/src/features/embeds/MetricsExplorerEmbed.svelte b/web-admin/src/features/embeds/MetricsExplorerEmbed.svelte deleted file mode 100644 index 0954f5772b8..00000000000 --- a/web-admin/src/features/embeds/MetricsExplorerEmbed.svelte +++ /dev/null @@ -1,47 +0,0 @@ - - -{#if $dashboard.isSuccess} - {#if isDashboardErrored} -
Dashboard Error
- {:else} - {#key dashboardName} - - - - - - - - - - {/key} - {/if} -{/if} diff --git a/web-admin/src/features/embeds/UnsupportedKind.svelte b/web-admin/src/features/embeds/UnsupportedKind.svelte new file mode 100644 index 00000000000..99d6dc869b1 --- /dev/null +++ b/web-admin/src/features/embeds/UnsupportedKind.svelte @@ -0,0 +1,7 @@ +
+
+ Embedding for this resource type is currently unavailable. +
+
diff --git a/web-admin/src/routes/-/embed/+page.svelte b/web-admin/src/routes/-/embed/+page.svelte index 19cc6623286..63c98d031ab 100644 --- a/web-admin/src/routes/-/embed/+page.svelte +++ b/web-admin/src/routes/-/embed/+page.svelte @@ -2,15 +2,17 @@ import { page } from "$app/stores"; import ContentContainer from "@rilldata/web-admin/components/layout/ContentContainer.svelte"; import DashboardsTable from "@rilldata/web-admin/features/dashboards/listing/DashboardsTable.svelte"; - import CanvasDashboardEmbed from "@rilldata/web-admin/features/embeds/CanvasDashboardEmbed.svelte"; - import MetricsExplorerEmbed from "@rilldata/web-admin/features/embeds/MetricsExplorerEmbed.svelte"; + import CanvasEmbed from "@rilldata/web-admin/features/embeds/CanvasEmbed.svelte"; + import ExploreEmbed from "@rilldata/web-admin/features/embeds/ExploreEmbed.svelte"; import TopNavigationBarEmbed from "@rilldata/web-admin/features/embeds/TopNavigationBarEmbed.svelte"; + import UnsupportedKind from "@rilldata/web-admin/features/embeds/UnsupportedKind.svelte"; import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors"; import type { V1ResourceName } from "@rilldata/web-common/runtime-client"; const instanceId = $page.url.searchParams.get("instance_id"); const initialResourceName = $page.url.searchParams.get("resource"); - const initialResourceKind = $page.url.searchParams.get("kind"); + const initialResourceType = + $page.url.searchParams.get("type") ?? $page.url.searchParams.get("kind"); // "kind" is for backwards compatibility const navigation = $page.url.searchParams.get("navigation"); // Ignoring state and theme params for now // const state = $page.url.searchParams.get("state"); @@ -18,10 +20,10 @@ // Manage active resource let activeResource: V1ResourceName | null = null; - if (initialResourceName && initialResourceKind) { + if (initialResourceName && initialResourceType) { activeResource = { name: initialResourceName, - kind: initialResourceKind, + kind: initialResourceType, }; } @@ -59,8 +61,10 @@ {/if} {/if} -{#if activeResource?.kind === ResourceKind.MetricsView.toString()} - +{#if activeResource?.kind === ResourceKind.Explore.toString()} + {:else if activeResource?.kind === ResourceKind.Canvas.toString()} - + +{:else} + {/if} From 94fc01a065799aec5ccdadcc5eecfd267726e515 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Tue, 24 Sep 2024 21:18:04 +0530 Subject: [PATCH 12/48] Fix syncDimensions --- .../dashboards/stores/dashboard-stores.ts | 2 +- .../CreateScheduledReportDialog.svelte | 139 --------------- .../EditScheduledReportDialog.svelte | 160 ------------------ 3 files changed, 1 insertion(+), 300 deletions(-) delete mode 100644 web-common/src/features/scheduled-reports/CreateScheduledReportDialog.svelte delete mode 100644 web-common/src/features/scheduled-reports/EditScheduledReportDialog.svelte diff --git a/web-common/src/features/dashboards/stores/dashboard-stores.ts b/web-common/src/features/dashboards/stores/dashboard-stores.ts index 6fa69072053..5dbb469e173 100644 --- a/web-common/src/features/dashboards/stores/dashboard-stores.ts +++ b/web-common/src/features/dashboards/stores/dashboard-stores.ts @@ -117,7 +117,7 @@ function syncDimensions( metricsExplorer: MetricsExplorerEntity, ) { // Having a map here improves the lookup for existing dimension name - const dimensionsSet = new Set(explore.measures ?? []); + const dimensionsSet = new Set(explore.dimensions ?? []); metricsExplorer.whereFilter = filterExpressions(metricsExplorer.whereFilter, (e) => { if (!e.cond?.exprs?.length) return true; diff --git a/web-common/src/features/scheduled-reports/CreateScheduledReportDialog.svelte b/web-common/src/features/scheduled-reports/CreateScheduledReportDialog.svelte deleted file mode 100644 index ac8115fc9ba..00000000000 --- a/web-common/src/features/scheduled-reports/CreateScheduledReportDialog.svelte +++ /dev/null @@ -1,139 +0,0 @@ - - - - Schedule report - - - - -
- {#if $createReport.isError} -
{$createReport.error.message}
- {/if} -
- - -
- -
diff --git a/web-common/src/features/scheduled-reports/EditScheduledReportDialog.svelte b/web-common/src/features/scheduled-reports/EditScheduledReportDialog.svelte deleted file mode 100644 index eaa68d87be0..00000000000 --- a/web-common/src/features/scheduled-reports/EditScheduledReportDialog.svelte +++ /dev/null @@ -1,160 +0,0 @@ - - - - Edit scheduled report - - - - -
- {#if $editReport.isError} -
{$editReport.error.message}
- {/if} -
- - -
- -
From 8c44b6de6d922282c4ffa84a4ac22220625c9c98 Mon Sep 17 00:00:00 2001 From: Eric P Green Date: Tue, 24 Sep 2024 14:45:39 -0400 Subject: [PATCH 13/48] Fix eslint --- .../dashboards/time-series/ChartInteractions.svelte | 6 +++--- web-common/src/features/entity-management/file-artifact.ts | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/web-common/src/features/dashboards/time-series/ChartInteractions.svelte b/web-common/src/features/dashboards/time-series/ChartInteractions.svelte index 330b09d8a83..834ccddb500 100644 --- a/web-common/src/features/dashboards/time-series/ChartInteractions.svelte +++ b/web-common/src/features/dashboards/time-series/ChartInteractions.svelte @@ -1,5 +1,6 @@ - - - Rill Developer | {metricsViewName} - - -{#if measures.length === 0 && $selectedMockUserStore !== null} - - -{:else if dashboardFileHasParseError && dashboardFileHasParseError.length > 0} - -{:else if mockUserHasNoAccess} - -{:else} - {#key metricsViewName} - - - - - - - - - - {/key} -{/if} diff --git a/web-local/src/routes/(viz)/dashboard/[name]/+page.ts b/web-local/src/routes/(viz)/dashboard/[name]/+page.ts index b1f60a8a9b6..a267b656417 100644 --- a/web-local/src/routes/(viz)/dashboard/[name]/+page.ts +++ b/web-local/src/routes/(viz)/dashboard/[name]/+page.ts @@ -1,53 +1,10 @@ -import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors.js"; -import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient.js"; -import { - getRuntimeServiceGetResourceQueryKey, - runtimeServiceGetResource, -} from "@rilldata/web-common/runtime-client"; -import { error } from "@sveltejs/kit"; -import type { QueryFunction } from "@tanstack/svelte-query"; -import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; -import { get } from "svelte/store"; - -export const load = async ({ params, depends }) => { - const { instanceId } = get(runtime); - - const dashboardName = params.name; - - depends(dashboardName, "dashboard"); - - const queryParams = { - "name.kind": ResourceKind.MetricsView, - "name.name": dashboardName, - }; - - const queryKey = getRuntimeServiceGetResourceQueryKey( - instanceId, - queryParams, - ); - - const queryFunction: QueryFunction< - Awaited> - > = ({ signal }) => - runtimeServiceGetResource(instanceId, queryParams, signal); - - try { - const response = await queryClient.fetchQuery({ - queryFn: queryFunction, - queryKey, - }); - - const metricsViewResource = response.resource; - - if (!metricsViewResource?.metricsView) { - throw error(404, "Dashboard not found"); - } - - return { - metricsView: metricsViewResource, - }; - } catch (e) { - console.error(e); - throw error(404, "Dashboard not found"); - } +import { redirect } from "@sveltejs/kit"; +import type { PageLoad } from "./$types"; + +/** + * Redirect `/dashboard/[name]` to `/explore/[name]`. + * Maintains backwards compatibility with legacy URLs. + */ +export const load: PageLoad = ({ params }) => { + throw redirect(307, `/explore/${params.name}`); }; From 8e5f8d37ac776c9707455ddbf65c79d8e2b92431 Mon Sep 17 00:00:00 2001 From: Eric P Green Date: Tue, 24 Sep 2024 15:14:17 -0400 Subject: [PATCH 15/48] `metricViewName` -> `metricsViewName` --- .../DashboardBookmarksStateProvider.svelte | 6 ++-- .../src/features/embeds/ExploreEmbed.svelte | 4 +-- .../[project]/-/share/[token]/+page.svelte | 4 +-- .../explore/[dashboard]/+page.svelte | 18 +++++----- .../big-number/MeasuresContainer.svelte | 4 +-- .../dimension-table-export-utils.ts | 4 +-- .../dashboards/pivot/pivot-queries.ts | 4 +-- .../DashboardURLStateProvider.svelte | 4 +-- .../dashboards/rows-viewer/RowsViewer.svelte | 4 +-- .../rows-viewer/RowsViewerAccordion.svelte | 18 ++++++---- .../src/features/dashboards/selectors.ts | 20 +++++------ .../features/dashboards/selectors/index.ts | 8 ++--- .../dashboards/stores/dashboard-stores.ts | 6 ++-- .../comparison-pill/ComparisonPill.svelte | 18 +++++----- .../time-controls/super-pill/SuperPill.svelte | 34 +++++++++---------- .../time-series/multiple-dimension-queries.ts | 4 +-- .../time-series/timeseries-data-store.ts | 4 +-- .../features/dashboards/user-preferences.ts | 4 +-- .../dashboards/workspace/Dashboard.svelte | 10 +++--- .../workspace/editor/MetricsEditor.svelte | 20 +++++------ .../features/templates/kpi/KPITemplate.svelte | 10 +++--- .../src/features/templates/kpi/selector.ts | 20 +++++------ .../src/features/templates/table/selector.ts | 7 ++-- .../workspaces/MetricsWorkspace.svelte | 8 ++--- .../routes/(viz)/explore/[name]/+page.svelte | 6 ++-- 25 files changed, 129 insertions(+), 120 deletions(-) diff --git a/web-admin/src/features/dashboards/DashboardBookmarksStateProvider.svelte b/web-admin/src/features/dashboards/DashboardBookmarksStateProvider.svelte index c26474b9470..b41c995f27e 100644 --- a/web-admin/src/features/dashboards/DashboardBookmarksStateProvider.svelte +++ b/web-admin/src/features/dashboards/DashboardBookmarksStateProvider.svelte @@ -5,11 +5,11 @@ import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers"; import { createDashboardStateSync } from "@rilldata/web-common/features/dashboards/stores/syncDashboardState"; import { initLocalUserPreferenceStore } from "@rilldata/web-common/features/dashboards/user-preferences"; - import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; import Spinner from "@rilldata/web-common/features/entity-management/Spinner.svelte"; import { EntityStatus } from "@rilldata/web-common/features/entity-management/types"; + import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; - export let metricViewName: string; + export let metricsViewName: string; export let exploreName: string; $: initLocalUserPreferenceStore(exploreName); @@ -19,7 +19,7 @@ $runtime?.instanceId, $page.params.organization, $page.params.project, - metricViewName, + metricsViewName, exploreName, ); diff --git a/web-admin/src/features/embeds/ExploreEmbed.svelte b/web-admin/src/features/embeds/ExploreEmbed.svelte index 572d8f69566..a3a1a6d0578 100644 --- a/web-admin/src/features/embeds/ExploreEmbed.svelte +++ b/web-admin/src/features/embeds/ExploreEmbed.svelte @@ -39,9 +39,9 @@ {#key exploreName} - + - + diff --git a/web-admin/src/routes/[organization]/[project]/-/share/[token]/+page.svelte b/web-admin/src/routes/[organization]/[project]/-/share/[token]/+page.svelte index 90395771062..66c0368acc0 100644 --- a/web-admin/src/routes/[organization]/[project]/-/share/[token]/+page.svelte +++ b/web-admin/src/routes/[organization]/[project]/-/share/[token]/+page.svelte @@ -54,12 +54,12 @@ > diff --git a/web-admin/src/routes/[organization]/[project]/explore/[dashboard]/+page.svelte b/web-admin/src/routes/[organization]/[project]/explore/[dashboard]/+page.svelte index dfd562e9d11..c7fc94cad90 100644 --- a/web-admin/src/routes/[organization]/[project]/explore/[dashboard]/+page.svelte +++ b/web-admin/src/routes/[organization]/[project]/explore/[dashboard]/+page.svelte @@ -55,7 +55,7 @@ $: isDashboardErrored = $explore?.data?.metricsView?.metricsView?.state?.validSpec === null && !!$explore?.data?.metricsView?.meta?.reconcileError; - $: metricViewName = $explore.data?.metricsView?.meta?.name?.name; + $: metricsViewName = $explore.data?.metricsView?.meta?.name?.name; // If no dashboard is found, show a 404 page $: if (isDashboardNotFound) { @@ -83,22 +83,22 @@ {:else if isDashboardErrored} - {:else if metricViewName} - {#key metricViewName} - + {:else if metricsViewName} + {#key metricsViewName} + {#if $user.isSuccess && $user.data.user} - - + + - + {:else} - + - + diff --git a/web-common/src/features/dashboards/big-number/MeasuresContainer.svelte b/web-common/src/features/dashboards/big-number/MeasuresContainer.svelte index abf9f7a1520..9a254e74d88 100644 --- a/web-common/src/features/dashboards/big-number/MeasuresContainer.svelte +++ b/web-common/src/features/dashboards/big-number/MeasuresContainer.svelte @@ -11,7 +11,7 @@ import SearchableFilterButton from "@rilldata/web-common/components/searchable-filter-menu/SearchableFilterButton.svelte"; - export let metricViewName: string; + export let metricsViewName: string; export let exploreName: string; export let exploreContainerWidth; @@ -125,7 +125,7 @@ $: totalsQuery = createQueryServiceMetricsViewAggregation( instanceId, - metricViewName, + metricsViewName, { measures: $selectedMeasureNames.map((name) => ({ name })), where: sanitiseExpression($dashboardStore?.whereFilter, undefined), diff --git a/web-common/src/features/dashboards/dimension-table/dimension-table-export-utils.ts b/web-common/src/features/dashboards/dimension-table/dimension-table-export-utils.ts index 442c0871c12..d34fc601d85 100644 --- a/web-common/src/features/dashboards/dimension-table/dimension-table-export-utils.ts +++ b/web-common/src/features/dashboards/dimension-table/dimension-table-export-utils.ts @@ -33,7 +33,7 @@ export function getDimensionTableExportArgs( useTimeControlStore(ctx), ctx.validSpecStore, ], - ([metricViewName, dashboardState, timeControlState, validSpecStore]) => { + ([metricsViewName, dashboardState, timeControlState, validSpecStore]) => { if (!validSpecStore.data?.explore || !timeControlState.ready) return undefined; @@ -50,7 +50,7 @@ export function getDimensionTableExportArgs( ); return getDimensionTableAggregationRequestForTime( - metricViewName, + metricsViewName, dashboardState, timeRange, comparisonTimeRange, diff --git a/web-common/src/features/dashboards/pivot/pivot-queries.ts b/web-common/src/features/dashboards/pivot/pivot-queries.ts index 9e7b6d32f07..d41bd953f55 100644 --- a/web-common/src/features/dashboards/pivot/pivot-queries.ts +++ b/web-common/src/features/dashboards/pivot/pivot-queries.ts @@ -67,10 +67,10 @@ export function createPivotAggregationRowQuery( return derived( [ctx.runtime, ctx.metricsViewName], - ([runtime, metricViewName], set) => + ([runtime, metricsViewName], set) => createQueryServiceMetricsViewAggregation( runtime.instanceId, - metricViewName, + metricsViewName, { measures: prepareMeasureForComparison(measures), dimensions, diff --git a/web-common/src/features/dashboards/proto-state/DashboardURLStateProvider.svelte b/web-common/src/features/dashboards/proto-state/DashboardURLStateProvider.svelte index d07fa43a77f..8022d9ad963 100644 --- a/web-common/src/features/dashboards/proto-state/DashboardURLStateProvider.svelte +++ b/web-common/src/features/dashboards/proto-state/DashboardURLStateProvider.svelte @@ -7,7 +7,7 @@ import { HTTPError } from "../../../runtime-client/fetchWrapper"; import { getStateManagers } from "../state-managers/state-managers"; - export let metricViewName: string; + export let metricsViewName: string; const ctx = getStateManagers(); let unsubscribe: Unsubscriber; @@ -22,7 +22,7 @@ $: ({ error } = timeRangeSummaryStore); $: timeRangeSummaryError = error as HTTPError; - $: if (metricViewName === $ctxName && $metricsViewSchema?.data?.schema) { + $: if (metricsViewName === $ctxName && $metricsViewSchema?.data?.schema) { // Make sure we use the correct sync instance for the current metrics view unsubscribe?.(); unsubscribe = useDashboardUrlSync(ctx, $metricsViewSchema?.data?.schema); diff --git a/web-common/src/features/dashboards/rows-viewer/RowsViewer.svelte b/web-common/src/features/dashboards/rows-viewer/RowsViewer.svelte index 2ec503cdd61..d4e960de167 100644 --- a/web-common/src/features/dashboards/rows-viewer/RowsViewer.svelte +++ b/web-common/src/features/dashboards/rows-viewer/RowsViewer.svelte @@ -13,7 +13,7 @@ import { PreviewTable } from "../../../components/preview-table"; import ReconcilingSpinner from "../../entity-management/ReconcilingSpinner.svelte"; - export let metricViewName = ""; + export let metricsViewName = ""; export let exploreName: string; export let height: number; export let filters: V1Expression | undefined; @@ -29,7 +29,7 @@ $: tableQuery = createQueryServiceMetricsViewRows( $runtime?.instanceId, - metricViewName, + metricsViewName, { limit: $limit, where: filters, diff --git a/web-common/src/features/dashboards/rows-viewer/RowsViewerAccordion.svelte b/web-common/src/features/dashboards/rows-viewer/RowsViewerAccordion.svelte index 0b984603fc0..064c7c3d0ea 100644 --- a/web-common/src/features/dashboards/rows-viewer/RowsViewerAccordion.svelte +++ b/web-common/src/features/dashboards/rows-viewer/RowsViewerAccordion.svelte @@ -21,7 +21,7 @@ const { exports } = featureFlags; const timeControlsStore = useTimeControlStore(getStateManagers()); - export let metricViewName: string; + export let metricsViewName: string; export let exploreName: string; const DEFAULT_LABEL = "Model Data"; @@ -69,7 +69,7 @@ $: filteredTotalsQuery = createQueryServiceMetricsViewAggregation( $runtime.instanceId, - metricViewName, + metricsViewName, { measures: [{ name: "count", builtinMeasure: "BUILTIN_MEASURE_COUNT" }], timeStart: timeRange.start, @@ -80,7 +80,7 @@ query: { queryKey: [ "dashboardFilteredRowsCt", - metricViewName, + metricsViewName, { timeStart: timeRange.start, timeEnd: timeRange.end, @@ -94,7 +94,7 @@ $: totalsQuery = createQueryServiceMetricsViewAggregation( $runtime.instanceId, - metricViewName, + metricsViewName, { measures: [{ name: "count", builtinMeasure: "BUILTIN_MEASURE_COUNT" }], }, @@ -102,7 +102,7 @@ query: { // This should not be needed, but we are getting occasional query failures where the query gets stuck on status: 'loading' when using the autogenerated key. // TODO: investigate this further - queryKey: ["dashboardAllRowsCt", metricViewName], + queryKey: ["dashboardAllRowsCt", metricsViewName], enabled: true, }, }, @@ -159,7 +159,13 @@
{#if isOpen} - + {/if}
diff --git a/web-common/src/features/dashboards/selectors.ts b/web-common/src/features/dashboards/selectors.ts index ce42c052f54..e2df26b9b95 100644 --- a/web-common/src/features/dashboards/selectors.ts +++ b/web-common/src/features/dashboards/selectors.ts @@ -24,7 +24,7 @@ import { ErrorType } from "../../runtime-client/http-client"; export function useDashboard( instanceId: string, - metricViewName: string, + metricsViewName: string, queryOptions?: CreateQueryOptions< V1GetResourceResponse, ErrorType, @@ -33,7 +33,7 @@ export function useDashboard( ) { return useResource( instanceId, - metricViewName, + metricsViewName, ResourceKind.MetricsView, queryOptions, ); @@ -75,10 +75,10 @@ export function useValidVisualizations(instanceId: string) { */ export const useMetricsView = ( instanceId: string, - metricViewName: string, + metricsViewName: string, selector?: (meta: V1MetricsViewSpec) => T, ) => { - return useResource(instanceId, metricViewName, ResourceKind.MetricsView, { + return useResource(instanceId, metricsViewName, ResourceKind.MetricsView, { select: (data) => selector ? selector(data.resource?.metricsView?.state?.validSpec) @@ -89,9 +89,9 @@ export const useMetricsView = ( // TODO: cleanup usage of useModelHasTimeSeries and useModelAllTimeRange export const useModelHasTimeSeries = ( instanceId: string, - metricViewName: string, + metricsViewName: string, ) => - useMetricsView(instanceId, metricViewName, (meta) => !!meta?.timeDimension); + useMetricsView(instanceId, metricsViewName, (meta) => !!meta?.timeDimension); export function useMetricsViewTimeRange( instanceId: string, @@ -121,19 +121,19 @@ export function useMetricsViewTimeRange( export const useMetaMeasure = ( instanceId: string, - metricViewName: string, + metricsViewName: string, measureName: string, ) => - useMetricsView(instanceId, metricViewName, (meta) => + useMetricsView(instanceId, metricsViewName, (meta) => meta?.measures?.find((measure) => measure.name === measureName), ); export const useMetaDimension = ( instanceId: string, - metricViewName: string, + metricsViewName: string, dimensionName: string, ) => - useMetricsView(instanceId, metricViewName, (meta) => { + useMetricsView(instanceId, metricsViewName, (meta) => { const dim = meta?.dimensions?.find( (dimension) => dimension.name === dimensionName, ); diff --git a/web-common/src/features/dashboards/selectors/index.ts b/web-common/src/features/dashboards/selectors/index.ts index e7a2b63a2c4..c1b2471a19e 100644 --- a/web-common/src/features/dashboards/selectors/index.ts +++ b/web-common/src/features/dashboards/selectors/index.ts @@ -30,10 +30,10 @@ export const useMetricsView = ( ): Readable> => { return derived( [ctx.runtime, ctx.metricsViewName], - ([runtime, metricViewName], set) => { + ([runtime, metricsViewName], set) => { return useResource( runtime.instanceId, - metricViewName, + metricsViewName, ResourceKind.MetricsView, { select: (data) => @@ -74,10 +74,10 @@ export const getFilterSearchList = ( ctx.metricsViewName, ctx.runtime, ], - ([metricsExplorer, timeControls, metricViewName, runtime], set) => { + ([metricsExplorer, timeControls, metricsViewName, runtime], set) => { return createQueryServiceMetricsViewComparison( runtime.instanceId, - metricViewName, + metricsViewName, { dimension: { name: dimension }, measures: [{ name: metricsExplorer.leaderboardMeasureName }], diff --git a/web-common/src/features/dashboards/stores/dashboard-stores.ts b/web-common/src/features/dashboards/stores/dashboard-stores.ts index 5dbb469e173..67af3e46f93 100644 --- a/web-common/src/features/dashboards/stores/dashboard-stores.ts +++ b/web-common/src/features/dashboards/stores/dashboard-stores.ts @@ -145,7 +145,7 @@ function syncDimensions( } } -const metricViewReducers = { +const metricsViewReducers = { init( name: string, metricsView: V1MetricsViewSpec, @@ -515,9 +515,9 @@ const metricViewReducers = { }; export const metricsExplorerStore: Readable & - typeof metricViewReducers = { + typeof metricsViewReducers = { subscribe, - ...metricViewReducers, + ...metricsViewReducers, }; export function useDashboardStore( diff --git a/web-common/src/features/dashboards/time-controls/comparison-pill/ComparisonPill.svelte b/web-common/src/features/dashboards/time-controls/comparison-pill/ComparisonPill.svelte index b5afdb1507c..20f42072064 100644 --- a/web-common/src/features/dashboards/time-controls/comparison-pill/ComparisonPill.svelte +++ b/web-common/src/features/dashboards/time-controls/comparison-pill/ComparisonPill.svelte @@ -1,18 +1,18 @@ @@ -96,7 +96,7 @@ {:else} {/if} @@ -120,7 +120,7 @@ {#if (isRillDeveloper || $cloudDataViewer) && !expandedMeasureName && !mockUserHasNoAccess} - + {/if}