@firecms/core 3.0.0-canary.167 → 3.0.0-canary.169
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/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +15 -1
- package/dist/components/EntityCollectionTable/index.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +4 -0
- package/dist/components/SelectableTable/SelectableTable.d.ts +12 -2
- package/dist/components/UnsavedChangesDialog.d.ts +8 -0
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -0
- package/dist/components/common/index.d.ts +1 -1
- package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +10 -2
- package/dist/components/common/useDebouncedCallback.d.ts +1 -0
- package/dist/components/common/useScrollRestoration.d.ts +14 -0
- package/dist/contexts/BreacrumbsContext.d.ts +8 -0
- package/dist/core/EntityEditView.d.ts +25 -7
- package/dist/core/FireCMSRouter.d.ts +4 -0
- package/dist/core/NavigationRoutes.d.ts +0 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/hooks/data/useEntityFetch.d.ts +2 -1
- package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
- package/dist/hooks/useBuildNavigationController.d.ts +0 -1
- package/dist/index.es.js +2344 -1305
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +2344 -1306
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
- package/dist/routes/CustomCMSRoute.d.ts +4 -0
- package/dist/routes/FireCMSRoute.d.ts +1 -0
- package/dist/routes/HomePageRoute.d.ts +3 -0
- package/dist/types/collections.d.ts +18 -6
- package/dist/types/datasource.d.ts +2 -2
- package/dist/types/dialogs_controller.d.ts +2 -6
- package/dist/types/entities.d.ts +1 -1
- package/dist/types/entity_actions.d.ts +1 -6
- package/dist/types/navigation.d.ts +28 -12
- package/dist/types/plugins.d.ts +1 -0
- package/dist/types/side_entity_controller.d.ts +1 -1
- package/dist/util/entity_cache.d.ts +23 -0
- package/dist/util/navigation_from_path.d.ts +5 -1
- package/dist/util/navigation_utils.d.ts +12 -1
- package/package.json +5 -5
- package/src/components/CircularProgressCenter.tsx +1 -1
- package/src/components/DeleteEntityDialog.tsx +1 -1
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +40 -19
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +10 -4
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +18 -1
- package/src/components/EntityCollectionTable/index.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +79 -38
- package/src/components/NotFoundPage.tsx +2 -2
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +9 -5
- package/src/components/SelectableTable/SelectableTable.tsx +18 -3
- package/src/components/UnsavedChangesDialog.tsx +42 -0
- package/src/components/VirtualTable/VirtualTable.tsx +19 -2
- package/src/components/VirtualTable/VirtualTableProps.tsx +15 -0
- package/src/components/VirtualTable/fields/VirtualTableInput.tsx +1 -1
- package/src/components/common/default_entity_actions.tsx +24 -10
- package/src/components/common/index.ts +1 -1
- package/src/components/common/{useDataSourceEntityCollectionTableController.tsx → useDataSourceTableController.tsx} +122 -13
- package/src/components/common/useDebouncedCallback.tsx +20 -0
- package/src/components/common/useScrollRestoration.tsx +68 -0
- package/src/contexts/BreacrumbsContext.tsx +38 -0
- package/src/contexts/DialogsProvider.tsx +0 -1
- package/src/core/DefaultAppBar.tsx +28 -4
- package/src/core/EntityEditView.tsx +457 -296
- package/src/core/EntitySidePanel.tsx +72 -6
- package/src/core/FireCMS.tsx +7 -4
- package/src/core/FireCMSRouter.tsx +17 -0
- package/src/core/NavigationRoutes.tsx +15 -28
- package/src/core/SideDialogs.tsx +10 -5
- package/src/core/index.tsx +4 -2
- package/src/hooks/data/save.ts +1 -1
- package/src/hooks/data/useCollectionFetch.tsx +1 -1
- package/src/hooks/data/useEntityFetch.tsx +5 -1
- package/src/hooks/useBreadcrumbsController.tsx +31 -0
- package/src/hooks/useBuildNavigationController.tsx +59 -21
- package/src/hooks/useLargeLayout.tsx +0 -35
- package/src/hooks/useResolvedNavigationFrom.tsx +4 -6
- package/src/internal/useBuildSideDialogsController.tsx +4 -2
- package/src/internal/useBuildSideEntityController.tsx +157 -77
- package/src/internal/useUnsavedChangesDialog.tsx +126 -92
- package/src/routes/CustomCMSRoute.tsx +21 -0
- package/src/routes/FireCMSRoute.tsx +230 -0
- package/src/routes/HomePageRoute.tsx +17 -0
- package/src/types/collections.ts +19 -6
- package/src/types/datasource.ts +2 -1
- package/src/types/dialogs_controller.tsx +2 -6
- package/src/types/entities.ts +1 -1
- package/src/types/entity_actions.tsx +1 -7
- package/src/types/navigation.ts +35 -16
- package/src/types/plugins.tsx +1 -0
- package/src/types/side_entity_controller.tsx +1 -1
- package/src/util/entity_cache.ts +196 -0
- package/src/util/navigation_from_path.ts +10 -2
- package/src/util/navigation_utils.ts +53 -1
- package/src/util/parent_references_from_path.ts +3 -3
- /package/src/util/{common.tsx → common.ts} +0 -0
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Custom hook to handle navigation blocking when there are unsaved changes.
|
|
3
|
+
*
|
|
4
|
+
* @param when - Indicates whether to block navigation.
|
|
5
|
+
* @param onSuccess - Callback invoked when navigation is confirmed.
|
|
6
|
+
* @returns An object containing the state of navigation blocking and handlers.
|
|
7
|
+
*/
|
|
2
8
|
export declare function useNavigationUnsavedChangesDialog(when: boolean, onSuccess: () => void): {
|
|
3
9
|
navigationWasBlocked: boolean;
|
|
4
10
|
handleCancel: () => void;
|
|
5
11
|
handleOk: () => void;
|
|
6
12
|
};
|
|
7
|
-
export interface UnsavedChangesDialogProps {
|
|
8
|
-
open: boolean;
|
|
9
|
-
body?: React.ReactNode;
|
|
10
|
-
title?: string;
|
|
11
|
-
handleOk: () => void;
|
|
12
|
-
handleCancel: () => void;
|
|
13
|
-
}
|
|
14
|
-
export declare function UnsavedChangesDialog({ open, handleOk, handleCancel, body, title }: UnsavedChangesDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function FireCMSRoute(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -72,6 +72,10 @@ export interface EntityCollection<M extends Record<string, any> = any, USER exte
|
|
|
72
72
|
* Set of properties that compose an entity
|
|
73
73
|
*/
|
|
74
74
|
properties: PropertiesOrBuilders<M>;
|
|
75
|
+
/**
|
|
76
|
+
* Default preview properties displayed when this collection is referenced to.
|
|
77
|
+
*/
|
|
78
|
+
previewProperties?: string[];
|
|
75
79
|
/**
|
|
76
80
|
* Title property of the entity. This is the property that will be used
|
|
77
81
|
* as the title in entity related views and references.
|
|
@@ -79,11 +83,10 @@ export interface EntityCollection<M extends Record<string, any> = any, USER exte
|
|
|
79
83
|
*/
|
|
80
84
|
titleProperty?: keyof M;
|
|
81
85
|
/**
|
|
82
|
-
*
|
|
83
|
-
* Defaults to `
|
|
84
|
-
* Keep in mind that you can also set this prop to individual properties.
|
|
86
|
+
* When editing an entity, you can choose to open the entity in a side dialog
|
|
87
|
+
* or in a full screen dialog. Defaults to `full_screen`.
|
|
85
88
|
*/
|
|
86
|
-
|
|
89
|
+
openEntityMode?: "side_panel" | "full_screen";
|
|
87
90
|
/**
|
|
88
91
|
* Order in which the properties are displayed.
|
|
89
92
|
* If you are specifying your collection as code, the order is the same as the
|
|
@@ -272,9 +275,12 @@ export interface EntityCollection<M extends Record<string, any> = any, USER exte
|
|
|
272
275
|
*/
|
|
273
276
|
sideDialogWidth?: number | string;
|
|
274
277
|
/**
|
|
275
|
-
*
|
|
278
|
+
* Can this collection configuration be edited by the end user.
|
|
279
|
+
* Defaults to `true`.
|
|
280
|
+
* Keep in mind that you can also set this prop to individual properties.
|
|
281
|
+
* This prop has only effect if you are using the collection editor.
|
|
276
282
|
*/
|
|
277
|
-
|
|
283
|
+
editable?: boolean;
|
|
278
284
|
}
|
|
279
285
|
/**
|
|
280
286
|
* Parameter passed to the `Actions` prop in the collection configuration.
|
|
@@ -485,6 +491,12 @@ export type EntityTableController<M extends Record<string, any> = any> = {
|
|
|
485
491
|
clearFilter?: () => void;
|
|
486
492
|
itemCount?: number;
|
|
487
493
|
setItemCount?: (itemCount: number) => void;
|
|
494
|
+
initialScroll?: number;
|
|
495
|
+
onScroll?: (props: {
|
|
496
|
+
scrollDirection: "forward" | "backward";
|
|
497
|
+
scrollOffset: number;
|
|
498
|
+
scrollUpdateWasRequested: boolean;
|
|
499
|
+
}) => void;
|
|
488
500
|
paginationEnabled?: boolean;
|
|
489
501
|
pageSize?: number;
|
|
490
502
|
checkFilterCombination?: (filterValues: FilterValues<any>, sortBy?: [string, "asc" | "desc"]) => boolean;
|
|
@@ -8,13 +8,13 @@ import { FireCMSContext } from "./firecms_context";
|
|
|
8
8
|
export interface FetchEntityProps<M extends Record<string, any> = any> {
|
|
9
9
|
path: string;
|
|
10
10
|
entityId: string;
|
|
11
|
+
databaseId?: string;
|
|
11
12
|
collection?: EntityCollection<M, any>;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
15
|
* @group Datasource
|
|
15
16
|
*/
|
|
16
17
|
export type ListenEntityProps<M extends Record<string, any> = any> = FetchEntityProps<M> & {
|
|
17
|
-
databaseId?: string;
|
|
18
18
|
onUpdate: (entity: Entity<M>) => void;
|
|
19
19
|
onError?: (error: Error) => void;
|
|
20
20
|
};
|
|
@@ -99,7 +99,7 @@ export interface DataSource {
|
|
|
99
99
|
* @param entityId
|
|
100
100
|
* @param collection
|
|
101
101
|
*/
|
|
102
|
-
fetchEntity<M extends Record<string, any> = any>({ path, entityId, collection }: FetchEntityProps<M>): Promise<Entity<M> | undefined>;
|
|
102
|
+
fetchEntity<M extends Record<string, any> = any>({ path, entityId, databaseId, collection }: FetchEntityProps<M>): Promise<Entity<M> | undefined>;
|
|
103
103
|
/**
|
|
104
104
|
* Get realtime updates on one entity.
|
|
105
105
|
* @param path
|
|
@@ -20,7 +20,7 @@ export interface DialogsController {
|
|
|
20
20
|
* Props used to open a side dialog
|
|
21
21
|
* @group Hooks and utilities
|
|
22
22
|
*/
|
|
23
|
-
export interface DialogControllerEntryProps
|
|
23
|
+
export interface DialogControllerEntryProps {
|
|
24
24
|
key: string;
|
|
25
25
|
/**
|
|
26
26
|
* The component type that will be rendered
|
|
@@ -28,9 +28,5 @@ export interface DialogControllerEntryProps<T extends object = {}> {
|
|
|
28
28
|
Component: React.ComponentType<{
|
|
29
29
|
open: boolean;
|
|
30
30
|
closeDialog: () => void;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Props to pass to the dialog component
|
|
34
|
-
*/
|
|
35
|
-
props?: T;
|
|
31
|
+
}>;
|
|
36
32
|
}
|
package/dist/types/entities.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type EntityStatus = "new" | "existing" | "copy";
|
|
|
7
7
|
* Representation of an entity fetched from the datasource
|
|
8
8
|
* @group Models
|
|
9
9
|
*/
|
|
10
|
-
export interface Entity<M extends object> {
|
|
10
|
+
export interface Entity<M extends object = any> {
|
|
11
11
|
/**
|
|
12
12
|
* ID of the entity
|
|
13
13
|
*/
|
|
@@ -4,7 +4,6 @@ import { Entity } from "./entities";
|
|
|
4
4
|
import { EntityCollection, SelectionController } from "./collections";
|
|
5
5
|
import { User } from "./user";
|
|
6
6
|
import { SideEntityController } from "./side_entity_controller";
|
|
7
|
-
import { FormContext } from "./fields";
|
|
8
7
|
/**
|
|
9
8
|
* An entity action is a custom action that can be performed on an entity.
|
|
10
9
|
* They are displayed in the entity view and in the collection view.
|
|
@@ -56,9 +55,5 @@ export type EntityActionClickProps<M extends object, USER extends User = User> =
|
|
|
56
55
|
* If this actions is being called from a side dialog
|
|
57
56
|
*/
|
|
58
57
|
sideEntityController?: SideEntityController;
|
|
59
|
-
|
|
60
|
-
* You can use the form context to manage the state of the form.
|
|
61
|
-
* This is only available if this action in being triggered from a form context.
|
|
62
|
-
*/
|
|
63
|
-
formContext?: FormContext<M>;
|
|
58
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
64
59
|
};
|
|
@@ -57,11 +57,13 @@ export type NavigationController<EC extends EntityCollection = EntityCollection<
|
|
|
57
57
|
*/
|
|
58
58
|
getCollectionFromPaths: (pathSegments: string[]) => EC | undefined;
|
|
59
59
|
/**
|
|
60
|
-
* Default path under the navigation routes of the CMS will be created
|
|
60
|
+
* Default path under the navigation routes of the CMS will be created.
|
|
61
|
+
* Defaults to '/'. You may want to change this `basepath` to 'admin' for example.
|
|
61
62
|
*/
|
|
62
63
|
basePath: string;
|
|
63
64
|
/**
|
|
64
|
-
* Default path under the collection routes of the CMS will be created
|
|
65
|
+
* Default path under the collection routes of the CMS will be created.
|
|
66
|
+
* It defaults to '/c'
|
|
65
67
|
*/
|
|
66
68
|
baseCollectionPath: string;
|
|
67
69
|
/**
|
|
@@ -72,14 +74,6 @@ export type NavigationController<EC extends EntityCollection = EntityCollection<
|
|
|
72
74
|
* @param cmsPath
|
|
73
75
|
*/
|
|
74
76
|
urlPathToDataPath: (cmsPath: string) => string;
|
|
75
|
-
/**
|
|
76
|
-
* Convert a collection or entity path to a URL path
|
|
77
|
-
* @param path
|
|
78
|
-
*/
|
|
79
|
-
buildCMSUrlPath: (path: string) => string;
|
|
80
|
-
buildUrlEditCollectionPath: (props: {
|
|
81
|
-
path: string;
|
|
82
|
-
}) => string;
|
|
83
77
|
/**
|
|
84
78
|
* Base url path for the home screen
|
|
85
79
|
*/
|
|
@@ -97,10 +91,11 @@ export type NavigationController<EC extends EntityCollection = EntityCollection<
|
|
|
97
91
|
*/
|
|
98
92
|
buildUrlCollectionPath: (path: string) => string;
|
|
99
93
|
/**
|
|
100
|
-
* Turn a path with
|
|
94
|
+
* Turn a path with collection ids into a resolved path.
|
|
95
|
+
* The ids (typically used in urls) will be replaced with relative paths (typically used in database paths)
|
|
101
96
|
* @param pathWithAliases
|
|
102
97
|
*/
|
|
103
|
-
|
|
98
|
+
resolveIdsFrom: (pathWithAliases: string) => string;
|
|
104
99
|
/**
|
|
105
100
|
* Call this method to recalculate the navigation
|
|
106
101
|
*/
|
|
@@ -120,6 +115,27 @@ export type NavigationController<EC extends EntityCollection = EntityCollection<
|
|
|
120
115
|
* @param ids
|
|
121
116
|
*/
|
|
122
117
|
convertIdsToPaths: (ids: string[]) => string[];
|
|
118
|
+
/**
|
|
119
|
+
* A function to navigate to a specified route or URL.
|
|
120
|
+
*
|
|
121
|
+
* @param {string} to - The target route or URL to navigate to.
|
|
122
|
+
* @param {NavigateOptions} [options] - Optional configuration settings for navigation, such as replace behavior or state data.
|
|
123
|
+
*/
|
|
124
|
+
navigate: (to: string, options?: NavigateOptions) => void;
|
|
125
|
+
};
|
|
126
|
+
export interface NavigateOptions {
|
|
127
|
+
replace?: boolean;
|
|
128
|
+
state?: any;
|
|
129
|
+
preventScrollReset?: boolean;
|
|
130
|
+
relative?: "route" | "path";
|
|
131
|
+
flushSync?: boolean;
|
|
132
|
+
viewTransition?: boolean;
|
|
133
|
+
}
|
|
134
|
+
export type NavigationBlocker = {
|
|
135
|
+
updateBlockListener: (path: string, block: boolean, basePath?: string) => () => void;
|
|
136
|
+
isBlocked: (path: string) => boolean;
|
|
137
|
+
proceed?: () => void;
|
|
138
|
+
reset?: () => void;
|
|
123
139
|
};
|
|
124
140
|
/**
|
|
125
141
|
* Custom additional views created by the developer, added to the main
|
package/dist/types/plugins.d.ts
CHANGED
|
@@ -162,6 +162,7 @@ export interface PluginFormActionProps<USER extends User = User, EC extends Enti
|
|
|
162
162
|
formContext?: FormContext<any>;
|
|
163
163
|
context: FireCMSContext<USER>;
|
|
164
164
|
currentEntityId?: string;
|
|
165
|
+
layout: "side_panel" | "full_screen";
|
|
165
166
|
}
|
|
166
167
|
export type PluginFieldBuilderParams<T extends CMSType = CMSType, M extends Record<string, any> = any, EC extends EntityCollection<M> = EntityCollection<M>> = {
|
|
167
168
|
fieldConfigId: string;
|
|
@@ -22,7 +22,7 @@ export interface EntitySidePanelProps<M extends Record<string, any> = any> {
|
|
|
22
22
|
* Open the entity with a selected sub-collection view. If the panel for this
|
|
23
23
|
* entity was already open, it is replaced.
|
|
24
24
|
*/
|
|
25
|
-
|
|
25
|
+
selectedTab?: string;
|
|
26
26
|
/**
|
|
27
27
|
* Use this prop to override the width of the form view.
|
|
28
28
|
* e.g. "600px"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Saves data to the in-memory cache and persists it individually in `localStorage`.
|
|
3
|
+
* @param path - The unique path/key for the data.
|
|
4
|
+
* @param data - The data to cache and persist.
|
|
5
|
+
*/
|
|
6
|
+
export declare function saveEntityToCache(path: string, data: object): void;
|
|
7
|
+
/**
|
|
8
|
+
* Retrieves an entity from the in-memory cache or `localStorage`.
|
|
9
|
+
* If the entity is not in the cache but exists in `localStorage`, it loads it into the cache.
|
|
10
|
+
* @param path - The unique path/key for the entity.
|
|
11
|
+
* @returns The cached entity or `undefined` if not found.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getEntityFromCache(path: string): object | undefined;
|
|
14
|
+
export declare function hasEntityInCache(path: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Removes an entity from both the in-memory cache and `localStorage`.
|
|
17
|
+
* @param path - The unique path/key for the entity to remove.
|
|
18
|
+
*/
|
|
19
|
+
export declare function removeEntityFromCache(path: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Clears the entire in-memory cache and removes all related entities from `localStorage`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function clearEntityCache(): void;
|
|
@@ -4,19 +4,23 @@ export interface NavigationViewEntityInternal<M extends Record<string, any>> {
|
|
|
4
4
|
type: "entity";
|
|
5
5
|
entityId: string;
|
|
6
6
|
path: string;
|
|
7
|
+
fullPath: string;
|
|
7
8
|
parentCollection: EntityCollection<M>;
|
|
8
9
|
}
|
|
9
10
|
export interface NavigationViewCollectionInternal<M extends Record<string, any>> {
|
|
10
11
|
type: "collection";
|
|
12
|
+
id: string;
|
|
11
13
|
path: string;
|
|
14
|
+
fullPath: string;
|
|
12
15
|
collection: EntityCollection<M>;
|
|
13
16
|
}
|
|
14
17
|
export interface NavigationViewEntityCustomInternal<M extends Record<string, any>> {
|
|
15
18
|
type: "custom_view";
|
|
16
19
|
path: string;
|
|
20
|
+
fullPath: string;
|
|
17
21
|
view: EntityCustomView<M>;
|
|
18
22
|
}
|
|
19
|
-
export declare function
|
|
23
|
+
export declare function getNavigationEntriesFromPath(props: {
|
|
20
24
|
path: string;
|
|
21
25
|
collections: EntityCollection[] | undefined;
|
|
22
26
|
currentFullPath?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityCollection } from "../types";
|
|
1
|
+
import { EntityCollection, NavigationController, SideEntityController } from "../types";
|
|
2
2
|
export declare function removeInitialAndTrailingSlashes(s: string): string;
|
|
3
3
|
export declare function removeInitialSlash(s: string): string;
|
|
4
4
|
export declare function removeTrailingSlash(s: string): string;
|
|
@@ -18,3 +18,14 @@ export declare function getCollectionByPathOrId(pathOrId: string, collections: E
|
|
|
18
18
|
* @param subpaths
|
|
19
19
|
*/
|
|
20
20
|
export declare function getCollectionPathsCombinations(subpaths: string[]): string[];
|
|
21
|
+
export declare function navigateToEntity({ openEntityMode, collection, entityId, copy, path, selectedTab, sideEntityController, onClose, navigation }: {
|
|
22
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
23
|
+
collection?: EntityCollection;
|
|
24
|
+
entityId?: string;
|
|
25
|
+
selectedTab?: string;
|
|
26
|
+
copy?: boolean;
|
|
27
|
+
path: string;
|
|
28
|
+
sideEntityController: SideEntityController;
|
|
29
|
+
onClose?: () => void;
|
|
30
|
+
navigation: NavigationController;
|
|
31
|
+
}): void;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firecms/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.0.0-canary.
|
|
4
|
+
"version": "3.0.0-canary.169",
|
|
5
5
|
"description": "Awesome Firebase/Firestore-based headless open-source CMS",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/firecmsco"
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"./package.json": "./package.json"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@firecms/editor": "^3.0.0-canary.
|
|
54
|
-
"@firecms/formex": "^3.0.0-canary.
|
|
55
|
-
"@firecms/ui": "^3.0.0-canary.
|
|
53
|
+
"@firecms/editor": "^3.0.0-canary.169",
|
|
54
|
+
"@firecms/formex": "^3.0.0-canary.169",
|
|
55
|
+
"@firecms/ui": "^3.0.0-canary.169",
|
|
56
56
|
"@hello-pangea/dnd": "^17.0.0",
|
|
57
57
|
"@radix-ui/react-portal": "^1.1.2",
|
|
58
58
|
"clsx": "^2.1.1",
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
"dist",
|
|
107
107
|
"src"
|
|
108
108
|
],
|
|
109
|
-
"gitHead": "
|
|
109
|
+
"gitHead": "8c086883fc1cb08a74d4bd66ef2f952affa9fdb9",
|
|
110
110
|
"publishConfig": {
|
|
111
111
|
"access": "public"
|
|
112
112
|
},
|
|
@@ -13,7 +13,7 @@ export function CircularProgressCenter({ text, ...props }: CircularProgressProps
|
|
|
13
13
|
}) {
|
|
14
14
|
return (
|
|
15
15
|
<div
|
|
16
|
-
className="flex w-full h-screen max-h-full max-w-full
|
|
16
|
+
className="flex w-full h-screen max-h-full max-w-full gap-4">
|
|
17
17
|
<div className="m-auto flex flex-col gap-2 items-center">
|
|
18
18
|
<CircularProgress {...props}/>
|
|
19
19
|
{text && <Typography
|
|
@@ -181,7 +181,7 @@ export function DeleteEntityDialog<M extends Record<string, any>>({
|
|
|
181
181
|
</DialogContent>
|
|
182
182
|
<DialogActions>
|
|
183
183
|
|
|
184
|
-
{loading && <CircularProgress size={"
|
|
184
|
+
{loading && <CircularProgress size={"smallest"}/>}
|
|
185
185
|
|
|
186
186
|
<Button onClick={handleCancel}
|
|
187
187
|
disabled={loading}
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import React, { MouseEvent, useCallback } from "react";
|
|
2
2
|
|
|
3
3
|
import { CollectionSize, Entity, EntityAction, EntityCollection, SelectionController } from "../../types";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
Checkbox,
|
|
6
|
+
Chip,
|
|
7
|
+
cls,
|
|
8
|
+
EditIcon,
|
|
9
|
+
IconButton,
|
|
10
|
+
Menu,
|
|
11
|
+
MenuItem,
|
|
12
|
+
MoreVertIcon,
|
|
13
|
+
Skeleton,
|
|
14
|
+
Tooltip
|
|
15
|
+
} from "@firecms/ui";
|
|
5
16
|
import { useFireCMSContext, useLargeLayout } from "../../hooks";
|
|
17
|
+
import { hasEntityInCache } from "../../util/entity_cache";
|
|
6
18
|
|
|
7
19
|
/**
|
|
8
20
|
*
|
|
@@ -32,23 +44,25 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
|
|
|
32
44
|
actions = [],
|
|
33
45
|
hideId,
|
|
34
46
|
selectionController,
|
|
47
|
+
openEntityMode
|
|
35
48
|
}:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
{
|
|
50
|
+
entity: Entity<any>,
|
|
51
|
+
collection?: EntityCollection<any>,
|
|
52
|
+
fullPath?: string,
|
|
53
|
+
width: number,
|
|
54
|
+
frozen?: boolean,
|
|
55
|
+
size: CollectionSize,
|
|
56
|
+
isSelected?: boolean,
|
|
57
|
+
selectionEnabled?: boolean,
|
|
58
|
+
actions?: EntityAction[],
|
|
59
|
+
hideId?: boolean,
|
|
60
|
+
onCollectionChange?: () => void,
|
|
61
|
+
selectionController?: SelectionController;
|
|
62
|
+
highlightEntity?: (entity: Entity<any>) => void;
|
|
63
|
+
unhighlightEntity?: (entity: Entity<any>) => void;
|
|
64
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
65
|
+
}) {
|
|
52
66
|
|
|
53
67
|
const largeLayout = useLargeLayout();
|
|
54
68
|
|
|
@@ -63,6 +77,7 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
|
|
|
63
77
|
|
|
64
78
|
const collapsedActions = actions.filter(a => a.collapsed || a.collapsed === undefined);
|
|
65
79
|
const uncollapsedActions = actions.filter(a => a.collapsed === false);
|
|
80
|
+
const hasDraft = hasEntityInCache(fullPath + "/" + entity.id);
|
|
66
81
|
return (
|
|
67
82
|
<div
|
|
68
83
|
className={cls(
|
|
@@ -98,6 +113,7 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
|
|
|
98
113
|
highlightEntity,
|
|
99
114
|
unhighlightEntity,
|
|
100
115
|
onCollectionChange,
|
|
116
|
+
openEntityMode: openEntityMode ?? collection?.openEntityMode
|
|
101
117
|
});
|
|
102
118
|
}}
|
|
103
119
|
size={largeLayout ? "medium" : "small"}>
|
|
@@ -126,6 +142,7 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
|
|
|
126
142
|
highlightEntity,
|
|
127
143
|
unhighlightEntity,
|
|
128
144
|
onCollectionChange,
|
|
145
|
+
openEntityMode: openEntityMode ?? collection?.openEntityMode
|
|
129
146
|
});
|
|
130
147
|
}}>
|
|
131
148
|
{action.icon}
|
|
@@ -148,11 +165,15 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
|
|
|
148
165
|
|
|
149
166
|
{!hideId && size !== "xs" && (
|
|
150
167
|
<div
|
|
151
|
-
className="w-[138px]
|
|
168
|
+
className="w-[138px] overflow-hidden truncate font-mono text-xs text-text-secondary dark:text-text-secondary-dark max-w-full text-ellipsis px-2 align-center flex items-center justify-center gap-1"
|
|
152
169
|
onClick={(event) => {
|
|
153
170
|
event.stopPropagation();
|
|
154
171
|
}}>
|
|
155
|
-
|
|
172
|
+
{hasDraft && <Tooltip title={"Unsaved changes"} className={"inline"}>
|
|
173
|
+
<Chip colorScheme={"orangeDarker"} className={"p-0.5"}>
|
|
174
|
+
<EditIcon size={12}/>
|
|
175
|
+
</Chip>
|
|
176
|
+
</Tooltip>}
|
|
156
177
|
{entity
|
|
157
178
|
? entity.id
|
|
158
179
|
: <Skeleton/>
|
|
@@ -34,14 +34,14 @@ import { getRowHeight } from "../common/table_height";
|
|
|
34
34
|
*
|
|
35
35
|
* The data displayed in the table is managed by a {@link EntityTableController}.
|
|
36
36
|
* You can build the default, bound to a path in the datasource, by using the hook
|
|
37
|
-
* {@link
|
|
37
|
+
* {@link useDataSourceTableController}
|
|
38
38
|
*
|
|
39
39
|
* @see EntityCollectionTableProps
|
|
40
40
|
* @see EntityCollectionView
|
|
41
41
|
* @see VirtualTable
|
|
42
42
|
* @group Components
|
|
43
43
|
*/
|
|
44
|
-
export const EntityCollectionTable = function EntityCollectionTable<M extends Record<string, any
|
|
44
|
+
export const EntityCollectionTable = function EntityCollectionTable<M extends Record<string, any> = any, USER extends User = any>
|
|
45
45
|
({
|
|
46
46
|
className,
|
|
47
47
|
style,
|
|
@@ -57,6 +57,8 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
57
57
|
highlightedEntities,
|
|
58
58
|
onEntityClick,
|
|
59
59
|
onColumnResize,
|
|
60
|
+
initialScroll,
|
|
61
|
+
onScroll,
|
|
60
62
|
onSizeChanged,
|
|
61
63
|
textSearchEnabled = false,
|
|
62
64
|
hoverRow = true,
|
|
@@ -76,7 +78,8 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
76
78
|
getIdColumnWidth,
|
|
77
79
|
onTextSearchClick,
|
|
78
80
|
textSearchLoading,
|
|
79
|
-
enablePopupIcon
|
|
81
|
+
enablePopupIcon,
|
|
82
|
+
openEntityMode = "side_panel"
|
|
80
83
|
}: EntityCollectionTableProps<M>) {
|
|
81
84
|
|
|
82
85
|
const ref = useRef<HTMLDivElement>(null);
|
|
@@ -265,7 +268,8 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
265
268
|
width={column.width}
|
|
266
269
|
frozen={column.frozen}
|
|
267
270
|
isSelected={false}
|
|
268
|
-
size={size}
|
|
271
|
+
size={size}
|
|
272
|
+
openEntityMode={openEntityMode}/>;
|
|
269
273
|
} else if (additionalFieldsMap[columnKey]) {
|
|
270
274
|
return additionalCellRenderer(props);
|
|
271
275
|
} else if (props.columnIndex < columns.length + 1) {
|
|
@@ -313,6 +317,8 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
313
317
|
highlightedRow={(entity: Entity<M>) => Boolean(selectedEntities?.find(e => e.id === entity.id && e.path === entity.path))}
|
|
314
318
|
tableController={tableController}
|
|
315
319
|
onValueChange={onValueChange}
|
|
320
|
+
initialScroll={initialScroll}
|
|
321
|
+
onScroll={onScroll}
|
|
316
322
|
onColumnResize={onColumnResize}
|
|
317
323
|
hoverRow={hoverRow}
|
|
318
324
|
filterable={filterable}
|
|
@@ -72,6 +72,21 @@ export type EntityCollectionTableProps<M extends Record<string, any>,
|
|
|
72
72
|
*/
|
|
73
73
|
onColumnResize?(params: OnColumnResizeParams): void;
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Initial scroll position
|
|
77
|
+
*/
|
|
78
|
+
initialScroll?: number;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Callback when the table is scrolled
|
|
82
|
+
* @param props
|
|
83
|
+
*/
|
|
84
|
+
onScroll?: (props: {
|
|
85
|
+
scrollDirection: "forward" | "backward",
|
|
86
|
+
scrollOffset: number,
|
|
87
|
+
scrollUpdateWasRequested: boolean
|
|
88
|
+
}) => void;
|
|
89
|
+
|
|
75
90
|
/**
|
|
76
91
|
* Callback when the selected size of the table is changed
|
|
77
92
|
*/
|
|
@@ -90,7 +105,7 @@ export type EntityCollectionTableProps<M extends Record<string, any>,
|
|
|
90
105
|
|
|
91
106
|
/**
|
|
92
107
|
* Controller holding the logic for the table
|
|
93
|
-
* {@link
|
|
108
|
+
* {@link useDataSourceTableController}
|
|
94
109
|
* {@link EntityTableController}
|
|
95
110
|
*/
|
|
96
111
|
tableController: EntityTableController<M>;
|
|
@@ -136,6 +151,8 @@ export type EntityCollectionTableProps<M extends Record<string, any>,
|
|
|
136
151
|
textSearchLoading?: boolean;
|
|
137
152
|
|
|
138
153
|
enablePopupIcon: boolean;
|
|
154
|
+
|
|
155
|
+
openEntityMode?: "side_panel" | "full_screen";
|
|
139
156
|
};
|
|
140
157
|
|
|
141
158
|
export type GetPropertyForProps<M extends Record<string, any>> = {
|
|
@@ -8,5 +8,5 @@ export type {
|
|
|
8
8
|
|
|
9
9
|
export * from "./PropertyTableCell";
|
|
10
10
|
export * from "./EntityCollectionRowActions";
|
|
11
|
-
export * from "../common/
|
|
11
|
+
export * from "../common/useDataSourceTableController";
|
|
12
12
|
export * from "./column_utils";
|
|
@@ -56,7 +56,7 @@ export function CollectionTableToolbar({
|
|
|
56
56
|
<Select
|
|
57
57
|
value={size as string}
|
|
58
58
|
className="w-16 h-10"
|
|
59
|
-
size={"
|
|
59
|
+
size={"small"}
|
|
60
60
|
onValueChange={(v) => onSizeChanged(v as CollectionSize)}
|
|
61
61
|
renderValue={(v) => <div className={"font-medium"}>{v.toUpperCase()}</div>}
|
|
62
62
|
>
|
|
@@ -87,9 +87,9 @@ export function CollectionTableToolbar({
|
|
|
87
87
|
|
|
88
88
|
<div className="flex items-center gap-2">
|
|
89
89
|
|
|
90
|
-
{largeLayout && <div className="w-[22px]">
|
|
90
|
+
{largeLayout && <div className="w-[22px] mr-4">
|
|
91
91
|
{loading &&
|
|
92
|
-
<CircularProgress size={"
|
|
92
|
+
<CircularProgress size={"smallest"}/>}
|
|
93
93
|
</div>}
|
|
94
94
|
|
|
95
95
|
{(onTextSearch || onTextSearchClick) &&
|