@firecms/core 3.0.0-canary.112 → 3.0.0-canary.114
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/ArrayContainer.d.ts +2 -1
- package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +1 -1
- package/dist/components/EntityPreview.d.ts +1 -1
- package/dist/form/components/FormikArrayContainer.d.ts +2 -1
- package/dist/index.es.js +167 -117
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +166 -116
- package/dist/index.umd.js.map +1 -1
- package/dist/preview/components/ReferencePreview.d.ts +1 -1
- package/dist/types/datasource.d.ts +8 -6
- package/dist/types/entity_overrides.d.ts +2 -2
- package/dist/types/side_dialogs_controller.d.ts +10 -0
- package/dist/util/icons.d.ts +1 -0
- package/package.json +5 -5
- package/src/components/ArrayContainer.tsx +7 -4
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +13 -8
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +1 -1
- package/src/components/EntityPreview.tsx +20 -22
- package/src/components/HomePage/DefaultHomePage.tsx +7 -9
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +7 -2
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -3
- package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -1
- package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
- package/src/core/EntityEditView.tsx +20 -18
- package/src/core/SideDialogs.tsx +0 -2
- package/src/form/components/FormikArrayContainer.tsx +4 -1
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +4 -4
- package/src/form/field_bindings/BlockFieldBinding.tsx +2 -1
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +5 -4
- package/src/hooks/data/delete.ts +2 -1
- package/src/hooks/data/useDataSource.tsx +10 -2
- package/src/hooks/useBuildNavigationController.tsx +2 -4
- package/src/internal/useBuildDataSource.ts +41 -67
- package/src/internal/useBuildSideDialogsController.tsx +1 -0
- package/src/internal/useBuildSideEntityController.tsx +13 -2
- package/src/preview/components/ReferencePreview.tsx +2 -13
- package/src/types/datasource.ts +9 -6
- package/src/types/entity_overrides.tsx +2 -2
- package/src/types/side_dialogs_controller.tsx +13 -0
- package/src/util/icons.tsx +8 -2
|
@@ -14,4 +14,4 @@ export type ReferencePreviewProps = {
|
|
|
14
14
|
/**
|
|
15
15
|
* @group Preview components
|
|
16
16
|
*/
|
|
17
|
-
export declare const ReferencePreview:
|
|
17
|
+
export declare const ReferencePreview: (props: ReferencePreviewProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -54,6 +54,7 @@ export interface SaveEntityProps<M extends Record<string, any> = any> {
|
|
|
54
54
|
*/
|
|
55
55
|
export interface DeleteEntityProps<M extends Record<string, any> = any> {
|
|
56
56
|
entity: Entity<M>;
|
|
57
|
+
collection?: EntityCollection<M> | ResolvedEntityCollection<M>;
|
|
57
58
|
}
|
|
58
59
|
/**
|
|
59
60
|
* Component in charge of communicating with the data source.
|
|
@@ -122,21 +123,21 @@ export interface DataSource {
|
|
|
122
123
|
* @param entity
|
|
123
124
|
* @return was the whole deletion flow successful
|
|
124
125
|
*/
|
|
125
|
-
deleteEntity<M extends Record<string, any> = any>({ entity }: DeleteEntityProps<M>): Promise<void>;
|
|
126
|
+
deleteEntity<M extends Record<string, any> = any>({ entity, collection }: DeleteEntityProps<M>): Promise<void>;
|
|
126
127
|
/**
|
|
127
128
|
* Check if the given property is unique in the given collection
|
|
128
129
|
* @param path Collection path
|
|
129
130
|
* @param name of the property
|
|
130
131
|
* @param value
|
|
131
|
-
* @param
|
|
132
|
+
* @param collection
|
|
132
133
|
* @param entityId
|
|
133
134
|
* @return `true` if there are no other fields besides the given entity
|
|
134
135
|
*/
|
|
135
|
-
checkUniqueField(path: string, name: string, value: any, entityId?: string,
|
|
136
|
+
checkUniqueField(path: string, name: string, value: any, entityId?: string, collection?: EntityCollection): Promise<boolean>;
|
|
136
137
|
/**
|
|
137
138
|
* Generate an id for a new entity
|
|
138
139
|
*/
|
|
139
|
-
generateEntityId(path: string): string;
|
|
140
|
+
generateEntityId(path: string, collection: EntityCollection): string;
|
|
140
141
|
/**
|
|
141
142
|
* Count the number of entities in a collection
|
|
142
143
|
*/
|
|
@@ -241,13 +242,14 @@ export interface DataSourceDelegate {
|
|
|
241
242
|
* @param name of the property
|
|
242
243
|
* @param value
|
|
243
244
|
* @param entityId
|
|
245
|
+
* @param collection
|
|
244
246
|
* @return `true` if there are no other fields besides the given entity
|
|
245
247
|
*/
|
|
246
|
-
checkUniqueField(path: string, name: string, value: any, entityId?: string,
|
|
248
|
+
checkUniqueField(path: string, name: string, value: any, entityId?: string, collection?: EntityCollection): Promise<boolean>;
|
|
247
249
|
/**
|
|
248
250
|
* Generate an id for a new entity
|
|
249
251
|
*/
|
|
250
|
-
generateEntityId(path: string): string;
|
|
252
|
+
generateEntityId(path: string, collection?: EntityCollection): string;
|
|
251
253
|
/**
|
|
252
254
|
* Count the number of entities in a collection
|
|
253
255
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DataSourceDelegate } from "./datasource";
|
|
2
2
|
import { StorageSource } from "./storage";
|
|
3
3
|
export type EntityOverrides = {
|
|
4
|
-
|
|
4
|
+
dataSourceDelegate?: DataSourceDelegate;
|
|
5
5
|
storageSource?: StorageSource;
|
|
6
6
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
/**
|
|
2
3
|
* Controller to open the side dialog
|
|
3
4
|
* @group Hooks and utilities
|
|
@@ -11,6 +12,11 @@ export interface SideDialogsController {
|
|
|
11
12
|
* List of side panels currently open
|
|
12
13
|
*/
|
|
13
14
|
sidePanels: SideDialogPanelProps[];
|
|
15
|
+
/**
|
|
16
|
+
* Override the current side panels
|
|
17
|
+
* @param panels
|
|
18
|
+
*/
|
|
19
|
+
setSidePanels: (panels: SideDialogPanelProps[]) => void;
|
|
14
20
|
/**
|
|
15
21
|
* Open one or multiple side panels
|
|
16
22
|
* @param props
|
|
@@ -54,4 +60,8 @@ export interface SideDialogPanelProps {
|
|
|
54
60
|
* Callback when the panel is closed
|
|
55
61
|
*/
|
|
56
62
|
onClose?: () => void;
|
|
63
|
+
/**
|
|
64
|
+
* Use this prop to store additional data in the panel
|
|
65
|
+
*/
|
|
66
|
+
additional?: any;
|
|
57
67
|
}
|
package/dist/util/icons.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firecms/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.0.0-canary.
|
|
4
|
+
"version": "3.0.0-canary.114",
|
|
5
5
|
"description": "Awesome Firebase/Firestore-based headless open-source CMS",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/firecmsco"
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"./package.json": "./package.json"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@firecms/editor": "^3.0.0-canary.
|
|
50
|
-
"@firecms/formex": "^3.0.0-canary.
|
|
51
|
-
"@firecms/ui": "^3.0.0-canary.
|
|
49
|
+
"@firecms/editor": "^3.0.0-canary.114",
|
|
50
|
+
"@firecms/formex": "^3.0.0-canary.114",
|
|
51
|
+
"@firecms/ui": "^3.0.0-canary.114",
|
|
52
52
|
"@hello-pangea/dnd": "^16.6.0",
|
|
53
53
|
"@radix-ui/react-portal": "^1.1.1",
|
|
54
54
|
"clsx": "^2.1.1",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"dist",
|
|
101
101
|
"src"
|
|
102
102
|
],
|
|
103
|
-
"gitHead": "
|
|
103
|
+
"gitHead": "4da25dc93f9634b085b6de96ce1bed4aab935626",
|
|
104
104
|
"publishConfig": {
|
|
105
105
|
"access": "public"
|
|
106
106
|
},
|
|
@@ -27,7 +27,8 @@ interface ArrayContainerProps<T> {
|
|
|
27
27
|
onInternalIdAdded?: (id: number) => void;
|
|
28
28
|
includeAddButton?: boolean;
|
|
29
29
|
newDefaultEntry: T;
|
|
30
|
-
onValueChange: (value: T[]) => void
|
|
30
|
+
onValueChange: (value: T[]) => void,
|
|
31
|
+
className?: string;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
const buildIdsMap = (value: any[]) =>
|
|
@@ -53,7 +54,8 @@ export function ArrayContainer<T>({
|
|
|
53
54
|
onInternalIdAdded,
|
|
54
55
|
includeAddButton,
|
|
55
56
|
newDefaultEntry,
|
|
56
|
-
onValueChange
|
|
57
|
+
onValueChange,
|
|
58
|
+
className
|
|
57
59
|
}: ArrayContainerProps<T>) {
|
|
58
60
|
|
|
59
61
|
const hasValue = value && Array.isArray(value) && value.length > 0;
|
|
@@ -154,6 +156,7 @@ export function ArrayContainer<T>({
|
|
|
154
156
|
>
|
|
155
157
|
{(droppableProvided, droppableSnapshot) => (
|
|
156
158
|
<div
|
|
159
|
+
className={className}
|
|
157
160
|
{...droppableProvided.droppableProps}
|
|
158
161
|
ref={droppableProvided.innerRef}>
|
|
159
162
|
{hasValue && internalIds.map((internalId: number, index: number) => {
|
|
@@ -236,13 +239,13 @@ export function ArrayContainerItem({
|
|
|
236
239
|
{...provided.draggableProps}
|
|
237
240
|
style={provided.draggableProps.style}
|
|
238
241
|
className={`${
|
|
239
|
-
(isDragging || onHover) ?
|
|
242
|
+
(isDragging || onHover) ? "hover:bg-slate-50 dark:hover:bg-gray-800 dark:hover:bg-opacity-20" : ""
|
|
240
243
|
} mb-1 rounded-md opacity-100`}
|
|
241
244
|
>
|
|
242
245
|
<div
|
|
243
246
|
className="flex items-start">
|
|
244
247
|
<div
|
|
245
|
-
className="flex-grow w-[calc(100%-48px)] text-text-primary dark:text-text-primary-dark
|
|
248
|
+
className="flex-grow w-[calc(100%-48px)] text-text-primary dark:text-text-primary-dark">
|
|
246
249
|
{buildEntry(index, internalId)}
|
|
247
250
|
</div>
|
|
248
251
|
<ArrayItemOptions direction={size === "small" ? "row" : "column"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React, { useCallback } from "react";
|
|
2
2
|
import equal from "react-fast-compare"
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { ReferencePreview } from "../../../preview";
|
|
5
5
|
import { CollectionSize, Entity, EntityCollection, EntityReference, FilterValues } from "../../../types";
|
|
6
6
|
|
|
7
7
|
import { getPreviewSizeFrom } from "../../../preview/util";
|
|
8
|
-
import { getReferenceFrom } from "../../../util";
|
|
8
|
+
import { getReferenceFrom, IconForView } from "../../../util";
|
|
9
9
|
import { useCustomizationController, useNavigationController, useReferenceDialog } from "../../../hooks";
|
|
10
10
|
import { ErrorView } from "../../ErrorView";
|
|
11
11
|
import { cls } from "@firecms/ui";
|
|
@@ -39,11 +39,11 @@ export function TableReferenceField(props: TableReferenceFieldProps) {
|
|
|
39
39
|
throw Error(`Couldn't find the corresponding collection view for the path: ${path}`);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
return <
|
|
42
|
+
return <TableReferenceFieldInternal {...props} collection={collection}/>;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export const
|
|
46
|
-
function
|
|
45
|
+
export const TableReferenceFieldInternal = React.memo(
|
|
46
|
+
function TableReferenceFieldInternal(props: TableReferenceFieldProps & {
|
|
47
47
|
collection: EntityCollection;
|
|
48
48
|
}) {
|
|
49
49
|
const {
|
|
@@ -88,11 +88,11 @@ export const TableReferenceFieldSuccess = React.memo(
|
|
|
88
88
|
}
|
|
89
89
|
);
|
|
90
90
|
|
|
91
|
-
const handleOpen =
|
|
91
|
+
const handleOpen = () => {
|
|
92
92
|
if (disabled)
|
|
93
93
|
return;
|
|
94
94
|
referenceDialogController.open();
|
|
95
|
-
}
|
|
95
|
+
};
|
|
96
96
|
|
|
97
97
|
const valueNotSet = !internalValue || (Array.isArray(internalValue) && internalValue.length === 0);
|
|
98
98
|
|
|
@@ -151,12 +151,17 @@ export const TableReferenceFieldSuccess = React.memo(
|
|
|
151
151
|
{internalValue && multiselect && buildMultipleReferenceField()}
|
|
152
152
|
|
|
153
153
|
{valueNotSet &&
|
|
154
|
-
<EntityPreviewContainer className={cls("p-4 text-sm font-medium flex items-center
|
|
154
|
+
<EntityPreviewContainer className={cls("p-4 text-sm font-medium flex items-center uppercase",
|
|
155
|
+
multiselect ? "gap-4" : "gap-6",
|
|
155
156
|
disabled
|
|
156
157
|
? "text-slate-500"
|
|
157
158
|
: "cursor-pointer text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-gray-800 group-hover:bg-slate-50 dark:group-hover:bg-gray-800")}
|
|
158
159
|
onClick={handleOpen}
|
|
159
160
|
size={"medium"}>
|
|
161
|
+
<IconForView
|
|
162
|
+
size={"small"}
|
|
163
|
+
collectionOrView={collection}
|
|
164
|
+
className={"text-gray-300 dark:text-gray-600"}/>
|
|
160
165
|
Edit {title}
|
|
161
166
|
</EntityPreviewContainer>}
|
|
162
167
|
|
|
@@ -306,7 +306,7 @@ export const EntityCollectionView = React.memo(
|
|
|
306
306
|
value,
|
|
307
307
|
property,
|
|
308
308
|
entityId
|
|
309
|
-
}) => dataSource.checkUniqueField(fullPath, name, value, entityId, collection
|
|
309
|
+
}) => dataSource.checkUniqueField(fullPath, name, value, entityId, collection),
|
|
310
310
|
[fullPath]);
|
|
311
311
|
|
|
312
312
|
const onValueChange: OnCellValueChange<any, any> = ({
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
getEntityPreviewKeys,
|
|
9
9
|
getEntityTitlePropertyKey,
|
|
10
10
|
getValueInPath,
|
|
11
|
+
IconForView,
|
|
11
12
|
resolveCollection
|
|
12
13
|
} from "../util";
|
|
13
14
|
import { cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Skeleton, Tooltip, Typography } from "@firecms/ui";
|
|
@@ -76,14 +77,14 @@ export function EntityPreview({
|
|
|
76
77
|
return <EntityPreviewContainer onClick={disabled ? undefined : onClick}
|
|
77
78
|
hover={disabled ? undefined : hover}
|
|
78
79
|
size={size}>
|
|
79
|
-
{
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
<div className={cls("w-10 h-10 mr-2 shrink-0 grow-0", size === "smallest" ? "my-0.5" : "m-2 self-start")}>
|
|
81
|
+
{imageProperty && <PropertyPreview property={imageProperty}
|
|
82
|
+
propertyKey={imagePropertyKey as string}
|
|
83
|
+
size={"smallest"}
|
|
84
|
+
value={getValueInPath(entity.values, imagePropertyKey as string)}/>}
|
|
85
|
+
{!imageProperty && <IconForView collectionOrView={collection} size={size} className={"mr-2"}/>}
|
|
86
|
+
</div>
|
|
87
|
+
|
|
87
88
|
|
|
88
89
|
<div className={"flex flex-col flex-grow w-full m-1"}>
|
|
89
90
|
|
|
@@ -180,16 +181,17 @@ export type EntityPreviewContainerProps = {
|
|
|
180
181
|
onClick?: (e: React.SyntheticEvent) => void;
|
|
181
182
|
};
|
|
182
183
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
184
|
+
|
|
185
|
+
export const EntityPreviewContainer = React.forwardRef<HTMLDivElement, EntityPreviewContainerProps>(({
|
|
186
|
+
children,
|
|
187
|
+
hover,
|
|
188
|
+
onClick,
|
|
189
|
+
size,
|
|
190
|
+
style,
|
|
191
|
+
className,
|
|
192
|
+
fullwidth = true,
|
|
193
|
+
...props
|
|
194
|
+
}, ref) => {
|
|
193
195
|
return <div
|
|
194
196
|
ref={ref}
|
|
195
197
|
style={{
|
|
@@ -218,7 +220,3 @@ const EntityPreviewContainerInner = React.forwardRef<HTMLDivElement, EntityPrevi
|
|
|
218
220
|
{children}
|
|
219
221
|
</div>;
|
|
220
222
|
});
|
|
221
|
-
|
|
222
|
-
EntityPreviewContainerInner.displayName = "EntityPreviewContainer";
|
|
223
|
-
|
|
224
|
-
export const EntityPreviewContainer = React.memo(EntityPreviewContainerInner) as React.FC<EntityPreviewContainerProps>;
|
|
@@ -64,18 +64,15 @@ export function DefaultHomePage({
|
|
|
64
64
|
} = navigationController.topLevelNavigation;
|
|
65
65
|
|
|
66
66
|
const [filteredUrls, setFilteredUrls] = useState<string[] | null>(null);
|
|
67
|
+
const performingSearch = Boolean(filteredUrls);
|
|
67
68
|
|
|
68
69
|
const filteredNavigationEntries = filteredUrls
|
|
69
|
-
?
|
|
70
|
+
? filteredUrls.map(url => navigationEntries.find(e => e.url === url)).filter(Boolean) as TopNavigationEntry[]
|
|
70
71
|
: navigationEntries;
|
|
71
72
|
|
|
72
73
|
useEffect(() => {
|
|
73
74
|
fuse.current = new Fuse(navigationEntries, {
|
|
74
|
-
keys: ["name",
|
|
75
|
-
"description",
|
|
76
|
-
"group",
|
|
77
|
-
"path"
|
|
78
|
-
]
|
|
75
|
+
keys: ["name", "description", "group", "path"]
|
|
79
76
|
});
|
|
80
77
|
}, [navigationEntries]);
|
|
81
78
|
|
|
@@ -92,7 +89,8 @@ export function DefaultHomePage({
|
|
|
92
89
|
}
|
|
93
90
|
}, []);
|
|
94
91
|
|
|
95
|
-
const
|
|
92
|
+
const filteredGroups = filteredUrls ? filteredNavigationEntries.map(entry => entry.group) : [];
|
|
93
|
+
const allGroups: Array<string | undefined> = filteredUrls ? filteredGroups.filter((group, index) => filteredGroups.indexOf(group) === index) : [...groups];
|
|
96
94
|
if (filteredNavigationEntries.filter(e => !e.group).length > 0 || filteredNavigationEntries.length === 0) {
|
|
97
95
|
allGroups.push(undefined);
|
|
98
96
|
}
|
|
@@ -148,7 +146,7 @@ export function DefaultHomePage({
|
|
|
148
146
|
{additionalActions}
|
|
149
147
|
</div>
|
|
150
148
|
|
|
151
|
-
<FavouritesView hidden={
|
|
149
|
+
<FavouritesView hidden={performingSearch}/>
|
|
152
150
|
|
|
153
151
|
{additionalChildrenStart}
|
|
154
152
|
|
|
@@ -172,7 +170,7 @@ export function DefaultHomePage({
|
|
|
172
170
|
|
|
173
171
|
const thisGroupCollections = filteredNavigationEntries
|
|
174
172
|
.filter((entry) => entry.group === group || (!entry.group && group === undefined));
|
|
175
|
-
if (thisGroupCollections.length === 0 && AdditionalCards.length === 0)
|
|
173
|
+
if (thisGroupCollections.length === 0 && (AdditionalCards.length === 0 || performingSearch))
|
|
176
174
|
return null;
|
|
177
175
|
return (
|
|
178
176
|
<NavigationGroup
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "../../hooks";
|
|
17
17
|
import { ErrorView } from "../ErrorView";
|
|
18
18
|
import { AddIcon, Button, DialogActions, Typography } from "@firecms/ui";
|
|
19
|
-
import { canCreateEntity, resolveCollection } from "../../util";
|
|
19
|
+
import { canCreateEntity, IconForView, resolveCollection } from "../../util";
|
|
20
20
|
import { useSelectionController } from "../EntityCollectionView/useSelectionController";
|
|
21
21
|
import { useColumnIds, useTableSearchHelper } from "../common";
|
|
22
22
|
import { useSideDialogContext } from "../../core";
|
|
@@ -109,6 +109,7 @@ export function ReferenceSelectionTable<M extends Record<string, any>>(
|
|
|
109
109
|
|
|
110
110
|
const fullPath = navigation.resolveAliasesFrom(pathInput);
|
|
111
111
|
|
|
112
|
+
console.trace("Opening reference dialog for path " + fullPath);
|
|
112
113
|
const dataSource = useDataSource(collection);
|
|
113
114
|
|
|
114
115
|
const [entitiesDisplayedFirst, setEntitiesDisplayedFirst] = useState<Entity<any>[]>([]);
|
|
@@ -289,7 +290,11 @@ export function ReferenceSelectionTable<M extends Record<string, any>>(
|
|
|
289
290
|
tableController={tableController}
|
|
290
291
|
enablePopupIcon={false}
|
|
291
292
|
tableRowActionsBuilder={tableRowActionsBuilder}
|
|
292
|
-
title={<Typography variant={"subtitle2"}>
|
|
293
|
+
title={<Typography variant={"subtitle2"} className={"flex flex-row gap-2"}>
|
|
294
|
+
<IconForView
|
|
295
|
+
size={"small"}
|
|
296
|
+
collectionOrView={collection}
|
|
297
|
+
className={"text-gray-300 dark:text-gray-600"}/>
|
|
293
298
|
{collection.singularName ? `Select ${collection.singularName}` : `Select from ${collection.name}`}
|
|
294
299
|
</Typography>}
|
|
295
300
|
defaultSize={collection.defaultSize}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { DateTimeField } from "@firecms/ui";
|
|
2
|
+
import { cls, DateTimeField, focusedDisabled } from "@firecms/ui";
|
|
3
3
|
import { useCustomizationController } from "../../../hooks";
|
|
4
4
|
|
|
5
5
|
export function VirtualTableDateField(props: {
|
|
@@ -28,8 +28,8 @@ export function VirtualTableDateField(props: {
|
|
|
28
28
|
onChange={(dateValue) => updateValue(dateValue ?? null)}
|
|
29
29
|
size={"medium"}
|
|
30
30
|
invisible={true}
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
inputClassName={cls("w-full h-full", focusedDisabled)}
|
|
32
|
+
className={cls("w-full h-full", focusedDisabled)}
|
|
33
33
|
mode={mode}
|
|
34
34
|
locale={locale}
|
|
35
35
|
/>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { useDebouncedCallback } from "../../../util";
|
|
4
|
-
import { TextareaAutosize } from "@firecms/ui";
|
|
4
|
+
import { focusedDisabled, TextareaAutosize } from "@firecms/ui";
|
|
5
5
|
|
|
6
6
|
export function VirtualTableInput(props: {
|
|
7
7
|
error: Error | undefined;
|
|
@@ -58,6 +58,7 @@ export function VirtualTableInput(props: {
|
|
|
58
58
|
|
|
59
59
|
return (
|
|
60
60
|
<TextareaAutosize
|
|
61
|
+
className={focusedDisabled}
|
|
61
62
|
ref={ref}
|
|
62
63
|
style={{
|
|
63
64
|
padding: 0,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from "react";
|
|
2
2
|
import { useDebouncedCallback } from "../../../util";
|
|
3
|
+
import { cls, focusedDisabled } from "@firecms/ui";
|
|
3
4
|
|
|
4
5
|
export function VirtualTableNumberInput(props: {
|
|
5
6
|
error: Error | undefined;
|
|
@@ -65,7 +66,7 @@ export function VirtualTableNumberInput(props: {
|
|
|
65
66
|
return (
|
|
66
67
|
<input
|
|
67
68
|
ref={ref}
|
|
68
|
-
className="w-full text-right p-0 m-0 bg-transparent border-none resize-none outline-none font-normal leading-normal text-unset"
|
|
69
|
+
className={cls("w-full text-right p-0 m-0 bg-transparent border-none resize-none outline-none font-normal leading-normal text-unset", focusedDisabled)}
|
|
69
70
|
style={{
|
|
70
71
|
textAlign: align
|
|
71
72
|
}}
|
|
@@ -199,7 +199,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
199
199
|
if (mustSetCustomId) {
|
|
200
200
|
return undefined;
|
|
201
201
|
} else {
|
|
202
|
-
return dataSource.generateEntityId(path);
|
|
202
|
+
return dataSource.generateEntityId(path, collection);
|
|
203
203
|
}
|
|
204
204
|
} else {
|
|
205
205
|
return entityIdProp;
|
|
@@ -231,9 +231,9 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
231
231
|
}
|
|
232
232
|
);
|
|
233
233
|
|
|
234
|
-
const
|
|
234
|
+
const [selectedTab, setSelectedTab] = useState<string>(defaultSelectedView ?? MAIN_TAB_VALUE);
|
|
235
235
|
|
|
236
|
-
const mainViewVisible =
|
|
236
|
+
const mainViewVisible = selectedTab === MAIN_TAB_VALUE;
|
|
237
237
|
|
|
238
238
|
const subcollections = (collection.subcollections ?? []).filter(c => !c.hideFromNavigation);
|
|
239
239
|
const subcollectionsCount = subcollections?.length ?? 0;
|
|
@@ -307,7 +307,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
307
307
|
sideEntityController.replace({
|
|
308
308
|
path,
|
|
309
309
|
entityId: updatedEntity.id,
|
|
310
|
-
selectedSubPath: MAIN_TAB_VALUE ===
|
|
310
|
+
selectedSubPath: MAIN_TAB_VALUE === selectedTab ? undefined : selectedTab,
|
|
311
311
|
updateUrl: true,
|
|
312
312
|
collection,
|
|
313
313
|
});
|
|
@@ -491,15 +491,15 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
491
491
|
.filter(Boolean) as EntityCustomView[]
|
|
492
492
|
: [];
|
|
493
493
|
|
|
494
|
-
const selectedEntityView = resolvedEntityViews.find(e => e.key ===
|
|
495
|
-
const shouldShowEntityActions = !autoSave && (
|
|
494
|
+
const selectedEntityView = resolvedEntityViews.find(e => e.key === selectedTab);
|
|
495
|
+
const shouldShowEntityActions = !autoSave && (selectedTab === MAIN_TAB_VALUE || selectedEntityView?.includeActions);
|
|
496
496
|
|
|
497
497
|
const customViewsView: React.ReactNode[] | undefined = customViews && resolvedEntityViews
|
|
498
498
|
.map(
|
|
499
499
|
(customView, colIndex) => {
|
|
500
500
|
if (!customView)
|
|
501
501
|
return null;
|
|
502
|
-
if (
|
|
502
|
+
if (selectedTab !== customView.key)
|
|
503
503
|
return null;
|
|
504
504
|
const Builder = customView.Builder;
|
|
505
505
|
if (!Builder) {
|
|
@@ -532,7 +532,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
532
532
|
(subcollection, colIndex) => {
|
|
533
533
|
const subcollectionId = subcollection.id ?? subcollection.path;
|
|
534
534
|
const fullPath = usedEntity ? `${path}/${usedEntity?.id}/${removeInitialAndTrailingSlashes(subcollectionId)}` : undefined;
|
|
535
|
-
if (
|
|
535
|
+
if (selectedTab !== subcollectionId)
|
|
536
536
|
return null;
|
|
537
537
|
return (
|
|
538
538
|
<div
|
|
@@ -568,14 +568,16 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
568
568
|
}, []);
|
|
569
569
|
|
|
570
570
|
const onSideTabClick = (value: string) => {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
571
|
+
setSelectedTab(value);
|
|
572
|
+
if (status === "existing") {
|
|
573
|
+
sideEntityController.replace({
|
|
574
|
+
path,
|
|
575
|
+
entityId,
|
|
576
|
+
selectedSubPath: value === MAIN_TAB_VALUE ? undefined : value,
|
|
577
|
+
updateUrl: true,
|
|
578
|
+
collection,
|
|
579
|
+
});
|
|
580
|
+
}
|
|
579
581
|
};
|
|
580
582
|
|
|
581
583
|
const onIdUpdateError = useCallback((error: any) => {
|
|
@@ -675,7 +677,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
675
677
|
name,
|
|
676
678
|
value,
|
|
677
679
|
property
|
|
678
|
-
}) => dataSource.checkUniqueField(path, name, value, entityId, collection
|
|
680
|
+
}) => dataSource.checkUniqueField(path, name, value, entityId, collection),
|
|
679
681
|
[dataSource, path, entityId]);
|
|
680
682
|
|
|
681
683
|
const validationSchema = useMemo(() => entityId
|
|
@@ -1027,7 +1029,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
1027
1029
|
</div>}
|
|
1028
1030
|
|
|
1029
1031
|
<Tabs
|
|
1030
|
-
value={
|
|
1032
|
+
value={selectedTab}
|
|
1031
1033
|
onValueChange={(value) => {
|
|
1032
1034
|
onSideTabClick(value);
|
|
1033
1035
|
}}
|
package/src/core/SideDialogs.tsx
CHANGED
|
@@ -104,11 +104,9 @@ function SideDialogView({
|
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
const onCloseRequest = (force?: boolean) => {
|
|
107
|
-
console.log("onCloseRequest", blocked, force);
|
|
108
107
|
if (blocked && !force) {
|
|
109
108
|
setDrawerCloseRequested(true);
|
|
110
109
|
} else {
|
|
111
|
-
console.log("onCloseRequest closing");
|
|
112
110
|
sideDialogsController.close();
|
|
113
111
|
panel?.onClose?.();
|
|
114
112
|
}
|
|
@@ -12,6 +12,7 @@ interface ArrayContainerProps<T> {
|
|
|
12
12
|
includeAddButton?: boolean;
|
|
13
13
|
newDefaultEntry?: T | null;
|
|
14
14
|
setFieldValue: (field: string, value: any, shouldValidate?: boolean | undefined) => void;
|
|
15
|
+
className?: string;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -27,7 +28,8 @@ export function FormikArrayContainer<T>({
|
|
|
27
28
|
onInternalIdAdded,
|
|
28
29
|
includeAddButton,
|
|
29
30
|
newDefaultEntry = null,
|
|
30
|
-
setFieldValue
|
|
31
|
+
setFieldValue,
|
|
32
|
+
className
|
|
31
33
|
}: ArrayContainerProps<T>) {
|
|
32
34
|
|
|
33
35
|
return <ArrayContainer droppableId={name}
|
|
@@ -39,6 +41,7 @@ export function FormikArrayContainer<T>({
|
|
|
39
41
|
onInternalIdAdded={onInternalIdAdded}
|
|
40
42
|
includeAddButton={includeAddButton}
|
|
41
43
|
newDefaultEntry={newDefaultEntry}
|
|
44
|
+
className={className}
|
|
42
45
|
onValueChange={(value) => setFieldValue(name, value)}
|
|
43
46
|
/>;
|
|
44
47
|
}
|
|
@@ -70,10 +70,10 @@ export function ArrayOfReferencesFieldBinding({
|
|
|
70
70
|
}
|
|
71
71
|
);
|
|
72
72
|
|
|
73
|
-
const onEntryClick =
|
|
73
|
+
const onEntryClick = (e: React.SyntheticEvent) => {
|
|
74
74
|
e.preventDefault();
|
|
75
75
|
referenceDialogController.open();
|
|
76
|
-
}
|
|
76
|
+
};
|
|
77
77
|
|
|
78
78
|
const buildEntry = useCallback((index: number, internalId: number) => {
|
|
79
79
|
const entryValue = value && value.length > index ? value[index] : undefined;
|
|
@@ -100,7 +100,7 @@ export function ArrayOfReferencesFieldBinding({
|
|
|
100
100
|
icon={getIconForProperty(property, "small")}
|
|
101
101
|
required={property.validation?.required}
|
|
102
102
|
title={property.name}
|
|
103
|
-
className={"flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
|
|
103
|
+
className={"flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
|
|
104
104
|
{Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
|
|
105
105
|
</>);
|
|
106
106
|
|
|
@@ -120,7 +120,7 @@ export function ArrayOfReferencesFieldBinding({
|
|
|
120
120
|
|
|
121
121
|
<Button
|
|
122
122
|
className="my-4 justify-center text-left"
|
|
123
|
-
variant="
|
|
123
|
+
variant="text"
|
|
124
124
|
color="primary"
|
|
125
125
|
disabled={isSubmitting}
|
|
126
126
|
onClick={onEntryClick}>
|
|
@@ -71,6 +71,7 @@ export function BlockFieldBinding<T extends Array<any>>({
|
|
|
71
71
|
|
|
72
72
|
const firstOneOfKey = Object.keys(property.oneOf.properties)[0];
|
|
73
73
|
const body = <FormikArrayContainer value={value}
|
|
74
|
+
className={"flex flex-col gap-3"}
|
|
74
75
|
name={propertyKey}
|
|
75
76
|
addLabel={property.name ? "Add entry to " + property.name : "Add entry"}
|
|
76
77
|
buildEntry={buildEntry}
|
|
@@ -194,7 +195,7 @@ function BlockEntry({
|
|
|
194
195
|
};
|
|
195
196
|
|
|
196
197
|
return (
|
|
197
|
-
<div className={cls(paperMixin, "bg-transparent p-2
|
|
198
|
+
<div className={cls(paperMixin, "bg-transparent p-2")}>
|
|
198
199
|
|
|
199
200
|
<Field
|
|
200
201
|
name={typeFieldName}
|