@firecms/collection_editor 3.0.0-beta.10 → 3.0.0-beta.12
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/ConfigControllerProvider.d.ts +0 -9
- package/dist/index.es.js +9188 -5266
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +9180 -5259
- package/dist/index.umd.js.map +1 -1
- package/dist/types/collection_editor_controller.d.ts +0 -10
- package/dist/types/config_permissions.d.ts +2 -2
- package/dist/types/persisted_collection.d.ts +1 -1
- package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +3 -1
- package/dist/ui/collection_editor/LayoutModeSwitch.d.ts +5 -0
- package/dist/useCollectionEditorPlugin.d.ts +4 -13
- package/dist/utils/collections.d.ts +1 -1
- package/package.json +22 -19
- package/src/ConfigControllerProvider.tsx +1 -10
- package/src/types/collection_editor_controller.tsx +0 -7
- package/src/types/config_permissions.ts +1 -1
- package/src/types/persisted_collection.ts +2 -3
- package/src/ui/CollectionViewHeaderAction.tsx +1 -1
- package/src/ui/HomePageEditorCollectionAction.tsx +1 -0
- package/src/ui/NewCollectionButton.tsx +1 -1
- package/src/ui/PropertyAddColumnComponent.tsx +2 -2
- package/src/ui/collection_editor/CollectionDetailsForm.tsx +26 -10
- package/src/ui/collection_editor/CollectionEditorDialog.tsx +50 -8
- package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +2 -2
- package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +3 -9
- package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +6 -5
- package/src/ui/collection_editor/EnumForm.tsx +10 -6
- package/src/ui/collection_editor/GetCodeDialog.tsx +42 -24
- package/src/ui/collection_editor/LayoutModeSwitch.tsx +54 -0
- package/src/ui/collection_editor/PropertyEditView.tsx +7 -3
- package/src/ui/collection_editor/PropertyFieldPreview.tsx +4 -4
- package/src/ui/collection_editor/PropertyTree.tsx +2 -2
- package/src/ui/collection_editor/UnsavedChangesDialog.tsx +3 -5
- package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +1 -0
- package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +2 -0
- package/src/ui/collection_editor/properties/BlockPropertyField.tsx +18 -12
- package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +4 -0
- package/src/ui/collection_editor/properties/EnumPropertyField.tsx +2 -0
- package/src/ui/collection_editor/properties/MapPropertyField.tsx +2 -1
- package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +3 -3
- package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +2 -0
- package/src/ui/collection_editor/properties/StoragePropertyField.tsx +3 -3
- package/src/ui/collection_editor/properties/UrlPropertyField.tsx +1 -0
- package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -1
- package/src/useCollectionEditorPlugin.tsx +6 -15
- package/src/utils/collections.ts +13 -7
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import { CollectionEditorPermissionsBuilder } from "./config_permissions";
|
|
3
2
|
import { Entity, Property } from "@firecms/core";
|
|
4
3
|
import { PersistedCollection } from "./persisted_collection";
|
|
@@ -36,13 +35,4 @@ export interface CollectionEditorController {
|
|
|
36
35
|
}) => void;
|
|
37
36
|
configPermissions: CollectionEditorPermissionsBuilder;
|
|
38
37
|
getPathSuggestions?: (path: string) => Promise<string[]>;
|
|
39
|
-
components?: {
|
|
40
|
-
/**
|
|
41
|
-
* Custom component to render the database field
|
|
42
|
-
*/
|
|
43
|
-
DatabaseField?: React.ComponentType<{
|
|
44
|
-
databaseId?: string;
|
|
45
|
-
onDatabaseIdUpdate: (databaseId: string) => void;
|
|
46
|
-
}>;
|
|
47
|
-
};
|
|
48
38
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EntityCollection } from "@firecms/core";
|
|
2
|
-
export type CollectionEditorPermissionsBuilder<
|
|
3
|
-
user:
|
|
2
|
+
export type CollectionEditorPermissionsBuilder<USER = any, EC extends EntityCollection = EntityCollection> = (params: {
|
|
3
|
+
user: USER | null;
|
|
4
4
|
collection?: EC;
|
|
5
5
|
}) => CollectionEditorPermissions;
|
|
6
6
|
export type CollectionEditorPermissions = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EntityCollection, User } from "@firecms/core";
|
|
2
|
-
export type PersistedCollection<M extends Record<string, any> = any,
|
|
2
|
+
export type PersistedCollection<M extends Record<string, any> = any, USER extends User = User> = Omit<EntityCollection<M, USER>, "subcollections"> & {
|
|
3
3
|
ownerId?: string;
|
|
4
4
|
subcollections?: PersistedCollection<any, any>[];
|
|
5
5
|
editable?: boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import { EntityCollection } from "@firecms/core";
|
|
2
|
-
export declare function CollectionDetailsForm({ isNewCollection, reservedGroups, existingPaths, existingIds, groups, parentCollection }: {
|
|
3
|
+
export declare function CollectionDetailsForm({ isNewCollection, reservedGroups, existingPaths, existingIds, groups, parentCollection, children }: {
|
|
3
4
|
isNewCollection: boolean;
|
|
4
5
|
reservedGroups?: string[];
|
|
5
6
|
existingPaths?: string[];
|
|
@@ -7,4 +8,5 @@ export declare function CollectionDetailsForm({ isNewCollection, reservedGroups,
|
|
|
7
8
|
groups: string[] | null;
|
|
8
9
|
parentCollection?: EntityCollection;
|
|
9
10
|
parentCollectionIds?: string[];
|
|
11
|
+
children?: React.ReactNode;
|
|
10
12
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -4,7 +4,7 @@ import { CollectionEditorPermissionsBuilder } from "./types/config_permissions";
|
|
|
4
4
|
import { PersistedCollection } from "./types/persisted_collection";
|
|
5
5
|
import { CollectionInference } from "./types/collection_inference";
|
|
6
6
|
import { CollectionsConfigController } from "./types/config_controller";
|
|
7
|
-
export interface CollectionConfigControllerProps<EC extends PersistedCollection = PersistedCollection,
|
|
7
|
+
export interface CollectionConfigControllerProps<EC extends PersistedCollection = PersistedCollection, USER extends User = User> {
|
|
8
8
|
/**
|
|
9
9
|
* Firebase app where the configuration is saved.
|
|
10
10
|
*/
|
|
@@ -12,7 +12,7 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
|
|
|
12
12
|
/**
|
|
13
13
|
* Define what actions can be performed on the configuration.
|
|
14
14
|
*/
|
|
15
|
-
configPermissions?: CollectionEditorPermissionsBuilder<
|
|
15
|
+
configPermissions?: CollectionEditorPermissionsBuilder<USER, EC>;
|
|
16
16
|
/**
|
|
17
17
|
* The words you define here will not be allowed to be used as group
|
|
18
18
|
* names when creating collections.
|
|
@@ -28,17 +28,8 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
|
|
|
28
28
|
getPathSuggestions?: (path?: string) => Promise<string[]>;
|
|
29
29
|
collectionInference?: CollectionInference;
|
|
30
30
|
getData?: (path: string, parentPaths: string[]) => Promise<object[]>;
|
|
31
|
-
getUser?: (uid: string) =>
|
|
31
|
+
getUser?: (uid: string) => USER | null;
|
|
32
32
|
onAnalyticsEvent?: (event: string, params?: object) => void;
|
|
33
|
-
components?: {
|
|
34
|
-
/**
|
|
35
|
-
* Custom component to render the database field
|
|
36
|
-
*/
|
|
37
|
-
DatabaseField?: React.ComponentType<{
|
|
38
|
-
databaseId?: string;
|
|
39
|
-
onDatabaseIdUpdate: (databaseId: string) => void;
|
|
40
|
-
}>;
|
|
41
|
-
};
|
|
42
33
|
}
|
|
43
34
|
/**
|
|
44
35
|
* Use this hook to initialise the Collection Editor plugin.
|
|
@@ -51,5 +42,5 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
|
|
|
51
42
|
* @param getUser
|
|
52
43
|
* @param collectionInference
|
|
53
44
|
*/
|
|
54
|
-
export declare function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection,
|
|
45
|
+
export declare function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, USER extends User = User>({ collectionConfigController, configPermissions, reservedGroups, extraView, getPathSuggestions, getUser, collectionInference, getData, onAnalyticsEvent, }: CollectionConfigControllerProps<EC, USER>): FireCMSPlugin<any, any, PersistedCollection>;
|
|
55
46
|
export declare function IntroWidget({}: {}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -3,4 +3,4 @@ import { PersistedCollection } from "../types/persisted_collection";
|
|
|
3
3
|
/**
|
|
4
4
|
* Function in charge of merging collections defined in code with those stored in the backend.
|
|
5
5
|
*/
|
|
6
|
-
export declare const mergeCollections: (baseCollections: EntityCollection[], backendCollections
|
|
6
|
+
export declare const mergeCollections: (baseCollections: EntityCollection[], backendCollections?: PersistedCollection[], modifyCollection?: (props: ModifyCollectionProps) => EntityCollection | void) => EntityCollection<any, any>[];
|
package/package.json
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firecms/collection_editor",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.0.0-beta.
|
|
4
|
+
"version": "3.0.0-beta.12",
|
|
5
5
|
"main": "./dist/index.umd.js",
|
|
6
6
|
"module": "./dist/index.es.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"source": "src/index.ts",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@firecms/data_export": "^3.0.0-beta.
|
|
11
|
-
"@firecms/data_import": "^3.0.0-beta.
|
|
12
|
-
"@firecms/data_import_export": "^3.0.0-beta.
|
|
13
|
-
"@firecms/formex": "^3.0.0-beta.
|
|
14
|
-
"@firecms/schema_inference": "^3.0.0-beta.
|
|
15
|
-
"@firecms/ui": "^3.0.0-beta.
|
|
10
|
+
"@firecms/data_export": "^3.0.0-beta.12",
|
|
11
|
+
"@firecms/data_import": "^3.0.0-beta.12",
|
|
12
|
+
"@firecms/data_import_export": "^3.0.0-beta.12",
|
|
13
|
+
"@firecms/formex": "^3.0.0-beta.12",
|
|
14
|
+
"@firecms/schema_inference": "^3.0.0-beta.12",
|
|
15
|
+
"@firecms/ui": "^3.0.0-beta.12",
|
|
16
|
+
"@hello-pangea/dnd": "^17.0.0",
|
|
16
17
|
"json5": "^2.2.3",
|
|
17
|
-
"prism-react-renderer": "^2.4.
|
|
18
|
+
"prism-react-renderer": "^2.4.1"
|
|
18
19
|
},
|
|
19
20
|
"peerDependencies": {
|
|
20
|
-
"react": "
|
|
21
|
-
"react-dom": "
|
|
22
|
-
"react-router": "^6.
|
|
23
|
-
"react-router-dom": "^6.
|
|
21
|
+
"react": ">=18.0.0",
|
|
22
|
+
"react-dom": ">=18.0.0",
|
|
23
|
+
"react-router": "^6.28.0",
|
|
24
|
+
"react-router-dom": "^6.28.0"
|
|
24
25
|
},
|
|
25
26
|
"exports": {
|
|
26
27
|
".": {
|
|
@@ -50,15 +51,17 @@
|
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
52
53
|
"@jest/globals": "^29.7.0",
|
|
53
|
-
"@types/react": "^18.3.
|
|
54
|
+
"@types/react": "^18.3.18",
|
|
54
55
|
"@types/react-dom": "^18.3.0",
|
|
55
|
-
"@vitejs/plugin-react": "^4.3.
|
|
56
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
57
|
+
"babel-plugin-react-compiler": "beta",
|
|
58
|
+
"eslint-plugin-react-compiler": "beta",
|
|
56
59
|
"jest": "^29.7.0",
|
|
57
|
-
"react-router": "^6.
|
|
58
|
-
"react-router-dom": "^6.
|
|
60
|
+
"react-router": "^6.28.2",
|
|
61
|
+
"react-router-dom": "^6.28.2",
|
|
59
62
|
"ts-jest": "^29.2.5",
|
|
60
|
-
"typescript": "^5.
|
|
61
|
-
"vite": "^5.4.
|
|
63
|
+
"typescript": "^5.7.3",
|
|
64
|
+
"vite": "^5.4.14"
|
|
62
65
|
},
|
|
63
66
|
"files": [
|
|
64
67
|
"dist",
|
|
@@ -67,5 +70,5 @@
|
|
|
67
70
|
"publishConfig": {
|
|
68
71
|
"access": "public"
|
|
69
72
|
},
|
|
70
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "8de3edb4560643922fe44e9c357985f64c3951c1"
|
|
71
74
|
}
|
|
@@ -57,13 +57,6 @@ export interface ConfigControllerProviderProps {
|
|
|
57
57
|
|
|
58
58
|
onAnalyticsEvent?: (event: string, params?: object) => void;
|
|
59
59
|
|
|
60
|
-
components?: {
|
|
61
|
-
/**
|
|
62
|
-
* Custom component to render the database field
|
|
63
|
-
*/
|
|
64
|
-
DatabaseField?: React.ComponentType<{ databaseId?: string, onDatabaseIdUpdate: (databaseId:string) => void }>;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
60
|
}
|
|
68
61
|
|
|
69
62
|
export const ConfigControllerProvider = React.memo(
|
|
@@ -78,7 +71,6 @@ export const ConfigControllerProvider = React.memo(
|
|
|
78
71
|
getUser,
|
|
79
72
|
getData,
|
|
80
73
|
onAnalyticsEvent,
|
|
81
|
-
components
|
|
82
74
|
}: PropsWithChildren<ConfigControllerProviderProps>) {
|
|
83
75
|
|
|
84
76
|
const navigation = useNavigationController();
|
|
@@ -239,7 +231,6 @@ export const ConfigControllerProvider = React.memo(
|
|
|
239
231
|
editProperty,
|
|
240
232
|
configPermissions: configPermissions ?? defaultConfigPermissions,
|
|
241
233
|
getPathSuggestions,
|
|
242
|
-
components
|
|
243
234
|
}}>
|
|
244
235
|
|
|
245
236
|
{children}
|
|
@@ -277,7 +268,7 @@ export const ConfigControllerProvider = React.memo(
|
|
|
277
268
|
getData={getData && currentPropertyDialog?.editedCollectionId
|
|
278
269
|
? () => {
|
|
279
270
|
console.debug("get data for property", currentPropertyDialog?.editedCollectionId);
|
|
280
|
-
const resolvedPath = navigation.
|
|
271
|
+
const resolvedPath = navigation.resolveIdsFrom(currentPropertyDialog.editedCollectionId!)
|
|
281
272
|
return getData(resolvedPath, []);
|
|
282
273
|
}
|
|
283
274
|
: undefined}
|
|
@@ -43,11 +43,4 @@ export interface CollectionEditorController {
|
|
|
43
43
|
|
|
44
44
|
getPathSuggestions?: (path: string) => Promise<string[]>;
|
|
45
45
|
|
|
46
|
-
components?: {
|
|
47
|
-
/**
|
|
48
|
-
* Custom component to render the database field
|
|
49
|
-
*/
|
|
50
|
-
DatabaseField?: React.ComponentType<{ databaseId?: string, onDatabaseIdUpdate: (databaseId: string) => void }>;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
46
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EntityCollection } from "@firecms/core";
|
|
2
2
|
|
|
3
|
-
export type CollectionEditorPermissionsBuilder<
|
|
3
|
+
export type CollectionEditorPermissionsBuilder<USER = any, EC extends EntityCollection = EntityCollection> = (params: { user: USER | null, collection?: EC }) => CollectionEditorPermissions;
|
|
4
4
|
|
|
5
5
|
export type CollectionEditorPermissions = {
|
|
6
6
|
/**
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { EntityCollection, User } from "@firecms/core";
|
|
2
2
|
|
|
3
|
-
export type PersistedCollection<M extends Record<string, any> = any,
|
|
4
|
-
= Omit<EntityCollection<M,
|
|
5
|
-
// properties: Properties<M>;
|
|
3
|
+
export type PersistedCollection<M extends Record<string, any> = any, USER extends User = User>
|
|
4
|
+
= Omit<EntityCollection<M, USER>, "subcollections"> & {
|
|
6
5
|
ownerId?: string;
|
|
7
6
|
subcollections?: PersistedCollection<any, any>[];
|
|
8
7
|
editable?: boolean;
|
|
@@ -29,7 +29,7 @@ export function CollectionViewHeaderAction({
|
|
|
29
29
|
asChild={true}
|
|
30
30
|
title={"Edit"}>
|
|
31
31
|
<IconButton
|
|
32
|
-
className={onHover ? "bg-white dark:bg-
|
|
32
|
+
className={onHover ? "bg-white dark:bg-surface-950" : "hidden"}
|
|
33
33
|
onClick={() => {
|
|
34
34
|
collectionEditorController.editProperty({
|
|
35
35
|
propertyKey,
|
|
@@ -14,6 +14,7 @@ export function HomePageEditorCollectionAction({
|
|
|
14
14
|
collection
|
|
15
15
|
}: PluginHomePageActionsProps) {
|
|
16
16
|
|
|
17
|
+
|
|
17
18
|
const snackbarController = useSnackbarController();
|
|
18
19
|
const authController = useAuthController();
|
|
19
20
|
const configController = useCollectionsConfigController();
|
|
@@ -3,7 +3,7 @@ import { useCollectionEditorController } from "../useCollectionEditorController"
|
|
|
3
3
|
|
|
4
4
|
export function NewCollectionButton() {
|
|
5
5
|
const collectionEditorController = useCollectionEditorController();
|
|
6
|
-
return <div className={"bg-
|
|
6
|
+
return <div className={"bg-surface-50 dark:bg-surface-900 min-w-fit rounded"}>
|
|
7
7
|
<Button className={"min-w-fit"}
|
|
8
8
|
variant={"outlined"}
|
|
9
9
|
onClick={() => collectionEditorController.createCollection({
|
|
@@ -29,8 +29,8 @@ export function PropertyAddColumnComponent({
|
|
|
29
29
|
asChild={true}
|
|
30
30
|
title={canEditCollection ? "Add new property" : "You don't have permission to add new properties"}>
|
|
31
31
|
<div
|
|
32
|
-
className={"p-0.5 w-20 h-full flex items-center justify-center cursor-pointer bg-
|
|
33
|
-
// className={onHover ? "bg-white dark:bg-
|
|
32
|
+
className={"p-0.5 w-20 h-full flex items-center justify-center cursor-pointer bg-surface-100 bg-opacity-40 hover:bg-surface-100 dark:bg-surface-950 dark:bg-opacity-40 dark:hover:bg-surface-950"}
|
|
33
|
+
// className={onHover ? "bg-white dark:bg-surface-950" : undefined}
|
|
34
34
|
onClick={() => {
|
|
35
35
|
collectionEditorController.editProperty({
|
|
36
36
|
editedCollectionId: collection.id,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
AutocompleteItem,
|
|
6
6
|
BooleanSwitchWithLabel,
|
|
7
7
|
Chip,
|
|
8
|
-
|
|
8
|
+
CloseIcon,
|
|
9
9
|
cls,
|
|
10
10
|
Container,
|
|
11
11
|
DebouncedTextField,
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
|
|
24
24
|
import { Field, getIn, useFormex } from "@firecms/formex";
|
|
25
25
|
import { useCollectionEditorController } from "../../useCollectionEditorController";
|
|
26
|
+
import { LayoutModeSwitch } from "./LayoutModeSwitch";
|
|
26
27
|
|
|
27
28
|
export function CollectionDetailsForm({
|
|
28
29
|
isNewCollection,
|
|
@@ -30,7 +31,8 @@ export function CollectionDetailsForm({
|
|
|
30
31
|
existingPaths,
|
|
31
32
|
existingIds,
|
|
32
33
|
groups,
|
|
33
|
-
parentCollection
|
|
34
|
+
parentCollection,
|
|
35
|
+
children
|
|
34
36
|
}: {
|
|
35
37
|
isNewCollection: boolean,
|
|
36
38
|
reservedGroups?: string[];
|
|
@@ -39,6 +41,7 @@ export function CollectionDetailsForm({
|
|
|
39
41
|
groups: string[] | null;
|
|
40
42
|
parentCollection?: EntityCollection;
|
|
41
43
|
parentCollectionIds?: string[];
|
|
44
|
+
children?: React.ReactNode;
|
|
42
45
|
}) {
|
|
43
46
|
|
|
44
47
|
const groupRef = React.useRef<HTMLInputElement>(null);
|
|
@@ -88,8 +91,6 @@ export function CollectionDetailsForm({
|
|
|
88
91
|
}
|
|
89
92
|
}, [errors.id]);
|
|
90
93
|
|
|
91
|
-
const DatabaseField = collectionEditor.components?.DatabaseField ?? DefaultDatabaseField;
|
|
92
|
-
|
|
93
94
|
const collectionIcon = <IconForView collectionOrView={values}/>;
|
|
94
95
|
|
|
95
96
|
const groupOptions = groups?.filter((group) => !reservedGroups?.includes(group));
|
|
@@ -126,8 +127,8 @@ export function CollectionDetailsForm({
|
|
|
126
127
|
<Typography variant={!isNewCollection ? "h5" : "h4"} className={"flex-grow"}>
|
|
127
128
|
{isNewCollection ? "New collection" : `${values?.name} collection`}
|
|
128
129
|
</Typography>
|
|
129
|
-
<
|
|
130
|
-
|
|
130
|
+
<DefaultDatabaseField databaseId={values.databaseId}
|
|
131
|
+
onDatabaseIdUpdate={updateDatabaseId}/>
|
|
131
132
|
|
|
132
133
|
<Tooltip title={"Change icon"}
|
|
133
134
|
asChild={true}>
|
|
@@ -207,14 +208,21 @@ export function CollectionDetailsForm({
|
|
|
207
208
|
<FieldCaption>
|
|
208
209
|
{showErrors && Boolean(errors.group) ? errors.group : "Group in the home page"}
|
|
209
210
|
</FieldCaption>
|
|
211
|
+
|
|
212
|
+
|
|
210
213
|
</div>}
|
|
211
214
|
|
|
212
|
-
<
|
|
215
|
+
<LayoutModeSwitch
|
|
216
|
+
className={"col-span-12"}
|
|
217
|
+
value={values.openEntityMode ?? "side_panel"}
|
|
218
|
+
onChange={(value) => setFieldValue("openEntityMode", value)}/>
|
|
219
|
+
|
|
220
|
+
<div className={"col-span-12 mt-8"}>
|
|
213
221
|
<ExpandablePanel
|
|
214
222
|
expanded={advancedPanelExpanded}
|
|
215
223
|
onExpandedChange={setAdvancedPanelExpanded}
|
|
216
224
|
title={
|
|
217
|
-
<div className="flex flex-row text-
|
|
225
|
+
<div className="flex flex-row text-surface-500">
|
|
218
226
|
<SettingsIcon/>
|
|
219
227
|
<Typography variant={"subtitle2"}
|
|
220
228
|
className="ml-2">
|
|
@@ -271,7 +279,7 @@ export function CollectionDetailsForm({
|
|
|
271
279
|
setFieldValue("sideDialogWidth", null);
|
|
272
280
|
}}
|
|
273
281
|
disabled={!values.sideDialogWidth}>
|
|
274
|
-
<
|
|
282
|
+
<CloseIcon size={"small"}/>
|
|
275
283
|
</IconButton>}
|
|
276
284
|
value={values.sideDialogWidth ?? ""}
|
|
277
285
|
label={"Side dialog width"}/>
|
|
@@ -298,6 +306,8 @@ export function CollectionDetailsForm({
|
|
|
298
306
|
<div className={"col-span-12"}>
|
|
299
307
|
<Select
|
|
300
308
|
name="defaultSize"
|
|
309
|
+
size={"large"}
|
|
310
|
+
fullWidth={true}
|
|
301
311
|
label="Default row size"
|
|
302
312
|
position={"item-aligned"}
|
|
303
313
|
onChange={handleChange}
|
|
@@ -318,6 +328,8 @@ export function CollectionDetailsForm({
|
|
|
318
328
|
name="customId"
|
|
319
329
|
label="Document IDs generation"
|
|
320
330
|
position={"item-aligned"}
|
|
331
|
+
size={"large"}
|
|
332
|
+
fullWidth={true}
|
|
321
333
|
disabled={customIdValue === "code_defined"}
|
|
322
334
|
onValueChange={(v) => {
|
|
323
335
|
if (v === "code_defined")
|
|
@@ -378,9 +390,13 @@ export function CollectionDetailsForm({
|
|
|
378
390
|
for large collections, as it may incur in performance and cost issues.
|
|
379
391
|
</FieldCaption>
|
|
380
392
|
</div>
|
|
393
|
+
|
|
394
|
+
|
|
381
395
|
</div>
|
|
382
396
|
</ExpandablePanel>
|
|
383
397
|
|
|
398
|
+
{children}
|
|
399
|
+
|
|
384
400
|
</div>
|
|
385
401
|
|
|
386
402
|
</div>
|
|
@@ -416,7 +432,7 @@ function DefaultDatabaseField({
|
|
|
416
432
|
return <Tooltip title={"Database ID"}
|
|
417
433
|
side={"top"}
|
|
418
434
|
align={"start"}>
|
|
419
|
-
<TextField size={"
|
|
435
|
+
<TextField size={"small"}
|
|
420
436
|
invisible={true}
|
|
421
437
|
inputClassName={"text-end"}
|
|
422
438
|
value={databaseId ?? ""}
|
|
@@ -2,6 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
import {
|
|
4
4
|
CircularProgressCenter,
|
|
5
|
+
ConfirmationDialog,
|
|
5
6
|
Entity,
|
|
6
7
|
EntityCollection,
|
|
7
8
|
ErrorView,
|
|
@@ -26,17 +27,19 @@ import {
|
|
|
26
27
|
import {
|
|
27
28
|
ArrowBackIcon,
|
|
28
29
|
Button,
|
|
30
|
+
CheckIcon,
|
|
29
31
|
cls,
|
|
30
32
|
coolIconKeys,
|
|
31
33
|
defaultBorderMixin,
|
|
32
34
|
Dialog,
|
|
33
35
|
DialogActions,
|
|
34
36
|
DialogContent,
|
|
35
|
-
|
|
37
|
+
DialogTitle,
|
|
36
38
|
IconButton,
|
|
37
39
|
LoadingButton,
|
|
38
40
|
Tab,
|
|
39
|
-
Tabs
|
|
41
|
+
Tabs,
|
|
42
|
+
Typography
|
|
40
43
|
} from "@firecms/ui";
|
|
41
44
|
import { YupSchema } from "./CollectionYupValidation";
|
|
42
45
|
import { CollectionDetailsForm } from "./CollectionDetailsForm";
|
|
@@ -114,6 +117,7 @@ export function CollectionEditorDialog(props: CollectionEditorDialogProps) {
|
|
|
114
117
|
maxWidth={"7xl"}
|
|
115
118
|
onOpenChange={(open) => !open ? handleCancel() : undefined}
|
|
116
119
|
>
|
|
120
|
+
<DialogTitle hidden>Collection editor</DialogTitle>
|
|
117
121
|
{open && <CollectionEditor {...props}
|
|
118
122
|
handleCancel={handleCancel}
|
|
119
123
|
setFormDirty={setFormDirty}/>}
|
|
@@ -276,6 +280,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
276
280
|
|
|
277
281
|
const saveCollection = (updatedCollection: PersistedCollection<M>): Promise<boolean> => {
|
|
278
282
|
const id = updatedCollection.id || updatedCollection.path;
|
|
283
|
+
|
|
279
284
|
return configController.saveCollection({
|
|
280
285
|
id,
|
|
281
286
|
collectionData: updatedCollection,
|
|
@@ -377,7 +382,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
377
382
|
|
|
378
383
|
if (!isNewCollection) {
|
|
379
384
|
saveCollection(newCollectionState).then(() => {
|
|
380
|
-
formexController.resetForm(
|
|
385
|
+
formexController.resetForm();
|
|
381
386
|
handleClose(newCollectionState);
|
|
382
387
|
});
|
|
383
388
|
return;
|
|
@@ -466,7 +471,8 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
466
471
|
const formController = useCreateFormex<PersistedCollection<M>>({
|
|
467
472
|
initialValues,
|
|
468
473
|
onSubmit,
|
|
469
|
-
validation
|
|
474
|
+
validation,
|
|
475
|
+
debugId: "COLLECTION_EDITOR"
|
|
470
476
|
});
|
|
471
477
|
|
|
472
478
|
const {
|
|
@@ -483,7 +489,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
483
489
|
const pathError = validatePath(path, isNewCollection, existingPaths, values.id);
|
|
484
490
|
|
|
485
491
|
const parentPaths = !pathError && parentCollectionIds ? navigation.convertIdsToPaths(parentCollectionIds) : undefined;
|
|
486
|
-
const resolvedPath = !pathError ? navigation.
|
|
492
|
+
const resolvedPath = !pathError ? navigation.resolveIdsFrom(updatedFullPath) : undefined;
|
|
487
493
|
const getDataWithPath = resolvedPath && getData ? async () => {
|
|
488
494
|
const data = await getData(resolvedPath, parentPaths ?? []);
|
|
489
495
|
if (existingEntities) {
|
|
@@ -529,14 +535,30 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
529
535
|
};
|
|
530
536
|
|
|
531
537
|
const editable = collection?.editable === undefined || collection?.editable === true;
|
|
538
|
+
// @ts-ignore
|
|
539
|
+
const isMergedCollection = collection?.merged ?? false;
|
|
532
540
|
const collectionEditable = editable || isNewCollection;
|
|
533
541
|
|
|
542
|
+
const [deleteRequested, setDeleteRequested] = useState(false);
|
|
543
|
+
|
|
544
|
+
const deleteCollection = () => {
|
|
545
|
+
if (!collection) return;
|
|
546
|
+
configController?.deleteCollection({ id: collection.id }).then(() => {
|
|
547
|
+
setDeleteRequested(false);
|
|
548
|
+
handleCancel();
|
|
549
|
+
snackbarController.open({
|
|
550
|
+
message: "Collection deleted",
|
|
551
|
+
type: "success"
|
|
552
|
+
});
|
|
553
|
+
});
|
|
554
|
+
};
|
|
555
|
+
|
|
534
556
|
return <DialogContent fullHeight={true}>
|
|
535
557
|
<Formex value={formController}>
|
|
536
558
|
|
|
537
559
|
<>
|
|
538
560
|
{!isNewCollection && <Tabs value={currentView}
|
|
539
|
-
|
|
561
|
+
innerClassName={cls(defaultBorderMixin, "px-4 h-14 w-full justify-end bg-surface-50 dark:bg-surface-950 border-b")}
|
|
540
562
|
onValueChange={(v) => setCurrentView(v as EditorView)}>
|
|
541
563
|
<Tab value={"details"}>
|
|
542
564
|
Details
|
|
@@ -610,7 +632,18 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
610
632
|
groups={groups}
|
|
611
633
|
parentCollectionIds={parentCollectionIds}
|
|
612
634
|
parentCollection={parentCollection}
|
|
613
|
-
isNewCollection={isNewCollection}
|
|
635
|
+
isNewCollection={isNewCollection}>
|
|
636
|
+
{!isNewCollection && isMergedCollection && <div className={"flex flex-col gap-4 mt-8"}>
|
|
637
|
+
<Typography variant={"body2"} color={"secondary"}>This collection is defined in code.
|
|
638
|
+
The changes done in this editor will override the properties defined in code.
|
|
639
|
+
You can delete the overridden values to revert to the state defined in code.
|
|
640
|
+
</Typography>
|
|
641
|
+
<Button variant={"neutral"}
|
|
642
|
+
onClick={() => {
|
|
643
|
+
setDeleteRequested(true);
|
|
644
|
+
}}>Reset to code</Button>
|
|
645
|
+
</div>}
|
|
646
|
+
</CollectionDetailsForm>}
|
|
614
647
|
|
|
615
648
|
{currentView === "subcollections" && collection &&
|
|
616
649
|
<SubcollectionsEditTab
|
|
@@ -722,7 +755,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
722
755
|
loading={isSubmitting}
|
|
723
756
|
disabled={isSubmitting || (currentView === "details" && !validValues)}
|
|
724
757
|
startIcon={currentView === "properties"
|
|
725
|
-
? <
|
|
758
|
+
? <CheckIcon/>
|
|
726
759
|
: undefined}
|
|
727
760
|
>
|
|
728
761
|
{currentView === "details" && "Next"}
|
|
@@ -744,6 +777,15 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
744
777
|
|
|
745
778
|
</Formex>
|
|
746
779
|
|
|
780
|
+
<ConfirmationDialog
|
|
781
|
+
open={deleteRequested}
|
|
782
|
+
onAccept={deleteCollection}
|
|
783
|
+
onCancel={() => setDeleteRequested(false)}
|
|
784
|
+
title={<>Delete the stored config?</>}
|
|
785
|
+
body={<> This will <b>not
|
|
786
|
+
delete any data</b>, only
|
|
787
|
+
the stored config, and reset to the code state.</>}/>
|
|
788
|
+
|
|
747
789
|
</DialogContent>
|
|
748
790
|
|
|
749
791
|
}
|
|
@@ -191,9 +191,9 @@ export function TemplateButton({
|
|
|
191
191
|
onClick={onClick}
|
|
192
192
|
className={cls(
|
|
193
193
|
"my-2 rounded-md border mx-0 p-6 px-4 focus:outline-none transition ease-in-out duration-150 flex flex-row gap-4 items-center",
|
|
194
|
-
"text-
|
|
194
|
+
"text-surface-700 dark:text-surface-accent-300",
|
|
195
195
|
"hover:border-primary-dark hover:text-primary-dark dark:hover:text-primary focus:ring-primary hover:ring-1 hover:ring-primary",
|
|
196
|
-
"border-
|
|
196
|
+
"border-surface-400 dark:border-surface-600 "
|
|
197
197
|
)}
|
|
198
198
|
>
|
|
199
199
|
{icon}
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "@firecms/core";
|
|
17
17
|
import {
|
|
18
18
|
AddIcon,
|
|
19
|
-
|
|
19
|
+
AutorenewIcon,
|
|
20
20
|
Button,
|
|
21
21
|
CircularProgress,
|
|
22
22
|
cls,
|
|
@@ -233,12 +233,6 @@ export function CollectionPropertiesEditorForm({
|
|
|
233
233
|
|
|
234
234
|
// If the id has changed we need to a little cleanup
|
|
235
235
|
if (previousId && previousId !== id) {
|
|
236
|
-
console.debug("onPropertyChanged, id change", {
|
|
237
|
-
id,
|
|
238
|
-
property,
|
|
239
|
-
previousId,
|
|
240
|
-
namespace
|
|
241
|
-
})
|
|
242
236
|
|
|
243
237
|
const previousFullId = getFullId(previousId, namespace);
|
|
244
238
|
const previousPropertyPath = idToPropertiesPath(previousFullId);
|
|
@@ -316,7 +310,7 @@ export function CollectionPropertiesEditorForm({
|
|
|
316
310
|
};
|
|
317
311
|
|
|
318
312
|
const body = (
|
|
319
|
-
<div className={"grid grid-cols-12 gap-2 h-full bg-
|
|
313
|
+
<div className={"grid grid-cols-12 gap-2 h-full bg-surface-50 dark:bg-surface-900"}>
|
|
320
314
|
<div className={cls(
|
|
321
315
|
"p-4 md:p-8 pb-20 md:pb-20",
|
|
322
316
|
"col-span-12 lg:col-span-5 h-full overflow-auto",
|
|
@@ -366,7 +360,7 @@ export function CollectionPropertiesEditorForm({
|
|
|
366
360
|
variant={"filled"}
|
|
367
361
|
disabled={inferringProperties}
|
|
368
362
|
onClick={inferPropertiesFromData}>
|
|
369
|
-
{inferringProperties ? <CircularProgress size={"small"}/> : <
|
|
363
|
+
{inferringProperties ? <CircularProgress size={"small"}/> : <AutorenewIcon/>}
|
|
370
364
|
</IconButton>
|
|
371
365
|
</Tooltip>}
|
|
372
366
|
<Tooltip title={"Add new property"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { useCustomizationController } from "@firecms/core";
|
|
2
|
-
import { Button, Dialog, DialogActions, DialogContent, Typography } from "@firecms/ui";
|
|
2
|
+
import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from "@firecms/ui";
|
|
3
3
|
import React from "react";
|
|
4
4
|
|
|
5
|
-
export function EntityCustomViewsSelectDialog({
|
|
5
|
+
export function EntityCustomViewsSelectDialog({
|
|
6
|
+
open,
|
|
7
|
+
onClose
|
|
8
|
+
}: { open: boolean, onClose: (selectedViewKey?: string) => void }) {
|
|
6
9
|
const {
|
|
7
10
|
entityViews,
|
|
8
11
|
} = useCustomizationController();
|
|
@@ -10,10 +13,8 @@ export function EntityCustomViewsSelectDialog({ open, onClose }: { open: boolean
|
|
|
10
13
|
return <Dialog
|
|
11
14
|
maxWidth={"md"}
|
|
12
15
|
open={open}>
|
|
16
|
+
<DialogTitle>Select custom view</DialogTitle>
|
|
13
17
|
<DialogContent className={"flex flex-col gap-4"}>
|
|
14
|
-
<Typography variant={"h6"}>
|
|
15
|
-
Select view
|
|
16
|
-
</Typography>
|
|
17
18
|
{entityViews?.map((view) => {
|
|
18
19
|
return <Button
|
|
19
20
|
key={view.key}
|