|
1 | 1 | <script lang="ts" context="module">
|
2 |
| - import Button from "@rilldata/web-common/components/button/Button.svelte"; |
3 | 2 | import * as DropdownMenu from "@rilldata/web-common/components/dropdown-menu/";
|
4 | 3 | import Add from "@rilldata/web-common/components/icons/Add.svelte";
|
5 | 4 | import { getStateManagers } from "../state-managers/state-managers";
|
6 | 5 | import { metricsExplorerStore } from "../stores/dashboard-stores";
|
| 6 | +
|
| 7 | + import { useTimeControlStore } from "@rilldata/web-common/features/dashboards/time-controls/time-control-store"; |
| 8 | + import { |
| 9 | + getAllowedTimeGrains, |
| 10 | + isGrainBigger, |
| 11 | + } from "@rilldata/web-common/lib/time/grains"; |
| 12 | + import { V1TimeGrain } from "@rilldata/web-common/runtime-client"; |
| 13 | +
|
| 14 | + import type { SearchableFilterSelectableGroup } from "@rilldata/web-common/components/searchable-filter-menu/SearchableFilterSelectableItem"; |
| 15 | + import SearchableMenuContent from "@rilldata/web-common/components/searchable-filter-menu/SearchableMenuContent.svelte"; |
| 16 | +
|
| 17 | + import { PivotChipType } from "./types"; |
7 | 18 | import type { PivotChipData } from "./types";
|
8 | 19 | </script>
|
9 | 20 |
|
|
16 | 27 | },
|
17 | 28 | exploreName,
|
18 | 29 | } = getStateManagers();
|
| 30 | + const timeControlsStore = useTimeControlStore(getStateManagers()); |
19 | 31 |
|
20 | 32 | let open = false;
|
21 | 33 |
|
22 |
| - function handleSelectValue(data: PivotChipData) { |
23 |
| - metricsExplorerStore.addPivotField($exploreName, data, zone === "rows"); |
| 34 | + $: allTimeGrains = getAllowedTimeGrains( |
| 35 | + new Date($timeControlsStore.timeStart!), |
| 36 | + new Date($timeControlsStore.timeEnd!), |
| 37 | + ).map((tgo) => { |
| 38 | + return { |
| 39 | + id: tgo.grain, |
| 40 | + title: tgo.label, |
| 41 | + type: PivotChipType.Time, |
| 42 | + }; |
| 43 | + }); |
| 44 | +
|
| 45 | + $: timeGrainOptions = allTimeGrains.filter( |
| 46 | + (tgo) => |
| 47 | + $timeControlsStore.minTimeGrain === undefined || |
| 48 | + $timeControlsStore.minTimeGrain === V1TimeGrain.TIME_GRAIN_UNSPECIFIED || |
| 49 | + !isGrainBigger($timeControlsStore.minTimeGrain, tgo.id), |
| 50 | + ); |
| 51 | +
|
| 52 | + $: selectableGroups = [ |
| 53 | + ...(zone === "columns" |
| 54 | + ? [ |
| 55 | + <SearchableFilterSelectableGroup>{ |
| 56 | + name: "MEASURES", |
| 57 | + items: $measures?.map((m) => ({ |
| 58 | + name: m.id, |
| 59 | + label: m.title, |
| 60 | + })), |
| 61 | + }, |
| 62 | + ] |
| 63 | + : []), |
| 64 | + <SearchableFilterSelectableGroup>{ |
| 65 | + name: "DIMENSIONS", |
| 66 | + items: $dimensions?.map((d) => ({ |
| 67 | + name: d.id, |
| 68 | + label: d.title, |
| 69 | + })), |
| 70 | + }, |
| 71 | + <SearchableFilterSelectableGroup>{ |
| 72 | + name: "TIME", |
| 73 | + items: timeGrainOptions.map((tgo) => ({ |
| 74 | + name: tgo.id, |
| 75 | + label: tgo.title, |
| 76 | + type: PivotChipType.Time, |
| 77 | + })), |
| 78 | + }, |
| 79 | + ]; |
| 80 | +
|
| 81 | + $: allDimensionsMeasures = [ |
| 82 | + ...$dimensions, |
| 83 | + ...$measures, |
| 84 | + ...timeGrainOptions, |
| 85 | + ]; |
| 86 | +
|
| 87 | + function handleSelectValue(name) { |
| 88 | + const selectedItem = allDimensionsMeasures.find( |
| 89 | + (item) => item.id === name, |
| 90 | + ) as PivotChipData; |
| 91 | +
|
| 92 | + metricsExplorerStore.addPivotField( |
| 93 | + $exploreName, |
| 94 | + selectedItem, |
| 95 | + zone === "rows", |
| 96 | + ); |
24 | 97 | }
|
25 | 98 | </script>
|
26 | 99 |
|
27 |
| -<DropdownMenu.Root bind:open> |
| 100 | +<DropdownMenu.Root bind:open typeahead={false}> |
28 | 101 | <DropdownMenu.Trigger asChild let:builder>
|
29 |
| - <Button builders={[builder]} type="add" selected={open} label="add-field"> |
| 102 | + <button |
| 103 | + class:active={open} |
| 104 | + use:builder.action |
| 105 | + {...builder} |
| 106 | + aria-label="Add filter button" |
| 107 | + > |
30 | 108 | <Add size="17px" />
|
31 |
| - </Button> |
| 109 | + </button> |
32 | 110 | </DropdownMenu.Trigger>
|
33 | 111 |
|
34 |
| - <DropdownMenu.Content |
35 |
| - class="min-h-10 max-h-80 w-64 overflow-y-auto" |
36 |
| - align="start" |
37 |
| - > |
38 |
| - {#if zone === "columns"} |
39 |
| - <DropdownMenu.Label>Measures</DropdownMenu.Label> |
40 |
| - <DropdownMenu.Group> |
41 |
| - {#each $measures as measure} |
42 |
| - <DropdownMenu.Item |
43 |
| - on:click={() => { |
44 |
| - handleSelectValue(measure); |
45 |
| - }} |
46 |
| - > |
47 |
| - {measure.title} |
48 |
| - </DropdownMenu.Item> |
49 |
| - {/each} |
50 |
| - </DropdownMenu.Group> |
51 |
| - <DropdownMenu.Separator /> |
52 |
| - {/if} |
53 |
| - <DropdownMenu.Label>Dimensions</DropdownMenu.Label> |
54 |
| - <DropdownMenu.Group> |
55 |
| - {#each $dimensions as dimension} |
56 |
| - <DropdownMenu.Item |
57 |
| - on:click={() => { |
58 |
| - handleSelectValue(dimension); |
59 |
| - }} |
60 |
| - > |
61 |
| - {dimension.title} |
62 |
| - </DropdownMenu.Item> |
63 |
| - {/each} |
64 |
| - </DropdownMenu.Group> |
65 |
| - </DropdownMenu.Content> |
| 112 | + <SearchableMenuContent |
| 113 | + allowMultiSelect={false} |
| 114 | + onSelect={(name) => { |
| 115 | + handleSelectValue(name); |
| 116 | + }} |
| 117 | + {selectableGroups} |
| 118 | + selectedItems={[]} |
| 119 | + /> |
66 | 120 | </DropdownMenu.Root>
|
| 121 | + |
| 122 | +<style lang="postcss"> |
| 123 | + button { |
| 124 | + @apply w-[34px] h-[26px] rounded-2xl; |
| 125 | + @apply flex items-center justify-center; |
| 126 | +
|
| 127 | + @apply bg-white; |
| 128 | + } |
| 129 | +
|
| 130 | + button.addBorder { |
| 131 | + @apply border border-dashed border-slate-300; |
| 132 | + } |
| 133 | +
|
| 134 | + button:hover { |
| 135 | + @apply bg-slate-100; |
| 136 | + } |
| 137 | +
|
| 138 | + button:active, |
| 139 | + .active { |
| 140 | + @apply bg-slate-200; |
| 141 | + } |
| 142 | +</style> |
0 commit comments