@firecms/core 3.0.0-canary.2 → 3.0.0-canary.200
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 +4 -4
- package/dist/app/AppBar.d.ts +12 -0
- package/dist/app/Drawer.d.ts +16 -0
- package/dist/app/Scaffold.d.ts +30 -0
- package/dist/app/index.d.ts +4 -0
- package/dist/app/useApp.d.ts +16 -0
- package/dist/components/ArrayContainer.d.ts +23 -6
- package/dist/components/CircularProgressCenter.d.ts +1 -1
- package/dist/components/ClearFilterSortButton.d.ts +5 -0
- package/dist/components/{DeleteConfirmationDialog.d.ts → ConfirmationDialog.d.ts} +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +13 -13
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +3 -3
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +22 -6
- package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +3 -2
- package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
- package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +3 -1
- package/dist/components/EntityCollectionTable/index.d.ts +1 -1
- package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
- package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
- package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +7 -4
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +17 -4
- package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
- package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
- package/dist/components/EntityCollectionView/utils.d.ts +3 -0
- package/dist/components/EntityPreview.d.ts +26 -7
- package/dist/components/EntityView.d.ts +11 -0
- package/dist/components/ErrorView.d.ts +1 -1
- package/dist/components/FieldCaption.d.ts +5 -0
- package/dist/components/HomePage/DefaultHomePage.d.ts +1 -1
- package/dist/components/HomePage/NavigationCard.d.ts +8 -0
- package/dist/components/HomePage/{NavigationCollectionCard.d.ts → NavigationCardBinding.d.ts} +3 -3
- package/dist/components/HomePage/SmallNavigationCard.d.ts +6 -0
- package/dist/components/HomePage/index.d.ts +3 -1
- package/dist/components/PropertyConfigBadge.d.ts +2 -1
- package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
- package/dist/components/ReferenceWidget.d.ts +6 -4
- package/dist/components/SelectableTable/SelectableTable.d.ts +13 -3
- package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
- package/dist/components/UnsavedChangesDialog.d.ts +8 -0
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +29 -13
- package/dist/components/VirtualTable/types.d.ts +3 -3
- package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -3
- package/dist/components/common/index.d.ts +2 -1
- package/dist/components/common/table_height.d.ts +5 -0
- package/dist/components/common/types.d.ts +4 -6
- package/dist/components/common/useColumnsIds.d.ts +3 -1
- package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +13 -2
- package/dist/components/common/useDebouncedCallback.d.ts +1 -0
- package/dist/components/common/useScrollRestoration.d.ts +14 -0
- package/dist/components/index.d.ts +8 -5
- package/dist/contexts/AuthControllerContext.d.ts +1 -1
- package/dist/contexts/BreacrumbsContext.d.ts +8 -0
- package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +6 -9
- package/dist/core/DefaultDrawer.d.ts +19 -0
- package/dist/core/DrawerNavigationItem.d.ts +10 -0
- package/dist/core/EntityEditView.d.ts +44 -0
- package/dist/core/EntityEditViewFormActions.d.ts +2 -0
- package/dist/core/FireCMS.d.ts +2 -2
- package/dist/core/FireCMSRouter.d.ts +4 -0
- package/dist/core/NavigationRoutes.d.ts +2 -3
- package/dist/core/SideDialogs.d.ts +4 -2
- package/dist/core/index.d.ts +4 -6
- package/dist/form/EntityForm.d.ts +45 -69
- package/dist/form/EntityFormActions.d.ts +17 -0
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/components/ErrorFocus.d.ts +1 -1
- package/dist/form/components/FieldHelperText.d.ts +3 -3
- package/dist/form/components/FormEntry.d.ts +6 -0
- package/dist/form/components/FormLayout.d.ts +5 -0
- package/dist/{components → form/components}/LabelWithIcon.d.ts +1 -1
- package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
- package/dist/form/components/StorageItemPreview.d.ts +4 -3
- package/dist/form/components/StorageUploadProgress.d.ts +1 -1
- package/dist/form/components/index.d.ts +4 -1
- package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
- package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
- package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
- package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -4
- package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
- package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
- package/dist/form/index.d.ts +17 -18
- package/dist/form/useClearRestoreValue.d.ts +2 -2
- package/dist/form/validation.d.ts +1 -1
- package/dist/hooks/data/delete.d.ts +4 -4
- package/dist/hooks/data/save.d.ts +4 -5
- package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
- package/dist/hooks/data/useDataSource.d.ts +2 -2
- package/dist/hooks/data/useEntityFetch.d.ts +4 -3
- package/dist/hooks/index.d.ts +4 -1
- package/dist/hooks/useAuthController.d.ts +1 -1
- package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
- package/dist/{core → hooks}/useBuildModeController.d.ts +1 -1
- package/dist/hooks/useBuildNavigationController.d.ts +11 -6
- package/dist/hooks/useFireCMSContext.d.ts +1 -1
- package/dist/hooks/useModeController.d.ts +1 -2
- package/dist/hooks/useProjectLog.d.ts +12 -2
- package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
- package/dist/hooks/useStorageSource.d.ts +2 -2
- package/dist/hooks/useValidateAuthenticator.d.ts +21 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +22131 -14039
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +24420 -588
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useBuildDataSource.d.ts +1 -12
- package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
- package/dist/preview/PropertyPreview.d.ts +1 -1
- package/dist/preview/PropertyPreviewProps.d.ts +7 -5
- package/dist/preview/components/BooleanPreview.d.ts +5 -1
- package/dist/preview/components/EnumValuesChip.d.ts +1 -1
- package/dist/preview/components/ReferencePreview.d.ts +4 -9
- package/dist/preview/components/StorageThumbnail.d.ts +2 -1
- package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
- package/dist/preview/util.d.ts +3 -3
- package/dist/routes/CustomCMSRoute.d.ts +4 -0
- package/dist/routes/FireCMSRoute.d.ts +1 -0
- package/dist/routes/HomePageRoute.d.ts +3 -0
- package/dist/types/analytics.d.ts +1 -1
- package/dist/types/auth.d.ts +37 -3
- package/dist/types/collections.d.ts +86 -24
- package/dist/types/datasource.d.ts +53 -37
- package/dist/types/dialogs_controller.d.ts +7 -3
- package/dist/types/entities.d.ts +8 -2
- package/dist/types/entity_actions.d.ts +28 -4
- package/dist/types/entity_callbacks.d.ts +16 -16
- package/dist/types/entity_overrides.d.ts +6 -0
- package/dist/types/export_import.d.ts +4 -4
- package/dist/types/fields.d.ts +71 -42
- package/dist/types/firecms.d.ts +6 -2
- package/dist/types/firecms_context.d.ts +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/navigation.d.ts +45 -26
- package/dist/types/permissions.d.ts +8 -4
- package/dist/types/plugins.d.ts +40 -31
- package/dist/types/properties.d.ts +54 -26
- package/dist/types/property_config.d.ts +2 -4
- package/dist/types/roles.d.ts +31 -0
- package/dist/types/side_dialogs_controller.d.ts +10 -0
- package/dist/types/side_entity_controller.d.ts +6 -1
- package/dist/types/storage.d.ts +86 -3
- package/dist/types/user.d.ts +6 -0
- package/dist/util/builders.d.ts +3 -3
- package/dist/util/collections.d.ts +9 -1
- package/dist/util/entities.d.ts +3 -3
- package/dist/util/entity_actions.d.ts +2 -0
- package/dist/util/entity_cache.d.ts +23 -0
- package/dist/util/icon_list.d.ts +5 -1
- package/dist/util/icon_synonyms.d.ts +1 -98
- package/dist/util/icons.d.ts +13 -4
- package/dist/util/index.d.ts +2 -0
- package/dist/util/navigation_from_path.d.ts +6 -1
- package/dist/util/navigation_utils.d.ts +14 -3
- package/dist/util/objects.d.ts +2 -1
- package/dist/util/permissions.d.ts +4 -4
- package/dist/util/plurals.d.ts +0 -2
- package/dist/util/property_utils.d.ts +3 -3
- package/dist/util/references.d.ts +4 -2
- package/dist/util/resolutions.d.ts +31 -17
- package/dist/util/storage.d.ts +23 -2
- package/dist/util/useStorageUploadController.d.ts +3 -3
- package/dist/util/useTraceUpdate.d.ts +1 -0
- package/package.json +64 -51
- package/src/app/AppBar.tsx +18 -0
- package/src/app/Drawer.tsx +24 -0
- package/src/app/Scaffold.tsx +243 -0
- package/src/app/index.ts +4 -0
- package/src/app/useApp.tsx +32 -0
- package/src/components/ArrayContainer.tsx +126 -40
- package/src/components/CircularProgressCenter.tsx +2 -2
- package/src/components/ClearFilterSortButton.tsx +41 -0
- package/src/components/{DeleteConfirmationDialog.tsx → ConfirmationDialog.tsx} +3 -3
- package/src/components/DeleteEntityDialog.tsx +14 -23
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +56 -39
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +283 -280
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +29 -8
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +58 -50
- package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +40 -33
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +22 -20
- package/src/components/EntityCollectionTable/index.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +31 -36
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +36 -34
- package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +20 -8
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +81 -80
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +228 -155
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +9 -8
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
- package/src/components/EntityCollectionView/useSelectionController.tsx +43 -0
- package/src/components/EntityCollectionView/utils.ts +19 -0
- package/src/components/EntityPreview.tsx +218 -71
- package/src/components/EntityView.tsx +84 -0
- package/src/components/ErrorView.tsx +4 -4
- package/src/components/FieldCaption.tsx +14 -0
- package/src/components/HomePage/DefaultHomePage.tsx +39 -28
- package/src/components/HomePage/FavouritesView.tsx +6 -11
- package/src/components/HomePage/NavigationCard.tsx +69 -0
- package/src/components/HomePage/NavigationCardBinding.tsx +111 -0
- package/src/components/HomePage/NavigationGroup.tsx +2 -2
- package/src/components/HomePage/SmallNavigationCard.tsx +44 -0
- package/src/components/HomePage/index.tsx +3 -1
- package/src/components/NotFoundPage.tsx +2 -2
- package/src/components/PropertyConfigBadge.tsx +9 -3
- package/src/components/PropertyIdCopyTooltip.tsx +47 -0
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +22 -17
- package/src/components/ReferenceWidget.tsx +26 -16
- package/src/components/SearchIconsView.tsx +10 -7
- package/src/components/SelectableTable/SelectableTable.tsx +27 -12
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +25 -8
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +46 -30
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +92 -23
- package/src/components/UnsavedChangesDialog.tsx +42 -0
- package/src/components/VirtualTable/VirtualTable.tsx +96 -48
- package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
- package/src/components/VirtualTable/VirtualTableHeader.tsx +10 -10
- package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
- package/src/components/VirtualTable/VirtualTableProps.tsx +34 -15
- package/src/components/VirtualTable/VirtualTableRow.tsx +5 -6
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +5 -5
- package/src/components/VirtualTable/fields/VirtualTableInput.tsx +3 -2
- package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
- package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +16 -28
- package/src/components/VirtualTable/types.tsx +2 -3
- package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +40 -43
- package/src/components/common/index.ts +2 -1
- package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
- package/src/components/common/types.tsx +4 -6
- package/src/components/common/useColumnsIds.tsx +24 -3
- package/src/components/common/useDataSourceTableController.tsx +420 -0
- package/src/components/common/useDebouncedCallback.tsx +20 -0
- package/src/components/common/useScrollRestoration.tsx +68 -0
- package/src/components/common/useTableSearchHelper.ts +53 -12
- package/src/components/index.tsx +8 -5
- package/src/contexts/AuthControllerContext.tsx +1 -1
- package/src/contexts/BreacrumbsContext.tsx +38 -0
- package/src/contexts/DialogsProvider.tsx +5 -4
- package/src/contexts/ModeController.tsx +1 -3
- package/src/contexts/SnackbarProvider.tsx +2 -0
- package/src/core/DefaultAppBar.tsx +207 -0
- package/src/core/DefaultDrawer.tsx +185 -0
- package/src/core/DrawerNavigationItem.tsx +66 -0
- package/src/core/EntityEditView.tsx +455 -0
- package/src/core/EntityEditViewFormActions.tsx +199 -0
- package/src/core/EntitySidePanel.tsx +87 -18
- package/src/core/FireCMS.tsx +67 -44
- package/src/core/FireCMSRouter.tsx +17 -0
- package/src/core/NavigationRoutes.tsx +36 -38
- package/src/core/SideDialogs.tsx +22 -12
- package/src/core/field_configs.tsx +11 -12
- package/src/core/index.tsx +6 -7
- package/src/form/EntityForm.tsx +565 -519
- package/src/form/EntityFormActions.tsx +169 -0
- package/src/form/PropertyFieldBinding.tsx +85 -44
- package/src/form/components/CustomIdField.tsx +6 -2
- package/src/form/components/FieldHelperText.tsx +4 -4
- package/src/form/components/FormEntry.tsx +22 -0
- package/src/form/components/FormLayout.tsx +16 -0
- package/src/form/components/LabelWithIcon.tsx +44 -0
- package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
- package/src/form/components/StorageItemPreview.tsx +23 -11
- package/src/form/components/StorageUploadProgress.tsx +9 -9
- package/src/form/components/index.tsx +4 -1
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +32 -21
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +54 -45
- package/src/form/field_bindings/BlockFieldBinding.tsx +57 -36
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +21 -17
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +76 -67
- package/src/form/field_bindings/MapFieldBinding.tsx +82 -65
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +153 -0
- package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +26 -22
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +12 -17
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +47 -34
- package/src/form/field_bindings/RepeatFieldBinding.tsx +57 -36
- package/src/form/field_bindings/SelectFieldBinding.tsx +24 -17
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +47 -46
- package/src/form/field_bindings/SwitchFieldBinding.tsx +31 -27
- package/src/form/field_bindings/TextFieldBinding.tsx +35 -30
- package/src/form/index.tsx +17 -37
- package/src/form/useClearRestoreValue.tsx +2 -2
- package/src/form/validation.ts +15 -26
- package/src/hooks/data/delete.ts +7 -6
- package/src/hooks/data/save.ts +13 -9
- package/src/hooks/data/useCollectionFetch.tsx +4 -4
- package/src/hooks/data/useDataSource.tsx +15 -2
- package/src/hooks/data/useEntityFetch.tsx +11 -7
- package/src/hooks/index.tsx +6 -1
- package/src/hooks/useAuthController.tsx +1 -1
- package/src/hooks/useBreadcrumbsController.tsx +31 -0
- package/src/{core → hooks}/useBuildLocalConfigurationPersistence.tsx +8 -10
- package/src/{core → hooks}/useBuildModeController.tsx +23 -30
- package/src/hooks/useBuildNavigationController.tsx +278 -117
- package/src/hooks/useFireCMSContext.tsx +5 -5
- package/src/hooks/useLargeLayout.tsx +0 -35
- package/src/hooks/useModeController.tsx +1 -2
- package/src/hooks/useProjectLog.tsx +41 -9
- package/src/hooks/useReferenceDialog.tsx +2 -2
- package/src/hooks/useResolvedNavigationFrom.tsx +10 -12
- package/src/hooks/useStorageSource.tsx +7 -2
- package/src/hooks/useValidateAuthenticator.tsx +115 -0
- package/src/index.ts +1 -0
- package/src/internal/useBuildDataSource.ts +72 -77
- package/src/internal/useBuildSideDialogsController.tsx +4 -2
- package/src/internal/useBuildSideEntityController.tsx +177 -70
- package/src/internal/useUnsavedChangesDialog.tsx +127 -91
- package/src/preview/PropertyPreview.tsx +19 -26
- package/src/preview/PropertyPreviewProps.tsx +5 -9
- package/src/preview/components/BooleanPreview.tsx +19 -4
- package/src/preview/components/EmptyValue.tsx +1 -1
- package/src/preview/components/EnumValuesChip.tsx +2 -2
- package/src/preview/components/ImagePreview.tsx +25 -36
- package/src/preview/components/ReferencePreview.tsx +73 -176
- package/src/preview/components/StorageThumbnail.tsx +5 -1
- package/src/preview/components/UrlComponentPreview.tsx +60 -28
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -3
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +2 -3
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +1 -2
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -5
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -5
- package/src/preview/property_previews/MapPropertyPreview.tsx +12 -11
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +12 -12
- package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
- package/src/preview/util.ts +10 -10
- package/src/routes/CustomCMSRoute.tsx +21 -0
- package/src/routes/FireCMSRoute.tsx +236 -0
- package/src/routes/HomePageRoute.tsx +17 -0
- package/src/types/analytics.ts +1 -0
- package/src/types/auth.tsx +48 -3
- package/src/types/collections.ts +102 -27
- package/src/types/customization_controller.tsx +0 -1
- package/src/types/datasource.ts +62 -44
- package/src/types/dialogs_controller.tsx +7 -3
- package/src/types/entities.ts +16 -2
- package/src/types/entity_actions.tsx +33 -4
- package/src/types/entity_callbacks.ts +18 -18
- package/src/types/entity_overrides.tsx +7 -0
- package/src/types/export_import.ts +4 -4
- package/src/types/fields.tsx +81 -46
- package/src/types/firecms.tsx +6 -2
- package/src/types/firecms_context.tsx +1 -1
- package/src/types/index.ts +2 -1
- package/src/types/navigation.ts +52 -31
- package/src/types/permissions.ts +10 -5
- package/src/types/plugins.tsx +47 -39
- package/src/types/properties.ts +63 -27
- package/src/types/property_config.tsx +2 -4
- package/src/types/roles.ts +41 -0
- package/src/types/side_dialogs_controller.tsx +15 -0
- package/src/types/side_entity_controller.tsx +7 -1
- package/src/types/storage.ts +94 -3
- package/src/types/user.ts +9 -0
- package/src/util/builders.ts +10 -8
- package/src/util/collections.ts +22 -0
- package/src/util/entities.ts +9 -6
- package/src/util/entity_actions.ts +28 -0
- package/src/util/entity_cache.ts +204 -0
- package/src/util/enums.ts +1 -1
- package/src/util/icon_list.ts +16 -10
- package/src/util/icon_synonyms.ts +3 -100
- package/src/util/icons.tsx +26 -8
- package/src/util/index.ts +2 -0
- package/src/util/join_collections.ts +3 -0
- package/src/util/make_properties_editable.ts +13 -5
- package/src/util/navigation_from_path.ts +13 -6
- package/src/util/navigation_utils.ts +59 -7
- package/src/util/objects.ts +45 -28
- package/src/util/parent_references_from_path.ts +3 -3
- package/src/util/permissions.ts +20 -16
- package/src/util/plurals.ts +0 -2
- package/src/util/property_utils.tsx +11 -4
- package/src/util/references.ts +45 -5
- package/src/util/resolutions.ts +79 -46
- package/src/util/storage.ts +79 -21
- package/src/util/strings.ts +2 -2
- package/src/util/useStorageUploadController.tsx +71 -27
- package/src/util/useTraceUpdate.tsx +2 -1
- package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
- package/dist/components/VirtualTable/common.d.ts +0 -2
- package/dist/core/Drawer.d.ts +0 -23
- package/dist/core/Scaffold.d.ts +0 -55
- package/dist/form/components/FormikArrayContainer.d.ts +0 -18
- package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
- package/dist/internal/EntityView.d.ts +0 -22
- package/dist/internal/useBuildCustomizationController.d.ts +0 -2
- package/dist/internal/useLocaleConfig.d.ts +0 -1
- package/dist/types/appcheck.d.ts +0 -26
- package/src/components/FireCMSAppBar.tsx +0 -157
- package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
- package/src/components/LabelWithIcon.tsx +0 -33
- package/src/components/PropertyIdCopyTooltipContent.tsx +0 -28
- package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -225
- package/src/core/Drawer.tsx +0 -164
- package/src/core/Scaffold.tsx +0 -281
- package/src/form/components/FormikArrayContainer.tsx +0 -44
- package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -696
- package/src/internal/EntityView.tsx +0 -578
- package/src/internal/useBuildCustomizationController.tsx +0 -5
- package/src/internal/useLocaleConfig.tsx +0 -18
- package/src/types/appcheck.ts +0 -29
- /package/dist/{core → hooks}/useBuildLocalConfigurationPersistence.d.ts +0 -0
- /package/src/util/{common.tsx → common.ts} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
-
import { useLocation } from "react-router-dom";
|
|
3
2
|
import equal from "react-fast-compare"
|
|
4
3
|
|
|
5
4
|
import {
|
|
@@ -10,30 +9,38 @@ import {
|
|
|
10
9
|
EntityCollection,
|
|
11
10
|
EntityCollectionsBuilder,
|
|
12
11
|
EntityReference,
|
|
12
|
+
NavigationBlocker,
|
|
13
13
|
NavigationController,
|
|
14
|
+
PermissionsBuilder,
|
|
14
15
|
TopNavigationEntry,
|
|
15
16
|
TopNavigationResult,
|
|
16
17
|
User,
|
|
17
18
|
UserConfigurationPersistence
|
|
18
19
|
} from "../types";
|
|
19
20
|
import {
|
|
21
|
+
applyPermissionsFunctionIfEmpty,
|
|
20
22
|
getCollectionByPathOrId,
|
|
21
23
|
mergeDeep,
|
|
24
|
+
removeFunctions,
|
|
22
25
|
removeInitialAndTrailingSlashes,
|
|
23
26
|
resolveCollectionPathIds,
|
|
24
27
|
resolvePermissions
|
|
25
28
|
} from "../util";
|
|
26
29
|
import { getParentReferencesFromPath } from "../util/parent_references_from_path";
|
|
30
|
+
import { useBlocker, useNavigate } from "react-router-dom";
|
|
27
31
|
|
|
28
32
|
const DEFAULT_BASE_PATH = "/";
|
|
29
33
|
const DEFAULT_COLLECTION_PATH = "/c";
|
|
30
34
|
|
|
31
|
-
type BuildNavigationContextProps<EC extends EntityCollection,
|
|
35
|
+
export type BuildNavigationContextProps<EC extends EntityCollection, USER extends User> = {
|
|
32
36
|
basePath?: string,
|
|
33
37
|
baseCollectionPath?: string,
|
|
34
|
-
authController: AuthController<
|
|
38
|
+
authController: AuthController<USER>;
|
|
35
39
|
collections?: EC[] | EntityCollectionsBuilder<EC>;
|
|
40
|
+
collectionPermissions?: PermissionsBuilder;
|
|
36
41
|
views?: CMSView[] | CMSViewsBuilder;
|
|
42
|
+
adminViews?: CMSView[] | CMSViewsBuilder;
|
|
43
|
+
viewsOrder?: string[];
|
|
37
44
|
userConfigPersistence?: UserConfigurationPersistence;
|
|
38
45
|
dataSourceDelegate: DataSourceDelegate;
|
|
39
46
|
/**
|
|
@@ -44,24 +51,35 @@ type BuildNavigationContextProps<EC extends EntityCollection, UserType extends U
|
|
|
44
51
|
* @param collections
|
|
45
52
|
*/
|
|
46
53
|
injectCollections?: (collections: EntityCollection[]) => EntityCollection[];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* If true, the navigation logic will not be updated until this flag is false
|
|
57
|
+
*/
|
|
58
|
+
disabled?: boolean;
|
|
47
59
|
};
|
|
48
60
|
|
|
49
|
-
export function useBuildNavigationController<EC extends EntityCollection,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
export function useBuildNavigationController<EC extends EntityCollection, USER extends User>(props: BuildNavigationContextProps<EC, USER>): NavigationController {
|
|
62
|
+
const {
|
|
63
|
+
basePath = DEFAULT_BASE_PATH,
|
|
64
|
+
baseCollectionPath = DEFAULT_COLLECTION_PATH,
|
|
65
|
+
authController,
|
|
66
|
+
collections: collectionsProp,
|
|
67
|
+
collectionPermissions,
|
|
68
|
+
views: viewsProp,
|
|
69
|
+
adminViews: adminViewsProp,
|
|
70
|
+
viewsOrder,
|
|
71
|
+
userConfigPersistence,
|
|
72
|
+
dataSourceDelegate,
|
|
73
|
+
injectCollections,
|
|
74
|
+
disabled
|
|
75
|
+
} = props;
|
|
76
|
+
|
|
77
|
+
const navigate = useNavigate();
|
|
78
|
+
|
|
79
|
+
const collectionsRef = useRef<EntityCollection[] | undefined>();
|
|
80
|
+
const viewsRef = useRef<CMSView[] | undefined>();
|
|
81
|
+
const adminViewsRef = useRef<CMSView[] | undefined>();
|
|
82
|
+
|
|
65
83
|
const [initialised, setInitialised] = useState<boolean>(false);
|
|
66
84
|
|
|
67
85
|
const [topLevelNavigation, setTopLevelNavigation] = useState<TopNavigationResult | undefined>(undefined);
|
|
@@ -81,18 +99,18 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
81
99
|
const buildUrlCollectionPath = useCallback((path: string): string => `${removeInitialAndTrailingSlashes(baseCollectionPath)}/${encodePath(path)}`,
|
|
82
100
|
[baseCollectionPath]);
|
|
83
101
|
|
|
84
|
-
const computeTopNavigation = useCallback((collections: EntityCollection[], views: CMSView[]): TopNavigationResult => {
|
|
85
|
-
|
|
102
|
+
const computeTopNavigation = useCallback((collections: EntityCollection[], views: CMSView[], adminViews: CMSView[], viewsOrder?: string[]): TopNavigationResult => {
|
|
103
|
+
let navigationEntries: TopNavigationEntry[] = [
|
|
86
104
|
...(collections ?? []).map(collection => (!collection.hideFromNavigation
|
|
87
|
-
? {
|
|
105
|
+
? ({
|
|
88
106
|
url: buildUrlCollectionPath(collection.id ?? collection.path),
|
|
89
107
|
type: "collection",
|
|
90
108
|
name: collection.name.trim(),
|
|
91
109
|
path: collection.id ?? collection.path,
|
|
92
110
|
collection,
|
|
93
111
|
description: collection.description?.trim(),
|
|
94
|
-
group: collection
|
|
95
|
-
}
|
|
112
|
+
group: getGroup(collection)
|
|
113
|
+
} satisfies TopNavigationEntry)
|
|
96
114
|
: undefined))
|
|
97
115
|
.filter(Boolean) as TopNavigationEntry[],
|
|
98
116
|
...(views ?? []).map(view =>
|
|
@@ -101,18 +119,74 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
101
119
|
url: buildCMSUrlPath(Array.isArray(view.path) ? view.path[0] : view.path),
|
|
102
120
|
name: view.name.trim(),
|
|
103
121
|
type: "view",
|
|
122
|
+
path: view.path,
|
|
104
123
|
view,
|
|
105
124
|
description: view.description?.trim(),
|
|
106
|
-
group: view
|
|
107
|
-
})
|
|
125
|
+
group: getGroup(view)
|
|
126
|
+
} satisfies TopNavigationEntry)
|
|
127
|
+
: undefined)
|
|
128
|
+
.filter(Boolean) as TopNavigationEntry[],
|
|
129
|
+
...(adminViews ?? []).map(view =>
|
|
130
|
+
!view.hideFromNavigation
|
|
131
|
+
? ({
|
|
132
|
+
url: buildCMSUrlPath(Array.isArray(view.path) ? view.path[0] : view.path),
|
|
133
|
+
name: view.name.trim(),
|
|
134
|
+
type: "admin",
|
|
135
|
+
path: view.path,
|
|
136
|
+
view,
|
|
137
|
+
description: view.description?.trim(),
|
|
138
|
+
group: "Admin"
|
|
139
|
+
} satisfies TopNavigationEntry)
|
|
108
140
|
: undefined)
|
|
109
141
|
.filter(Boolean) as TopNavigationEntry[]
|
|
110
142
|
];
|
|
111
143
|
|
|
144
|
+
// Sort by group, entries with group "Admin" will go last, and second to last will be the group "Views"
|
|
145
|
+
navigationEntries = navigationEntries.sort((a, b) => {
|
|
146
|
+
if (a.group !== "Views" && a.group !== "Admin" && (b.group === "Views" || b.group === "Admin")) {
|
|
147
|
+
return -1;
|
|
148
|
+
}
|
|
149
|
+
if (b.group !== "Views" && b.group !== "Admin" && (a.group === "Views" || a.group === "Admin")) {
|
|
150
|
+
return 1;
|
|
151
|
+
}
|
|
152
|
+
if (a.group === "Admin" && b.group !== "Admin") {
|
|
153
|
+
return 1;
|
|
154
|
+
}
|
|
155
|
+
if (a.group !== "Admin" && b.group === "Admin") {
|
|
156
|
+
return -1;
|
|
157
|
+
}
|
|
158
|
+
if (a.group === "Views" && b.group !== "Views") {
|
|
159
|
+
return -1;
|
|
160
|
+
}
|
|
161
|
+
if (a.group !== "Views" && b.group === "Views") {
|
|
162
|
+
return 1;
|
|
163
|
+
}
|
|
164
|
+
return 0;
|
|
165
|
+
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
if (viewsOrder) {
|
|
169
|
+
navigationEntries = navigationEntries.sort((a, b) => {
|
|
170
|
+
const aIndex = viewsOrder.indexOf(a.path);
|
|
171
|
+
const bIndex = viewsOrder.indexOf(b.path);
|
|
172
|
+
if (aIndex === -1 && bIndex === -1) {
|
|
173
|
+
return 0;
|
|
174
|
+
}
|
|
175
|
+
if (aIndex === -1) {
|
|
176
|
+
return 1;
|
|
177
|
+
}
|
|
178
|
+
if (bIndex === -1) {
|
|
179
|
+
return -1;
|
|
180
|
+
}
|
|
181
|
+
return aIndex - bIndex;
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
112
185
|
const groups: string[] = Object.values(navigationEntries)
|
|
113
186
|
.map(e => e.group)
|
|
114
187
|
.filter(Boolean)
|
|
115
188
|
.filter((value, index, array) => array.indexOf(value) === index) as string[];
|
|
189
|
+
|
|
116
190
|
return {
|
|
117
191
|
navigationEntries,
|
|
118
192
|
groups
|
|
@@ -121,48 +195,81 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
121
195
|
|
|
122
196
|
const refreshNavigation = useCallback(async () => {
|
|
123
197
|
|
|
124
|
-
if (authController.initialLoading)
|
|
198
|
+
if (disabled || authController.initialLoading)
|
|
125
199
|
return;
|
|
126
200
|
|
|
201
|
+
console.debug("Refreshing navigation");
|
|
202
|
+
|
|
127
203
|
try {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
204
|
+
|
|
205
|
+
const [resolvedCollections = [], resolvedViews, resolvedAdminViews = []] = await Promise.all([
|
|
206
|
+
resolveCollections(collectionsProp, collectionPermissions, authController, dataSourceDelegate, injectCollections),
|
|
207
|
+
resolveCMSViews(viewsProp, authController, dataSourceDelegate),
|
|
208
|
+
resolveCMSViews(adminViewsProp, authController, dataSourceDelegate)
|
|
131
209
|
]
|
|
132
210
|
);
|
|
133
|
-
|
|
211
|
+
|
|
212
|
+
let shouldUpdateTopLevelNav = false;
|
|
213
|
+
if (!areCollectionListsEqual(collectionsRef.current ?? [], resolvedCollections)) {
|
|
214
|
+
collectionsRef.current = resolvedCollections;
|
|
215
|
+
console.log("Collections have changed", resolvedCollections);
|
|
216
|
+
shouldUpdateTopLevelNav = true;
|
|
217
|
+
}
|
|
218
|
+
if (collectionsRef.current === undefined) {
|
|
134
219
|
collectionsRef.current = resolvedCollections;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
220
|
+
shouldUpdateTopLevelNav = true;
|
|
221
|
+
}
|
|
222
|
+
if (!equal(viewsRef.current, resolvedViews)) {
|
|
223
|
+
viewsRef.current = resolvedViews;
|
|
224
|
+
shouldUpdateTopLevelNav = true;
|
|
225
|
+
}
|
|
226
|
+
if (!equal(adminViewsRef.current, resolvedAdminViews)) {
|
|
227
|
+
adminViewsRef.current = resolvedAdminViews;
|
|
228
|
+
shouldUpdateTopLevelNav = true;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder);
|
|
232
|
+
if (shouldUpdateTopLevelNav && !equal(topLevelNavigation, computedTopLevelNav)) {
|
|
233
|
+
setTopLevelNavigation(computedTopLevelNav);
|
|
138
234
|
}
|
|
139
235
|
} catch (e) {
|
|
140
236
|
console.error(e);
|
|
141
237
|
setNavigationLoadingError(e as any);
|
|
142
238
|
}
|
|
143
239
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
240
|
+
if (navigationLoading)
|
|
241
|
+
setNavigationLoading(false);
|
|
242
|
+
if (!initialised)
|
|
243
|
+
setInitialised(true);
|
|
244
|
+
|
|
245
|
+
}, [
|
|
246
|
+
collectionsProp,
|
|
247
|
+
collectionPermissions,
|
|
248
|
+
authController.user,
|
|
249
|
+
authController.initialLoading,
|
|
250
|
+
disabled,
|
|
251
|
+
viewsProp,
|
|
252
|
+
adminViewsProp,
|
|
253
|
+
computeTopNavigation,
|
|
254
|
+
injectCollections
|
|
255
|
+
]);
|
|
147
256
|
|
|
148
257
|
useEffect(() => {
|
|
149
258
|
refreshNavigation();
|
|
150
259
|
}, [refreshNavigation]);
|
|
151
260
|
|
|
152
|
-
const getCollection = useCallback(
|
|
261
|
+
const getCollection = useCallback((
|
|
153
262
|
idOrPath: string,
|
|
154
|
-
entityId?: string,
|
|
155
263
|
includeUserOverride = false
|
|
156
264
|
): EC | undefined => {
|
|
157
|
-
|
|
265
|
+
const collections = collectionsRef.current;
|
|
158
266
|
if (!collections)
|
|
159
267
|
return undefined;
|
|
160
268
|
|
|
161
269
|
const baseCollection = getCollectionByPathOrId(removeInitialAndTrailingSlashes(idOrPath), collections);
|
|
162
270
|
|
|
163
271
|
const userOverride = includeUserOverride ? userConfigPersistence?.getCollectionConfig(idOrPath) : undefined;
|
|
164
|
-
|
|
165
|
-
const overriddenCollection = baseCollection ? mergeDeep(baseCollection, userOverride) : undefined;
|
|
272
|
+
const overriddenCollection = baseCollection ? mergeDeep(baseCollection, userOverride ?? {}) : undefined;
|
|
166
273
|
|
|
167
274
|
let result: Partial<EntityCollection> | undefined = overriddenCollection;
|
|
168
275
|
|
|
@@ -182,16 +289,14 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
182
289
|
|
|
183
290
|
return { ...overriddenCollection, ...result } as EC;
|
|
184
291
|
|
|
185
|
-
}, [
|
|
186
|
-
basePath,
|
|
187
|
-
baseCollectionPath,
|
|
188
|
-
collections,
|
|
189
|
-
]);
|
|
292
|
+
}, [userConfigPersistence]);
|
|
190
293
|
|
|
191
294
|
const getCollectionFromPaths = useCallback(<EC extends EntityCollection>(pathSegments: string[]): EC | undefined => {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
295
|
+
|
|
296
|
+
const collections = collectionsRef.current;
|
|
297
|
+
if (collections === undefined)
|
|
298
|
+
throw Error("getCollectionFromPaths: Collections have not been initialised yet");
|
|
299
|
+
let currentCollections: EntityCollection[] | undefined = [...(collections ?? [])];
|
|
195
300
|
|
|
196
301
|
for (let i = 0; i < pathSegments.length; i++) {
|
|
197
302
|
const pathSegment = pathSegments[i];
|
|
@@ -205,12 +310,14 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
205
310
|
|
|
206
311
|
return undefined;
|
|
207
312
|
|
|
208
|
-
}, [
|
|
313
|
+
}, []);
|
|
209
314
|
|
|
210
315
|
const getCollectionFromIds = useCallback(<EC extends EntityCollection>(ids: string[]): EC | undefined => {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
316
|
+
|
|
317
|
+
const collections = collectionsRef.current;
|
|
318
|
+
if (collections === undefined)
|
|
319
|
+
throw Error("getCollectionFromIds: Collections have not been initialised yet");
|
|
320
|
+
let currentCollections: EntityCollection[] | undefined = [...(collections ?? [])];
|
|
214
321
|
|
|
215
322
|
for (let i = 0; i < ids.length; i++) {
|
|
216
323
|
const id = ids[i];
|
|
@@ -224,7 +331,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
224
331
|
|
|
225
332
|
return undefined;
|
|
226
333
|
|
|
227
|
-
}, [
|
|
334
|
+
}, []);
|
|
228
335
|
|
|
229
336
|
const isUrlCollectionPath = useCallback(
|
|
230
337
|
(path: string): boolean => removeInitialAndTrailingSlashes(path + "/").startsWith(removeInitialAndTrailingSlashes(fullCollectionPath) + "/"),
|
|
@@ -236,35 +343,18 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
236
343
|
throw Error("Expected path starting with " + fullCollectionPath);
|
|
237
344
|
}, [fullCollectionPath]);
|
|
238
345
|
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
}: {
|
|
242
|
-
path: string
|
|
243
|
-
}): string => {
|
|
244
|
-
return `s/edit/${encodePath(path)}`;
|
|
245
|
-
},
|
|
246
|
-
[]);
|
|
247
|
-
|
|
248
|
-
const resolveAliasesFrom = useCallback((path: string): string => {
|
|
249
|
-
if (!collections)
|
|
250
|
-
throw Error("Collections have not been initialised yet");
|
|
346
|
+
const resolveIdsFrom = useCallback((path: string): string => {
|
|
347
|
+
const collections = collectionsRef.current ?? [];
|
|
251
348
|
return resolveCollectionPathIds(path, collections);
|
|
252
|
-
}, [
|
|
253
|
-
|
|
254
|
-
const state = location.state as any;
|
|
255
|
-
/**
|
|
256
|
-
* The location can be overridden if `base_location` is set in the
|
|
257
|
-
* state field of the current location. This can happen if you open
|
|
258
|
-
* a side entity, like `products`, from a different one, like `users`
|
|
259
|
-
*/
|
|
260
|
-
const baseLocation = state && state.base_location ? state.base_location : location;
|
|
349
|
+
}, []);
|
|
261
350
|
|
|
262
351
|
const getAllParentReferencesForPath = useCallback((path: string): EntityReference[] => {
|
|
352
|
+
const collections = collectionsRef.current ?? [];
|
|
263
353
|
return getParentReferencesFromPath({
|
|
264
354
|
path,
|
|
265
355
|
collections
|
|
266
356
|
});
|
|
267
|
-
}, [
|
|
357
|
+
}, []);
|
|
268
358
|
|
|
269
359
|
const getParentCollectionIds = useCallback((path: string): string[] => {
|
|
270
360
|
|
|
@@ -279,35 +369,28 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
279
369
|
}
|
|
280
370
|
|
|
281
371
|
// for each odd path segment, get the collection
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
getCollectionFromPaths(oddPathSegments);
|
|
285
|
-
|
|
286
|
-
// const allParentCollectionsForPath = getAllParentReferencesForPath(path);
|
|
287
|
-
// console.log("allParentCollectionsForPath", allParentCollectionsForPath);
|
|
288
|
-
// const parentCollectionIds = allParentCollectionsForPath.map(r => r.id);
|
|
289
|
-
console.log("getParentCollectionIds", path, parentCollectionIds);
|
|
290
|
-
return parentCollectionIds;
|
|
372
|
+
return result.map(r => getCollectionFromPaths(r)?.id).filter(Boolean) as string[];
|
|
291
373
|
}, [getAllParentReferencesForPath])
|
|
292
374
|
|
|
293
375
|
const convertIdsToPaths = useCallback((ids: string[]): string[] => {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
return paths;
|
|
376
|
+
const collections = collectionsRef.current;
|
|
377
|
+
let currentCollections = collections;
|
|
378
|
+
const paths: string[] = [];
|
|
379
|
+
for (let i = 0; i < ids.length; i++) {
|
|
380
|
+
const id = ids[i];
|
|
381
|
+
const collection: EntityCollection | undefined = currentCollections!.find(c => c.id === id);
|
|
382
|
+
if (!collection)
|
|
383
|
+
throw Error(`Collection with id ${id} not found`);
|
|
384
|
+
paths.push(collection.path);
|
|
385
|
+
currentCollections = collection.subcollections;
|
|
305
386
|
}
|
|
306
|
-
|
|
387
|
+
return paths;
|
|
388
|
+
}, [getCollectionFromIds]);
|
|
307
389
|
|
|
308
390
|
return {
|
|
309
|
-
collections,
|
|
310
|
-
views,
|
|
391
|
+
collections: collectionsRef.current,
|
|
392
|
+
views: viewsRef.current,
|
|
393
|
+
adminViews: adminViewsRef.current,
|
|
311
394
|
loading: !initialised || navigationLoading,
|
|
312
395
|
navigationLoadingError,
|
|
313
396
|
homeUrl,
|
|
@@ -320,25 +403,16 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
320
403
|
isUrlCollectionPath,
|
|
321
404
|
urlPathToDataPath,
|
|
322
405
|
buildUrlCollectionPath,
|
|
323
|
-
|
|
324
|
-
buildCMSUrlPath,
|
|
325
|
-
resolveAliasesFrom,
|
|
406
|
+
resolveIdsFrom,
|
|
326
407
|
topLevelNavigation,
|
|
327
|
-
baseLocation,
|
|
328
408
|
refreshNavigation,
|
|
329
409
|
getParentReferencesFromPath: getAllParentReferencesForPath,
|
|
330
410
|
getParentCollectionIds,
|
|
331
|
-
convertIdsToPaths
|
|
411
|
+
convertIdsToPaths,
|
|
412
|
+
navigate,
|
|
332
413
|
};
|
|
333
414
|
}
|
|
334
415
|
|
|
335
|
-
export function getSidePanelKey(path: string, entityId?: string) {
|
|
336
|
-
if (entityId)
|
|
337
|
-
return `${removeInitialAndTrailingSlashes(path)}/${removeInitialAndTrailingSlashes(entityId)}`;
|
|
338
|
-
else
|
|
339
|
-
return removeInitialAndTrailingSlashes(path);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
416
|
function encodePath(input: string) {
|
|
343
417
|
return encodeURIComponent(removeInitialAndTrailingSlashes(input))
|
|
344
418
|
.replaceAll("%2F", "/")
|
|
@@ -347,10 +421,11 @@ function encodePath(input: string) {
|
|
|
347
421
|
|
|
348
422
|
function filterOutNotAllowedCollections(resolvedCollections: EntityCollection[], authController: AuthController<User>): EntityCollection[] {
|
|
349
423
|
return resolvedCollections
|
|
424
|
+
.filter((c) => Boolean(c.path))
|
|
350
425
|
.filter((c) => {
|
|
351
426
|
if (!c.permissions) return true;
|
|
352
|
-
const resolvedPermissions = resolvePermissions(c, authController,
|
|
353
|
-
return resolvedPermissions
|
|
427
|
+
const resolvedPermissions = resolvePermissions(c, authController, c.path, null);
|
|
428
|
+
return resolvedPermissions?.read !== false;
|
|
354
429
|
})
|
|
355
430
|
.map((c) => {
|
|
356
431
|
if (!c.subcollections) return c;
|
|
@@ -362,9 +437,10 @@ function filterOutNotAllowedCollections(resolvedCollections: EntityCollection[],
|
|
|
362
437
|
}
|
|
363
438
|
|
|
364
439
|
async function resolveCollections(collections: undefined | EntityCollection[] | EntityCollectionsBuilder<any>,
|
|
440
|
+
collectionPermissions: PermissionsBuilder | undefined,
|
|
365
441
|
authController: AuthController,
|
|
366
442
|
dataSource: DataSourceDelegate,
|
|
367
|
-
injectCollections?: (collections: EntityCollection[]) => EntityCollection[]) {
|
|
443
|
+
injectCollections?: (collections: EntityCollection[]) => EntityCollection[]): Promise<EntityCollection[]> {
|
|
368
444
|
let resolvedCollections: EntityCollection[] = [];
|
|
369
445
|
if (typeof collections === "function") {
|
|
370
446
|
resolvedCollections = await collections({
|
|
@@ -376,12 +452,12 @@ async function resolveCollections(collections: undefined | EntityCollection[] |
|
|
|
376
452
|
resolvedCollections = collections;
|
|
377
453
|
}
|
|
378
454
|
|
|
379
|
-
resolvedCollections = filterOutNotAllowedCollections(resolvedCollections, authController);
|
|
380
|
-
|
|
381
455
|
if (injectCollections) {
|
|
382
456
|
resolvedCollections = injectCollections(resolvedCollections ?? []);
|
|
383
457
|
}
|
|
384
458
|
|
|
459
|
+
resolvedCollections = applyPermissionsFunctionIfEmpty(resolvedCollections, collectionPermissions);
|
|
460
|
+
resolvedCollections = filterOutNotAllowedCollections(resolvedCollections, authController);
|
|
385
461
|
return resolvedCollections;
|
|
386
462
|
}
|
|
387
463
|
|
|
@@ -398,3 +474,88 @@ async function resolveCMSViews(baseViews: CMSView[] | CMSViewsBuilder | undefine
|
|
|
398
474
|
}
|
|
399
475
|
return resolvedViews;
|
|
400
476
|
}
|
|
477
|
+
|
|
478
|
+
function getGroup(collectionOrView: EntityCollection<any, any> | CMSView) {
|
|
479
|
+
const trimmed = collectionOrView.group?.trim();
|
|
480
|
+
if (!trimmed || trimmed === "") {
|
|
481
|
+
return "Views";
|
|
482
|
+
}
|
|
483
|
+
return trimmed ?? "Views";
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function areCollectionListsEqual(a: EntityCollection[], b: EntityCollection[]) {
|
|
487
|
+
if (a.length !== b.length) {
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
const aCopy = [...a];
|
|
491
|
+
const bCopy = [...b];
|
|
492
|
+
const aSorted = aCopy.sort((x, y) => x.id.localeCompare(y.id));
|
|
493
|
+
const bSorted = bCopy.sort((x, y) => x.id.localeCompare(y.id));
|
|
494
|
+
return aSorted.every((value, index) => areCollectionsEqual(value, bSorted[index]));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function areCollectionsEqual(a: EntityCollection, b: EntityCollection) {
|
|
498
|
+
const {
|
|
499
|
+
subcollections: subcollectionsA,
|
|
500
|
+
...restA
|
|
501
|
+
} = a;
|
|
502
|
+
const {
|
|
503
|
+
subcollections: subcollectionsB,
|
|
504
|
+
...restB
|
|
505
|
+
} = b;
|
|
506
|
+
if (!areCollectionListsEqual(subcollectionsA ?? [], subcollectionsB ?? [])) {
|
|
507
|
+
return false;
|
|
508
|
+
}
|
|
509
|
+
return equal(removeFunctions(restA), removeFunctions(restB));
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function useCustomBlocker(): NavigationBlocker {
|
|
513
|
+
const [blockListeners, setBlockListeners] = useState<Record<string, {
|
|
514
|
+
block: boolean,
|
|
515
|
+
basePath?: string
|
|
516
|
+
}>>({});
|
|
517
|
+
|
|
518
|
+
const shouldBlock = Object.values(blockListeners).some(b => b.block);
|
|
519
|
+
|
|
520
|
+
let blocker: any;
|
|
521
|
+
try {
|
|
522
|
+
blocker = useBlocker(({
|
|
523
|
+
nextLocation
|
|
524
|
+
}) => {
|
|
525
|
+
const allBasePaths = Object.values(blockListeners).map(b => b.basePath).filter(Boolean) as string[];
|
|
526
|
+
if (allBasePaths && allBasePaths.some(path => nextLocation.pathname.startsWith(path)))
|
|
527
|
+
return false;
|
|
528
|
+
return shouldBlock;
|
|
529
|
+
});
|
|
530
|
+
} catch (e) {
|
|
531
|
+
console.warn("Blocker not available, navigation will not be blocked");
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const updateBlockListener = (path: string, block: boolean, basePath?: string) => {
|
|
535
|
+
setBlockListeners(prev => ({
|
|
536
|
+
...prev,
|
|
537
|
+
[path]: {
|
|
538
|
+
block,
|
|
539
|
+
basePath
|
|
540
|
+
}
|
|
541
|
+
}));
|
|
542
|
+
return () => setBlockListeners(prev => {
|
|
543
|
+
const {
|
|
544
|
+
[path]: removed,
|
|
545
|
+
...rest
|
|
546
|
+
} = prev;
|
|
547
|
+
return rest;
|
|
548
|
+
})
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
const isBlocked = (path: string) => {
|
|
552
|
+
return (blockListeners[path]?.block ?? false) && blocker?.state === "blocked";
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return {
|
|
556
|
+
updateBlockListener,
|
|
557
|
+
isBlocked,
|
|
558
|
+
proceed: blocker?.proceed,
|
|
559
|
+
reset: blocker?.reset
|
|
560
|
+
}
|
|
561
|
+
}
|
|
@@ -21,9 +21,9 @@ import React, { useEffect } from "react";
|
|
|
21
21
|
* @see FireCMSContext
|
|
22
22
|
* @group Hooks and utilities
|
|
23
23
|
*/
|
|
24
|
-
export const useFireCMSContext = <
|
|
24
|
+
export const useFireCMSContext = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): FireCMSContext<USER, AuthControllerType> => {
|
|
25
25
|
|
|
26
|
-
const authController = useAuthController<
|
|
26
|
+
const authController = useAuthController<USER, AuthControllerType>();
|
|
27
27
|
const sideDialogsController = useSideDialogsController();
|
|
28
28
|
const sideEntityController = useSideEntityController();
|
|
29
29
|
const navigation = useNavigationController();
|
|
@@ -35,7 +35,7 @@ export const useFireCMSContext = <UserType extends User = User, AuthControllerTy
|
|
|
35
35
|
const customizationController = useCustomizationController();
|
|
36
36
|
const analyticsController = useAnalyticsController();
|
|
37
37
|
|
|
38
|
-
const fireCMSContextRef = React.useRef<FireCMSContext<
|
|
38
|
+
const fireCMSContextRef = React.useRef<FireCMSContext<USER, AuthControllerType>>({
|
|
39
39
|
authController,
|
|
40
40
|
sideDialogsController,
|
|
41
41
|
sideEntityController,
|
|
@@ -68,9 +68,9 @@ export const useFireCMSContext = <UserType extends User = User, AuthControllerTy
|
|
|
68
68
|
return fireCMSContextRef.current;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
// export const useFireCMSContext = <
|
|
71
|
+
// export const useFireCMSContext = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): FireCMSContext<USER, AuthControllerType> => {
|
|
72
72
|
//
|
|
73
|
-
// const authController = useAuthController<
|
|
73
|
+
// const authController = useAuthController<USER, AuthControllerType>();
|
|
74
74
|
// const sideDialogsController = useSideDialogsController();
|
|
75
75
|
// const sideEntityController = useSideEntityController();
|
|
76
76
|
// const navigation = useNavigationController();
|
|
@@ -63,38 +63,3 @@ function checkLargeLayout(breakpoint: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" |
|
|
|
63
63
|
return false;
|
|
64
64
|
return window.matchMedia(`(min-width: ${breakpoints[breakpoint] + 1}px)`).matches;
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
// import { useEffect, useState } from "react";
|
|
68
|
-
//
|
|
69
|
-
// const breakpoints = {
|
|
70
|
-
// xs: 0,
|
|
71
|
-
// sm: 640,
|
|
72
|
-
// md: 768,
|
|
73
|
-
// lg: 1024,
|
|
74
|
-
// xl: 1280,
|
|
75
|
-
// "2xl": 1536,
|
|
76
|
-
// "3xl": 1920
|
|
77
|
-
// }
|
|
78
|
-
// export const useLargeLayout = (breakpoint: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" = "lg"): boolean => {
|
|
79
|
-
// const [isLargeLayout, setIsLargeLayout] = useState<boolean>(false);
|
|
80
|
-
//
|
|
81
|
-
// useEffect(() => {
|
|
82
|
-
// const handleResize = () => {
|
|
83
|
-
// const matched = window.matchMedia(`(min-width: ${breakpoints[breakpoint] + 1}px)`).matches;
|
|
84
|
-
// setIsLargeLayout(matched);
|
|
85
|
-
// };
|
|
86
|
-
//
|
|
87
|
-
// // Set initial state
|
|
88
|
-
// handleResize();
|
|
89
|
-
//
|
|
90
|
-
// // Set up event listener for resize events
|
|
91
|
-
// window.addEventListener("resize", handleResize);
|
|
92
|
-
//
|
|
93
|
-
// // Clean up event listener when component unmounts
|
|
94
|
-
// return () => {
|
|
95
|
-
// window.removeEventListener("resize", handleResize);
|
|
96
|
-
// };
|
|
97
|
-
// }, []);
|
|
98
|
-
//
|
|
99
|
-
// return isLargeLayout;
|
|
100
|
-
// };
|