@lavalogic/scoria 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -58
- package/dist/Components/AccordionGroup.svelte +42 -42
- package/dist/Components/AccordionGroupButton.svelte +99 -99
- package/dist/Components/Action.svelte +138 -138
- package/dist/Components/AlertModal.svelte +125 -125
- package/dist/Components/Base/ContextWrapper.svelte +50 -50
- package/dist/Components/Base/Pagination.svelte +190 -190
- package/dist/Components/Base/Snippets.svelte +29 -29
- package/dist/Components/BigRadioSet.svelte +29 -29
- package/dist/Components/Bubble.svelte +77 -77
- package/dist/Components/Button.svelte +197 -197
- package/dist/Components/Checkbox.svelte +68 -68
- package/dist/Components/CollapsibleCard.svelte +70 -70
- package/dist/Components/Contexts/ContextMenu.svelte +157 -157
- package/dist/Components/Contexts/ContextMenuDivider.svelte +11 -11
- package/dist/Components/Contexts/ContextMenuOption.svelte +52 -52
- package/dist/Components/Contexts/Toast.svelte +61 -61
- package/dist/Components/Contexts/ToastContainer.svelte +46 -46
- package/dist/Components/Contexts/Tooltip.svelte +26 -26
- package/dist/Components/DataMatrixIcon.svelte +41 -41
- package/dist/Components/DateInput.svelte +109 -109
- package/dist/Components/DatePicker.svelte +312 -312
- package/dist/Components/DesktopModal.svelte +106 -106
- package/dist/Components/Dial.svelte +151 -151
- package/dist/Components/DimensionInput.svelte +184 -184
- package/dist/Components/DragMenu/DragMenuHolder.svelte +106 -106
- package/dist/Components/DragMenu/DraggableCard.svelte +41 -41
- package/dist/Components/FileCard.svelte +20 -20
- package/dist/Components/FileUpload.svelte +196 -196
- package/dist/Components/GridInput.svelte +190 -190
- package/dist/Components/GridInputSet.svelte +22 -22
- package/dist/Components/HorizontalTabGroup.svelte +78 -78
- package/dist/Components/HorizontalTabGroupButton.svelte +96 -96
- package/dist/Components/Icon.svelte +97 -97
- package/dist/Components/Icons.js +357 -357
- package/dist/Components/LoadingAnimation.svelte +32 -32
- package/dist/Components/LoadingModal.svelte +47 -47
- package/dist/Components/LoadingOverlay.svelte +27 -27
- package/dist/Components/Modal.svelte +251 -251
- package/dist/Components/MultiSelect.svelte +197 -197
- package/dist/Components/Nav/Nav.svelte +97 -97
- package/dist/Components/Nav/NavServiceMenuList.svelte +34 -34
- package/dist/Components/Nav/NavTab.svelte +91 -91
- package/dist/Components/Nav/ServiceMenuItem.svelte +91 -91
- package/dist/Components/Nav/ServicesNav.svelte +53 -53
- package/dist/Components/NumberInput.svelte +144 -144
- package/dist/Components/PageHeading.svelte +36 -36
- package/dist/Components/PasswordInput.svelte +73 -73
- package/dist/Components/Portal.svelte +25 -25
- package/dist/Components/ProgressBubble.svelte +80 -80
- package/dist/Components/QuerySelect.svelte +411 -411
- package/dist/Components/SingleSelect.svelte +261 -261
- package/dist/Components/StepButton.svelte +120 -120
- package/dist/Components/StepForm.svelte +108 -108
- package/dist/Components/Switch.svelte +36 -36
- package/dist/Components/Table/Body/QuickSearchCell.svelte +632 -632
- package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +30 -30
- package/dist/Components/Table/Body/Rows/ColumnList.svelte +56 -56
- package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +179 -179
- package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +49 -49
- package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +180 -180
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +102 -102
- package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +119 -119
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +114 -114
- package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +96 -96
- package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +72 -72
- package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +131 -131
- package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +144 -144
- package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +238 -238
- package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +358 -358
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +338 -338
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +183 -183
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +309 -309
- package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +369 -369
- package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +170 -170
- package/dist/Components/Table/Body/Rows/TableRow.svelte +259 -259
- package/dist/Components/Table/Body/TableBody.svelte +67 -67
- package/dist/Components/Table/Headers/HighlightAllHeader.svelte +39 -39
- package/dist/Components/Table/Headers/SelectAllHeader.svelte +28 -28
- package/dist/Components/Table/Headers/TableHead.svelte +260 -260
- package/dist/Components/Table/Misc/ColumnPanel.svelte +78 -78
- package/dist/Components/Table/Misc/ColumnPanelModal.svelte +99 -99
- package/dist/Components/Table/Misc/FilterInput.svelte +556 -556
- package/dist/Components/Table/Misc/FilterPanel.svelte +46 -46
- package/dist/Components/Table/Misc/FilterPanelModal.svelte +67 -67
- package/dist/Components/Table/Misc/SidePanel.svelte +32 -32
- package/dist/Components/Table/Misc/TableFooter.svelte +304 -304
- package/dist/Components/Table/Misc/TableHorizontalBar.svelte +156 -156
- package/dist/Components/Table/Misc/TableSidebar.svelte +176 -176
- package/dist/Components/Table/Misc/ToolboxPanel.svelte +77 -77
- package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +91 -91
- package/dist/Components/Table/NestedTable.svelte +84 -84
- package/dist/Components/Table/Table.svelte +492 -492
- package/dist/Components/Test/TestContextConsumer.svelte +13 -13
- package/dist/Components/TextArea.svelte +108 -108
- package/dist/Components/TextInput.svelte +147 -147
- package/dist/Components/ThreeStateRadio.svelte +124 -124
- package/dist/Components/Touch/BoolCard.svelte +52 -52
- package/dist/Components/Touch/DateModal.svelte +217 -217
- package/dist/Components/Touch/EditCard.svelte +52 -52
- package/dist/Components/Touch/InfoCard.svelte +24 -24
- package/dist/Components/Touch/InfoTextCard.svelte +21 -21
- package/dist/Components/Touch/ModalExplanation.svelte +20 -20
- package/dist/Components/Touch/NumberKeyboard.svelte +268 -268
- package/dist/Components/Touch/NumberModal.svelte +69 -69
- package/dist/Components/Touch/PlusMinusCard.svelte +50 -50
- package/dist/Components/Touch/SelectModal.svelte +105 -105
- package/dist/Components/Touch/SummaryCard.svelte +65 -65
- package/dist/Components/Touch/TextAreaModal.svelte +86 -86
- package/dist/Components/Touch/TextModal.svelte +123 -123
- package/dist/Components/Touch/TouchCard.svelte +28 -28
- package/dist/Components/Touch/TouchModal.svelte +259 -259
- package/dist/Components/Touch/UtilityButton.svelte +91 -91
- package/dist/Components/VerticalTabGroup.svelte +66 -66
- package/dist/Components/VerticalTabGroupButton.svelte +97 -97
- package/dist/Helpers/Datamatrix.d.ts +10 -10
- package/dist/Helpers/Datamatrix.js +1 -1
- package/dist/Helpers/Helpers.svelte.d.ts +1 -0
- package/dist/Helpers/Helpers.svelte.js +15 -0
- package/dist/Types/Examples/ExampleModal.svelte +34 -34
- package/dist/scss/_basics.scss +12 -12
- package/dist/scss/_colours.scss +134 -134
- package/dist/scss/_mixins.scss +3016 -3016
- package/dist/scss/_sizing.scss +69 -69
- package/dist/scss/_transitions.scss +8 -8
- package/package.json +30 -30
|
@@ -1,634 +1,634 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<script
|
|
4
|
-
lang="ts"
|
|
5
|
-
generics="T extends object, FilterValueType"
|
|
6
|
-
>
|
|
7
|
-
import { dev } from '$app/environment';
|
|
8
|
-
import Action from '../../Action.svelte';
|
|
9
|
-
import Button from '../../Button.svelte';
|
|
10
|
-
import MultiSelect from '../../MultiSelect.svelte';
|
|
11
|
-
import NumberInput from '../../NumberInput.svelte';
|
|
12
|
-
import SingleSelect from '../../SingleSelect.svelte';
|
|
13
|
-
import TextInput from '../../TextInput.svelte';
|
|
14
|
-
import ThreeStateRadio from '../../ThreeStateRadio.svelte';
|
|
15
|
-
import DateModal from '../../Touch/DateModal.svelte';
|
|
16
|
-
import { devCatch, hasQuery, isDateTuple, isNumericArray } from '../../../Helpers/Helpers.svelte.js';
|
|
17
|
-
import { Colour, ColourSet } from '../../../scss/colours.js';
|
|
18
|
-
import { InputVariant } from '../../../Types/Internal/InputVariant.js';
|
|
19
|
-
import type { SelectOption } from '../../../Types/Internal/SelectOption.js';
|
|
20
|
-
import { Size } from '../../../Types/Internal/Size.js';
|
|
21
|
-
import { getContext, onMount, untrack } from 'svelte';
|
|
22
|
-
import { cubicOut } from 'svelte/easing';
|
|
23
|
-
import { fade } from 'svelte/transition';
|
|
24
|
-
|
|
25
|
-
import QuerySelect from '../../QuerySelect.svelte';
|
|
26
|
-
import { Ternary } from '../../../Types/Internal/Ternary.js';
|
|
27
|
-
import { numberDateFilterTypes } from '../Misc/numberDateFilterTypes.js';
|
|
28
|
-
import { stringFilterTypes } from '../Misc/stringFilterTypes.js';
|
|
29
|
-
import { quickFilterContextIdentifier } from '../Table.svelte';
|
|
30
|
-
import { CheckboxDef } from '../Types/Columns/Definitions/Accessors/CheckboxDef.svelte.js';
|
|
31
|
-
import { DateInputDef } from '../Types/Columns/Definitions/Accessors/DateInputDef.svelte.js';
|
|
32
|
-
import { NumberInputDef } from '../Types/Columns/Definitions/Accessors/NumberInputDef.svelte.js';
|
|
33
|
-
import { SelectDef } from '../Types/Columns/Definitions/Accessors/SelectDef.svelte.js';
|
|
34
|
-
import { TableContext } from '../Types/Context/TableContext.svelte.js';
|
|
35
|
-
import { CustomFilterType } from '../Types/Filtering/CustomFilterType.js';
|
|
36
|
-
import { NumberDateFilterMode } from '../Types/Filtering/NumberDateFilterMode.js';
|
|
37
|
-
import { StringFilterMode } from '../Types/Filtering/StringFilterMode.js';
|
|
38
|
-
import type { QuickSearchCellProps } from './QuickSearchCellProps.js';
|
|
39
|
-
|
|
40
|
-
const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
|
|
41
|
-
|
|
42
|
-
const { column, customFilters }: QuickSearchCellProps<T, FilterValueType> = $props();
|
|
43
|
-
|
|
44
|
-
const def = $derived(column.columnDef);
|
|
45
|
-
|
|
46
|
-
const customFilter = $derived(customFilters?.get(def.id));
|
|
47
|
-
|
|
48
|
-
const isSelect = $derived(
|
|
49
|
-
def instanceof SelectDef ||
|
|
50
|
-
def.filterValueType == CustomFilterType.Select ||
|
|
51
|
-
customFilter?.type === CustomFilterType.Select
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
const hasFilterFn = $derived(!!def.filterFn && typeof def.filterFn === 'function');
|
|
55
|
-
|
|
56
|
-
// const hasAcceptableColumnType = $derived(
|
|
57
|
-
// (def instanceof AccessorDef && searchableTypes.has(def.accessorType)) ||
|
|
58
|
-
// (def instanceof AbstractDisplayDef && searchableTypes.has(def.displayType))
|
|
59
|
-
// );
|
|
60
|
-
|
|
61
|
-
const isSearchable = $derived(
|
|
62
|
-
def.allowFiltering && (hasFilterFn || customFilters?.has(def.id) == true)
|
|
63
|
-
// ((hasFilterFn && hasAcceptableColumnType) || customFilters?.has(def.id) == true) // removed hasAcceptableColumnType due to it being redundant
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
const isNumeric = $derived(
|
|
67
|
-
def instanceof NumberInputDef ||
|
|
68
|
-
def.filterValueType == 'Number' ||
|
|
69
|
-
customFilter?.type === CustomFilterType.Number
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
function emptyOptsAndWarn(): Array<SelectOption<unknown>> {
|
|
73
|
-
console.warn(`def ${def.id} is declared as a select filter but has no getOptions() function`);
|
|
74
|
-
return [];
|
|
75
|
-
}
|
|
76
|
-
const options = $derived(
|
|
77
|
-
isSelect ? (def.getOptions?.() ?? customFilter?.options ?? emptyOptsAndWarn()) : []
|
|
78
|
-
);
|
|
79
|
-
const isDate = $derived(def instanceof DateInputDef);
|
|
80
|
-
const isRemoteSelect = $derived(customFilter?.type === CustomFilterType.Select);
|
|
81
|
-
|
|
82
|
-
const selectSymbol = Symbol();
|
|
83
|
-
|
|
84
|
-
const openedSelect = getContext<{ value: symbol | null } | null | undefined>(
|
|
85
|
-
quickFilterContextIdentifier
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
const isSelectOpen = $derived(openedSelect?.value === selectSymbol);
|
|
89
|
-
|
|
90
|
-
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
|
91
|
-
let asdfvalue: unknown | null = $state(null);
|
|
92
|
-
let valueMin: number | null = $state(null);
|
|
93
|
-
let valueMax: number | null = $state(null);
|
|
94
|
-
|
|
95
|
-
let selectedOptions: Array<SelectOption<unknown>> = $state([]);
|
|
96
|
-
let lastQueryOptions: Array<SelectOption<unknown>> = $state([]);
|
|
97
|
-
|
|
98
|
-
const inputId = $derived(`${tableContext.tableName}-cell-quicksearch-${column.id}`);
|
|
99
|
-
|
|
100
|
-
const filterMode = $derived(tableContext.paginationRepo?.filterModes.get(def.id));
|
|
101
|
-
|
|
102
|
-
const selectedNumberFilterType: SelectOption<NumberDateFilterMode> | null = $derived.by(() => {
|
|
103
|
-
const value = (filterMode as NumberDateFilterMode | undefined) ?? NumberDateFilterMode.In;
|
|
104
|
-
return numberDateFilterTypes.find((it) => it.value === value) ?? null;
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const selectedStringFilterType: SelectOption<StringFilterMode> | null = $derived.by(() => {
|
|
108
|
-
const value = (filterMode as StringFilterMode | undefined) ?? StringFilterMode.Contains;
|
|
109
|
-
return stringFilterTypes.find((it) => it.value === value) ?? null;
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const filteringStateValue = $derived(
|
|
113
|
-
tableContext.paginationRepo?.filtering.find((it) => it.id === def.id)?.value
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
$effect(() => {
|
|
117
|
-
if (isRemoteSelect && !tableContext.paginationRepo?.filtering) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
void filteringStateValue;
|
|
121
|
-
|
|
122
|
-
if (hasQuery(customFilter)) {
|
|
123
|
-
if (def.debug) {
|
|
124
|
-
console.debug(`${def.id}: `, 'has query');
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
untrack(async () => {
|
|
128
|
-
const gotValue = filteringStateValue as Array<unknown> | undefined;
|
|
129
|
-
|
|
130
|
-
try {
|
|
131
|
-
// as unknown as string | number | undefined;
|
|
132
|
-
|
|
133
|
-
if (gotValue != undefined) {
|
|
134
|
-
if (def.debug) {
|
|
135
|
-
console.debug(`${def.id}: query values:`, tableContext.dataRepo.__queryValues);
|
|
136
|
-
}
|
|
137
|
-
const key = customFilter.id;
|
|
138
|
-
const x = await tableContext.dataRepo.__queryValues.get(key);
|
|
139
|
-
|
|
140
|
-
if (def.debug) {
|
|
141
|
-
console.debug(`${def.id}: `, 'value:', $state.snapshot(x));
|
|
142
|
-
}
|
|
143
|
-
asdfvalue = (await x) ?? null;
|
|
144
|
-
} else if (def.debug) {
|
|
145
|
-
console.debug(
|
|
146
|
-
`${def.id}: `,
|
|
147
|
-
'filtering state value was undefined',
|
|
148
|
-
$state.snapshot(tableContext.paginationRepo?.filtering)
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
} catch (e) {
|
|
152
|
-
console.warn(e);
|
|
153
|
-
asdfvalue = null;
|
|
154
|
-
}
|
|
155
|
-
}).catch(devCatch);
|
|
156
|
-
} else if (isSelect) {
|
|
157
|
-
if (def.debug) {
|
|
158
|
-
console.debug(`${def.id}: `, 'is select (not query)');
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (!tableContext.paginationRepo?.filtering) {
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const gotValue = filteringStateValue as Array<unknown> | undefined;
|
|
166
|
-
|
|
167
|
-
function isSelectOption(it: unknown): it is SelectOption<unknown> {
|
|
168
|
-
return it != null && typeof it == 'object';
|
|
169
|
-
}
|
|
170
|
-
untrack(async () => {
|
|
171
|
-
try {
|
|
172
|
-
const opts = await options;
|
|
173
|
-
if (def.debug) {
|
|
174
|
-
console.debug(`${def.id}: possible options:`, $state.snapshot(opts));
|
|
175
|
-
}
|
|
176
|
-
const x = opts.filter((it) => {
|
|
177
|
-
if (!isSelectOption(it)) {
|
|
178
|
-
return false;
|
|
179
|
-
}
|
|
180
|
-
if (it.value == undefined) {
|
|
181
|
-
return true;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (typeof it.value == 'string' || typeof it.value == 'number') {
|
|
185
|
-
return (gotValue as unknown as Array<string | number> | undefined)?.includes(
|
|
186
|
-
it.value
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return false;
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
if (def.debug) {
|
|
194
|
-
console.debug(`${def.id}: `, 'selected options:', x);
|
|
195
|
-
}
|
|
196
|
-
selectedOptions = x;
|
|
197
|
-
} catch (e) {
|
|
198
|
-
if (dev || def.debug) {
|
|
199
|
-
console.debug(`${def.id}: `, e);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}).catch(devCatch);
|
|
203
|
-
} else if (isNumeric) {
|
|
204
|
-
if (
|
|
205
|
-
selectedNumberFilterType?.value === NumberDateFilterMode.Between &&
|
|
206
|
-
tableContext.paginationRepo?.filtering
|
|
207
|
-
) {
|
|
208
|
-
const gotValue = filteringStateValue;
|
|
209
|
-
if (gotValue != undefined) {
|
|
210
|
-
const [min, max] = gotValue as [number, number | undefined];
|
|
211
|
-
asdfvalue = min;
|
|
212
|
-
valueMin = min;
|
|
213
|
-
valueMax = max ?? null;
|
|
214
|
-
} else {
|
|
215
|
-
asdfvalue = valueMin = valueMax = null;
|
|
216
|
-
}
|
|
217
|
-
} else if (tableContext.paginationRepo?.filtering) {
|
|
218
|
-
const gotValue = filteringStateValue;
|
|
219
|
-
|
|
220
|
-
if (gotValue != undefined) {
|
|
221
|
-
const [min] = gotValue as [number, number | undefined];
|
|
222
|
-
asdfvalue = min;
|
|
223
|
-
valueMin = min;
|
|
224
|
-
valueMax = min;
|
|
225
|
-
} else {
|
|
226
|
-
asdfvalue = valueMin = valueMax = null;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
} else if (tableContext.paginationRepo?.filtering) {
|
|
230
|
-
const gotValue = filteringStateValue;
|
|
231
|
-
if (gotValue == null || typeof gotValue == 'string' || typeof gotValue == 'number') {
|
|
232
|
-
//RATS
|
|
233
|
-
rats(gotValue);
|
|
234
|
-
asdfvalue = gotValue;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
function rats(gotValue: unknown) {
|
|
240
|
-
// RATS
|
|
241
|
-
if (dev && gotValue != null && typeof gotValue == 'object' && gotValue instanceof Promise) {
|
|
242
|
-
throw new Error(`Unexpected Promise`);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
onMount(() => {
|
|
246
|
-
const filterOption =
|
|
247
|
-
tableContext.paginationRepo?.filtering &&
|
|
248
|
-
tableContext.paginationRepo.filtering.find((it) => it.id === def.id);
|
|
249
|
-
|
|
250
|
-
if (filterOption) {
|
|
251
|
-
if (isNumericArray(filterOption.value)) {
|
|
252
|
-
[valueMin, valueMax] = filterOption.value;
|
|
253
|
-
if (valueMax == undefined) {
|
|
254
|
-
valueMax = valueMin;
|
|
255
|
-
asdfvalue = valueMin?.toString();
|
|
256
|
-
} else if (valueMin == undefined) {
|
|
257
|
-
valueMin = valueMax;
|
|
258
|
-
asdfvalue = valueMax.toString();
|
|
259
|
-
} else {
|
|
260
|
-
asdfvalue = valueMin.toString();
|
|
261
|
-
}
|
|
262
|
-
} else if (!hasQuery(customFilter)) {
|
|
263
|
-
const gotValue = filterOption.value;
|
|
264
|
-
if (gotValue == null || typeof gotValue == 'string' || typeof gotValue == 'number') {
|
|
265
|
-
//RATS
|
|
266
|
-
rats(gotValue);
|
|
267
|
-
asdfvalue = gotValue;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
function closeOnCtrlF(e: KeyboardEvent) {
|
|
274
|
-
if (e.key.toLocaleUpperCase() === 'F' && e.ctrlKey) {
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
e.stopPropagation();
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
let showFromDateModal = $state(false);
|
|
281
|
-
let showToDateModal = $state(false);
|
|
282
|
-
|
|
283
|
-
function generateOnChangeObject(label: string) {
|
|
284
|
-
return (newValue: SelectOption<unknown> | null) => {
|
|
285
|
-
tableContext.paginationRepo?.filterBy(def.id, newValue?.value ?? null);
|
|
286
|
-
tableContext.dataRepo.__queryValues.set(label, newValue);
|
|
287
|
-
rats(newValue);
|
|
288
|
-
asdfvalue = newValue;
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function generateOnChangePrimitive(label: string) {
|
|
293
|
-
return (newValue: SelectOption<unknown> | null) => {
|
|
294
|
-
tableContext.paginationRepo?.filterBy(def.id, newValue?.value ?? null);
|
|
295
|
-
tableContext.dataRepo.__queryValues.set(label, newValue?.value ?? null);
|
|
296
|
-
rats(newValue);
|
|
297
|
-
asdfvalue = newValue?.value ?? null;
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
let isNullFilter = $derived(selectedNumberFilterType?.value == NumberDateFilterMode.null);
|
|
302
|
-
</script>
|
|
303
|
-
|
|
304
|
-
<td class="input-cell {inputId}">
|
|
305
|
-
{#if isSearchable}
|
|
306
|
-
<div class="input-wrapper-parent">
|
|
307
|
-
{#if isDate}
|
|
308
|
-
{@const dateValues = tableContext.paginationRepo?.filtering.find((it) => it.id === def.id)
|
|
309
|
-
?.value ?? [null, null]}
|
|
310
|
-
{#if isDateTuple(dateValues)}
|
|
311
|
-
{@const [fromDate, toDate] = dateValues}
|
|
312
|
-
<div class="spaced-around">
|
|
313
|
-
<Button
|
|
314
|
-
size={Size.FillHeight}
|
|
315
|
-
fullWidth
|
|
316
|
-
onclick={() => {
|
|
317
|
-
showFromDateModal = true;
|
|
318
|
-
}}>From {fromDate?.toLocaleDateString() ?? 'Any Date'}</Button
|
|
319
|
-
>
|
|
320
|
-
|
|
321
|
-
<Button
|
|
322
|
-
size={Size.FillHeight}
|
|
323
|
-
fullWidth
|
|
324
|
-
onclick={() => {
|
|
325
|
-
showToDateModal = true;
|
|
326
|
-
}}>To {toDate?.toLocaleDateString() ?? 'Any Date'}</Button
|
|
327
|
-
>
|
|
328
|
-
</div>
|
|
329
|
-
|
|
330
|
-
{#if showFromDateModal}
|
|
331
|
-
<DateModal
|
|
332
|
-
header="Edit Date From"
|
|
333
|
-
value={fromDate}
|
|
334
|
-
cancelEditing={() => {
|
|
335
|
-
showFromDateModal = false;
|
|
336
|
-
}}
|
|
337
|
-
confirm={(e) => {
|
|
338
|
-
tableContext.paginationRepo?.filterBy(def.id, [e, toDate]);
|
|
339
|
-
showFromDateModal = false;
|
|
340
|
-
}}
|
|
341
|
-
/>
|
|
342
|
-
{/if}
|
|
343
|
-
|
|
344
|
-
{#if showToDateModal}
|
|
345
|
-
<DateModal
|
|
346
|
-
inclusive
|
|
347
|
-
header="Edit Date To"
|
|
348
|
-
value={toDate}
|
|
349
|
-
cancelEditing={() => {
|
|
350
|
-
showToDateModal = false;
|
|
351
|
-
}}
|
|
352
|
-
confirm={(e) => {
|
|
353
|
-
tableContext.paginationRepo?.filterBy(def.id, [fromDate, e]);
|
|
354
|
-
showToDateModal = false;
|
|
355
|
-
}}
|
|
356
|
-
/>
|
|
357
|
-
{/if}
|
|
358
|
-
{/if}
|
|
359
|
-
{:else if isSelect}
|
|
360
|
-
{#if hasQuery(customFilter)}
|
|
361
|
-
{#if customFilter.valueAsObject !== true}
|
|
362
|
-
{@const label = customFilter.id}
|
|
363
|
-
|
|
364
|
-
<!-- TODO: multiselect -->
|
|
365
|
-
|
|
366
|
-
<!-- FIXME: Most likely Unsafe -->
|
|
367
|
-
<QuerySelect
|
|
368
|
-
valueAsObject={false}
|
|
369
|
-
clearable
|
|
370
|
-
name={customFilter.objectName ?? 'Item'}
|
|
371
|
-
valueProp="value"
|
|
372
|
-
labelProp="label"
|
|
373
|
-
value={asdfvalue as null}
|
|
374
|
-
query={customFilter.query}
|
|
375
|
-
bind:options={lastQueryOptions}
|
|
376
|
-
onchange={generateOnChangePrimitive(label)}
|
|
377
|
-
/>
|
|
378
|
-
{:else}
|
|
379
|
-
{@const label = customFilter.id}
|
|
380
|
-
|
|
381
|
-
<!-- TODO: multiselect -->
|
|
382
|
-
|
|
383
|
-
<QuerySelect
|
|
384
|
-
valueAsObject={true}
|
|
385
|
-
clearable
|
|
386
|
-
name={customFilter.objectName ?? 'Item'}
|
|
387
|
-
valueProp="value"
|
|
388
|
-
labelProp="label"
|
|
389
|
-
value={asdfvalue as null}
|
|
390
|
-
query={customFilter.query}
|
|
391
|
-
bind:options={lastQueryOptions}
|
|
392
|
-
onchange={generateOnChangeObject(label)}
|
|
393
|
-
/>
|
|
394
|
-
{/if}
|
|
395
|
-
{:else}
|
|
396
|
-
{#await options then options}
|
|
397
|
-
<MultiSelect
|
|
398
|
-
labelProp="label"
|
|
399
|
-
valueProp="value"
|
|
400
|
-
{options}
|
|
401
|
-
valueAsObject
|
|
402
|
-
onchange={(e: Array<SelectOption<unknown>>) => {
|
|
403
|
-
tableContext.paginationRepo?.filterBy(
|
|
404
|
-
def.id,
|
|
405
|
-
e.map((it) => it.value)
|
|
406
|
-
);
|
|
407
|
-
}}
|
|
408
|
-
selectedValues={selectedOptions}
|
|
409
|
-
collapseSelection
|
|
410
|
-
/>
|
|
411
|
-
{/await}
|
|
412
|
-
{/if}
|
|
413
|
-
{:else if def instanceof CheckboxDef}
|
|
414
|
-
{@const value = (() => {
|
|
415
|
-
switch (tableContext.paginationRepo?.filtering.find((it) => it.id === def.id)?.value) {
|
|
416
|
-
case true: {
|
|
417
|
-
return Ternary.True;
|
|
418
|
-
}
|
|
419
|
-
case false: {
|
|
420
|
-
return Ternary.False;
|
|
421
|
-
}
|
|
422
|
-
default: {
|
|
423
|
-
return Ternary.Neutral;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
})()}
|
|
427
|
-
<div class="centered">
|
|
428
|
-
<ThreeStateRadio
|
|
429
|
-
{value}
|
|
430
|
-
yesLabel="Selected"
|
|
431
|
-
noLabel="Not Selected"
|
|
432
|
-
neutralLabel="Any"
|
|
433
|
-
neutralIcon={{ name: 'circle-minus' }}
|
|
434
|
-
onchange={(v) => {
|
|
435
|
-
switch (v) {
|
|
436
|
-
case Ternary.False: {
|
|
437
|
-
tableContext.paginationRepo?.filterBy(def.id, false);
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
case Ternary.True: {
|
|
441
|
-
tableContext.paginationRepo?.filterBy(def.id, true);
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
case Ternary.Neutral:
|
|
445
|
-
default: {
|
|
446
|
-
tableContext.paginationRepo?.filterBy(def.id, null);
|
|
447
|
-
return;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
}}
|
|
451
|
-
/>
|
|
452
|
-
</div>
|
|
453
|
-
{:else if isNumeric}
|
|
454
|
-
{#if selectedNumberFilterType?.value === NumberDateFilterMode.Between}
|
|
455
|
-
<div class="input-wrapper left">
|
|
456
|
-
<NumberInput
|
|
457
|
-
data-type="quicksearch"
|
|
458
|
-
id={inputId}
|
|
459
|
-
bind:value={valueMin}
|
|
460
|
-
variant={InputVariant.Table}
|
|
461
|
-
placeholder="Min…"
|
|
462
|
-
oninput={() => {
|
|
463
|
-
tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMax]);
|
|
464
|
-
}}
|
|
465
|
-
onkeydown={closeOnCtrlF}
|
|
466
|
-
/>
|
|
467
|
-
</div>
|
|
468
|
-
<div class="input-wrapper right">
|
|
469
|
-
<NumberInput
|
|
470
|
-
data-type="quicksearch"
|
|
471
|
-
id={inputId}
|
|
472
|
-
bind:value={valueMax}
|
|
473
|
-
placeholder="Max…"
|
|
474
|
-
variant={InputVariant.Table}
|
|
475
|
-
oninput={() => {
|
|
476
|
-
tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMax]);
|
|
477
|
-
}}
|
|
478
|
-
onkeydown={closeOnCtrlF}
|
|
479
|
-
/>
|
|
480
|
-
</div>
|
|
481
|
-
{:else}
|
|
482
|
-
<div class="input-wrapper right">
|
|
483
|
-
{#await isNullFilter}
|
|
484
|
-
loading
|
|
485
|
-
{:then isNullFilter}
|
|
486
|
-
{#if isNullFilter}
|
|
487
|
-
<TextInput
|
|
488
|
-
data-type="quicksearch"
|
|
489
|
-
id={inputId}
|
|
490
|
-
value="is Null"
|
|
491
|
-
disabled
|
|
492
|
-
variant={InputVariant.Table}
|
|
493
|
-
/>
|
|
494
|
-
{:else}
|
|
495
|
-
<!-- NOTE: This is a text input in order to support the __in functionality, which is a comma separated list of numbers -->
|
|
496
|
-
<TextInput
|
|
497
|
-
data-type="quicksearch"
|
|
498
|
-
id={inputId}
|
|
499
|
-
bind:value={asdfvalue as string | null}
|
|
500
|
-
placeholder="Filter…"
|
|
501
|
-
variant={InputVariant.Table}
|
|
502
|
-
oninput={() => {
|
|
503
|
-
tableContext.paginationRepo?.filterBy(def.id, [asdfvalue || null]);
|
|
504
|
-
}}
|
|
505
|
-
onkeydown={closeOnCtrlF}
|
|
506
|
-
/>
|
|
507
|
-
{/if}
|
|
508
|
-
{:catch e}
|
|
509
|
-
{@debug e}
|
|
510
|
-
{/await}
|
|
511
|
-
</div>
|
|
512
|
-
{/if}
|
|
513
|
-
{:else if asdfvalue == null || typeof asdfvalue == 'string'}
|
|
514
|
-
<div class="input-wrapper right">
|
|
515
|
-
{#if selectedStringFilterType?.value == StringFilterMode.null}
|
|
516
|
-
<TextInput
|
|
517
|
-
data-type="quicksearch"
|
|
518
|
-
id={inputId}
|
|
519
|
-
value="is Null"
|
|
520
|
-
disabled
|
|
521
|
-
variant={InputVariant.Table}
|
|
522
|
-
/>
|
|
523
|
-
{:else if selectedStringFilterType?.value == StringFilterMode.Empty}
|
|
524
|
-
<TextInput
|
|
525
|
-
data-type="quicksearch"
|
|
526
|
-
id={inputId}
|
|
527
|
-
value="is Empty"
|
|
528
|
-
disabled
|
|
529
|
-
variant={InputVariant.Table}
|
|
530
|
-
/>
|
|
531
|
-
{:else}
|
|
532
|
-
<TextInput
|
|
533
|
-
data-type="quicksearch"
|
|
534
|
-
id={inputId}
|
|
535
|
-
oninput={() => {
|
|
536
|
-
tableContext.paginationRepo?.filterBy(def.id, asdfvalue);
|
|
537
|
-
}}
|
|
538
|
-
variant={InputVariant.Table}
|
|
539
|
-
bind:value={asdfvalue as string | null}
|
|
540
|
-
placeholder="Filter…"
|
|
541
|
-
/>
|
|
542
|
-
{/if}
|
|
543
|
-
</div>
|
|
544
|
-
{/if}
|
|
545
|
-
|
|
546
|
-
<!-- TODO button for date, checkbox or select for checkbox -->
|
|
547
|
-
</div>
|
|
548
|
-
|
|
549
|
-
{#if !isSelect && !isDate && !(def instanceof CheckboxDef)}
|
|
550
|
-
<div class="stick-right">
|
|
551
|
-
<Action
|
|
552
|
-
data-type="quicksearch"
|
|
553
|
-
size={Size.FillHeight}
|
|
554
|
-
colourSet={ColourSet.Auxiliary}
|
|
555
|
-
icon={{
|
|
556
|
-
name: 'filter-2',
|
|
557
|
-
size: Size.MediumLarge,
|
|
558
|
-
colour: Colour['$ui-blue-5'],
|
|
559
|
-
}}
|
|
560
|
-
onclick={() => {
|
|
561
|
-
if (!openedSelect) {
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
if (openedSelect.value === selectSymbol) {
|
|
565
|
-
openedSelect.value = null;
|
|
566
|
-
} else {
|
|
567
|
-
openedSelect.value = selectSymbol;
|
|
568
|
-
}
|
|
569
|
-
}}
|
|
570
|
-
/>
|
|
571
|
-
</div>
|
|
572
|
-
{/if}
|
|
573
|
-
{/if}
|
|
574
|
-
|
|
575
|
-
{#if isSelectOpen}
|
|
576
|
-
<div
|
|
577
|
-
class="floating"
|
|
578
|
-
transition:fade={{ easing: cubicOut, duration: 100 }}
|
|
579
|
-
>
|
|
580
|
-
<div class="select-wrapper">
|
|
581
|
-
{#if isNumeric}
|
|
582
|
-
<SingleSelect
|
|
583
|
-
options={numberDateFilterTypes}
|
|
584
|
-
labelProp="label"
|
|
585
|
-
valueProp="value"
|
|
586
|
-
name="Filter Type"
|
|
587
|
-
valueAsObject
|
|
588
|
-
value={selectedNumberFilterType}
|
|
589
|
-
onchange={(newValue: SelectOption<NumberDateFilterMode> | null) => {
|
|
590
|
-
const oldFilterType = selectedNumberFilterType;
|
|
591
|
-
|
|
592
|
-
const newFilterType = newValue?.value ?? NumberDateFilterMode.In;
|
|
593
|
-
|
|
594
|
-
if (newFilterType !== oldFilterType?.value) {
|
|
595
|
-
tableContext.paginationRepo?.setFilterMode(def.id, newFilterType);
|
|
596
|
-
|
|
597
|
-
if (newFilterType === NumberDateFilterMode.Between) {
|
|
598
|
-
tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMin]);
|
|
599
|
-
} else if (newFilterType === NumberDateFilterMode.In) {
|
|
600
|
-
tableContext.paginationRepo?.filterBy(def.id, [asdfvalue]);
|
|
601
|
-
} else {
|
|
602
|
-
tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMax]);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
}}
|
|
606
|
-
onkeydown={(e: KeyboardEvent) => {
|
|
607
|
-
e.stopPropagation();
|
|
608
|
-
}}
|
|
609
|
-
/>
|
|
610
|
-
{:else}
|
|
611
|
-
<SingleSelect
|
|
612
|
-
options={stringFilterTypes}
|
|
613
|
-
labelProp="label"
|
|
614
|
-
valueProp="value"
|
|
615
|
-
name="Filter Type"
|
|
616
|
-
valueAsObject
|
|
617
|
-
value={selectedStringFilterType}
|
|
618
|
-
onchange={(newValue: SelectOption<StringFilterMode> | null) => {
|
|
619
|
-
const filterType = newValue?.value ?? StringFilterMode.Contains;
|
|
620
|
-
tableContext.paginationRepo?.setFilterMode(def.id, filterType);
|
|
621
|
-
}}
|
|
622
|
-
onkeydown={(e: KeyboardEvent) => {
|
|
623
|
-
e.stopPropagation();
|
|
624
|
-
}}
|
|
625
|
-
/>
|
|
626
|
-
{/if}
|
|
627
|
-
</div>
|
|
628
|
-
</div>
|
|
629
|
-
{/if}
|
|
630
|
-
</td>
|
|
631
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<script
|
|
4
|
+
lang="ts"
|
|
5
|
+
generics="T extends object, FilterValueType"
|
|
6
|
+
>
|
|
7
|
+
import { dev } from '$app/environment';
|
|
8
|
+
import Action from '../../Action.svelte';
|
|
9
|
+
import Button from '../../Button.svelte';
|
|
10
|
+
import MultiSelect from '../../MultiSelect.svelte';
|
|
11
|
+
import NumberInput from '../../NumberInput.svelte';
|
|
12
|
+
import SingleSelect from '../../SingleSelect.svelte';
|
|
13
|
+
import TextInput from '../../TextInput.svelte';
|
|
14
|
+
import ThreeStateRadio from '../../ThreeStateRadio.svelte';
|
|
15
|
+
import DateModal from '../../Touch/DateModal.svelte';
|
|
16
|
+
import { devCatch, hasQuery, isDateTuple, isNumericArray } from '../../../Helpers/Helpers.svelte.js';
|
|
17
|
+
import { Colour, ColourSet } from '../../../scss/colours.js';
|
|
18
|
+
import { InputVariant } from '../../../Types/Internal/InputVariant.js';
|
|
19
|
+
import type { SelectOption } from '../../../Types/Internal/SelectOption.js';
|
|
20
|
+
import { Size } from '../../../Types/Internal/Size.js';
|
|
21
|
+
import { getContext, onMount, untrack } from 'svelte';
|
|
22
|
+
import { cubicOut } from 'svelte/easing';
|
|
23
|
+
import { fade } from 'svelte/transition';
|
|
24
|
+
|
|
25
|
+
import QuerySelect from '../../QuerySelect.svelte';
|
|
26
|
+
import { Ternary } from '../../../Types/Internal/Ternary.js';
|
|
27
|
+
import { numberDateFilterTypes } from '../Misc/numberDateFilterTypes.js';
|
|
28
|
+
import { stringFilterTypes } from '../Misc/stringFilterTypes.js';
|
|
29
|
+
import { quickFilterContextIdentifier } from '../Table.svelte';
|
|
30
|
+
import { CheckboxDef } from '../Types/Columns/Definitions/Accessors/CheckboxDef.svelte.js';
|
|
31
|
+
import { DateInputDef } from '../Types/Columns/Definitions/Accessors/DateInputDef.svelte.js';
|
|
32
|
+
import { NumberInputDef } from '../Types/Columns/Definitions/Accessors/NumberInputDef.svelte.js';
|
|
33
|
+
import { SelectDef } from '../Types/Columns/Definitions/Accessors/SelectDef.svelte.js';
|
|
34
|
+
import { TableContext } from '../Types/Context/TableContext.svelte.js';
|
|
35
|
+
import { CustomFilterType } from '../Types/Filtering/CustomFilterType.js';
|
|
36
|
+
import { NumberDateFilterMode } from '../Types/Filtering/NumberDateFilterMode.js';
|
|
37
|
+
import { StringFilterMode } from '../Types/Filtering/StringFilterMode.js';
|
|
38
|
+
import type { QuickSearchCellProps } from './QuickSearchCellProps.js';
|
|
39
|
+
|
|
40
|
+
const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
|
|
41
|
+
|
|
42
|
+
const { column, customFilters }: QuickSearchCellProps<T, FilterValueType> = $props();
|
|
43
|
+
|
|
44
|
+
const def = $derived(column.columnDef);
|
|
45
|
+
|
|
46
|
+
const customFilter = $derived(customFilters?.get(def.id));
|
|
47
|
+
|
|
48
|
+
const isSelect = $derived(
|
|
49
|
+
def instanceof SelectDef ||
|
|
50
|
+
def.filterValueType == CustomFilterType.Select ||
|
|
51
|
+
customFilter?.type === CustomFilterType.Select
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const hasFilterFn = $derived(!!def.filterFn && typeof def.filterFn === 'function');
|
|
55
|
+
|
|
56
|
+
// const hasAcceptableColumnType = $derived(
|
|
57
|
+
// (def instanceof AccessorDef && searchableTypes.has(def.accessorType)) ||
|
|
58
|
+
// (def instanceof AbstractDisplayDef && searchableTypes.has(def.displayType))
|
|
59
|
+
// );
|
|
60
|
+
|
|
61
|
+
const isSearchable = $derived(
|
|
62
|
+
def.allowFiltering && (hasFilterFn || customFilters?.has(def.id) == true)
|
|
63
|
+
// ((hasFilterFn && hasAcceptableColumnType) || customFilters?.has(def.id) == true) // removed hasAcceptableColumnType due to it being redundant
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const isNumeric = $derived(
|
|
67
|
+
def instanceof NumberInputDef ||
|
|
68
|
+
def.filterValueType == 'Number' ||
|
|
69
|
+
customFilter?.type === CustomFilterType.Number
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
function emptyOptsAndWarn(): Array<SelectOption<unknown>> {
|
|
73
|
+
console.warn(`def ${def.id} is declared as a select filter but has no getOptions() function`);
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
const options = $derived(
|
|
77
|
+
isSelect ? (def.getOptions?.() ?? customFilter?.options ?? emptyOptsAndWarn()) : []
|
|
78
|
+
);
|
|
79
|
+
const isDate = $derived(def instanceof DateInputDef);
|
|
80
|
+
const isRemoteSelect = $derived(customFilter?.type === CustomFilterType.Select);
|
|
81
|
+
|
|
82
|
+
const selectSymbol = Symbol();
|
|
83
|
+
|
|
84
|
+
const openedSelect = getContext<{ value: symbol | null } | null | undefined>(
|
|
85
|
+
quickFilterContextIdentifier
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const isSelectOpen = $derived(openedSelect?.value === selectSymbol);
|
|
89
|
+
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
|
91
|
+
let asdfvalue: unknown | null = $state(null);
|
|
92
|
+
let valueMin: number | null = $state(null);
|
|
93
|
+
let valueMax: number | null = $state(null);
|
|
94
|
+
|
|
95
|
+
let selectedOptions: Array<SelectOption<unknown>> = $state([]);
|
|
96
|
+
let lastQueryOptions: Array<SelectOption<unknown>> = $state([]);
|
|
97
|
+
|
|
98
|
+
const inputId = $derived(`${tableContext.tableName}-cell-quicksearch-${column.id}`);
|
|
99
|
+
|
|
100
|
+
const filterMode = $derived(tableContext.paginationRepo?.filterModes.get(def.id));
|
|
101
|
+
|
|
102
|
+
const selectedNumberFilterType: SelectOption<NumberDateFilterMode> | null = $derived.by(() => {
|
|
103
|
+
const value = (filterMode as NumberDateFilterMode | undefined) ?? NumberDateFilterMode.In;
|
|
104
|
+
return numberDateFilterTypes.find((it) => it.value === value) ?? null;
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const selectedStringFilterType: SelectOption<StringFilterMode> | null = $derived.by(() => {
|
|
108
|
+
const value = (filterMode as StringFilterMode | undefined) ?? StringFilterMode.Contains;
|
|
109
|
+
return stringFilterTypes.find((it) => it.value === value) ?? null;
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const filteringStateValue = $derived(
|
|
113
|
+
tableContext.paginationRepo?.filtering.find((it) => it.id === def.id)?.value
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
$effect(() => {
|
|
117
|
+
if (isRemoteSelect && !tableContext.paginationRepo?.filtering) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
void filteringStateValue;
|
|
121
|
+
|
|
122
|
+
if (hasQuery(customFilter)) {
|
|
123
|
+
if (def.debug) {
|
|
124
|
+
console.debug(`${def.id}: `, 'has query');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
untrack(async () => {
|
|
128
|
+
const gotValue = filteringStateValue as Array<unknown> | undefined;
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
// as unknown as string | number | undefined;
|
|
132
|
+
|
|
133
|
+
if (gotValue != undefined) {
|
|
134
|
+
if (def.debug) {
|
|
135
|
+
console.debug(`${def.id}: query values:`, tableContext.dataRepo.__queryValues);
|
|
136
|
+
}
|
|
137
|
+
const key = customFilter.id;
|
|
138
|
+
const x = await tableContext.dataRepo.__queryValues.get(key);
|
|
139
|
+
|
|
140
|
+
if (def.debug) {
|
|
141
|
+
console.debug(`${def.id}: `, 'value:', $state.snapshot(x));
|
|
142
|
+
}
|
|
143
|
+
asdfvalue = (await x) ?? null;
|
|
144
|
+
} else if (def.debug) {
|
|
145
|
+
console.debug(
|
|
146
|
+
`${def.id}: `,
|
|
147
|
+
'filtering state value was undefined',
|
|
148
|
+
$state.snapshot(tableContext.paginationRepo?.filtering)
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
} catch (e) {
|
|
152
|
+
console.warn(e);
|
|
153
|
+
asdfvalue = null;
|
|
154
|
+
}
|
|
155
|
+
}).catch(devCatch);
|
|
156
|
+
} else if (isSelect) {
|
|
157
|
+
if (def.debug) {
|
|
158
|
+
console.debug(`${def.id}: `, 'is select (not query)');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!tableContext.paginationRepo?.filtering) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const gotValue = filteringStateValue as Array<unknown> | undefined;
|
|
166
|
+
|
|
167
|
+
function isSelectOption(it: unknown): it is SelectOption<unknown> {
|
|
168
|
+
return it != null && typeof it == 'object';
|
|
169
|
+
}
|
|
170
|
+
untrack(async () => {
|
|
171
|
+
try {
|
|
172
|
+
const opts = await options;
|
|
173
|
+
if (def.debug) {
|
|
174
|
+
console.debug(`${def.id}: possible options:`, $state.snapshot(opts));
|
|
175
|
+
}
|
|
176
|
+
const x = opts.filter((it) => {
|
|
177
|
+
if (!isSelectOption(it)) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
if (it.value == undefined) {
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (typeof it.value == 'string' || typeof it.value == 'number') {
|
|
185
|
+
return (gotValue as unknown as Array<string | number> | undefined)?.includes(
|
|
186
|
+
it.value
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return false;
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
if (def.debug) {
|
|
194
|
+
console.debug(`${def.id}: `, 'selected options:', x);
|
|
195
|
+
}
|
|
196
|
+
selectedOptions = x;
|
|
197
|
+
} catch (e) {
|
|
198
|
+
if (dev || def.debug) {
|
|
199
|
+
console.debug(`${def.id}: `, e);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}).catch(devCatch);
|
|
203
|
+
} else if (isNumeric) {
|
|
204
|
+
if (
|
|
205
|
+
selectedNumberFilterType?.value === NumberDateFilterMode.Between &&
|
|
206
|
+
tableContext.paginationRepo?.filtering
|
|
207
|
+
) {
|
|
208
|
+
const gotValue = filteringStateValue;
|
|
209
|
+
if (gotValue != undefined) {
|
|
210
|
+
const [min, max] = gotValue as [number, number | undefined];
|
|
211
|
+
asdfvalue = min;
|
|
212
|
+
valueMin = min;
|
|
213
|
+
valueMax = max ?? null;
|
|
214
|
+
} else {
|
|
215
|
+
asdfvalue = valueMin = valueMax = null;
|
|
216
|
+
}
|
|
217
|
+
} else if (tableContext.paginationRepo?.filtering) {
|
|
218
|
+
const gotValue = filteringStateValue;
|
|
219
|
+
|
|
220
|
+
if (gotValue != undefined) {
|
|
221
|
+
const [min] = gotValue as [number, number | undefined];
|
|
222
|
+
asdfvalue = min;
|
|
223
|
+
valueMin = min;
|
|
224
|
+
valueMax = min;
|
|
225
|
+
} else {
|
|
226
|
+
asdfvalue = valueMin = valueMax = null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
} else if (tableContext.paginationRepo?.filtering) {
|
|
230
|
+
const gotValue = filteringStateValue;
|
|
231
|
+
if (gotValue == null || typeof gotValue == 'string' || typeof gotValue == 'number') {
|
|
232
|
+
//RATS
|
|
233
|
+
rats(gotValue);
|
|
234
|
+
asdfvalue = gotValue;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
function rats(gotValue: unknown) {
|
|
240
|
+
// RATS
|
|
241
|
+
if (dev && gotValue != null && typeof gotValue == 'object' && gotValue instanceof Promise) {
|
|
242
|
+
throw new Error(`Unexpected Promise`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
onMount(() => {
|
|
246
|
+
const filterOption =
|
|
247
|
+
tableContext.paginationRepo?.filtering &&
|
|
248
|
+
tableContext.paginationRepo.filtering.find((it) => it.id === def.id);
|
|
249
|
+
|
|
250
|
+
if (filterOption) {
|
|
251
|
+
if (isNumericArray(filterOption.value)) {
|
|
252
|
+
[valueMin, valueMax] = filterOption.value;
|
|
253
|
+
if (valueMax == undefined) {
|
|
254
|
+
valueMax = valueMin;
|
|
255
|
+
asdfvalue = valueMin?.toString();
|
|
256
|
+
} else if (valueMin == undefined) {
|
|
257
|
+
valueMin = valueMax;
|
|
258
|
+
asdfvalue = valueMax.toString();
|
|
259
|
+
} else {
|
|
260
|
+
asdfvalue = valueMin.toString();
|
|
261
|
+
}
|
|
262
|
+
} else if (!hasQuery(customFilter)) {
|
|
263
|
+
const gotValue = filterOption.value;
|
|
264
|
+
if (gotValue == null || typeof gotValue == 'string' || typeof gotValue == 'number') {
|
|
265
|
+
//RATS
|
|
266
|
+
rats(gotValue);
|
|
267
|
+
asdfvalue = gotValue;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
function closeOnCtrlF(e: KeyboardEvent) {
|
|
274
|
+
if (e.key.toLocaleUpperCase() === 'F' && e.ctrlKey) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
e.stopPropagation();
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
let showFromDateModal = $state(false);
|
|
281
|
+
let showToDateModal = $state(false);
|
|
282
|
+
|
|
283
|
+
function generateOnChangeObject(label: string) {
|
|
284
|
+
return (newValue: SelectOption<unknown> | null) => {
|
|
285
|
+
tableContext.paginationRepo?.filterBy(def.id, newValue?.value ?? null);
|
|
286
|
+
tableContext.dataRepo.__queryValues.set(label, newValue);
|
|
287
|
+
rats(newValue);
|
|
288
|
+
asdfvalue = newValue;
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function generateOnChangePrimitive(label: string) {
|
|
293
|
+
return (newValue: SelectOption<unknown> | null) => {
|
|
294
|
+
tableContext.paginationRepo?.filterBy(def.id, newValue?.value ?? null);
|
|
295
|
+
tableContext.dataRepo.__queryValues.set(label, newValue?.value ?? null);
|
|
296
|
+
rats(newValue);
|
|
297
|
+
asdfvalue = newValue?.value ?? null;
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
let isNullFilter = $derived(selectedNumberFilterType?.value == NumberDateFilterMode.null);
|
|
302
|
+
</script>
|
|
303
|
+
|
|
304
|
+
<td class="input-cell {inputId}">
|
|
305
|
+
{#if isSearchable}
|
|
306
|
+
<div class="input-wrapper-parent">
|
|
307
|
+
{#if isDate}
|
|
308
|
+
{@const dateValues = tableContext.paginationRepo?.filtering.find((it) => it.id === def.id)
|
|
309
|
+
?.value ?? [null, null]}
|
|
310
|
+
{#if isDateTuple(dateValues)}
|
|
311
|
+
{@const [fromDate, toDate] = dateValues}
|
|
312
|
+
<div class="spaced-around">
|
|
313
|
+
<Button
|
|
314
|
+
size={Size.FillHeight}
|
|
315
|
+
fullWidth
|
|
316
|
+
onclick={() => {
|
|
317
|
+
showFromDateModal = true;
|
|
318
|
+
}}>From {fromDate?.toLocaleDateString() ?? 'Any Date'}</Button
|
|
319
|
+
>
|
|
320
|
+
|
|
321
|
+
<Button
|
|
322
|
+
size={Size.FillHeight}
|
|
323
|
+
fullWidth
|
|
324
|
+
onclick={() => {
|
|
325
|
+
showToDateModal = true;
|
|
326
|
+
}}>To {toDate?.toLocaleDateString() ?? 'Any Date'}</Button
|
|
327
|
+
>
|
|
328
|
+
</div>
|
|
329
|
+
|
|
330
|
+
{#if showFromDateModal}
|
|
331
|
+
<DateModal
|
|
332
|
+
header="Edit Date From"
|
|
333
|
+
value={fromDate}
|
|
334
|
+
cancelEditing={() => {
|
|
335
|
+
showFromDateModal = false;
|
|
336
|
+
}}
|
|
337
|
+
confirm={(e) => {
|
|
338
|
+
tableContext.paginationRepo?.filterBy(def.id, [e, toDate]);
|
|
339
|
+
showFromDateModal = false;
|
|
340
|
+
}}
|
|
341
|
+
/>
|
|
342
|
+
{/if}
|
|
343
|
+
|
|
344
|
+
{#if showToDateModal}
|
|
345
|
+
<DateModal
|
|
346
|
+
inclusive
|
|
347
|
+
header="Edit Date To"
|
|
348
|
+
value={toDate}
|
|
349
|
+
cancelEditing={() => {
|
|
350
|
+
showToDateModal = false;
|
|
351
|
+
}}
|
|
352
|
+
confirm={(e) => {
|
|
353
|
+
tableContext.paginationRepo?.filterBy(def.id, [fromDate, e]);
|
|
354
|
+
showToDateModal = false;
|
|
355
|
+
}}
|
|
356
|
+
/>
|
|
357
|
+
{/if}
|
|
358
|
+
{/if}
|
|
359
|
+
{:else if isSelect}
|
|
360
|
+
{#if hasQuery(customFilter)}
|
|
361
|
+
{#if customFilter.valueAsObject !== true}
|
|
362
|
+
{@const label = customFilter.id}
|
|
363
|
+
|
|
364
|
+
<!-- TODO: multiselect -->
|
|
365
|
+
|
|
366
|
+
<!-- FIXME: Most likely Unsafe -->
|
|
367
|
+
<QuerySelect
|
|
368
|
+
valueAsObject={false}
|
|
369
|
+
clearable
|
|
370
|
+
name={customFilter.objectName ?? 'Item'}
|
|
371
|
+
valueProp="value"
|
|
372
|
+
labelProp="label"
|
|
373
|
+
value={asdfvalue as null}
|
|
374
|
+
query={customFilter.query}
|
|
375
|
+
bind:options={lastQueryOptions}
|
|
376
|
+
onchange={generateOnChangePrimitive(label)}
|
|
377
|
+
/>
|
|
378
|
+
{:else}
|
|
379
|
+
{@const label = customFilter.id}
|
|
380
|
+
|
|
381
|
+
<!-- TODO: multiselect -->
|
|
382
|
+
|
|
383
|
+
<QuerySelect
|
|
384
|
+
valueAsObject={true}
|
|
385
|
+
clearable
|
|
386
|
+
name={customFilter.objectName ?? 'Item'}
|
|
387
|
+
valueProp="value"
|
|
388
|
+
labelProp="label"
|
|
389
|
+
value={asdfvalue as null}
|
|
390
|
+
query={customFilter.query}
|
|
391
|
+
bind:options={lastQueryOptions}
|
|
392
|
+
onchange={generateOnChangeObject(label)}
|
|
393
|
+
/>
|
|
394
|
+
{/if}
|
|
395
|
+
{:else}
|
|
396
|
+
{#await options then options}
|
|
397
|
+
<MultiSelect
|
|
398
|
+
labelProp="label"
|
|
399
|
+
valueProp="value"
|
|
400
|
+
{options}
|
|
401
|
+
valueAsObject
|
|
402
|
+
onchange={(e: Array<SelectOption<unknown>>) => {
|
|
403
|
+
tableContext.paginationRepo?.filterBy(
|
|
404
|
+
def.id,
|
|
405
|
+
e.map((it) => it.value)
|
|
406
|
+
);
|
|
407
|
+
}}
|
|
408
|
+
selectedValues={selectedOptions}
|
|
409
|
+
collapseSelection
|
|
410
|
+
/>
|
|
411
|
+
{/await}
|
|
412
|
+
{/if}
|
|
413
|
+
{:else if def instanceof CheckboxDef}
|
|
414
|
+
{@const value = (() => {
|
|
415
|
+
switch (tableContext.paginationRepo?.filtering.find((it) => it.id === def.id)?.value) {
|
|
416
|
+
case true: {
|
|
417
|
+
return Ternary.True;
|
|
418
|
+
}
|
|
419
|
+
case false: {
|
|
420
|
+
return Ternary.False;
|
|
421
|
+
}
|
|
422
|
+
default: {
|
|
423
|
+
return Ternary.Neutral;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
})()}
|
|
427
|
+
<div class="centered">
|
|
428
|
+
<ThreeStateRadio
|
|
429
|
+
{value}
|
|
430
|
+
yesLabel="Selected"
|
|
431
|
+
noLabel="Not Selected"
|
|
432
|
+
neutralLabel="Any"
|
|
433
|
+
neutralIcon={{ name: 'circle-minus' }}
|
|
434
|
+
onchange={(v) => {
|
|
435
|
+
switch (v) {
|
|
436
|
+
case Ternary.False: {
|
|
437
|
+
tableContext.paginationRepo?.filterBy(def.id, false);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
case Ternary.True: {
|
|
441
|
+
tableContext.paginationRepo?.filterBy(def.id, true);
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
case Ternary.Neutral:
|
|
445
|
+
default: {
|
|
446
|
+
tableContext.paginationRepo?.filterBy(def.id, null);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}}
|
|
451
|
+
/>
|
|
452
|
+
</div>
|
|
453
|
+
{:else if isNumeric}
|
|
454
|
+
{#if selectedNumberFilterType?.value === NumberDateFilterMode.Between}
|
|
455
|
+
<div class="input-wrapper left">
|
|
456
|
+
<NumberInput
|
|
457
|
+
data-type="quicksearch"
|
|
458
|
+
id={inputId}
|
|
459
|
+
bind:value={valueMin}
|
|
460
|
+
variant={InputVariant.Table}
|
|
461
|
+
placeholder="Min…"
|
|
462
|
+
oninput={() => {
|
|
463
|
+
tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMax]);
|
|
464
|
+
}}
|
|
465
|
+
onkeydown={closeOnCtrlF}
|
|
466
|
+
/>
|
|
467
|
+
</div>
|
|
468
|
+
<div class="input-wrapper right">
|
|
469
|
+
<NumberInput
|
|
470
|
+
data-type="quicksearch"
|
|
471
|
+
id={inputId}
|
|
472
|
+
bind:value={valueMax}
|
|
473
|
+
placeholder="Max…"
|
|
474
|
+
variant={InputVariant.Table}
|
|
475
|
+
oninput={() => {
|
|
476
|
+
tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMax]);
|
|
477
|
+
}}
|
|
478
|
+
onkeydown={closeOnCtrlF}
|
|
479
|
+
/>
|
|
480
|
+
</div>
|
|
481
|
+
{:else}
|
|
482
|
+
<div class="input-wrapper right">
|
|
483
|
+
{#await isNullFilter}
|
|
484
|
+
loading
|
|
485
|
+
{:then isNullFilter}
|
|
486
|
+
{#if isNullFilter}
|
|
487
|
+
<TextInput
|
|
488
|
+
data-type="quicksearch"
|
|
489
|
+
id={inputId}
|
|
490
|
+
value="is Null"
|
|
491
|
+
disabled
|
|
492
|
+
variant={InputVariant.Table}
|
|
493
|
+
/>
|
|
494
|
+
{:else}
|
|
495
|
+
<!-- NOTE: This is a text input in order to support the __in functionality, which is a comma separated list of numbers -->
|
|
496
|
+
<TextInput
|
|
497
|
+
data-type="quicksearch"
|
|
498
|
+
id={inputId}
|
|
499
|
+
bind:value={asdfvalue as string | null}
|
|
500
|
+
placeholder="Filter…"
|
|
501
|
+
variant={InputVariant.Table}
|
|
502
|
+
oninput={() => {
|
|
503
|
+
tableContext.paginationRepo?.filterBy(def.id, [asdfvalue || null]);
|
|
504
|
+
}}
|
|
505
|
+
onkeydown={closeOnCtrlF}
|
|
506
|
+
/>
|
|
507
|
+
{/if}
|
|
508
|
+
{:catch e}
|
|
509
|
+
{@debug e}
|
|
510
|
+
{/await}
|
|
511
|
+
</div>
|
|
512
|
+
{/if}
|
|
513
|
+
{:else if asdfvalue == null || typeof asdfvalue == 'string'}
|
|
514
|
+
<div class="input-wrapper right">
|
|
515
|
+
{#if selectedStringFilterType?.value == StringFilterMode.null}
|
|
516
|
+
<TextInput
|
|
517
|
+
data-type="quicksearch"
|
|
518
|
+
id={inputId}
|
|
519
|
+
value="is Null"
|
|
520
|
+
disabled
|
|
521
|
+
variant={InputVariant.Table}
|
|
522
|
+
/>
|
|
523
|
+
{:else if selectedStringFilterType?.value == StringFilterMode.Empty}
|
|
524
|
+
<TextInput
|
|
525
|
+
data-type="quicksearch"
|
|
526
|
+
id={inputId}
|
|
527
|
+
value="is Empty"
|
|
528
|
+
disabled
|
|
529
|
+
variant={InputVariant.Table}
|
|
530
|
+
/>
|
|
531
|
+
{:else}
|
|
532
|
+
<TextInput
|
|
533
|
+
data-type="quicksearch"
|
|
534
|
+
id={inputId}
|
|
535
|
+
oninput={() => {
|
|
536
|
+
tableContext.paginationRepo?.filterBy(def.id, asdfvalue);
|
|
537
|
+
}}
|
|
538
|
+
variant={InputVariant.Table}
|
|
539
|
+
bind:value={asdfvalue as string | null}
|
|
540
|
+
placeholder="Filter…"
|
|
541
|
+
/>
|
|
542
|
+
{/if}
|
|
543
|
+
</div>
|
|
544
|
+
{/if}
|
|
545
|
+
|
|
546
|
+
<!-- TODO button for date, checkbox or select for checkbox -->
|
|
547
|
+
</div>
|
|
548
|
+
|
|
549
|
+
{#if !isSelect && !isDate && !(def instanceof CheckboxDef)}
|
|
550
|
+
<div class="stick-right">
|
|
551
|
+
<Action
|
|
552
|
+
data-type="quicksearch"
|
|
553
|
+
size={Size.FillHeight}
|
|
554
|
+
colourSet={ColourSet.Auxiliary}
|
|
555
|
+
icon={{
|
|
556
|
+
name: 'filter-2',
|
|
557
|
+
size: Size.MediumLarge,
|
|
558
|
+
colour: Colour['$ui-blue-5'],
|
|
559
|
+
}}
|
|
560
|
+
onclick={() => {
|
|
561
|
+
if (!openedSelect) {
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (openedSelect.value === selectSymbol) {
|
|
565
|
+
openedSelect.value = null;
|
|
566
|
+
} else {
|
|
567
|
+
openedSelect.value = selectSymbol;
|
|
568
|
+
}
|
|
569
|
+
}}
|
|
570
|
+
/>
|
|
571
|
+
</div>
|
|
572
|
+
{/if}
|
|
573
|
+
{/if}
|
|
574
|
+
|
|
575
|
+
{#if isSelectOpen}
|
|
576
|
+
<div
|
|
577
|
+
class="floating"
|
|
578
|
+
transition:fade={{ easing: cubicOut, duration: 100 }}
|
|
579
|
+
>
|
|
580
|
+
<div class="select-wrapper">
|
|
581
|
+
{#if isNumeric}
|
|
582
|
+
<SingleSelect
|
|
583
|
+
options={numberDateFilterTypes}
|
|
584
|
+
labelProp="label"
|
|
585
|
+
valueProp="value"
|
|
586
|
+
name="Filter Type"
|
|
587
|
+
valueAsObject
|
|
588
|
+
value={selectedNumberFilterType}
|
|
589
|
+
onchange={(newValue: SelectOption<NumberDateFilterMode> | null) => {
|
|
590
|
+
const oldFilterType = selectedNumberFilterType;
|
|
591
|
+
|
|
592
|
+
const newFilterType = newValue?.value ?? NumberDateFilterMode.In;
|
|
593
|
+
|
|
594
|
+
if (newFilterType !== oldFilterType?.value) {
|
|
595
|
+
tableContext.paginationRepo?.setFilterMode(def.id, newFilterType);
|
|
596
|
+
|
|
597
|
+
if (newFilterType === NumberDateFilterMode.Between) {
|
|
598
|
+
tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMin]);
|
|
599
|
+
} else if (newFilterType === NumberDateFilterMode.In) {
|
|
600
|
+
tableContext.paginationRepo?.filterBy(def.id, [asdfvalue]);
|
|
601
|
+
} else {
|
|
602
|
+
tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMax]);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}}
|
|
606
|
+
onkeydown={(e: KeyboardEvent) => {
|
|
607
|
+
e.stopPropagation();
|
|
608
|
+
}}
|
|
609
|
+
/>
|
|
610
|
+
{:else}
|
|
611
|
+
<SingleSelect
|
|
612
|
+
options={stringFilterTypes}
|
|
613
|
+
labelProp="label"
|
|
614
|
+
valueProp="value"
|
|
615
|
+
name="Filter Type"
|
|
616
|
+
valueAsObject
|
|
617
|
+
value={selectedStringFilterType}
|
|
618
|
+
onchange={(newValue: SelectOption<StringFilterMode> | null) => {
|
|
619
|
+
const filterType = newValue?.value ?? StringFilterMode.Contains;
|
|
620
|
+
tableContext.paginationRepo?.setFilterMode(def.id, filterType);
|
|
621
|
+
}}
|
|
622
|
+
onkeydown={(e: KeyboardEvent) => {
|
|
623
|
+
e.stopPropagation();
|
|
624
|
+
}}
|
|
625
|
+
/>
|
|
626
|
+
{/if}
|
|
627
|
+
</div>
|
|
628
|
+
</div>
|
|
629
|
+
{/if}
|
|
630
|
+
</td>
|
|
631
|
+
|
|
632
632
|
<style>td {
|
|
633
633
|
transition: line-height 0.2s ease, height 0.2s ease;
|
|
634
634
|
--input-border: none;
|
|
@@ -753,4 +753,4 @@ td .input-wrapper-parent {
|
|
|
753
753
|
height: 60px;
|
|
754
754
|
--input-height: 60px;
|
|
755
755
|
background-color: #ffffff;
|
|
756
|
-
}</style>
|
|
756
|
+
}</style>
|