@firecms/core 3.0.0-rc.1 → 3.0.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/HomePage/HomePageDnD.d.ts +2 -1
- package/dist/components/PropertyCollectionView.d.ts +23 -0
- package/dist/components/UserDisplay.d.ts +7 -0
- package/dist/components/VirtualTable/fields/VirtualTableUserSelect.d.ts +12 -0
- package/dist/contexts/InternalUserManagementContext.d.ts +3 -0
- package/dist/core/EntityEditView.d.ts +10 -4
- package/dist/core/FireCMS.d.ts +0 -1
- package/dist/core/field_configs.d.ts +1 -1
- package/dist/form/EntityForm.d.ts +5 -2
- package/dist/form/components/LocalChangesMenu.d.ts +11 -0
- package/dist/form/field_bindings/UserSelectFieldBinding.d.ts +12 -0
- package/dist/form/index.d.ts +2 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/useCollapsedGroups.d.ts +9 -0
- package/dist/hooks/useInternalUserManagementController.d.ts +12 -0
- package/dist/index.es.js +1983 -650
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1981 -648
- package/dist/index.umd.js.map +1 -1
- package/dist/preview/components/UserPreview.d.ts +8 -0
- package/dist/preview/index.d.ts +1 -0
- package/dist/types/collections.d.ts +13 -0
- package/dist/types/entities.d.ts +5 -1
- package/dist/types/firecms.d.ts +15 -0
- package/dist/types/firecms_context.d.ts +16 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/internal_user_management.d.ts +20 -0
- package/dist/types/plugins.d.ts +2 -0
- package/dist/types/properties.d.ts +41 -6
- package/dist/types/property_config.d.ts +1 -1
- package/dist/types/user.d.ts +1 -1
- package/dist/util/collections.d.ts +1 -0
- package/dist/util/entity_cache.d.ts +6 -1
- package/dist/util/make_properties_editable.d.ts +1 -2
- package/dist/util/objects.d.ts +1 -0
- package/dist/util/useStorageUploadController.d.ts +1 -0
- package/package.json +6 -6
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +47 -47
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +12 -0
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +6 -1
- package/src/components/EntityView.tsx +29 -40
- package/src/components/ErrorView.tsx +1 -1
- package/src/components/HomePage/DefaultHomePage.tsx +21 -34
- package/src/components/HomePage/HomePageDnD.tsx +143 -83
- package/src/components/HomePage/RenameGroupDialog.tsx +9 -3
- package/src/components/PropertyCollectionView.tsx +329 -0
- package/src/components/PropertyConfigBadge.tsx +2 -2
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +2 -1
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
- package/src/components/UserDisplay.tsx +55 -0
- package/src/components/VirtualTable/fields/VirtualTableUserSelect.tsx +99 -0
- package/src/components/common/useColumnsIds.tsx +1 -8
- package/src/contexts/InternalUserManagementContext.tsx +4 -0
- package/src/core/EntityEditView.tsx +27 -14
- package/src/core/EntityEditViewFormActions.tsx +33 -18
- package/src/core/EntitySidePanel.tsx +9 -3
- package/src/core/FireCMS.tsx +22 -13
- package/src/core/field_configs.tsx +15 -1
- package/src/form/EntityForm.tsx +173 -42
- package/src/form/EntityFormActions.tsx +30 -15
- package/src/form/PropertyFieldBinding.tsx +4 -0
- package/src/form/components/ErrorFocus.tsx +22 -29
- package/src/form/components/LocalChangesMenu.tsx +144 -0
- package/src/form/field_bindings/UserSelectFieldBinding.tsx +94 -0
- package/src/form/index.tsx +5 -1
- package/src/hooks/index.tsx +3 -0
- package/src/hooks/useBrowserTitleAndIcon.tsx +1 -1
- package/src/hooks/useBuildNavigationController.tsx +104 -31
- package/src/hooks/useCollapsedGroups.ts +64 -0
- package/src/hooks/useFireCMSContext.tsx +6 -2
- package/src/hooks/useInternalUserManagementController.tsx +16 -0
- package/src/preview/PropertyPreview.tsx +8 -0
- package/src/preview/components/ReferencePreview.tsx +4 -2
- package/src/preview/components/UserPreview.tsx +27 -0
- package/src/preview/index.ts +1 -0
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +1 -1
- package/src/preview/property_previews/MapPropertyPreview.tsx +2 -2
- package/src/preview/property_previews/NumberPropertyPreview.tsx +2 -2
- package/src/types/collections.ts +14 -0
- package/src/types/entities.ts +7 -1
- package/src/types/firecms.tsx +16 -0
- package/src/types/firecms_context.tsx +17 -0
- package/src/types/index.ts +1 -0
- package/src/types/internal_user_management.ts +24 -0
- package/src/types/plugins.tsx +3 -0
- package/src/types/properties.ts +45 -6
- package/src/types/property_config.tsx +1 -0
- package/src/types/user.ts +1 -1
- package/src/util/collections.ts +8 -0
- package/src/util/createFormexStub.tsx +4 -0
- package/src/util/entities.ts +1 -1
- package/src/util/entity_cache.ts +72 -53
- package/src/util/join_collections.ts +3 -3
- package/src/util/make_properties_editable.ts +0 -22
- package/src/util/objects.ts +40 -2
- package/src/util/useStorageUploadController.tsx +71 -34
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Entity,
|
|
4
4
|
EntityCollection,
|
|
5
5
|
EntityStatus,
|
|
6
|
+
EntityValues,
|
|
6
7
|
FireCMSPlugin,
|
|
7
8
|
FormContext,
|
|
8
9
|
PluginFormActionProps,
|
|
@@ -26,7 +27,7 @@ import {
|
|
|
26
27
|
useLargeLayout
|
|
27
28
|
} from "../hooks";
|
|
28
29
|
import { CircularProgress, cls, CodeIcon, defaultBorderMixin, Tab, Tabs, Typography } from "@firecms/ui";
|
|
29
|
-
import {
|
|
30
|
+
import { getEntityFromMemoryCache } from "../util/entity_cache";
|
|
30
31
|
import { EntityForm, EntityFormProps } from "../form";
|
|
31
32
|
import { EntityEditViewFormActions } from "./EntityEditViewFormActions";
|
|
32
33
|
import { EntityJsonPreview } from "../components/EntityJsonPreview";
|
|
@@ -44,6 +45,13 @@ export type OnUpdateParams = {
|
|
|
44
45
|
collection: EntityCollection<any>
|
|
45
46
|
};
|
|
46
47
|
|
|
48
|
+
export type BarActionsParams = {
|
|
49
|
+
values: object,
|
|
50
|
+
status: EntityStatus,
|
|
51
|
+
path: string,
|
|
52
|
+
entityId?: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
47
55
|
export type OnTabChangeParams<M extends Record<string, any>> = {
|
|
48
56
|
path: string;
|
|
49
57
|
entityId?: string;
|
|
@@ -67,11 +75,11 @@ export interface EntityEditViewProps<M extends Record<string, any>> {
|
|
|
67
75
|
copy?: boolean;
|
|
68
76
|
selectedTab?: string;
|
|
69
77
|
parentCollectionIds: string[];
|
|
70
|
-
onValuesModified?: (modified: boolean) => void;
|
|
78
|
+
onValuesModified?: (modified: boolean, values:M) => void;
|
|
71
79
|
onSaved?: (params: OnUpdateParams) => void;
|
|
72
80
|
onTabChange?: (props: OnTabChangeParams<M>) => void;
|
|
73
81
|
layout?: "side_panel" | "full_screen";
|
|
74
|
-
barActions?: React.ReactNode;
|
|
82
|
+
barActions?: (params: BarActionsParams) => React.ReactNode;
|
|
75
83
|
formProps?: Partial<EntityFormProps<M>>,
|
|
76
84
|
}
|
|
77
85
|
|
|
@@ -97,9 +105,9 @@ export function EntityEditView<M extends Record<string, any>, USER extends User>
|
|
|
97
105
|
useCache: false
|
|
98
106
|
});
|
|
99
107
|
|
|
100
|
-
const
|
|
101
|
-
?
|
|
102
|
-
:
|
|
108
|
+
const initialDirtyValues = entityId
|
|
109
|
+
? getEntityFromMemoryCache(props.path + "/" + entityId)
|
|
110
|
+
: getEntityFromMemoryCache(props.path + "#new");
|
|
103
111
|
|
|
104
112
|
const authController = useAuthController();
|
|
105
113
|
|
|
@@ -114,18 +122,18 @@ export function EntityEditView<M extends Record<string, any>, USER extends User>
|
|
|
114
122
|
}
|
|
115
123
|
}, [authController, entity, status]);
|
|
116
124
|
|
|
117
|
-
if ((dataLoading && !
|
|
125
|
+
if ((dataLoading && !initialDirtyValues) || (!entity || canEdit === undefined) && (status === "existing" || status === "copy")) {
|
|
118
126
|
return <CircularProgressCenter/>;
|
|
119
127
|
}
|
|
120
128
|
|
|
121
|
-
if (entityId && !entity && !
|
|
129
|
+
if (entityId && !entity && !initialDirtyValues) {
|
|
122
130
|
console.error(`Entity with id ${entityId} not found in collection ${props.path}`);
|
|
123
131
|
}
|
|
124
132
|
|
|
125
133
|
return <EntityEditViewInner<M> {...props}
|
|
126
134
|
entityId={entityId}
|
|
127
135
|
entity={entity}
|
|
128
|
-
|
|
136
|
+
initialDirtyValues={initialDirtyValues as Partial<M>}
|
|
129
137
|
dataLoading={dataLoading}
|
|
130
138
|
status={status}
|
|
131
139
|
setStatus={setStatus}
|
|
@@ -144,7 +152,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
144
152
|
onSaved,
|
|
145
153
|
onTabChange,
|
|
146
154
|
entity,
|
|
147
|
-
|
|
155
|
+
initialDirtyValues,
|
|
148
156
|
dataLoading,
|
|
149
157
|
layout = "side_panel",
|
|
150
158
|
barActions,
|
|
@@ -154,7 +162,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
154
162
|
canEdit
|
|
155
163
|
}: EntityEditViewProps<M> & {
|
|
156
164
|
entity?: Entity<M>,
|
|
157
|
-
|
|
165
|
+
initialDirtyValues?: Partial<M>, // dirty cached entity in memory
|
|
158
166
|
dataLoading: boolean,
|
|
159
167
|
status: EntityStatus,
|
|
160
168
|
setStatus: (status: EntityStatus) => void,
|
|
@@ -379,7 +387,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
379
387
|
entityId={entityId ?? usedEntity?.id}
|
|
380
388
|
onValuesModified={onValuesModified}
|
|
381
389
|
entity={entity}
|
|
382
|
-
initialDirtyValues={
|
|
390
|
+
initialDirtyValues={initialDirtyValues}
|
|
383
391
|
openEntityMode={layout}
|
|
384
392
|
forceActionsAtTheBottom={actionsAtTheBottom}
|
|
385
393
|
initialStatus={status}
|
|
@@ -388,6 +396,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
388
396
|
disabled={!canEdit}
|
|
389
397
|
{...formProps}
|
|
390
398
|
onEntityChange={(entity) => {
|
|
399
|
+
console.log("333 EntityEditView onEntityChange:", entity);
|
|
391
400
|
setUsedEntity(entity);
|
|
392
401
|
formProps?.onEntityChange?.(entity);
|
|
393
402
|
}}
|
|
@@ -445,7 +454,12 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
445
454
|
{shouldShowTopBar && <div
|
|
446
455
|
className={cls("h-14 items-center flex overflow-visible overflow-x-scroll w-full no-scrollbar h-14 border-b pl-2 pr-2 pt-1 flex bg-surface-50 dark:bg-surface-900", defaultBorderMixin)}>
|
|
447
456
|
|
|
448
|
-
{barActions
|
|
457
|
+
{barActions?.({
|
|
458
|
+
path: fullIdPath ?? path,
|
|
459
|
+
entityId,
|
|
460
|
+
values: formContext?.values ?? usedEntity?.values ?? {},
|
|
461
|
+
status
|
|
462
|
+
})}
|
|
449
463
|
|
|
450
464
|
<div className={"flex-grow"}/>
|
|
451
465
|
|
|
@@ -523,4 +537,3 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
523
537
|
|
|
524
538
|
return result;
|
|
525
539
|
}
|
|
526
|
-
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
cls,
|
|
18
18
|
defaultBorderMixin,
|
|
19
19
|
DialogActions,
|
|
20
|
+
ErrorIcon,
|
|
20
21
|
IconButton,
|
|
21
22
|
LoadingButton,
|
|
22
23
|
Tooltip,
|
|
@@ -31,6 +32,8 @@ import {
|
|
|
31
32
|
} from "../hooks";
|
|
32
33
|
import { EntityFormActionsProps } from "../form/EntityFormActions";
|
|
33
34
|
import { SideDialogController, useSideDialogContext } from "./SideDialogs";
|
|
35
|
+
import { FormexController } from "@firecms/formex";
|
|
36
|
+
import { ErrorTooltip } from "../components/ErrorTooltip";
|
|
34
37
|
|
|
35
38
|
export function EntityEditViewFormActions({
|
|
36
39
|
collection,
|
|
@@ -80,14 +83,14 @@ export function EntityEditViewFormActions({
|
|
|
80
83
|
collection,
|
|
81
84
|
context,
|
|
82
85
|
sideEntityController,
|
|
83
|
-
isSubmitting: formex.isSubmitting,
|
|
84
86
|
disabled,
|
|
85
87
|
status,
|
|
86
88
|
sideDialogContext,
|
|
87
89
|
pluginActions,
|
|
88
90
|
openEntityMode,
|
|
89
91
|
navigateBack,
|
|
90
|
-
formContext
|
|
92
|
+
formContext,
|
|
93
|
+
formex
|
|
91
94
|
})
|
|
92
95
|
: buildSideActions({
|
|
93
96
|
savingError,
|
|
@@ -96,14 +99,14 @@ export function EntityEditViewFormActions({
|
|
|
96
99
|
collection,
|
|
97
100
|
context,
|
|
98
101
|
sideEntityController,
|
|
99
|
-
isSubmitting: formex.isSubmitting,
|
|
100
102
|
sideDialogContext,
|
|
101
103
|
disabled,
|
|
102
104
|
status,
|
|
103
105
|
pluginActions,
|
|
104
106
|
openEntityMode,
|
|
105
107
|
navigateBack,
|
|
106
|
-
formContext
|
|
108
|
+
formContext,
|
|
109
|
+
formex
|
|
107
110
|
});
|
|
108
111
|
}
|
|
109
112
|
|
|
@@ -114,14 +117,14 @@ type ActionsViewProps<M extends object> = {
|
|
|
114
117
|
collection: ResolvedEntityCollection,
|
|
115
118
|
context: FireCMSContext,
|
|
116
119
|
sideEntityController: SideEntityController,
|
|
117
|
-
isSubmitting: boolean,
|
|
118
120
|
disabled: boolean,
|
|
119
121
|
status: "new" | "existing" | "copy",
|
|
120
122
|
sideDialogContext: SideDialogController,
|
|
121
123
|
pluginActions?: React.ReactNode[],
|
|
122
124
|
openEntityMode: "side_panel" | "full_screen";
|
|
123
125
|
navigateBack: () => void;
|
|
124
|
-
formContext: FormContext
|
|
126
|
+
formContext: FormContext,
|
|
127
|
+
formex: FormexController<any>;
|
|
125
128
|
};
|
|
126
129
|
|
|
127
130
|
function buildBottomActions<M extends object>({
|
|
@@ -131,16 +134,17 @@ function buildBottomActions<M extends object>({
|
|
|
131
134
|
collection,
|
|
132
135
|
context,
|
|
133
136
|
sideEntityController,
|
|
134
|
-
isSubmitting,
|
|
135
137
|
disabled,
|
|
136
138
|
status,
|
|
137
139
|
sideDialogContext,
|
|
138
140
|
pluginActions,
|
|
139
141
|
openEntityMode,
|
|
140
142
|
navigateBack,
|
|
141
|
-
formContext
|
|
143
|
+
formContext,
|
|
144
|
+
formex
|
|
142
145
|
}: ActionsViewProps<M>) {
|
|
143
146
|
|
|
147
|
+
const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
|
|
144
148
|
const canClose = openEntityMode === "side_panel";
|
|
145
149
|
return <DialogActions
|
|
146
150
|
position={"absolute"}>
|
|
@@ -179,16 +183,20 @@ function buildBottomActions<M extends object>({
|
|
|
179
183
|
|
|
180
184
|
{pluginActions}
|
|
181
185
|
|
|
186
|
+
{hasErrors ?
|
|
187
|
+
<ErrorTooltip title={"This form has errors"}>
|
|
188
|
+
<ErrorIcon className="ml-4" color="error" size={"smallest"}/>
|
|
189
|
+
</ErrorTooltip> : null}
|
|
182
190
|
<Button variant="text"
|
|
183
191
|
color="primary"
|
|
184
|
-
disabled={disabled || isSubmitting}
|
|
192
|
+
disabled={disabled || formex.isSubmitting}
|
|
185
193
|
type="reset">
|
|
186
194
|
{status === "existing" ? "Discard" : "Clear"}
|
|
187
195
|
</Button>
|
|
188
196
|
<Button variant={canClose ? "text" : "filled"}
|
|
189
197
|
color="primary"
|
|
190
198
|
type="submit"
|
|
191
|
-
disabled={disabled || isSubmitting}
|
|
199
|
+
disabled={disabled || formex.isSubmitting}
|
|
192
200
|
onClick={() => {
|
|
193
201
|
sideDialogContext.setPendingClose(false);
|
|
194
202
|
}}>
|
|
@@ -199,7 +207,7 @@ function buildBottomActions<M extends object>({
|
|
|
199
207
|
{canClose && <LoadingButton variant="filled"
|
|
200
208
|
color="primary"
|
|
201
209
|
type="submit"
|
|
202
|
-
loading={isSubmitting}
|
|
210
|
+
loading={formex.isSubmitting}
|
|
203
211
|
disabled={disabled}
|
|
204
212
|
onClick={() => {
|
|
205
213
|
sideDialogContext.setPendingClose?.(true);
|
|
@@ -218,28 +226,35 @@ function buildSideActions<M extends object>({
|
|
|
218
226
|
collection,
|
|
219
227
|
context,
|
|
220
228
|
sideEntityController,
|
|
221
|
-
isSubmitting,
|
|
222
229
|
disabled,
|
|
223
230
|
status,
|
|
224
231
|
sideDialogContext,
|
|
225
232
|
pluginActions,
|
|
226
233
|
openEntityMode,
|
|
227
234
|
navigateBack,
|
|
228
|
-
formContext
|
|
235
|
+
formContext,
|
|
236
|
+
formex
|
|
229
237
|
}: ActionsViewProps<M>) {
|
|
230
238
|
|
|
239
|
+
const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
|
|
231
240
|
return <div
|
|
232
241
|
className={cls("overflow-auto h-full flex flex-col gap-2 w-80 2xl:w-96 px-4 py-16 sticky top-0 border-l", defaultBorderMixin)}>
|
|
233
|
-
<LoadingButton fullWidth={true}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
242
|
+
<LoadingButton fullWidth={true}
|
|
243
|
+
variant="filled"
|
|
244
|
+
color="primary"
|
|
245
|
+
type="submit"
|
|
246
|
+
size={"large"}
|
|
247
|
+
startIcon={hasErrors ? <ErrorIcon/> : undefined}
|
|
248
|
+
disabled={disabled || formex.isSubmitting}
|
|
249
|
+
onClick={() => {
|
|
250
|
+
sideDialogContext.setPendingClose?.(false);
|
|
251
|
+
}}>
|
|
237
252
|
{status === "existing" && "Save"}
|
|
238
253
|
{status === "copy" && "Create copy"}
|
|
239
254
|
{status === "new" && "Create"}
|
|
240
255
|
</LoadingButton>
|
|
241
256
|
|
|
242
|
-
<Button fullWidth={true} variant="text" disabled={disabled || isSubmitting} type="reset">
|
|
257
|
+
<Button fullWidth={true} variant="text" disabled={disabled || formex.isSubmitting} type="reset">
|
|
243
258
|
{status === "existing" ? "Discard" : "Clear"}
|
|
244
259
|
</Button>
|
|
245
260
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useMemo } from "react";
|
|
2
2
|
|
|
3
|
-
import { EntitySidePanelProps } from "../types";
|
|
3
|
+
import { EntityCollection, EntitySidePanelProps } from "../types";
|
|
4
4
|
import { useNavigationController, useSideEntityController } from "../hooks";
|
|
5
5
|
|
|
6
6
|
import { ErrorBoundary } from "../components";
|
|
@@ -8,6 +8,7 @@ import { EntityEditView, OnUpdateParams } from "./EntityEditView";
|
|
|
8
8
|
import { useSideDialogContext } from "./SideDialogs";
|
|
9
9
|
import { CloseIcon, IconButton, OpenInFullIcon } from "@firecms/ui";
|
|
10
10
|
import { useLocation, useNavigate } from "react-router-dom";
|
|
11
|
+
import { saveEntityToMemoryCache } from "../util/entity_cache";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* This is the component in charge of rendering the side dialog used
|
|
@@ -114,11 +115,14 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
114
115
|
{...props}
|
|
115
116
|
fullIdPath={fullIdPath}
|
|
116
117
|
layout={"side_panel"}
|
|
117
|
-
collection={collection}
|
|
118
|
+
collection={collection as EntityCollection}
|
|
118
119
|
parentCollectionIds={parentCollectionIds}
|
|
119
120
|
onValuesModified={onValuesModified}
|
|
120
121
|
onSaved={onUpdate}
|
|
121
|
-
barActions={
|
|
122
|
+
barActions={({
|
|
123
|
+
status,
|
|
124
|
+
values
|
|
125
|
+
}) => <>
|
|
122
126
|
<IconButton
|
|
123
127
|
className="self-center"
|
|
124
128
|
onClick={onClose}>
|
|
@@ -127,6 +131,8 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
127
131
|
{allowFullScreen && <IconButton
|
|
128
132
|
className="self-center"
|
|
129
133
|
onClick={() => {
|
|
134
|
+
const key = (status === "new" || status === "copy") ? path + "#new" : path + "/" + entityId;
|
|
135
|
+
saveEntityToMemoryCache(key, values);
|
|
130
136
|
if (entityId)
|
|
131
137
|
navigate(location.pathname);
|
|
132
138
|
else
|
package/src/core/FireCMS.tsx
CHANGED
|
@@ -20,6 +20,7 @@ import { CustomizationControllerContext } from "../contexts/CustomizationControl
|
|
|
20
20
|
import { AnalyticsContext } from "../contexts/AnalyticsContext";
|
|
21
21
|
import { useProjectLog } from "../hooks/useProjectLog";
|
|
22
22
|
import { BreadcrumbsProvider } from "../contexts/BreacrumbsContext";
|
|
23
|
+
import { InternalUserManagementContext } from "../contexts/InternalUserManagementContext";
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* If you are using independent components of the CMS
|
|
@@ -30,7 +31,6 @@ import { BreadcrumbsProvider } from "../contexts/BreacrumbsContext";
|
|
|
30
31
|
*
|
|
31
32
|
* You only need to use this component if you are building a custom app.
|
|
32
33
|
*
|
|
33
|
-
|
|
34
34
|
* @group Core
|
|
35
35
|
*/
|
|
36
36
|
export function FireCMS<USER extends User>(props: FireCMSProps<USER>) {
|
|
@@ -44,21 +44,28 @@ export function FireCMS<USER extends User>(props: FireCMSProps<USER>) {
|
|
|
44
44
|
authController,
|
|
45
45
|
storageSource,
|
|
46
46
|
dataSourceDelegate,
|
|
47
|
-
plugins:
|
|
47
|
+
plugins: _pluginsProp,
|
|
48
48
|
onAnalyticsEvent,
|
|
49
49
|
propertyConfigs,
|
|
50
50
|
entityViews,
|
|
51
51
|
entityActions,
|
|
52
52
|
components,
|
|
53
53
|
navigationController,
|
|
54
|
-
apiKey
|
|
54
|
+
apiKey,
|
|
55
|
+
userManagement: _userManagement
|
|
55
56
|
} = props;
|
|
56
57
|
|
|
57
|
-
if (
|
|
58
|
+
if (_pluginsProp) {
|
|
58
59
|
console.warn("The `plugins` prop is deprecated in the FireCMS component. You should pass your plugins to `useBuildNavigationController` instead.");
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
const plugins = navigationController.plugins ??
|
|
62
|
+
const plugins = navigationController.plugins ?? _pluginsProp;
|
|
63
|
+
const userManagement = plugins?.find(p => p.userManagement)?.userManagement
|
|
64
|
+
?? _userManagement
|
|
65
|
+
?? {
|
|
66
|
+
users: [],
|
|
67
|
+
getUser: (uid: string) => null
|
|
68
|
+
};
|
|
62
69
|
|
|
63
70
|
const sideDialogsController = useBuildSideDialogsController();
|
|
64
71
|
const sideEntityController = useBuildSideEntityController(navigationController, sideDialogsController, authController);
|
|
@@ -156,14 +163,16 @@ export function FireCMS<USER extends User>(props: FireCMSProps<USER>) {
|
|
|
156
163
|
value={sideEntityController}>
|
|
157
164
|
<NavigationContext.Provider
|
|
158
165
|
value={navigationController}>
|
|
159
|
-
<
|
|
160
|
-
<
|
|
161
|
-
<
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
166
|
+
<InternalUserManagementContext.Provider value={userManagement}>
|
|
167
|
+
<DialogsProvider>
|
|
168
|
+
<BreadcrumbsProvider>
|
|
169
|
+
<FireCMSInternal
|
|
170
|
+
loading={loading}>
|
|
171
|
+
{children}
|
|
172
|
+
</FireCMSInternal>
|
|
173
|
+
</BreadcrumbsProvider>
|
|
174
|
+
</DialogsProvider>
|
|
175
|
+
</InternalUserManagementContext.Provider>
|
|
167
176
|
</NavigationContext.Provider>
|
|
168
177
|
</SideEntityControllerContext.Provider>
|
|
169
178
|
</SideDialogsControllerContext.Provider>
|
|
@@ -32,14 +32,16 @@ import {
|
|
|
32
32
|
ListAltIcon,
|
|
33
33
|
ListIcon,
|
|
34
34
|
MailIcon,
|
|
35
|
-
NumbersIcon,
|
|
35
|
+
NumbersIcon, PersonIcon,
|
|
36
36
|
RepeatIcon,
|
|
37
37
|
ScheduleIcon,
|
|
38
38
|
ShortTextIcon,
|
|
39
39
|
SubjectIcon,
|
|
40
40
|
UploadFileIcon,
|
|
41
|
+
VerifiedUserIcon,
|
|
41
42
|
ViewStreamIcon
|
|
42
43
|
} from "@firecms/ui";
|
|
44
|
+
import { UserSelectFieldBinding } from "../form/field_bindings/UserSelectFieldBinding";
|
|
43
45
|
|
|
44
46
|
export function isDefaultFieldConfigId(id: string) {
|
|
45
47
|
return Object.keys(DEFAULT_FIELD_CONFIGS).includes(id);
|
|
@@ -143,6 +145,16 @@ export const DEFAULT_FIELD_CONFIGS: Record<string, PropertyConfig<any>> = {
|
|
|
143
145
|
Field: MultiSelectFieldBinding
|
|
144
146
|
}
|
|
145
147
|
},
|
|
148
|
+
user_select: {
|
|
149
|
+
key: "user_select",
|
|
150
|
+
name: "User select",
|
|
151
|
+
description: "Select a user from the user management system. Store the user ID.",
|
|
152
|
+
Icon: PersonIcon,
|
|
153
|
+
property: {
|
|
154
|
+
dataType: "string",
|
|
155
|
+
Field: UserSelectFieldBinding
|
|
156
|
+
}
|
|
157
|
+
},
|
|
146
158
|
number_input: {
|
|
147
159
|
key: "number_input",
|
|
148
160
|
name: "Number input",
|
|
@@ -360,6 +372,8 @@ export function getDefaultFieldId(property: Property | ResolvedProperty) {
|
|
|
360
372
|
return "email";
|
|
361
373
|
} else if (property.enumValues) {
|
|
362
374
|
return "select";
|
|
375
|
+
} else if (property.userSelect) {
|
|
376
|
+
return "user_select";
|
|
363
377
|
} else if (property.reference) {
|
|
364
378
|
return "reference_as_string";
|
|
365
379
|
} else {
|