@rebasepro/admin 0.1.0 → 0.2.1
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/LICENSE +21 -6
- package/dist/{CollectionEditorDialog-MbvXGzEq.js → CollectionEditorDialog-BXIh2AXg.js} +40 -31
- package/dist/CollectionEditorDialog-BXIh2AXg.js.map +1 -0
- package/dist/{CollectionsStudioView-D9X6aiAr.js → CollectionsStudioView-jR8iz_ja.js} +6 -8
- package/dist/CollectionsStudioView-jR8iz_ja.js.map +1 -0
- package/dist/{ContentHomePage-CfVB1eUo.js → ContentHomePage-BQZWuOFb.js} +5 -7
- package/dist/ContentHomePage-BQZWuOFb.js.map +1 -0
- package/dist/{ExportCollectionAction-CUwJg4F9.js → ExportCollectionAction-CMdiiv1L.js} +36 -38
- package/dist/ExportCollectionAction-CMdiiv1L.js.map +1 -0
- package/dist/{ImportCollectionAction-DGa_SF_8.js → ImportCollectionAction-C05lE0IW.js} +5 -7
- package/dist/ImportCollectionAction-C05lE0IW.js.map +1 -0
- package/dist/{PropertyEditView-C4nlYmAc.js → PropertyEditView-BB5xjnhZ.js} +261 -165
- package/dist/PropertyEditView-BB5xjnhZ.js.map +1 -0
- package/dist/{RolesView-CNWxnR8e.js → RolesView-CULIHWZ9.js} +22 -11
- package/dist/RolesView-CULIHWZ9.js.map +1 -0
- package/dist/{UsersView-YiTIcXkA.js → UsersView-D7_AtJ44.js} +7 -71
- package/dist/UsersView-D7_AtJ44.js.map +1 -0
- package/dist/collection_editor/ui/collection_editor/LayoutModeSwitch.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/properties/VectorPropertyField.d.ts +3 -0
- package/dist/collection_editor_ui.js +5 -5
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionListView.d.ts +18 -2
- package/dist/components/EntityCollectionView/FilterPresetsButton.d.ts +21 -0
- package/dist/components/EntityDetailView.d.ts +31 -0
- package/dist/components/EntityEditView.d.ts +3 -2
- package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +1 -1
- package/dist/components/admin/CreationResultDialog.d.ts +5 -0
- package/dist/components/admin/RolesFilterSelect.d.ts +2 -0
- package/dist/components/admin/UserRolesSelectField.d.ts +2 -0
- package/dist/components/common/default_entity_actions.d.ts +7 -1
- package/dist/components/field_configs.d.ts +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/data_import/utils/data.d.ts +1 -1
- package/dist/data_import/utils/file_headers.d.ts +6 -1
- package/dist/data_import/utils/file_to_json.d.ts +1 -11
- package/dist/data_import/utils/transforms.d.ts +11 -0
- package/dist/editor.js +2 -4
- package/dist/editor.js.map +1 -1
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/VectorFieldBinding.d.ts +11 -0
- package/dist/form/index.d.ts +1 -0
- package/dist/hooks/navigation/useResolvedViews.d.ts +2 -1
- package/dist/{index-CtzpHzMQ.js → index-BAM9KCmM.js} +4 -6
- package/dist/index-BAM9KCmM.js.map +1 -0
- package/dist/{index-DKlrVD1m.js → index-CoSNm3e3.js} +3 -3
- package/dist/index-CoSNm3e3.js.map +1 -0
- package/dist/{index-kHJXfLNI.js → index-D5OQhv-T.js} +3 -3
- package/dist/index-D5OQhv-T.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +352 -148
- package/dist/index.js.map +1 -1
- package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
- package/dist/types/components/EntityFormProps.d.ts +2 -1
- package/dist/types/fields.d.ts +3 -3
- package/dist/util/navigation_utils.d.ts +1 -1
- package/dist/{util-CwLmSpGp.js → util-DtbWD7LF.js} +5312 -2580
- package/dist/util-DtbWD7LF.js.map +1 -0
- package/package.json +45 -39
- package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
- package/src/collection_editor/ui/AddKanbanColumnAction.tsx +12 -2
- package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +1 -2
- package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -2
- package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -2
- package/src/collection_editor/ui/EditorEntityAction.tsx +1 -2
- package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +1 -2
- package/src/collection_editor/ui/NewCollectionButton.tsx +1 -2
- package/src/collection_editor/ui/NewCollectionCard.tsx +4 -6
- package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +10 -2
- package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +18 -2
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +22 -7
- package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +16 -2
- package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +19 -9
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +13 -2
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +24 -2
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +22 -3
- package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +11 -2
- package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +12 -2
- package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +16 -3
- package/src/collection_editor/ui/collection_editor/EnumForm.tsx +17 -2
- package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +18 -2
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +17 -5
- package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +32 -6
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +7 -7
- package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +14 -2
- package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +16 -2
- package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +9 -2
- package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +9 -2
- package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +11 -2
- package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +34 -0
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +15 -7
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +15 -3
- package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +1 -1
- package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -2
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -2
- package/src/collection_editor/validateCollectionJson.ts +9 -9
- package/src/components/AdminModeSyncer.tsx +1 -1
- package/src/components/ArrayContainer.tsx +19 -15
- package/src/components/ClearFilterSortButton.tsx +1 -2
- package/src/components/CollectionEditorDialogs.tsx +1 -1
- package/src/components/DefaultAppBar.tsx +15 -3
- package/src/components/DefaultDrawer.tsx +3 -3
- package/src/components/DrawerNavigationGroup.tsx +1 -2
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +19 -9
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +2 -2
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
- package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/VirtualTableSelect.tsx +0 -1
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +15 -27
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +3 -4
- package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -2
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
- package/src/components/EntityCollectionTable/table_bindings.tsx +51 -45
- package/src/components/EntityCollectionView/Board.tsx +1 -2
- package/src/components/EntityCollectionView/BoardColumn.tsx +9 -2
- package/src/components/EntityCollectionView/BoardColumnTitle.tsx +5 -4
- package/src/components/EntityCollectionView/EntityCard.tsx +2 -2
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +18 -16
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +16 -17
- package/src/components/EntityCollectionView/EntityCollectionListView.tsx +90 -21
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +20 -11
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +6 -7
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +14 -5
- package/src/components/EntityCollectionView/FilterPresetsButton.tsx +292 -0
- package/src/components/EntityCollectionView/FiltersDialog.tsx +1 -2
- package/src/components/EntityCollectionView/SplitListView.tsx +76 -25
- package/src/components/EntityCollectionView/ViewModeToggle.tsx +20 -7
- package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +1 -1
- package/src/components/EntityCollectionView/useBoardDataController.tsx +74 -6
- package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +1 -1
- package/src/components/EntityDetailView.tsx +619 -0
- package/src/components/EntityEditView.tsx +29 -10
- package/src/components/EntityEditViewFormActions.tsx +20 -7
- package/src/components/EntityPreview.tsx +14 -5
- package/src/components/EntitySidePanel.tsx +116 -62
- package/src/components/EntityView.tsx +1 -2
- package/src/components/HomePage/ContentHomePage.tsx +1 -1
- package/src/components/HomePage/FavouritesView.tsx +1 -2
- package/src/components/HomePage/NavigationCard.tsx +1 -2
- package/src/components/HomePage/NavigationCardBinding.tsx +1 -2
- package/src/components/HomePage/NavigationGroup.tsx +1 -2
- package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
- package/src/components/PropertyIdCopyTooltip.tsx +1 -2
- package/src/components/RebaseAuthGate.tsx +2 -2
- package/src/components/RebaseNavigation.tsx +9 -7
- package/src/components/ReferenceTable/EntitySelectionTable.tsx +12 -8
- package/src/components/RelationSelector.tsx +34 -6
- package/src/components/SearchIconsView.tsx +10 -2
- package/src/components/SelectableTable/SelectableTable.tsx +4 -4
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
- package/src/components/SideDialogs.tsx +63 -38
- package/src/components/UserSelector.tsx +30 -6
- package/src/components/admin/CreationResultDialog.tsx +135 -0
- package/src/components/admin/RolesFilterSelect.tsx +45 -0
- package/src/components/admin/RolesView.tsx +53 -14
- package/src/components/admin/UserRolesSelectField.tsx +50 -0
- package/src/components/admin/UsersView.tsx +41 -124
- package/src/components/app/Scaffold.tsx +1 -2
- package/src/components/common/default_entity_actions.tsx +119 -12
- package/src/components/field_configs.tsx +39 -3
- package/src/components/history/EntityHistoryEntry.tsx +1 -2
- package/src/components/history/EntityHistoryView.tsx +1 -2
- package/src/components/index.ts +2 -0
- package/src/data_export/export/BasicExportAction.tsx +35 -38
- package/src/data_export/export/ExportCollectionAction.tsx +39 -40
- package/src/data_import/components/DataNewPropertiesMapping.tsx +15 -2
- package/src/data_import/components/ImportFileUpload.tsx +1 -2
- package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +1 -2
- package/src/data_import/import/ImportCollectionAction.tsx +21 -8
- package/src/data_import/utils/data.ts +23 -5
- package/src/data_import/utils/file_headers.ts +13 -89
- package/src/data_import/utils/file_to_json.ts +43 -68
- package/src/data_import/utils/transforms.ts +47 -0
- package/src/editor/components/SlashCommandMenu.tsx +17 -2
- package/src/editor/components/editor-bubble-item.tsx +1 -1
- package/src/editor/extensions/Image/index.ts +1 -1
- package/src/editor/extensions/Image.ts +1 -1
- package/src/editor/selectors/color-selector.tsx +1 -2
- package/src/editor/selectors/link-selector.tsx +1 -2
- package/src/editor/selectors/node-selector.tsx +16 -2
- package/src/editor/selectors/text-buttons.tsx +1 -2
- package/src/editor/utils/prosemirror-utils.ts +1 -1
- package/src/form/EntityForm.tsx +16 -6
- package/src/form/EntityFormActions.tsx +11 -3
- package/src/form/PropertyFieldBinding.tsx +5 -12
- package/src/form/components/FieldHelperText.tsx +1 -2
- package/src/form/components/LocalChangesMenu.tsx +17 -2
- package/src/form/components/StorageItemPreview.tsx +1 -2
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -2
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +17 -2
- package/src/form/field_bindings/MapFieldBinding.tsx +1 -1
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +10 -3
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -2
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -2
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
- package/src/form/field_bindings/RelationFieldBinding.tsx +150 -147
- package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
- package/src/form/field_bindings/SelectFieldBinding.tsx +1 -2
- package/src/form/field_bindings/TextFieldBinding.tsx +10 -2
- package/src/form/field_bindings/VectorFieldBinding.tsx +202 -0
- package/src/form/index.tsx +1 -0
- package/src/form/validation.ts +54 -2
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +2 -1
- package/src/hooks/navigation/useResolvedViews.tsx +30 -15
- package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
- package/src/index.ts +6 -0
- package/src/preview/PropertyPreview.tsx +1 -1
- package/src/preview/components/ImagePreview.tsx +1 -1
- package/src/preview/components/UrlComponentPreview.tsx +1 -2
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +23 -24
- package/src/routes/RebaseRoute.tsx +64 -35
- package/src/types/components/EntityFormActionsProps.tsx +1 -1
- package/src/types/components/EntityFormProps.tsx +3 -1
- package/src/types/fields.tsx +4 -3
- package/src/util/navigation_utils.ts +4 -3
- package/src/util/previews.ts +1 -1
- package/src/util/property_utils.tsx +22 -6
- package/src/util/resolutions.ts +2 -2
- package/dist/CollectionEditorDialog-MbvXGzEq.js.map +0 -1
- package/dist/CollectionsStudioView-D9X6aiAr.js.map +0 -1
- package/dist/ContentHomePage-CfVB1eUo.js.map +0 -1
- package/dist/ExportCollectionAction-CUwJg4F9.js.map +0 -1
- package/dist/ImportCollectionAction-DGa_SF_8.js.map +0 -1
- package/dist/PropertyEditView-C4nlYmAc.js.map +0 -1
- package/dist/RolesView-CNWxnR8e.js.map +0 -1
- package/dist/UsersView-YiTIcXkA.js.map +0 -1
- package/dist/index-CtzpHzMQ.js.map +0 -1
- package/dist/index-DKlrVD1m.js.map +0 -1
- package/dist/index-kHJXfLNI.js.map +0 -1
- package/dist/util-CwLmSpGp.js.map +0 -1
|
@@ -15,21 +15,8 @@ import { RelationPreview } from "../../preview";
|
|
|
15
15
|
import { RelationSelector } from "../../components/RelationSelector";
|
|
16
16
|
import { MultipleRelationFieldBinding } from "./MultipleRelationFieldBinding";
|
|
17
17
|
|
|
18
|
-
export function RelationFieldBinding({
|
|
19
|
-
propertyKey,
|
|
20
|
-
value,
|
|
21
|
-
size,
|
|
22
|
-
error,
|
|
23
|
-
showError,
|
|
24
|
-
disabled,
|
|
25
|
-
isSubmitting,
|
|
26
|
-
property,
|
|
27
|
-
includeDescription,
|
|
28
|
-
setValue,
|
|
29
|
-
setFieldValue,
|
|
30
|
-
context,
|
|
31
|
-
customProps
|
|
32
|
-
}: FieldProps<RelationProperty>) {
|
|
18
|
+
export function RelationFieldBinding(props: FieldProps<RelationProperty>) {
|
|
19
|
+
const { property, propertyKey, context } = props;
|
|
33
20
|
|
|
34
21
|
if (property.type !== "relation") {
|
|
35
22
|
throw Error("RelationFieldBinding expected a property containing a relation");
|
|
@@ -39,146 +26,162 @@ export function RelationFieldBinding({
|
|
|
39
26
|
if (!collection || !capabilities?.supportsRelations || !("relations" in collection) || !collection.relations) {
|
|
40
27
|
throw Error("RelationFieldBinding expected a collection with relations support");
|
|
41
28
|
}
|
|
42
|
-
const resolvedProperty = resolveRelationProperty(property, collection.relations, propertyKey)
|
|
29
|
+
const resolvedProperty = resolveRelationProperty(property, collection.relations, propertyKey);
|
|
43
30
|
const relation = resolvedProperty.relation;
|
|
44
31
|
|
|
45
32
|
const manyRelation = relation?.cardinality === "many";
|
|
46
|
-
|
|
47
|
-
// Inline selector mode
|
|
48
33
|
const widget = property.ui?.widget ?? "select";
|
|
49
34
|
|
|
50
35
|
if (widget === "select" && relation) {
|
|
51
|
-
|
|
52
|
-
const singleValue = normalizedSingle ?? null;
|
|
53
|
-
const multipleValue = (manyRelation && Array.isArray(value)) ? value : [];
|
|
54
|
-
|
|
55
|
-
const selectorSize: "small" | "medium" | undefined = size === "large" ? "medium" : size;
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<div className="">
|
|
59
|
-
<LabelWithIconAndTooltip
|
|
60
|
-
propertyKey={propertyKey}
|
|
61
|
-
icon={getIconForProperty(property, "small")}
|
|
62
|
-
required={property.validation?.required}
|
|
63
|
-
title={property.name ?? propertyKey}
|
|
64
|
-
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
65
|
-
|
|
66
|
-
<RelationSelector
|
|
67
|
-
relation={relation}
|
|
68
|
-
value={manyRelation ? multipleValue : singleValue}
|
|
69
|
-
onValueChange={(newVal) => {
|
|
70
|
-
if (manyRelation) {
|
|
71
|
-
setValue(Array.isArray(newVal) ? newVal : []);
|
|
72
|
-
} else {
|
|
73
|
-
setValue(!Array.isArray(newVal) ? (newVal ?? null) : null);
|
|
74
|
-
}
|
|
75
|
-
}}
|
|
76
|
-
disabled={disabled || isSubmitting}
|
|
77
|
-
fixedFilter={property.fixedFilter}
|
|
78
|
-
size={selectorSize}
|
|
79
|
-
/>
|
|
80
|
-
|
|
81
|
-
<FieldHelperText includeDescription={includeDescription}
|
|
82
|
-
showError={showError}
|
|
83
|
-
error={error}
|
|
84
|
-
disabled={disabled}
|
|
85
|
-
property={property}/>
|
|
86
|
-
</div>
|
|
87
|
-
);
|
|
36
|
+
return <RelationSelectorBinding {...props} relation={relation} manyRelation={manyRelation} />;
|
|
88
37
|
}
|
|
89
38
|
|
|
90
39
|
if (manyRelation) {
|
|
91
|
-
return <MultipleRelationFieldBinding
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
{
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
{`Edit ${property.name}`.toUpperCase()}
|
|
171
|
-
</EntityPreviewContainer>
|
|
172
|
-
</div>}
|
|
173
|
-
</>}
|
|
174
|
-
|
|
175
|
-
<FieldHelperText includeDescription={includeDescription}
|
|
176
|
-
showError={showError}
|
|
177
|
-
error={error}
|
|
178
|
-
disabled={disabled}
|
|
179
|
-
property={property}/>
|
|
180
|
-
|
|
181
|
-
</>
|
|
182
|
-
);
|
|
40
|
+
return <MultipleRelationFieldBinding {...props} />;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return <SingleRelationFieldBinding {...props} relation={relation} />;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function RelationSelectorBinding({
|
|
47
|
+
propertyKey,
|
|
48
|
+
value,
|
|
49
|
+
size,
|
|
50
|
+
error,
|
|
51
|
+
showError,
|
|
52
|
+
disabled,
|
|
53
|
+
isSubmitting,
|
|
54
|
+
property,
|
|
55
|
+
includeDescription,
|
|
56
|
+
setValue,
|
|
57
|
+
relation,
|
|
58
|
+
manyRelation
|
|
59
|
+
}: FieldProps<RelationProperty> & { relation: any; manyRelation: boolean }) {
|
|
60
|
+
const normalizedSingle = (!manyRelation && value && !Array.isArray(value)) ? normalizeToEntityRelation(value) : null;
|
|
61
|
+
const singleValue = normalizedSingle ?? null;
|
|
62
|
+
const multipleValue = (manyRelation && Array.isArray(value)) ? value : [];
|
|
63
|
+
|
|
64
|
+
const selectorSize: "small" | "medium" | undefined = size === "large" ? "medium" : size;
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div className="">
|
|
68
|
+
<LabelWithIconAndTooltip
|
|
69
|
+
propertyKey={propertyKey}
|
|
70
|
+
icon={getIconForProperty(property, "small")}
|
|
71
|
+
required={property.validation?.required}
|
|
72
|
+
title={property.name ?? propertyKey}
|
|
73
|
+
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
74
|
+
|
|
75
|
+
<RelationSelector
|
|
76
|
+
relation={relation}
|
|
77
|
+
value={manyRelation ? multipleValue : singleValue}
|
|
78
|
+
onValueChange={(newVal) => {
|
|
79
|
+
if (manyRelation) {
|
|
80
|
+
setValue(Array.isArray(newVal) ? newVal : []);
|
|
81
|
+
} else {
|
|
82
|
+
setValue(!Array.isArray(newVal) ? (newVal ?? null) : null);
|
|
83
|
+
}
|
|
84
|
+
}}
|
|
85
|
+
disabled={disabled || isSubmitting}
|
|
86
|
+
fixedFilter={property.fixedFilter}
|
|
87
|
+
size={selectorSize}
|
|
88
|
+
/>
|
|
89
|
+
|
|
90
|
+
<FieldHelperText includeDescription={includeDescription}
|
|
91
|
+
showError={showError}
|
|
92
|
+
error={error}
|
|
93
|
+
disabled={disabled}
|
|
94
|
+
property={property}/>
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function SingleRelationFieldBinding({
|
|
100
|
+
propertyKey,
|
|
101
|
+
value,
|
|
102
|
+
size,
|
|
103
|
+
error,
|
|
104
|
+
showError,
|
|
105
|
+
disabled,
|
|
106
|
+
isSubmitting,
|
|
107
|
+
property,
|
|
108
|
+
includeDescription,
|
|
109
|
+
setValue,
|
|
110
|
+
relation
|
|
111
|
+
}: FieldProps<RelationProperty> & { relation: any }) {
|
|
112
|
+
const normalizedValue = value && !Array.isArray(value) ? normalizeToEntityRelation(value) : null;
|
|
113
|
+
const validValue = !!normalizedValue;
|
|
114
|
+
|
|
115
|
+
const collection = relation?.target();
|
|
116
|
+
|
|
117
|
+
if (!collection) {
|
|
118
|
+
throw Error(`Couldn't find the corresponding collection for the relation: ${propertyKey}`);
|
|
183
119
|
}
|
|
120
|
+
|
|
121
|
+
const onSingleEntitySelected = useCallback((e: Entity<any> | null) => {
|
|
122
|
+
setValue(e ? getRelationFrom(e) : null);
|
|
123
|
+
}, [setValue]);
|
|
124
|
+
|
|
125
|
+
const referenceDialogController = useEntitySelectionDialog({
|
|
126
|
+
multiselect: false,
|
|
127
|
+
path: collection.slug,
|
|
128
|
+
collection,
|
|
129
|
+
onSingleEntitySelected,
|
|
130
|
+
selectedEntityIds: validValue && normalizedValue ? [normalizedValue.id] : undefined,
|
|
131
|
+
fixedFilter: property.fixedFilter
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const onEntryClick = (e: React.SyntheticEvent) => {
|
|
135
|
+
e.preventDefault();
|
|
136
|
+
referenceDialogController.open();
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const usedRelation = Array.isArray(value) ? undefined : normalizedValue ?? undefined;
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<>
|
|
143
|
+
<LabelWithIconAndTooltip
|
|
144
|
+
propertyKey={propertyKey}
|
|
145
|
+
icon={getIconForProperty(property, "small")}
|
|
146
|
+
required={property.validation?.required}
|
|
147
|
+
title={property.name ?? propertyKey}
|
|
148
|
+
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
149
|
+
|
|
150
|
+
{!collection && <ErrorView
|
|
151
|
+
error={"The specified collection does not exist. Check console"}/>}
|
|
152
|
+
|
|
153
|
+
{collection && <>
|
|
154
|
+
|
|
155
|
+
{usedRelation && <RelationPreview
|
|
156
|
+
disabled={!usedRelation}
|
|
157
|
+
previewProperties={property.ui?.previewProperties}
|
|
158
|
+
hover={!disabled}
|
|
159
|
+
size={size}
|
|
160
|
+
onClick={disabled || isSubmitting ? undefined : onEntryClick}
|
|
161
|
+
relation={usedRelation}
|
|
162
|
+
includeEntityLink={property.includeEntityLink}
|
|
163
|
+
includeId={property.includeId}
|
|
164
|
+
/>}
|
|
165
|
+
|
|
166
|
+
{!value && <div className="justify-center text-left">
|
|
167
|
+
<EntityPreviewContainer className={cls("px-6 h-16 text-sm font-medium flex items-center gap-6",
|
|
168
|
+
disabled || isSubmitting
|
|
169
|
+
? "text-surface-accent-500"
|
|
170
|
+
: "cursor-pointer text-surface-accent-700 dark:text-surface-accent-300 hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800")}
|
|
171
|
+
onClick={onEntryClick}
|
|
172
|
+
size={"medium"}>
|
|
173
|
+
<IconForView collectionOrView={collection}
|
|
174
|
+
className={"text-surface-300 dark:text-surface-600"}/>
|
|
175
|
+
{`Edit ${property.name}`.toUpperCase()}
|
|
176
|
+
</EntityPreviewContainer>
|
|
177
|
+
</div>}
|
|
178
|
+
</>}
|
|
179
|
+
|
|
180
|
+
<FieldHelperText includeDescription={includeDescription}
|
|
181
|
+
showError={showError}
|
|
182
|
+
error={error}
|
|
183
|
+
disabled={disabled}
|
|
184
|
+
property={property}/>
|
|
185
|
+
</>
|
|
186
|
+
);
|
|
184
187
|
}
|
|
@@ -6,8 +6,7 @@ import React, { useCallback } from "react";
|
|
|
6
6
|
import { FieldHelperText, LabelWithIcon } from "../components";
|
|
7
7
|
import { EnumValuesChip } from "../../preview";
|
|
8
8
|
import { getIconForProperty } from "../../util/property_utils";
|
|
9
|
-
import { cls, IconButton, Select, SelectItem } from "@rebasepro/ui";
|
|
10
|
-
import { XIcon } from "lucide-react";
|
|
9
|
+
import { cls, IconButton, Select, SelectItem, XIcon } from "@rebasepro/ui";
|
|
11
10
|
import { useClearRestoreValue } from "../useClearRestoreValue";
|
|
12
11
|
import { PropertyIdCopyTooltip } from "../../components/PropertyIdCopyTooltip";
|
|
13
12
|
import { resolveEnumValues } from "@rebasepro/common";
|
|
@@ -2,8 +2,16 @@ import type { FieldProps } from "../../types/fields";
|
|
|
2
2
|
import type { NumberProperty, StringProperty } from "@rebasepro/types";
|
|
3
3
|
import React, { useCallback } from "react";
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
cls,
|
|
7
|
+
Collapse,
|
|
8
|
+
fieldBackgroundHoverMixin,
|
|
9
|
+
fieldBackgroundMixin,
|
|
10
|
+
IconButton,
|
|
11
|
+
TextareaAutosize,
|
|
12
|
+
TextField,
|
|
13
|
+
XIcon
|
|
14
|
+
} from "@rebasepro/ui";
|
|
7
15
|
import { PreviewType } from "@rebasepro/types";
|
|
8
16
|
import { FieldHelperText, LabelWithIcon } from "../components";
|
|
9
17
|
import { PropertyPreview } from "../../preview";
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import type { FieldProps } from "../../types/fields";
|
|
2
|
+
import type { VectorProperty } from "@rebasepro/types";
|
|
3
|
+
import React, { useState, useEffect, useCallback } from "react";
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
CheckIcon,
|
|
7
|
+
EyeIcon,
|
|
8
|
+
EyeOffIcon,
|
|
9
|
+
IconButton,
|
|
10
|
+
PencilIcon,
|
|
11
|
+
TextField,
|
|
12
|
+
Trash2Icon
|
|
13
|
+
} from "@rebasepro/ui";
|
|
14
|
+
import { FieldHelperText, LabelWithIcon } from "../components";
|
|
15
|
+
import { useClearRestoreValue } from "../useClearRestoreValue";
|
|
16
|
+
import { PropertyIdCopyTooltip } from "../../components/PropertyIdCopyTooltip";
|
|
17
|
+
import { getIconForProperty } from "../../util/property_utils";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Custom field binding to render vector fields (e.g. for high-dimensional embeddings).
|
|
21
|
+
* Shows a compact metadata card by default, and lets users expand values or edit them.
|
|
22
|
+
*
|
|
23
|
+
* Automatically parses inputs to number arrays and packages them into the canonical
|
|
24
|
+
* Vector object structure expected by Rebase driver.
|
|
25
|
+
* @group Form fields
|
|
26
|
+
*/
|
|
27
|
+
export function VectorFieldBinding({
|
|
28
|
+
propertyKey,
|
|
29
|
+
value,
|
|
30
|
+
setValue,
|
|
31
|
+
error,
|
|
32
|
+
showError,
|
|
33
|
+
disabled,
|
|
34
|
+
autoFocus,
|
|
35
|
+
property,
|
|
36
|
+
includeDescription,
|
|
37
|
+
size = "large"
|
|
38
|
+
}: FieldProps<VectorProperty>) {
|
|
39
|
+
const isVectorObject = (val: unknown): val is { value: number[] } => {
|
|
40
|
+
return typeof val === "object" && val !== null && "value" in val;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Extract array value from the custom { __type: "Vector", value: number[] } wrapper
|
|
44
|
+
const arrayValue = isVectorObject(value)
|
|
45
|
+
? value.value
|
|
46
|
+
: (Array.isArray(value) ? value : []);
|
|
47
|
+
|
|
48
|
+
const [textValue, setTextValue] = useState(() => arrayValue.join(", "));
|
|
49
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
50
|
+
const [showValues, setShowValues] = useState(false);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
setTextValue(arrayValue.join(", "));
|
|
54
|
+
}, [JSON.stringify(arrayValue)]);
|
|
55
|
+
|
|
56
|
+
useClearRestoreValue({
|
|
57
|
+
property,
|
|
58
|
+
value,
|
|
59
|
+
setValue
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const handleClearClick = useCallback((e: React.MouseEvent) => {
|
|
63
|
+
e.stopPropagation();
|
|
64
|
+
e.preventDefault();
|
|
65
|
+
setValue(null);
|
|
66
|
+
setTextValue("");
|
|
67
|
+
}, [setValue]);
|
|
68
|
+
|
|
69
|
+
const onChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
|
70
|
+
const raw = event.target.value;
|
|
71
|
+
setTextValue(raw);
|
|
72
|
+
|
|
73
|
+
// Parse comma-separated string to number array
|
|
74
|
+
const numbers = raw
|
|
75
|
+
.split(",")
|
|
76
|
+
.map(str => str.trim())
|
|
77
|
+
.filter(str => str !== "")
|
|
78
|
+
.map(Number);
|
|
79
|
+
|
|
80
|
+
setValue({
|
|
81
|
+
__type: "Vector",
|
|
82
|
+
value: numbers
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const label = (
|
|
87
|
+
<LabelWithIcon
|
|
88
|
+
icon={getIconForProperty(property, "small")}
|
|
89
|
+
required={property.validation?.required}
|
|
90
|
+
title={property.name ?? propertyKey}
|
|
91
|
+
/>
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const isPopulated = arrayValue.length > 0;
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<div className="flex flex-col gap-2 w-full mt-2">
|
|
98
|
+
{/* Field Label */}
|
|
99
|
+
<div className="flex items-center justify-between mb-1">
|
|
100
|
+
{label}
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<PropertyIdCopyTooltip propertyKey={propertyKey}>
|
|
104
|
+
<div className="w-full">
|
|
105
|
+
{!isEditing ? (
|
|
106
|
+
/* Compact Preview Card */
|
|
107
|
+
<div className="flex flex-col gap-3 p-4 rounded-xl border border-surface-200 dark:border-surface-700 bg-surface-50/50 dark:bg-surface-800/20 backdrop-blur-sm transition-all duration-200 hover:border-surface-300 dark:hover:border-surface-600">
|
|
108
|
+
<div className="flex items-center justify-between flex-wrap gap-2">
|
|
109
|
+
<div className="flex items-center gap-2.5">
|
|
110
|
+
{/* Status Dot */}
|
|
111
|
+
<div className={`w-2.5 h-2.5 rounded-full ${isPopulated ? 'bg-emerald-500 animate-pulse' : 'bg-surface-300 dark:bg-surface-600'}`} />
|
|
112
|
+
<span className="text-sm font-semibold text-text-primary dark:text-text-primary-dark">
|
|
113
|
+
{isPopulated ? `${arrayValue.length} Dimensions` : "Empty Vector"}
|
|
114
|
+
</span>
|
|
115
|
+
{isPopulated && (
|
|
116
|
+
<span className="text-xs text-text-secondary dark:text-text-secondary-dark px-2 py-0.5 rounded-full bg-surface-100 dark:bg-surface-800 font-medium">
|
|
117
|
+
Embedding
|
|
118
|
+
</span>
|
|
119
|
+
)}
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div className="flex items-center gap-2">
|
|
123
|
+
{isPopulated && (
|
|
124
|
+
<Button
|
|
125
|
+
variant="text"
|
|
126
|
+
size="small"
|
|
127
|
+
onClick={() => setShowValues(!showValues)}
|
|
128
|
+
startIcon={showValues ? <EyeOffIcon size={14} /> : <EyeIcon size={14} />}
|
|
129
|
+
>
|
|
130
|
+
{showValues ? "Hide values" : "Show values"}
|
|
131
|
+
</Button>
|
|
132
|
+
)}
|
|
133
|
+
{!disabled && (
|
|
134
|
+
<Button
|
|
135
|
+
variant="outlined"
|
|
136
|
+
size="small"
|
|
137
|
+
onClick={() => setIsEditing(true)}
|
|
138
|
+
startIcon={<PencilIcon size={14} />}
|
|
139
|
+
>
|
|
140
|
+
{isPopulated ? "Edit values" : "Add values"}
|
|
141
|
+
</Button>
|
|
142
|
+
)}
|
|
143
|
+
{isPopulated && !disabled && (
|
|
144
|
+
<IconButton size="small" onClick={handleClearClick} className="text-text-secondary hover:text-red-500">
|
|
145
|
+
<Trash2Icon size={14} />
|
|
146
|
+
</IconButton>
|
|
147
|
+
)}
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
{/* Collapsible scrollable numbers list */}
|
|
152
|
+
{showValues && isPopulated && (
|
|
153
|
+
<div className="mt-1 p-3 rounded-lg bg-surface-100/50 dark:bg-surface-900/40 border border-surface-200/50 dark:border-surface-800/50 max-h-36 overflow-y-auto font-mono text-[11px] leading-relaxed text-text-secondary dark:text-text-secondary-dark break-all selection:bg-primary-100 dark:selection:bg-primary-900/40">
|
|
154
|
+
{arrayValue.join(", ")}
|
|
155
|
+
</div>
|
|
156
|
+
)}
|
|
157
|
+
</div>
|
|
158
|
+
) : (
|
|
159
|
+
/* Editing View: Text Input */
|
|
160
|
+
<div className="flex flex-col gap-2 p-4 rounded-xl border border-primary-500/30 dark:border-primary-400/20 bg-surface-50/20 dark:bg-surface-800/10">
|
|
161
|
+
<TextField
|
|
162
|
+
size={size}
|
|
163
|
+
value={textValue}
|
|
164
|
+
onChange={onChange}
|
|
165
|
+
autoFocus={true}
|
|
166
|
+
placeholder={`e.g., 0.15, -0.42, 0.88 (Requires ${property.dimensions} dimensions)`}
|
|
167
|
+
disabled={disabled}
|
|
168
|
+
error={showError ? !!error : undefined}
|
|
169
|
+
inputClassName={error ? "text-red-500 dark:text-red-600 font-mono text-xs" : "font-mono text-xs"}
|
|
170
|
+
/>
|
|
171
|
+
<div className="flex justify-end gap-2 mt-2">
|
|
172
|
+
<Button
|
|
173
|
+
variant="outlined"
|
|
174
|
+
size="small"
|
|
175
|
+
onClick={() => setIsEditing(false)}
|
|
176
|
+
>
|
|
177
|
+
Cancel
|
|
178
|
+
</Button>
|
|
179
|
+
<Button
|
|
180
|
+
variant="filled"
|
|
181
|
+
size="small"
|
|
182
|
+
onClick={() => setIsEditing(false)}
|
|
183
|
+
startIcon={<CheckIcon size={14} />}
|
|
184
|
+
>
|
|
185
|
+
Done
|
|
186
|
+
</Button>
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
)}
|
|
190
|
+
</div>
|
|
191
|
+
</PropertyIdCopyTooltip>
|
|
192
|
+
|
|
193
|
+
<FieldHelperText
|
|
194
|
+
includeDescription={includeDescription}
|
|
195
|
+
showError={showError}
|
|
196
|
+
error={error}
|
|
197
|
+
disabled={disabled}
|
|
198
|
+
property={property}
|
|
199
|
+
/>
|
|
200
|
+
</div>
|
|
201
|
+
);
|
|
202
|
+
}
|
package/src/form/index.tsx
CHANGED
|
@@ -20,6 +20,7 @@ export { BlockFieldBinding } from "./field_bindings/BlockFieldBinding";
|
|
|
20
20
|
export { ReadOnlyFieldBinding } from "./field_bindings/ReadOnlyFieldBinding";
|
|
21
21
|
export { MarkdownEditorFieldBinding } from "./field_bindings/MarkdownEditorFieldBinding";
|
|
22
22
|
export { ArrayCustomShapedFieldBinding } from "./field_bindings/ArrayCustomShapedFieldBinding";
|
|
23
|
+
export { VectorFieldBinding } from "./field_bindings/VectorFieldBinding";
|
|
23
24
|
|
|
24
25
|
export * from "./components";
|
|
25
26
|
|
package/src/form/validation.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Properties } from "@rebasepro/types";
|
|
2
|
-
import type { ArrayProperty, MapProperty, NumberProperty, Property, BooleanProperty, DateProperty, GeopointProperty, ReferenceProperty, RelationProperty, StringProperty } from "@rebasepro/types";
|
|
2
|
+
import type { ArrayProperty, MapProperty, NumberProperty, Property, BooleanProperty, DateProperty, GeopointProperty, ReferenceProperty, RelationProperty, StringProperty, VectorProperty, BinaryProperty } from "@rebasepro/types";
|
|
3
3
|
;
|
|
4
4
|
import { z, ZodTypeAny } from "zod";
|
|
5
5
|
import { enumToObjectEntries, isPropertyBuilder } from "@rebasepro/common";
|
|
@@ -74,11 +74,15 @@ export function mapPropertyToZod(propertyContext: PropertyContext<Property>): Zo
|
|
|
74
74
|
return getZodReferenceSchema(propertyContext as PropertyContext<ReferenceProperty>);
|
|
75
75
|
} else if (property.type === "relation") {
|
|
76
76
|
return getZodRelationSchema(propertyContext as PropertyContext<RelationProperty>);
|
|
77
|
+
} else if (property.type === "vector") {
|
|
78
|
+
return getZodVectorSchema(propertyContext as PropertyContext<VectorProperty>);
|
|
79
|
+
} else if (property.type === "binary") {
|
|
80
|
+
return getZodBinarySchema(propertyContext as PropertyContext<BinaryProperty>);
|
|
77
81
|
}
|
|
78
82
|
|
|
79
83
|
// Log the error but don't crash the form
|
|
80
84
|
console.error("Unsupported data type in zod mapping", property);
|
|
81
|
-
const dataType = "dataType" in (property as
|
|
85
|
+
const dataType = "dataType" in (property as Record<string, unknown>) ? String((property as Record<string, unknown>).dataType) : "unknown";
|
|
82
86
|
return z.any().refine(
|
|
83
87
|
() => false,
|
|
84
88
|
{ message: `Unsupported data type: ${dataType}` }
|
|
@@ -517,3 +521,51 @@ function getZodArraySchema({
|
|
|
517
521
|
}
|
|
518
522
|
return arraySchema;
|
|
519
523
|
}
|
|
524
|
+
|
|
525
|
+
function getZodVectorSchema({
|
|
526
|
+
property
|
|
527
|
+
}: PropertyContext<VectorProperty>): ZodTypeAny {
|
|
528
|
+
let schema: ZodTypeAny = z.preprocess(
|
|
529
|
+
(val: any) => {
|
|
530
|
+
if (val && typeof val === "object" && "__type" in val && val.__type === "Vector") {
|
|
531
|
+
return val.value;
|
|
532
|
+
}
|
|
533
|
+
if (val && typeof val === "object" && "value" in val && Array.isArray(val.value)) {
|
|
534
|
+
return val.value;
|
|
535
|
+
}
|
|
536
|
+
return val;
|
|
537
|
+
},
|
|
538
|
+
z.array(z.number()).nullable().optional()
|
|
539
|
+
);
|
|
540
|
+
|
|
541
|
+
if (property.dimensions) {
|
|
542
|
+
schema = schema.refine(
|
|
543
|
+
(val: any) => val === null || val === undefined || val.length === property.dimensions,
|
|
544
|
+
{ message: `${property.name ?? "Vector"} must have exactly ${property.dimensions} dimensions` }
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (property.validation?.required) {
|
|
549
|
+
schema = schema.refine(
|
|
550
|
+
(val: any) => val !== null && val !== undefined && val.length > 0,
|
|
551
|
+
{ message: property.validation?.requiredMessage ?? "Required" }
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return schema;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
function getZodBinarySchema({
|
|
559
|
+
property
|
|
560
|
+
}: PropertyContext<BinaryProperty>): ZodTypeAny {
|
|
561
|
+
let schema: ZodTypeAny = z.string().nullable().optional();
|
|
562
|
+
const validation = property.validation;
|
|
563
|
+
|
|
564
|
+
if (validation?.required) {
|
|
565
|
+
schema = schema.nullable().optional().refine(
|
|
566
|
+
(value: any) => value !== undefined && value !== null && value !== "",
|
|
567
|
+
{ message: validation.requiredMessage ? validation.requiredMessage : "Required" }
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
return schema;
|
|
571
|
+
}
|
|
@@ -89,7 +89,8 @@ export function useBuildNavigationStateController<EC extends EntityCollection, U
|
|
|
89
89
|
plugins,
|
|
90
90
|
adminMode,
|
|
91
91
|
effectiveRoleController,
|
|
92
|
-
userManagement
|
|
92
|
+
userManagement,
|
|
93
|
+
collections
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
// Step 3: Compute top-level navigation (pure derived state)
|