@firecms/core 3.0.0-canary.102 → 3.0.0-canary.104
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/internal/popup_field/PopupFormField.d.ts +1 -1
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +9 -0
- package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +1 -1
- package/dist/form/index.d.ts +2 -2
- package/dist/index.es.js +269 -817
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +268 -815
- package/dist/index.umd.js.map +1 -1
- package/dist/types/collections.d.ts +11 -1
- package/dist/types/datasource.d.ts +12 -12
- package/dist/types/entities.d.ts +1 -0
- package/dist/types/fields.d.ts +5 -13
- package/dist/types/navigation.d.ts +1 -0
- package/dist/util/index.d.ts +1 -0
- package/dist/util/storage.d.ts +1 -1
- package/package.json +5 -5
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +4 -2
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +4 -4
- package/src/components/common/useTableSearchHelper.ts +1 -0
- package/src/core/DefaultDrawer.tsx +1 -1
- package/src/core/EntityEditView.tsx +3 -4
- package/src/core/field_configs.tsx +2 -2
- package/src/form/PropertyFieldBinding.tsx +4 -8
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +4 -5
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +3 -3
- package/src/form/field_bindings/BlockFieldBinding.tsx +5 -6
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +5 -5
- package/src/form/field_bindings/MapFieldBinding.tsx +6 -8
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +133 -0
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +5 -5
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +5 -4
- package/src/form/field_bindings/RepeatFieldBinding.tsx +6 -7
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +2 -2
- package/src/form/index.tsx +2 -2
- package/src/hooks/data/save.ts +5 -1
- package/src/internal/useBuildDataSource.ts +29 -14
- package/src/preview/PropertyPreview.tsx +2 -2
- package/src/types/collections.ts +13 -1
- package/src/types/datasource.ts +13 -16
- package/src/types/entities.ts +2 -0
- package/src/types/fields.tsx +5 -15
- package/src/types/navigation.ts +1 -0
- package/src/util/index.ts +1 -0
- package/src/util/references.ts +3 -0
- package/src/util/storage.ts +1 -1
- package/src/util/useStorageUploadController.tsx +2 -2
- package/dist/form/PropertiesForm.d.ts +0 -8
- package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
- package/src/form/PropertiesForm.tsx +0 -81
- package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FieldHelperText,
|
|
3
|
+
FieldProps,
|
|
4
|
+
getIconForProperty,
|
|
5
|
+
LabelWithIcon,
|
|
6
|
+
randomString,
|
|
7
|
+
useStorageSource
|
|
8
|
+
} from "../../index";
|
|
9
|
+
import { Paper } from "@firecms/ui";
|
|
10
|
+
import { FireCMSEditor } from "@firecms/editor";
|
|
11
|
+
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
12
|
+
import { resolveStorageFilenameString, resolveStoragePathString } from "../../util/storage";
|
|
13
|
+
|
|
14
|
+
interface MarkdownEditorFieldProps {
|
|
15
|
+
highlight?: { from: number, to: number };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function MarkdownEditorFieldBinding({
|
|
19
|
+
property,
|
|
20
|
+
propertyKey,
|
|
21
|
+
value,
|
|
22
|
+
setValue,
|
|
23
|
+
includeDescription,
|
|
24
|
+
showError,
|
|
25
|
+
error,
|
|
26
|
+
minimalistView,
|
|
27
|
+
isSubmitting,
|
|
28
|
+
context,
|
|
29
|
+
customProps,
|
|
30
|
+
...props
|
|
31
|
+
}: FieldProps<string, MarkdownEditorFieldProps>) {
|
|
32
|
+
|
|
33
|
+
const highlight = customProps?.highlight;
|
|
34
|
+
const storageSource = useStorageSource();
|
|
35
|
+
const storage = property.storage;
|
|
36
|
+
|
|
37
|
+
const entityValues = context.values;
|
|
38
|
+
const entityId = context.entityId;
|
|
39
|
+
const path = context.path;
|
|
40
|
+
|
|
41
|
+
// const fieldVersion = useRef(0);
|
|
42
|
+
const [fieldVersion, setFieldVersion] = useState(0);
|
|
43
|
+
const internalValue = useRef(value);
|
|
44
|
+
|
|
45
|
+
const onContentChange = useCallback((content: string) => {
|
|
46
|
+
internalValue.current = content;
|
|
47
|
+
setValue(content);
|
|
48
|
+
}, [setValue]);
|
|
49
|
+
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (internalValue.current !== value) {
|
|
52
|
+
internalValue.current = value;
|
|
53
|
+
setFieldVersion(fieldVersion + 1);
|
|
54
|
+
// fieldVersion.current = fieldVersion.current + 1;
|
|
55
|
+
}
|
|
56
|
+
}, [value]);
|
|
57
|
+
|
|
58
|
+
const fileNameBuilder = useCallback(async (file: File) => {
|
|
59
|
+
if (storage?.fileName) {
|
|
60
|
+
const fileName = await resolveStorageFilenameString({
|
|
61
|
+
input: storage.fileName,
|
|
62
|
+
storage,
|
|
63
|
+
values: entityValues,
|
|
64
|
+
entityId,
|
|
65
|
+
path,
|
|
66
|
+
property,
|
|
67
|
+
file,
|
|
68
|
+
propertyKey
|
|
69
|
+
});
|
|
70
|
+
if (!fileName || fileName.length === 0) {
|
|
71
|
+
throw Error("You need to return a valid filename");
|
|
72
|
+
}
|
|
73
|
+
return fileName;
|
|
74
|
+
}
|
|
75
|
+
return randomString() + "_" + file.name;
|
|
76
|
+
}, [entityId, entityValues, path, property, propertyKey, storage]);
|
|
77
|
+
|
|
78
|
+
const storagePathBuilder = useCallback((file: File) => {
|
|
79
|
+
if (!storage) return "/";
|
|
80
|
+
return resolveStoragePathString({
|
|
81
|
+
input: storage.storagePath,
|
|
82
|
+
storage,
|
|
83
|
+
values: entityValues,
|
|
84
|
+
entityId,
|
|
85
|
+
path,
|
|
86
|
+
property,
|
|
87
|
+
file,
|
|
88
|
+
propertyKey
|
|
89
|
+
}) ?? "/";
|
|
90
|
+
}, [entityId, entityValues, path, property, propertyKey, storage]);
|
|
91
|
+
|
|
92
|
+
const editor = <FireCMSEditor
|
|
93
|
+
content={value}
|
|
94
|
+
onMarkdownContentChange={onContentChange}
|
|
95
|
+
version={context.formex.version + fieldVersion}
|
|
96
|
+
highlight={highlight}
|
|
97
|
+
handleImageUpload={async (file: File) => {
|
|
98
|
+
const storagePath = storagePathBuilder(file);
|
|
99
|
+
const fileName = await fileNameBuilder(file);
|
|
100
|
+
const result = await storageSource.uploadFile({
|
|
101
|
+
file,
|
|
102
|
+
fileName,
|
|
103
|
+
path: storagePath,
|
|
104
|
+
});
|
|
105
|
+
const downloadConfig = await storageSource.getDownloadURL(result.path);
|
|
106
|
+
const url = downloadConfig.url;
|
|
107
|
+
if (!url) {
|
|
108
|
+
throw new Error("Error uploading image");
|
|
109
|
+
}
|
|
110
|
+
return url;
|
|
111
|
+
}}/>;
|
|
112
|
+
|
|
113
|
+
if (minimalistView)
|
|
114
|
+
return editor;
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<>
|
|
118
|
+
<LabelWithIcon icon={getIconForProperty(property, "small")}
|
|
119
|
+
required={property.validation?.required}
|
|
120
|
+
title={property.name}
|
|
121
|
+
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
122
|
+
<Paper>
|
|
123
|
+
{editor}
|
|
124
|
+
</Paper>
|
|
125
|
+
<FieldHelperText includeDescription={includeDescription}
|
|
126
|
+
showError={showError}
|
|
127
|
+
error={error}
|
|
128
|
+
property={property}/>
|
|
129
|
+
</>
|
|
130
|
+
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
}
|
|
@@ -21,7 +21,7 @@ export function ReadOnlyFieldBinding({
|
|
|
21
21
|
value,
|
|
22
22
|
error,
|
|
23
23
|
showError,
|
|
24
|
-
|
|
24
|
+
minimalistView,
|
|
25
25
|
property,
|
|
26
26
|
includeDescription,
|
|
27
27
|
context
|
|
@@ -34,10 +34,10 @@ export function ReadOnlyFieldBinding({
|
|
|
34
34
|
|
|
35
35
|
<>
|
|
36
36
|
|
|
37
|
-
{!
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
{!minimalistView && <LabelWithIcon icon={getIconForProperty(property, "small")}
|
|
38
|
+
required={property.validation?.required}
|
|
39
|
+
title={property.name}
|
|
40
|
+
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
<div
|
|
@@ -34,6 +34,7 @@ function ReferenceFieldBindingInternal({
|
|
|
34
34
|
showError,
|
|
35
35
|
isSubmitting,
|
|
36
36
|
disabled,
|
|
37
|
+
minimalistView,
|
|
37
38
|
touched,
|
|
38
39
|
autoFocus,
|
|
39
40
|
property,
|
|
@@ -82,10 +83,10 @@ function ReferenceFieldBindingInternal({
|
|
|
82
83
|
|
|
83
84
|
return (
|
|
84
85
|
<>
|
|
85
|
-
<LabelWithIcon icon={getIconForProperty(property, "small")}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
{!minimalistView && <LabelWithIcon icon={getIconForProperty(property, "small")}
|
|
87
|
+
required={property.validation?.required}
|
|
88
|
+
title={property.name}
|
|
89
|
+
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
|
|
89
90
|
|
|
90
91
|
{!collection && <ErrorView
|
|
91
92
|
error={"The specified collection does not exist. Check console"}/>}
|
|
@@ -23,7 +23,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
|
|
|
23
23
|
isSubmitting,
|
|
24
24
|
setValue,
|
|
25
25
|
setFieldValue,
|
|
26
|
-
|
|
26
|
+
minimalistView,
|
|
27
27
|
property,
|
|
28
28
|
includeDescription,
|
|
29
29
|
underlyingValueHasChanged,
|
|
@@ -57,9 +57,8 @@ export function RepeatFieldBinding<T extends Array<any>>({
|
|
|
57
57
|
includeDescription,
|
|
58
58
|
underlyingValueHasChanged,
|
|
59
59
|
context,
|
|
60
|
-
tableMode: false,
|
|
61
60
|
partOfArray: true,
|
|
62
|
-
|
|
61
|
+
minimalistView: false,
|
|
63
62
|
autoFocus: internalId === lastAddedId
|
|
64
63
|
};
|
|
65
64
|
return <ErrorBoundary>
|
|
@@ -89,13 +88,13 @@ export function RepeatFieldBinding<T extends Array<any>>({
|
|
|
89
88
|
|
|
90
89
|
<>
|
|
91
90
|
|
|
92
|
-
{!
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
{!minimalistView && <ExpandablePanel initiallyExpanded={expanded}
|
|
92
|
+
className={"px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2"}
|
|
93
|
+
title={title}>
|
|
95
94
|
{arrayContainer}
|
|
96
95
|
</ExpandablePanel>}
|
|
97
96
|
|
|
98
|
-
{
|
|
97
|
+
{minimalistView && arrayContainer}
|
|
99
98
|
|
|
100
99
|
<FieldHelperText includeDescription={includeDescription}
|
|
101
100
|
showError={showError}
|
|
@@ -44,7 +44,7 @@ export function StorageUploadFieldBinding({
|
|
|
44
44
|
error,
|
|
45
45
|
showError,
|
|
46
46
|
autoFocus,
|
|
47
|
-
|
|
47
|
+
minimalistView,
|
|
48
48
|
property,
|
|
49
49
|
includeDescription,
|
|
50
50
|
context,
|
|
@@ -87,7 +87,7 @@ export function StorageUploadFieldBinding({
|
|
|
87
87
|
|
|
88
88
|
<>
|
|
89
89
|
|
|
90
|
-
{!
|
|
90
|
+
{!minimalistView &&
|
|
91
91
|
<LabelWithIcon icon={getIconForProperty(property, "small")}
|
|
92
92
|
required={property.validation?.required}
|
|
93
93
|
title={property.name}
|
package/src/form/index.tsx
CHANGED
|
@@ -11,7 +11,7 @@ import { KeyValueFieldBinding } from "./field_bindings/KeyValueFieldBinding";
|
|
|
11
11
|
import { RepeatFieldBinding } from "./field_bindings/RepeatFieldBinding";
|
|
12
12
|
import { BlockFieldBinding } from "./field_bindings/BlockFieldBinding";
|
|
13
13
|
import { ReadOnlyFieldBinding } from "./field_bindings/ReadOnlyFieldBinding";
|
|
14
|
-
import {
|
|
14
|
+
import { MarkdownEditorFieldBinding } from "./field_bindings/MarkdownEditorFieldBinding";
|
|
15
15
|
import { ArrayCustomShapedFieldBinding } from "./field_bindings/ArrayCustomShapedFieldBinding";
|
|
16
16
|
|
|
17
17
|
export {
|
|
@@ -28,7 +28,7 @@ export {
|
|
|
28
28
|
SelectFieldBinding,
|
|
29
29
|
StorageUploadFieldBinding,
|
|
30
30
|
SwitchFieldBinding,
|
|
31
|
-
|
|
31
|
+
MarkdownEditorFieldBinding,
|
|
32
32
|
TextFieldBinding
|
|
33
33
|
};
|
|
34
34
|
|
package/src/hooks/data/save.ts
CHANGED
|
@@ -108,7 +108,11 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
|
|
|
108
108
|
updatedValues = values;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
console.log("Saving entity",
|
|
111
|
+
console.log("Saving entity", {
|
|
112
|
+
entityId,
|
|
113
|
+
updatedValues,
|
|
114
|
+
collection
|
|
115
|
+
});
|
|
112
116
|
return dataSource.saveEntity({
|
|
113
117
|
collection,
|
|
114
118
|
path: resolvedPath,
|
|
@@ -52,13 +52,13 @@ export function useBuildDataSource({
|
|
|
52
52
|
*/
|
|
53
53
|
fetchCollection: useCallback(<M extends Record<string, any>>({
|
|
54
54
|
path,
|
|
55
|
-
collection
|
|
55
|
+
collection,
|
|
56
56
|
filter,
|
|
57
57
|
limit,
|
|
58
58
|
startAfter,
|
|
59
59
|
searchString,
|
|
60
60
|
orderBy,
|
|
61
|
-
order
|
|
61
|
+
order,
|
|
62
62
|
}: FetchCollectionProps<M>
|
|
63
63
|
): Promise<Entity<M>[]> => {
|
|
64
64
|
return delegate.fetchCollection<M>({
|
|
@@ -68,7 +68,8 @@ export function useBuildDataSource({
|
|
|
68
68
|
startAfter,
|
|
69
69
|
searchString,
|
|
70
70
|
orderBy,
|
|
71
|
-
order
|
|
71
|
+
order,
|
|
72
|
+
collection
|
|
72
73
|
});
|
|
73
74
|
}, [delegate]),
|
|
74
75
|
|
|
@@ -89,7 +90,6 @@ export function useBuildDataSource({
|
|
|
89
90
|
* @group Firestore
|
|
90
91
|
*/
|
|
91
92
|
listenCollection: delegate.listenCollection
|
|
92
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
93
93
|
? useCallback(<M extends Record<string, any>>(
|
|
94
94
|
{
|
|
95
95
|
path,
|
|
@@ -106,7 +106,7 @@ export function useBuildDataSource({
|
|
|
106
106
|
): () => void => {
|
|
107
107
|
|
|
108
108
|
const collection = collectionProp ?? navigationController.getCollection(path);
|
|
109
|
-
const isCollectionGroup = Boolean(collection?.collectionGroup)
|
|
109
|
+
const isCollectionGroup = Boolean(collection?.collectionGroup);
|
|
110
110
|
if (!delegate.listenCollection)
|
|
111
111
|
throw Error("useBuildDataSource delegate not initialised");
|
|
112
112
|
|
|
@@ -120,8 +120,7 @@ export function useBuildDataSource({
|
|
|
120
120
|
order,
|
|
121
121
|
onUpdate,
|
|
122
122
|
onError,
|
|
123
|
-
|
|
124
|
-
collection
|
|
123
|
+
collection,
|
|
125
124
|
});
|
|
126
125
|
}, [delegate, navigationController.getCollection])
|
|
127
126
|
: undefined,
|
|
@@ -135,11 +134,13 @@ export function useBuildDataSource({
|
|
|
135
134
|
*/
|
|
136
135
|
fetchEntity: useCallback(<M extends Record<string, any>>({
|
|
137
136
|
path,
|
|
138
|
-
entityId
|
|
137
|
+
entityId,
|
|
138
|
+
collection
|
|
139
139
|
}: FetchEntityProps<M>
|
|
140
140
|
): Promise<Entity<M> | undefined> => delegate.fetchEntity({
|
|
141
141
|
path,
|
|
142
|
-
entityId
|
|
142
|
+
entityId,
|
|
143
|
+
collection
|
|
143
144
|
}), [delegate]),
|
|
144
145
|
|
|
145
146
|
/**
|
|
@@ -153,7 +154,6 @@ export function useBuildDataSource({
|
|
|
153
154
|
* @group Firestore
|
|
154
155
|
*/
|
|
155
156
|
listenEntity: delegate.listenEntity
|
|
156
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
157
157
|
? useCallback(<M extends Record<string, any>>(
|
|
158
158
|
{
|
|
159
159
|
path,
|
|
@@ -169,7 +169,8 @@ export function useBuildDataSource({
|
|
|
169
169
|
path,
|
|
170
170
|
entityId,
|
|
171
171
|
onUpdate,
|
|
172
|
-
onError
|
|
172
|
+
onError,
|
|
173
|
+
collection
|
|
173
174
|
})
|
|
174
175
|
}, [delegate.listenEntity]) : undefined,
|
|
175
176
|
|
|
@@ -195,6 +196,15 @@ export function useBuildDataSource({
|
|
|
195
196
|
|
|
196
197
|
const collection = collectionProp ?? navigationController.getCollection(path);
|
|
197
198
|
|
|
199
|
+
console.log("useBuildDatasource save", {
|
|
200
|
+
path,
|
|
201
|
+
entityId,
|
|
202
|
+
values,
|
|
203
|
+
collectionProp,
|
|
204
|
+
collection,
|
|
205
|
+
status
|
|
206
|
+
});
|
|
207
|
+
|
|
198
208
|
const resolvedCollection = collection
|
|
199
209
|
? resolveCollection<M>({
|
|
200
210
|
collection,
|
|
@@ -223,6 +233,7 @@ export function useBuildDataSource({
|
|
|
223
233
|
|
|
224
234
|
return delegate.saveEntity({
|
|
225
235
|
path,
|
|
236
|
+
collection,
|
|
226
237
|
entityId,
|
|
227
238
|
values: updatedFirestoreValues,
|
|
228
239
|
status
|
|
@@ -263,9 +274,10 @@ export function useBuildDataSource({
|
|
|
263
274
|
path: string,
|
|
264
275
|
name: string,
|
|
265
276
|
value: any,
|
|
266
|
-
entityId?: string
|
|
277
|
+
entityId?: string,
|
|
278
|
+
databaseId?: string
|
|
267
279
|
): Promise<boolean> => {
|
|
268
|
-
return delegate.checkUniqueField(path, name, value, entityId);
|
|
280
|
+
return delegate.checkUniqueField(path, name, value, entityId, databaseId);
|
|
269
281
|
}, [delegate.checkUniqueField]),
|
|
270
282
|
|
|
271
283
|
generateEntityId: useCallback((path: string): string => {
|
|
@@ -290,16 +302,18 @@ export function useBuildDataSource({
|
|
|
290
302
|
filter,
|
|
291
303
|
orderBy,
|
|
292
304
|
order,
|
|
293
|
-
|
|
305
|
+
collection
|
|
294
306
|
});
|
|
295
307
|
} : undefined,
|
|
296
308
|
|
|
297
309
|
isFilterCombinationValid: useCallback(({
|
|
298
310
|
path,
|
|
311
|
+
databaseId,
|
|
299
312
|
filterValues,
|
|
300
313
|
sortBy
|
|
301
314
|
}: {
|
|
302
315
|
path: string,
|
|
316
|
+
databaseId?: string,
|
|
303
317
|
filterValues: FilterValues<any>,
|
|
304
318
|
sortBy?: [string, "asc" | "desc"]
|
|
305
319
|
}): boolean => {
|
|
@@ -308,6 +322,7 @@ export function useBuildDataSource({
|
|
|
308
322
|
return delegate.isFilterCombinationValid(
|
|
309
323
|
{
|
|
310
324
|
path,
|
|
325
|
+
databaseId,
|
|
311
326
|
filterValues,
|
|
312
327
|
sortBy
|
|
313
328
|
}
|
|
@@ -86,6 +86,8 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
|
|
|
86
86
|
url={value}
|
|
87
87
|
interactive={interactive}
|
|
88
88
|
previewType={stringProperty.url}/>;
|
|
89
|
+
} else if (stringProperty.markdown) {
|
|
90
|
+
content = <Markdown source={value} size={"small"}/>;
|
|
89
91
|
} else if (stringProperty.storage) {
|
|
90
92
|
const filePath = stringProperty.storage.previewUrl ? stringProperty.storage.previewUrl(value) : value;
|
|
91
93
|
content = <StorageThumbnail
|
|
@@ -93,8 +95,6 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
|
|
|
93
95
|
storeUrl={property.storage?.storeUrl ?? false}
|
|
94
96
|
size={props.size}
|
|
95
97
|
storagePathOrDownloadUrl={filePath}/>;
|
|
96
|
-
} else if (stringProperty.markdown) {
|
|
97
|
-
content = <Markdown source={value} size={"small"}/>;
|
|
98
98
|
} else {
|
|
99
99
|
content = <StringPropertyPreview {...props}
|
|
100
100
|
property={stringProperty}
|
package/src/types/collections.ts
CHANGED
|
@@ -51,6 +51,12 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
|
|
|
51
51
|
*/
|
|
52
52
|
path: string;
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Optional database id of this collection. If not specified, the default
|
|
56
|
+
* database id will be used.
|
|
57
|
+
*/
|
|
58
|
+
databaseId?: string;
|
|
59
|
+
|
|
54
60
|
/**
|
|
55
61
|
* If this collection is a top level navigation entry, you can set this
|
|
56
62
|
* property to `true` to indicate that this collection is a collection group.
|
|
@@ -61,7 +67,8 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
|
|
|
61
67
|
* Icon key to use in this collection.
|
|
62
68
|
* You can use any of the icons in the Material specs:
|
|
63
69
|
* https://fonts.google.com/icons
|
|
64
|
-
* e.g. 'account_tree' or 'person'
|
|
70
|
+
* e.g. 'account_tree' or 'person'.
|
|
71
|
+
* Find all the icons in https://firecms.co/docs/icons
|
|
65
72
|
*/
|
|
66
73
|
icon?: string;
|
|
67
74
|
|
|
@@ -304,6 +311,11 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
|
|
|
304
311
|
* Width of the side dialog (in pixels) when opening an entity in this collection.
|
|
305
312
|
*/
|
|
306
313
|
sideDialogWidth?: number | string;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Default preview properties displayed when this collection is referenced to.
|
|
317
|
+
*/
|
|
318
|
+
previewProperties?: string[];
|
|
307
319
|
}
|
|
308
320
|
|
|
309
321
|
/**
|
package/src/types/datasource.ts
CHANGED
|
@@ -18,6 +18,7 @@ export interface FetchEntityProps<M extends Record<string, any> = any> {
|
|
|
18
18
|
export type ListenEntityProps<M extends Record<string, any> = any> =
|
|
19
19
|
FetchEntityProps<M>
|
|
20
20
|
& {
|
|
21
|
+
databaseId?: string;
|
|
21
22
|
onUpdate: (entity: Entity<M>) => void,
|
|
22
23
|
onError?: (error: Error) => void,
|
|
23
24
|
}
|
|
@@ -198,7 +199,8 @@ export interface DataSource {
|
|
|
198
199
|
path: string,
|
|
199
200
|
name: string,
|
|
200
201
|
value: any,
|
|
201
|
-
entityId?: string
|
|
202
|
+
entityId?: string,
|
|
203
|
+
databaseId?: string
|
|
202
204
|
): Promise<boolean>;
|
|
203
205
|
|
|
204
206
|
/**
|
|
@@ -238,19 +240,11 @@ export type FilterCombinationValidProps = {
|
|
|
238
240
|
sortBy?: [string, "asc" | "desc"];
|
|
239
241
|
};
|
|
240
242
|
|
|
241
|
-
export type SaveEntityDelegateProps<M extends Record<string, any> = any> =
|
|
243
|
+
export type SaveEntityDelegateProps<M extends Record<string, any> = any> = SaveEntityProps<M>;
|
|
242
244
|
|
|
243
|
-
export type FetchCollectionDelegateProps<M extends Record<string, any> = any> =
|
|
244
|
-
Omit<FetchCollectionProps<M>, "collection">
|
|
245
|
-
& {
|
|
246
|
-
isCollectionGroup?: boolean
|
|
247
|
-
};
|
|
245
|
+
export type FetchCollectionDelegateProps<M extends Record<string, any> = any> = FetchCollectionProps<M>;
|
|
248
246
|
|
|
249
|
-
export type ListenCollectionDelegateProps<M extends Record<string, any> = any> =
|
|
250
|
-
ListenCollectionProps<M>
|
|
251
|
-
& {
|
|
252
|
-
isCollectionGroup?: boolean;
|
|
253
|
-
};
|
|
247
|
+
export type ListenCollectionDelegateProps<M extends Record<string, any> = any> = ListenCollectionProps<M>;
|
|
254
248
|
|
|
255
249
|
export interface DataSourceDelegate {
|
|
256
250
|
|
|
@@ -321,7 +315,7 @@ export interface DataSourceDelegate {
|
|
|
321
315
|
fetchEntity<M extends Record<string, any> = any>({
|
|
322
316
|
path,
|
|
323
317
|
entityId,
|
|
324
|
-
}:
|
|
318
|
+
}: FetchEntityProps<M>): Promise<Entity<M> | undefined>;
|
|
325
319
|
|
|
326
320
|
/**
|
|
327
321
|
* Get realtime updates on one entity.
|
|
@@ -337,7 +331,7 @@ export interface DataSourceDelegate {
|
|
|
337
331
|
entityId,
|
|
338
332
|
onUpdate,
|
|
339
333
|
onError
|
|
340
|
-
}:
|
|
334
|
+
}: ListenEntityProps<M>): () => void;
|
|
341
335
|
|
|
342
336
|
/**
|
|
343
337
|
* Save entity to the specified path
|
|
@@ -368,7 +362,7 @@ export interface DataSourceDelegate {
|
|
|
368
362
|
* @param entityId
|
|
369
363
|
* @return `true` if there are no other fields besides the given entity
|
|
370
364
|
*/
|
|
371
|
-
checkUniqueField(path: string, name: string, value: any, entityId?: string): Promise<boolean>;
|
|
365
|
+
checkUniqueField(path: string, name: string, value: any, entityId?: string, databaseId?: string): Promise<boolean>;
|
|
372
366
|
|
|
373
367
|
/**
|
|
374
368
|
* Generate an id for a new entity
|
|
@@ -384,7 +378,9 @@ export interface DataSourceDelegate {
|
|
|
384
378
|
* Check if the given filter combination is valid
|
|
385
379
|
* @param props
|
|
386
380
|
*/
|
|
387
|
-
isFilterCombinationValid?(props: Omit<FilterCombinationValidProps, "collection">
|
|
381
|
+
isFilterCombinationValid?(props: Omit<FilterCombinationValidProps, "collection"> & {
|
|
382
|
+
databaseId?: string
|
|
383
|
+
}): boolean;
|
|
388
384
|
|
|
389
385
|
/**
|
|
390
386
|
* Get the object to generate the current time in the datasource
|
|
@@ -400,6 +396,7 @@ export interface DataSourceDelegate {
|
|
|
400
396
|
initTextSearch?: (props: {
|
|
401
397
|
context: FireCMSContext,
|
|
402
398
|
path: string,
|
|
399
|
+
databaseId?: string,
|
|
403
400
|
collection: EntityCollection,
|
|
404
401
|
parentCollectionIds?: string[]
|
|
405
402
|
}) => Promise<boolean>;
|
package/src/types/entities.ts
CHANGED
package/src/types/fields.tsx
CHANGED
|
@@ -81,14 +81,9 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
|
|
|
81
81
|
partOfArray?: boolean;
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
*
|
|
85
|
-
*/
|
|
86
|
-
partOfBlock?: boolean;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Is this field being rendered in the entity table popup
|
|
84
|
+
* Should this field render with the minimal amount of UI elements
|
|
90
85
|
*/
|
|
91
|
-
|
|
86
|
+
minimalistView?: boolean;
|
|
92
87
|
|
|
93
88
|
/**
|
|
94
89
|
* Should this field autofocus on mount
|
|
@@ -98,7 +93,7 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
|
|
|
98
93
|
/**
|
|
99
94
|
* Additional properties set by the developer
|
|
100
95
|
*/
|
|
101
|
-
customProps
|
|
96
|
+
customProps: CustomProps
|
|
102
97
|
|
|
103
98
|
/**
|
|
104
99
|
* Additional values related to the state of the form or the entity
|
|
@@ -144,7 +139,7 @@ export interface FormContext<M extends Record<string, any> = any> {
|
|
|
144
139
|
/**
|
|
145
140
|
* Entity id, it can be null if it's a new entity
|
|
146
141
|
*/
|
|
147
|
-
entityId
|
|
142
|
+
entityId: string;
|
|
148
143
|
|
|
149
144
|
/**
|
|
150
145
|
* Path this entity is located at
|
|
@@ -192,11 +187,6 @@ export interface PropertyFieldBindingProps<T extends CMSType, M extends Record<s
|
|
|
192
187
|
*/
|
|
193
188
|
underlyingValueHasChanged?: boolean;
|
|
194
189
|
|
|
195
|
-
/**
|
|
196
|
-
* Is this field being rendered in a table
|
|
197
|
-
*/
|
|
198
|
-
tableMode?: boolean;
|
|
199
|
-
|
|
200
190
|
/**
|
|
201
191
|
* Is this field part of an array
|
|
202
192
|
*/
|
|
@@ -205,7 +195,7 @@ export interface PropertyFieldBindingProps<T extends CMSType, M extends Record<s
|
|
|
205
195
|
/**
|
|
206
196
|
* Is this field part of a block (oneOf array)
|
|
207
197
|
*/
|
|
208
|
-
|
|
198
|
+
minimalistView?: boolean;
|
|
209
199
|
|
|
210
200
|
/**
|
|
211
201
|
* Should the field take focus when rendered. When opening the popup view
|
package/src/types/navigation.ts
CHANGED
package/src/util/index.ts
CHANGED
package/src/util/references.ts
CHANGED
|
@@ -9,6 +9,9 @@ export function getEntityPreviewKeys(targetCollection: EntityCollection<any>,
|
|
|
9
9
|
limit = 3) {
|
|
10
10
|
const allProperties = Object.keys(targetCollection.properties);
|
|
11
11
|
let listProperties = previewProperties?.filter(p => allProperties.includes(p as string));
|
|
12
|
+
if (!listProperties && targetCollection.previewProperties) {
|
|
13
|
+
listProperties = targetCollection.previewProperties?.filter(p => allProperties.includes(p as string));
|
|
14
|
+
}
|
|
12
15
|
if (listProperties && listProperties.length > 0) {
|
|
13
16
|
return listProperties;
|
|
14
17
|
} else {
|
package/src/util/storage.ts
CHANGED