@firecms/core 3.0.0-beta.7 → 3.0.0-beta.8
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/app/AppBar.d.ts +12 -0
- package/dist/app/Drawer.d.ts +17 -0
- package/dist/app/Scaffold.d.ts +30 -0
- package/dist/app/index.d.ts +4 -0
- package/dist/app/useApp.d.ts +16 -0
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +4 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +2 -7
- package/dist/core/DefaultDrawer.d.ts +19 -0
- package/dist/core/EntityEditView.d.ts +17 -3
- package/dist/core/NavigationRoutes.d.ts +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/form/PropertiesForm.d.ts +8 -0
- package/dist/form/components/FieldHelperText.d.ts +3 -3
- package/dist/form/components/StorageItemPreview.d.ts +4 -4
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +2 -4
- package/dist/form/index.d.ts +0 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +5595 -5574
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +5 -5
- package/dist/index.umd.js.map +1 -1
- package/dist/preview/PropertyPreviewProps.d.ts +5 -0
- package/dist/preview/components/StorageThumbnail.d.ts +2 -1
- package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
- package/dist/types/auth.d.ts +1 -1
- package/dist/types/collections.d.ts +14 -0
- package/dist/types/datasource.d.ts +18 -8
- package/dist/types/fields.d.ts +31 -30
- package/dist/types/plugins.d.ts +11 -3
- package/dist/types/properties.d.ts +7 -2
- package/dist/util/icons.d.ts +2 -2
- package/dist/util/storage.d.ts +23 -2
- package/dist/util/useStorageUploadController.d.ts +1 -1
- package/package.json +13 -22
- package/src/app/AppBar.tsx +18 -0
- package/src/app/Drawer.tsx +25 -0
- package/src/{core → app}/Scaffold.tsx +61 -107
- package/src/app/index.ts +4 -0
- package/src/app/useApp.tsx +32 -0
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +7 -9
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -1
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +7 -4
- package/src/components/VirtualTable/VirtualTable.tsx +3 -1
- package/src/components/VirtualTable/VirtualTableProps.tsx +5 -0
- package/src/components/common/useTableSearchHelper.ts +52 -12
- package/src/components/index.tsx +1 -1
- package/src/contexts/DialogsProvider.tsx +2 -2
- package/src/{components/FireCMSAppBar.tsx → core/DefaultAppBar.tsx} +26 -28
- package/src/core/DefaultDrawer.tsx +177 -0
- package/src/core/EntityEditView.tsx +669 -129
- package/src/core/EntitySidePanel.tsx +0 -1
- package/src/core/NavigationRoutes.tsx +3 -3
- package/src/core/index.tsx +2 -2
- package/src/form/PropertiesForm.tsx +81 -0
- package/src/form/PropertyFieldBinding.tsx +29 -5
- package/src/form/components/FieldHelperText.tsx +3 -3
- package/src/form/components/StorageItemPreview.tsx +19 -10
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +8 -5
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +5 -4
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +40 -35
- package/src/form/field_bindings/MapFieldBinding.tsx +11 -3
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +0 -7
- package/src/form/field_bindings/RepeatFieldBinding.tsx +10 -7
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +6 -35
- package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -1
- package/src/form/index.tsx +4 -4
- package/src/form/validation.ts +1 -17
- package/src/index.ts +1 -0
- package/src/internal/useBuildDataSource.ts +12 -0
- package/src/preview/PropertyPreview.tsx +5 -2
- package/src/preview/PropertyPreviewProps.tsx +6 -0
- package/src/preview/components/ImagePreview.tsx +21 -33
- package/src/preview/components/ReferencePreview.tsx +2 -1
- package/src/preview/components/StorageThumbnail.tsx +5 -1
- package/src/preview/components/UrlComponentPreview.tsx +44 -11
- package/src/types/auth.tsx +1 -1
- package/src/types/collections.ts +14 -0
- package/src/types/customization_controller.tsx +0 -1
- package/src/types/datasource.ts +20 -16
- package/src/types/fields.tsx +33 -33
- package/src/types/plugins.tsx +12 -3
- package/src/types/properties.ts +7 -2
- package/src/util/entities.ts +4 -3
- package/src/util/objects.ts +17 -7
- package/src/util/permissions.ts +1 -0
- package/src/util/storage.ts +75 -21
- package/src/util/useStorageUploadController.tsx +21 -3
- package/dist/core/Drawer.d.ts +0 -16
- package/dist/core/Scaffold.d.ts +0 -51
- package/dist/form/EntityForm.d.ts +0 -77
- package/src/core/Drawer.tsx +0 -139
- package/src/form/EntityForm.tsx +0 -736
|
@@ -1,55 +1,16 @@
|
|
|
1
1
|
import React, { PropsWithChildren, useCallback } from "react";
|
|
2
|
-
import equal from "react-fast-compare"
|
|
3
|
-
import { Link } from "react-router-dom";
|
|
4
|
-
|
|
5
|
-
import { Drawer as DefaultDrawer, DrawerProps } from "./Drawer";
|
|
6
|
-
import { useLargeLayout, useNavigationController } from "../hooks";
|
|
7
|
-
import { ErrorBoundary, FireCMSAppBar as DefaultFireCMSAppBar, FireCMSAppBarProps, FireCMSLogo } from "../components";
|
|
8
2
|
import { ChevronLeftIcon, cls, defaultBorderMixin, IconButton, MenuIcon, Sheet, Tooltip } from "@firecms/ui";
|
|
3
|
+
import equal from "react-fast-compare"
|
|
4
|
+
import { useLargeLayout } from "../hooks";
|
|
5
|
+
import { ErrorBoundary } from "../components";
|
|
6
|
+
import { AppContext } from "./useApp";
|
|
9
7
|
|
|
10
8
|
export const DRAWER_WIDTH = 280;
|
|
11
9
|
|
|
12
|
-
const DrawerContext = React.createContext<DrawerProps>({
|
|
13
|
-
hovered: false,
|
|
14
|
-
drawerOpen: false,
|
|
15
|
-
openDrawer: () => {
|
|
16
|
-
throw new Error("openDrawer not implemented");
|
|
17
|
-
},
|
|
18
|
-
closeDrawer: () => {
|
|
19
|
-
throw new Error("closeDrawer not implemented");
|
|
20
|
-
},
|
|
21
|
-
autoOpenDrawer: false
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
export function useDrawer() {
|
|
25
|
-
return React.useContext(DrawerContext);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
10
|
/**
|
|
29
11
|
* @group Core
|
|
30
12
|
*/
|
|
31
|
-
export interface ScaffoldProps
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Name of the app, displayed as the main title and in the tab title
|
|
35
|
-
*/
|
|
36
|
-
name?: React.ReactNode;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Logo to be displayed in the drawer of the CMS
|
|
40
|
-
*/
|
|
41
|
-
logo?: string;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Whether to include the drawer in the scaffold
|
|
45
|
-
*/
|
|
46
|
-
includeDrawer?: boolean;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* You can define a custom drawer to be displayed in the scaffold.
|
|
50
|
-
* Use the hook `useDrawer` to access the context values.
|
|
51
|
-
*/
|
|
52
|
-
drawer?: React.ReactNode;
|
|
13
|
+
export interface ScaffoldProps {
|
|
53
14
|
|
|
54
15
|
/**
|
|
55
16
|
* Open the drawer on hover
|
|
@@ -57,15 +18,14 @@ export interface ScaffoldProps<ExtraAppbarProps = object> {
|
|
|
57
18
|
autoOpenDrawer?: boolean;
|
|
58
19
|
|
|
59
20
|
/**
|
|
60
|
-
*
|
|
21
|
+
* Logo to be displayed in the top bar and drawer.
|
|
22
|
+
* Note that this has no effect if you are using a custom AppBar or Drawer.
|
|
61
23
|
*/
|
|
62
|
-
|
|
24
|
+
logo?: string;
|
|
63
25
|
|
|
64
|
-
|
|
65
|
-
* Additional props passed to the custom AppBar
|
|
66
|
-
*/
|
|
67
|
-
fireCMSAppBarProps?: Partial<FireCMSAppBarProps> & ExtraAppbarProps;
|
|
26
|
+
className?: string;
|
|
68
27
|
|
|
28
|
+
style?: React.CSSProperties;
|
|
69
29
|
}
|
|
70
30
|
|
|
71
31
|
/**
|
|
@@ -84,15 +44,23 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
|
|
|
84
44
|
|
|
85
45
|
const {
|
|
86
46
|
children,
|
|
87
|
-
name,
|
|
88
|
-
logo,
|
|
89
|
-
includeDrawer = true,
|
|
90
47
|
autoOpenDrawer,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
48
|
+
logo,
|
|
49
|
+
className,
|
|
50
|
+
style
|
|
94
51
|
} = props;
|
|
95
52
|
|
|
53
|
+
const drawerChildren = React.Children.toArray(children).filter((child: any) => child.type.componentType === "Drawer");
|
|
54
|
+
if (drawerChildren.length > 1) {
|
|
55
|
+
throw Error("Only one Drawer component is allowed in Scaffold");
|
|
56
|
+
}
|
|
57
|
+
const appBarChildren = React.Children.toArray(children).filter((child: any) => child.type.componentType === "AppBar");
|
|
58
|
+
if (appBarChildren.length > 1) {
|
|
59
|
+
throw Error("Only one AppBar component is allowed in Scaffold");
|
|
60
|
+
}
|
|
61
|
+
const otherChildren = React.Children.toArray(children)
|
|
62
|
+
.filter((child: any) => child.type.componentType !== "Drawer" && child.type.componentType !== "AppBar");
|
|
63
|
+
const includeDrawer = drawerChildren.length > 0;
|
|
96
64
|
const largeLayout = useLargeLayout();
|
|
97
65
|
|
|
98
66
|
const [drawerOpen, setDrawerOpen] = React.useState(false);
|
|
@@ -112,38 +80,37 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
|
|
|
112
80
|
const computedDrawerOpen: boolean = drawerOpen || Boolean(largeLayout && autoOpenDrawer && onHover);
|
|
113
81
|
|
|
114
82
|
return (
|
|
115
|
-
<
|
|
116
|
-
|
|
83
|
+
<AppContext.Provider value={{
|
|
84
|
+
logo,
|
|
85
|
+
hasDrawer: includeDrawer,
|
|
86
|
+
drawerHovered: onHover,
|
|
117
87
|
drawerOpen: computedDrawerOpen,
|
|
118
88
|
closeDrawer: handleDrawerClose,
|
|
119
89
|
openDrawer: handleDrawerOpen,
|
|
120
90
|
autoOpenDrawer
|
|
121
91
|
}}>
|
|
122
92
|
<div
|
|
123
|
-
className="flex h-screen w-screen bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white overflow-hidden"
|
|
93
|
+
className={cls("flex h-screen w-screen bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white overflow-hidden", className)}
|
|
124
94
|
style={{
|
|
125
95
|
paddingTop: "env(safe-area-inset-top)",
|
|
126
96
|
paddingLeft: "env(safe-area-inset-left)",
|
|
127
97
|
paddingRight: "env(safe-area-inset-right)",
|
|
128
98
|
paddingBottom: "env(safe-area-inset-bottom)",
|
|
129
|
-
height: "100dvh"
|
|
99
|
+
height: "100dvh",
|
|
100
|
+
...style
|
|
130
101
|
}}>
|
|
131
102
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
logo={logo}
|
|
135
|
-
drawerOpen={computedDrawerOpen}
|
|
136
|
-
{...fireCMSAppBarProps}/>
|
|
103
|
+
{appBarChildren}
|
|
104
|
+
|
|
137
105
|
<DrawerWrapper
|
|
138
106
|
displayed={includeDrawer}
|
|
139
107
|
onMouseEnter={setOnHoverTrue}
|
|
140
108
|
onMouseMove={setOnHoverTrue}
|
|
141
109
|
onMouseLeave={setOnHoverFalse}
|
|
142
110
|
open={computedDrawerOpen}
|
|
143
|
-
logo={logo}
|
|
144
111
|
hovered={onHover}
|
|
145
112
|
setDrawerOpen={setDrawerOpen}>
|
|
146
|
-
{includeDrawer &&
|
|
113
|
+
{includeDrawer && drawerChildren}
|
|
147
114
|
</DrawerWrapper>
|
|
148
115
|
|
|
149
116
|
<main
|
|
@@ -153,13 +120,13 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
|
|
|
153
120
|
className={cls(defaultBorderMixin, "flex-grow overflow-auto lg:m-0 lg:mx-4 lg:mb-4 lg:rounded-lg lg:border lg:border-solid m-0 mt-1")}>
|
|
154
121
|
|
|
155
122
|
<ErrorBoundary>
|
|
156
|
-
{
|
|
123
|
+
{otherChildren}
|
|
157
124
|
</ErrorBoundary>
|
|
158
125
|
|
|
159
126
|
</div>
|
|
160
127
|
</main>
|
|
161
128
|
</div>
|
|
162
|
-
</
|
|
129
|
+
</AppContext.Provider>
|
|
163
130
|
);
|
|
164
131
|
},
|
|
165
132
|
equal
|
|
@@ -183,8 +150,6 @@ function DrawerWrapper(props: {
|
|
|
183
150
|
onMouseLeave: () => void
|
|
184
151
|
}) {
|
|
185
152
|
|
|
186
|
-
const navigation = useNavigationController();
|
|
187
|
-
|
|
188
153
|
const width = !props.displayed ? 0 : (props.open ? DRAWER_WIDTH : 72);
|
|
189
154
|
const innerDrawer = <div
|
|
190
155
|
className={"relative h-full no-scrollbar overflow-y-auto overflow-x-hidden"}
|
|
@@ -198,7 +163,7 @@ function DrawerWrapper(props: {
|
|
|
198
163
|
<Tooltip title="Open menu"
|
|
199
164
|
side="right"
|
|
200
165
|
sideOffset={12}
|
|
201
|
-
className="fixed top-2 left-3 !bg-gray-50 dark:!bg-gray-900 rounded-full w-fit"
|
|
166
|
+
className="fixed top-2 left-3 !bg-gray-50 dark:!bg-gray-900 rounded-full w-fit z-20"
|
|
202
167
|
>
|
|
203
168
|
<IconButton
|
|
204
169
|
color="inherit"
|
|
@@ -212,30 +177,19 @@ function DrawerWrapper(props: {
|
|
|
212
177
|
</Tooltip>
|
|
213
178
|
)}
|
|
214
179
|
|
|
215
|
-
<div
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
<
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
<Link
|
|
227
|
-
to={navigation.basePath}>
|
|
228
|
-
{props.logo
|
|
229
|
-
? <img src={props.logo}
|
|
230
|
-
alt="Logo"
|
|
231
|
-
className={cls("max-w-full max-h-full",
|
|
232
|
-
props.open ?? "w-[112px] h-[112px]")}/>
|
|
233
|
-
: <FireCMSLogo/>}
|
|
234
|
-
|
|
235
|
-
</Link>
|
|
236
|
-
</Tooltip>
|
|
237
|
-
</div>
|
|
180
|
+
<div
|
|
181
|
+
className={`z-20 absolute right-0 top-4 ${
|
|
182
|
+
props.open ? "opacity-100" : "opacity-0 invisible"
|
|
183
|
+
} transition-opacity duration-200 ease-in-out`}>
|
|
184
|
+
<IconButton
|
|
185
|
+
aria-label="Close drawer"
|
|
186
|
+
onClick={() => props.setDrawerOpen(false)}
|
|
187
|
+
>
|
|
188
|
+
<ChevronLeftIcon/>
|
|
189
|
+
</IconButton>
|
|
190
|
+
</div>
|
|
238
191
|
|
|
192
|
+
<div className={"flex flex-col h-full"}>
|
|
239
193
|
{props.children}
|
|
240
194
|
</div>
|
|
241
195
|
|
|
@@ -267,7 +221,7 @@ function DrawerWrapper(props: {
|
|
|
267
221
|
|
|
268
222
|
return (
|
|
269
223
|
<div
|
|
270
|
-
className="relative"
|
|
224
|
+
className="z-20 relative"
|
|
271
225
|
onMouseEnter={props.onMouseEnter}
|
|
272
226
|
onMouseMove={props.onMouseMove}
|
|
273
227
|
onMouseLeave={props.onMouseLeave}
|
|
@@ -278,17 +232,17 @@ function DrawerWrapper(props: {
|
|
|
278
232
|
|
|
279
233
|
{innerDrawer}
|
|
280
234
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
235
|
+
{/*<div*/}
|
|
236
|
+
{/* className={`z-20 absolute right-0 top-4 ${*/}
|
|
237
|
+
{/* props.open ? "opacity-100" : "opacity-0 invisible"*/}
|
|
238
|
+
{/* } transition-opacity duration-1000 ease-in-out`}>*/}
|
|
239
|
+
{/* <IconButton*/}
|
|
240
|
+
{/* aria-label="Close drawer"*/}
|
|
241
|
+
{/* onClick={() => props.setDrawerOpen(false)}*/}
|
|
242
|
+
{/* >*/}
|
|
243
|
+
{/* <ChevronLeftIcon/>*/}
|
|
244
|
+
{/* </IconButton>*/}
|
|
245
|
+
{/*</div>*/}
|
|
292
246
|
|
|
293
247
|
</div>
|
|
294
248
|
);
|
package/src/app/index.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This context represents the state of the app in terms of layout.
|
|
5
|
+
* @group Core
|
|
6
|
+
*/
|
|
7
|
+
export type AppState = {
|
|
8
|
+
hasDrawer: boolean,
|
|
9
|
+
drawerHovered: boolean,
|
|
10
|
+
drawerOpen: boolean,
|
|
11
|
+
openDrawer: () => void,
|
|
12
|
+
closeDrawer: () => void,
|
|
13
|
+
autoOpenDrawer?: boolean,
|
|
14
|
+
logo?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const AppContext = React.createContext<AppState>({
|
|
18
|
+
hasDrawer: false,
|
|
19
|
+
drawerHovered: false,
|
|
20
|
+
drawerOpen: false,
|
|
21
|
+
openDrawer: () => {
|
|
22
|
+
throw new Error("openDrawer not implemented");
|
|
23
|
+
},
|
|
24
|
+
closeDrawer: () => {
|
|
25
|
+
throw new Error("closeDrawer not implemented");
|
|
26
|
+
},
|
|
27
|
+
autoOpenDrawer: false
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export function useApp() {
|
|
31
|
+
return React.useContext(AppContext);
|
|
32
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { MouseEvent, useCallback } from "react";
|
|
2
2
|
|
|
3
3
|
import { CollectionSize, Entity, EntityAction, EntityCollection, SelectionController } from "../../types";
|
|
4
|
-
import { Checkbox, cls, IconButton, Menu, MenuItem, MoreVertIcon, Skeleton, Tooltip
|
|
4
|
+
import { Checkbox, cls, IconButton, Menu, MenuItem, MoreVertIcon, Skeleton, Tooltip } from "@firecms/ui";
|
|
5
5
|
import { useFireCMSContext, useLargeLayout } from "../../hooks";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -149,16 +149,14 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
|
|
|
149
149
|
</div>}
|
|
150
150
|
|
|
151
151
|
{!hideId && size !== "xs" && (
|
|
152
|
-
<div
|
|
152
|
+
<div
|
|
153
|
+
className="w-[138px] text-center overflow-hidden truncate font-mono text-xs text-text-secondary dark:text-text-secondary-dark max-w-full text-ellipsis px-2"
|
|
154
|
+
onClick={(event) => {
|
|
155
|
+
event.stopPropagation();
|
|
156
|
+
}}>
|
|
153
157
|
|
|
154
158
|
{entity
|
|
155
|
-
?
|
|
156
|
-
onClick={(event) => {
|
|
157
|
-
event.stopPropagation();
|
|
158
|
-
}}
|
|
159
|
-
className={"font-mono select-all"}
|
|
160
|
-
variant={"caption"}
|
|
161
|
-
color={"secondary"}> {entity.id} </Typography>
|
|
159
|
+
? entity.id
|
|
162
160
|
: <Skeleton/>
|
|
163
161
|
}
|
|
164
162
|
</div>
|
|
@@ -264,7 +264,8 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
|
|
|
264
264
|
values,
|
|
265
265
|
path,
|
|
266
266
|
setFieldValue,
|
|
267
|
-
save: saveValue
|
|
267
|
+
save: saveValue,
|
|
268
|
+
formex
|
|
268
269
|
};
|
|
269
270
|
|
|
270
271
|
const property: ResolvedProperty<any> | undefined = propertyKey && getPropertyInPath(collection.properties, propertyKey as string);
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
CollectionSize,
|
|
8
8
|
Entity,
|
|
9
9
|
EntityAction,
|
|
10
|
-
EntityCollection,
|
|
10
|
+
EntityCollection, EntityTableController,
|
|
11
11
|
FilterValues,
|
|
12
12
|
PartialEntityCollection,
|
|
13
13
|
PropertyOrBuilder,
|
|
@@ -266,6 +266,7 @@ export const EntityCollectionView = React.memo(
|
|
|
266
266
|
fullPath: string,
|
|
267
267
|
parentCollectionIds: string[],
|
|
268
268
|
collection: EntityCollection;
|
|
269
|
+
tableController: EntityTableController;
|
|
269
270
|
}> | undefined
|
|
270
271
|
|
|
271
272
|
// we are only using the first plugin that implements this
|
|
@@ -368,12 +369,12 @@ export const EntityCollectionView = React.memo(
|
|
|
368
369
|
return resolveProperty({
|
|
369
370
|
propertyKey,
|
|
370
371
|
propertyOrBuilder,
|
|
371
|
-
path:
|
|
372
|
+
path: entity.path,
|
|
372
373
|
values: entity.values,
|
|
373
374
|
entityId: entity.id,
|
|
374
375
|
fields: customizationController.propertyConfigs
|
|
375
376
|
});
|
|
376
|
-
}, [collection.properties, customizationController.propertyConfigs,
|
|
377
|
+
}, [collection.properties, customizationController.propertyConfigs, resolvedCollection.properties]);
|
|
377
378
|
|
|
378
379
|
const displayedColumnIds = useColumnIds(resolvedCollection, true);
|
|
379
380
|
|
|
@@ -564,6 +565,7 @@ export const EntityCollectionView = React.memo(
|
|
|
564
565
|
property={property}
|
|
565
566
|
fullPath={fullPath}
|
|
566
567
|
collection={collection}
|
|
568
|
+
tableController={tableController}
|
|
567
569
|
parentCollectionIds={parentCollectionIds ?? []}/>;
|
|
568
570
|
})}
|
|
569
571
|
</>;
|
|
@@ -574,7 +576,8 @@ export const EntityCollectionView = React.memo(
|
|
|
574
576
|
if (typeof AddColumnComponent === "function")
|
|
575
577
|
return <AddColumnComponent fullPath={fullPath}
|
|
576
578
|
parentCollectionIds={parentCollectionIds ?? []}
|
|
577
|
-
collection={collection}
|
|
579
|
+
collection={collection}
|
|
580
|
+
tableController={tableController}/>;
|
|
578
581
|
return null;
|
|
579
582
|
}
|
|
580
583
|
: undefined;
|
|
@@ -107,6 +107,7 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
107
107
|
hoverRow,
|
|
108
108
|
createFilterField,
|
|
109
109
|
rowClassName,
|
|
110
|
+
style,
|
|
110
111
|
className,
|
|
111
112
|
endAdornment,
|
|
112
113
|
AddColumnComponent
|
|
@@ -239,7 +240,7 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
239
240
|
const empty = !loading && (data?.length ?? 0) === 0;
|
|
240
241
|
const customView = error
|
|
241
242
|
? <CenteredView maxWidth={"2xl"}
|
|
242
|
-
|
|
243
|
+
className="flex flex-col gap-2">
|
|
243
244
|
|
|
244
245
|
<Typography variant={"h6"}>
|
|
245
246
|
{"Error fetching data from the data source"}
|
|
@@ -275,6 +276,7 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
275
276
|
return (
|
|
276
277
|
<div
|
|
277
278
|
ref={measureRef}
|
|
279
|
+
style={style}
|
|
278
280
|
className={cls("h-full w-full", className)}>
|
|
279
281
|
<VirtualListContext.Provider
|
|
280
282
|
value={virtualListController}>
|
|
@@ -131,6 +131,11 @@ export interface VirtualTableProps<T extends Record<string, any>> {
|
|
|
131
131
|
*/
|
|
132
132
|
className?: string;
|
|
133
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Style applied to the table
|
|
136
|
+
*/
|
|
137
|
+
style?: React.CSSProperties;
|
|
138
|
+
|
|
134
139
|
/**
|
|
135
140
|
* Component rendered at the end of the table, after scroll
|
|
136
141
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { EntityCollection } from "../../types";
|
|
4
|
-
import { useCustomizationController, useFireCMSContext } from "../../hooks";
|
|
4
|
+
import { useCustomizationController, useDataSource, useFireCMSContext } from "../../hooks";
|
|
5
5
|
|
|
6
6
|
export interface UseTableSearchHelperParams<M extends Record<string, any>> {
|
|
7
7
|
collection: EntityCollection<M>;
|
|
@@ -9,27 +9,57 @@ export interface UseTableSearchHelperParams<M extends Record<string, any>> {
|
|
|
9
9
|
parentCollectionIds?: string[];
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export function useTableSearchHelper<M extends Record<string, any>>({
|
|
12
|
+
export function useTableSearchHelper<M extends Record<string, any>>({
|
|
13
|
+
collection,
|
|
14
|
+
fullPath,
|
|
15
|
+
parentCollectionIds
|
|
16
|
+
}: UseTableSearchHelperParams<M>) {
|
|
13
17
|
|
|
14
18
|
const context = useFireCMSContext();
|
|
15
19
|
const customizationController = useCustomizationController();
|
|
20
|
+
const dataSource = useDataSource();
|
|
16
21
|
|
|
17
22
|
const [textSearchLoading, setTextSearchLoading] = useState<boolean>(false);
|
|
18
23
|
const [textSearchInitialised, setTextSearchInitialised] = useState<boolean>(false);
|
|
24
|
+
|
|
19
25
|
let onTextSearchClick: (() => void) | undefined;
|
|
20
26
|
let textSearchEnabled = Boolean(collection.textSearchEnabled);
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
|
|
28
|
+
const props = {
|
|
29
|
+
context,
|
|
30
|
+
path: fullPath,
|
|
31
|
+
collection,
|
|
32
|
+
parentCollectionIds
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const searchBlocked = customizationController.plugins?.find(p => {
|
|
36
|
+
return p.collectionView?.blockSearch?.(props);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const addTextSearchClickListener = Boolean(dataSource?.initTextSearch) || customizationController.plugins?.find(p => Boolean(p.collectionView?.onTextSearchClick));
|
|
40
|
+
|
|
41
|
+
if (addTextSearchClickListener) {
|
|
23
42
|
|
|
24
43
|
onTextSearchClick = addTextSearchClickListener
|
|
25
44
|
? () => {
|
|
26
45
|
setTextSearchLoading(true);
|
|
27
|
-
Promise
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.
|
|
46
|
+
const promises: Promise<boolean>[] = [];
|
|
47
|
+
if (dataSource?.initTextSearch && !searchBlocked) {
|
|
48
|
+
promises.push(dataSource.initTextSearch(props));
|
|
49
|
+
}
|
|
50
|
+
if (searchBlocked) {
|
|
51
|
+
customizationController.plugins?.forEach(p => {
|
|
52
|
+
if (p.collectionView?.onTextSearchClick)
|
|
53
|
+
promises.push(p.collectionView.onTextSearchClick({
|
|
54
|
+
context,
|
|
55
|
+
path: fullPath,
|
|
56
|
+
collection,
|
|
57
|
+
parentCollectionIds
|
|
58
|
+
}));
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
return Promise.all(promises)
|
|
62
|
+
.then((res: boolean[]) => {
|
|
33
63
|
if (res.every(Boolean)) setTextSearchInitialised(true);
|
|
34
64
|
})
|
|
35
65
|
.finally(() => setTextSearchLoading(false));
|
|
@@ -39,9 +69,19 @@ export function useTableSearchHelper<M extends Record<string, any>>({ collection
|
|
|
39
69
|
customizationController.plugins?.forEach(p => {
|
|
40
70
|
if (!textSearchEnabled)
|
|
41
71
|
if (p.collectionView?.showTextSearchBar) {
|
|
42
|
-
textSearchEnabled = p.collectionView.showTextSearchBar({
|
|
72
|
+
textSearchEnabled = p.collectionView.showTextSearchBar({
|
|
73
|
+
context,
|
|
74
|
+
path: fullPath,
|
|
75
|
+
collection,
|
|
76
|
+
parentCollectionIds
|
|
77
|
+
});
|
|
43
78
|
}
|
|
44
79
|
})
|
|
45
80
|
}
|
|
46
|
-
return {
|
|
81
|
+
return {
|
|
82
|
+
textSearchLoading,
|
|
83
|
+
textSearchInitialised,
|
|
84
|
+
onTextSearchClick,
|
|
85
|
+
textSearchEnabled
|
|
86
|
+
};
|
|
47
87
|
}
|
package/src/components/index.tsx
CHANGED
|
@@ -18,14 +18,14 @@ export const DialogsProvider: React.FC<PropsWithChildren<{}>> = ({ children }) =
|
|
|
18
18
|
if (dialogEntries.length === 0)
|
|
19
19
|
return;
|
|
20
20
|
|
|
21
|
-
const updatedPanels = [...
|
|
21
|
+
const updatedPanels = [...dialogEntriesRef.current.slice(0, -1)];
|
|
22
22
|
updateDialogEntries(updatedPanels);
|
|
23
23
|
|
|
24
24
|
}, [dialogEntries]);
|
|
25
25
|
|
|
26
26
|
const open = useCallback((dialogEntry: DialogControllerEntryProps) => {
|
|
27
27
|
|
|
28
|
-
const updatedPanels = [...
|
|
28
|
+
const updatedPanels = [...dialogEntriesRef.current, dialogEntry];
|
|
29
29
|
updateDialogEntries(updatedPanels);
|
|
30
30
|
|
|
31
31
|
return {
|