@firecms/core 3.0.1 → 3.1.0-canary.24c8270
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 +1 -1
- package/dist/components/AIIcon.d.ts +16 -0
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +7 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +14 -0
- package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +6 -0
- package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -4
- package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +6 -0
- package/dist/components/EntityCollectionTable/internal/popup_field/useDraggable.d.ts +2 -2
- package/dist/components/EntityCollectionView/Board.d.ts +2 -0
- package/dist/components/EntityCollectionView/BoardColumn.d.ts +42 -0
- package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +9 -0
- package/dist/components/EntityCollectionView/BoardSortableList.d.ts +14 -0
- package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +26 -0
- package/dist/components/EntityCollectionView/EntityCard.d.ts +19 -0
- package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +20 -0
- package/dist/components/EntityCollectionView/EntityCollectionCardView.d.ts +31 -0
- package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +2 -2
- package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +7 -3
- package/dist/components/EntityCollectionView/FiltersDialog.d.ts +14 -0
- package/dist/components/EntityCollectionView/ViewModeToggle.d.ts +44 -0
- package/dist/components/EntityCollectionView/board_types.d.ts +105 -0
- package/dist/components/EntityCollectionView/useBoardDataController.d.ts +60 -0
- package/dist/components/ErrorBoundary.d.ts +1 -1
- package/dist/components/SelectableTable/SelectableTable.d.ts +5 -1
- package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -1
- package/dist/components/VirtualTable/VirtualTableCell.d.ts +6 -0
- package/dist/components/VirtualTable/VirtualTableHeader.d.ts +3 -1
- package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +11 -0
- package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +1 -0
- package/dist/components/VirtualTable/types.d.ts +2 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/contexts/index.d.ts +10 -0
- package/dist/core/DrawerNavigationGroup.d.ts +45 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/form/components/ErrorFocus.d.ts +1 -1
- package/dist/form/validation.d.ts +3 -2
- package/dist/hooks/useBreadcrumbsController.d.ts +16 -0
- package/dist/hooks/useCollapsedGroups.d.ts +4 -1
- package/dist/index.es.js +5316 -1592
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +5309 -1586
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useRestoreScroll.d.ts +1 -1
- package/dist/preview/PropertyPreviewProps.d.ts +5 -0
- package/dist/preview/components/DatePreview.d.ts +13 -3
- package/dist/preview/components/ImagePreview.d.ts +5 -1
- package/dist/preview/components/StorageThumbnail.d.ts +2 -1
- package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
- package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
- package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
- package/dist/types/analytics.d.ts +1 -1
- package/dist/types/collections.d.ts +50 -2
- package/dist/types/datasource.d.ts +0 -1
- package/dist/types/plugins.d.ts +62 -1
- package/dist/types/properties.d.ts +259 -4
- package/dist/util/__tests__/conditions.test.d.ts +1 -0
- package/dist/util/__tests__/objects.test.d.ts +1 -0
- package/dist/util/conditions.d.ts +26 -0
- package/dist/util/entities.d.ts +2 -3
- package/dist/util/index.d.ts +2 -1
- package/dist/util/property_utils.d.ts +2 -1
- package/dist/util/resolutions.d.ts +3 -3
- package/package.json +14 -11
- package/src/app/Scaffold.tsx +14 -15
- package/src/components/AIIcon.tsx +39 -0
- package/src/components/ArrayContainer.tsx +1 -4
- package/src/components/ClearFilterSortButton.tsx +19 -16
- package/src/components/ConfirmationDialog.tsx +0 -2
- package/src/components/DeleteEntityDialog.tsx +2 -4
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +74 -41
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +130 -79
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +121 -104
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +132 -103
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +20 -42
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +90 -49
- package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +11 -11
- package/src/components/EntityCollectionView/Board.tsx +324 -0
- package/src/components/EntityCollectionView/BoardColumn.tsx +158 -0
- package/src/components/EntityCollectionView/BoardColumnTitle.tsx +45 -0
- package/src/components/EntityCollectionView/BoardSortableList.tsx +172 -0
- package/src/components/EntityCollectionView/EntityBoardCard.tsx +212 -0
- package/src/components/EntityCollectionView/EntityCard.tsx +235 -0
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +733 -0
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +244 -0
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +519 -203
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +31 -19
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +84 -15
- package/src/components/EntityCollectionView/FiltersDialog.tsx +249 -0
- package/src/components/EntityCollectionView/ViewModeToggle.tsx +199 -0
- package/src/components/EntityCollectionView/board_types.ts +113 -0
- package/src/components/EntityCollectionView/useBoardDataController.tsx +490 -0
- package/src/components/ErrorTooltip.tsx +2 -1
- package/src/components/HomePage/DefaultHomePage.tsx +47 -10
- package/src/components/HomePage/HomePageDnD.tsx +56 -41
- package/src/components/HomePage/NavigationCard.tsx +20 -18
- package/src/components/HomePage/NavigationGroup.tsx +17 -16
- package/src/components/HomePage/RenameGroupDialog.tsx +0 -2
- package/src/components/HomePage/SmallNavigationCard.tsx +10 -9
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +3 -10
- package/src/components/ReferenceWidget.tsx +2 -4
- package/src/components/SelectableTable/SelectableTable.tsx +75 -67
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +7 -6
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +39 -40
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +38 -38
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +49 -58
- package/src/components/UnsavedChangesDialog.tsx +0 -2
- package/src/components/UserDisplay.tsx +4 -4
- package/src/components/VirtualTable/VirtualTable.tsx +272 -118
- package/src/components/VirtualTable/VirtualTableCell.tsx +18 -2
- package/src/components/VirtualTable/VirtualTableHeader.tsx +59 -50
- package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +158 -42
- package/src/components/VirtualTable/VirtualTableProps.tsx +14 -1
- package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -0
- package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +19 -6
- package/src/components/VirtualTable/types.tsx +2 -0
- package/src/components/common/useColumnsIds.tsx +95 -3
- package/src/components/common/useDataSourceTableController.tsx +21 -4
- package/src/components/index.tsx +4 -0
- package/src/contexts/BreacrumbsContext.tsx +15 -8
- package/src/contexts/index.ts +10 -0
- package/src/core/DefaultAppBar.tsx +40 -27
- package/src/core/DefaultDrawer.tsx +42 -56
- package/src/core/DrawerNavigationGroup.tsx +118 -0
- package/src/core/DrawerNavigationItem.tsx +4 -3
- package/src/core/EntityEditView.tsx +41 -43
- package/src/core/EntitySidePanel.tsx +28 -26
- package/src/core/SideDialogs.tsx +4 -2
- package/src/core/field_configs.tsx +14 -9
- package/src/core/index.tsx +1 -0
- package/src/form/EntityForm.tsx +69 -60
- package/src/form/PropertyFieldBinding.tsx +61 -46
- package/src/form/components/ErrorFocus.tsx +3 -3
- package/src/form/components/StorageItemPreview.tsx +2 -1
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +0 -1
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +17 -16
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +0 -1
- package/src/form/field_bindings/MapFieldBinding.tsx +69 -67
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +22 -18
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +83 -83
- package/src/form/field_bindings/TextFieldBinding.tsx +71 -35
- package/src/form/validation.ts +245 -160
- package/src/hooks/useBreadcrumbsController.tsx +18 -0
- package/src/hooks/useBuildNavigationController.tsx +71 -28
- package/src/hooks/useCollapsedGroups.ts +12 -4
- package/src/hooks/useValidateAuthenticator.tsx +1 -1
- package/src/internal/useBuildDataSource.ts +68 -34
- package/src/internal/useBuildSideDialogsController.tsx +11 -8
- package/src/internal/useBuildSideEntityController.tsx +24 -24
- package/src/internal/useRestoreScroll.tsx +26 -14
- package/src/preview/PropertyPreview.tsx +41 -32
- package/src/preview/PropertyPreviewProps.tsx +6 -0
- package/src/preview/components/DatePreview.tsx +72 -4
- package/src/preview/components/EmptyValue.tsx +1 -1
- package/src/preview/components/ImagePreview.tsx +37 -21
- package/src/preview/components/StorageThumbnail.tsx +16 -12
- package/src/preview/components/UrlComponentPreview.tsx +28 -25
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +9 -7
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +11 -9
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +26 -24
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +61 -56
- package/src/routes/CustomCMSRoute.tsx +1 -0
- package/src/routes/FireCMSRoute.tsx +26 -13
- package/src/types/analytics.ts +10 -0
- package/src/types/collections.ts +57 -3
- package/src/types/datasource.ts +54 -56
- package/src/types/plugins.tsx +69 -1
- package/src/types/properties.ts +347 -27
- package/src/util/__tests__/conditions.test.ts +506 -0
- package/src/util/__tests__/objects.test.ts +196 -0
- package/src/util/callbacks.ts +6 -3
- package/src/util/collections.ts +51 -6
- package/src/util/conditions.ts +339 -0
- package/src/util/entities.ts +29 -30
- package/src/util/entity_cache.ts +2 -1
- package/src/util/index.ts +2 -1
- package/src/util/join_collections.ts +10 -8
- package/src/util/objects.ts +31 -13
- package/src/util/{references.ts → previews.ts} +16 -2
- package/src/util/property_utils.tsx +37 -11
- package/src/util/resolutions.ts +62 -58
- /package/dist/util/{references.d.ts → previews.d.ts} +0 -0
|
@@ -10,11 +10,11 @@ interface BooleanFieldProps {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function BooleanFilterField({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
name,
|
|
14
|
+
title,
|
|
15
|
+
value,
|
|
16
|
+
setValue
|
|
17
|
+
}: BooleanFieldProps) {
|
|
18
18
|
|
|
19
19
|
function updateFilter(val?: boolean) {
|
|
20
20
|
if (val !== undefined) {
|
|
@@ -32,8 +32,9 @@ export function BooleanFilterField({
|
|
|
32
32
|
const valueSet = !!value;
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
-
<div className="w-
|
|
35
|
+
<div className="w-full">
|
|
36
36
|
<BooleanSwitchWithLabel
|
|
37
|
+
size={"medium"}
|
|
37
38
|
value={valueSetToTrue}
|
|
38
39
|
allowIndeterminate={true}
|
|
39
40
|
onValueChange={(v: boolean | null) => updateFilter(v === null ? undefined : v)}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
2
|
import { VirtualTableWhereFilterOp } from "../../VirtualTable";
|
|
3
|
-
import {
|
|
3
|
+
import { DateTimeField, Select, SelectItem } from "@firecms/ui";
|
|
4
4
|
import { useCustomizationController } from "../../../hooks";
|
|
5
5
|
|
|
6
6
|
interface DateTimeFilterFieldProps {
|
|
@@ -10,9 +10,10 @@ interface DateTimeFilterFieldProps {
|
|
|
10
10
|
setValue: (value?: [op: VirtualTableWhereFilterOp, newValue: any]) => void;
|
|
11
11
|
isArray?: boolean;
|
|
12
12
|
title?: string;
|
|
13
|
+
timezone?: string;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
const operationLabels: Record<VirtualTableWhereFilterOp, string> = {
|
|
16
|
+
const operationLabels: Record<VirtualTableWhereFilterOp | "is-null", string> = {
|
|
16
17
|
"==": "==",
|
|
17
18
|
"!=": "!=",
|
|
18
19
|
">": ">",
|
|
@@ -22,30 +23,42 @@ const operationLabels: Record<VirtualTableWhereFilterOp, string> = {
|
|
|
22
23
|
"not-in": "not in",
|
|
23
24
|
in: "in",
|
|
24
25
|
"array-contains": "Contains",
|
|
25
|
-
"array-contains-any": "Any"
|
|
26
|
+
"array-contains-any": "Any",
|
|
27
|
+
"is-null": "Is null"
|
|
26
28
|
};
|
|
27
29
|
|
|
28
30
|
const multipleSelectOperations = ["array-contains-any", "in"];
|
|
29
31
|
|
|
30
32
|
export function DateTimeFilterField({
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
name,
|
|
34
|
+
isArray,
|
|
35
|
+
mode,
|
|
36
|
+
value,
|
|
37
|
+
setValue,
|
|
38
|
+
title,
|
|
39
|
+
timezone
|
|
40
|
+
}: DateTimeFilterFieldProps) {
|
|
38
41
|
|
|
39
42
|
const { locale } = useCustomizationController();
|
|
40
|
-
const possibleOperations: (keyof typeof operationLabels)
|
|
43
|
+
const possibleOperations: (keyof typeof operationLabels)[] = isArray
|
|
41
44
|
? ["array-contains"]
|
|
42
|
-
: ["==", "!=", ">", "<", ">=", "<="];
|
|
45
|
+
: ["==", "!=", ">", "<", ">=", "<=", "is-null"];
|
|
43
46
|
|
|
44
47
|
const [fieldOperation, fieldValue] = value || [possibleOperations[0], undefined];
|
|
45
|
-
const [operation, setOperation] = useState<VirtualTableWhereFilterOp>(fieldOperation);
|
|
48
|
+
const [operation, setOperation] = useState<VirtualTableWhereFilterOp | "is-null">(fieldOperation === "==" && fieldValue === null ? "is-null" : fieldOperation);
|
|
46
49
|
const [internalValue, setInternalValue] = useState<Date | null | undefined>(fieldValue);
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
const isNullOperation = operation === "is-null";
|
|
52
|
+
|
|
53
|
+
function updateFilter(op: VirtualTableWhereFilterOp | "is-null", val: Date | undefined | null) {
|
|
54
|
+
// Handle "is null" operation
|
|
55
|
+
if (op === "is-null") {
|
|
56
|
+
setOperation(op);
|
|
57
|
+
setInternalValue(null);
|
|
58
|
+
setValue(["==", null]);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
49
62
|
let newValue: Date | null | undefined = val;
|
|
50
63
|
const prevOpIsArray = multipleSelectOperations.includes(operation);
|
|
51
64
|
const newOpIsArray = multipleSelectOperations.includes(op);
|
|
@@ -73,15 +86,15 @@ export function DateTimeFilterField({
|
|
|
73
86
|
|
|
74
87
|
return (
|
|
75
88
|
|
|
76
|
-
<div className="flex w-
|
|
77
|
-
<div className="w-[
|
|
89
|
+
<div className="flex w-full">
|
|
90
|
+
<div className="w-[100px]">
|
|
78
91
|
<Select value={operation}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
size={"medium"}
|
|
93
|
+
fullWidth={true}
|
|
94
|
+
onValueChange={(value) => {
|
|
95
|
+
updateFilter(value as VirtualTableWhereFilterOp | "is-null", internalValue);
|
|
96
|
+
}}
|
|
97
|
+
renderValue={(op) => operationLabels[op as keyof typeof operationLabels]}>
|
|
85
98
|
{possibleOperations.map((op) => (
|
|
86
99
|
<SelectItem key={op} value={op}>
|
|
87
100
|
{operationLabels[op]}
|
|
@@ -94,31 +107,17 @@ export function DateTimeFilterField({
|
|
|
94
107
|
|
|
95
108
|
<DateTimeField
|
|
96
109
|
mode={mode}
|
|
97
|
-
size={"
|
|
110
|
+
size={"medium"}
|
|
98
111
|
locale={locale}
|
|
99
|
-
|
|
100
|
-
|
|
112
|
+
timezone={timezone}
|
|
113
|
+
disabled={isNullOperation}
|
|
114
|
+
value={isNullOperation ? undefined : (internalValue ?? undefined)}
|
|
101
115
|
onChange={(dateValue: Date | null) => {
|
|
102
116
|
updateFilter(operation, dateValue === null ? undefined : dateValue);
|
|
103
117
|
}}
|
|
104
118
|
clearable={true}
|
|
105
119
|
/>
|
|
106
120
|
|
|
107
|
-
<Label
|
|
108
|
-
className="border cursor-pointer rounded-md p-2 flex items-center gap-2 [&:has(:checked)]:bg-surface-100 dark:[&:has(:checked)]:bg-surface-800"
|
|
109
|
-
htmlFor="null-filter"
|
|
110
|
-
>
|
|
111
|
-
<Checkbox id="null-filter"
|
|
112
|
-
checked={internalValue === null}
|
|
113
|
-
size={"small"}
|
|
114
|
-
onCheckedChange={(checked) => {
|
|
115
|
-
if (internalValue !== null)
|
|
116
|
-
updateFilter(operation, null);
|
|
117
|
-
else updateFilter(operation, undefined);
|
|
118
|
-
}}/>
|
|
119
|
-
Filter for null values
|
|
120
|
-
</Label>
|
|
121
|
-
|
|
122
121
|
</div>
|
|
123
122
|
|
|
124
123
|
</div>
|
|
@@ -35,16 +35,16 @@ const operationLabels = {
|
|
|
35
35
|
const multipleSelectOperations = ["array-contains-any", "in", "not-in"];
|
|
36
36
|
|
|
37
37
|
export function ReferenceFilterField({
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const possibleOperations: (keyof typeof operationLabels)
|
|
38
|
+
value,
|
|
39
|
+
setValue,
|
|
40
|
+
isArray,
|
|
41
|
+
path,
|
|
42
|
+
includeId = true,
|
|
43
|
+
previewProperties,
|
|
44
|
+
setHidden
|
|
45
|
+
}: ReferenceFilterFieldProps) {
|
|
46
|
+
|
|
47
|
+
const possibleOperations: (keyof typeof operationLabels)[] = isArray
|
|
48
48
|
? ["array-contains"]
|
|
49
49
|
: ["==", "!=", ">", "<", ">=", "<="];
|
|
50
50
|
|
|
@@ -110,16 +110,16 @@ export function ReferenceFilterField({
|
|
|
110
110
|
const multiple = multipleSelectOperations.includes(operation);
|
|
111
111
|
|
|
112
112
|
const referenceDialogController = useReferenceDialog({
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
113
|
+
multiselect: multiple,
|
|
114
|
+
path,
|
|
115
|
+
collection,
|
|
116
|
+
onSingleEntitySelected,
|
|
117
|
+
onMultipleEntitiesSelected,
|
|
118
|
+
selectedEntityIds,
|
|
119
|
+
onClose: () => {
|
|
120
|
+
setHidden(false);
|
|
122
121
|
}
|
|
122
|
+
}
|
|
123
123
|
);
|
|
124
124
|
|
|
125
125
|
const doOpenDialog = () => {
|
|
@@ -144,15 +144,15 @@ export function ReferenceFilterField({
|
|
|
144
144
|
|
|
145
145
|
return (
|
|
146
146
|
|
|
147
|
-
<div className="flex w-
|
|
148
|
-
<div className="w-[
|
|
147
|
+
<div className="flex w-full flex-row">
|
|
148
|
+
<div className="w-[100px]">
|
|
149
149
|
<Select value={operation}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
150
|
+
size={"medium"}
|
|
151
|
+
fullWidth={true}
|
|
152
|
+
onValueChange={(value) => {
|
|
153
|
+
updateFilter(value as VirtualTableWhereFilterOp, internalValue);
|
|
154
|
+
}}
|
|
155
|
+
renderValue={(op) => operationLabels[op as VirtualTableWhereFilterOp]}>
|
|
156
156
|
{possibleOperations.map((op) => (
|
|
157
157
|
<SelectItem key={op} value={op}>
|
|
158
158
|
{operationLabels[op]}
|
|
@@ -161,7 +161,7 @@ export function ReferenceFilterField({
|
|
|
161
161
|
</Select>
|
|
162
162
|
</div>
|
|
163
163
|
|
|
164
|
-
<div className="flex-grow ml-2 h-full gap-2 flex flex-col
|
|
164
|
+
<div className="flex-grow ml-2 h-full gap-2 flex flex-col">
|
|
165
165
|
|
|
166
166
|
{internalValue && Array.isArray(internalValue) && <div>
|
|
167
167
|
{internalValue.map((ref, index) => buildEntry(ref))}
|
|
@@ -173,9 +173,9 @@ export function ReferenceFilterField({
|
|
|
173
173
|
|
|
174
174
|
{(!internalValue || (Array.isArray(internalValue) && internalValue.length === 0)) &&
|
|
175
175
|
<Button onClick={doOpenDialog}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
|
|
177
|
+
size={"medium"}
|
|
178
|
+
className="h-full w-full">
|
|
179
179
|
{multiple ? "Select references" : "Select reference"}
|
|
180
180
|
</Button>
|
|
181
181
|
}
|
|
@@ -185,13 +185,13 @@ export function ReferenceFilterField({
|
|
|
185
185
|
htmlFor="null-filter"
|
|
186
186
|
>
|
|
187
187
|
<Checkbox id="null-filter"
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
188
|
+
checked={internalValue === null}
|
|
189
|
+
size={"small"}
|
|
190
|
+
onCheckedChange={(checked) => {
|
|
191
|
+
if (internalValue !== null)
|
|
192
|
+
updateFilter(operation, null);
|
|
193
|
+
else updateFilter(operation, undefined);
|
|
194
|
+
}} />
|
|
195
195
|
Filter for null values
|
|
196
196
|
</Label>}
|
|
197
197
|
|
|
@@ -2,10 +2,8 @@ import React, { useState } from "react";
|
|
|
2
2
|
import { EnumValuesChip } from "../../../preview";
|
|
3
3
|
import { VirtualTableWhereFilterOp } from "../../VirtualTable";
|
|
4
4
|
import {
|
|
5
|
-
Checkbox,
|
|
6
5
|
CloseIcon,
|
|
7
6
|
IconButton,
|
|
8
|
-
Label,
|
|
9
7
|
MultiSelect,
|
|
10
8
|
MultiSelectItem,
|
|
11
9
|
Select,
|
|
@@ -34,24 +32,25 @@ const operationLabels = {
|
|
|
34
32
|
in: "In",
|
|
35
33
|
"not-in": "Not in",
|
|
36
34
|
"array-contains": "Contains",
|
|
37
|
-
"array-contains-any": "Any"
|
|
35
|
+
"array-contains-any": "Any",
|
|
36
|
+
"is-null": "Is null"
|
|
38
37
|
};
|
|
39
38
|
|
|
40
39
|
const multipleSelectOperations = ["array-contains-any", "in", "not-in"];
|
|
41
40
|
|
|
42
41
|
export function StringNumberFilterField({
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const possibleOperations: (keyof typeof operationLabels)
|
|
42
|
+
name,
|
|
43
|
+
value,
|
|
44
|
+
setValue,
|
|
45
|
+
dataType,
|
|
46
|
+
isArray,
|
|
47
|
+
enumValues,
|
|
48
|
+
title
|
|
49
|
+
}: StringNumberFilterFieldProps) {
|
|
50
|
+
|
|
51
|
+
const possibleOperations: (keyof typeof operationLabels)[] = isArray
|
|
53
52
|
? ["array-contains"]
|
|
54
|
-
: ["==", "!=", ">", "<", ">=", "<="];
|
|
53
|
+
: ["==", "!=", ">", "<", ">=", "<=", "is-null"];
|
|
55
54
|
|
|
56
55
|
if (enumValues)
|
|
57
56
|
isArray
|
|
@@ -59,10 +58,20 @@ export function StringNumberFilterField({
|
|
|
59
58
|
: possibleOperations.push("in", "not-in");
|
|
60
59
|
|
|
61
60
|
const [fieldOperation, fieldValue] = value || [possibleOperations[0], undefined];
|
|
62
|
-
const [operation, setOperation] = useState<VirtualTableWhereFilterOp>(fieldOperation);
|
|
61
|
+
const [operation, setOperation] = useState<VirtualTableWhereFilterOp | "is-null">(fieldOperation === "==" && fieldValue === null ? "is-null" : fieldOperation);
|
|
63
62
|
const [internalValue, setInternalValue] = useState<string | number | string[] | number[] | null | undefined>(fieldValue);
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
const isNullOperation = operation === "is-null";
|
|
65
|
+
|
|
66
|
+
function updateFilter(op: VirtualTableWhereFilterOp | "is-null", val: string | number | string[] | number[] | null | undefined) {
|
|
67
|
+
// Handle "is null" operation
|
|
68
|
+
if (op === "is-null") {
|
|
69
|
+
setOperation(op);
|
|
70
|
+
setInternalValue(null);
|
|
71
|
+
setValue(["==", null]);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
66
75
|
let newValue = val;
|
|
67
76
|
const prevOpIsArray = multipleSelectOperations.includes(operation);
|
|
68
77
|
const newOpIsArray = multipleSelectOperations.includes(op);
|
|
@@ -95,15 +104,16 @@ export function StringNumberFilterField({
|
|
|
95
104
|
|
|
96
105
|
return (
|
|
97
106
|
|
|
98
|
-
<div className="flex w-
|
|
99
|
-
<div className={"w-[
|
|
107
|
+
<div className="flex w-full">
|
|
108
|
+
<div className={"w-[100px]"}>
|
|
100
109
|
<Select value={operation}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
size={"medium"}
|
|
111
|
+
fullWidth={true}
|
|
112
|
+
position={"item-aligned"}
|
|
113
|
+
onValueChange={(value) => {
|
|
114
|
+
updateFilter(value as VirtualTableWhereFilterOp | "is-null", internalValue);
|
|
115
|
+
}}
|
|
116
|
+
renderValue={(op) => operationLabels[op as keyof typeof operationLabels]}>
|
|
107
117
|
{possibleOperations.map((op) => (
|
|
108
118
|
<SelectItem key={op} value={op}>
|
|
109
119
|
{operationLabels[op]}
|
|
@@ -115,8 +125,11 @@ export function StringNumberFilterField({
|
|
|
115
125
|
<div className="flex-grow ml-2 flex flex-col gap-2">
|
|
116
126
|
|
|
117
127
|
{!enumValues && <TextField
|
|
128
|
+
size={"medium"}
|
|
118
129
|
type={dataType === "number" ? "number" : undefined}
|
|
119
130
|
value={internalValue !== undefined && internalValue != null ? String(internalValue) : ""}
|
|
131
|
+
disabled={isNullOperation}
|
|
132
|
+
placeholder={isNullOperation ? "null" : undefined}
|
|
120
133
|
onChange={(evt) => {
|
|
121
134
|
const val = dataType === "number"
|
|
122
135
|
? parseFloat(evt.target.value)
|
|
@@ -125,14 +138,16 @@ export function StringNumberFilterField({
|
|
|
125
138
|
}}
|
|
126
139
|
endAdornment={internalValue !== undefined && internalValue != null && <IconButton
|
|
127
140
|
onClick={(e) => updateFilter(operation, undefined)}>
|
|
128
|
-
<CloseIcon/>
|
|
141
|
+
<CloseIcon />
|
|
129
142
|
</IconButton>}
|
|
130
143
|
/>}
|
|
131
144
|
|
|
132
145
|
{enumValues && !multiple &&
|
|
133
146
|
<Select
|
|
147
|
+
size={"medium"}
|
|
134
148
|
position={"item-aligned"}
|
|
135
149
|
fullWidth={true}
|
|
150
|
+
disabled={isNullOperation}
|
|
136
151
|
value={typeof internalValue === "string" ? internalValue : ""}
|
|
137
152
|
onValueChange={(value) => {
|
|
138
153
|
if (value !== "")
|
|
@@ -140,7 +155,7 @@ export function StringNumberFilterField({
|
|
|
140
155
|
}}
|
|
141
156
|
endAdornment={internalValue && <IconButton
|
|
142
157
|
onClick={(e) => updateFilter(operation, undefined)}>
|
|
143
|
-
<CloseIcon/>
|
|
158
|
+
<CloseIcon />
|
|
144
159
|
</IconButton>}
|
|
145
160
|
renderValue={(enumKey) => {
|
|
146
161
|
if (enumKey === null)
|
|
@@ -152,15 +167,15 @@ export function StringNumberFilterField({
|
|
|
152
167
|
key={`select_value_${name}_${enumKey}`}
|
|
153
168
|
enumKey={enumKey}
|
|
154
169
|
enumValues={enumValues}
|
|
155
|
-
size={"small"}/>;
|
|
170
|
+
size={"small"} />;
|
|
156
171
|
}}>
|
|
157
172
|
{enumValues.map((enumConfig) => (
|
|
158
173
|
<SelectItem key={`select_item_${name}_${enumConfig.id}`}
|
|
159
|
-
|
|
174
|
+
value={String(enumConfig.id)}>
|
|
160
175
|
<EnumValuesChip
|
|
161
176
|
enumKey={String(enumConfig.id)}
|
|
162
177
|
enumValues={enumValues}
|
|
163
|
-
size={"small"}/>
|
|
178
|
+
size={"small"} />
|
|
164
179
|
</SelectItem>
|
|
165
180
|
))}
|
|
166
181
|
</Select>
|
|
@@ -168,8 +183,10 @@ export function StringNumberFilterField({
|
|
|
168
183
|
|
|
169
184
|
{enumValues && multiple &&
|
|
170
185
|
<MultiSelect
|
|
186
|
+
size={"medium"}
|
|
171
187
|
position={"item-aligned"}
|
|
172
188
|
value={Array.isArray(internalValue) ? internalValue.map(e => String(e)) : []}
|
|
189
|
+
disabled={isNullOperation}
|
|
173
190
|
onValueChange={(value) => {
|
|
174
191
|
updateFilter(operation, dataType === "number" ? value.map(v => parseInt(v)) : value)
|
|
175
192
|
}}
|
|
@@ -177,47 +194,21 @@ export function StringNumberFilterField({
|
|
|
177
194
|
endAdornment={internalValue && <IconButton
|
|
178
195
|
className="absolute right-2 top-3"
|
|
179
196
|
onClick={(e) => updateFilter(operation, undefined)}>
|
|
180
|
-
<CloseIcon/>
|
|
197
|
+
<CloseIcon />
|
|
181
198
|
</IconButton>}
|
|
182
|
-
// renderValues={(enumKeys) => {
|
|
183
|
-
// console.log("renderValues", enumKeys);
|
|
184
|
-
// if (enumKeys === null)
|
|
185
|
-
// return "Filter for null values";
|
|
186
|
-
//
|
|
187
|
-
// return enumKeys.map(key => <EnumValuesChip
|
|
188
|
-
// key={`select_value_${name}_${enumKeys}`}
|
|
189
|
-
// enumKey={key}
|
|
190
|
-
// enumValues={enumValues}
|
|
191
|
-
// size={"small"}/>);
|
|
192
|
-
// }}
|
|
193
199
|
>
|
|
194
200
|
{enumValues.map((enumConfig) => (
|
|
195
201
|
<MultiSelectItem key={`select_value_${name}_${enumConfig.id}`}
|
|
196
|
-
|
|
202
|
+
value={String(enumConfig.id)}>
|
|
197
203
|
<EnumValuesChip
|
|
198
204
|
enumKey={String(enumConfig.id)}
|
|
199
205
|
enumValues={enumValues}
|
|
200
|
-
size={"small"}/>
|
|
206
|
+
size={"small"} />
|
|
201
207
|
</MultiSelectItem>
|
|
202
208
|
))}
|
|
203
209
|
</MultiSelect>
|
|
204
210
|
}
|
|
205
211
|
|
|
206
|
-
{!isArray && <Label
|
|
207
|
-
className="border cursor-pointer rounded-md p-2 flex items-center gap-2 [&:has(:checked)]:bg-surface-100 dark:[&:has(:checked)]:bg-surface-800"
|
|
208
|
-
htmlFor="null-filter"
|
|
209
|
-
>
|
|
210
|
-
<Checkbox id="null-filter"
|
|
211
|
-
checked={internalValue === null}
|
|
212
|
-
size={"small"}
|
|
213
|
-
onCheckedChange={(checked) => {
|
|
214
|
-
if (internalValue !== null)
|
|
215
|
-
updateFilter(operation, null);
|
|
216
|
-
else updateFilter(operation, undefined);
|
|
217
|
-
}}/>
|
|
218
|
-
Filter for null values
|
|
219
|
-
</Label>}
|
|
220
|
-
|
|
221
212
|
</div>
|
|
222
213
|
|
|
223
214
|
</div>
|
|
@@ -35,10 +35,8 @@ export function UnsavedChangesDialog({
|
|
|
35
35
|
</DialogContent>
|
|
36
36
|
<DialogActions>
|
|
37
37
|
<Button variant="text"
|
|
38
|
-
color={"primary"}
|
|
39
38
|
onClick={handleCancel} autoFocus> Cancel </Button>
|
|
40
39
|
<Button
|
|
41
|
-
color={"primary"}
|
|
42
40
|
onClick={handleOk}> Ok </Button>
|
|
43
41
|
</DialogActions>
|
|
44
42
|
</Dialog>
|
|
@@ -6,17 +6,17 @@ import { EmptyValue } from "../preview";
|
|
|
6
6
|
* Component to render a single user with name and email
|
|
7
7
|
*/
|
|
8
8
|
export function UserDisplay({
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
user,
|
|
10
|
+
}: { user: User | null }) {
|
|
11
11
|
if (!user) {
|
|
12
|
-
return <EmptyValue/>;
|
|
12
|
+
return <EmptyValue />;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const avatarSizeClass = "w-6 h-6";
|
|
16
16
|
|
|
17
17
|
return (
|
|
18
18
|
<div className={cls(
|
|
19
|
-
"inline-flex items-center gap-4 px-2 py-1 rounded-xl",
|
|
19
|
+
"inline-flex items-center gap-4 px-2 py-1 rounded-xl text-left",
|
|
20
20
|
"bg-surface-accent-100 dark:bg-surface-accent-800",
|
|
21
21
|
"border",
|
|
22
22
|
defaultBorderMixin
|