@rebasepro/admin 0.1.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -6
- package/dist/{CollectionEditorDialog-ywdxhs1L.js → CollectionEditorDialog-CmGXXSY9.js} +42 -209
- package/dist/CollectionEditorDialog-CmGXXSY9.js.map +1 -0
- package/dist/{CollectionsStudioView-BDzMFzqH.js → CollectionsStudioView-DcLHT5bU.js} +6 -8
- package/dist/CollectionsStudioView-DcLHT5bU.js.map +1 -0
- package/dist/{ContentHomePage-0tHuEIm_.js → ContentHomePage-C7vFqKSe.js} +5 -7
- package/dist/ContentHomePage-C7vFqKSe.js.map +1 -0
- package/dist/{ExportCollectionAction-BIrq92To.js → ExportCollectionAction-BfN34eWX.js} +36 -38
- package/dist/ExportCollectionAction-BfN34eWX.js.map +1 -0
- package/dist/{ImportCollectionAction-h8yg_To8.js → ImportCollectionAction-SZrInjhx.js} +5 -7
- package/dist/ImportCollectionAction-SZrInjhx.js.map +1 -0
- package/dist/{PropertyEditView-BuZrNnBN.js → PropertyEditView-Cvryrb3B.js} +563 -489
- package/dist/PropertyEditView-Cvryrb3B.js.map +1 -0
- package/dist/{RolesView-CMPsaIXo.js → RolesView-BCb7qwWs.js} +22 -11
- package/dist/RolesView-BCb7qwWs.js.map +1 -0
- package/dist/{UsersView-BkeblMVT.js → UsersView-Cex24r8H.js} +7 -71
- package/dist/UsersView-Cex24r8H.js.map +1 -0
- package/dist/collection_editor/ui/collection_editor/LayoutModeSwitch.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/properties/RelationPropertyField.d.ts +1 -7
- package/dist/collection_editor/ui/collection_editor/properties/VectorPropertyField.d.ts +3 -0
- package/dist/collection_editor_ui.js +5 -5
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionListView.d.ts +18 -2
- package/dist/components/EntityCollectionView/FilterPresetsButton.d.ts +21 -0
- package/dist/components/EntityDetailView.d.ts +31 -0
- package/dist/components/EntityEditView.d.ts +3 -2
- package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +1 -1
- package/dist/components/admin/CreationResultDialog.d.ts +5 -0
- package/dist/components/admin/RolesFilterSelect.d.ts +2 -0
- package/dist/components/admin/UserRolesSelectField.d.ts +2 -0
- package/dist/components/common/default_entity_actions.d.ts +7 -1
- package/dist/components/field_configs.d.ts +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/data_import/utils/data.d.ts +1 -1
- package/dist/data_import/utils/file_headers.d.ts +6 -1
- package/dist/data_import/utils/file_to_json.d.ts +1 -11
- package/dist/data_import/utils/transforms.d.ts +11 -0
- package/dist/editor.js +2 -4
- package/dist/editor.js.map +1 -1
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/VectorFieldBinding.d.ts +11 -0
- package/dist/form/index.d.ts +1 -0
- package/dist/hooks/navigation/useResolvedViews.d.ts +2 -1
- package/dist/{index-eRJbMvHi.js → index-DjduZG1T.js} +3 -3
- package/dist/index-DjduZG1T.js.map +1 -0
- package/dist/{index-BuZaHcyc.js → index-MKPc70-v.js} +3 -3
- package/dist/index-MKPc70-v.js.map +1 -0
- package/dist/{index-CS6uJ7oW.js → index-PLIQXpTt.js} +4 -6
- package/dist/index-PLIQXpTt.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +352 -148
- package/dist/index.js.map +1 -1
- package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
- package/dist/types/components/EntityFormProps.d.ts +2 -1
- package/dist/types/fields.d.ts +3 -3
- package/dist/util/navigation_utils.d.ts +1 -1
- package/dist/{util-zfU1zOCX.js → util-DbWax_sV.js} +5453 -2641
- package/dist/util-DbWax_sV.js.map +1 -0
- package/package.json +46 -39
- package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
- package/src/collection_editor/ui/AddKanbanColumnAction.tsx +12 -2
- package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +1 -2
- package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -2
- package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -2
- package/src/collection_editor/ui/EditorEntityAction.tsx +1 -2
- package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +1 -2
- package/src/collection_editor/ui/NewCollectionButton.tsx +1 -2
- package/src/collection_editor/ui/NewCollectionCard.tsx +4 -6
- package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +10 -2
- package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +18 -2
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +23 -17
- package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +16 -2
- package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +19 -9
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +13 -2
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +24 -2
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +22 -3
- package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +11 -2
- package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +12 -2
- package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +16 -3
- package/src/collection_editor/ui/collection_editor/EnumForm.tsx +17 -2
- package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +18 -2
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +17 -5
- package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +32 -6
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +7 -7
- package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +14 -2
- package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +16 -2
- package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +9 -2
- package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +9 -2
- package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +37 -57
- package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +11 -2
- package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +34 -0
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +15 -7
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +15 -3
- package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +1 -1
- package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -2
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -2
- package/src/collection_editor/validateCollectionJson.ts +97 -10
- package/src/components/AdminModeSyncer.tsx +1 -1
- package/src/components/ArrayContainer.tsx +19 -15
- package/src/components/ClearFilterSortButton.tsx +1 -2
- package/src/components/CollectionEditorDialogs.tsx +1 -1
- package/src/components/DefaultAppBar.tsx +15 -3
- package/src/components/DefaultDrawer.tsx +3 -3
- package/src/components/DrawerNavigationGroup.tsx +1 -2
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +14 -6
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +1 -1
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
- package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/VirtualTableSelect.tsx +0 -1
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +15 -27
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +1 -2
- package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -2
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
- package/src/components/EntityCollectionTable/table_bindings.tsx +51 -45
- package/src/components/EntityCollectionView/Board.tsx +1 -2
- package/src/components/EntityCollectionView/BoardColumn.tsx +9 -2
- package/src/components/EntityCollectionView/BoardColumnTitle.tsx +5 -4
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +18 -16
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +16 -17
- package/src/components/EntityCollectionView/EntityCollectionListView.tsx +87 -18
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +20 -11
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +6 -7
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +14 -5
- package/src/components/EntityCollectionView/FilterPresetsButton.tsx +292 -0
- package/src/components/EntityCollectionView/FiltersDialog.tsx +1 -2
- package/src/components/EntityCollectionView/SplitListView.tsx +76 -25
- package/src/components/EntityCollectionView/ViewModeToggle.tsx +20 -7
- package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +1 -1
- package/src/components/EntityCollectionView/useBoardDataController.tsx +74 -6
- package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +1 -1
- package/src/components/EntityDetailView.tsx +619 -0
- package/src/components/EntityEditView.tsx +29 -10
- package/src/components/EntityEditViewFormActions.tsx +20 -7
- package/src/components/EntityPreview.tsx +14 -5
- package/src/components/EntitySidePanel.tsx +116 -62
- package/src/components/EntityView.tsx +1 -2
- package/src/components/HomePage/ContentHomePage.tsx +1 -1
- package/src/components/HomePage/FavouritesView.tsx +1 -2
- package/src/components/HomePage/NavigationCard.tsx +1 -2
- package/src/components/HomePage/NavigationCardBinding.tsx +1 -2
- package/src/components/HomePage/NavigationGroup.tsx +1 -2
- package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
- package/src/components/PropertyIdCopyTooltip.tsx +1 -2
- package/src/components/RebaseAuthGate.tsx +2 -2
- package/src/components/RebaseNavigation.tsx +9 -7
- package/src/components/ReferenceTable/EntitySelectionTable.tsx +12 -8
- package/src/components/RelationSelector.tsx +34 -6
- package/src/components/SearchIconsView.tsx +10 -2
- package/src/components/SelectableTable/SelectableTable.tsx +2 -2
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
- package/src/components/SideDialogs.tsx +63 -38
- package/src/components/UserSelector.tsx +30 -6
- package/src/components/admin/CreationResultDialog.tsx +135 -0
- package/src/components/admin/RolesFilterSelect.tsx +45 -0
- package/src/components/admin/RolesView.tsx +53 -14
- package/src/components/admin/UserRolesSelectField.tsx +50 -0
- package/src/components/admin/UsersView.tsx +41 -124
- package/src/components/app/Scaffold.tsx +1 -2
- package/src/components/common/default_entity_actions.tsx +119 -12
- package/src/components/field_configs.tsx +39 -3
- package/src/components/history/EntityHistoryEntry.tsx +1 -2
- package/src/components/history/EntityHistoryView.tsx +1 -2
- package/src/components/index.ts +2 -0
- package/src/data_export/export/BasicExportAction.tsx +35 -38
- package/src/data_export/export/ExportCollectionAction.tsx +39 -40
- package/src/data_import/components/DataNewPropertiesMapping.tsx +15 -2
- package/src/data_import/components/ImportFileUpload.tsx +1 -2
- package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +1 -2
- package/src/data_import/import/ImportCollectionAction.tsx +21 -8
- package/src/data_import/utils/data.ts +23 -5
- package/src/data_import/utils/file_headers.ts +13 -89
- package/src/data_import/utils/file_to_json.ts +43 -68
- package/src/data_import/utils/transforms.ts +47 -0
- package/src/editor/components/SlashCommandMenu.tsx +17 -2
- package/src/editor/components/editor-bubble-item.tsx +1 -1
- package/src/editor/extensions/Image/index.ts +1 -1
- package/src/editor/extensions/Image.ts +1 -1
- package/src/editor/selectors/color-selector.tsx +1 -2
- package/src/editor/selectors/link-selector.tsx +1 -2
- package/src/editor/selectors/node-selector.tsx +16 -2
- package/src/editor/selectors/text-buttons.tsx +1 -2
- package/src/editor/utils/prosemirror-utils.ts +1 -1
- package/src/form/EntityForm.tsx +16 -6
- package/src/form/EntityFormActions.tsx +11 -3
- package/src/form/PropertyFieldBinding.tsx +5 -12
- package/src/form/components/FieldHelperText.tsx +1 -2
- package/src/form/components/LocalChangesMenu.tsx +17 -2
- package/src/form/components/StorageItemPreview.tsx +1 -2
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -2
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +17 -2
- package/src/form/field_bindings/MapFieldBinding.tsx +1 -1
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +10 -3
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -2
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -2
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
- package/src/form/field_bindings/RelationFieldBinding.tsx +150 -147
- package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
- package/src/form/field_bindings/SelectFieldBinding.tsx +1 -2
- package/src/form/field_bindings/TextFieldBinding.tsx +10 -2
- package/src/form/field_bindings/VectorFieldBinding.tsx +202 -0
- package/src/form/index.tsx +1 -0
- package/src/form/validation.ts +54 -2
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +2 -1
- package/src/hooks/navigation/useResolvedViews.tsx +30 -15
- package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
- package/src/index.ts +6 -0
- package/src/preview/PropertyPreview.tsx +1 -1
- package/src/preview/components/ImagePreview.tsx +1 -1
- package/src/preview/components/UrlComponentPreview.tsx +1 -2
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +23 -24
- package/src/routes/RebaseRoute.tsx +64 -35
- package/src/types/components/EntityFormActionsProps.tsx +1 -1
- package/src/types/components/EntityFormProps.tsx +3 -1
- package/src/types/fields.tsx +4 -3
- package/src/util/navigation_utils.ts +4 -3
- package/src/util/previews.ts +1 -1
- package/src/util/property_utils.tsx +22 -6
- package/src/util/resolutions.ts +2 -2
- package/dist/CollectionEditorDialog-ywdxhs1L.js.map +0 -1
- package/dist/CollectionsStudioView-BDzMFzqH.js.map +0 -1
- package/dist/ContentHomePage-0tHuEIm_.js.map +0 -1
- package/dist/ExportCollectionAction-BIrq92To.js.map +0 -1
- package/dist/ImportCollectionAction-h8yg_To8.js.map +0 -1
- package/dist/PropertyEditView-BuZrNnBN.js.map +0 -1
- package/dist/RolesView-CMPsaIXo.js.map +0 -1
- package/dist/UsersView-BkeblMVT.js.map +0 -1
- package/dist/index-BuZaHcyc.js.map +0 -1
- package/dist/index-CS6uJ7oW.js.map +0 -1
- package/dist/index-eRJbMvHi.js.map +0 -1
- package/dist/util-zfU1zOCX.js.map +0 -1
|
@@ -4,7 +4,7 @@ import type { FormContext, PropertyFieldBindingProps } from "../../../../types/f
|
|
|
4
4
|
import type { Property } from "@rebasepro/types";
|
|
5
5
|
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useState } from "react";
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import { Button, DialogActions, IconButton, Portal, Typography, XIcon } from "@rebasepro/ui";
|
|
8
8
|
|
|
9
9
|
import { Entity, EntityValues } from "@rebasepro/types";
|
|
10
10
|
import { PluginProviderStack } from "@rebasepro/core";
|
|
@@ -13,8 +13,6 @@ import { useDraggable } from "./useDraggable";
|
|
|
13
13
|
import { CustomFieldValidator, getEntitySchema } from "../../../../form/validation";
|
|
14
14
|
import { useWindowSize } from "./useWindowSize";
|
|
15
15
|
import { getPropertyInPath } from "../../../../util/property_utils";
|
|
16
|
-
import { Button, DialogActions, IconButton, Typography } from "@rebasepro/ui";
|
|
17
|
-
import { XIcon } from "lucide-react";
|
|
18
16
|
import { PropertyFieldBinding, zodToFormErrors } from "../../../../form";
|
|
19
17
|
import { useAuthController, useCustomizationController, useData, useRebaseContext } from "@rebasepro/core";
|
|
20
18
|
import type { OnCellValueChangeParams } from "@rebasepro/core";
|
|
@@ -61,7 +59,7 @@ export function PopupFormFieldLoading<M extends Record<string, unknown>>({
|
|
|
61
59
|
const [entity, setEntity] = useState<Entity<M> | undefined>(undefined);
|
|
62
60
|
useEffect(() => {
|
|
63
61
|
if (entityId && inputCollection) {
|
|
64
|
-
dataClient.collection(path).findById(entityId).then(setEntity as
|
|
62
|
+
dataClient.collection(path).findById(entityId).then((result) => setEntity(result as Entity<M> | undefined));
|
|
65
63
|
}
|
|
66
64
|
}, [entityId, inputCollection, dataClient, path]);
|
|
67
65
|
|
|
@@ -409,7 +407,7 @@ export function PopupFormFieldInternal<M extends Record<string, unknown>>({
|
|
|
409
407
|
return (
|
|
410
408
|
<Portal.Root asChild
|
|
411
409
|
container={container}>
|
|
412
|
-
<Formex value={formex as
|
|
410
|
+
<Formex value={formex as FormexController<Record<string, unknown>>}>
|
|
413
411
|
{draggable}
|
|
414
412
|
</Formex>
|
|
415
413
|
</Portal.Root>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { ArrayProperty, Entity, EntityReference, EntityRelation, NumberProperty, Property, StringProperty } from "@rebasepro/types";
|
|
2
|
+
import { ArrayProperty, DateProperty, Entity, EntityReference, EntityRelation, NumberProperty, Property, ReferenceProperty, RelationProperty, StringProperty } from "@rebasepro/types";
|
|
3
3
|
|
|
4
4
|
import { VirtualTableInput } from "./fields/VirtualTableInput";
|
|
5
5
|
import { VirtualTableSelect } from "./fields/VirtualTableSelect";
|
|
@@ -64,10 +64,11 @@ export function getTableBindingForProperty(
|
|
|
64
64
|
|
|
65
65
|
if (property.type === "string" && (property as StringProperty).reference?.path) {
|
|
66
66
|
return {
|
|
67
|
-
Component: ({ propertyKey, property, internalValue, updateValue, disabled, size, path }) => {
|
|
68
|
-
const referenceProperty = (property as StringProperty).reference
|
|
67
|
+
Component: ({ propertyKey, property, internalValue, updateValue, disabled, size, path }: TableFieldBindingProps) => {
|
|
68
|
+
const referenceProperty = (property as StringProperty).reference;
|
|
69
|
+
if (!referenceProperty) return null;
|
|
69
70
|
const referenceValue = internalValue ? new EntityReference({ id: internalValue as string,
|
|
70
|
-
path: referenceProperty.path as string }) : undefined;
|
|
71
|
+
path: referenceProperty.path as string }) : undefined;
|
|
71
72
|
return (
|
|
72
73
|
<TableReferenceField
|
|
73
74
|
name={propertyKey}
|
|
@@ -77,7 +78,7 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
77
78
|
size={size}
|
|
78
79
|
path={referenceProperty.path as string}
|
|
79
80
|
multiselect={false}
|
|
80
|
-
previewProperties={referenceProperty.previewProperties}
|
|
81
|
+
previewProperties={referenceProperty.ui?.previewProperties}
|
|
81
82
|
includeId={referenceProperty.includeId}
|
|
82
83
|
includeEntityLink={referenceProperty.includeEntityLink}
|
|
83
84
|
title={property.name}
|
|
@@ -89,14 +90,14 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
89
90
|
};
|
|
90
91
|
} else if (isAStorageProperty) {
|
|
91
92
|
return {
|
|
92
|
-
Component: ({ validationError, error, disabled, selected, openPopup, property, entity, path, internalValue, size, updateValue, propertyKey }:
|
|
93
|
+
Component: ({ validationError, error, disabled, selected, openPopup, property, entity, path, internalValue, size, updateValue, propertyKey }: TableFieldBindingProps) => (
|
|
93
94
|
<TableStorageUpload
|
|
94
95
|
error={validationError ?? error}
|
|
95
96
|
disabled={disabled}
|
|
96
97
|
focused={selected}
|
|
97
98
|
selected={selected}
|
|
98
99
|
openPopup={openPopup}
|
|
99
|
-
property={property as
|
|
100
|
+
property={property as StringProperty | ArrayProperty}
|
|
100
101
|
entity={entity}
|
|
101
102
|
path={path}
|
|
102
103
|
value={internalValue}
|
|
@@ -114,7 +115,7 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
114
115
|
const numberProperty = property as NumberProperty;
|
|
115
116
|
if (numberProperty.enum) {
|
|
116
117
|
return {
|
|
117
|
-
Component: ({ propertyKey, disabled, selected, size, error, validationError, internalValue, updateValue }:
|
|
118
|
+
Component: ({ propertyKey, disabled, selected, size, error, validationError, internalValue, updateValue }: TableFieldBindingProps) => (
|
|
118
119
|
<VirtualTableSelect
|
|
119
120
|
name={propertyKey}
|
|
120
121
|
multiple={false}
|
|
@@ -132,7 +133,7 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
132
133
|
};
|
|
133
134
|
} else {
|
|
134
135
|
return {
|
|
135
|
-
Component: ({ align, error, validationError, selected, disabled, internalValue, updateValue }:
|
|
136
|
+
Component: ({ align, error, validationError, selected, disabled, internalValue, updateValue }: TableFieldBindingProps) => (
|
|
136
137
|
<VirtualTableNumberInput
|
|
137
138
|
align={align}
|
|
138
139
|
error={validationError ?? error}
|
|
@@ -149,7 +150,7 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
149
150
|
const stringProperty = property as StringProperty;
|
|
150
151
|
if (stringProperty.enum) {
|
|
151
152
|
return {
|
|
152
|
-
Component: ({ propertyKey, disabled, selected, size, error, validationError, internalValue, updateValue }:
|
|
153
|
+
Component: ({ propertyKey, disabled, selected, size, error, validationError, internalValue, updateValue }: TableFieldBindingProps) => (
|
|
153
154
|
<VirtualTableSelect
|
|
154
155
|
name={propertyKey}
|
|
155
156
|
multiple={false}
|
|
@@ -167,7 +168,7 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
167
168
|
};
|
|
168
169
|
} else if (stringProperty.userSelect) {
|
|
169
170
|
return {
|
|
170
|
-
Component: ({ propertyKey, disabled, selected, size, error, validationError, internalValue, updateValue }:
|
|
171
|
+
Component: ({ propertyKey, disabled, selected, size, error, validationError, internalValue, updateValue }: TableFieldBindingProps) => (
|
|
171
172
|
<VirtualTableUserSelect
|
|
172
173
|
name={propertyKey}
|
|
173
174
|
multiple={false}
|
|
@@ -184,7 +185,7 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
184
185
|
} else if (stringProperty.ui?.markdown || !stringProperty.storage || !stringProperty.reference) {
|
|
185
186
|
const multiline = Boolean(stringProperty.ui?.multiline) || Boolean(stringProperty.ui?.markdown);
|
|
186
187
|
return {
|
|
187
|
-
Component: ({ error, validationError, disabled, selected, internalValue, updateValue }:
|
|
188
|
+
Component: ({ error, validationError, disabled, selected, internalValue, updateValue }: TableFieldBindingProps) => (
|
|
188
189
|
<VirtualTableInput
|
|
189
190
|
error={validationError ?? error}
|
|
190
191
|
disabled={disabled}
|
|
@@ -199,7 +200,7 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
199
200
|
}
|
|
200
201
|
} else if (property.type === "boolean") {
|
|
201
202
|
return {
|
|
202
|
-
Component: ({ error, validationError, disabled, selected, internalValue, updateValue }:
|
|
203
|
+
Component: ({ error, validationError, disabled, selected, internalValue, updateValue }: TableFieldBindingProps) => (
|
|
203
204
|
<VirtualTableSwitch
|
|
204
205
|
error={validationError ?? error}
|
|
205
206
|
disabled={disabled}
|
|
@@ -211,12 +212,12 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
211
212
|
};
|
|
212
213
|
} else if (property.type === "date") {
|
|
213
214
|
return {
|
|
214
|
-
Component: ({ propertyKey, error, validationError, disabled, selected, property, internalValue, updateValue }:
|
|
215
|
+
Component: ({ propertyKey, error, validationError, disabled, selected, property, internalValue, updateValue }: TableFieldBindingProps) => (
|
|
215
216
|
<VirtualTableDateField
|
|
216
217
|
name={propertyKey}
|
|
217
218
|
error={validationError ?? error}
|
|
218
219
|
disabled={disabled}
|
|
219
|
-
mode={property.mode}
|
|
220
|
+
mode={(property as DateProperty).mode}
|
|
220
221
|
focused={selected}
|
|
221
222
|
internalValue={internalValue as Date}
|
|
222
223
|
updateValue={updateValue}
|
|
@@ -227,30 +228,32 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
227
228
|
allowScroll: false
|
|
228
229
|
};
|
|
229
230
|
} else if (property.type === "reference") {
|
|
230
|
-
if (
|
|
231
|
+
if ((property as ReferenceProperty).path) {
|
|
231
232
|
return {
|
|
232
|
-
Component: ({ propertyKey, internalValue, updateValue, disabled, size, property }:
|
|
233
|
+
Component: ({ propertyKey, internalValue, updateValue, disabled, size, property }: TableFieldBindingProps) => {
|
|
234
|
+
return (
|
|
233
235
|
<TableReferenceField
|
|
234
236
|
name={propertyKey}
|
|
235
237
|
internalValue={internalValue as EntityReference}
|
|
236
238
|
updateValue={updateValue}
|
|
237
239
|
disabled={disabled}
|
|
238
240
|
size={size}
|
|
239
|
-
path={property.path}
|
|
241
|
+
path={(property as ReferenceProperty).path!}
|
|
240
242
|
multiselect={false}
|
|
241
|
-
previewProperties={property.ui?.previewProperties}
|
|
242
|
-
includeId={property.includeId}
|
|
243
|
-
includeEntityLink={property.includeEntityLink}
|
|
243
|
+
previewProperties={(property as ReferenceProperty).ui?.previewProperties}
|
|
244
|
+
includeId={(property as ReferenceProperty).includeId}
|
|
245
|
+
includeEntityLink={(property as ReferenceProperty).includeEntityLink}
|
|
244
246
|
title={property.name ?? propertyKey}
|
|
245
|
-
fixedFilter={property.fixedFilter}
|
|
247
|
+
fixedFilter={(property as ReferenceProperty).fixedFilter}
|
|
246
248
|
/>
|
|
247
|
-
|
|
249
|
+
);
|
|
250
|
+
},
|
|
248
251
|
allowScroll: false
|
|
249
252
|
};
|
|
250
253
|
}
|
|
251
254
|
} else if (property.type === "relation") {
|
|
252
|
-
if (property.relation) {
|
|
253
|
-
if (property.ui?.widget === "dialog") {
|
|
255
|
+
if ((property as RelationProperty).relation) {
|
|
256
|
+
if ((property as RelationProperty).ui?.widget === "dialog") {
|
|
254
257
|
return {
|
|
255
258
|
Component: RelationDialogBindingComponent,
|
|
256
259
|
allowScroll: false
|
|
@@ -268,11 +271,11 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
268
271
|
if (!arrayProperty.of && !arrayProperty.oneOf) {
|
|
269
272
|
throw Error("You need to specify an 'of' or 'oneOf' prop (or specify a custom field) in your array property");
|
|
270
273
|
} else if (arrayProperty.of && !Array.isArray(arrayProperty.of)) {
|
|
271
|
-
const ofProp = arrayProperty.of as
|
|
274
|
+
const ofProp = arrayProperty.of as Property;
|
|
272
275
|
if (ofProp.type === "string" || ofProp.type === "number") {
|
|
273
276
|
if (selected && ofProp.enum) {
|
|
274
277
|
return {
|
|
275
|
-
Component: ({ propertyKey, disabled, selected, size, error, validationError, internalValue, updateValue }:
|
|
278
|
+
Component: ({ propertyKey, disabled, selected, size, error, validationError, internalValue, updateValue }: TableFieldBindingProps) => (
|
|
276
279
|
<VirtualTableSelect
|
|
277
280
|
name={propertyKey}
|
|
278
281
|
multiple={true}
|
|
@@ -280,7 +283,7 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
280
283
|
focused={selected}
|
|
281
284
|
small={getPreviewSizeFrom(size) !== "medium"}
|
|
282
285
|
valueType={ofProp.type}
|
|
283
|
-
enumValues={ofProp.enum}
|
|
286
|
+
enumValues={ofProp.enum!}
|
|
284
287
|
error={validationError ?? error}
|
|
285
288
|
internalValue={internalValue as string | number}
|
|
286
289
|
updateValue={updateValue}
|
|
@@ -292,9 +295,10 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
292
295
|
};
|
|
293
296
|
}
|
|
294
297
|
} else if (ofProp.type === "reference") {
|
|
295
|
-
|
|
298
|
+
const refOfProp = ofProp as ReferenceProperty;
|
|
299
|
+
if (refOfProp.path) {
|
|
296
300
|
return {
|
|
297
|
-
Component: ({ propertyKey, disabled, internalValue, updateValue, size }:
|
|
301
|
+
Component: ({ propertyKey, disabled, internalValue, updateValue, size }: TableFieldBindingProps) => (
|
|
298
302
|
<TableReferenceField
|
|
299
303
|
name={propertyKey}
|
|
300
304
|
disabled={disabled}
|
|
@@ -302,12 +306,12 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
302
306
|
updateValue={updateValue}
|
|
303
307
|
size={size}
|
|
304
308
|
multiselect={true}
|
|
305
|
-
path={
|
|
306
|
-
previewProperties={
|
|
309
|
+
path={refOfProp.path!}
|
|
310
|
+
previewProperties={refOfProp.ui?.previewProperties}
|
|
307
311
|
title={arrayProperty.name}
|
|
308
|
-
fixedFilter={
|
|
309
|
-
includeId={
|
|
310
|
-
includeEntityLink={
|
|
312
|
+
fixedFilter={refOfProp.fixedFilter}
|
|
313
|
+
includeId={refOfProp.includeId}
|
|
314
|
+
includeEntityLink={refOfProp.includeEntityLink}
|
|
311
315
|
/>
|
|
312
316
|
),
|
|
313
317
|
allowScroll: false
|
|
@@ -321,7 +325,8 @@ path: referenceProperty.path as string }) : undefined;
|
|
|
321
325
|
}
|
|
322
326
|
|
|
323
327
|
/** Stable component for relation fields rendered with the dialog widget */
|
|
324
|
-
function RelationDialogBindingComponent({ propertyKey, internalValue, updateValue, disabled, size, property }:
|
|
328
|
+
function RelationDialogBindingComponent({ propertyKey, internalValue, updateValue, disabled, size, property }: TableFieldBindingProps) {
|
|
329
|
+
const relProp = property as RelationProperty;
|
|
325
330
|
return (
|
|
326
331
|
<TableRelationField
|
|
327
332
|
name={propertyKey}
|
|
@@ -330,18 +335,19 @@ function RelationDialogBindingComponent({ propertyKey, internalValue, updateValu
|
|
|
330
335
|
disabled={disabled}
|
|
331
336
|
size={size}
|
|
332
337
|
multiselect={false}
|
|
333
|
-
relation={
|
|
334
|
-
previewProperties={
|
|
335
|
-
includeId={
|
|
336
|
-
includeEntityLink={
|
|
337
|
-
title={
|
|
338
|
-
fixedFilter={
|
|
338
|
+
relation={relProp.relation!}
|
|
339
|
+
previewProperties={relProp.ui?.previewProperties}
|
|
340
|
+
includeId={relProp.includeId}
|
|
341
|
+
includeEntityLink={relProp.includeEntityLink}
|
|
342
|
+
title={relProp.name ?? propertyKey}
|
|
343
|
+
fixedFilter={relProp.fixedFilter}
|
|
339
344
|
/>
|
|
340
345
|
);
|
|
341
346
|
}
|
|
342
347
|
|
|
343
348
|
/** Stable component for relation fields rendered with the inline selector */
|
|
344
|
-
function RelationSelectorBindingComponent({ propertyKey, internalValue, updateValue, disabled, property }:
|
|
349
|
+
function RelationSelectorBindingComponent({ propertyKey, internalValue, updateValue, disabled, property }: TableFieldBindingProps) {
|
|
350
|
+
const relProp = property as RelationProperty;
|
|
345
351
|
return (
|
|
346
352
|
<TableRelationSelectorField
|
|
347
353
|
name={propertyKey}
|
|
@@ -349,8 +355,8 @@ function RelationSelectorBindingComponent({ propertyKey, internalValue, updateVa
|
|
|
349
355
|
updateValue={updateValue}
|
|
350
356
|
disabled={disabled}
|
|
351
357
|
size={"small"}
|
|
352
|
-
relation={
|
|
353
|
-
fixedFilter={
|
|
358
|
+
relation={relProp.relation!}
|
|
359
|
+
fixedFilter={relProp.fixedFilter}
|
|
354
360
|
/>
|
|
355
361
|
);
|
|
356
362
|
}
|
|
@@ -148,7 +148,6 @@ export function Board<M extends Record<string, unknown>, COLUMN extends string>(
|
|
|
148
148
|
}
|
|
149
149
|
return updated;
|
|
150
150
|
});
|
|
151
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
152
151
|
}, [data, columnsProp, assignColumn]);
|
|
153
152
|
|
|
154
153
|
const findColumnByItemId = (id: string): string | undefined => {
|
|
@@ -328,7 +327,7 @@ export function Board<M extends Record<string, unknown>, COLUMN extends string>(
|
|
|
328
327
|
const overColumn = findColumnByItemId(overId) || currentColumn;
|
|
329
328
|
|
|
330
329
|
|
|
331
|
-
|
|
330
|
+
const finalItemMapState = { ...itemMapState };
|
|
332
331
|
|
|
333
332
|
if (currentColumn && currentColumn === overColumn) {
|
|
334
333
|
// Use dnd-kit's sortable indexes if available to avoid race conditions with mutating handleDragOver
|
|
@@ -4,8 +4,15 @@ import { CSS } from "@dnd-kit/utilities";
|
|
|
4
4
|
import { BoardSortableList } from "./BoardSortableList";
|
|
5
5
|
import { BoardColumnTitle } from "./BoardColumnTitle";
|
|
6
6
|
import { BoardItem, BoardItemViewProps } from "./board_types";
|
|
7
|
-
import {
|
|
8
|
-
|
|
7
|
+
import {
|
|
8
|
+
ChipColorKey,
|
|
9
|
+
ChipColorScheme,
|
|
10
|
+
cls,
|
|
11
|
+
defaultBorderMixin,
|
|
12
|
+
IconButton,
|
|
13
|
+
iconSize,
|
|
14
|
+
PlusIcon
|
|
15
|
+
} from "@rebasepro/ui";
|
|
9
16
|
|
|
10
17
|
export interface BoardColumnProps<M extends Record<string, unknown>> {
|
|
11
18
|
id: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChipColorKey, ChipColorScheme, getColorSchemeForKey, cls } from "@rebasepro/ui";
|
|
1
|
+
import { ChipColorKey, ChipColorScheme, getColorSchemeForKey, cls, Typography } from "@rebasepro/ui";
|
|
2
2
|
import React, { useMemo } from "react";
|
|
3
3
|
|
|
4
4
|
export interface BoardColumnTitleProps {
|
|
@@ -23,10 +23,11 @@ export function BoardColumnTitle({
|
|
|
23
23
|
}, [color]);
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
|
-
<
|
|
26
|
+
<Typography
|
|
27
|
+
variant="subtitle2"
|
|
28
|
+
component="h4"
|
|
27
29
|
className={
|
|
28
30
|
cls("py-3 px-3 transition-colors duration-200 flex-grow select-none relative outline-none focus:outline focus:outline-2 focus:outline-offset-2 flex items-center gap-3",
|
|
29
|
-
"text-sm font-semibold text-surface-900 dark:text-surface-200",
|
|
30
31
|
className)
|
|
31
32
|
}
|
|
32
33
|
{...props}
|
|
@@ -40,6 +41,6 @@ export function BoardColumnTitle({
|
|
|
40
41
|
/>
|
|
41
42
|
)}
|
|
42
43
|
{children}
|
|
43
|
-
</
|
|
44
|
+
</Typography>
|
|
44
45
|
);
|
|
45
46
|
}
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
|
|
2
2
|
import type { EntityCollection } from "@rebasepro/types";
|
|
3
|
-
import type { Property } from "@rebasepro/types";
|
|
4
3
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
-
import { Entity, EntityTableController, EnumValueConfig,
|
|
4
|
+
import { Entity, EntityTableController, EnumValueConfig, SaveEntityProps, SelectionController } from "@rebasepro/types";
|
|
6
5
|
import { Board } from "./Board";
|
|
7
6
|
import { BoardItem, BoardItemViewProps, ColumnLoadingState } from "./board_types";
|
|
8
7
|
import { EntityBoardCard } from "./EntityBoardCard";
|
|
9
|
-
import {
|
|
10
|
-
|
|
8
|
+
import {
|
|
9
|
+
Button,
|
|
10
|
+
ChipColorKey,
|
|
11
|
+
ChipColorScheme,
|
|
12
|
+
CircularProgress,
|
|
13
|
+
Dialog,
|
|
14
|
+
DialogActions,
|
|
15
|
+
DialogContent,
|
|
16
|
+
getColorSchemeForSeed,
|
|
17
|
+
IconButton,
|
|
18
|
+
iconSize,
|
|
19
|
+
RefreshCwIcon,
|
|
20
|
+
Tooltip,
|
|
21
|
+
Typography
|
|
22
|
+
} from "@rebasepro/ui";
|
|
11
23
|
import { resolveEnumValues } from "@rebasepro/common";
|
|
12
24
|
import { getPropertyInPath } from "../../util/property_utils";
|
|
13
25
|
import {
|
|
@@ -58,7 +70,6 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
|
|
|
58
70
|
emptyComponent,
|
|
59
71
|
deletedEntities
|
|
60
72
|
}: EntityCollectionBoardViewProps<M>) {
|
|
61
|
-
const authController = useAuthController();
|
|
62
73
|
const customizationController = useCustomizationController();
|
|
63
74
|
const context = useRebaseContext();
|
|
64
75
|
const dataClient = useData();
|
|
@@ -245,7 +256,6 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
|
|
|
245
256
|
|
|
246
257
|
useEffect(() => {
|
|
247
258
|
const currentDataClient = dataClientRef.current;
|
|
248
|
-
const currentCollection = collectionRef.current;
|
|
249
259
|
const accessor = currentDataClient.collection(fullPath);
|
|
250
260
|
|
|
251
261
|
if (!orderProperty || !accessor.count) {
|
|
@@ -351,9 +361,7 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
|
|
|
351
361
|
|
|
352
362
|
// Backfill order values for all entities
|
|
353
363
|
const handleBackfill = useCallback(async () => {
|
|
354
|
-
console.log("handleBackfill called", { orderProperty });
|
|
355
364
|
if (!orderProperty) {
|
|
356
|
-
console.log("No orderProperty, returning");
|
|
357
365
|
return;
|
|
358
366
|
}
|
|
359
367
|
analyticsController.onAnalyticsEvent?.("kanban_backfill_order", {
|
|
@@ -363,19 +371,16 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
|
|
|
363
371
|
|
|
364
372
|
try {
|
|
365
373
|
// Fetch ALL documents from collection (not relying on loaded entities)
|
|
366
|
-
console.log("Fetching all documents from collection...");
|
|
367
374
|
const allDocsRes = await dataClient.collection(fullPath).find({
|
|
368
375
|
limit: 10000 // Fetch all
|
|
369
376
|
});
|
|
370
377
|
const allDocs = allDocsRes.data as Entity<M>[];
|
|
371
|
-
console.log(`Fetched ${allDocs.length} documents`);
|
|
372
378
|
|
|
373
379
|
// Find entities missing order property
|
|
374
380
|
const entitiesToUpdate = allDocs.filter((entity: Entity<M>) => {
|
|
375
381
|
const orderValue = entity.values?.[orderProperty];
|
|
376
382
|
return orderValue === undefined || orderValue === null;
|
|
377
383
|
});
|
|
378
|
-
console.log(`${entitiesToUpdate.length} entities need order values`);
|
|
379
384
|
|
|
380
385
|
// Generate string fractional keys for all entities that need them
|
|
381
386
|
const keys = generateNKeysBetween(null, null, entitiesToUpdate.length);
|
|
@@ -404,9 +409,7 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
|
|
|
404
409
|
);
|
|
405
410
|
});
|
|
406
411
|
|
|
407
|
-
console.log(`Total updates to run: ${updates.length}`);
|
|
408
412
|
await Promise.all(updates);
|
|
409
|
-
console.log("All updates complete");
|
|
410
413
|
setShowBackfillDialog(false);
|
|
411
414
|
|
|
412
415
|
// Reset missing count to hide banner
|
|
@@ -456,7 +459,6 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
|
|
|
456
459
|
// Uses refs for ALL dynamic values so the component type never changes.
|
|
457
460
|
// When ItemComponent identity changes, React.memo'd SortableItem remounts
|
|
458
461
|
// the card → DOM is destroyed/recreated → CSS :hover state is lost → flicker.
|
|
459
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
460
462
|
const ItemComponent = useMemo(() => {
|
|
461
463
|
const Comp = (props: BoardItemViewProps<M>) => (
|
|
462
464
|
<EntityBoardCard
|
|
@@ -479,7 +481,7 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
|
|
|
479
481
|
parentCollectionSlugs,
|
|
480
482
|
parentEntityIds
|
|
481
483
|
});
|
|
482
|
-
|
|
484
|
+
|
|
483
485
|
|
|
484
486
|
// Get AddKanbanColumnComponent from plugin slots
|
|
485
487
|
const addKanbanColumnSlots = useSlot("kanban.add-column", {
|
|
@@ -488,7 +490,7 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
|
|
|
488
490
|
parentCollectionSlugs, parentEntityIds,
|
|
489
491
|
columnProperty
|
|
490
492
|
});
|
|
491
|
-
|
|
493
|
+
|
|
492
494
|
|
|
493
495
|
// Check for loading error
|
|
494
496
|
const hasError = Boolean(dataLoadingError);
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
CircularProgress,
|
|
8
8
|
Typography
|
|
9
9
|
} from "@rebasepro/ui";
|
|
10
|
-
import { useAuthController, useCustomizationController } from "@rebasepro/core";
|
|
11
10
|
|
|
12
11
|
export type EntityCollectionCardViewProps<M extends Record<string, unknown> = Record<string, unknown>> = {
|
|
13
12
|
collection: EntityCollection<M>;
|
|
@@ -77,8 +76,6 @@ export function EntityCollectionCardView<M extends Record<string, unknown> = Rec
|
|
|
77
76
|
initialScroll,
|
|
78
77
|
size = "m"
|
|
79
78
|
}: EntityCollectionCardViewProps<M>) {
|
|
80
|
-
const authController = useAuthController();
|
|
81
|
-
const customizationController = useCustomizationController();
|
|
82
79
|
|
|
83
80
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
84
81
|
const loadMoreRef = useRef<HTMLDivElement>(null);
|
|
@@ -98,28 +95,30 @@ export function EntityCollectionCardView<M extends Record<string, unknown> = Rec
|
|
|
98
95
|
// Track if we're currently loading to prevent multiple simultaneous load requests
|
|
99
96
|
const isLoadingMore = useRef(false);
|
|
100
97
|
|
|
101
|
-
//
|
|
98
|
+
// Keep mutable refs for values used in the IntersectionObserver callback
|
|
99
|
+
// to avoid re-creating the observer every time pagination state changes.
|
|
100
|
+
const paginationStateRef = useRef({ paginationEnabled, noMoreToLoad, dataLoading, itemCount, pageSize });
|
|
102
101
|
useEffect(() => {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
102
|
+
paginationStateRef.current = { paginationEnabled, noMoreToLoad, dataLoading, itemCount, pageSize };
|
|
103
|
+
}, [paginationEnabled, noMoreToLoad, dataLoading, itemCount, pageSize]);
|
|
106
104
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
// Reset loading flag when new data arrives (separate effect, like list view)
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
if (!dataLoading) isLoadingMore.current = false;
|
|
108
|
+
}, [dataLoading]);
|
|
111
109
|
|
|
110
|
+
// Infinite scroll with Intersection Observer — stable deps only
|
|
111
|
+
useEffect(() => {
|
|
112
112
|
const observer = new IntersectionObserver(
|
|
113
113
|
(entries) => {
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
const { paginationEnabled: pe, noMoreToLoad: nm, dataLoading: dl, itemCount: ic, pageSize: ps } = paginationStateRef.current;
|
|
115
|
+
if (entries[0].isIntersecting && pe && !dl && !nm && !isLoadingMore.current) {
|
|
116
116
|
isLoadingMore.current = true;
|
|
117
|
-
|
|
118
|
-
setItemCount?.((itemCount ?? pageSize) + pageSize);
|
|
117
|
+
setItemCount?.((ic ?? ps) + ps);
|
|
119
118
|
}
|
|
120
119
|
},
|
|
121
120
|
{
|
|
122
|
-
root: containerRef.current,
|
|
121
|
+
root: containerRef.current,
|
|
123
122
|
rootMargin: "400px",
|
|
124
123
|
threshold: 0
|
|
125
124
|
}
|
|
@@ -130,7 +129,7 @@ export function EntityCollectionCardView<M extends Record<string, unknown> = Rec
|
|
|
130
129
|
}
|
|
131
130
|
|
|
132
131
|
return () => observer.disconnect();
|
|
133
|
-
}, [
|
|
132
|
+
}, [setItemCount]);
|
|
134
133
|
|
|
135
134
|
// Scroll restoration — deferred to after layout paint
|
|
136
135
|
useEffect(() => {
|