@firecms/core 3.0.0-tw4.6 → 3.0.1
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/README.md +1 -1
- package/dist/components/VirtualTable/VirtualTable.performance.test.d.ts +1 -0
- package/dist/form/components/LocalChangesMenu.d.ts +2 -2
- package/dist/form/components/StorageUploadProgress.d.ts +1 -1
- package/dist/index.es.js +218 -238
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +218 -238
- package/dist/index.umd.js.map +1 -1
- package/dist/types/entities.d.ts +1 -0
- package/dist/types/properties.d.ts +9 -0
- package/dist/types/storage.d.ts +8 -0
- package/dist/util/useStorageUploadController.d.ts +1 -1
- package/package.json +6 -5
- package/src/app/Scaffold.tsx +1 -1
- package/src/components/ArrayContainer.tsx +1 -1
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +3 -3
- package/src/components/EntityPreview.tsx +1 -1
- package/src/components/ReferenceWidget.tsx +1 -1
- package/src/components/SelectableTable/SelectableTable.tsx +1 -1
- package/src/components/VirtualTable/VirtualTable.performance.test.tsx +386 -0
- package/src/components/VirtualTable/VirtualTable.tsx +3 -3
- package/src/components/VirtualTable/VirtualTableHeader.tsx +1 -1
- package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
- package/src/core/DefaultDrawer.tsx +1 -1
- package/src/core/DrawerNavigationItem.tsx +3 -4
- package/src/form/EntityForm.tsx +3 -10
- package/src/form/components/LocalChangesMenu.tsx +6 -6
- package/src/form/components/StorageUploadProgress.tsx +4 -3
- package/src/preview/components/EmptyValue.tsx +1 -1
- package/src/preview/components/ReferencePreview.tsx +6 -1
- package/src/types/entities.ts +10 -0
- package/src/types/properties.ts +10 -0
- package/src/types/storage.ts +9 -0
- package/src/util/useStorageUploadController.tsx +11 -1
package/src/form/EntityForm.tsx
CHANGED
|
@@ -328,14 +328,7 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
328
328
|
return [initialValues, initialDirty];
|
|
329
329
|
}, [autoApplyLocalChanges, localChangesDataRaw, baseInitialValues, initialDirtyValues]);
|
|
330
330
|
|
|
331
|
-
const
|
|
332
|
-
if (!localChangesDataRaw) {
|
|
333
|
-
return undefined;
|
|
334
|
-
}
|
|
335
|
-
return getChanges(localChangesDataRaw, initialValues);
|
|
336
|
-
}, [localChangesDataRaw, initialValues]);
|
|
337
|
-
|
|
338
|
-
const hasLocalChanges = !localChangesCleared && localChangesData && Object.keys(localChangesData).length > 0;
|
|
331
|
+
const hasLocalChanges = !localChangesCleared && localChangesDataRaw && Object.keys(localChangesDataRaw).length > 0;
|
|
339
332
|
|
|
340
333
|
const formex: FormexController<M> = formexProp ?? useCreateFormex<M>({
|
|
341
334
|
initialValues: initialValues as M,
|
|
@@ -851,7 +844,7 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
851
844
|
<LocalChangesMenu
|
|
852
845
|
cacheKey={status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId}
|
|
853
846
|
properties={resolvedCollection.properties}
|
|
854
|
-
|
|
847
|
+
cachedData={localChangesDataRaw as Partial<M>}
|
|
855
848
|
formex={formex}
|
|
856
849
|
onClearLocalChanges={() => setLocalChangesCleared(true)}
|
|
857
850
|
/>}
|
|
@@ -863,7 +856,7 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
863
856
|
</Chip>
|
|
864
857
|
</Tooltip>
|
|
865
858
|
: <Tooltip title={"The current form is in sync with the database"}>
|
|
866
|
-
<Chip size={"small"} className={"py-1"}
|
|
859
|
+
<Chip size={"small"} className={"py-1"}>
|
|
867
860
|
<CheckIcon size={"smallest"}/>
|
|
868
861
|
</Chip>
|
|
869
862
|
</Tooltip>}
|
|
@@ -24,14 +24,14 @@ import { PropertyCollectionView } from "../../components/PropertyCollectionView"
|
|
|
24
24
|
|
|
25
25
|
interface LocalChangesMenuProps<M extends object> {
|
|
26
26
|
cacheKey: string;
|
|
27
|
-
|
|
27
|
+
cachedData: Partial<M>;
|
|
28
28
|
formex: FormexController<M>;
|
|
29
29
|
onClearLocalChanges?: () => void;
|
|
30
30
|
properties: ResolvedProperties<M>;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export function LocalChangesMenu<M extends object>({
|
|
34
|
-
|
|
34
|
+
cachedData,
|
|
35
35
|
formex,
|
|
36
36
|
onClearLocalChanges,
|
|
37
37
|
cacheKey,
|
|
@@ -51,10 +51,10 @@ export function LocalChangesMenu<M extends object>({
|
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
const handleApply = () => {
|
|
54
|
-
const mergedValues = mergeDeep(formex.values,
|
|
54
|
+
const mergedValues = mergeDeep(formex.values, cachedData);
|
|
55
55
|
const touched = { ...formex.touched };
|
|
56
|
-
const
|
|
57
|
-
|
|
56
|
+
const cachedKeys = flattenKeys(cachedData);
|
|
57
|
+
cachedKeys.forEach((key) => {
|
|
58
58
|
touched[key] = true;
|
|
59
59
|
});
|
|
60
60
|
|
|
@@ -121,7 +121,7 @@ export function LocalChangesMenu<M extends object>({
|
|
|
121
121
|
overflow: "auto"
|
|
122
122
|
}}>
|
|
123
123
|
<div className="p-4">
|
|
124
|
-
<PropertyCollectionView data={
|
|
124
|
+
<PropertyCollectionView data={cachedData}
|
|
125
125
|
properties={properties as ResolvedProperties}/>
|
|
126
126
|
</div>
|
|
127
127
|
</div>
|
|
@@ -11,7 +11,8 @@ export interface StorageUploadItemProps {
|
|
|
11
11
|
entry: StorageFieldItem,
|
|
12
12
|
onFileUploadComplete: (value: string,
|
|
13
13
|
entry: StorageFieldItem,
|
|
14
|
-
metadata?: any
|
|
14
|
+
metadata?: any,
|
|
15
|
+
uploadedUrl?: string) => Promise<void>;
|
|
15
16
|
imageSize: number;
|
|
16
17
|
simple: boolean;
|
|
17
18
|
}
|
|
@@ -47,9 +48,9 @@ export function StorageUploadProgress({
|
|
|
47
48
|
path: storagePath,
|
|
48
49
|
metadata
|
|
49
50
|
})
|
|
50
|
-
.then(async ({ path }) => {
|
|
51
|
+
.then(async ({ path, storageUrl }) => {
|
|
51
52
|
console.debug("Upload successful", path);
|
|
52
|
-
await onFileUploadComplete(path, entry, metadata);
|
|
53
|
+
await onFileUploadComplete(path, entry, metadata, storageUrl);
|
|
53
54
|
if (mounted.current)
|
|
54
55
|
setLoading(false);
|
|
55
56
|
})
|
|
@@ -6,5 +6,5 @@ import React from "react";
|
|
|
6
6
|
export function EmptyValue() {
|
|
7
7
|
|
|
8
8
|
return <div
|
|
9
|
-
className="rounded-full bg-surface-200 bg-opacity-30
|
|
9
|
+
className="rounded-full bg-surface-200 bg-opacity-30 dark:bg-opacity-20 w-5 h-2 inline-block"/>;
|
|
10
10
|
}
|
|
@@ -57,7 +57,12 @@ function ReferencePreviewInternal({
|
|
|
57
57
|
if (customizationController.components?.missingReference) {
|
|
58
58
|
return <customizationController.components.missingReference path={reference.path}/>;
|
|
59
59
|
} else {
|
|
60
|
-
|
|
60
|
+
return <EntityPreviewContainer
|
|
61
|
+
onClick={onClick}
|
|
62
|
+
size={size ?? "medium"}>
|
|
63
|
+
<ErrorView error={"Unexpected reference value. Click to edit"}
|
|
64
|
+
tooltip={reference.pathWithId}/>
|
|
65
|
+
</EntityPreviewContainer>;
|
|
61
66
|
}
|
|
62
67
|
}
|
|
63
68
|
|
package/src/types/entities.ts
CHANGED
|
@@ -65,6 +65,16 @@ export class EntityReference {
|
|
|
65
65
|
return `${this.path}/${this.id}`;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
get pathWithIdAndDatabase() {
|
|
69
|
+
if (this.databaseId) {
|
|
70
|
+
if (this.databaseId === "(default)") {
|
|
71
|
+
return this.pathWithId;
|
|
72
|
+
}
|
|
73
|
+
return `${this.databaseId}:::${this.path}/${this.id}`;
|
|
74
|
+
}
|
|
75
|
+
return this.pathWithId;
|
|
76
|
+
}
|
|
77
|
+
|
|
68
78
|
isEntityReference() {
|
|
69
79
|
return true;
|
|
70
80
|
}
|
package/src/types/properties.ts
CHANGED
|
@@ -828,6 +828,16 @@ export type StorageConfig = {
|
|
|
828
828
|
*/
|
|
829
829
|
storagePath: string | ((context: UploadedFileContext) => string);
|
|
830
830
|
|
|
831
|
+
/**
|
|
832
|
+
* When set to true, this flag indicates that the bucket name will be
|
|
833
|
+
* included in the saved storage path.
|
|
834
|
+
*
|
|
835
|
+
* E.g. `gs://my-bucket/path/to/file.png` instead of just `path/to/file.png`
|
|
836
|
+
*
|
|
837
|
+
* Defaults to false.
|
|
838
|
+
*/
|
|
839
|
+
includeBucketUrl?: boolean;
|
|
840
|
+
|
|
831
841
|
/**
|
|
832
842
|
* When set to true, this flag indicates that the download URL of the file
|
|
833
843
|
* will be saved in the datasource, instead of the storage path.
|
package/src/types/storage.ts
CHANGED
|
@@ -21,6 +21,15 @@ export interface UploadFileResult {
|
|
|
21
21
|
* Bucket where the file was uploaded
|
|
22
22
|
*/
|
|
23
23
|
bucket: string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Fully qualified storage URL for the uploaded file.
|
|
27
|
+
*
|
|
28
|
+
* For example: `gs://my-bucket/path/to/file.png`.
|
|
29
|
+
*
|
|
30
|
+
* This is optional for backwards compatibility.
|
|
31
|
+
*/
|
|
32
|
+
storageUrl?: string;
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
/**
|
|
@@ -134,11 +134,21 @@ export function useStorageUploadController<M extends object>({
|
|
|
134
134
|
|
|
135
135
|
const onFileUploadComplete = useCallback(async (uploadedPath: string,
|
|
136
136
|
entry: StorageFieldItem,
|
|
137
|
-
metadata?: any
|
|
137
|
+
metadata?: any,
|
|
138
|
+
uploadedUrl?: string) => {
|
|
138
139
|
|
|
139
140
|
console.debug("onFileUploadComplete", uploadedPath, entry);
|
|
140
141
|
|
|
141
142
|
let uploadPathOrDownloadUrl: string | null = uploadedPath;
|
|
143
|
+
|
|
144
|
+
if (storage.includeBucketUrl) {
|
|
145
|
+
if (!uploadedUrl) {
|
|
146
|
+
console.warn("includeBucketUrl is set but no fully-qualified storage URL was returned by the StorageSource. Falling back to the storage path.");
|
|
147
|
+
} else {
|
|
148
|
+
uploadPathOrDownloadUrl = uploadedUrl;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
142
152
|
if (storage.storeUrl) {
|
|
143
153
|
uploadPathOrDownloadUrl = (await storageSource.getDownloadURL(uploadedPath)).url;
|
|
144
154
|
}
|