@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
|
@@ -14,13 +14,15 @@ import {
|
|
|
14
14
|
PartialEntityCollection,
|
|
15
15
|
PropertyOrBuilder,
|
|
16
16
|
ResolvedProperty,
|
|
17
|
-
SaveEntityProps
|
|
17
|
+
SaveEntityProps,
|
|
18
|
+
ViewMode
|
|
18
19
|
} from "../../types";
|
|
19
20
|
import {
|
|
20
21
|
EntityCollectionRowActions,
|
|
21
22
|
EntityCollectionTable,
|
|
22
23
|
useDataSourceTableController
|
|
23
24
|
} from "../EntityCollectionTable";
|
|
25
|
+
import { CollectionTableToolbar } from "../EntityCollectionTable/internal/CollectionTableToolbar";
|
|
24
26
|
|
|
25
27
|
import {
|
|
26
28
|
canCreateEntity,
|
|
@@ -43,10 +45,16 @@ import {
|
|
|
43
45
|
useFireCMSContext,
|
|
44
46
|
useLargeLayout,
|
|
45
47
|
useNavigationController,
|
|
46
|
-
useSideEntityController
|
|
48
|
+
useSideEntityController,
|
|
49
|
+
useTranslation
|
|
47
50
|
} from "../../hooks";
|
|
51
|
+
import { useBreadcrumbsController } from "../../hooks/useBreadcrumbsController";
|
|
48
52
|
import { useUserConfigurationPersistence } from "../../hooks/useUserConfigurationPersistence";
|
|
49
53
|
import { EntityCollectionViewActions } from "./EntityCollectionViewActions";
|
|
54
|
+
import { EntityCollectionCardView } from "./EntityCollectionCardView";
|
|
55
|
+
import { EntityCollectionBoardView } from "./EntityCollectionBoardView";
|
|
56
|
+
import { CollectionDataErrorBanner } from "./CollectionDataErrorBanner";
|
|
57
|
+
import { ViewModeToggle, KanbanPropertyOption } from "./ViewModeToggle";
|
|
50
58
|
import {
|
|
51
59
|
AddIcon,
|
|
52
60
|
Button,
|
|
@@ -142,18 +150,20 @@ export type EntityCollectionViewProps<M extends Record<string, any>> = {
|
|
|
142
150
|
*/
|
|
143
151
|
export const EntityCollectionView = React.memo(
|
|
144
152
|
function EntityCollectionView<M extends Record<string, any>>({
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
fullPath: fullPathProp,
|
|
154
|
+
fullIdPath,
|
|
155
|
+
parentCollectionIds,
|
|
156
|
+
isSubCollection,
|
|
157
|
+
className,
|
|
158
|
+
updateUrl,
|
|
159
|
+
...collectionProp
|
|
160
|
+
}: EntityCollectionViewProps<M>
|
|
153
161
|
) {
|
|
154
162
|
|
|
155
163
|
const context = useFireCMSContext();
|
|
164
|
+
const { t } = useTranslation();
|
|
156
165
|
const navigation = useNavigationController();
|
|
166
|
+
const breadcrumbs = useBreadcrumbsController();
|
|
157
167
|
const fullPath = fullPathProp ?? collectionProp.path;
|
|
158
168
|
const dataSource = useDataSource(collectionProp);
|
|
159
169
|
const sideEntityController = useSideEntityController();
|
|
@@ -184,8 +194,19 @@ export const EntityCollectionView = React.memo(
|
|
|
184
194
|
|
|
185
195
|
const [lastDeleteTimestamp, setLastDeleteTimestamp] = React.useState<number>(0);
|
|
186
196
|
|
|
187
|
-
//
|
|
188
|
-
const [
|
|
197
|
+
// Track recently deleted entities for optimistic Kanban count updates
|
|
198
|
+
const [deletedEntities, setDeletedEntities] = React.useState<Entity<M>[]>([]);
|
|
199
|
+
|
|
200
|
+
// number of entities in the collection (undefined = loading)
|
|
201
|
+
const [docsCount, setDocsCount] = useState<number | undefined>(undefined);
|
|
202
|
+
|
|
203
|
+
// Optimistic state for column order to prevent UI flickering during persistence
|
|
204
|
+
const [localPropertiesOrder, setLocalPropertiesOrder] = useState<string[] | undefined>(collection.propertiesOrder);
|
|
205
|
+
|
|
206
|
+
// Sync local state with collection's propertiesOrder when it changes from external sources
|
|
207
|
+
useEffect(() => {
|
|
208
|
+
setLocalPropertiesOrder(collection.propertiesOrder);
|
|
209
|
+
}, [collection.propertiesOrder]);
|
|
189
210
|
|
|
190
211
|
const unselectNavigatedEntity = useCallback(() => {
|
|
191
212
|
const currentSelection = highlightedEntity;
|
|
@@ -208,6 +229,83 @@ export const EntityCollectionView = React.memo(
|
|
|
208
229
|
|
|
209
230
|
const [popOverOpen, setPopOverOpen] = useState(false);
|
|
210
231
|
|
|
232
|
+
// View mode priority: URL > saved user config > collection.defaultViewMode
|
|
233
|
+
const defaultViewMode = collection.defaultViewMode ?? "table";
|
|
234
|
+
|
|
235
|
+
// Parse view from URL
|
|
236
|
+
const getViewFromUrl = useCallback((): ViewMode | null => {
|
|
237
|
+
const params = new URLSearchParams(window.location.search);
|
|
238
|
+
const urlView = params.get("__view");
|
|
239
|
+
if (urlView && ["table", "kanban", "cards"].includes(urlView)) {
|
|
240
|
+
return urlView as ViewMode;
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}, []);
|
|
244
|
+
|
|
245
|
+
// Get saved view from local persistence
|
|
246
|
+
const getSavedView = useCallback((): ViewMode | null => {
|
|
247
|
+
const saved = userConfigPersistence?.getCollectionConfig<M>(fullPath)?.defaultViewMode;
|
|
248
|
+
return (saved as ViewMode) ?? null;
|
|
249
|
+
}, [userConfigPersistence, fullPath]);
|
|
250
|
+
|
|
251
|
+
const [viewMode, setViewModeState] = useState<ViewMode>(() => {
|
|
252
|
+
// Priority: URL > saved config > collection default
|
|
253
|
+
const urlView = getViewFromUrl();
|
|
254
|
+
if (urlView) return urlView;
|
|
255
|
+
const savedView = getSavedView();
|
|
256
|
+
if (savedView) return savedView;
|
|
257
|
+
return defaultViewMode;
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Sync URL with current view on init (if view came from saved config)
|
|
261
|
+
useEffect(() => {
|
|
262
|
+
const urlView = getViewFromUrl();
|
|
263
|
+
if (!urlView && viewMode !== "table") {
|
|
264
|
+
// View came from saved config but URL doesn't have it - update URL without push
|
|
265
|
+
const url = new URL(window.location.href);
|
|
266
|
+
url.searchParams.set("__view", viewMode);
|
|
267
|
+
window.history.replaceState({}, "", url.toString());
|
|
268
|
+
}
|
|
269
|
+
}, []); // Only on mount
|
|
270
|
+
|
|
271
|
+
// Update URL when view mode changes (user action)
|
|
272
|
+
const setViewMode = useCallback((newMode: ViewMode) => {
|
|
273
|
+
setViewModeState(newMode);
|
|
274
|
+
|
|
275
|
+
// Update URL with __view param
|
|
276
|
+
const url = new URL(window.location.href);
|
|
277
|
+
if (newMode === "table") {
|
|
278
|
+
url.searchParams.delete("__view");
|
|
279
|
+
} else {
|
|
280
|
+
url.searchParams.set("__view", newMode);
|
|
281
|
+
}
|
|
282
|
+
window.history.pushState({}, "", url.toString());
|
|
283
|
+
}, []);
|
|
284
|
+
|
|
285
|
+
// Listen for browser back/forward
|
|
286
|
+
useEffect(() => {
|
|
287
|
+
const handlePopState = () => {
|
|
288
|
+
const urlView = getViewFromUrl();
|
|
289
|
+
if (urlView) {
|
|
290
|
+
// URL has explicit view - use it
|
|
291
|
+
setViewModeState(urlView);
|
|
292
|
+
} else {
|
|
293
|
+
// No URL param - fallback to saved config or collection default
|
|
294
|
+
const savedView = getSavedView();
|
|
295
|
+
setViewModeState(savedView ?? defaultViewMode);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
window.addEventListener("popstate", handlePopState);
|
|
300
|
+
return () => window.removeEventListener("popstate", handlePopState);
|
|
301
|
+
}, [getViewFromUrl, getSavedView, defaultViewMode]);
|
|
302
|
+
|
|
303
|
+
// Card view size state - controls the grid column count
|
|
304
|
+
const [cardSize, setCardSize] = useState<CollectionSize>(collection.defaultSize ?? "m");
|
|
305
|
+
|
|
306
|
+
// Table view size state - controls row height
|
|
307
|
+
const [tableSize, setTableSize] = useState<CollectionSize>(collection.defaultSize ?? "m");
|
|
308
|
+
|
|
211
309
|
const selectionController = useSelectionController<M>();
|
|
212
310
|
const usedSelectionController = collection.selectionController ?? selectionController;
|
|
213
311
|
const {
|
|
@@ -284,6 +382,7 @@ export const EntityCollectionView = React.memo(
|
|
|
284
382
|
path: fullPath
|
|
285
383
|
});
|
|
286
384
|
setSelectedEntities((selectedEntities) => selectedEntities.filter((e) => e.id !== entity.id));
|
|
385
|
+
setDeletedEntities(prev => [...prev, entity]);
|
|
287
386
|
setLastDeleteTimestamp(Date.now());
|
|
288
387
|
};
|
|
289
388
|
|
|
@@ -293,6 +392,7 @@ export const EntityCollectionView = React.memo(
|
|
|
293
392
|
});
|
|
294
393
|
setSelectedEntities([]);
|
|
295
394
|
setDeleteEntityClicked(undefined);
|
|
395
|
+
setDeletedEntities(prev => [...prev, ...entities]);
|
|
296
396
|
setLastDeleteTimestamp(Date.now());
|
|
297
397
|
};
|
|
298
398
|
|
|
@@ -317,9 +417,9 @@ export const EntityCollectionView = React.memo(
|
|
|
317
417
|
}, [userConfigPersistence]);
|
|
318
418
|
|
|
319
419
|
const onColumnResize = useCallback(({
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
420
|
+
width,
|
|
421
|
+
key
|
|
422
|
+
}: OnColumnResizeParams) => {
|
|
323
423
|
|
|
324
424
|
const collection = collectionRef.current;
|
|
325
425
|
// Only for property columns
|
|
@@ -328,29 +428,44 @@ export const EntityCollectionView = React.memo(
|
|
|
328
428
|
onCollectionModifiedForUser(fullPath, localCollection);
|
|
329
429
|
}, [onCollectionModifiedForUser, fullPath]);
|
|
330
430
|
|
|
331
|
-
const
|
|
431
|
+
const onTableSizeChanged = useCallback((size: CollectionSize) => {
|
|
432
|
+
setTableSize(size);
|
|
332
433
|
if (userConfigPersistence)
|
|
333
434
|
onCollectionModifiedForUser(fullPath, { defaultSize: size })
|
|
334
435
|
}, [onCollectionModifiedForUser, fullPath, userConfigPersistence]);
|
|
335
436
|
|
|
437
|
+
// View mode change: update URL + save to local persistence
|
|
438
|
+
const onViewModeChange = useCallback((mode: ViewMode) => {
|
|
439
|
+
analyticsController.onAnalyticsEvent?.("view_mode_changed", {
|
|
440
|
+
path: fullPath,
|
|
441
|
+
from: viewMode,
|
|
442
|
+
to: mode
|
|
443
|
+
});
|
|
444
|
+
setViewMode(mode);
|
|
445
|
+
// Save to local persistence for next visit
|
|
446
|
+
if (userConfigPersistence) {
|
|
447
|
+
onCollectionModifiedForUser(fullPath, { defaultViewMode: mode } as PartialEntityCollection<M>);
|
|
448
|
+
}
|
|
449
|
+
}, [setViewMode, userConfigPersistence, onCollectionModifiedForUser, fullPath, analyticsController, viewMode]);
|
|
450
|
+
|
|
336
451
|
const createEnabled = canCreateEntity(collection, authController, fullPath, null);
|
|
337
452
|
|
|
338
453
|
const uniqueFieldValidator: UniqueFieldValidator = useCallback(
|
|
339
454
|
({
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
455
|
+
name,
|
|
456
|
+
value,
|
|
457
|
+
property,
|
|
458
|
+
entityId
|
|
459
|
+
}) => dataSource.checkUniqueField(fullPath, name, value, entityId, collection),
|
|
345
460
|
[fullPath]);
|
|
346
461
|
|
|
347
462
|
const onValueChange: OnCellValueChange<any, any> = ({
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
463
|
+
value,
|
|
464
|
+
propertyKey,
|
|
465
|
+
onValueUpdated,
|
|
466
|
+
setError,
|
|
467
|
+
data: entity,
|
|
468
|
+
}) => {
|
|
354
469
|
|
|
355
470
|
const updatedValues = setIn({ ...entity.values }, propertyKey, value);
|
|
356
471
|
|
|
@@ -394,10 +509,88 @@ export const EntityCollectionView = React.memo(
|
|
|
394
509
|
authController,
|
|
395
510
|
}), [collection, fullPath]);
|
|
396
511
|
|
|
512
|
+
// Check if Kanban view is possible (collection has at least one string enum property)
|
|
513
|
+
const hasEnumProperty = useMemo(() => {
|
|
514
|
+
const properties = resolvedCollection.properties;
|
|
515
|
+
return Object.values(properties).some((prop: any) =>
|
|
516
|
+
prop && prop.dataType === "string" && prop.enumValues
|
|
517
|
+
);
|
|
518
|
+
}, [resolvedCollection.properties]);
|
|
519
|
+
|
|
520
|
+
// Compute the effective enabled views:
|
|
521
|
+
// - Start from collection.enabledViews (defaults to all three)
|
|
522
|
+
// - Filter out kanban if no enum properties exist
|
|
523
|
+
const enabledViews: ViewMode[] = useMemo(() => {
|
|
524
|
+
const configured = collection.enabledViews ?? ["table", "cards", "kanban"];
|
|
525
|
+
if (!hasEnumProperty) {
|
|
526
|
+
return configured.filter(v => v !== "kanban");
|
|
527
|
+
}
|
|
528
|
+
return configured;
|
|
529
|
+
}, [collection.enabledViews, hasEnumProperty]);
|
|
530
|
+
|
|
531
|
+
// Compute available enum properties for kanban column selection
|
|
532
|
+
const kanbanPropertyOptions: KanbanPropertyOption[] = useMemo(() => {
|
|
533
|
+
const options: KanbanPropertyOption[] = [];
|
|
534
|
+
const properties = resolvedCollection.properties;
|
|
535
|
+
|
|
536
|
+
for (const [key, property] of Object.entries(properties)) {
|
|
537
|
+
const prop = property as any;
|
|
538
|
+
if (prop && prop.dataType === "string" && prop.enumValues) {
|
|
539
|
+
options.push({
|
|
540
|
+
key,
|
|
541
|
+
label: prop.name || key
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return options;
|
|
547
|
+
}, [resolvedCollection.properties]);
|
|
548
|
+
|
|
549
|
+
// Get saved kanban property from user config
|
|
550
|
+
const getSavedKanbanProperty = useCallback((): string | undefined => {
|
|
551
|
+
const saved = userConfigPersistence?.getCollectionConfig<M>(fullPath);
|
|
552
|
+
return (saved as any)?.kanbanColumnProperty;
|
|
553
|
+
}, [userConfigPersistence, fullPath]);
|
|
554
|
+
|
|
555
|
+
// Selected kanban property state - priority: saved config > collection default > first available
|
|
556
|
+
const [selectedKanbanProperty, setSelectedKanbanProperty] = useState<string>(() => {
|
|
557
|
+
const saved = getSavedKanbanProperty();
|
|
558
|
+
if (saved && kanbanPropertyOptions.some(o => o.key === saved)) return saved;
|
|
559
|
+
if (collection.kanban?.columnProperty) return collection.kanban.columnProperty;
|
|
560
|
+
return kanbanPropertyOptions[0]?.key ?? "";
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
// Update selected property if options change and current selection is no longer valid
|
|
564
|
+
useEffect(() => {
|
|
565
|
+
if (kanbanPropertyOptions.length > 0 && !kanbanPropertyOptions.some(o => o.key === selectedKanbanProperty)) {
|
|
566
|
+
const saved = getSavedKanbanProperty();
|
|
567
|
+
if (saved && kanbanPropertyOptions.some(o => o.key === saved)) {
|
|
568
|
+
setSelectedKanbanProperty(saved);
|
|
569
|
+
} else if (collection.kanban?.columnProperty && kanbanPropertyOptions.some(o => o.key === collection.kanban?.columnProperty)) {
|
|
570
|
+
setSelectedKanbanProperty(collection.kanban.columnProperty);
|
|
571
|
+
} else {
|
|
572
|
+
setSelectedKanbanProperty(kanbanPropertyOptions[0]?.key ?? "");
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}, [kanbanPropertyOptions, selectedKanbanProperty, getSavedKanbanProperty, collection.kanban?.columnProperty]);
|
|
576
|
+
|
|
577
|
+
// Handle kanban property change
|
|
578
|
+
const onKanbanPropertyChange = useCallback((property: string) => {
|
|
579
|
+
analyticsController.onAnalyticsEvent?.("kanban_property_changed", {
|
|
580
|
+
path: fullPath,
|
|
581
|
+
property
|
|
582
|
+
});
|
|
583
|
+
setSelectedKanbanProperty(property);
|
|
584
|
+
// Save to local persistence
|
|
585
|
+
if (userConfigPersistence) {
|
|
586
|
+
onCollectionModifiedForUser(fullPath, { kanbanColumnProperty: property } as any);
|
|
587
|
+
}
|
|
588
|
+
}, [userConfigPersistence, onCollectionModifiedForUser, fullPath, analyticsController]);
|
|
589
|
+
|
|
397
590
|
const getPropertyFor = useCallback(({
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
591
|
+
propertyKey,
|
|
592
|
+
entity
|
|
593
|
+
}: GetPropertyForProps<M>) => {
|
|
401
594
|
let propertyOrBuilder: PropertyOrBuilder<any, M> | undefined = getPropertyInPath<M>(collection.properties, propertyKey);
|
|
402
595
|
|
|
403
596
|
// we might not find the property in the collection if combining property builders and map spread
|
|
@@ -417,7 +610,18 @@ export const EntityCollectionView = React.memo(
|
|
|
417
610
|
});
|
|
418
611
|
}, [collection.properties, customizationController.propertyConfigs, resolvedCollection.properties]);
|
|
419
612
|
|
|
420
|
-
|
|
613
|
+
// Use a collection with local propertiesOrder for optimistic UI updates
|
|
614
|
+
const collectionWithLocalOrder = useMemo(() => {
|
|
615
|
+
if (localPropertiesOrder && localPropertiesOrder !== resolvedCollection.propertiesOrder) {
|
|
616
|
+
return {
|
|
617
|
+
...resolvedCollection,
|
|
618
|
+
propertiesOrder: localPropertiesOrder
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
return resolvedCollection;
|
|
622
|
+
}, [resolvedCollection, localPropertiesOrder]);
|
|
623
|
+
|
|
624
|
+
const displayedColumnIds = useColumnIds(collectionWithLocalOrder, true);
|
|
421
625
|
|
|
422
626
|
const additionalFields = useMemo(() => {
|
|
423
627
|
const subcollectionColumns: AdditionalFieldDelegate<M, any>[] = collection.subcollections?.map((subcollection) => {
|
|
@@ -427,23 +631,22 @@ export const EntityCollectionView = React.memo(
|
|
|
427
631
|
width: 200,
|
|
428
632
|
dependencies: [],
|
|
429
633
|
Builder: ({ entity }) => (
|
|
430
|
-
<Button
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}}>
|
|
634
|
+
<Button
|
|
635
|
+
className={"max-w-full truncate justify-start"}
|
|
636
|
+
startIcon={<KeyboardTabIcon size={"small"} />}
|
|
637
|
+
onClick={(event: any) => {
|
|
638
|
+
event.stopPropagation();
|
|
639
|
+
navigateToEntity({
|
|
640
|
+
openEntityMode,
|
|
641
|
+
collection,
|
|
642
|
+
entityId: entity.id,
|
|
643
|
+
selectedTab: subcollection.id ?? subcollection.path,
|
|
644
|
+
path: fullPath,
|
|
645
|
+
fullIdPath,
|
|
646
|
+
navigation,
|
|
647
|
+
sideEntityController
|
|
648
|
+
})
|
|
649
|
+
}}>
|
|
447
650
|
{subcollection.name}
|
|
448
651
|
</Button>
|
|
449
652
|
)
|
|
@@ -465,7 +668,7 @@ export const EntityCollectionView = React.memo(
|
|
|
465
668
|
<ReferencePreview
|
|
466
669
|
key={reference.path + "/" + reference.id}
|
|
467
670
|
reference={reference}
|
|
468
|
-
size={"small"}/>
|
|
671
|
+
size={"small"} />
|
|
469
672
|
);
|
|
470
673
|
})}
|
|
471
674
|
</div>
|
|
@@ -488,18 +691,20 @@ export const EntityCollectionView = React.memo(
|
|
|
488
691
|
const largeLayout = useLargeLayout();
|
|
489
692
|
|
|
490
693
|
const getActionsForEntity = ({
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
694
|
+
entity,
|
|
695
|
+
customEntityActions
|
|
696
|
+
}: {
|
|
494
697
|
entity?: Entity<M>,
|
|
495
698
|
customEntityActions?: EntityAction[]
|
|
496
699
|
}): EntityAction[] => {
|
|
497
700
|
const deleteEnabled = entity ? canDeleteEntity(collection, authController, fullPath, entity) : true;
|
|
498
|
-
const actions: EntityAction[] = [
|
|
701
|
+
const actions: EntityAction[] = [
|
|
702
|
+
{ ...editEntityAction, name: t("edit") }
|
|
703
|
+
];
|
|
499
704
|
if (createEnabled)
|
|
500
|
-
actions.push(copyEntityAction);
|
|
705
|
+
actions.push({ ...copyEntityAction, name: t("copy") });
|
|
501
706
|
if (deleteEnabled)
|
|
502
|
-
actions.push(deleteEntityAction);
|
|
707
|
+
actions.push({ ...deleteEntityAction, name: t("delete") });
|
|
503
708
|
if (customEntityActions)
|
|
504
709
|
return mergeEntityActions(actions, customEntityActions);
|
|
505
710
|
return actions;
|
|
@@ -514,11 +719,11 @@ export const EntityCollectionView = React.memo(
|
|
|
514
719
|
};
|
|
515
720
|
|
|
516
721
|
const tableRowActionsBuilder = useCallback(({
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
722
|
+
entity,
|
|
723
|
+
size,
|
|
724
|
+
width,
|
|
725
|
+
frozen
|
|
726
|
+
}: {
|
|
522
727
|
entity: Entity<any>,
|
|
523
728
|
size: CollectionSize,
|
|
524
729
|
width: number,
|
|
@@ -558,45 +763,28 @@ export const EntityCollectionView = React.memo(
|
|
|
558
763
|
|
|
559
764
|
}, [updateLastDeleteTimestamp, usedSelectionController]);
|
|
560
765
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
variant={"subtitle1"}
|
|
568
|
-
className={`leading-none truncate max-w-[160px] lg:max-w-[240px] ${collection.description ? "cursor-pointer" : "cursor-auto"}`}
|
|
569
|
-
onClick={collection.description
|
|
570
|
-
? (e) => {
|
|
571
|
-
setPopOverOpen(true);
|
|
572
|
-
e.stopPropagation();
|
|
573
|
-
}
|
|
574
|
-
: undefined}>
|
|
575
|
-
{`${collection.name}`}
|
|
576
|
-
</Typography>
|
|
577
|
-
|
|
578
|
-
<EntitiesCount
|
|
579
|
-
fullPath={fullPath}
|
|
580
|
-
collection={collection}
|
|
581
|
-
filter={tableController.filterValues}
|
|
582
|
-
sortBy={tableController.sortBy}
|
|
583
|
-
onCountChange={setDocsCount}
|
|
584
|
-
/>
|
|
585
|
-
|
|
586
|
-
</div>}
|
|
587
|
-
>
|
|
766
|
+
// Update breadcrumb count when count changes (only if loaded)
|
|
767
|
+
useEffect(() => {
|
|
768
|
+
if (docsCount !== undefined) {
|
|
769
|
+
breadcrumbs.updateCount(fullPath, docsCount);
|
|
770
|
+
}
|
|
771
|
+
}, [docsCount, fullPath, breadcrumbs.updateCount]);
|
|
588
772
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
773
|
+
// EntitiesCount fetches count and updates breadcrumb - no visual rendering needed here
|
|
774
|
+
const countFetcher = <EntitiesCount
|
|
775
|
+
fullPath={fullPath}
|
|
776
|
+
collection={collection}
|
|
777
|
+
filter={tableController.filterValues}
|
|
778
|
+
sortBy={tableController.sortBy}
|
|
779
|
+
onCountChange={setDocsCount}
|
|
780
|
+
/>;
|
|
592
781
|
|
|
593
|
-
</Popover>;
|
|
594
782
|
|
|
595
783
|
const buildAdditionalHeaderWidget = useCallback(({
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
784
|
+
property,
|
|
785
|
+
propertyKey,
|
|
786
|
+
onHover
|
|
787
|
+
}: {
|
|
600
788
|
property: ResolvedProperty,
|
|
601
789
|
propertyKey: string,
|
|
602
790
|
onHover: boolean
|
|
@@ -616,7 +804,7 @@ export const EntityCollectionView = React.memo(
|
|
|
616
804
|
fullPath={fullPath}
|
|
617
805
|
collection={collection}
|
|
618
806
|
tableController={tableController}
|
|
619
|
-
parentCollectionIds={parentCollectionIds ?? []}/>;
|
|
807
|
+
parentCollectionIds={parentCollectionIds ?? []} />;
|
|
620
808
|
})}
|
|
621
809
|
</>;
|
|
622
810
|
}, [customizationController.plugins, fullPath, parentCollectionIds]);
|
|
@@ -625,9 +813,9 @@ export const EntityCollectionView = React.memo(
|
|
|
625
813
|
? function () {
|
|
626
814
|
if (typeof AddColumnComponent === "function")
|
|
627
815
|
return <AddColumnComponent fullPath={fullPath}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
816
|
+
parentCollectionIds={parentCollectionIds ?? []}
|
|
817
|
+
collection={collection}
|
|
818
|
+
tableController={tableController} />;
|
|
631
819
|
return null;
|
|
632
820
|
}
|
|
633
821
|
: undefined;
|
|
@@ -643,32 +831,55 @@ export const EntityCollectionView = React.memo(
|
|
|
643
831
|
parentCollectionIds
|
|
644
832
|
});
|
|
645
833
|
|
|
834
|
+
// Popover open state managed at parent level to prevent closing when view changes
|
|
835
|
+
const [viewModePopoverOpen, setViewModePopoverOpen] = useState(false);
|
|
836
|
+
|
|
837
|
+
// Create ViewModeToggle once to prevent remounting when view changes
|
|
838
|
+
const viewModeToggleElement = (
|
|
839
|
+
<ViewModeToggle
|
|
840
|
+
viewMode={viewMode}
|
|
841
|
+
onViewModeChange={onViewModeChange}
|
|
842
|
+
enabledViews={enabledViews}
|
|
843
|
+
size={viewMode === "table" ? tableSize : viewMode === "cards" ? cardSize : undefined}
|
|
844
|
+
onSizeChanged={viewMode === "table" ? onTableSizeChanged : viewMode === "cards" ? setCardSize : undefined}
|
|
845
|
+
open={viewModePopoverOpen}
|
|
846
|
+
onOpenChange={setViewModePopoverOpen}
|
|
847
|
+
kanbanPropertyOptions={kanbanPropertyOptions}
|
|
848
|
+
selectedKanbanProperty={selectedKanbanProperty}
|
|
849
|
+
onKanbanPropertyChange={onKanbanPropertyChange}
|
|
850
|
+
/>
|
|
851
|
+
);
|
|
852
|
+
|
|
853
|
+
// Compute plugin-provided error view for collection loading errors
|
|
854
|
+
const pluginErrorView = useMemo(() => {
|
|
855
|
+
const error = tableController.dataLoadingError;
|
|
856
|
+
if (!error || !customizationController.plugins) return null;
|
|
857
|
+
for (const plugin of customizationController.plugins) {
|
|
858
|
+
if (plugin.collectionView?.CollectionError) {
|
|
859
|
+
const CollectionError = plugin.collectionView.CollectionError;
|
|
860
|
+
return <CollectionError
|
|
861
|
+
path={fullPath}
|
|
862
|
+
collection={collection}
|
|
863
|
+
parentCollectionIds={parentCollectionIds}
|
|
864
|
+
error={error}
|
|
865
|
+
/>;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
return null;
|
|
869
|
+
}, [tableController.dataLoadingError, customizationController.plugins, fullPath, collection, parentCollectionIds]);
|
|
870
|
+
|
|
646
871
|
return (
|
|
647
|
-
<div className={cls("overflow-hidden h-full w-full rounded-md", className)}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
onEntityClick={onEntityClick}
|
|
657
|
-
onColumnResize={onColumnResize}
|
|
658
|
-
onValueChange={onValueChange}
|
|
659
|
-
tableRowActionsBuilder={tableRowActionsBuilder}
|
|
660
|
-
uniqueFieldValidator={uniqueFieldValidator}
|
|
661
|
-
title={title}
|
|
662
|
-
selectionController={usedSelectionController}
|
|
663
|
-
highlightedEntities={highlightedEntity ? [highlightedEntity] : []}
|
|
664
|
-
defaultSize={collection.defaultSize}
|
|
665
|
-
properties={resolvedCollection.properties}
|
|
666
|
-
getPropertyFor={getPropertyFor}
|
|
667
|
-
onTextSearchClick={textSearchInitialised ? undefined : onTextSearchClick}
|
|
668
|
-
onScroll={tableController.onScroll}
|
|
669
|
-
initialScroll={tableController.initialScroll}
|
|
872
|
+
<div className={cls("overflow-hidden h-full w-full rounded-md flex flex-col", className)}
|
|
873
|
+
ref={containerRef}>
|
|
874
|
+
|
|
875
|
+
{/* Unified toolbar - rendered once, outside view conditionals */}
|
|
876
|
+
{countFetcher}
|
|
877
|
+
<CollectionTableToolbar
|
|
878
|
+
loading={tableController.dataLoading}
|
|
879
|
+
onTextSearch={textSearchEnabled && textSearchInitialised ? tableController.setSearchString : undefined}
|
|
880
|
+
onTextSearchClick={textSearchEnabled && !textSearchInitialised ? onTextSearchClick : undefined}
|
|
670
881
|
textSearchLoading={textSearchLoading}
|
|
671
|
-
|
|
882
|
+
viewModeToggle={viewModeToggleElement}
|
|
672
883
|
actionsStart={<EntityCollectionViewStartActions
|
|
673
884
|
parentCollectionIds={parentCollectionIds ?? []}
|
|
674
885
|
collection={collection}
|
|
@@ -676,7 +887,8 @@ export const EntityCollectionView = React.memo(
|
|
|
676
887
|
path={fullPath}
|
|
677
888
|
relativePath={collection.path}
|
|
678
889
|
selectionController={usedSelectionController}
|
|
679
|
-
collectionEntitiesCount={docsCount}
|
|
890
|
+
collectionEntitiesCount={docsCount}
|
|
891
|
+
resolvedProperties={resolvedCollection.properties} />}
|
|
680
892
|
actions={<EntityCollectionViewActions
|
|
681
893
|
parentCollectionIds={parentCollectionIds ?? []}
|
|
682
894
|
collection={collection}
|
|
@@ -689,33 +901,145 @@ export const EntityCollectionView = React.memo(
|
|
|
689
901
|
selectionEnabled={selectionEnabled}
|
|
690
902
|
collectionEntitiesCount={docsCount}
|
|
691
903
|
/>}
|
|
692
|
-
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
693
|
-
? <div className="flex flex-col items-center justify-center">
|
|
694
|
-
<Typography variant={"subtitle2"}>So empty...</Typography>
|
|
695
|
-
<Button
|
|
696
|
-
color={"primary"}
|
|
697
|
-
variant={"outlined"}
|
|
698
|
-
onClick={onNewClick}
|
|
699
|
-
className="mt-4"
|
|
700
|
-
>
|
|
701
|
-
<AddIcon/>
|
|
702
|
-
Create your first entry
|
|
703
|
-
</Button>
|
|
704
|
-
</div>
|
|
705
|
-
: <Typography variant={"label"}>No results with the applied filter/sort</Typography>
|
|
706
|
-
}
|
|
707
|
-
hoverRow={hoverRow}
|
|
708
|
-
inlineEditing={checkInlineEditing()}
|
|
709
|
-
AdditionalHeaderWidget={buildAdditionalHeaderWidget}
|
|
710
|
-
AddColumnComponent={addColumnComponentInternal}
|
|
711
|
-
getIdColumnWidth={getIdColumnWidth}
|
|
712
|
-
additionalIDHeaderWidget={<EntityIdHeaderWidget
|
|
713
|
-
path={fullPath}
|
|
714
|
-
fullIdPath={fullIdPath ?? fullPath}
|
|
715
|
-
collection={collection}/>}
|
|
716
|
-
openEntityMode={openEntityMode}
|
|
717
904
|
/>
|
|
718
905
|
|
|
906
|
+
{/* View content - only the view-specific content changes */}
|
|
907
|
+
{tableController.dataLoadingError ? (
|
|
908
|
+
pluginErrorView ?? <CollectionDataErrorBanner error={tableController.dataLoadingError} />
|
|
909
|
+
) : viewMode === "kanban" && enabledViews.includes("kanban") ? (
|
|
910
|
+
<EntityCollectionBoardView
|
|
911
|
+
key={`kanban-view-${fullPath}-${selectedKanbanProperty}`}
|
|
912
|
+
collection={collection}
|
|
913
|
+
tableController={tableController}
|
|
914
|
+
fullPath={fullPath}
|
|
915
|
+
parentCollectionIds={parentCollectionIds}
|
|
916
|
+
columnProperty={selectedKanbanProperty}
|
|
917
|
+
onEntityClick={onEntityClick}
|
|
918
|
+
selectionController={usedSelectionController}
|
|
919
|
+
selectionEnabled={selectionEnabled}
|
|
920
|
+
highlightedEntities={highlightedEntity ? [highlightedEntity] : []}
|
|
921
|
+
deletedEntities={deletedEntities}
|
|
922
|
+
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
923
|
+
? <div className="flex flex-col items-center justify-center">
|
|
924
|
+
<Typography variant={"subtitle2"}>{t("so_empty")}</Typography>
|
|
925
|
+
<Button
|
|
926
|
+
onClick={onNewClick}
|
|
927
|
+
className="mt-4"
|
|
928
|
+
>
|
|
929
|
+
<AddIcon />
|
|
930
|
+
{t("create_your_first_entry")}
|
|
931
|
+
</Button>
|
|
932
|
+
</div>
|
|
933
|
+
: <Typography variant={"label"}>{t("no_results_filter_sort")}</Typography>
|
|
934
|
+
}
|
|
935
|
+
/>
|
|
936
|
+
) : viewMode === "cards" ? (
|
|
937
|
+
<EntityCollectionCardView
|
|
938
|
+
key={`cards-view-${fullPath}`}
|
|
939
|
+
collection={collection}
|
|
940
|
+
tableController={tableController}
|
|
941
|
+
onEntityClick={onEntityClick}
|
|
942
|
+
selectionController={usedSelectionController}
|
|
943
|
+
selectionEnabled={selectionEnabled}
|
|
944
|
+
highlightedEntities={highlightedEntity ? [highlightedEntity] : []}
|
|
945
|
+
onScroll={tableController.onScroll}
|
|
946
|
+
initialScroll={tableController.initialScroll}
|
|
947
|
+
size={cardSize}
|
|
948
|
+
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
949
|
+
? <div className="flex flex-col items-center justify-center">
|
|
950
|
+
<Typography variant={"subtitle2"}>{t("so_empty")}</Typography>
|
|
951
|
+
<Button
|
|
952
|
+
onClick={onNewClick}
|
|
953
|
+
className="mt-4"
|
|
954
|
+
>
|
|
955
|
+
<AddIcon />
|
|
956
|
+
{t("create_your_first_entry")}
|
|
957
|
+
</Button>
|
|
958
|
+
</div>
|
|
959
|
+
: <Typography variant={"label"}>{t("no_results_filter_sort")}</Typography>
|
|
960
|
+
}
|
|
961
|
+
/>
|
|
962
|
+
) : (
|
|
963
|
+
<EntityCollectionTable
|
|
964
|
+
key={`collection_table_${fullPath}`}
|
|
965
|
+
hideToolbar={true}
|
|
966
|
+
additionalFields={additionalFields}
|
|
967
|
+
tableController={tableController}
|
|
968
|
+
enablePopupIcon={true}
|
|
969
|
+
displayedColumnIds={displayedColumnIds}
|
|
970
|
+
onSizeChanged={onTableSizeChanged}
|
|
971
|
+
onEntityClick={onEntityClick}
|
|
972
|
+
onColumnResize={onColumnResize}
|
|
973
|
+
onValueChange={onValueChange}
|
|
974
|
+
tableRowActionsBuilder={tableRowActionsBuilder}
|
|
975
|
+
uniqueFieldValidator={uniqueFieldValidator}
|
|
976
|
+
selectionController={usedSelectionController}
|
|
977
|
+
highlightedEntities={highlightedEntity ? [highlightedEntity] : []}
|
|
978
|
+
defaultSize={tableSize}
|
|
979
|
+
properties={resolvedCollection.properties}
|
|
980
|
+
getPropertyFor={getPropertyFor}
|
|
981
|
+
onTextSearchClick={textSearchInitialised ? undefined : onTextSearchClick}
|
|
982
|
+
onScroll={tableController.onScroll}
|
|
983
|
+
initialScroll={tableController.initialScroll}
|
|
984
|
+
textSearchLoading={textSearchLoading}
|
|
985
|
+
textSearchEnabled={textSearchEnabled}
|
|
986
|
+
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
987
|
+
? <div className="flex flex-col items-center justify-center">
|
|
988
|
+
<Typography variant={"subtitle2"}>{t("so_empty")}</Typography>
|
|
989
|
+
<Button
|
|
990
|
+
onClick={onNewClick}
|
|
991
|
+
className="mt-4"
|
|
992
|
+
>
|
|
993
|
+
<AddIcon />
|
|
994
|
+
{t("create_your_first_entry")}
|
|
995
|
+
</Button>
|
|
996
|
+
</div>
|
|
997
|
+
: <Typography variant={"label"}>{t("no_results_filter_sort")}</Typography>
|
|
998
|
+
}
|
|
999
|
+
hoverRow={hoverRow}
|
|
1000
|
+
inlineEditing={checkInlineEditing()}
|
|
1001
|
+
AdditionalHeaderWidget={buildAdditionalHeaderWidget}
|
|
1002
|
+
AddColumnComponent={addColumnComponentInternal}
|
|
1003
|
+
getIdColumnWidth={getIdColumnWidth}
|
|
1004
|
+
additionalIDHeaderWidget={<EntityIdHeaderWidget
|
|
1005
|
+
path={fullPath}
|
|
1006
|
+
fullIdPath={fullIdPath ?? fullPath}
|
|
1007
|
+
collection={collection} />}
|
|
1008
|
+
openEntityMode={openEntityMode}
|
|
1009
|
+
onColumnsOrderChange={(newColumns) => {
|
|
1010
|
+
// Extract property keys from the new column order
|
|
1011
|
+
// Filter to only include actual property columns (not frozen columns, not additional fields, etc.)
|
|
1012
|
+
// Deduplicate to clean up any previously duplicated keys
|
|
1013
|
+
const seenKeys = new Set<string>();
|
|
1014
|
+
const newPropertiesOrder = newColumns
|
|
1015
|
+
.filter(col => !col.frozen && getPropertyInPath(collection.properties, col.key))
|
|
1016
|
+
.map(col => col.key)
|
|
1017
|
+
.filter(key => {
|
|
1018
|
+
if (seenKeys.has(key)) return false;
|
|
1019
|
+
seenKeys.add(key);
|
|
1020
|
+
return true;
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
// Optimistically update local state to prevent UI flickering
|
|
1024
|
+
setLocalPropertiesOrder(newPropertiesOrder);
|
|
1025
|
+
|
|
1026
|
+
// Call each plugin's onColumnsReorder callback
|
|
1027
|
+
if (customizationController?.plugins) {
|
|
1028
|
+
customizationController.plugins
|
|
1029
|
+
.filter(plugin => plugin.collectionView?.onColumnsReorder)
|
|
1030
|
+
.forEach(plugin => {
|
|
1031
|
+
plugin.collectionView!.onColumnsReorder!({
|
|
1032
|
+
fullPath,
|
|
1033
|
+
parentCollectionIds: parentCollectionIds ?? [],
|
|
1034
|
+
collection,
|
|
1035
|
+
newPropertiesOrder
|
|
1036
|
+
});
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
}}
|
|
1040
|
+
/>
|
|
1041
|
+
)}
|
|
1042
|
+
|
|
719
1043
|
{popupCell && <PopupFormField
|
|
720
1044
|
key={`popup_form_${popupCell?.propertyKey}_${popupCell?.entityId}`}
|
|
721
1045
|
open={Boolean(popupCell)}
|
|
@@ -728,7 +1052,7 @@ export const EntityCollectionView = React.memo(
|
|
|
728
1052
|
customFieldValidator={uniqueFieldValidator}
|
|
729
1053
|
path={resolvedFullPath}
|
|
730
1054
|
onCellValueChange={onValueChange}
|
|
731
|
-
container={containerRef.current}/>}
|
|
1055
|
+
container={containerRef.current} />}
|
|
732
1056
|
|
|
733
1057
|
{deleteEntityClicked &&
|
|
734
1058
|
<DeleteEntityDialog
|
|
@@ -739,7 +1063,7 @@ export const EntityCollectionView = React.memo(
|
|
|
739
1063
|
open={Boolean(deleteEntityClicked)}
|
|
740
1064
|
onEntityDelete={internalOnEntityDelete}
|
|
741
1065
|
onMultipleEntitiesDelete={internalOnMultipleEntitiesDelete}
|
|
742
|
-
onClose={() => setDeleteEntityClicked(undefined)}/>}
|
|
1066
|
+
onClose={() => setDeleteEntityClicked(undefined)} />}
|
|
743
1067
|
|
|
744
1068
|
</div>
|
|
745
1069
|
);
|
|
@@ -769,12 +1093,12 @@ export const EntityCollectionView = React.memo(
|
|
|
769
1093
|
}) as React.FunctionComponent<EntityCollectionViewProps<any>>
|
|
770
1094
|
|
|
771
1095
|
function EntitiesCount({
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
1096
|
+
fullPath,
|
|
1097
|
+
collection,
|
|
1098
|
+
filter,
|
|
1099
|
+
sortBy,
|
|
1100
|
+
onCountChange
|
|
1101
|
+
}: {
|
|
778
1102
|
fullPath: string,
|
|
779
1103
|
collection: EntityCollection,
|
|
780
1104
|
filter?: FilterValues<any>,
|
|
@@ -803,9 +1127,9 @@ function EntitiesCount({
|
|
|
803
1127
|
}, [fullPath, dataSource.countEntities, resolvedPath, collection, filter, sortByProperty, currentSort]);
|
|
804
1128
|
|
|
805
1129
|
useEffect(() => {
|
|
806
|
-
if (onCountChange) {
|
|
1130
|
+
if (onCountChange && count !== undefined) {
|
|
807
1131
|
setError(undefined);
|
|
808
|
-
onCountChange(count
|
|
1132
|
+
onCountChange(count);
|
|
809
1133
|
}
|
|
810
1134
|
}, [onCountChange, count]);
|
|
811
1135
|
|
|
@@ -813,14 +1137,11 @@ function EntitiesCount({
|
|
|
813
1137
|
return null;
|
|
814
1138
|
}
|
|
815
1139
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
variant={"caption"}
|
|
819
|
-
color={"secondary"}>
|
|
820
|
-
{count !== undefined ? `${count} entities` : <Skeleton className={"w-full max-w-[80px] mt-1"}/>}
|
|
821
|
-
</Typography>;
|
|
1140
|
+
// Count is now displayed in the breadcrumb bar, this component only fetches and reports
|
|
1141
|
+
return null;
|
|
822
1142
|
}
|
|
823
1143
|
|
|
1144
|
+
|
|
824
1145
|
function buildPropertyWidthOverwrite(key: string, width: number): PartialEntityCollection {
|
|
825
1146
|
if (key.includes(".")) {
|
|
826
1147
|
const [parentKey, ...childKey] = key.split(".");
|
|
@@ -830,10 +1151,10 @@ function buildPropertyWidthOverwrite(key: string, width: number): PartialEntityC
|
|
|
830
1151
|
}
|
|
831
1152
|
|
|
832
1153
|
function EntityIdHeaderWidget({
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
1154
|
+
collection,
|
|
1155
|
+
path,
|
|
1156
|
+
fullIdPath
|
|
1157
|
+
}: {
|
|
837
1158
|
collection: EntityCollection,
|
|
838
1159
|
path: string,
|
|
839
1160
|
fullIdPath: string
|
|
@@ -844,11 +1165,12 @@ function EntityIdHeaderWidget({
|
|
|
844
1165
|
const [searchString, setSearchString] = React.useState("");
|
|
845
1166
|
const [recentIds, setRecentIds] = React.useState<string[]>(getRecentIds(collection.id));
|
|
846
1167
|
const sideEntityController = useSideEntityController();
|
|
1168
|
+
const { t } = useTranslation();
|
|
847
1169
|
|
|
848
1170
|
const openEntityMode = collection?.openEntityMode ?? DEFAULT_ENTITY_OPEN_MODE;
|
|
849
1171
|
|
|
850
1172
|
return (
|
|
851
|
-
<Tooltip title={!openPopup ? "
|
|
1173
|
+
<Tooltip title={!openPopup ? t("find_by_id") : undefined} asChild={false}>
|
|
852
1174
|
<Popover
|
|
853
1175
|
open={openPopup}
|
|
854
1176
|
onOpenChange={setOpenPopup}
|
|
@@ -857,65 +1179,65 @@ function EntityIdHeaderWidget({
|
|
|
857
1179
|
alignOffset={-117}
|
|
858
1180
|
trigger={
|
|
859
1181
|
<IconButton size={"small"}>
|
|
860
|
-
<SearchIcon size={"small"}/>
|
|
1182
|
+
<SearchIcon size={"small"} />
|
|
861
1183
|
</IconButton>
|
|
862
1184
|
}>
|
|
863
1185
|
<div
|
|
864
1186
|
className={cls("my-2 rounded-lg bg-surface-50 dark:bg-surface-950 text-surface-900 dark:text-white")}>
|
|
865
1187
|
<form noValidate={true}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
1188
|
+
onSubmit={(e) => {
|
|
1189
|
+
e.preventDefault();
|
|
1190
|
+
if (!searchString) return;
|
|
1191
|
+
setOpenPopup(false);
|
|
1192
|
+
const entityId = searchString.trim();
|
|
1193
|
+
setRecentIds(addRecentId(collection.id, entityId));
|
|
1194
|
+
navigateToEntity({
|
|
1195
|
+
openEntityMode,
|
|
1196
|
+
collection,
|
|
1197
|
+
entityId,
|
|
1198
|
+
path,
|
|
1199
|
+
fullIdPath,
|
|
1200
|
+
sideEntityController,
|
|
1201
|
+
navigation
|
|
1202
|
+
})
|
|
1203
|
+
}}
|
|
1204
|
+
className={"w-96 max-w-full"}>
|
|
883
1205
|
|
|
884
1206
|
<div className="flex p-2 w-full gap-2">
|
|
885
1207
|
<input
|
|
886
1208
|
autoFocus={openPopup}
|
|
887
|
-
placeholder={"
|
|
1209
|
+
placeholder={t("find_entity_by_id")}
|
|
888
1210
|
// size={"small"}
|
|
889
1211
|
onChange={(e) => {
|
|
890
1212
|
setSearchString(e.target.value);
|
|
891
1213
|
}}
|
|
892
1214
|
value={searchString}
|
|
893
|
-
className={"rounded-lg bg-white dark:bg-surface-800 flex-grow bg-transparent outline-none p-2 " + focusedDisabled}/>
|
|
1215
|
+
className={"rounded-lg bg-white dark:bg-surface-800 flex-grow bg-transparent outline-none p-2 " + focusedDisabled} />
|
|
894
1216
|
<Button variant={"text"}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
><KeyboardTabIcon/></Button>
|
|
1217
|
+
disabled={!(searchString.trim())}
|
|
1218
|
+
type={"submit"}
|
|
1219
|
+
><KeyboardTabIcon /></Button>
|
|
898
1220
|
</div>
|
|
899
1221
|
</form>
|
|
900
1222
|
{recentIds && recentIds.length > 0 && <div className="flex flex-col gap-2 p-2">
|
|
901
1223
|
{recentIds.map(id => (
|
|
902
1224
|
<ReferencePreview reference={new EntityReference(id, path)}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1225
|
+
key={id}
|
|
1226
|
+
hover={true}
|
|
1227
|
+
onClick={() => {
|
|
1228
|
+
setOpenPopup(false);
|
|
1229
|
+
navigateToEntity({
|
|
1230
|
+
openEntityMode,
|
|
1231
|
+
collection,
|
|
1232
|
+
entityId: id,
|
|
1233
|
+
path,
|
|
1234
|
+
fullIdPath,
|
|
1235
|
+
sideEntityController,
|
|
1236
|
+
navigation
|
|
1237
|
+
})
|
|
1238
|
+
}}
|
|
1239
|
+
includeEntityLink={false}
|
|
1240
|
+
size={"small"} />
|
|
919
1241
|
))}
|
|
920
1242
|
</div>}
|
|
921
1243
|
</div>
|