@rebasepro/admin 0.2.3 → 0.3.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/dist/{CollectionEditorDialog-CmGXXSY9.js → CollectionEditorDialog-D0VqpLPO.js} +70 -77
- package/dist/CollectionEditorDialog-D0VqpLPO.js.map +1 -0
- package/dist/{CollectionsStudioView-DcLHT5bU.js → CollectionsStudioView-Bc3Rxxc2.js} +5 -4
- package/dist/{CollectionsStudioView-DcLHT5bU.js.map → CollectionsStudioView-Bc3Rxxc2.js.map} +1 -1
- package/dist/{ExportCollectionAction-BfN34eWX.js → ExportCollectionAction-Ckc-09BQ.js} +4 -3
- package/dist/ExportCollectionAction-Ckc-09BQ.js.map +1 -0
- package/dist/{ImportCollectionAction-SZrInjhx.js → ImportCollectionAction-BqjIrC3Z.js} +3 -2
- package/dist/{ImportCollectionAction-SZrInjhx.js.map → ImportCollectionAction-BqjIrC3Z.js.map} +1 -1
- package/dist/{PropertyEditView-Cvryrb3B.js → PropertyEditView-CvRSV-A2.js} +128 -121
- package/dist/PropertyEditView-CvRSV-A2.js.map +1 -0
- package/dist/collection_editor/ConfigControllerProvider.d.ts +0 -5
- package/dist/collection_editor/index.d.ts +0 -1
- package/dist/collection_editor/types/collection_editor_controller.d.ts +0 -2
- package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +3 -3
- package/dist/collection_editor_ui.js +3 -3
- package/dist/components/ArrayContainer.d.ts +2 -2
- package/dist/components/DefaultAppBar.d.ts +18 -1
- package/dist/components/DefaultDrawer.d.ts +51 -3
- package/dist/components/EntityCollectionTable/fields/TableStorageUpload.d.ts +2 -2
- package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
- package/dist/components/EntityCollectionTable/table_bindings.d.ts +4 -3
- package/dist/components/EntityCollectionView/hooks/useKanbanDragAndDrop.d.ts +4 -3
- package/dist/components/EntityEditView.d.ts +2 -1
- package/dist/components/HomePage/HomePageDnD.d.ts +3 -3
- package/dist/components/PropertyCollectionView.d.ts +1 -1
- package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
- package/dist/components/SelectableTable/SelectionStore.d.ts +4 -1
- package/dist/components/SelectableTable/filters/BooleanFilterField.d.ts +2 -2
- package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -2
- package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -2
- package/dist/components/SelectableTable/filters/StringNumberFilterField.d.ts +2 -2
- package/dist/components/admin/RolesView.d.ts +3 -3
- package/dist/components/admin/UsersView.d.ts +3 -3
- package/dist/components/app/Drawer.d.ts +8 -1
- package/dist/data_export/export/export.d.ts +3 -3
- package/dist/editor/components/editor-bubble.d.ts +5 -1
- package/dist/editor/components/image-bubble.d.ts +5 -1
- package/dist/editor/components/index.d.ts +3 -3
- package/dist/editor/components/table-bubble.d.ts +5 -1
- package/dist/editor/nodeViews/ReactNodeView.d.ts +4 -1
- package/dist/editor/useProseMirror.d.ts +2 -2
- package/dist/editor/utils/remove_classes.d.ts +1 -1
- package/dist/editor.js +15 -14
- package/dist/editor.js.map +1 -1
- package/dist/form/EntityForm.d.ts +2 -2
- package/dist/form/components/StorageUploadProgress.d.ts +2 -2
- package/dist/form/field_bindings/MultiSelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +1 -1
- package/dist/form/validation.d.ts +3 -3
- package/dist/hooks/navigation/useResolvedCollections.d.ts +6 -0
- package/dist/hooks/navigation/useResolvedViews.d.ts +3 -4
- package/dist/{index-PLIQXpTt.js → index-BCcLwgfe.js} +3 -2
- package/dist/{index-PLIQXpTt.js.map → index-BCcLwgfe.js.map} +1 -1
- package/dist/{index-DjduZG1T.js → index-DY2k5TtG.js} +3 -3
- package/dist/index-DY2k5TtG.js.map +1 -0
- package/dist/{index-MKPc70-v.js → index-UQOMHwt1.js} +3 -3
- package/dist/index-UQOMHwt1.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2813 -372
- package/dist/index.js.map +1 -1
- package/dist/{markdown-z2Ir7Cgo.js → markdown-DD2JDU1X.js} +2 -2
- package/dist/markdown-DD2JDU1X.js.map +1 -0
- package/dist/preview/components/UrlComponentPreview.d.ts +1 -0
- package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
- package/dist/types/components/EntityFormProps.d.ts +2 -2
- package/dist/types/fields.d.ts +1 -1
- package/dist/{util-DbWax_sV.js → util-ZM9gQuCv.js} +2031 -2078
- package/dist/util-ZM9gQuCv.js.map +1 -0
- package/package.json +8 -8
- package/src/collection_editor/ConfigControllerProvider.tsx +3 -13
- package/src/collection_editor/index.ts +1 -3
- package/src/collection_editor/types/collection_editor_controller.tsx +0 -3
- package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -6
- package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -6
- package/src/collection_editor/ui/EditorEntityAction.tsx +1 -6
- package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +7 -14
- package/src/collection_editor/ui/NewCollectionCard.tsx +1 -5
- package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +3 -8
- package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +8 -12
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +21 -21
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +4 -4
- package/src/collection_editor/ui/collection_editor/EnumForm.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/properties/CommonPropertyFields.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/properties/DateTimePropertyField.tsx +8 -8
- package/src/collection_editor/ui/collection_editor/properties/EnumPropertyField.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/properties/NumberPropertyField.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/RepeatPropertyField.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +8 -8
- package/src/collection_editor/ui/collection_editor/properties/StringPropertyField.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/properties/UrlPropertyField.tsx +3 -2
- package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +4 -7
- package/src/collection_editor/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +4 -4
- package/src/components/ArrayContainer.tsx +3 -3
- package/src/components/DefaultAppBar.tsx +52 -31
- package/src/components/DefaultDrawer.tsx +279 -66
- package/src/components/DrawerNavigationItem.tsx +1 -1
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +6 -5
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +9 -7
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +5 -5
- package/src/components/EntityCollectionTable/fields/VirtualTableNumberInput.tsx +12 -9
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +2 -2
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +1 -1
- package/src/components/EntityCollectionTable/table_bindings.tsx +5 -4
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +6 -4
- package/src/components/EntityCollectionView/hooks/useCollectionInlineEditor.ts +1 -1
- package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +7 -6
- package/src/components/EntityDetailView.tsx +46 -24
- package/src/components/EntityEditView.tsx +51 -28
- package/src/components/EntityEditViewFormActions.tsx +4 -4
- package/src/components/EntityPreview.tsx +9 -4
- package/src/components/HomePage/HomePageDnD.tsx +3 -2
- package/src/components/PropertyCollectionView.tsx +1 -1
- package/src/components/PropertyIdCopyTooltip.tsx +1 -1
- package/src/components/RebaseLayout.tsx +5 -1
- package/src/components/RebaseNavigation.tsx +2 -2
- package/src/components/RebaseRouteDefs.tsx +4 -7
- package/src/components/RebaseShell.tsx +16 -13
- package/src/components/SearchIconsView.tsx +1 -8
- package/src/components/SelectableTable/SelectableTable.tsx +8 -11
- package/src/components/SelectableTable/SelectionStore.ts +1 -1
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +3 -3
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +3 -3
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +5 -5
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +3 -3
- package/src/components/SideEntityProvider.tsx +2 -1
- package/src/components/admin/RolesView.tsx +7 -2
- package/src/components/admin/UsersView.tsx +12 -6
- package/src/components/app/Drawer.tsx +9 -1
- package/src/components/app/Scaffold.tsx +5 -1
- package/src/data_export/export/export.ts +17 -17
- package/src/data_import/components/DataNewPropertiesMapping.tsx +1 -1
- package/src/editor/components/editor-bubble.tsx +32 -9
- package/src/editor/components/image-bubble.tsx +27 -11
- package/src/editor/components/index.ts +3 -3
- package/src/editor/components/table-bubble.tsx +79 -17
- package/src/editor/extensions/HighlightDecorationExtension.ts +3 -2
- package/src/editor/nodeViews/ReactNodeView.tsx +1 -1
- package/src/editor/nodeViews/TaskItemComponent.tsx +9 -8
- package/src/editor/schema.ts +135 -59
- package/src/editor/selectors/link-selector.tsx +8 -5
- package/src/editor/useProseMirror.ts +2 -2
- package/src/editor/utils/remove_classes.ts +6 -5
- package/src/form/EntityForm.tsx +15 -15
- package/src/form/EntityFormActions.tsx +2 -2
- package/src/form/PropertyFieldBinding.tsx +64 -64
- package/src/form/components/FieldHelperText.tsx +4 -4
- package/src/form/components/StorageUploadProgress.tsx +2 -2
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -1
- package/src/form/field_bindings/BlockFieldBinding.tsx +54 -53
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +290 -289
- package/src/form/field_bindings/MapFieldBinding.tsx +2 -2
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +2 -2
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +8 -6
- package/src/form/field_bindings/RelationFieldBinding.tsx +4 -4
- package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
- package/src/form/field_bindings/SelectFieldBinding.tsx +1 -1
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +84 -84
- package/src/form/field_bindings/SwitchFieldBinding.tsx +16 -16
- package/src/form/field_bindings/TextFieldBinding.tsx +77 -73
- package/src/form/field_bindings/UserSelectFieldBinding.tsx +17 -17
- package/src/form/validation.ts +43 -43
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +3 -5
- package/src/hooks/navigation/useResolvedCollections.ts +27 -7
- package/src/hooks/navigation/useResolvedViews.tsx +24 -44
- package/src/index.ts +2 -0
- package/src/preview/PropertyPreview.tsx +2 -2
- package/src/preview/components/ImagePreview.tsx +2 -1
- package/src/preview/components/UrlComponentPreview.tsx +11 -2
- package/src/preview/components/UserPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -4
- package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +3 -3
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +3 -3
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +3 -2
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +6 -8
- package/src/preview/property_previews/ArrayPropertyEnumPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +3 -3
- package/src/preview/property_previews/MapPropertyPreview.tsx +4 -3
- package/src/preview/property_previews/NumberPropertyPreview.tsx +5 -3
- package/src/preview/property_previews/StringPropertyPreview.tsx +10 -8
- package/src/types/components/EntityFormActionsProps.tsx +1 -1
- package/src/types/components/EntityFormProps.tsx +2 -2
- package/src/types/fields.tsx +2 -2
- package/dist/CollectionEditorDialog-CmGXXSY9.js.map +0 -1
- package/dist/ContentHomePage-C7vFqKSe.js +0 -1784
- package/dist/ContentHomePage-C7vFqKSe.js.map +0 -1
- package/dist/ExportCollectionAction-BfN34eWX.js.map +0 -1
- package/dist/PropertyEditView-Cvryrb3B.js.map +0 -1
- package/dist/RoleChip-QtUFXeTp.js +0 -67
- package/dist/RoleChip-QtUFXeTp.js.map +0 -1
- package/dist/RolesView-BCb7qwWs.js +0 -437
- package/dist/RolesView-BCb7qwWs.js.map +0 -1
- package/dist/UsersView-Cex24r8H.js +0 -408
- package/dist/UsersView-Cex24r8H.js.map +0 -1
- package/dist/collection_editor/types/config_permissions.d.ts +0 -19
- package/dist/index-DjduZG1T.js.map +0 -1
- package/dist/index-MKPc70-v.js.map +0 -1
- package/dist/markdown-z2Ir7Cgo.js.map +0 -1
- package/dist/util-DbWax_sV.js.map +0 -1
- package/src/collection_editor/types/config_permissions.ts +0 -20
|
@@ -19,18 +19,18 @@ type UserSelectProps = FieldProps<StringProperty>;
|
|
|
19
19
|
* @group Form fields
|
|
20
20
|
*/
|
|
21
21
|
export function UserSelectFieldBinding({
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}: UserSelectProps) {
|
|
22
|
+
propertyKey,
|
|
23
|
+
value,
|
|
24
|
+
setValue,
|
|
25
|
+
error,
|
|
26
|
+
showError,
|
|
27
|
+
disabled,
|
|
28
|
+
autoFocus,
|
|
29
|
+
touched,
|
|
30
|
+
property,
|
|
31
|
+
includeDescription,
|
|
32
|
+
size = "large"
|
|
33
|
+
}: UserSelectProps) {
|
|
34
34
|
|
|
35
35
|
const selectorSize: "small" | "medium" | undefined = size === "large" ? "medium" : size;
|
|
36
36
|
|
|
@@ -46,7 +46,7 @@ export function UserSelectFieldBinding({
|
|
|
46
46
|
</PropertyIdCopyTooltip>
|
|
47
47
|
|
|
48
48
|
<UserSelector
|
|
49
|
-
value={value
|
|
49
|
+
value={value as string | null | undefined}
|
|
50
50
|
onValueChange={(userId) => {
|
|
51
51
|
setValue(userId);
|
|
52
52
|
}}
|
|
@@ -56,10 +56,10 @@ export function UserSelectFieldBinding({
|
|
|
56
56
|
/>
|
|
57
57
|
|
|
58
58
|
<FieldHelperText includeDescription={includeDescription}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
showError={showError}
|
|
60
|
+
error={error}
|
|
61
|
+
disabled={disabled}
|
|
62
|
+
property={property}/>
|
|
63
63
|
|
|
64
64
|
</>
|
|
65
65
|
);
|
package/src/form/validation.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { getValueInPath, hydrateRegExp } from "@rebasepro/utils";
|
|
|
7
7
|
|
|
8
8
|
export type CustomFieldValidator = (props: {
|
|
9
9
|
name: string,
|
|
10
|
-
value:
|
|
10
|
+
value: unknown,
|
|
11
11
|
property: Property,
|
|
12
12
|
entityId?: string | number,
|
|
13
13
|
parentProperty?: MapProperty | ArrayProperty,
|
|
@@ -18,13 +18,13 @@ interface PropertyContext<P extends Property> {
|
|
|
18
18
|
parentProperty?: MapProperty | ArrayProperty,
|
|
19
19
|
entityId?: string | number,
|
|
20
20
|
customFieldValidator?: CustomFieldValidator,
|
|
21
|
-
name?:
|
|
21
|
+
name?: string
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export function getEntitySchema<M extends Record<string, unknown>>(
|
|
25
25
|
entityId: string | number | undefined,
|
|
26
26
|
properties: Properties,
|
|
27
|
-
customFieldValidator?: CustomFieldValidator): z.ZodObject<
|
|
27
|
+
customFieldValidator?: CustomFieldValidator): z.ZodObject<Record<string, ZodTypeAny>> {
|
|
28
28
|
const shape: Record<string, ZodTypeAny> = {};
|
|
29
29
|
Object.entries(properties as Record<string, Property>)
|
|
30
30
|
.forEach(([name, property]) => {
|
|
@@ -153,14 +153,14 @@ function getZodStringSchema({
|
|
|
153
153
|
const allowedValues = (isRequired ? entries : [...entries, null])
|
|
154
154
|
.map((enumValueConfig) => enumValueConfig?.id ?? null);
|
|
155
155
|
schema = schema.refine(
|
|
156
|
-
(value:
|
|
156
|
+
(value: unknown) => allowedValues.includes(value as string | null),
|
|
157
157
|
{ message: `Must be one of: ${allowedValues.filter(Boolean).join(", ")}` }
|
|
158
158
|
);
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
if (isRequired && !property.enum) {
|
|
162
162
|
schema = schema.refine(
|
|
163
|
-
(value:
|
|
163
|
+
(value: unknown) => value !== undefined && value !== null && value !== "",
|
|
164
164
|
{ message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
|
|
165
165
|
);
|
|
166
166
|
}
|
|
@@ -168,36 +168,36 @@ function getZodStringSchema({
|
|
|
168
168
|
if (validation) {
|
|
169
169
|
|
|
170
170
|
if (validation.min || validation.min === 0) schema = schema.refine(
|
|
171
|
-
(value:
|
|
171
|
+
(value: unknown) => value == null || (typeof value === "string" && value.length >= validation.min!),
|
|
172
172
|
{ message: `${property.name} must be min ${validation.min} characters long` }
|
|
173
173
|
);
|
|
174
174
|
if (validation.max || validation.max === 0) schema = schema.refine(
|
|
175
|
-
(value:
|
|
175
|
+
(value: unknown) => value == null || (typeof value === "string" && value.length <= validation.max!),
|
|
176
176
|
{ message: `${property.name} must be max ${validation.max} characters long` }
|
|
177
177
|
);
|
|
178
178
|
if (validation.matches) {
|
|
179
179
|
const regExp = typeof validation.matches === "string" ? hydrateRegExp(validation.matches) : validation.matches;
|
|
180
180
|
if (regExp) {
|
|
181
181
|
schema = schema.refine(
|
|
182
|
-
(value:
|
|
182
|
+
(value: unknown) => value == null || (typeof value === "string" && regExp.test(value)),
|
|
183
183
|
{ message: validation.matchesMessage ?? "Invalid format" }
|
|
184
184
|
);
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
|
-
if (validation.trim) schema = z.preprocess((v:
|
|
188
|
-
if (validation.lowercase) schema = z.preprocess((v:
|
|
189
|
-
if (validation.uppercase) schema = z.preprocess((v:
|
|
187
|
+
if (validation.trim) schema = z.preprocess((v: unknown) => typeof v === "string" ? v.trim() : v, schema);
|
|
188
|
+
if (validation.lowercase) schema = z.preprocess((v: unknown) => typeof v === "string" ? v.toLowerCase() : v, schema);
|
|
189
|
+
if (validation.uppercase) schema = z.preprocess((v: unknown) => typeof v === "string" ? v.toUpperCase() : v, schema);
|
|
190
190
|
if (property.email) schema = schema.refine(
|
|
191
|
-
(value:
|
|
191
|
+
(value: unknown) => value == null || (typeof value === "string" && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)),
|
|
192
192
|
{ message: `${property.name} must be an email` }
|
|
193
193
|
);
|
|
194
194
|
if (property.ui?.url) {
|
|
195
195
|
if (!property.storage || property.storage?.storeUrl) {
|
|
196
196
|
schema = schema.refine(
|
|
197
|
-
(value:
|
|
197
|
+
(value: unknown) => {
|
|
198
198
|
if (value == null) return true;
|
|
199
199
|
try {
|
|
200
|
-
new URL(value);
|
|
200
|
+
new URL(value as string);
|
|
201
201
|
return true;
|
|
202
202
|
} catch {
|
|
203
203
|
return false;
|
|
@@ -236,7 +236,7 @@ function getZodNumberSchema({
|
|
|
236
236
|
|
|
237
237
|
if (isRequired) {
|
|
238
238
|
schema = schema.refine(
|
|
239
|
-
(value:
|
|
239
|
+
(value: unknown) => value !== undefined && value !== null,
|
|
240
240
|
{ message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
|
|
241
241
|
);
|
|
242
242
|
}
|
|
@@ -244,31 +244,31 @@ function getZodNumberSchema({
|
|
|
244
244
|
if (validation) {
|
|
245
245
|
|
|
246
246
|
if (validation.min || validation.min === 0) schema = schema.refine(
|
|
247
|
-
(value:
|
|
247
|
+
(value: unknown) => value == null || (typeof value === "number" && value >= validation.min!),
|
|
248
248
|
{ message: `${property.name} must be higher or equal to ${validation.min}` }
|
|
249
249
|
);
|
|
250
250
|
if (validation.max || validation.max === 0) schema = schema.refine(
|
|
251
|
-
(value:
|
|
251
|
+
(value: unknown) => value == null || (typeof value === "number" && value <= validation.max!),
|
|
252
252
|
{ message: `${property.name} must be lower or equal to ${validation.max}` }
|
|
253
253
|
);
|
|
254
254
|
if (validation.lessThan || validation.lessThan === 0) schema = schema.refine(
|
|
255
|
-
(value:
|
|
255
|
+
(value: unknown) => value == null || (typeof value === "number" && value < validation.lessThan!),
|
|
256
256
|
{ message: `${property.name} must be higher than ${validation.lessThan}` }
|
|
257
257
|
);
|
|
258
258
|
if (validation.moreThan || validation.moreThan === 0) schema = schema.refine(
|
|
259
|
-
(value:
|
|
259
|
+
(value: unknown) => value == null || (typeof value === "number" && value > validation.moreThan!),
|
|
260
260
|
{ message: `${property.name} must be lower than ${validation.moreThan}` }
|
|
261
261
|
);
|
|
262
262
|
if (validation.positive) schema = schema.refine(
|
|
263
|
-
(value:
|
|
263
|
+
(value: unknown) => value == null || (typeof value === "number" && value > 0),
|
|
264
264
|
{ message: `${property.name} must be positive` }
|
|
265
265
|
);
|
|
266
266
|
if (validation.negative) schema = schema.refine(
|
|
267
|
-
(value:
|
|
267
|
+
(value: unknown) => value == null || (typeof value === "number" && value < 0),
|
|
268
268
|
{ message: `${property.name} must be negative` }
|
|
269
269
|
);
|
|
270
270
|
if (validation.integer) schema = schema.refine(
|
|
271
|
-
(value:
|
|
271
|
+
(value: unknown) => value == null || (typeof value === "number" && Number.isInteger(value)),
|
|
272
272
|
{ message: `${property.name} must be an integer` }
|
|
273
273
|
);
|
|
274
274
|
}
|
|
@@ -288,7 +288,7 @@ function getZodGeoPointSchema({
|
|
|
288
288
|
|
|
289
289
|
if (validation?.required) {
|
|
290
290
|
schema = schema.refine(
|
|
291
|
-
(value:
|
|
291
|
+
(value: unknown) => value !== undefined && value !== null,
|
|
292
292
|
{ message: validation.requiredMessage ? validation.requiredMessage : "Required" }
|
|
293
293
|
);
|
|
294
294
|
}
|
|
@@ -315,17 +315,17 @@ function getZodDateSchema({
|
|
|
315
315
|
if (validation) {
|
|
316
316
|
if (validation.required) {
|
|
317
317
|
schema = schema.refine(
|
|
318
|
-
(value:
|
|
318
|
+
(value: unknown) => value !== undefined && value !== null,
|
|
319
319
|
{ message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
|
|
320
320
|
);
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
if (validation.min) schema = schema.refine(
|
|
324
|
-
(value:
|
|
324
|
+
(value: unknown) => value == null || (value instanceof Date && value >= validation.min!),
|
|
325
325
|
{ message: `${property.name} must be after ${validation.min}` }
|
|
326
326
|
);
|
|
327
327
|
if (validation.max) schema = schema.refine(
|
|
328
|
-
(value:
|
|
328
|
+
(value: unknown) => value == null || (value instanceof Date && value <= validation.max!),
|
|
329
329
|
{ message: `${property.name} must be before ${validation.min}` }
|
|
330
330
|
);
|
|
331
331
|
}
|
|
@@ -345,7 +345,7 @@ function getZodReferenceSchema({
|
|
|
345
345
|
if (validation) {
|
|
346
346
|
if (validation.required) {
|
|
347
347
|
schema = schema.refine(
|
|
348
|
-
(value:
|
|
348
|
+
(value: unknown) => value !== undefined && value !== null,
|
|
349
349
|
{ message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
|
|
350
350
|
);
|
|
351
351
|
}
|
|
@@ -370,7 +370,7 @@ function getZodRelationSchema({
|
|
|
370
370
|
if (validation) {
|
|
371
371
|
if (validation.required) {
|
|
372
372
|
schema = schema.refine(
|
|
373
|
-
(value:
|
|
373
|
+
(value: unknown) => {
|
|
374
374
|
if (isMany) {
|
|
375
375
|
return value !== undefined && value !== null && Array.isArray(value) && value.length > 0;
|
|
376
376
|
}
|
|
@@ -397,7 +397,7 @@ function getZodBooleanSchema({
|
|
|
397
397
|
if (validation) {
|
|
398
398
|
if (validation.required) {
|
|
399
399
|
schema = schema.refine(
|
|
400
|
-
(value:
|
|
400
|
+
(value: unknown) => value !== undefined && value !== null,
|
|
401
401
|
{ message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
|
|
402
402
|
);
|
|
403
403
|
}
|
|
@@ -480,13 +480,13 @@ function getZodArraySchema({
|
|
|
480
480
|
if (arrayUniqueFields) {
|
|
481
481
|
if (typeof arrayUniqueFields === "boolean") {
|
|
482
482
|
arraySchema = arraySchema.refine(
|
|
483
|
-
(values:
|
|
483
|
+
(values: unknown) => !values || !Array.isArray(values) || values.length === new Set(values).size,
|
|
484
484
|
{ message: `${property.name} should have unique values within the array` }
|
|
485
485
|
);
|
|
486
486
|
} else if (Array.isArray(arrayUniqueFields)) {
|
|
487
487
|
arrayUniqueFields.forEach(([fieldName, childProperty]) => {
|
|
488
488
|
arraySchema = arraySchema.refine(
|
|
489
|
-
(values:
|
|
489
|
+
(values: unknown) => !values || !Array.isArray(values) || values.length === new Set(values.map((v: unknown) => v && typeof v === "object" ? (v as Record<string, unknown>)[fieldName] : v)).size,
|
|
490
490
|
{ message: `${property.name} → ${childProperty.name ?? fieldName}: should have unique values within the array` }
|
|
491
491
|
);
|
|
492
492
|
});
|
|
@@ -499,22 +499,22 @@ function getZodArraySchema({
|
|
|
499
499
|
if (validation) {
|
|
500
500
|
if (validation.required) {
|
|
501
501
|
arraySchema = arraySchema.refine(
|
|
502
|
-
(value:
|
|
502
|
+
(value: unknown) => value !== undefined && value !== null && Array.isArray(value) && value.length > 0,
|
|
503
503
|
{ message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
|
|
504
504
|
);
|
|
505
505
|
}
|
|
506
506
|
if (validation.min || validation.min === 0) arraySchema = arraySchema.refine(
|
|
507
|
-
(value:
|
|
507
|
+
(value: unknown) => !value || !Array.isArray(value) || value.length >= validation.min!,
|
|
508
508
|
{ message: `${property.name} should be min ${validation.min} entries long` }
|
|
509
509
|
);
|
|
510
510
|
if (validation.max) arraySchema = arraySchema.refine(
|
|
511
|
-
(value:
|
|
511
|
+
(value: unknown) => !value || !Array.isArray(value) || value.length <= validation.max!,
|
|
512
512
|
{ message: `${property.name} should be max ${validation.max} entries long` }
|
|
513
513
|
);
|
|
514
514
|
// Handle uniqueInArray at the array level
|
|
515
515
|
if (validation.uniqueInArray) {
|
|
516
516
|
arraySchema = arraySchema.refine(
|
|
517
|
-
(values:
|
|
517
|
+
(values: unknown) => !values || !Array.isArray(values) || values.length === new Set(values).size,
|
|
518
518
|
{ message: `${property.name} should have unique values within the array` }
|
|
519
519
|
);
|
|
520
520
|
}
|
|
@@ -526,12 +526,12 @@ function getZodVectorSchema({
|
|
|
526
526
|
property
|
|
527
527
|
}: PropertyContext<VectorProperty>): ZodTypeAny {
|
|
528
528
|
let schema: ZodTypeAny = z.preprocess(
|
|
529
|
-
(val:
|
|
530
|
-
if (val && typeof val === "object" && "__type" in val && val.__type === "Vector") {
|
|
531
|
-
return val.value;
|
|
529
|
+
(val: unknown) => {
|
|
530
|
+
if (val && typeof val === "object" && "__type" in val && (val as Record<string, unknown>).__type === "Vector") {
|
|
531
|
+
return (val as Record<string, unknown>).value;
|
|
532
532
|
}
|
|
533
|
-
if (val && typeof val === "object" && "value" in val && Array.isArray(val.value)) {
|
|
534
|
-
return val.value;
|
|
533
|
+
if (val && typeof val === "object" && "value" in val && Array.isArray((val as Record<string, unknown>).value)) {
|
|
534
|
+
return (val as Record<string, unknown>).value;
|
|
535
535
|
}
|
|
536
536
|
return val;
|
|
537
537
|
},
|
|
@@ -540,14 +540,14 @@ function getZodVectorSchema({
|
|
|
540
540
|
|
|
541
541
|
if (property.dimensions) {
|
|
542
542
|
schema = schema.refine(
|
|
543
|
-
(val:
|
|
543
|
+
(val: unknown) => val === null || val === undefined || (Array.isArray(val) && val.length === property.dimensions),
|
|
544
544
|
{ message: `${property.name ?? "Vector"} must have exactly ${property.dimensions} dimensions` }
|
|
545
545
|
);
|
|
546
546
|
}
|
|
547
547
|
|
|
548
548
|
if (property.validation?.required) {
|
|
549
549
|
schema = schema.refine(
|
|
550
|
-
(val:
|
|
550
|
+
(val: unknown) => val !== null && val !== undefined && Array.isArray(val) && val.length > 0,
|
|
551
551
|
{ message: property.validation?.requiredMessage ?? "Required" }
|
|
552
552
|
);
|
|
553
553
|
}
|
|
@@ -563,7 +563,7 @@ function getZodBinarySchema({
|
|
|
563
563
|
|
|
564
564
|
if (validation?.required) {
|
|
565
565
|
schema = schema.nullable().optional().refine(
|
|
566
|
-
(value:
|
|
566
|
+
(value: unknown) => value !== undefined && value !== null && value !== "",
|
|
567
567
|
{ message: validation.requiredMessage ? validation.requiredMessage : "Required" }
|
|
568
568
|
);
|
|
569
569
|
}
|
|
@@ -59,7 +59,6 @@ export function useBuildNavigationStateController<EC extends EntityCollection, U
|
|
|
59
59
|
userManagement
|
|
60
60
|
} = props;
|
|
61
61
|
|
|
62
|
-
// Step 1: Resolve collections
|
|
63
62
|
const {
|
|
64
63
|
collections,
|
|
65
64
|
loading: collectionsLoading,
|
|
@@ -71,10 +70,10 @@ export function useBuildNavigationStateController<EC extends EntityCollection, U
|
|
|
71
70
|
data,
|
|
72
71
|
plugins,
|
|
73
72
|
disabled,
|
|
74
|
-
collectionRegistryController
|
|
73
|
+
collectionRegistryController,
|
|
74
|
+
userManagement
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
// Step 2: Resolve views and admin views
|
|
78
77
|
const {
|
|
79
78
|
views,
|
|
80
79
|
adminViews,
|
|
@@ -89,8 +88,7 @@ export function useBuildNavigationStateController<EC extends EntityCollection, U
|
|
|
89
88
|
plugins,
|
|
90
89
|
adminMode,
|
|
91
90
|
effectiveRoleController,
|
|
92
|
-
userManagement
|
|
93
|
-
collections
|
|
91
|
+
userManagement
|
|
94
92
|
});
|
|
95
93
|
|
|
96
94
|
// Step 3: Compute top-level navigation (pure derived state)
|
|
@@ -3,7 +3,8 @@ import { useCallback, useEffect, useRef, useState, useMemo } from "react";
|
|
|
3
3
|
|
|
4
4
|
import { AuthController, CollectionRegistryController, RebaseData, User } from "@rebasepro/types";
|
|
5
5
|
import type { EntityCollectionsBuilder } from "@rebasepro/types";
|
|
6
|
-
import { CollectionRegistry } from "@rebasepro/common";
|
|
6
|
+
import { CollectionRegistry, defaultUsersCollection } from "@rebasepro/common";
|
|
7
|
+
import { UserManagementDelegate } from "@rebasepro/types";
|
|
7
8
|
|
|
8
9
|
import { resolveCollections } from "./useNavigationResolution";
|
|
9
10
|
import { areCollectionListsEqual } from "./utils";
|
|
@@ -15,6 +16,7 @@ export type UseResolvedCollectionsProps<EC extends EntityCollection, USER extend
|
|
|
15
16
|
plugins?: RebasePlugin[];
|
|
16
17
|
disabled?: boolean;
|
|
17
18
|
collectionRegistryController: CollectionRegistryController<EC> & { collectionRegistryRef: React.MutableRefObject<CollectionRegistry> };
|
|
19
|
+
userManagement?: UserManagementDelegate<USER>;
|
|
18
20
|
};
|
|
19
21
|
|
|
20
22
|
export type UseResolvedCollectionsResult = {
|
|
@@ -28,6 +30,10 @@ export type UseResolvedCollectionsResult = {
|
|
|
28
30
|
* Hook that resolves collection props (which may be async builders or arrays)
|
|
29
31
|
* into concrete EntityCollection[], and registers them with the CollectionRegistry.
|
|
30
32
|
*
|
|
33
|
+
* When userManagement is provided, the default users collection is always
|
|
34
|
+
* prepended. Developer collections override via generic slug-based dedup
|
|
35
|
+
* (Map keyed by slug, last-write-wins). No hardcoded string checks.
|
|
36
|
+
*
|
|
31
37
|
* Uses refs for potentially-unstable dependencies (driver, authController,
|
|
32
38
|
* plugins) to avoid re-triggering effects when their object identity changes.
|
|
33
39
|
*/
|
|
@@ -41,7 +47,8 @@ export function useResolvedCollections<EC extends EntityCollection, USER extends
|
|
|
41
47
|
data,
|
|
42
48
|
plugins,
|
|
43
49
|
disabled,
|
|
44
|
-
collectionRegistryController
|
|
50
|
+
collectionRegistryController,
|
|
51
|
+
userManagement
|
|
45
52
|
} = props;
|
|
46
53
|
|
|
47
54
|
const [loading, setLoading] = useState(true);
|
|
@@ -63,6 +70,8 @@ export function useResolvedCollections<EC extends EntityCollection, USER extends
|
|
|
63
70
|
authControllerRef.current = authController;
|
|
64
71
|
const pluginsRef = useRef(plugins);
|
|
65
72
|
pluginsRef.current = plugins;
|
|
73
|
+
const userManagementRef = useRef(userManagement);
|
|
74
|
+
userManagementRef.current = userManagement;
|
|
66
75
|
|
|
67
76
|
// Ref for resolved collections change detection
|
|
68
77
|
const resolvedCollectionsRef = useRef<EntityCollection[]>([]);
|
|
@@ -86,17 +95,27 @@ export function useResolvedCollections<EC extends EntityCollection, USER extends
|
|
|
86
95
|
|
|
87
96
|
if (cancelled) return;
|
|
88
97
|
|
|
98
|
+
// Prepend system defaults; developer collections override via generic dedup.
|
|
99
|
+
// Map keyed by slug — last-write-wins, so developer collections overwrite defaults.
|
|
100
|
+
const defaults: EntityCollection[] = [];
|
|
101
|
+
if (userManagementRef.current) {
|
|
102
|
+
defaults.push(defaultUsersCollection);
|
|
103
|
+
}
|
|
104
|
+
const deduped = Array.from(
|
|
105
|
+
new Map([...defaults, ...resolved].map(c => [c.slug, c])).values()
|
|
106
|
+
);
|
|
107
|
+
|
|
89
108
|
// Register with the CollectionRegistry; returns true if changed
|
|
90
|
-
const changed = collectionRegistryController.collectionRegistryRef.current.registerMultiple(
|
|
109
|
+
const changed = collectionRegistryController.collectionRegistryRef.current.registerMultiple(deduped);
|
|
91
110
|
|
|
92
111
|
if (changed) {
|
|
93
|
-
console.debug("Collections have changed",
|
|
112
|
+
console.debug("Collections have changed", deduped);
|
|
94
113
|
}
|
|
95
114
|
|
|
96
115
|
// Only update state if collections actually changed
|
|
97
|
-
if (!areCollectionListsEqual(resolvedCollectionsRef.current,
|
|
98
|
-
resolvedCollectionsRef.current =
|
|
99
|
-
setResolvedCollections(
|
|
116
|
+
if (!areCollectionListsEqual(resolvedCollectionsRef.current, deduped)) {
|
|
117
|
+
resolvedCollectionsRef.current = deduped;
|
|
118
|
+
setResolvedCollections(deduped);
|
|
100
119
|
}
|
|
101
120
|
|
|
102
121
|
setError(undefined);
|
|
@@ -131,3 +150,4 @@ export function useResolvedCollections<EC extends EntityCollection, USER extends
|
|
|
131
150
|
refresh
|
|
132
151
|
}), [resolvedCollections, loading, error, refresh]);
|
|
133
152
|
}
|
|
153
|
+
|
|
@@ -23,9 +23,7 @@ import { UserManagementDelegate } from "@rebasepro/types";
|
|
|
23
23
|
import { resolveAppViews } from "./useNavigationResolution";
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
const UsersView = lazy(() => import("../../components/admin/UsersView").then(m => ({ default: m.UsersView })));
|
|
28
|
-
const RolesView = lazy(() => import("../../components/admin/RolesView").then(m => ({ default: m.RolesView })));
|
|
26
|
+
import { RolesView } from "../../components/admin/RolesView";
|
|
29
27
|
|
|
30
28
|
export type UseResolvedViewsProps<USER extends User> = {
|
|
31
29
|
authController: AuthController<USER>;
|
|
@@ -36,7 +34,6 @@ export type UseResolvedViewsProps<USER extends User> = {
|
|
|
36
34
|
adminMode?: "content" | "studio" | "settings";
|
|
37
35
|
effectiveRoleController?: EffectiveRoleController;
|
|
38
36
|
userManagement?: UserManagementDelegate<USER>;
|
|
39
|
-
collections?: EntityCollection[];
|
|
40
37
|
};
|
|
41
38
|
|
|
42
39
|
export type UseResolvedViewsResult = {
|
|
@@ -49,8 +46,8 @@ export type UseResolvedViewsResult = {
|
|
|
49
46
|
|
|
50
47
|
/**
|
|
51
48
|
* Hook that resolves view and admin view props (which may be async builders or arrays)
|
|
52
|
-
* into concrete AppView[]. Also injects
|
|
53
|
-
* is provided.
|
|
49
|
+
* into concrete AppView[]. Also injects the Roles admin view when userManagement
|
|
50
|
+
* is provided with roles.
|
|
54
51
|
*
|
|
55
52
|
* Uses refs for potentially-unstable dependencies (driver, authController,
|
|
56
53
|
* plugins) to avoid re-triggering effects when their object identity changes.
|
|
@@ -67,8 +64,7 @@ export function useResolvedViews<USER extends User>(
|
|
|
67
64
|
plugins,
|
|
68
65
|
adminMode = "content",
|
|
69
66
|
effectiveRoleController,
|
|
70
|
-
userManagement
|
|
71
|
-
collections
|
|
67
|
+
userManagement
|
|
72
68
|
} = props;
|
|
73
69
|
|
|
74
70
|
const [loading, setLoading] = useState(true);
|
|
@@ -114,43 +110,27 @@ export function useResolvedViews<USER extends User>(
|
|
|
114
110
|
const resolvedAuthControllerRef = useRef(resolvedAuthController);
|
|
115
111
|
resolvedAuthControllerRef.current = resolvedAuthController;
|
|
116
112
|
|
|
117
|
-
// Memoize JSX
|
|
118
|
-
const
|
|
119
|
-
userManagement ? <Suspense fallback={null}><UsersView userManagement={userManagement as unknown as UserManagementDelegate<User>}/></Suspense> : null,
|
|
120
|
-
[userManagement]
|
|
121
|
-
);
|
|
113
|
+
// Memoize JSX element for injected Roles admin view to ensure stable reference.
|
|
114
|
+
const hasRoles = !!userManagement?.roles;
|
|
122
115
|
const rolesViewElement = useMemo(() =>
|
|
123
|
-
|
|
124
|
-
[
|
|
116
|
+
hasRoles ? <RolesView /> : null,
|
|
117
|
+
[hasRoles]
|
|
125
118
|
);
|
|
126
119
|
|
|
127
120
|
const injectedAdminViews: AppView[] = useMemo(() => {
|
|
128
121
|
const views: AppView[] = [];
|
|
129
122
|
const isUserAdmin = userManagement?.isAdmin !== false;
|
|
130
|
-
if (userManagement && isUserAdmin &&
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
group: "Settings"
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
const hasRolesCollection = collections?.some(c => c.slug === "roles");
|
|
142
|
-
if (userManagement.roles && rolesViewElement && !hasRolesCollection) {
|
|
143
|
-
views.push({
|
|
144
|
-
slug: "roles",
|
|
145
|
-
name: "Roles",
|
|
146
|
-
icon: "Shield",
|
|
147
|
-
view: rolesViewElement,
|
|
148
|
-
group: "Settings"
|
|
149
|
-
});
|
|
150
|
-
}
|
|
123
|
+
if (userManagement && isUserAdmin && userManagement.roles && rolesViewElement) {
|
|
124
|
+
views.push({
|
|
125
|
+
slug: "roles",
|
|
126
|
+
name: "Roles",
|
|
127
|
+
icon: "Shield",
|
|
128
|
+
view: rolesViewElement,
|
|
129
|
+
group: "Settings"
|
|
130
|
+
});
|
|
151
131
|
}
|
|
152
132
|
return views;
|
|
153
|
-
}, [userManagement,
|
|
133
|
+
}, [userManagement, rolesViewElement]);
|
|
154
134
|
|
|
155
135
|
// Store injectedAdminViews in a ref for effect access
|
|
156
136
|
const injectedAdminViewsRef = useRef(injectedAdminViews);
|
|
@@ -171,12 +151,12 @@ export function useResolvedViews<USER extends User>(
|
|
|
171
151
|
resolveAppViews(adminViewsProp, resolvedAuthControllerRef.current, dataRef.current)
|
|
172
152
|
]);
|
|
173
153
|
|
|
174
|
-
|
|
175
|
-
|
|
154
|
+
// Generic dedup: developer-provided admin views override any injected ones with the same slug.
|
|
155
|
+
// No hardcoded slug checks — works for any slug generically.
|
|
156
|
+
const customSlugs = new Set(newAdminViewsProp.flatMap(v => Array.isArray(v.slug) ? v.slug : [v.slug]));
|
|
176
157
|
const finalInjected = injectedAdminViewsRef.current.filter(v => {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return true;
|
|
158
|
+
const slugs = Array.isArray(v.slug) ? v.slug : [v.slug];
|
|
159
|
+
return slugs.every(s => !customSlugs.has(s));
|
|
180
160
|
});
|
|
181
161
|
const newAdminViews = [...newAdminViewsProp, ...finalInjected];
|
|
182
162
|
|
|
@@ -215,8 +195,7 @@ export function useResolvedViews<USER extends User>(
|
|
|
215
195
|
refreshTrigger,
|
|
216
196
|
adminMode,
|
|
217
197
|
initialLoading,
|
|
218
|
-
user
|
|
219
|
-
collections
|
|
198
|
+
user
|
|
220
199
|
]);
|
|
221
200
|
|
|
222
201
|
return useMemo(() => ({
|
|
@@ -227,3 +206,4 @@ export function useResolvedViews<USER extends User>(
|
|
|
227
206
|
refresh
|
|
228
207
|
}), [resolvedViews, resolvedAdminViews, loading, error, refresh]);
|
|
229
208
|
}
|
|
209
|
+
|
package/src/index.ts
CHANGED
|
@@ -57,7 +57,7 @@ export const PropertyPreview = React.memo(function PropertyPreview<P extends Pro
|
|
|
57
57
|
if (property === null) {
|
|
58
58
|
content = <EmptyValue/>;
|
|
59
59
|
} else if (property.ui?.Preview) {
|
|
60
|
-
const ResolvedPreview = resolveComponentRef(property.ui.Preview);
|
|
60
|
+
const ResolvedPreview = resolveComponentRef(property.ui.Preview) as React.ComponentType<PropertyPreviewProps<Property>> | undefined;
|
|
61
61
|
if (ResolvedPreview) {
|
|
62
62
|
content = <Suspense fallback={null}>
|
|
63
63
|
{createElement(ResolvedPreview,
|
|
@@ -205,7 +205,7 @@ path: stringProperty.reference.path })}
|
|
|
205
205
|
}
|
|
206
206
|
} else if (property.type === "reference") {
|
|
207
207
|
if (typeof property.path === "string") {
|
|
208
|
-
if (typeof value === "object" && "isEntityReference" in value && value.isEntityReference()) {
|
|
208
|
+
if (typeof value === "object" && value !== null && "isEntityReference" in value && (value as EntityReference).isEntityReference()) {
|
|
209
209
|
content = <ReferencePreview
|
|
210
210
|
disabled={!property.path}
|
|
211
211
|
previewProperties={property.ui?.previewProperties}
|
|
@@ -3,6 +3,7 @@ import React, { CSSProperties, useMemo, useState, useEffect } from "react";impor
|
|
|
3
3
|
import { PreviewSize } from "../../types/components/PropertyPreviewProps";
|
|
4
4
|
import { getThumbnailMeasure } from "../util";
|
|
5
5
|
import { useTranslation } from "@rebasepro/core";
|
|
6
|
+
import { sanitizeUrl } from "./UrlComponentPreview";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @group Preview components
|
|
@@ -127,7 +128,7 @@ maxHeight: "100%" }}>
|
|
|
127
128
|
className="invisible group-hover:visible"
|
|
128
129
|
variant={"filled"}
|
|
129
130
|
component={"a" as React.ElementType}
|
|
130
|
-
href={url}
|
|
131
|
+
href={sanitizeUrl(url)}
|
|
131
132
|
rel="noopener noreferrer"
|
|
132
133
|
target="_blank"
|
|
133
134
|
size={"smallest"}
|