diff --git a/web-common/src/components/chip/removable-list-chip/RemovableListBody.svelte b/web-common/src/components/chip/removable-list-chip/RemovableListBody.svelte index 425510be7f8..c8796c18ae2 100644 --- a/web-common/src/components/chip/removable-list-chip/RemovableListBody.svelte +++ b/web-common/src/components/chip/removable-list-chip/RemovableListBody.svelte @@ -2,6 +2,7 @@ export let label: string; export let values: string[]; export let show = 1; + export let smallChip = false; export let labelMaxWidth = "160px"; export let valueMaxWidth = "320px"; @@ -9,17 +10,26 @@
- + {label} - {#each values.slice(0, show) as value (value)} - - {value} - - {/each} + {#if !smallChip} + {#each values.slice(0, show) as value (value)} + + {value} + + {/each} + {/if} - {#if values.length > 1} + {#if smallChip} + + {values.length} selected + + {:else if values.length > 1} +{whatsLeft} other{#if whatsLeft !== 1}s{/if} diff --git a/web-common/src/features/canvas/components/charts/selector.ts b/web-common/src/features/canvas/components/charts/selector.ts index 9469a56a4b7..e949edc411b 100644 --- a/web-common/src/features/canvas/components/charts/selector.ts +++ b/web-common/src/features/canvas/components/charts/selector.ts @@ -11,7 +11,6 @@ import { type V1MetricsViewAggregationMeasure, type V1MetricsViewAggregationResponse, type V1MetricsViewAggregationResponseDataItem, - type V1TimeRange, } from "@rilldata/web-common/runtime-client"; import type { HTTPError } from "@rilldata/web-common/runtime-client/fetchWrapper"; import type { CreateQueryResult } from "@tanstack/svelte-query"; @@ -98,9 +97,15 @@ export function createChartDataQuery( limit = "500", offset = "0", ): CreateQueryResult { - const { - timeControls: { selectedTimeRange }, - } = ctx.canvasEntity; + const { canvasEntity } = ctx; + + const timeAndFilterStore = canvasEntity.createTimeAndFilterStore( + config.metrics_view, + { + componentTimeRange: config.time_range, + componentFilter: config.dimension_filters, + }, + ); let measures: V1MetricsViewAggregationMeasure[] = []; let dimensions: V1MetricsViewAggregationDimension[] = []; @@ -110,14 +115,9 @@ export function createChartDataQuery( } return derived( - [ctx.runtime, selectedTimeRange], - ([runtime, $selectedTimeRange], set) => { - let timeRange: V1TimeRange = { - start: $selectedTimeRange?.start?.toISOString(), - end: $selectedTimeRange?.end?.toISOString(), - }; - - const timeGrain = $selectedTimeRange?.interval; + [ctx.runtime, timeAndFilterStore], + ([runtime, $timeAndFilterStore], set) => { + const { timeRange, where, timeGrain } = $timeAndFilterStore; if (config.x?.type === "nominal" && config.x?.field) { dimensions = [{ name: config.x?.field }]; @@ -129,24 +129,21 @@ export function createChartDataQuery( dimensions = [...dimensions, { name: config.color.field }]; } - if (config.time_range) { - timeRange = { isoDuration: config.time_range }; - } - return createQueryServiceMetricsViewAggregation( runtime.instanceId, config.metrics_view, { measures, dimensions, - where: undefined, + where, timeRange, limit, offset, }, { query: { - enabled: !!$selectedTimeRange?.start && !!$selectedTimeRange?.end, + enabled: + !!config.time_range || (!!timeRange?.start && !!timeRange?.end), queryClient: ctx.queryClient, keepPreviousData: true, }, diff --git a/web-common/src/features/canvas/components/kpi/KPI.svelte b/web-common/src/features/canvas/components/kpi/KPI.svelte index 5fb06386d6c..a527cad1f65 100644 --- a/web-common/src/features/canvas/components/kpi/KPI.svelte +++ b/web-common/src/features/canvas/components/kpi/KPI.svelte @@ -41,6 +41,7 @@ time_range: timeRange, sparkline: showSparkline, comparison_range: comparisonTimeRange, + dimension_filters: dimensionFilters, } = kpiProperties); $: measure = spec.getMeasureForMetricView(measureName, metricsViewName); @@ -51,6 +52,7 @@ metricsViewName, measureName, timeRange, + dimensionFilters, ); $: comparisonValue = useKPIComparisonTotal( @@ -59,6 +61,7 @@ metricsViewName, measureName, comparisonTimeRange, + dimensionFilters, ); $: sparkline = useKPISparkline( @@ -67,6 +70,7 @@ metricsViewName, measureName, timeRange, + dimensionFilters, ); $: sparkData = $sparkline?.data || []; diff --git a/web-common/src/features/canvas/components/kpi/selector.ts b/web-common/src/features/canvas/components/kpi/selector.ts index f0057509330..365983fe5cb 100644 --- a/web-common/src/features/canvas/components/kpi/selector.ts +++ b/web-common/src/features/canvas/components/kpi/selector.ts @@ -18,16 +18,16 @@ export function useKPITotals( instanceId: string, metricsViewName: string, measure: string, - overrideTimeRange: string | undefined, + componentTimeRange: string | undefined, + componentFilter: string | undefined, ): CreateQueryResult { const { canvasEntity } = ctx; - const { selectedTimeRange } = canvasEntity.timeControls; const timeAndFilterStore = canvasEntity.createTimeAndFilterStore( metricsViewName, { - timeRangeStore: selectedTimeRange, - overrideTimeRange: overrideTimeRange, + componentTimeRange, + componentFilter, }, ); @@ -43,7 +43,7 @@ export function useKPITotals( { query: { enabled: - !!overrideTimeRange || (!!timeRange?.start && !!timeRange?.end), + !!componentTimeRange || (!!timeRange?.start && !!timeRange?.end), select: (data) => { return data.data?.[0]?.[measure] ?? null; }, @@ -60,6 +60,7 @@ export function useKPIComparisonTotal( metricsViewName: string, measure: string, overrideComparisonRange: string | undefined, + componentFilter: string | undefined, ): CreateQueryResult { const { canvasEntity } = ctx; const { showTimeComparison, selectedComparisonTimeRange } = @@ -70,7 +71,8 @@ export function useKPIComparisonTotal( metricsViewName, { timeRangeStore: selectedComparisonTimeRange, - overrideTimeRange: overrideComparisonRange, + componentTimeRange: overrideComparisonRange, + componentFilter, }, ); @@ -108,7 +110,8 @@ export function useKPISparkline( instanceId: string, metricsViewName: string, measure: string, - overrideTimeRange: string | undefined, + componentTimeRange: string | undefined, + componentFilter: string | undefined, ): CreateQueryResult>> { const allTimeRangeQuery = useMetricsViewTimeRange( instanceId, @@ -121,8 +124,8 @@ export function useKPISparkline( const timeAndFilterStore = canvasEntity.createTimeAndFilterStore( metricsViewName, { - timeRangeStore: selectedTimeRange, - overrideTimeRange: overrideTimeRange, + componentTimeRange: componentTimeRange, + componentFilter, }, ); @@ -137,9 +140,9 @@ export function useKPISparkline( let defaultGrain = selectedRange?.interval || V1TimeGrain.TIME_GRAIN_DAY; - if (overrideTimeRange) { + if (componentTimeRange) { const overrideRange = isoDurationToTimeRange( - overrideTimeRange, + componentTimeRange, maxTimeDate, ); diff --git a/web-common/src/features/canvas/components/table/TableTemplate.svelte b/web-common/src/features/canvas/components/table/TableTemplate.svelte index 92273aac1e9..6f11778ebdd 100644 --- a/web-common/src/features/canvas/components/table/TableTemplate.svelte +++ b/web-common/src/features/canvas/components/table/TableTemplate.svelte @@ -66,6 +66,8 @@ let pivotDataStore: PivotDataStore | undefined = undefined; let pivotConfig: Readable | undefined = undefined; $: if (isValidSchema) { + // TODO: Rewrite this replace ctx across pivot to + // a subset of necessary entities const stateManagerContext = createStateManagers({ queryClient, exploreName: "TODO", // Historically, State Managers have only been used for Explore, not Canvas. diff --git a/web-common/src/features/canvas/components/util.ts b/web-common/src/features/canvas/components/util.ts index 8c5ea0bac48..d225fcca911 100644 --- a/web-common/src/features/canvas/components/util.ts +++ b/web-common/src/features/canvas/components/util.ts @@ -39,7 +39,7 @@ export function getFilterOptions( : {}), dimension_filters: { type: "dimension_filters", - label: "Dimension Filters", + label: "Filters", }, }; } diff --git a/web-common/src/features/canvas/inspector/ComponentsEditor.svelte b/web-common/src/features/canvas/inspector/ComponentsEditor.svelte index 68ccc68aab3..35091e30211 100644 --- a/web-common/src/features/canvas/inspector/ComponentsEditor.svelte +++ b/web-common/src/features/canvas/inspector/ComponentsEditor.svelte @@ -14,7 +14,7 @@ import SidebarWrapper from "@rilldata/web-common/features/visual-editing/SidebarWrapper.svelte"; import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; import ComponentTabs from "./ComponentTabs.svelte"; - import FiltersMapper from "./FiltersMapper.svelte"; + import FiltersMapper from "./filters/FiltersMapper.svelte"; import ParamMapper from "./ParamMapper.svelte"; export let selectedComponentName: string; @@ -61,7 +61,7 @@ {#if componentType && component && rendererProperties} - {#key selectedComponentIndex} + {#key selectedComponentName} {#if currentTab === "options"} {:else if currentTab === "filters"} - + {:else if currentTab === "config"} {/if} diff --git a/web-common/src/features/canvas/inspector/filters/DimensionFiltersInput.svelte b/web-common/src/features/canvas/inspector/filters/DimensionFiltersInput.svelte new file mode 100644 index 00000000000..bb379842087 --- /dev/null +++ b/web-common/src/features/canvas/inspector/filters/DimensionFiltersInput.svelte @@ -0,0 +1,164 @@ + + +
+
+ + + +
+ +
+
+ {#if isComplexFilter} + + {:else if allDimensionFilters.length || allMeasureFilters.length} + {#each allDimensionFilters as { name, label, selectedValues } (name)} + {@const dimension = $allDimensions.find( + (d) => d.name === name || d.column === name, + )} + {@const dimensionName = dimension?.name || dimension?.column} +
+ {#if dimensionName} + removeDimensionFilter(name)} + onToggleFilterMode={() => toggleDimensionFilterMode(name)} + onSelect={(value) => + toggleDimensionValueSelection(name, value, true)} + /> + {/if} +
+ {/each} + {#each allMeasureFilters as { name, label, dimensionName, filter } (name)} +
+ removeMeasureFilter(dimensionName, name)} + onApply={({ dimension, oldDimension, filter }) => + handleMeasureFilterApply(dimension, name, oldDimension, filter)} + /> +
+ {/each} + {/if} +
+
+ {#if hasFilters} + + {/if} +
+
+
diff --git a/web-common/src/features/canvas/inspector/FiltersMapper.svelte b/web-common/src/features/canvas/inspector/filters/FiltersMapper.svelte similarity index 71% rename from web-common/src/features/canvas/inspector/FiltersMapper.svelte rename to web-common/src/features/canvas/inspector/filters/FiltersMapper.svelte index 4747618357e..6deeae92177 100644 --- a/web-common/src/features/canvas/inspector/FiltersMapper.svelte +++ b/web-common/src/features/canvas/inspector/filters/FiltersMapper.svelte @@ -1,9 +1,11 @@