|
8 | 8 | InputSelectCheckbox,
|
9 | 9 | InputDateTime
|
10 | 10 | } from '$lib/elements/forms';
|
11 |
| - import { onMount } from 'svelte'; |
| 11 | + import { onMount, createEventDispatcher } from 'svelte'; |
12 | 12 | import { operators, addFilter, queries, tags } from './store';
|
13 | 13 | import type { Column } from '$lib/helpers/types';
|
14 | 14 | import type { Writable } from 'svelte/store';
|
15 | 15 | import { TagList } from '.';
|
16 | 16 | import { Icon, Layout } from '@appwrite.io/pink-svelte';
|
17 | 17 | import { IconPlus } from '@appwrite.io/pink-icons-svelte';
|
18 | 18 |
|
19 |
| - // We cast to any to not cause type errors in the input components |
20 |
| - /* eslint @typescript-eslint/no-explicit-any: 'off' */ |
21 |
| - export let value: any = null; |
22 |
| - export let columns: Writable<Column[]>; |
23 |
| - export let columnId: string | null = null; |
24 |
| - export let arrayValues: string[] = []; |
25 |
| - export let operatorKey: string | null = null; |
26 |
| - export let singleCondition = false; |
| 19 | + let { |
| 20 | + value = $bindable(null), |
| 21 | + columns, |
| 22 | + columnId = $bindable(null), |
| 23 | + arrayValues = $bindable([]), |
| 24 | + operatorKey = $bindable(null), |
| 25 | + singleCondition = false |
| 26 | + }: { |
| 27 | + value?: string | number | string[] | null; |
| 28 | + columns: Writable<Column[]>; |
| 29 | + columnId?: string | null; |
| 30 | + arrayValues?: string[]; |
| 31 | + operatorKey?: string | null; |
| 32 | + singleCondition?: boolean; |
| 33 | + } = $props(); |
27 | 34 |
|
28 |
| - $: column = $columns.find((c) => c.id === columnId) as Column; |
| 35 | + let columnsArray = $derived($columns); |
| 36 | + let column = $derived(columnsArray.find((c) => c.id === columnId)); |
29 | 37 |
|
30 |
| - $: operatorsForColumn = Object.entries(operators) |
31 |
| - .filter(([, v]) => v.types.includes(column?.type)) |
32 |
| - .map(([k]) => ({ |
33 |
| - label: k, |
34 |
| - value: k |
| 38 | + let operatorsForColumn = $derived(() => { |
| 39 | + if (!column?.type) return []; |
| 40 | + return Object.entries(operators) |
| 41 | + .filter(([, v]) => v.types.includes(column.type)) |
| 42 | + .map(([k]) => ({ label: k, value: k })); |
| 43 | + }); |
| 44 | +
|
| 45 | + let operator = $derived(operatorKey ? operators[operatorKey] : null); |
| 46 | + let isDisabled = $derived(!operator); |
| 47 | + let appliedTags = $derived($tags); |
| 48 | +
|
| 49 | + let columnOptions = $derived(() => |
| 50 | + columnsArray |
| 51 | + .filter((c) => c.filter !== false) |
| 52 | + .map((c) => ({ |
| 53 | + label: c.title, |
| 54 | + value: c.id |
| 55 | + })) |
| 56 | + ); |
| 57 | +
|
| 58 | + let enumOptions = $derived(() => { |
| 59 | + if (!column?.elements) return []; |
| 60 | + return column.elements.map((e) => ({ |
| 61 | + label: e?.label ?? e, |
| 62 | + value: e?.value ?? e |
35 | 63 | }));
|
| 64 | + }); |
36 | 65 |
|
37 |
| - $: operator = operatorKey ? operators[operatorKey] : null; |
38 |
| - $: isDisabled = !operator; |
| 66 | + let enumOptionsWithChecked = $derived(() => { |
| 67 | + if (!column?.elements) return []; |
| 68 | + return column.elements.map((e) => ({ |
| 69 | + label: e?.label ?? e, |
| 70 | + value: e?.value ?? e, |
| 71 | + checked: arrayValues.includes(e?.value ?? e) |
| 72 | + })); |
| 73 | + }); |
39 | 74 |
|
40 | 75 | onMount(() => {
|
41 | 76 | value = column?.array ? [] : null;
|
|
45 | 80 | }
|
46 | 81 | });
|
47 | 82 |
|
| 83 | + const dispatch = createEventDispatcher<{ clear: void; apply: { applied: number } }>(); |
| 84 | +
|
48 | 85 | function addFilterAndReset() {
|
49 |
| - addFilter($columns, columnId, operatorKey, value, arrayValues); |
| 86 | + addFilter(columnsArray, columnId, operatorKey, value, arrayValues); |
50 | 87 | columnId = null;
|
51 | 88 | operatorKey = null;
|
52 | 89 | value = null;
|
53 | 90 | arrayValues = [];
|
| 91 | + dispatch('apply', { applied: appliedTags.length }); |
54 | 92 | if (singleCondition) {
|
55 | 93 | queries.apply();
|
56 | 94 | }
|
|
62 | 100 | <Layout.Stack gap="s" direction="row" alignItems="flex-start">
|
63 | 101 | <InputSelect
|
64 | 102 | id="column"
|
65 |
| - options={$columns |
66 |
| - .filter((c) => c.filter !== false) |
67 |
| - .map((c) => ({ |
68 |
| - label: c.title, |
69 |
| - value: c.id |
70 |
| - }))} |
| 103 | + options={columnOptions()} |
71 | 104 | placeholder="Select column"
|
72 | 105 | bind:value={columnId} />
|
73 | 106 | <InputSelect
|
74 | 107 | id="operator"
|
75 | 108 | disabled={!column}
|
76 |
| - options={operatorsForColumn} |
| 109 | + options={operatorsForColumn()} |
77 | 110 | placeholder="Select operator"
|
78 | 111 | bind:value={operatorKey} />
|
79 | 112 | </Layout.Stack>
|
|
84 | 117 | name="value"
|
85 | 118 | bind:tags={arrayValues}
|
86 | 119 | placeholder="Select value"
|
87 |
| - options={column?.elements?.map((e) => ({ |
88 |
| - label: e?.label ?? e, |
89 |
| - value: e?.value ?? e, |
90 |
| - checked: arrayValues.includes(e?.value ?? e) |
91 |
| - }))}> |
| 120 | + options={enumOptionsWithChecked()}> |
92 | 121 | </InputSelectCheckbox>
|
93 | 122 | {:else}
|
94 | 123 | <InputTags
|
|
102 | 131 | {#if column.format === 'enum'}
|
103 | 132 | <InputSelect
|
104 | 133 | id="value"
|
105 |
| - bind:value |
| 134 | + bind:value={value as string} |
106 | 135 | placeholder="Select value"
|
107 |
| - options={column?.elements?.map((e) => ({ |
108 |
| - label: e?.label ?? e, |
109 |
| - value: e?.value ?? e |
110 |
| - }))} /> |
| 136 | + options={enumOptions()} /> |
111 | 137 | {:else if column.type === 'integer' || column.type === 'double'}
|
112 |
| - <InputNumber id="value" bind:value placeholder="Enter value" /> |
| 138 | + <InputNumber |
| 139 | + id="value" |
| 140 | + bind:value={value as number} |
| 141 | + placeholder="Enter value" /> |
113 | 142 | {:else if column.type === 'boolean'}
|
114 | 143 | <InputSelect
|
115 | 144 | id="value"
|
|
118 | 147 | options={[
|
119 | 148 | { label: 'True', value: true },
|
120 | 149 | { label: 'False', value: false }
|
121 |
| - ].filter(Boolean)} |
122 |
| - bind:value /> |
| 150 | + ]} |
| 151 | + bind:value={value as unknown as boolean} /> |
123 | 152 | {:else if column.type === 'datetime'}
|
124 | 153 | {#key value}
|
125 |
| - <InputDateTime id="value" bind:value step={60} /> |
| 154 | + <InputDateTime id="value" bind:value={value as string} step={60} /> |
126 | 155 | {/key}
|
127 | 156 | {:else}
|
128 |
| - <InputText id="value" bind:value placeholder="Enter value" /> |
| 157 | + <InputText |
| 158 | + id="value" |
| 159 | + bind:value={value as string} |
| 160 | + placeholder="Enter value" /> |
129 | 161 | {/if}
|
130 | 162 | </ul>
|
131 | 163 | {/if}
|
|
138 | 170 | {/if}
|
139 | 171 | </form>
|
140 | 172 |
|
141 |
| - {#if !singleCondition && $tags.length > 0} |
| 173 | + {#if !singleCondition && appliedTags.length > 0} |
142 | 174 | <ul class="u-flex u-flex-wrap u-cross-center u-gap-8 u-margin-block-start-16 tags">
|
143 | 175 | <TagList
|
144 |
| - tags={$tags} |
| 176 | + tags={appliedTags} |
145 | 177 | on:remove={(e) => {
|
146 | 178 | queries.removeFilter(e.detail);
|
147 | 179 | queries.apply();
|
|
0 commit comments