@rebasepro/admin 0.6.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{CollectionEditorDialog-HNXGxXdO.js → CollectionEditorDialog-BO_aQ-Z4.js} +236 -155
- package/dist/CollectionEditorDialog-BO_aQ-Z4.js.map +1 -0
- package/dist/{PropertyEditView-C2wp8kQ9.js → PropertyEditView-DKzOpMjR.js} +190 -50
- package/dist/PropertyEditView-DKzOpMjR.js.map +1 -0
- package/dist/{CollectionsStudioView-B1mN33GB.js → RouterCollectionsStudioView-BQTIExjA.js} +61 -39
- package/dist/RouterCollectionsStudioView-BQTIExjA.js.map +1 -0
- package/dist/collection_editor/_cms_internals.d.ts +1 -1
- package/dist/collection_editor/api/generateCollectionApi.d.ts +3 -2
- package/dist/collection_editor/extensibility_types.d.ts +135 -0
- package/dist/collection_editor/index.d.ts +6 -0
- package/dist/collection_editor/serializable_types.d.ts +370 -0
- package/dist/collection_editor/serializable_utils.d.ts +50 -0
- package/dist/collection_editor/ui/collection_editor/CollectionEditorDialog.d.ts +3 -3
- package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +12 -1
- package/dist/collection_editor/ui/collection_editor/CollectionStudioView.d.ts +13 -1
- package/dist/collection_editor/ui/collection_editor/CollectionsStudioView.d.ts +24 -2
- package/dist/collection_editor/ui/collection_editor/DisplaySettingsForm.d.ts +2 -1
- package/dist/collection_editor/ui/collection_editor/GeneralSettingsForm.d.ts +4 -1
- package/dist/collection_editor/ui/collection_editor/PropertyEditView.d.ts +12 -1
- package/dist/collection_editor/ui/collection_editor/RouterCollectionStudioView.d.ts +15 -0
- package/dist/collection_editor/ui/collection_editor/RouterCollectionsStudioView.d.ts +14 -0
- package/dist/collection_editor/useJsonCollectionsConfigController.d.ts +37 -0
- package/dist/collection_editor/useSafeSnackbarController.d.ts +2 -0
- package/dist/collection_editor_ui.d.ts +4 -0
- package/dist/collection_editor_ui.js +33 -4
- package/dist/collection_editor_ui.js.map +1 -0
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
- package/dist/components/EntityCollectionTable/index.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +3 -3
- package/dist/components/EntityCollectionView/hooks/useKanbanDragAndDrop.d.ts +3 -3
- package/dist/components/EntityEditView.d.ts +3 -2
- package/dist/components/RebaseCMS.d.ts +1 -1
- package/dist/components/SelectableTable/SelectionStore.d.ts +12 -21
- package/dist/components/field_configs.d.ts +1 -1
- package/dist/editor/editor.d.ts +0 -6
- package/dist/editor.js +1 -3
- package/dist/editor.js.map +1 -1
- package/dist/form/EntityForm.d.ts +10 -9
- package/dist/form/EntityFormBinding.d.ts +27 -0
- package/dist/form/components/StorageUploadProgress.d.ts +6 -1
- package/dist/form/form_utils.d.ts +8 -0
- package/dist/form/index.d.ts +5 -2
- package/dist/{history-BO6VT85a.js → history-B3cqBzEV.js} +2 -2
- package/dist/{history-BO6VT85a.js.map → history-B3cqBzEV.js.map} +1 -1
- package/dist/hooks/navigation/contexts/CollectionRegistryContext.d.ts +1 -1
- package/dist/hooks/navigation/useAsyncResolver.d.ts +26 -0
- package/dist/hooks/navigation/useBuildCollectionRegistryController.d.ts +2 -0
- package/dist/hooks/navigation/useTopLevelNavigation.d.ts +1 -1
- package/dist/hooks/navigation/utils.d.ts +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -2
- package/dist/preview/components/StorageThumbnail.d.ts +3 -1
- package/dist/routes/CustomViewRoute.d.ts +2 -1
- package/dist/{src-BYniefVu.js → src-cxV1ODRG.js} +1731 -1710
- package/dist/src-cxV1ODRG.js.map +1 -0
- package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
- package/dist/types/components/EntityFormProps.d.ts +59 -0
- package/dist/types/components/PropertyPreviewProps.d.ts +2 -1
- package/dist/types/fields.d.ts +10 -7
- package/dist/util/dataControllerAdapter.d.ts +30 -0
- package/dist/util/navigation_utils.d.ts +1 -1
- package/dist/util/propertyConfigMapper.d.ts +17 -0
- package/package.json +8 -8
- package/src/collection_editor/_cms_internals.ts +1 -1
- package/src/collection_editor/api/generateCollectionApi.ts +3 -2
- package/src/collection_editor/extensibility_types.ts +168 -0
- package/src/collection_editor/index.ts +46 -0
- package/src/collection_editor/pgColumnToProperty.ts +2 -2
- package/src/collection_editor/serializable_types.ts +474 -0
- package/src/collection_editor/serializable_utils.ts +576 -0
- package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +6 -6
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +170 -89
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +95 -78
- package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +23 -20
- package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +79 -27
- package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +9 -7
- package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +22 -5
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +154 -18
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +6 -6
- package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +1 -0
- package/src/collection_editor/ui/collection_editor/RouterCollectionStudioView.tsx +44 -0
- package/src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx +41 -0
- package/src/collection_editor/ui/collection_editor/properties/EnumPropertyField.tsx +4 -3
- package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +35 -1
- package/src/collection_editor/ui/collection_editor/templates/blog_template.ts +1 -1
- package/src/collection_editor/ui/collection_editor/utils/supported_fields.tsx +0 -1
- package/src/collection_editor/ui/collection_editor/utils/update_property_for_widget.ts +7 -29
- package/src/collection_editor/useJsonCollectionsConfigController.tsx +286 -0
- package/src/collection_editor/useSafeSnackbarController.ts +9 -0
- package/src/collection_editor_ui.ts +6 -0
- package/src/components/DefaultDrawer.tsx +14 -4
- package/src/components/DrawerNavigationGroup.tsx +2 -2
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +11 -9
- package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +2 -1
- package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +2 -1
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +23 -20
- package/src/components/EntityCollectionTable/index.tsx +1 -1
- package/src/components/EntityCollectionTable/table_bindings.tsx +24 -44
- package/src/components/EntityCollectionView/EntityBoardCard.tsx +6 -6
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +13 -12
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +40 -190
- package/src/components/EntityCollectionView/EntityCollectionListView.tsx +66 -184
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +8 -25
- package/src/components/EntityCollectionView/hooks/useCollectionInlineEditor.ts +1 -1
- package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +6 -6
- package/src/components/EntityCollectionView/useBoardDataController.tsx +12 -40
- package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +3 -3
- package/src/components/EntityDetailView.tsx +2 -2
- package/src/components/EntityEditView.tsx +7 -6
- package/src/components/EntityEditViewFormActions.tsx +35 -29
- package/src/components/HomePage/ContentHomePage.tsx +14 -5
- package/src/components/RebaseCMS.tsx +3 -3
- package/src/components/RebaseNavigation.tsx +74 -9
- package/src/components/RelationSelector.tsx +2 -2
- package/src/components/SelectableTable/SelectableTable.tsx +13 -5
- package/src/components/SelectableTable/SelectionStore.ts +18 -48
- package/src/components/SideDialogs.tsx +0 -7
- package/src/components/common/default_entity_actions.tsx +22 -11
- package/src/components/field_configs.tsx +0 -14
- package/src/contexts/BreacrumbsContext.tsx +15 -6
- package/src/editor/editor.tsx +4 -7
- package/src/editor/selectors/ai-selector.tsx +0 -1
- package/src/form/EntityForm.tsx +191 -428
- package/src/form/EntityFormActions.tsx +35 -49
- package/src/form/EntityFormBinding.tsx +323 -0
- package/src/form/components/FormLayout.tsx +1 -1
- package/src/form/components/StorageUploadProgress.tsx +9 -2
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +12 -1
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +4 -4
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +7 -2
- package/src/form/field_bindings/RelationFieldBinding.tsx +5 -7
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +19 -15
- package/src/form/form_utils.ts +163 -0
- package/src/form/index.tsx +14 -6
- package/src/hooks/navigation/contexts/CollectionRegistryContext.tsx +2 -2
- package/src/hooks/navigation/contexts/NavigationStateContext.tsx +2 -2
- package/src/hooks/navigation/contexts/UrlContext.tsx +1 -2
- package/src/hooks/navigation/useAsyncResolver.ts +100 -0
- package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +15 -8
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +12 -8
- package/src/hooks/navigation/useNavigationResolution.ts +33 -0
- package/src/hooks/navigation/useResolvedCollections.ts +29 -71
- package/src/hooks/navigation/useResolvedViews.tsx +40 -70
- package/src/hooks/navigation/useTopLevelNavigation.ts +20 -16
- package/src/hooks/navigation/utils.ts +7 -4
- package/src/index.ts +6 -1
- package/src/preview/PropertyPreview.tsx +1 -16
- package/src/preview/components/StorageThumbnail.tsx +24 -7
- package/src/routes/CustomViewRoute.tsx +14 -6
- package/src/types/components/EntityFormActionsProps.tsx +1 -1
- package/src/types/components/EntityFormProps.tsx +68 -0
- package/src/types/components/PropertyPreviewProps.tsx +1 -1
- package/src/types/fields.tsx +9 -8
- package/src/util/dataControllerAdapter.ts +93 -0
- package/src/util/navigation_utils.ts +1 -1
- package/src/util/previews.ts +20 -0
- package/src/util/propertyConfigMapper.ts +134 -0
- package/src/util/property_utils.tsx +1 -2
- package/dist/CollectionEditorDialog-HNXGxXdO.js.map +0 -1
- package/dist/CollectionsStudioView-B1mN33GB.js.map +0 -1
- package/dist/PropertyEditView-C2wp8kQ9.js.map +0 -1
- package/dist/components/EntityCollectionTable/fields/VirtualTableDateField.d.ts +0 -12
- package/dist/components/EntityCollectionTable/fields/VirtualTableInput.d.ts +0 -10
- package/dist/components/EntityCollectionTable/fields/VirtualTableNumberInput.d.ts +0 -9
- package/dist/components/EntityCollectionTable/fields/VirtualTableSwitch.d.ts +0 -8
- package/dist/components/EntityCollectionView/Board.d.ts +0 -3
- package/dist/components/EntityCollectionView/BoardColumn.d.ts +0 -42
- package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +0 -9
- package/dist/components/EntityCollectionView/BoardSortableList.d.ts +0 -14
- package/dist/components/EntityCollectionView/board_types.d.ts +0 -105
- package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +0 -11
- package/dist/hooks/navigation/useNavigationRegistry.d.ts +0 -12
- package/dist/hooks/navigation/useNavigationURLs.d.ts +0 -11
- package/dist/src-BYniefVu.js.map +0 -1
- package/src/components/EntityCollectionTable/fields/VirtualTableDateField.tsx +0 -39
- package/src/components/EntityCollectionTable/fields/VirtualTableInput.tsx +0 -90
- package/src/components/EntityCollectionTable/fields/VirtualTableNumberInput.tsx +0 -83
- package/src/components/EntityCollectionTable/fields/VirtualTableSwitch.tsx +0 -32
- package/src/components/EntityCollectionView/Board.tsx +0 -475
- package/src/components/EntityCollectionView/BoardColumn.tsx +0 -165
- package/src/components/EntityCollectionView/BoardColumnTitle.tsx +0 -46
- package/src/components/EntityCollectionView/BoardSortableList.tsx +0 -177
- package/src/components/EntityCollectionView/board_types.ts +0 -113
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +0 -141
- package/src/hooks/navigation/useNavigationRegistry.ts +0 -164
- package/src/hooks/navigation/useNavigationURLs.ts +0 -56
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import React, { memo, useEffect, useMemo, useRef } from "react";
|
|
2
|
-
import { useDroppable } from "@dnd-kit/core";
|
|
3
|
-
import { useSortable, SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
|
4
|
-
import { CSS } from "@dnd-kit/utilities";
|
|
5
|
-
import { CircularProgress, cls } from "@rebasepro/ui";
|
|
6
|
-
import { BoardItem, BoardItemViewProps } from "./board_types";
|
|
7
|
-
|
|
8
|
-
interface BoardSortableListProps<M extends Record<string, unknown>> {
|
|
9
|
-
columnId: string;
|
|
10
|
-
items: BoardItem<M>[];
|
|
11
|
-
ItemComponent: React.ComponentType<BoardItemViewProps<M>>;
|
|
12
|
-
isDragging: boolean;
|
|
13
|
-
isDragOverColumn: boolean;
|
|
14
|
-
loading?: boolean;
|
|
15
|
-
hasMore?: boolean;
|
|
16
|
-
onLoadMore?: () => void;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function BoardSortableList<M extends Record<string, unknown>>({
|
|
20
|
-
columnId,
|
|
21
|
-
items,
|
|
22
|
-
ItemComponent,
|
|
23
|
-
isDragging,
|
|
24
|
-
isDragOverColumn,
|
|
25
|
-
loading = false,
|
|
26
|
-
hasMore = false,
|
|
27
|
-
onLoadMore
|
|
28
|
-
}: BoardSortableListProps<M>) {
|
|
29
|
-
const {
|
|
30
|
-
setNodeRef
|
|
31
|
-
} = useDroppable({
|
|
32
|
-
id: columnId,
|
|
33
|
-
data: { type: "ITEM-LIST" }
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// Infinite scroll sentinel ref - must be inside scrollable container
|
|
37
|
-
const sentinelRef = useRef<HTMLDivElement>(null);
|
|
38
|
-
const isLoadingRef = useRef(false);
|
|
39
|
-
isLoadingRef.current = loading;
|
|
40
|
-
const lastLoadTimeRef = useRef(0);
|
|
41
|
-
|
|
42
|
-
// Set up IntersectionObserver for infinite scroll
|
|
43
|
-
useEffect(() => {
|
|
44
|
-
if (!sentinelRef.current || !hasMore || !onLoadMore) return;
|
|
45
|
-
|
|
46
|
-
const sentinel = sentinelRef.current;
|
|
47
|
-
|
|
48
|
-
const observer = new IntersectionObserver(
|
|
49
|
-
(entries) => {
|
|
50
|
-
const now = Date.now();
|
|
51
|
-
if (
|
|
52
|
-
entries[0].isIntersecting &&
|
|
53
|
-
hasMore &&
|
|
54
|
-
!isLoadingRef.current &&
|
|
55
|
-
now - lastLoadTimeRef.current > 500
|
|
56
|
-
) {
|
|
57
|
-
lastLoadTimeRef.current = now;
|
|
58
|
-
onLoadMore();
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
{ threshold: 0.1 }
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
observer.observe(sentinel);
|
|
65
|
-
|
|
66
|
-
// Check if sentinel is already visible when effect runs
|
|
67
|
-
// This handles the case where the sentinel was visible before the observer was created
|
|
68
|
-
const rect = sentinel.getBoundingClientRect();
|
|
69
|
-
const containerRect = sentinel.parentElement?.getBoundingClientRect();
|
|
70
|
-
if (containerRect && rect.top < containerRect.bottom && rect.bottom > containerRect.top) {
|
|
71
|
-
const now = Date.now();
|
|
72
|
-
if (hasMore && !isLoadingRef.current && now - lastLoadTimeRef.current > 500) {
|
|
73
|
-
lastLoadTimeRef.current = now;
|
|
74
|
-
onLoadMore();
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return () => observer.disconnect();
|
|
79
|
-
}, [hasMore, onLoadMore]);
|
|
80
|
-
|
|
81
|
-
// Memoize className to avoid recomputation on every render
|
|
82
|
-
const containerClassName = useMemo(() => cls(
|
|
83
|
-
"flex flex-col p-2 transition-opacity duration-100 transition-bg ease-linear w-full overflow-y-auto no-scrollbar flex-1 rounded-md",
|
|
84
|
-
isDragging && isDragOverColumn
|
|
85
|
-
? "bg-surface-accent-200 dark:bg-surface-900"
|
|
86
|
-
: isDragging
|
|
87
|
-
? "bg-surface-50 dark:bg-surface-900 hover:bg-surface-accent-100 dark:hover:bg-surface-800"
|
|
88
|
-
: "bg-surface-50 dark:bg-surface-900"
|
|
89
|
-
), [isDragging, isDragOverColumn]);
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<div
|
|
93
|
-
ref={setNodeRef}
|
|
94
|
-
className={containerClassName}
|
|
95
|
-
style={{ minHeight: 80 }}
|
|
96
|
-
>
|
|
97
|
-
<SortableContext
|
|
98
|
-
items={items.map(i => i.id)}
|
|
99
|
-
strategy={verticalListSortingStrategy}
|
|
100
|
-
>
|
|
101
|
-
{items.length === 0 && !loading ? (
|
|
102
|
-
<div className="flex-1 flex items-center justify-center">
|
|
103
|
-
<span className="text-xs text-surface-400 dark:text-surface-500">
|
|
104
|
-
No items
|
|
105
|
-
</span>
|
|
106
|
-
</div>
|
|
107
|
-
) : (
|
|
108
|
-
<>
|
|
109
|
-
{items.map((item, index) => (
|
|
110
|
-
<SortableItem
|
|
111
|
-
key={item.id}
|
|
112
|
-
item={item}
|
|
113
|
-
index={index}
|
|
114
|
-
columnId={columnId}
|
|
115
|
-
ItemComponent={ItemComponent}
|
|
116
|
-
/>
|
|
117
|
-
))}
|
|
118
|
-
{/* Infinite scroll sentinel - inside scrollable container */}
|
|
119
|
-
{(loading || hasMore) && (
|
|
120
|
-
<div ref={sentinelRef} className="flex items-center justify-center py-2 min-h-6">
|
|
121
|
-
{loading && <CircularProgress size="smallest"/>}
|
|
122
|
-
</div>
|
|
123
|
-
)}
|
|
124
|
-
</>
|
|
125
|
-
)}
|
|
126
|
-
</SortableContext>
|
|
127
|
-
</div>
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
interface SortableItemProps<M extends Record<string, unknown>> {
|
|
132
|
-
item: BoardItem<M>;
|
|
133
|
-
index: number;
|
|
134
|
-
columnId: string;
|
|
135
|
-
ItemComponent: React.ComponentType<BoardItemViewProps<M>>;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Memoized to prevent unnecessary re-renders when other items in the list change
|
|
139
|
-
const SortableItem = memo(function SortableItem<M extends Record<string, unknown>>({
|
|
140
|
-
item,
|
|
141
|
-
index,
|
|
142
|
-
columnId,
|
|
143
|
-
ItemComponent
|
|
144
|
-
}: SortableItemProps<M>) {
|
|
145
|
-
const {
|
|
146
|
-
setNodeRef,
|
|
147
|
-
attributes,
|
|
148
|
-
listeners,
|
|
149
|
-
isDragging: isItemBeingDragged,
|
|
150
|
-
transform,
|
|
151
|
-
transition
|
|
152
|
-
} = useSortable({
|
|
153
|
-
id: item.id,
|
|
154
|
-
data: {
|
|
155
|
-
type: "ITEM",
|
|
156
|
-
columnId
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// Memoize style object to prevent object recreation on each render
|
|
161
|
-
const sortableStyle = useMemo(() => ({
|
|
162
|
-
transform: CSS.Transform.toString(transform),
|
|
163
|
-
transition,
|
|
164
|
-
zIndex: isItemBeingDragged ? 2 : 1,
|
|
165
|
-
opacity: isItemBeingDragged ? 0 : 1
|
|
166
|
-
}), [transform, transition, isItemBeingDragged]);
|
|
167
|
-
|
|
168
|
-
return (
|
|
169
|
-
<div ref={setNodeRef} style={sortableStyle} {...attributes} {...listeners}>
|
|
170
|
-
<ItemComponent
|
|
171
|
-
item={item}
|
|
172
|
-
isDragging={isItemBeingDragged}
|
|
173
|
-
index={index}
|
|
174
|
-
/>
|
|
175
|
-
</div>
|
|
176
|
-
);
|
|
177
|
-
}) as <M extends Record<string, unknown>>(props: SortableItemProps<M>) => React.ReactElement;
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { CSSProperties } from "react";
|
|
2
|
-
import { ChipColorKey, ChipColorScheme } from "@rebasepro/ui";
|
|
3
|
-
import { Entity } from "@rebasepro/types";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Item wrapper for entities in the Board component
|
|
7
|
-
*/
|
|
8
|
-
export interface BoardItem<M extends Record<string, unknown> = Record<string, unknown>> {
|
|
9
|
-
id: string;
|
|
10
|
-
entity: Entity<M>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Map of column keys to arrays of board items
|
|
15
|
-
*/
|
|
16
|
-
export interface BoardItemMap<M extends Record<string, unknown> = Record<string, unknown>> {
|
|
17
|
-
[columnKey: string]: BoardItem<M>[];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Props passed to custom item render components
|
|
22
|
-
*/
|
|
23
|
-
export interface BoardItemViewProps<M extends Record<string, unknown> = Record<string, unknown>> {
|
|
24
|
-
item: BoardItem<M>;
|
|
25
|
-
isDragging: boolean;
|
|
26
|
-
isClone?: boolean;
|
|
27
|
-
isGroupedOver?: boolean;
|
|
28
|
-
style?: CSSProperties;
|
|
29
|
-
index?: number;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Per-column loading state
|
|
34
|
-
*/
|
|
35
|
-
export interface ColumnLoadingState {
|
|
36
|
-
[columnKey: string]: {
|
|
37
|
-
loading: boolean;
|
|
38
|
-
hasMore: boolean;
|
|
39
|
-
itemCount: number;
|
|
40
|
-
/** Total count of entities in column (may differ from itemCount if some lack orderProperty) */
|
|
41
|
-
totalCount?: number;
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Props for the Board component
|
|
47
|
-
*/
|
|
48
|
-
export interface BoardProps<M extends Record<string, unknown>, COLUMN extends string> {
|
|
49
|
-
/**
|
|
50
|
-
* Array of board items (entities wrapped with id)
|
|
51
|
-
*/
|
|
52
|
-
data: BoardItem<M>[];
|
|
53
|
-
/**
|
|
54
|
-
* Array of column keys/identifiers
|
|
55
|
-
*/
|
|
56
|
-
columns: COLUMN[];
|
|
57
|
-
/**
|
|
58
|
-
* Labels for each column (optional, uses column key if not provided)
|
|
59
|
-
*/
|
|
60
|
-
columnLabels?: Record<COLUMN, string>;
|
|
61
|
-
/**
|
|
62
|
-
* Colors for each column from enum values (optional)
|
|
63
|
-
*/
|
|
64
|
-
columnColors?: Record<COLUMN, ChipColorKey | ChipColorScheme | undefined>;
|
|
65
|
-
/**
|
|
66
|
-
* CSS class name for the board container
|
|
67
|
-
*/
|
|
68
|
-
className?: string;
|
|
69
|
-
/**
|
|
70
|
-
* Function to determine which column an item belongs to
|
|
71
|
-
*/
|
|
72
|
-
assignColumn: (item: BoardItem<M>) => COLUMN;
|
|
73
|
-
/**
|
|
74
|
-
* Whether column reordering is allowed.
|
|
75
|
-
* Set to true only when a plugin provides persistence for column order.
|
|
76
|
-
*/
|
|
77
|
-
allowColumnReorder?: boolean;
|
|
78
|
-
/**
|
|
79
|
-
* Callback when columns are reordered
|
|
80
|
-
*/
|
|
81
|
-
onColumnReorder?: (columns: COLUMN[]) => void;
|
|
82
|
-
/**
|
|
83
|
-
* Callback when items are reordered or moved between columns
|
|
84
|
-
*/
|
|
85
|
-
onItemsReorder?: (
|
|
86
|
-
items: BoardItem<M>[],
|
|
87
|
-
moveInfo?: {
|
|
88
|
-
itemId: string;
|
|
89
|
-
sourceColumn: COLUMN;
|
|
90
|
-
targetColumn: COLUMN;
|
|
91
|
-
}
|
|
92
|
-
) => void;
|
|
93
|
-
/**
|
|
94
|
-
* Component to render individual items
|
|
95
|
-
*/
|
|
96
|
-
ItemComponent: React.ComponentType<BoardItemViewProps<M>>;
|
|
97
|
-
/**
|
|
98
|
-
* Per-column loading state for pagination
|
|
99
|
-
*/
|
|
100
|
-
columnLoadingState?: ColumnLoadingState;
|
|
101
|
-
/**
|
|
102
|
-
* Callback to load more items for a column
|
|
103
|
-
*/
|
|
104
|
-
onLoadMoreColumn?: (column: COLUMN) => void;
|
|
105
|
-
/**
|
|
106
|
-
* Callback to add a new item to a specific column
|
|
107
|
-
*/
|
|
108
|
-
onAddItemToColumn?: (column: COLUMN) => void;
|
|
109
|
-
/**
|
|
110
|
-
* Optional component to render at the end of the board for adding new columns
|
|
111
|
-
*/
|
|
112
|
-
AddColumnComponent?: React.ReactNode;
|
|
113
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { useEntitySelectionDialog } from "../../hooks/useEntitySelectionDialog";
|
|
2
|
-
import type { EntityCollection } from "@rebasepro/types";
|
|
3
|
-
import type { FieldProps } from "../../types/fields";
|
|
4
|
-
import type { Property, StringProperty } from "@rebasepro/types";
|
|
5
|
-
import React, { useCallback, useMemo } from "react";
|
|
6
|
-
import { Entity, EntityReference } from "@rebasepro/types";
|
|
7
|
-
import { ReadOnlyFieldBinding } from "./ReadOnlyFieldBinding";
|
|
8
|
-
import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
|
|
9
|
-
import { ErrorView } from "@rebasepro/core";
|
|
10
|
-
import { ReferencePreview } from "../../preview";
|
|
11
|
-
import { IconForView } from "@rebasepro/core";
|
|
12
|
-
import { getIconForProperty } from "../../util/property_utils";
|
|
13
|
-
import { useClearRestoreValue } from "../useClearRestoreValue";
|
|
14
|
-
import { EntityPreviewContainer } from "../../components/EntityPreview";
|
|
15
|
-
import { cls } from "@rebasepro/ui";
|
|
16
|
-
import { useCollectionRegistryController } from "../../index";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Field that opens a reference selection dialog and stores the entity ID as a string.
|
|
20
|
-
*
|
|
21
|
-
* This is one of the internal components that get mapped natively inside forms
|
|
22
|
-
* and tables to the specified properties.
|
|
23
|
-
* @group Form fields
|
|
24
|
-
*/
|
|
25
|
-
export function ReferenceAsStringFieldBinding(props: FieldProps<StringProperty>) {
|
|
26
|
-
if (typeof props.property.reference?.path !== "string") {
|
|
27
|
-
return <ReadOnlyFieldBinding {...props as FieldProps<Property>}/>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return <ReferenceAsStringFieldBindingInternal {...props}/>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function ReferenceAsStringFieldBindingInternal({
|
|
34
|
-
propertyKey,
|
|
35
|
-
value,
|
|
36
|
-
setValue,
|
|
37
|
-
error,
|
|
38
|
-
showError,
|
|
39
|
-
isSubmitting,
|
|
40
|
-
disabled,
|
|
41
|
-
minimalistView,
|
|
42
|
-
property,
|
|
43
|
-
includeDescription,
|
|
44
|
-
size = "medium"
|
|
45
|
-
}: FieldProps<StringProperty>) {
|
|
46
|
-
if (!property.reference?.path) {
|
|
47
|
-
throw new Error("Property path is required for ReferenceAsStringFieldBinding");
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
useClearRestoreValue({
|
|
51
|
-
property,
|
|
52
|
-
value,
|
|
53
|
-
setValue
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const collectionRegistryController = useCollectionRegistryController();
|
|
57
|
-
const path = property.reference!.path;
|
|
58
|
-
const collection: EntityCollection | undefined = useMemo(() => {
|
|
59
|
-
return path ? collectionRegistryController.getCollection(path) : undefined;
|
|
60
|
-
}, [path]);
|
|
61
|
-
|
|
62
|
-
const referenceValue: EntityReference | undefined = useMemo(() => {
|
|
63
|
-
if (value && path) {
|
|
64
|
-
return new EntityReference({ id: value,
|
|
65
|
-
path });
|
|
66
|
-
}
|
|
67
|
-
return undefined;
|
|
68
|
-
}, [value, path]);
|
|
69
|
-
|
|
70
|
-
if (!collection) {
|
|
71
|
-
throw Error(`Couldn't find the corresponding collection for the path: ${path}`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const onSingleEntitySelected = useCallback((e: Entity<Record<string, unknown>> | null) => {
|
|
75
|
-
setValue(e ? String(e.id) : null);
|
|
76
|
-
}, [setValue]);
|
|
77
|
-
|
|
78
|
-
const referenceDialogController = useEntitySelectionDialog({
|
|
79
|
-
multiselect: false,
|
|
80
|
-
path,
|
|
81
|
-
collection,
|
|
82
|
-
onSingleEntitySelected,
|
|
83
|
-
selectedEntityIds: value ? [value] : undefined,
|
|
84
|
-
fixedFilter: property.reference?.fixedFilter
|
|
85
|
-
}
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
const onEntryClick = (e: React.SyntheticEvent) => {
|
|
89
|
-
e.preventDefault();
|
|
90
|
-
referenceDialogController.open();
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
return (
|
|
94
|
-
<>
|
|
95
|
-
{!minimalistView && <LabelWithIconAndTooltip
|
|
96
|
-
propertyKey={propertyKey}
|
|
97
|
-
icon={getIconForProperty(property, "small")}
|
|
98
|
-
required={property.validation?.required}
|
|
99
|
-
title={property.name ?? propertyKey}
|
|
100
|
-
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
|
|
101
|
-
|
|
102
|
-
{!collection && <ErrorView
|
|
103
|
-
error={"The specified collection does not exist. Check console"}/>}
|
|
104
|
-
|
|
105
|
-
{collection && <>
|
|
106
|
-
|
|
107
|
-
{referenceValue && <ReferencePreview
|
|
108
|
-
disabled={!path}
|
|
109
|
-
previewProperties={property.reference?.ui?.previewProperties}
|
|
110
|
-
hover={!disabled}
|
|
111
|
-
size={size}
|
|
112
|
-
onClick={disabled || isSubmitting ? undefined : onEntryClick}
|
|
113
|
-
reference={referenceValue}
|
|
114
|
-
includeEntityLink={property.reference?.includeEntityLink}
|
|
115
|
-
includeId={property.reference?.includeId}
|
|
116
|
-
/>}
|
|
117
|
-
|
|
118
|
-
{!value && <div className="justify-center text-left">
|
|
119
|
-
<EntityPreviewContainer
|
|
120
|
-
className={cls("px-6 h-16 text-sm font-medium flex items-center gap-6",
|
|
121
|
-
disabled || isSubmitting
|
|
122
|
-
? "text-surface-accent-500"
|
|
123
|
-
: "cursor-pointer text-surface-accent-700 dark:text-surface-accent-300 hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800")}
|
|
124
|
-
onClick={onEntryClick}
|
|
125
|
-
size={"medium"}>
|
|
126
|
-
<IconForView collectionOrView={collection}
|
|
127
|
-
className={"text-surface-300 dark:text-surface-600"}/>
|
|
128
|
-
{`Edit ${property.name}`.toUpperCase()}
|
|
129
|
-
</EntityPreviewContainer>
|
|
130
|
-
</div>}
|
|
131
|
-
</>}
|
|
132
|
-
|
|
133
|
-
<FieldHelperText includeDescription={includeDescription}
|
|
134
|
-
showError={showError}
|
|
135
|
-
error={error}
|
|
136
|
-
disabled={disabled}
|
|
137
|
-
property={property}/>
|
|
138
|
-
|
|
139
|
-
</>
|
|
140
|
-
);
|
|
141
|
-
}
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import type { EntityCollection } from "@rebasepro/types";
|
|
2
|
-
import { useCallback, useRef, useMemo } from "react";
|
|
3
|
-
import { CollectionRegistry, getParentReferencesFromPath, getSubcollections, removeInitialAndTrailingSlashes } from "@rebasepro/common";
|
|
4
|
-
import { EntityReference, UserConfigurationPersistence } from "@rebasepro/types";
|
|
5
|
-
import { mergeDeep } from "@rebasepro/utils";
|
|
6
|
-
|
|
7
|
-
export function useNavigationRegistry(userConfigPersistence?: UserConfigurationPersistence) {
|
|
8
|
-
const collectionRegistryRef = useRef<CollectionRegistry>(new CollectionRegistry());
|
|
9
|
-
|
|
10
|
-
const getCollection = useCallback((
|
|
11
|
-
slugOrPath: string,
|
|
12
|
-
includeUserOverride = false
|
|
13
|
-
): EntityCollection | undefined => {
|
|
14
|
-
|
|
15
|
-
const registry = collectionRegistryRef.current;
|
|
16
|
-
|
|
17
|
-
const cleanedPath = removeInitialAndTrailingSlashes(slugOrPath);
|
|
18
|
-
if (!cleanedPath) return undefined;
|
|
19
|
-
|
|
20
|
-
const pathSegments = cleanedPath.split("/");
|
|
21
|
-
|
|
22
|
-
let collectionPath = cleanedPath;
|
|
23
|
-
// If the path has an even number of segments, it points to an entity, so we get the parent collection
|
|
24
|
-
if (pathSegments.length > 0 && pathSegments.length % 2 === 0) {
|
|
25
|
-
collectionPath = pathSegments.slice(0, -1).join("/");
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!collectionPath) return undefined;
|
|
29
|
-
|
|
30
|
-
let collection: EntityCollection | undefined;
|
|
31
|
-
try {
|
|
32
|
-
collection = registry.resolvePathToCollections(collectionPath).finalCollection;
|
|
33
|
-
} catch (e) {
|
|
34
|
-
console.debug(`Could not resolve path to collection: ${collectionPath}`, e);
|
|
35
|
-
return undefined;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!collection) {
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const userOverride = includeUserOverride ? userConfigPersistence?.getCollectionConfig(slugOrPath) : undefined;
|
|
43
|
-
const overriddenCollection = collection ? mergeDeep(collection, userOverride ?? {}) : undefined;
|
|
44
|
-
|
|
45
|
-
if (!overriddenCollection) return undefined;
|
|
46
|
-
|
|
47
|
-
let result: Partial<EntityCollection> | undefined = overriddenCollection;
|
|
48
|
-
const subcollections = "subcollections" in overriddenCollection ? overriddenCollection.subcollections : undefined;
|
|
49
|
-
const callbacks = overriddenCollection.callbacks;
|
|
50
|
-
result = {
|
|
51
|
-
...result,
|
|
52
|
-
callbacks: result?.callbacks ?? callbacks
|
|
53
|
-
};
|
|
54
|
-
if (subcollections && "subcollections" in result) {
|
|
55
|
-
(result as Record<string, unknown>).subcollections = (result as Record<string, unknown>).subcollections ?? subcollections;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return { ...overriddenCollection,
|
|
59
|
-
...result } as EntityCollection;
|
|
60
|
-
|
|
61
|
-
}, [userConfigPersistence]);
|
|
62
|
-
|
|
63
|
-
const getRawCollection = useCallback((slugOrPath: string): EntityCollection | undefined => {
|
|
64
|
-
const registry = collectionRegistryRef.current;
|
|
65
|
-
if (registry === undefined) return undefined;
|
|
66
|
-
|
|
67
|
-
const cleanedPath = removeInitialAndTrailingSlashes(slugOrPath);
|
|
68
|
-
if (!cleanedPath) return undefined;
|
|
69
|
-
|
|
70
|
-
return registry.getRaw(cleanedPath) as EntityCollection | undefined;
|
|
71
|
-
}, []);
|
|
72
|
-
|
|
73
|
-
const getCollectionFromPaths = useCallback(<EC extends EntityCollection>(pathSegments: string[]): EC | undefined => {
|
|
74
|
-
const registry = collectionRegistryRef.current;
|
|
75
|
-
if (registry === undefined)
|
|
76
|
-
throw Error("getCollectionFromPaths: Collections have not been initialised yet");
|
|
77
|
-
|
|
78
|
-
if (!pathSegments?.length) {
|
|
79
|
-
return undefined;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const path = pathSegments.reduce((acc, segment, i) => {
|
|
83
|
-
if (i === 0) return segment;
|
|
84
|
-
return `${acc}/fake_id/${segment}`;
|
|
85
|
-
}, "");
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
const { finalCollection } = registry.resolvePathToCollections(path);
|
|
89
|
-
return finalCollection as EC | undefined;
|
|
90
|
-
} catch (e) {
|
|
91
|
-
console.debug(`Could not resolve path segments to collection: ${pathSegments.join("/")}`, e);
|
|
92
|
-
return undefined;
|
|
93
|
-
}
|
|
94
|
-
}, []);
|
|
95
|
-
|
|
96
|
-
const getAllParentReferencesForPath = useCallback((path: string): EntityReference[] => {
|
|
97
|
-
const registry = collectionRegistryRef.current;
|
|
98
|
-
if (!registry) {
|
|
99
|
-
return [];
|
|
100
|
-
}
|
|
101
|
-
return getParentReferencesFromPath({
|
|
102
|
-
path,
|
|
103
|
-
collections: registry.getCollections()
|
|
104
|
-
});
|
|
105
|
-
}, []);
|
|
106
|
-
|
|
107
|
-
const getParentCollectionSlugs = useCallback((path: string): string[] => {
|
|
108
|
-
const strings = path.split("/");
|
|
109
|
-
const oddPathSegments = strings.filter((_, i) => i % 2 === 0);
|
|
110
|
-
oddPathSegments.pop();
|
|
111
|
-
|
|
112
|
-
const result: string[][] = [];
|
|
113
|
-
|
|
114
|
-
for (let i = 1; i <= oddPathSegments.length; i++) {
|
|
115
|
-
result.push(oddPathSegments.slice(0, i));
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return result.map(r => getCollectionFromPaths(r)?.slug).filter(Boolean) as string[];
|
|
119
|
-
}, [getAllParentReferencesForPath, getCollectionFromPaths]);
|
|
120
|
-
|
|
121
|
-
const getParentEntityIds = useCallback((path: string): string[] => {
|
|
122
|
-
const strings = path.split("/");
|
|
123
|
-
const evenPathSegments = strings.filter((_, i) => i % 2 !== 0);
|
|
124
|
-
if (strings.length % 2 === 0) {
|
|
125
|
-
evenPathSegments.pop();
|
|
126
|
-
}
|
|
127
|
-
return evenPathSegments;
|
|
128
|
-
}, []);
|
|
129
|
-
|
|
130
|
-
const convertIdsToPaths = useCallback((ids: string[]): string[] => {
|
|
131
|
-
const registry = collectionRegistryRef.current;
|
|
132
|
-
if (!registry) {
|
|
133
|
-
throw new Error("convertIdsToPaths: collectionRegistryRef not initialised");
|
|
134
|
-
}
|
|
135
|
-
let currentCollections: EntityCollection[] = registry.getCollections();
|
|
136
|
-
const paths: string[] = [];
|
|
137
|
-
for (let i = 0; i < ids.length; i++) {
|
|
138
|
-
const id = ids[i];
|
|
139
|
-
const collection: EntityCollection | undefined = currentCollections.find(c => c.slug === id);
|
|
140
|
-
if (!collection)
|
|
141
|
-
throw Error(`Collection with id ${id} not found`);
|
|
142
|
-
paths.push(collection.slug);
|
|
143
|
-
currentCollections = getSubcollections(collection) ?? [];
|
|
144
|
-
}
|
|
145
|
-
return paths;
|
|
146
|
-
}, []);
|
|
147
|
-
|
|
148
|
-
return useMemo(() => ({
|
|
149
|
-
collectionRegistryRef,
|
|
150
|
-
getCollection,
|
|
151
|
-
getRawCollection,
|
|
152
|
-
getParentReferencesFromPath: getAllParentReferencesForPath,
|
|
153
|
-
getParentCollectionSlugs,
|
|
154
|
-
getParentEntityIds,
|
|
155
|
-
convertIdsToPaths
|
|
156
|
-
}), [
|
|
157
|
-
getCollection,
|
|
158
|
-
getRawCollection,
|
|
159
|
-
getAllParentReferencesForPath,
|
|
160
|
-
getParentCollectionSlugs,
|
|
161
|
-
getParentEntityIds,
|
|
162
|
-
convertIdsToPaths
|
|
163
|
-
]);
|
|
164
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { useCallback, useMemo } from "react";
|
|
2
|
-
import { removeInitialAndTrailingSlashes, resolveCollectionPathIds } from "@rebasepro/common";
|
|
3
|
-
import { CollectionRegistry } from "@rebasepro/common";
|
|
4
|
-
|
|
5
|
-
export function encodePath(input: string) {
|
|
6
|
-
return encodeURIComponent(removeInitialAndTrailingSlashes(input))
|
|
7
|
-
.replaceAll("%2F", "/")
|
|
8
|
-
.replaceAll("%23", "#");
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function useNavigationURLs(basePath: string, baseCollectionPath: string, collectionRegistryRef: React.MutableRefObject<CollectionRegistry>) {
|
|
12
|
-
|
|
13
|
-
const cleanBasePath = removeInitialAndTrailingSlashes(basePath);
|
|
14
|
-
const cleanBaseCollectionPath = removeInitialAndTrailingSlashes(baseCollectionPath);
|
|
15
|
-
|
|
16
|
-
const homeUrl = cleanBasePath ? `/${cleanBasePath}` : "/";
|
|
17
|
-
const fullCollectionPath = cleanBasePath ? `/${cleanBasePath}/${cleanBaseCollectionPath}` : `/${cleanBaseCollectionPath}`;
|
|
18
|
-
|
|
19
|
-
const buildAppUrlPath = useCallback((path: string): string => {
|
|
20
|
-
// Strip trailing /* wildcard from paths (used for nested routes in React Router)
|
|
21
|
-
const cleanPath = path.replace(/\/\*$/, "");
|
|
22
|
-
return cleanBasePath ? `/${cleanBasePath}/${encodePath(cleanPath)}` : `/${encodePath(cleanPath)}`;
|
|
23
|
-
}, [cleanBasePath]);
|
|
24
|
-
|
|
25
|
-
const buildUrlCollectionPath = useCallback((path: string): string => `${removeInitialAndTrailingSlashes(baseCollectionPath)}/${encodePath(path)}`,
|
|
26
|
-
[baseCollectionPath]);
|
|
27
|
-
|
|
28
|
-
const isUrlCollectionPath = useCallback(
|
|
29
|
-
(path: string): boolean => removeInitialAndTrailingSlashes(path + "/").startsWith(removeInitialAndTrailingSlashes(fullCollectionPath) + "/"),
|
|
30
|
-
[fullCollectionPath]);
|
|
31
|
-
|
|
32
|
-
const urlPathToDataPath = useCallback((path: string): string => {
|
|
33
|
-
const decodedPath = decodeURIComponent(path);
|
|
34
|
-
if (decodedPath.startsWith(fullCollectionPath))
|
|
35
|
-
return decodedPath.replace(fullCollectionPath, "");
|
|
36
|
-
throw Error("Expected path starting with " + fullCollectionPath);
|
|
37
|
-
}, [fullCollectionPath]);
|
|
38
|
-
|
|
39
|
-
const resolveDatabasePathsFrom = useCallback((path: string): string => {
|
|
40
|
-
const registry = collectionRegistryRef.current;
|
|
41
|
-
if (!registry) {
|
|
42
|
-
return resolveCollectionPathIds(path, []);
|
|
43
|
-
}
|
|
44
|
-
return resolveCollectionPathIds(path, registry.getCollections());
|
|
45
|
-
}, [collectionRegistryRef]);
|
|
46
|
-
|
|
47
|
-
return useMemo(() => ({
|
|
48
|
-
homeUrl,
|
|
49
|
-
fullCollectionPath,
|
|
50
|
-
buildAppUrlPath,
|
|
51
|
-
buildUrlCollectionPath,
|
|
52
|
-
isUrlCollectionPath,
|
|
53
|
-
urlPathToDataPath,
|
|
54
|
-
resolveDatabasePathsFrom
|
|
55
|
-
}), [homeUrl, fullCollectionPath, buildAppUrlPath, buildUrlCollectionPath, isUrlCollectionPath, urlPathToDataPath, resolveDatabasePathsFrom]);
|
|
56
|
-
}
|