@firecms/core 3.0.0 → 3.1.0-canary.02232f4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/components/AIIcon.d.ts +16 -0
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +7 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +14 -0
- package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +6 -0
- package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -4
- package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +6 -0
- package/dist/components/EntityCollectionTable/internal/popup_field/useDraggable.d.ts +2 -2
- package/dist/components/EntityCollectionView/Board.d.ts +2 -0
- package/dist/components/EntityCollectionView/BoardColumn.d.ts +42 -0
- package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +9 -0
- package/dist/components/EntityCollectionView/BoardSortableList.d.ts +14 -0
- package/dist/components/EntityCollectionView/CollectionDataErrorBanner.d.ts +4 -0
- package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +26 -0
- package/dist/components/EntityCollectionView/EntityCard.d.ts +19 -0
- package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +20 -0
- package/dist/components/EntityCollectionView/EntityCollectionCardView.d.ts +31 -0
- package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +2 -2
- package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +7 -3
- package/dist/components/EntityCollectionView/FiltersDialog.d.ts +14 -0
- package/dist/components/EntityCollectionView/ViewModeToggle.d.ts +44 -0
- package/dist/components/EntityCollectionView/board_types.d.ts +105 -0
- package/dist/components/EntityCollectionView/useBoardDataController.d.ts +60 -0
- package/dist/components/ErrorBoundary.d.ts +4 -2
- package/dist/components/HomePage/DefaultHomePage.d.ts +0 -1
- package/dist/components/LanguageToggle.d.ts +1 -0
- package/dist/components/SelectableTable/SelectableTable.d.ts +5 -1
- package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -1
- package/dist/components/UnsavedChangesDialog.d.ts +1 -0
- package/dist/components/VirtualTable/VirtualTable.performance.test.d.ts +1 -0
- package/dist/components/VirtualTable/VirtualTableCell.d.ts +6 -0
- package/dist/components/VirtualTable/VirtualTableHeader.d.ts +4 -1
- package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +17 -1
- package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +1 -0
- package/dist/components/VirtualTable/types.d.ts +3 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/contexts/index.d.ts +10 -0
- package/dist/core/DrawerNavigationGroup.d.ts +45 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/editor/components/SlashCommandMenu.d.ts +6 -0
- package/dist/editor/components/editor-bubble-item.d.ts +8 -0
- package/dist/editor/components/editor-bubble.d.ts +8 -0
- package/dist/editor/components/image-bubble.d.ts +5 -0
- package/dist/editor/components/index.d.ts +16 -0
- package/dist/editor/components/table-bubble.d.ts +5 -0
- package/dist/editor/editor.d.ts +30 -0
- package/dist/editor/extensions/HighlightDecorationExtension.d.ts +24 -0
- package/dist/editor/extensions/Image/index.d.ts +6 -0
- package/dist/editor/extensions/Image.d.ts +6 -0
- package/dist/editor/extensions/TextLoadingDecorationExtension.d.ts +16 -0
- package/dist/editor/extensions/clipboard.d.ts +7 -0
- package/dist/editor/extensions/custom-keymap.d.ts +1 -0
- package/dist/editor/extensions/drag-and-drop.d.ts +9 -0
- package/dist/editor/hooks/useProseMirror.d.ts +13 -0
- package/dist/editor/hooks/useProseMirrorContext.d.ts +9 -0
- package/dist/editor/index.d.ts +2 -0
- package/dist/editor/markdown.d.ts +5 -0
- package/dist/editor/nodeViews/ImageComponent.d.ts +3 -0
- package/dist/editor/nodeViews/ReactNodeView.d.ts +29 -0
- package/dist/editor/nodeViews/TaskItemComponent.d.ts +3 -0
- package/dist/editor/nodeViews/index.d.ts +6 -0
- package/dist/editor/plugins/index.d.ts +2 -0
- package/dist/editor/plugins/inputrules.d.ts +6 -0
- package/dist/editor/plugins/placeholderPlugin.d.ts +3 -0
- package/dist/editor/plugins/slashCommandPlugin.d.ts +12 -0
- package/dist/editor/schema.d.ts +2 -0
- package/dist/editor/selectors/ai-selector.d.ts +0 -0
- package/dist/editor/selectors/color-selector.d.ts +10 -0
- package/dist/editor/selectors/link-selector.d.ts +8 -0
- package/dist/editor/selectors/node-selector.d.ts +15 -0
- package/dist/editor/selectors/text-buttons.d.ts +1 -0
- package/dist/editor/types.d.ts +5 -0
- package/dist/editor/useProseMirror.d.ts +16 -0
- package/dist/editor/utils/prosemirror-utils.d.ts +6 -0
- package/dist/editor/utils/remove_classes.d.ts +1 -0
- package/dist/editor/utils/useDebouncedCallback.d.ts +1 -0
- package/dist/form/components/ErrorFocus.d.ts +1 -1
- package/dist/form/components/LocalChangesMenu.d.ts +2 -2
- package/dist/form/components/StorageUploadProgress.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
- package/dist/form/validation.d.ts +3 -2
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useBreadcrumbsController.d.ts +16 -0
- package/dist/hooks/useBuildNavigationController.d.ts +0 -1
- package/dist/hooks/useCollapsedGroups.d.ts +6 -3
- package/dist/hooks/useTranslation.d.ts +17 -0
- package/dist/i18n/FireCMSi18nProvider.d.ts +33 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.es.js +31028 -16080
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +29955 -15028
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useRestoreScroll.d.ts +1 -1
- package/dist/locales/de.d.ts +2 -0
- package/dist/locales/en.d.ts +10 -0
- package/dist/locales/es.d.ts +10 -0
- package/dist/locales/fr.d.ts +2 -0
- package/dist/locales/hi.d.ts +2 -0
- package/dist/locales/it.d.ts +2 -0
- package/dist/locales/pt.d.ts +7 -0
- package/dist/preview/PropertyPreviewProps.d.ts +5 -0
- package/dist/preview/components/DatePreview.d.ts +13 -3
- package/dist/preview/components/ImagePreview.d.ts +5 -1
- package/dist/preview/components/StorageThumbnail.d.ts +2 -1
- package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
- package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
- package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
- package/dist/types/analytics.d.ts +1 -1
- package/dist/types/collections.d.ts +88 -2
- package/dist/types/customization_controller.d.ts +2 -1
- package/dist/types/datasource.d.ts +0 -1
- package/dist/types/entities.d.ts +1 -0
- package/dist/types/firecms.d.ts +2 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/navigation.d.ts +2 -2
- package/dist/types/plugins.d.ts +69 -1
- package/dist/types/properties.d.ts +277 -12
- package/dist/types/storage.d.ts +9 -0
- package/dist/types/translations.d.ts +669 -0
- package/dist/util/__tests__/conditions.test.d.ts +1 -0
- package/dist/util/__tests__/objects.test.d.ts +1 -0
- package/dist/util/conditions.d.ts +26 -0
- package/dist/util/entities.d.ts +2 -3
- package/dist/util/index.d.ts +3 -1
- package/dist/util/lazy_eager.d.ts +7 -0
- package/dist/util/objects.d.ts +1 -0
- package/dist/util/property_utils.d.ts +2 -1
- package/dist/util/resolutions.d.ts +3 -3
- package/dist/util/useStorageUploadController.d.ts +11 -2
- package/package.json +52 -12
- package/src/app/Scaffold.tsx +20 -19
- package/src/components/AIIcon.tsx +41 -0
- package/src/components/ArrayContainer.tsx +7 -8
- package/src/components/ClearFilterSortButton.tsx +25 -19
- package/src/components/ConfirmationDialog.tsx +4 -4
- package/src/components/DeleteEntityDialog.tsx +12 -11
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +82 -43
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +130 -79
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +121 -104
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +132 -103
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +6 -3
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +24 -44
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +90 -49
- package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -2
- package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +11 -11
- package/src/components/EntityCollectionView/Board.tsx +324 -0
- package/src/components/EntityCollectionView/BoardColumn.tsx +158 -0
- package/src/components/EntityCollectionView/BoardColumnTitle.tsx +45 -0
- package/src/components/EntityCollectionView/BoardSortableList.tsx +174 -0
- package/src/components/EntityCollectionView/CollectionDataErrorBanner.tsx +43 -0
- package/src/components/EntityCollectionView/EntityBoardCard.tsx +212 -0
- package/src/components/EntityCollectionView/EntityCard.tsx +235 -0
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +706 -0
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +236 -0
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +531 -209
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +35 -22
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +86 -15
- package/src/components/EntityCollectionView/FiltersDialog.tsx +252 -0
- package/src/components/EntityCollectionView/ViewModeToggle.tsx +202 -0
- package/src/components/EntityCollectionView/board_types.ts +113 -0
- package/src/components/EntityCollectionView/useBoardDataController.tsx +490 -0
- package/src/components/EntityJsonPreview.tsx +2 -1
- package/src/components/EntityPreview.tsx +1 -1
- package/src/components/EntityView.tsx +3 -2
- package/src/components/ErrorBoundary.tsx +27 -15
- package/src/components/ErrorTooltip.tsx +2 -1
- package/src/components/HomePage/DefaultHomePage.tsx +65 -22
- package/src/components/HomePage/HomePageDnD.tsx +59 -42
- package/src/components/HomePage/NavigationCard.tsx +20 -18
- package/src/components/HomePage/NavigationGroup.tsx +20 -17
- package/src/components/HomePage/RenameGroupDialog.tsx +15 -15
- package/src/components/HomePage/SmallNavigationCard.tsx +10 -9
- package/src/components/LanguageToggle.tsx +66 -0
- package/src/components/NotFoundPage.tsx +5 -3
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +12 -17
- package/src/components/ReferenceWidget.tsx +5 -6
- package/src/components/SearchIconsView.tsx +3 -1
- package/src/components/SelectableTable/SelectableTable.tsx +75 -67
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +7 -6
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +50 -40
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +53 -40
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +60 -58
- package/src/components/UnsavedChangesDialog.tsx +6 -6
- package/src/components/UserDisplay.tsx +4 -4
- package/src/components/VirtualTable/VirtualTable.performance.test.tsx +387 -0
- package/src/components/VirtualTable/VirtualTable.tsx +277 -121
- package/src/components/VirtualTable/VirtualTableCell.tsx +18 -2
- package/src/components/VirtualTable/VirtualTableHeader.tsx +76 -64
- package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +163 -42
- package/src/components/VirtualTable/VirtualTableProps.tsx +21 -2
- package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -0
- package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +19 -6
- package/src/components/VirtualTable/types.tsx +3 -0
- package/src/components/common/default_entity_actions.tsx +4 -0
- package/src/components/common/useColumnsIds.tsx +95 -3
- package/src/components/common/useDataSourceTableController.tsx +12 -4
- package/src/components/index.tsx +5 -0
- package/src/contexts/BreacrumbsContext.tsx +15 -8
- package/src/contexts/index.ts +10 -0
- package/src/core/DefaultAppBar.tsx +49 -32
- package/src/core/DefaultDrawer.tsx +49 -57
- package/src/core/DrawerNavigationGroup.tsx +120 -0
- package/src/core/DrawerNavigationItem.tsx +4 -3
- package/src/core/EntityEditView.tsx +94 -50
- package/src/core/EntityEditViewFormActions.tsx +24 -17
- package/src/core/EntitySidePanel.tsx +34 -30
- package/src/core/FireCMS.tsx +33 -6
- package/src/core/SideDialogs.tsx +4 -2
- package/src/core/field_configs.tsx +18 -11
- package/src/core/index.tsx +1 -0
- package/src/editor/components/SlashCommandMenu.tsx +516 -0
- package/src/editor/components/editor-bubble-item.tsx +32 -0
- package/src/editor/components/editor-bubble.tsx +118 -0
- package/src/editor/components/image-bubble.tsx +156 -0
- package/src/editor/components/index.ts +14 -0
- package/src/editor/components/table-bubble.tsx +165 -0
- package/src/editor/editor.tsx +455 -0
- package/src/editor/extensions/HighlightDecorationExtension.ts +114 -0
- package/src/editor/extensions/Image/index.ts +133 -0
- package/src/editor/extensions/Image.ts +159 -0
- package/src/editor/extensions/TextLoadingDecorationExtension.tsx +107 -0
- package/src/editor/extensions/clipboard.ts +72 -0
- package/src/editor/extensions/custom-keymap.ts +24 -0
- package/src/editor/extensions/drag-and-drop.tsx +480 -0
- package/src/editor/hooks/useProseMirror.ts +124 -0
- package/src/editor/hooks/useProseMirrorContext.ts +15 -0
- package/src/editor/index.ts +2 -0
- package/src/editor/markdown.ts +172 -0
- package/src/editor/nodeViews/ImageComponent.tsx +20 -0
- package/src/editor/nodeViews/ReactNodeView.tsx +89 -0
- package/src/editor/nodeViews/TaskItemComponent.tsx +29 -0
- package/src/editor/nodeViews/index.ts +35 -0
- package/src/editor/plugins/index.ts +58 -0
- package/src/editor/plugins/inputrules.ts +82 -0
- package/src/editor/plugins/placeholderPlugin.ts +55 -0
- package/src/editor/plugins/slashCommandPlugin.ts +61 -0
- package/src/editor/schema.ts +240 -0
- package/src/editor/selectors/ai-selector.tsx +111 -0
- package/src/editor/selectors/color-selector.tsx +200 -0
- package/src/editor/selectors/link-selector.tsx +118 -0
- package/src/editor/selectors/node-selector.tsx +157 -0
- package/src/editor/selectors/text-buttons.tsx +86 -0
- package/src/editor/types.ts +6 -0
- package/src/editor/useProseMirror.ts +126 -0
- package/src/editor/utils/prosemirror-utils.ts +108 -0
- package/src/editor/utils/remove_classes.ts +17 -0
- package/src/editor/utils/useDebouncedCallback.ts +25 -0
- package/src/form/EntityForm.tsx +150 -75
- package/src/form/EntityFormActions.tsx +19 -12
- package/src/form/PropertyFieldBinding.tsx +68 -51
- package/src/form/components/ErrorFocus.tsx +3 -3
- package/src/form/components/LocalChangesMenu.tsx +19 -19
- package/src/form/components/StorageItemPreview.tsx +5 -3
- package/src/form/components/StorageUploadProgress.tsx +22 -6
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +18 -5
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +22 -10
- package/src/form/field_bindings/BlockFieldBinding.tsx +26 -9
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -17
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +46 -25
- package/src/form/field_bindings/MapFieldBinding.tsx +88 -70
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +93 -52
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +15 -1
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +25 -11
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +25 -11
- package/src/form/field_bindings/RepeatFieldBinding.tsx +21 -6
- package/src/form/field_bindings/SelectFieldBinding.tsx +7 -5
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +110 -92
- package/src/form/field_bindings/SwitchFieldBinding.tsx +31 -14
- package/src/form/field_bindings/TextFieldBinding.tsx +77 -38
- package/src/form/field_bindings/UserSelectFieldBinding.tsx +7 -5
- package/src/form/validation.ts +245 -160
- package/src/hooks/index.tsx +1 -0
- package/src/hooks/useBreadcrumbsController.tsx +18 -0
- package/src/hooks/useBuildNavigationController.tsx +91 -41
- package/src/hooks/useCollapsedGroups.ts +18 -9
- package/src/hooks/useTranslation.ts +31 -0
- package/src/hooks/useValidateAuthenticator.tsx +1 -1
- package/src/i18n/FireCMSi18nProvider.tsx +160 -0
- package/src/index.ts +5 -0
- package/src/internal/useBuildDataSource.ts +68 -34
- package/src/internal/useBuildSideDialogsController.tsx +11 -8
- package/src/internal/useBuildSideEntityController.tsx +24 -24
- package/src/internal/useRestoreScroll.tsx +26 -14
- package/src/locales/de.ts +718 -0
- package/src/locales/en.ts +730 -0
- package/src/locales/es.ts +730 -0
- package/src/locales/fr.ts +718 -0
- package/src/locales/hi.ts +718 -0
- package/src/locales/it.ts +718 -0
- package/src/locales/pt.ts +727 -0
- package/src/preview/PropertyPreview.tsx +43 -33
- package/src/preview/PropertyPreviewProps.tsx +6 -0
- package/src/preview/components/DatePreview.tsx +72 -4
- package/src/preview/components/EmptyValue.tsx +1 -1
- package/src/preview/components/ImagePreview.tsx +37 -21
- package/src/preview/components/ReferencePreview.tsx +8 -2
- package/src/preview/components/StorageThumbnail.tsx +16 -12
- package/src/preview/components/UrlComponentPreview.tsx +32 -27
- package/src/preview/components/UserPreview.tsx +3 -1
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +9 -7
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +11 -9
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +26 -24
- package/src/preview/property_previews/MapPropertyPreview.tsx +49 -27
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +61 -56
- package/src/routes/CustomCMSRoute.tsx +1 -0
- package/src/routes/FireCMSRoute.tsx +87 -65
- package/src/types/analytics.ts +10 -0
- package/src/types/collections.ts +97 -3
- package/src/types/customization_controller.tsx +2 -1
- package/src/types/datasource.ts +54 -56
- package/src/types/entities.ts +10 -0
- package/src/types/firecms.tsx +2 -1
- package/src/types/index.ts +1 -0
- package/src/types/navigation.ts +2 -2
- package/src/types/plugins.tsx +77 -1
- package/src/types/properties.ts +369 -37
- package/src/types/storage.ts +11 -1
- package/src/types/translations.ts +752 -0
- package/src/util/__tests__/conditions.test.ts +506 -0
- package/src/util/__tests__/objects.test.ts +196 -0
- package/src/util/callbacks.ts +6 -3
- package/src/util/collections.ts +51 -6
- package/src/util/conditions.ts +339 -0
- package/src/util/entities.ts +29 -30
- package/src/util/entity_cache.ts +2 -1
- package/src/util/index.ts +3 -1
- package/src/util/join_collections.ts +10 -8
- package/src/util/lazy_eager.tsx +33 -0
- package/src/util/objects.ts +46 -13
- package/src/util/{references.ts → previews.ts} +16 -2
- package/src/util/property_utils.tsx +37 -11
- package/src/util/resolutions.ts +62 -58
- package/src/util/useStorageUploadController.tsx +34 -30
- /package/dist/util/{references.d.ts → previews.d.ts} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
2
|
import { EntityCollection, ResolvedEntityCollection, ResolvedProperty } from "../../types";
|
|
3
|
+
import { getPropertyInPath } from "../../util";
|
|
3
4
|
import { getSubcollectionColumnId } from "../EntityCollectionTable/internal/common";
|
|
4
5
|
import { PropertyColumnConfig } from "../EntityCollectionTable/EntityCollectionTableProps";
|
|
5
6
|
|
|
@@ -16,15 +17,45 @@ export function useColumnIds<M extends Record<string, any>>(collection: Resolved
|
|
|
16
17
|
|
|
17
18
|
function hideAndExpandKeys<M extends Record<string, any>>(collection: ResolvedEntityCollection<M>, keys: string[]): PropertyColumnConfig[] {
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
// First, figure out which spread map roots have individual child keys in the order
|
|
21
|
+
// If so, we should NOT auto-expand them - just use the explicit child keys
|
|
22
|
+
const rootsWithExplicitChildren = new Set<string>();
|
|
23
|
+
for (const key of keys) {
|
|
24
|
+
if (key.includes(".")) {
|
|
25
|
+
const rootKey = key.split(".")[0];
|
|
26
|
+
const rootProperty = collection.properties[rootKey];
|
|
27
|
+
if (rootProperty && rootProperty.dataType === "map" && rootProperty.spreadChildren && rootProperty.properties) {
|
|
28
|
+
rootsWithExplicitChildren.add(rootKey);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Track processed keys to avoid duplicates
|
|
34
|
+
const processedPropertyKeys = new Set<string>();
|
|
35
|
+
|
|
36
|
+
const result = keys.flatMap((key) => {
|
|
37
|
+
// Skip if already processed (handles duplicates in propertiesOrder)
|
|
38
|
+
if (processedPropertyKeys.has(key)) return [null];
|
|
39
|
+
|
|
40
|
+
// Check if it's a top-level property
|
|
20
41
|
const property = collection.properties[key];
|
|
21
42
|
if (property) {
|
|
43
|
+
processedPropertyKeys.add(key);
|
|
22
44
|
if (property.hideFromCollection)
|
|
23
45
|
return [null];
|
|
24
46
|
if (property.disabled && typeof property.disabled === "object" && property.disabled.hidden)
|
|
25
47
|
return [null];
|
|
48
|
+
|
|
26
49
|
if (property.dataType === "map" && property.spreadChildren && property.properties) {
|
|
27
|
-
|
|
50
|
+
// Check if this spread map has explicit child keys in propertiesOrder
|
|
51
|
+
if (rootsWithExplicitChildren.has(key)) {
|
|
52
|
+
// DON'T auto-expand - the children are explicitly listed elsewhere
|
|
53
|
+
return [null];
|
|
54
|
+
}
|
|
55
|
+
// Auto-expand all children
|
|
56
|
+
const childConfigs = getColumnKeysForProperty(property, key);
|
|
57
|
+
childConfigs.forEach(c => processedPropertyKeys.add(c.key));
|
|
58
|
+
return childConfigs;
|
|
28
59
|
}
|
|
29
60
|
return [{
|
|
30
61
|
key,
|
|
@@ -32,6 +63,33 @@ function hideAndExpandKeys<M extends Record<string, any>>(collection: ResolvedEn
|
|
|
32
63
|
}];
|
|
33
64
|
}
|
|
34
65
|
|
|
66
|
+
// Check if it's a nested key like "data.mode" (for spread map properties)
|
|
67
|
+
if (key.includes(".")) {
|
|
68
|
+
const rootKey = key.split(".")[0];
|
|
69
|
+
const rootProperty = collection.properties[rootKey];
|
|
70
|
+
|
|
71
|
+
if (rootProperty && rootProperty.dataType === "map" && rootProperty.properties) {
|
|
72
|
+
const nestedProperty = getPropertyInPath(collection.properties, key) as ResolvedProperty | undefined;
|
|
73
|
+
if (nestedProperty) {
|
|
74
|
+
processedPropertyKeys.add(key);
|
|
75
|
+
// Mark root as seen
|
|
76
|
+
processedPropertyKeys.add(rootKey);
|
|
77
|
+
|
|
78
|
+
if (nestedProperty.hideFromCollection)
|
|
79
|
+
return [null];
|
|
80
|
+
if (nestedProperty.disabled && typeof nestedProperty.disabled === "object" && nestedProperty.disabled.hidden)
|
|
81
|
+
return [null];
|
|
82
|
+
|
|
83
|
+
return [{
|
|
84
|
+
key,
|
|
85
|
+
disabled: Boolean(rootProperty.disabled) || Boolean(rootProperty.readOnly) ||
|
|
86
|
+
Boolean(nestedProperty.disabled) || Boolean(nestedProperty.readOnly)
|
|
87
|
+
}];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Check additional fields
|
|
35
93
|
const additionalField = collection.additionalFields?.find(field => field.key === key);
|
|
36
94
|
if (additionalField) {
|
|
37
95
|
return [{
|
|
@@ -40,6 +98,7 @@ function hideAndExpandKeys<M extends Record<string, any>>(collection: ResolvedEn
|
|
|
40
98
|
}];
|
|
41
99
|
}
|
|
42
100
|
|
|
101
|
+
// Check subcollections
|
|
43
102
|
if (collection.subcollections) {
|
|
44
103
|
const subCollection = collection.subcollections.find(subCol => getSubcollectionColumnId(subCol) === key);
|
|
45
104
|
if (subCollection) {
|
|
@@ -50,6 +109,7 @@ function hideAndExpandKeys<M extends Record<string, any>>(collection: ResolvedEn
|
|
|
50
109
|
}
|
|
51
110
|
}
|
|
52
111
|
|
|
112
|
+
// Check collection group parent
|
|
53
113
|
if (collection.collectionGroup && key === COLLECTION_GROUP_PARENT_ID) {
|
|
54
114
|
return [{
|
|
55
115
|
key,
|
|
@@ -59,6 +119,37 @@ function hideAndExpandKeys<M extends Record<string, any>>(collection: ResolvedEn
|
|
|
59
119
|
|
|
60
120
|
return [null];
|
|
61
121
|
}).filter(Boolean) as PropertyColumnConfig[];
|
|
122
|
+
|
|
123
|
+
// Add any missing properties that weren't in propertiesOrder
|
|
124
|
+
// This ensures properties NEVER disappear
|
|
125
|
+
for (const propKey of Object.keys(collection.properties)) {
|
|
126
|
+
// Skip if already processed
|
|
127
|
+
if (processedPropertyKeys.has(propKey)) continue;
|
|
128
|
+
|
|
129
|
+
const property = collection.properties[propKey];
|
|
130
|
+
if (!property) continue;
|
|
131
|
+
if (property.hideFromCollection) continue;
|
|
132
|
+
if (property.disabled && typeof property.disabled === "object" && property.disabled.hidden) continue;
|
|
133
|
+
|
|
134
|
+
if (property.dataType === "map" && property.spreadChildren && property.properties) {
|
|
135
|
+
// For spread maps, add all children that weren't already added
|
|
136
|
+
const allChildConfigs = getColumnKeysForProperty(property, propKey);
|
|
137
|
+
for (const childConfig of allChildConfigs) {
|
|
138
|
+
if (!processedPropertyKeys.has(childConfig.key)) {
|
|
139
|
+
result.push(childConfig);
|
|
140
|
+
processedPropertyKeys.add(childConfig.key);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
result.push({
|
|
145
|
+
key: propKey,
|
|
146
|
+
disabled: Boolean(property.disabled) || Boolean(property.readOnly)
|
|
147
|
+
});
|
|
148
|
+
processedPropertyKeys.add(propKey);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return result;
|
|
62
153
|
}
|
|
63
154
|
|
|
64
155
|
function getDefaultColumnKeys<M extends Record<string, any> = any>(collection: ResolvedEntityCollection<M>, includeSubCollections: boolean) {
|
|
@@ -69,7 +160,8 @@ function getDefaultColumnKeys<M extends Record<string, any> = any>(collection: R
|
|
|
69
160
|
|
|
70
161
|
const columnIds: string[] = [
|
|
71
162
|
...propertyKeys,
|
|
72
|
-
|
|
163
|
+
// Filter out additional fields whose key already exists in propertyKeys to avoid duplicate column keys
|
|
164
|
+
...additionalFields.filter((field) => !propertyKeys.includes(field.key)).map((field) => field.key)
|
|
73
165
|
];
|
|
74
166
|
|
|
75
167
|
if (includeSubCollections) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { useLocation } from "react-router-dom";
|
|
2
3
|
|
|
3
4
|
import { useDataSource, useFireCMSContext, useNavigationController } from "../../hooks";
|
|
4
5
|
import { useDataOrder } from "../../hooks/data/useDataOrder";
|
|
@@ -94,7 +95,7 @@ export function useDataSourceTableController<M extends Record<string, any> = any
|
|
|
94
95
|
const [searchString, setSearchString] = React.useState<string | undefined>();
|
|
95
96
|
|
|
96
97
|
const checkFilterCombination = useCallback((filterValues: FilterValues<any>,
|
|
97
|
-
|
|
98
|
+
sortBy?: [string, "asc" | "desc"]) => {
|
|
98
99
|
if (!dataSource.isFilterCombinationValid)
|
|
99
100
|
return true;
|
|
100
101
|
return dataSource.isFilterCombinationValid({
|
|
@@ -106,8 +107,8 @@ export function useDataSourceTableController<M extends Record<string, any> = any
|
|
|
106
107
|
}, []);
|
|
107
108
|
|
|
108
109
|
const onScroll = ({
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
scrollOffset
|
|
111
|
+
}: {
|
|
111
112
|
scrollOffset: number
|
|
112
113
|
}) => {
|
|
113
114
|
if (scrollRestoration) {
|
|
@@ -128,10 +129,12 @@ export function useDataSourceTableController<M extends Record<string, any> = any
|
|
|
128
129
|
return initialSort;
|
|
129
130
|
}, [initialSort, forceFilter]);
|
|
130
131
|
|
|
132
|
+
const location = useLocation();
|
|
133
|
+
|
|
131
134
|
const {
|
|
132
135
|
filterValues: initialFilterUrl,
|
|
133
136
|
sortBy: initialSortUrl,
|
|
134
|
-
} = parseFilterAndSort(
|
|
137
|
+
} = parseFilterAndSort(location.search);
|
|
135
138
|
|
|
136
139
|
const [filterValues, setFilterValues] = React.useState<FilterValues<Extract<keyof M, string>> | undefined>(forceFilter ?? (updateUrl ? initialFilterUrl : undefined) ?? initialFilter ?? undefined);
|
|
137
140
|
const [sortBy, setSortBy] = React.useState<[Extract<keyof M, string>, "asc" | "desc"] | undefined>((updateUrl ? initialSortUrl : undefined) ?? initialSortInternal);
|
|
@@ -328,6 +331,11 @@ function encodeFilterAndSort(filterValues?: FilterValues<string>, sortBy?: [stri
|
|
|
328
331
|
} else if (val instanceof EntityReference) {
|
|
329
332
|
encodedValue = encodeRef(val);
|
|
330
333
|
}
|
|
334
|
+
} else if (typeof val === "string") {
|
|
335
|
+
// JSON.stringify wraps the string in quotes (e.g. "4" → '"4"')
|
|
336
|
+
// so that decodeString's JSON.parse restores the string type,
|
|
337
|
+
// not a number. Without this, "4" round-trips as the number 4.
|
|
338
|
+
encodedValue = JSON.stringify(val);
|
|
331
339
|
}
|
|
332
340
|
} catch (e) {
|
|
333
341
|
encodedValue = val;
|
package/src/components/index.tsx
CHANGED
|
@@ -16,6 +16,8 @@ export * from "./SelectableTable/SelectableTable";
|
|
|
16
16
|
export * from "./SelectableTable/SelectableTableContext";
|
|
17
17
|
export * from "./EntityCollectionView/EntityCollectionView";
|
|
18
18
|
export * from "./EntityCollectionView/EntityCollectionViewActions";
|
|
19
|
+
export * from "./EntityCollectionView/EntityCollectionCardView";
|
|
20
|
+
export * from "./EntityCollectionView/EntityCard";
|
|
19
21
|
export * from "./EntityCollectionView/useSelectionController";
|
|
20
22
|
|
|
21
23
|
export * from "./PropertyConfigBadge";
|
|
@@ -38,3 +40,6 @@ export * from "./SearchIconsView";
|
|
|
38
40
|
export * from "./FieldCaption";
|
|
39
41
|
|
|
40
42
|
export * from "./EntityPreview";
|
|
43
|
+
|
|
44
|
+
export * from "./AIIcon";
|
|
45
|
+
export * from "./LanguageToggle";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
1
|
+
import React, { useCallback, useState } from "react";
|
|
2
2
|
import { BreadcrumbEntry, BreadcrumbsController } from "../hooks/useBreadcrumbsController";
|
|
3
3
|
|
|
4
|
-
const DEFAULT_BREADCRUMBS_CONTROLLER = {
|
|
4
|
+
const DEFAULT_BREADCRUMBS_CONTROLLER: BreadcrumbsController = {
|
|
5
5
|
breadcrumbs: [],
|
|
6
|
-
set: (
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
set: () => {
|
|
7
|
+
},
|
|
8
|
+
updateCount: () => {
|
|
9
9
|
}
|
|
10
10
|
};
|
|
11
11
|
|
|
@@ -19,17 +19,24 @@ export const BreadcrumbsProvider: React.FC<BreadcrumbsProviderProps> = ({ childr
|
|
|
19
19
|
|
|
20
20
|
const [breadcrumbs, setBreadcrumbs] = useState<BreadcrumbEntry[]>([]);
|
|
21
21
|
|
|
22
|
-
const set = (props: {
|
|
22
|
+
const set = useCallback((props: {
|
|
23
23
|
breadcrumbs: BreadcrumbEntry[];
|
|
24
24
|
}) => {
|
|
25
25
|
setBreadcrumbs(props.breadcrumbs);
|
|
26
|
-
};
|
|
26
|
+
}, []);
|
|
27
|
+
|
|
28
|
+
const updateCount = useCallback((id: string, count: number | null | undefined) => {
|
|
29
|
+
setBreadcrumbs(prev => prev.map(entry =>
|
|
30
|
+
entry.id === id ? { ...entry, count } : entry
|
|
31
|
+
));
|
|
32
|
+
}, []);
|
|
27
33
|
|
|
28
34
|
return (
|
|
29
35
|
<BreadcrumbContext.Provider
|
|
30
36
|
value={{
|
|
31
37
|
breadcrumbs,
|
|
32
|
-
set
|
|
38
|
+
set,
|
|
39
|
+
updateCount
|
|
33
40
|
}}
|
|
34
41
|
>
|
|
35
42
|
{children}
|
package/src/contexts/index.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
export * from "./SnackbarProvider";
|
|
2
2
|
export * from "./ModeController";
|
|
3
3
|
export * from "./AuthControllerContext";
|
|
4
|
+
export * from "./DataSourceContext";
|
|
5
|
+
export * from "./NavigationContext";
|
|
6
|
+
export * from "./CustomizationControllerContext";
|
|
7
|
+
export * from "./SideEntityControllerContext";
|
|
8
|
+
export * from "./SideDialogsControllerContext";
|
|
9
|
+
export * from "./AnalyticsContext";
|
|
10
|
+
export * from "./StorageSourceContext";
|
|
11
|
+
export * from "./UserConfigurationPersistenceContext";
|
|
12
|
+
export * from "./DialogsProvider";
|
|
13
|
+
export * from "./InternalUserManagementContext";
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
import { Link, useNavigate } from "react-router-dom";
|
|
4
|
-
import { ErrorBoundary, FireCMSLogo } from "../components";
|
|
4
|
+
import { ErrorBoundary, FireCMSLogo, LanguageToggle } from "../components";
|
|
5
5
|
import {
|
|
6
6
|
Avatar,
|
|
7
7
|
BrightnessMediumIcon,
|
|
8
|
+
CheckIcon,
|
|
8
9
|
cls,
|
|
9
10
|
DarkModeIcon,
|
|
10
11
|
IconButton,
|
|
@@ -15,7 +16,7 @@ import {
|
|
|
15
16
|
Skeleton,
|
|
16
17
|
Typography
|
|
17
18
|
} from "@firecms/ui";
|
|
18
|
-
import { useAuthController, useLargeLayout, useModeController, useNavigationController } from "../hooks";
|
|
19
|
+
import { useAuthController, useLargeLayout, useModeController, useNavigationController, useTranslation } from "../hooks";
|
|
19
20
|
import { User } from "../types";
|
|
20
21
|
import { useApp } from "../app/useApp";
|
|
21
22
|
import { useBreadcrumbsController } from "../hooks/useBreadcrumbsController";
|
|
@@ -57,16 +58,16 @@ export type DefaultAppBarProps<ADDITIONAL_PROPS = object> = {
|
|
|
57
58
|
|
|
58
59
|
*/
|
|
59
60
|
export const DefaultAppBar = function DefaultAppBar({
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
title,
|
|
62
|
+
endAdornment,
|
|
63
|
+
startAdornment,
|
|
64
|
+
dropDownActions,
|
|
65
|
+
includeModeToggle = true,
|
|
66
|
+
className,
|
|
67
|
+
style,
|
|
68
|
+
user: userProp,
|
|
69
|
+
logo: logoProp,
|
|
70
|
+
}: DefaultAppBarProps) {
|
|
70
71
|
|
|
71
72
|
const {
|
|
72
73
|
hasDrawer,
|
|
@@ -85,6 +86,8 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
85
86
|
mode,
|
|
86
87
|
setMode
|
|
87
88
|
} = useModeController();
|
|
89
|
+
|
|
90
|
+
const { i18n, t } = useTranslation();
|
|
88
91
|
|
|
89
92
|
const navigate = useNavigate();
|
|
90
93
|
|
|
@@ -92,7 +95,7 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
92
95
|
|
|
93
96
|
const user = userProp ?? authController.user;
|
|
94
97
|
|
|
95
|
-
let avatarComponent:
|
|
98
|
+
let avatarComponent: React.ReactElement | null;
|
|
96
99
|
|
|
97
100
|
if (user) {
|
|
98
101
|
const initial = user?.displayName
|
|
@@ -103,7 +106,7 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
103
106
|
</Avatar>;
|
|
104
107
|
} else if (user === undefined || authController.initialLoading) {
|
|
105
108
|
avatarComponent = <div className={"p-1 flex justify-center"}>
|
|
106
|
-
<Skeleton className={"w-10 h-10 rounded-full"}/>
|
|
109
|
+
<Skeleton className={"w-10 h-10 rounded-full"} />
|
|
107
110
|
</div>;
|
|
108
111
|
} else {
|
|
109
112
|
avatarComponent = null;
|
|
@@ -131,13 +134,13 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
131
134
|
<div className={"flex flex-row gap-4"}>
|
|
132
135
|
{!hasDrawer && (logo
|
|
133
136
|
? <img src={logo}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
: <FireCMSLogo width={"32px"} height={"32px"}/>)}
|
|
137
|
+
alt="Logo"
|
|
138
|
+
className={cls("w-[32px] h-[32px] object-contain")} />
|
|
139
|
+
: <FireCMSLogo width={"32px"} height={"32px"} />)}
|
|
137
140
|
|
|
138
141
|
{typeof title === "string"
|
|
139
142
|
? <Typography variant="subtitle1"
|
|
140
|
-
|
|
143
|
+
noWrap>
|
|
141
144
|
{title}
|
|
142
145
|
</Typography>
|
|
143
146
|
: title}
|
|
@@ -146,7 +149,7 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
146
149
|
</div>}
|
|
147
150
|
|
|
148
151
|
{(breadcrumbs.breadcrumbs ?? []).length > 0 && <div className="mr-8 hidden lg:block">
|
|
149
|
-
<div className={"flex flex-row gap-2"}>
|
|
152
|
+
<div className={"flex flex-row gap-2 items-center"}>
|
|
150
153
|
{breadcrumbs.breadcrumbs.map((breadcrumb, index) => {
|
|
151
154
|
return <React.Fragment key={breadcrumb.url + "_" + index}>
|
|
152
155
|
<Typography variant={"caption"} color={"secondary"}>
|
|
@@ -157,18 +160,31 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
157
160
|
className="visited:text-inherit visited:dark:text-inherit block"
|
|
158
161
|
to={breadcrumb.url}
|
|
159
162
|
>
|
|
160
|
-
<
|
|
161
|
-
{
|
|
162
|
-
|
|
163
|
+
<div className="flex flex-row items-center gap-2 whitespace-nowrap">
|
|
164
|
+
<Typography variant={"body2"}>
|
|
165
|
+
{breadcrumb.title}
|
|
166
|
+
</Typography>
|
|
167
|
+
{/* Show count badge for collection breadcrumbs: undefined = not applicable, null = loading, number = count */}
|
|
168
|
+
{breadcrumb.count !== undefined && (
|
|
169
|
+
breadcrumb.count !== null ? (
|
|
170
|
+
<span className="text-xs text-surface-accent-500 dark:text-surface-accent-400 bg-surface-100 dark:bg-surface-700 px-1 py-0 rounded">
|
|
171
|
+
{breadcrumb.count}
|
|
172
|
+
</span>
|
|
173
|
+
) : (
|
|
174
|
+
<Skeleton className="w-8 h-4 rounded-md" />
|
|
175
|
+
)
|
|
176
|
+
)}
|
|
177
|
+
</div>
|
|
163
178
|
</Link>
|
|
164
179
|
</React.Fragment>;
|
|
165
180
|
})}
|
|
166
181
|
</div>
|
|
167
182
|
</div>}
|
|
168
183
|
|
|
184
|
+
|
|
169
185
|
{startAdornment}
|
|
170
186
|
|
|
171
|
-
<div className={"flex-grow"}/>
|
|
187
|
+
<div className={"flex-grow"} />
|
|
172
188
|
|
|
173
189
|
{endAdornment &&
|
|
174
190
|
<ErrorBoundary>
|
|
@@ -179,18 +195,19 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
179
195
|
<Menu
|
|
180
196
|
trigger={<IconButton
|
|
181
197
|
color="inherit"
|
|
182
|
-
aria-label="Open drawer"
|
|
183
|
-
size="large">
|
|
198
|
+
aria-label="Open drawer">
|
|
184
199
|
{mode === "dark"
|
|
185
|
-
? <DarkModeIcon/>
|
|
186
|
-
: <LightModeIcon/>}
|
|
200
|
+
? <DarkModeIcon size="small" />
|
|
201
|
+
: <LightModeIcon size="small" />}
|
|
187
202
|
</IconButton>}>
|
|
188
|
-
<MenuItem onClick={() => setMode("dark")}><DarkModeIcon size={"smallest"}/>
|
|
189
|
-
<MenuItem onClick={() => setMode("light")}><LightModeIcon size={"smallest"}/>
|
|
203
|
+
<MenuItem onClick={() => setMode("dark")}><DarkModeIcon size={"smallest"} /> {t("dark_mode")}</MenuItem>
|
|
204
|
+
<MenuItem onClick={() => setMode("light")}><LightModeIcon size={"smallest"} /> {t("light_mode")}</MenuItem>
|
|
190
205
|
<MenuItem onClick={() => setMode("system")}> <BrightnessMediumIcon
|
|
191
|
-
size={"smallest"}/>
|
|
206
|
+
size={"smallest"} />{t("system_mode")}</MenuItem>
|
|
192
207
|
</Menu>}
|
|
193
208
|
|
|
209
|
+
<LanguageToggle />
|
|
210
|
+
|
|
194
211
|
<Menu trigger={avatarComponent}>
|
|
195
212
|
{user && <div className={"px-4 py-2 mb-2"}>
|
|
196
213
|
{user.displayName && <Typography variant={"body1"} color={"secondary"}>
|
|
@@ -208,8 +225,8 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
208
225
|
// replace current route with home
|
|
209
226
|
navigate("/");
|
|
210
227
|
}}>
|
|
211
|
-
<LogoutIcon/>
|
|
212
|
-
|
|
228
|
+
<LogoutIcon />
|
|
229
|
+
{t("log_out")}
|
|
213
230
|
</MenuItem>}
|
|
214
231
|
|
|
215
232
|
</Menu>
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
useCollapsedGroups,
|
|
5
|
+
useLargeLayout,
|
|
6
|
+
useNavigationController,
|
|
7
|
+
useTranslation
|
|
8
|
+
} from "../hooks";
|
|
4
9
|
|
|
5
10
|
import { Link, useNavigate } from "react-router-dom";
|
|
6
11
|
import { CMSAnalyticsEvent, NavigationEntry, NavigationResult } from "../types";
|
|
7
12
|
import { IconForView } from "../util";
|
|
8
|
-
import { cls, IconButton, Menu, MenuItem, MoreVertIcon, Tooltip
|
|
13
|
+
import { cls, IconButton, Menu, MenuItem, MoreVertIcon, Tooltip } from "@firecms/ui";
|
|
9
14
|
import { useAnalyticsController } from "../hooks/useAnalyticsController";
|
|
10
|
-
import {
|
|
15
|
+
import { DrawerNavigationGroup } from "./DrawerNavigationGroup";
|
|
11
16
|
import { FireCMSLogo } from "../components";
|
|
12
17
|
import { useApp } from "../app/useApp";
|
|
13
18
|
|
|
@@ -16,9 +21,9 @@ import { useApp } from "../app/useApp";
|
|
|
16
21
|
* @group Core
|
|
17
22
|
*/
|
|
18
23
|
export function DefaultDrawer({
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
className,
|
|
25
|
+
style,
|
|
26
|
+
}: {
|
|
22
27
|
className?: string
|
|
23
28
|
style?: React.CSSProperties,
|
|
24
29
|
}) {
|
|
@@ -34,6 +39,7 @@ export function DefaultDrawer({
|
|
|
34
39
|
|
|
35
40
|
const analyticsController = useAnalyticsController();
|
|
36
41
|
const navigation = useNavigationController();
|
|
42
|
+
const { t } = useTranslation();
|
|
37
43
|
|
|
38
44
|
const tooltipsOpen = drawerHovered && !drawerOpen && !adminMenuOpen;
|
|
39
45
|
const largeLayout = useLargeLayout();
|
|
@@ -50,20 +56,10 @@ export function DefaultDrawer({
|
|
|
50
56
|
const adminViews = navigationEntries.filter(e => e.type === "admin") ?? [];
|
|
51
57
|
const groupsWithoutAdmin = groups.filter(g => g !== "Admin");
|
|
52
58
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return <div
|
|
56
|
-
className="pl-6 pr-8 py-4 flex flex-row items-center">
|
|
57
|
-
<Typography variant={"caption"}
|
|
58
|
-
color={"secondary"}
|
|
59
|
-
className="font-medium flex-grow line-clamp-1">
|
|
60
|
-
{group ? group.toUpperCase() : "Views".toUpperCase()}
|
|
61
|
-
</Typography>
|
|
59
|
+
// Collapsible groups state - using "drawer" namespace for independent state from home page
|
|
60
|
+
const { isGroupCollapsed, toggleGroupCollapsed } = useCollapsedGroups(groupsWithoutAdmin, "drawer");
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
}, [drawerOpen]);
|
|
65
|
-
|
|
66
|
-
const onClick = (view: NavigationEntry) => {
|
|
62
|
+
const onItemClick = (view: NavigationEntry) => {
|
|
67
63
|
const eventName: CMSAnalyticsEvent = view.type === "collection"
|
|
68
64
|
? "drawer_navigate_to_collection"
|
|
69
65
|
: (view.type === "view" ? "drawer_navigate_to_view" : "unmapped_event");
|
|
@@ -76,33 +72,29 @@ export function DefaultDrawer({
|
|
|
76
72
|
<>
|
|
77
73
|
<div className={cls("flex flex-col h-full relative flex-grow w-full", className)} style={style}>
|
|
78
74
|
|
|
79
|
-
<DrawerLogo logo={logo}/>
|
|
75
|
+
<DrawerLogo logo={logo} />
|
|
80
76
|
|
|
81
77
|
<div className={"mt-4 flex-grow overflow-scroll no-scrollbar"}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
{groupsWithoutAdmin.map((group) =>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
url={view.url}
|
|
103
|
-
name={view.name}/>)}
|
|
104
|
-
</div>
|
|
105
|
-
))}
|
|
78
|
+
style={{
|
|
79
|
+
maskImage: "linear-gradient(to bottom, transparent 0, black 20px, black calc(100% - 20px), transparent 100%)",
|
|
80
|
+
}}>
|
|
81
|
+
|
|
82
|
+
{groupsWithoutAdmin.map((group) => {
|
|
83
|
+
const entriesInGroup = Object.values(navigationEntries).filter(e => e.group === group);
|
|
84
|
+
return (
|
|
85
|
+
<DrawerNavigationGroup
|
|
86
|
+
key={`drawer_group_${group}`}
|
|
87
|
+
group={group}
|
|
88
|
+
entries={entriesInGroup}
|
|
89
|
+
collapsed={isGroupCollapsed(group)}
|
|
90
|
+
onToggleCollapsed={() => toggleGroupCollapsed(group)}
|
|
91
|
+
drawerOpen={drawerOpen}
|
|
92
|
+
tooltipsOpen={tooltipsOpen}
|
|
93
|
+
adminMenuOpen={adminMenuOpen}
|
|
94
|
+
onItemClick={onItemClick}
|
|
95
|
+
/>
|
|
96
|
+
);
|
|
97
|
+
})}
|
|
106
98
|
|
|
107
99
|
</div>
|
|
108
100
|
|
|
@@ -115,9 +107,9 @@ export function DefaultDrawer({
|
|
|
115
107
|
shape={"square"}
|
|
116
108
|
className={"m-4 text-surface-900 dark:text-white w-fit"}>
|
|
117
109
|
<Tooltip title={"Admin"}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
<MoreVertIcon/>
|
|
110
|
+
open={tooltipsOpen}
|
|
111
|
+
side={"right"} sideOffset={28}>
|
|
112
|
+
<MoreVertIcon />
|
|
121
113
|
</Tooltip>
|
|
122
114
|
{drawerOpen && <div
|
|
123
115
|
className={cls(
|
|
@@ -132,11 +124,11 @@ export function DefaultDrawer({
|
|
|
132
124
|
<MenuItem
|
|
133
125
|
onClick={(event) => {
|
|
134
126
|
event.preventDefault();
|
|
135
|
-
navigate(entry.url);
|
|
127
|
+
navigate(entry.url);
|
|
136
128
|
}}
|
|
137
129
|
key={entry.id}>
|
|
138
|
-
{<IconForView collectionOrView={entry.view}/>}
|
|
139
|
-
{entry.name}
|
|
130
|
+
{<IconForView collectionOrView={entry.view} />}
|
|
131
|
+
{t(entry.name as any)}
|
|
140
132
|
</MenuItem>)}
|
|
141
133
|
|
|
142
134
|
</Menu>}
|
|
@@ -167,17 +159,17 @@ export function DrawerLogo({ logo }: {
|
|
|
167
159
|
className={cls("cursor-pointer rounded ml-3 mr-1")}>
|
|
168
160
|
|
|
169
161
|
<Tooltip title={"Home"}
|
|
170
|
-
|
|
171
|
-
|
|
162
|
+
sideOffset={20}
|
|
163
|
+
side="right">
|
|
172
164
|
<Link
|
|
173
165
|
className={"block"}
|
|
174
166
|
to={navigation.basePath}>
|
|
175
167
|
{logo
|
|
176
168
|
? <img src={logo}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
: <FireCMSLogo/>}
|
|
169
|
+
alt="Logo"
|
|
170
|
+
className={cls("max-w-full max-h-full transition-all object-contain",
|
|
171
|
+
drawerOpen ? "w-[96px] h-[96px]" : "w-[32px] h-[32px]")} />
|
|
172
|
+
: <FireCMSLogo />}
|
|
181
173
|
|
|
182
174
|
</Link>
|
|
183
175
|
</Tooltip>
|