@applica-software-guru/react-admin 1.5.234 → 1.5.235
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/.husky/pre-commit +1 -2
- package/dist/components/ra-buttons/CreateInDialogButton.d.ts +28 -28
- package/dist/components/ra-buttons/CreateInDialogButton.d.ts.map +1 -1
- package/dist/components/ra-buttons/EditInDialogButton.d.ts +11 -8
- package/dist/components/ra-buttons/EditInDialogButton.d.ts.map +1 -1
- package/dist/react-admin.cjs.js +66 -66
- package/dist/react-admin.cjs.js.map +1 -1
- package/dist/react-admin.es.js +11089 -10292
- package/dist/react-admin.es.js.map +1 -1
- package/dist/react-admin.umd.js +59 -59
- package/dist/react-admin.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ra-buttons/CreateInDialogButton.tsx +99 -216
- package/src/components/ra-buttons/EditInDialogButton.tsx +66 -101
- package/src/playground/App.jsx +1 -0
- package/src/playground/components/ra-forms/CategoryForm.jsx +12 -0
- package/src/playground/components/ra-forms/index.jsx +1 -0
- package/src/playground/components/ra-lists/CategoryList.jsx +62 -0
- package/src/playground/components/ra-lists/index.jsx +1 -0
- package/src/playground/entities/category.jsx +26 -0
- package/src/playground/entities/index.jsx +1 -0
- package/src/playground/menu.jsx +10 -3
package/package.json
CHANGED
|
@@ -1,25 +1,9 @@
|
|
|
1
|
-
import { useAppConfig } from '@/components/AppStateProvider';
|
|
2
1
|
import { Toolbar } from '@/components/ra-forms';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import clsx from 'clsx';
|
|
2
|
+
import { Breakpoint, Dialog } from '@mui/material';
|
|
3
|
+
import { CreateBase, UseCreateMutateParams, useResourceContext } from 'ra-core';
|
|
4
|
+
import { Button, CreateButton, CreateButtonProps, CreateProps, SaveButton } from 'ra-ui-materialui';
|
|
7
5
|
import React, { Children, PropsWithChildren, useCallback, useState } from 'react';
|
|
8
|
-
import {
|
|
9
|
-
Button,
|
|
10
|
-
CreateButtonClasses,
|
|
11
|
-
CreateContextProvider,
|
|
12
|
-
CreateControllerProps,
|
|
13
|
-
CreateControllerResult,
|
|
14
|
-
RedirectionSideEffect,
|
|
15
|
-
SaveButton,
|
|
16
|
-
UseCreateMutateParams,
|
|
17
|
-
useCreateController,
|
|
18
|
-
useNotify,
|
|
19
|
-
useRedirect,
|
|
20
|
-
useResourceContext,
|
|
21
|
-
useTranslate
|
|
22
|
-
} from 'react-admin';
|
|
6
|
+
import { FieldValues, useFormContext } from 'react-hook-form';
|
|
23
7
|
import { useQueryClient } from 'react-query';
|
|
24
8
|
|
|
25
9
|
function updateColl(old: any, data: any) {
|
|
@@ -43,80 +27,74 @@ function setListQueryData(res: any, data: any) {
|
|
|
43
27
|
return res && res.data ? { ...res, data: updateColl(res.data, data), total: res.total + 1 } : res;
|
|
44
28
|
}
|
|
45
29
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
onSuccess,
|
|
59
|
-
onError,
|
|
60
|
-
...controllerProps
|
|
61
|
-
}: CreateInDialogButtonProps): JSX.Element {
|
|
62
|
-
const [open, setOpen] = useState(false);
|
|
63
|
-
const translate = useTranslate();
|
|
64
|
-
const resource = useResourceContext();
|
|
65
|
-
const { openDialog, closeDialog } = useAppConfig();
|
|
66
|
-
const handleOpen = useCallback(() => openDialog(resource, () => setOpen(true)), [openDialog, resource]);
|
|
67
|
-
const handleClose = useCallback(() => closeDialog(resource, () => setOpen(false)), [closeDialog, resource]);
|
|
68
|
-
const isMobile = useMediaQuery((theme: Theme) => theme.breakpoints.down('md'));
|
|
69
|
-
const isSmall = fab && isMobile;
|
|
70
|
-
return (
|
|
71
|
-
<>
|
|
72
|
-
{isSmall ? (
|
|
73
|
-
<StyledFab
|
|
74
|
-
// @ts-expect-error WARN: Why state prop not exists on styled fab?
|
|
75
|
-
state={scrollStates[String(scrollToTop)]}
|
|
76
|
-
color="primary"
|
|
77
|
-
className={clsx(CreateButtonClasses.floating, className)}
|
|
78
|
-
aria-label={label ? translate(label) : null}
|
|
79
|
-
onClick={handleOpen}
|
|
80
|
-
>
|
|
81
|
-
<ContentAdd />
|
|
82
|
-
</StyledFab>
|
|
83
|
-
) : (
|
|
84
|
-
<Button sx={sx} label={label} onClick={handleOpen} style={style}>
|
|
85
|
-
<ContentAdd />
|
|
86
|
-
</Button>
|
|
87
|
-
)}
|
|
88
|
-
<Dialog open={open} scroll="body" onClose={handleClose} fullWidth={fullWidth} maxWidth={maxWidth}>
|
|
89
|
-
<CreateInDialogContent
|
|
90
|
-
{...controllerProps}
|
|
91
|
-
redirect={redirect}
|
|
92
|
-
record={record}
|
|
93
|
-
onClose={handleClose}
|
|
94
|
-
onSubmit={onSubmit}
|
|
95
|
-
onSuccess={onSuccess}
|
|
96
|
-
onError={onError}
|
|
97
|
-
/>
|
|
98
|
-
</Dialog>
|
|
99
|
-
</>
|
|
30
|
+
type ResponsiveButtonProps = CreateButtonProps & {
|
|
31
|
+
label?: string;
|
|
32
|
+
onClick?: () => void;
|
|
33
|
+
};
|
|
34
|
+
function ResponsiveButton(props: ResponsiveButtonProps): JSX.Element {
|
|
35
|
+
const handleClick = useCallback(
|
|
36
|
+
(event: any) => {
|
|
37
|
+
(event as Event).preventDefault();
|
|
38
|
+
(event as Event).stopPropagation();
|
|
39
|
+
props?.onClick?.();
|
|
40
|
+
},
|
|
41
|
+
[props]
|
|
100
42
|
);
|
|
43
|
+
return <CreateButton {...props} onClick={handleClick} />;
|
|
101
44
|
}
|
|
45
|
+
type CloseDialogFunction = () => void;
|
|
46
|
+
type SubmitFunction = (values: FieldValues, closeDialog: CloseDialogFunction) => void;
|
|
47
|
+
type SubmitButtonProps = {
|
|
48
|
+
onSubmit: SubmitFunction;
|
|
49
|
+
closeDialog: CloseDialogFunction;
|
|
50
|
+
};
|
|
51
|
+
function SubmitButton(props: SubmitButtonProps) {
|
|
52
|
+
const { onSubmit, closeDialog } = props;
|
|
53
|
+
const { handleSubmit } = useFormContext();
|
|
54
|
+
const handleClick = useCallback(
|
|
55
|
+
(event: any) => {
|
|
56
|
+
(event as Event).preventDefault();
|
|
57
|
+
(event as Event).stopPropagation();
|
|
58
|
+
handleSubmit((fieldValues) => onSubmit(fieldValues, closeDialog))();
|
|
59
|
+
},
|
|
60
|
+
[handleSubmit, onSubmit, closeDialog]
|
|
61
|
+
);
|
|
62
|
+
return <Button onClick={handleClick} label="ra.action.save" color="primary" variant="contained" size="medium" />;
|
|
63
|
+
}
|
|
64
|
+
type CreateInDialogButtonProps = PropsWithChildren &
|
|
65
|
+
CreateProps &
|
|
66
|
+
ResponsiveButtonProps & {
|
|
67
|
+
maxWidth: Breakpoint;
|
|
68
|
+
fullWidth?: boolean;
|
|
69
|
+
fullScreen?: boolean;
|
|
102
70
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Custom handler for the submit event, in this case you are responsible for closing the dialog.
|
|
73
|
+
* @example
|
|
74
|
+
*
|
|
75
|
+
* const handleSubmit = (values, closeDialog) => {
|
|
76
|
+
* console.log(values); // { title: 'Hello World' }
|
|
77
|
+
* closeDialog();
|
|
78
|
+
* }
|
|
79
|
+
* <CreateInDialogButton onSubmit={handleSubmit}>
|
|
80
|
+
* <SimpleForm>
|
|
81
|
+
* <TextInput source="title" />
|
|
82
|
+
* </SimpleForm>
|
|
83
|
+
* </CreateInDialogButton>
|
|
84
|
+
*
|
|
85
|
+
*/
|
|
86
|
+
onSubmit?: SubmitFunction;
|
|
87
|
+
};
|
|
88
|
+
function CreateInDialogButton(props: CreateInDialogButtonProps) {
|
|
89
|
+
const { children, maxWidth = 'md', fullWidth = true, fullScreen, onSubmit, mutationOptions, ...rest } = props;
|
|
114
90
|
const queryClient = useQueryClient();
|
|
115
91
|
const resource = useResourceContext();
|
|
116
|
-
const
|
|
117
|
-
const
|
|
92
|
+
const Child = Children.only(children);
|
|
93
|
+
const [open, setOpen] = useState(false);
|
|
94
|
+
const handleOpen = useCallback(() => setOpen(true), []);
|
|
95
|
+
const handleClose = useCallback(() => setOpen(false), []);
|
|
118
96
|
const handleSuccess = useCallback(
|
|
119
|
-
(data: any,
|
|
97
|
+
(data: any, params: UseCreateMutateParams<any>, context: unknown) => {
|
|
120
98
|
const now = Date.now();
|
|
121
99
|
const updatedAt = now;
|
|
122
100
|
|
|
@@ -130,139 +108,44 @@ function CreateInDialogContent({
|
|
|
130
108
|
queryClient.setQueriesData([resource, 'getManyReference'], (res: any) => setManyReferenceQueryData(res, data), {
|
|
131
109
|
updatedAt
|
|
132
110
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
notify('ra.notification.created');
|
|
136
|
-
if (_redirect !== undefined) {
|
|
137
|
-
redirect(_redirect as RedirectionSideEffect, resource, data.id, data);
|
|
138
|
-
}
|
|
139
|
-
if (onSuccess) {
|
|
140
|
-
onSuccess(data, onClose);
|
|
141
|
-
}
|
|
142
|
-
if (props?.mutationOptions?.onSuccess) {
|
|
143
|
-
props.mutationOptions.onSuccess(data, variables, { ...(context as any), onClose });
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
[onClose, onSuccess, queryClient, resource, notify, redirect, _redirect, props?.mutationOptions]
|
|
147
|
-
);
|
|
148
|
-
const { save, ...createProps } = useCreateController({
|
|
149
|
-
...props,
|
|
150
|
-
mutationOptions: {
|
|
151
|
-
...props?.mutationOptions,
|
|
152
|
-
onSuccess: handleSuccess,
|
|
153
|
-
onError: onError
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
const handleSave = useCallback(
|
|
157
|
-
(record: any) => {
|
|
158
|
-
if (onSubmit) {
|
|
159
|
-
onSubmit(record, onClose);
|
|
160
|
-
} else if (save) {
|
|
161
|
-
save(record);
|
|
162
|
-
}
|
|
111
|
+
handleClose();
|
|
112
|
+
props?.mutationOptions?.onSuccess?.(data, params, context);
|
|
163
113
|
},
|
|
164
|
-
[
|
|
114
|
+
[handleClose, props.mutationOptions, queryClient, resource]
|
|
165
115
|
);
|
|
116
|
+
|
|
166
117
|
return (
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
118
|
+
<>
|
|
119
|
+
<ResponsiveButton {...rest} onClick={handleOpen} />
|
|
120
|
+
<CreateBase
|
|
121
|
+
{...props}
|
|
122
|
+
mutationOptions={{
|
|
123
|
+
...mutationOptions,
|
|
124
|
+
onSuccess: handleSuccess
|
|
125
|
+
}}
|
|
126
|
+
>
|
|
127
|
+
<Dialog open={open} onClose={handleClose} maxWidth={maxWidth} fullWidth={fullWidth} fullScreen={fullScreen}>
|
|
128
|
+
{React.isValidElement(Child)
|
|
129
|
+
? React.cloneElement(Child, {
|
|
130
|
+
...Child.props,
|
|
131
|
+
modal: true,
|
|
132
|
+
toolbar: (
|
|
133
|
+
<Toolbar>
|
|
134
|
+
<Button variant="text" size="medium" label="ra.action.cancel" onClick={handleClose} />
|
|
135
|
+
{onSubmit ? (
|
|
136
|
+
<SubmitButton onSubmit={onSubmit!} closeDialog={handleClose} />
|
|
137
|
+
) : (
|
|
138
|
+
<SaveButton type="button" />
|
|
139
|
+
)}
|
|
140
|
+
</Toolbar>
|
|
141
|
+
)
|
|
142
|
+
})
|
|
143
|
+
: null}
|
|
144
|
+
</Dialog>
|
|
145
|
+
</CreateBase>
|
|
146
|
+
</>
|
|
196
147
|
);
|
|
197
148
|
}
|
|
198
149
|
|
|
199
|
-
const scrollStates = {
|
|
200
|
-
true: { _scrollToTop: true },
|
|
201
|
-
false: {}
|
|
202
|
-
} as any;
|
|
203
|
-
|
|
204
|
-
const StyledFab = styled(Fab, { overridesResolver: (_props, styles) => styles.root })(({ theme }) => ({
|
|
205
|
-
[`&.${CreateButtonClasses.floating}`]: {
|
|
206
|
-
color: theme.palette.getContrastText(theme.palette.primary.main),
|
|
207
|
-
margin: 0,
|
|
208
|
-
top: 'auto',
|
|
209
|
-
right: 20,
|
|
210
|
-
bottom: 60,
|
|
211
|
-
left: 'auto',
|
|
212
|
-
position: 'fixed',
|
|
213
|
-
zIndex: 1000
|
|
214
|
-
}
|
|
215
|
-
}));
|
|
216
|
-
|
|
217
|
-
type CreateInDialogButtonProps = CreateControllerProps &
|
|
218
|
-
PropsWithChildren<{
|
|
219
|
-
fullWidth?: boolean;
|
|
220
|
-
maxWidth?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | false;
|
|
221
|
-
label?: string;
|
|
222
|
-
record?: any;
|
|
223
|
-
redirect?: RedirectionSideEffect;
|
|
224
|
-
scrollToTop?: boolean;
|
|
225
|
-
className?: string;
|
|
226
|
-
sx?: SxProps;
|
|
227
|
-
style?: React.CSSProperties;
|
|
228
|
-
/**
|
|
229
|
-
* If set to false, the button will always render as a regular button, regardless of the screen size.
|
|
230
|
-
*/
|
|
231
|
-
fab: boolean;
|
|
232
|
-
/**
|
|
233
|
-
* @deprecated Use mutationOptions.onSubmit instead
|
|
234
|
-
*/
|
|
235
|
-
onSubmit?: (record: any, close: () => void) => void;
|
|
236
|
-
/**
|
|
237
|
-
* @deprecated Use mutationOptions.onSuccess instead
|
|
238
|
-
*/
|
|
239
|
-
onSuccess?: (data: any) => void;
|
|
240
|
-
/**
|
|
241
|
-
*
|
|
242
|
-
* @deprecated Use mutationOptions.onError instead
|
|
243
|
-
*/
|
|
244
|
-
onError?: (error: any) => void;
|
|
245
|
-
}>;
|
|
246
|
-
|
|
247
|
-
type CreateInDialogContentProps = CreateControllerProps &
|
|
248
|
-
PropsWithChildren<{
|
|
249
|
-
onClose: () => void;
|
|
250
|
-
record?: any;
|
|
251
|
-
redirect: RedirectionSideEffect | boolean | undefined;
|
|
252
|
-
/**
|
|
253
|
-
* You can use it to handle the form submission yourself.
|
|
254
|
-
* Good luck with that.
|
|
255
|
-
*/
|
|
256
|
-
onSubmit?: (record: any, close: () => void) => void;
|
|
257
|
-
/**
|
|
258
|
-
* @deprecated Use mutationOptions.onSuccess instead
|
|
259
|
-
*/
|
|
260
|
-
onSuccess?: (data: any, close: () => void) => void;
|
|
261
|
-
/**
|
|
262
|
-
* @deprecated Use mutationOptions.onError instead
|
|
263
|
-
*/
|
|
264
|
-
onError?: (error: any) => void;
|
|
265
|
-
}>;
|
|
266
|
-
|
|
267
150
|
export { CreateInDialogButton };
|
|
268
151
|
export type { CreateInDialogButtonProps };
|
|
@@ -1,119 +1,84 @@
|
|
|
1
|
-
import { useAppConfig } from '@/components/AppStateProvider';
|
|
2
1
|
import { Toolbar } from '@/components/ra-forms';
|
|
3
|
-
import { Edit } from '@mui/icons-material';
|
|
4
2
|
import { Breakpoint, Dialog } from '@mui/material';
|
|
3
|
+
import { EditBase, UseUpdateMutateParams, useRecordContext } from 'ra-core';
|
|
4
|
+
import { Button, EditButton, EditProps, SaveButton } from 'ra-ui-materialui';
|
|
5
5
|
import React, { Children, PropsWithChildren, useCallback, useState } from 'react';
|
|
6
|
-
import {
|
|
7
|
-
Button,
|
|
8
|
-
EditContextProvider,
|
|
9
|
-
EditControllerProps,
|
|
10
|
-
SaveButton,
|
|
11
|
-
useEditController,
|
|
12
|
-
useGetOne,
|
|
13
|
-
useNotify,
|
|
14
|
-
useRecordContext,
|
|
15
|
-
useResourceContext
|
|
16
|
-
} from 'react-admin';
|
|
17
6
|
|
|
18
|
-
type
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
function EditInDialogContent({ onClose, children, mutationMode = 'pessimistic', ...props }: EditInDialogContentProps) {
|
|
23
|
-
const Child = Children.only(children);
|
|
24
|
-
const notify = useNotify();
|
|
25
|
-
const record = useRecordContext();
|
|
26
|
-
const resource = useResourceContext();
|
|
27
|
-
const { id } = record;
|
|
28
|
-
const { isLoading, data } = useGetOne(resource, { id });
|
|
29
|
-
const { onSuccess } = props;
|
|
7
|
+
type ResponsiveButtonProps = {
|
|
8
|
+
label?: string;
|
|
9
|
+
onClick: () => void;
|
|
10
|
+
};
|
|
30
11
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
onClose();
|
|
40
|
-
if (onSuccess) {
|
|
41
|
-
onSuccess(...args);
|
|
42
|
-
}
|
|
12
|
+
function ResponsiveButton(props: ResponsiveButtonProps): JSX.Element {
|
|
13
|
+
const handleClick = useCallback(
|
|
14
|
+
(event: any) => {
|
|
15
|
+
(event as Event).preventDefault();
|
|
16
|
+
(event as Event).stopPropagation();
|
|
17
|
+
props?.onClick?.();
|
|
43
18
|
},
|
|
44
|
-
[
|
|
45
|
-
);
|
|
46
|
-
const { save, saving } = useEditController({
|
|
47
|
-
...props,
|
|
48
|
-
resource,
|
|
49
|
-
id,
|
|
50
|
-
mutationMode,
|
|
51
|
-
mutationOptions: {
|
|
52
|
-
...props?.mutationOptions,
|
|
53
|
-
onSuccess: handleSuccess
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<EditContextProvider
|
|
59
|
-
// @ts-ignore
|
|
60
|
-
value={{
|
|
61
|
-
record: data,
|
|
62
|
-
isLoading,
|
|
63
|
-
save: save,
|
|
64
|
-
saving: saving
|
|
65
|
-
}}
|
|
66
|
-
>
|
|
67
|
-
{React.isValidElement(Child)
|
|
68
|
-
? React.cloneElement(Child, {
|
|
69
|
-
...Child.props,
|
|
70
|
-
modal: true,
|
|
71
|
-
toolbar: (
|
|
72
|
-
<Toolbar>
|
|
73
|
-
<Button variant="text" size="medium" label="ra.action.cancel" onClick={onClose} />
|
|
74
|
-
<SaveButton type="button" />
|
|
75
|
-
</Toolbar>
|
|
76
|
-
)
|
|
77
|
-
})
|
|
78
|
-
: null}
|
|
79
|
-
</EditContextProvider>
|
|
19
|
+
[props]
|
|
80
20
|
);
|
|
21
|
+
return <EditButton {...props} onClick={handleClick} />;
|
|
81
22
|
}
|
|
82
23
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
24
|
+
type EditInDialogButtonProps = PropsWithChildren &
|
|
25
|
+
EditProps &
|
|
26
|
+
ResponsiveButtonProps & {
|
|
27
|
+
maxWidth: Breakpoint;
|
|
28
|
+
fullWidth?: boolean;
|
|
29
|
+
fullScreen?: boolean;
|
|
30
|
+
};
|
|
31
|
+
function EditInDialogButton(props: EditInDialogButtonProps): JSX.Element {
|
|
32
|
+
const { children, maxWidth = 'md', fullWidth = true, fullScreen, mutationOptions, ...rest } = props;
|
|
91
33
|
const [open, setOpen] = useState(false);
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
const
|
|
34
|
+
const Child = Children.only(children);
|
|
35
|
+
const handleOpen = useCallback(() => setOpen(true), []);
|
|
36
|
+
const handleClose = useCallback(() => setOpen(false), []);
|
|
37
|
+
const handleSuccess = useCallback(
|
|
38
|
+
(data: any, params: UseUpdateMutateParams<any>, context: unknown) => {
|
|
39
|
+
handleClose();
|
|
40
|
+
props?.mutationOptions?.onSuccess?.(data, params, context);
|
|
41
|
+
},
|
|
42
|
+
[handleClose, props.mutationOptions]
|
|
43
|
+
);
|
|
44
|
+
const record = useRecordContext();
|
|
96
45
|
return (
|
|
97
46
|
<>
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
47
|
+
<ResponsiveButton {...rest} onClick={handleOpen} />
|
|
48
|
+
<EditBase
|
|
49
|
+
{...props}
|
|
50
|
+
id={record.id}
|
|
51
|
+
mutationMode="pessimistic"
|
|
52
|
+
mutationOptions={{
|
|
53
|
+
...mutationOptions,
|
|
54
|
+
onSuccess: handleSuccess
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
<Dialog
|
|
58
|
+
open={open}
|
|
59
|
+
onClose={handleClose}
|
|
60
|
+
fullWidth={fullWidth}
|
|
61
|
+
maxWidth={maxWidth}
|
|
62
|
+
fullScreen={fullScreen}
|
|
63
|
+
keepMounted={false}
|
|
64
|
+
>
|
|
65
|
+
{React.isValidElement(Child)
|
|
66
|
+
? React.cloneElement(Child, {
|
|
67
|
+
...Child.props,
|
|
68
|
+
modal: true,
|
|
69
|
+
toolbar: (
|
|
70
|
+
<Toolbar>
|
|
71
|
+
<Button variant="text" size="medium" label="ra.action.cancel" onClick={handleClose} />
|
|
72
|
+
<SaveButton type="button" />
|
|
73
|
+
</Toolbar>
|
|
74
|
+
)
|
|
75
|
+
})
|
|
76
|
+
: null}
|
|
77
|
+
</Dialog>
|
|
78
|
+
</EditBase>
|
|
106
79
|
</>
|
|
107
80
|
);
|
|
108
81
|
}
|
|
109
82
|
|
|
110
|
-
type EditInDialogButtonProps = EditControllerProps &
|
|
111
|
-
PropsWithChildren<{
|
|
112
|
-
fullWidth?: boolean;
|
|
113
|
-
maxWidth?: false | Breakpoint | undefined;
|
|
114
|
-
label?: string;
|
|
115
|
-
style?: React.CSSProperties;
|
|
116
|
-
}>;
|
|
117
|
-
|
|
118
83
|
export { EditInDialogButton };
|
|
119
84
|
export type { EditInDialogButtonProps };
|
package/src/playground/App.jsx
CHANGED
|
@@ -45,6 +45,7 @@ function App() {
|
|
|
45
45
|
<Resource name="entities/user" {...entities.user} />
|
|
46
46
|
<Resource name="entities/i18n-message" {...entities.i18nMessage} />
|
|
47
47
|
<Resource name="entities/device" {...entities.device} />
|
|
48
|
+
<Resource name="entities/category" {...entities.category} />
|
|
48
49
|
<CustomRoutes noLayout>
|
|
49
50
|
<Route path="/register" element={<RegisterPage name={APP_NAME} copy="Test" version={build.version} />} />
|
|
50
51
|
<Route path="/recover" element={<RecoverPage name={APP_NAME} copy="Test" version={build.version} />} />
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BooleanInput, SimpleForm, TextInput } from '@/';
|
|
2
|
+
|
|
3
|
+
function CategoryForm(props) {
|
|
4
|
+
return (
|
|
5
|
+
<SimpleForm {...props}>
|
|
6
|
+
<TextInput source="description" fullWidth />
|
|
7
|
+
<BooleanInput source="active" />
|
|
8
|
+
</SimpleForm>
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { CategoryForm };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { CategoryForm } from '@/playground/components';
|
|
2
|
+
import {
|
|
3
|
+
ActionsMenu,
|
|
4
|
+
CreateInDialogButton,
|
|
5
|
+
Datagrid,
|
|
6
|
+
EditInDialogButton,
|
|
7
|
+
Empty,
|
|
8
|
+
FilterButton,
|
|
9
|
+
List,
|
|
10
|
+
SearchInput,
|
|
11
|
+
SimpleForm,
|
|
12
|
+
TextField,
|
|
13
|
+
TextInput,
|
|
14
|
+
required
|
|
15
|
+
} from '@applica-software-guru/react-admin';
|
|
16
|
+
|
|
17
|
+
function CategoryAddButton() {
|
|
18
|
+
return (
|
|
19
|
+
<CreateInDialogButton maxWidth="sm" redirect="list" size="small" variant="text">
|
|
20
|
+
<CategoryForm />
|
|
21
|
+
</CreateInDialogButton>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function CategorySubmitButton() {
|
|
26
|
+
function handleSubmit(values) {
|
|
27
|
+
console.log(values);
|
|
28
|
+
}
|
|
29
|
+
return (
|
|
30
|
+
<CreateInDialogButton onSubmit={handleSubmit} redirect="list" label="Submit">
|
|
31
|
+
<SimpleForm>
|
|
32
|
+
<TextInput source="description" validate={required()} fullWidth />
|
|
33
|
+
</SimpleForm>
|
|
34
|
+
</CreateInDialogButton>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function CategoryList() {
|
|
39
|
+
return (
|
|
40
|
+
<List
|
|
41
|
+
filters={[<SearchInput key="keyword" source="keyword" alwaysOn />]}
|
|
42
|
+
actions={
|
|
43
|
+
<>
|
|
44
|
+
<FilterButton />
|
|
45
|
+
<ActionsMenu>
|
|
46
|
+
<CategoryAddButton />
|
|
47
|
+
<CategorySubmitButton />
|
|
48
|
+
</ActionsMenu>
|
|
49
|
+
</>
|
|
50
|
+
}
|
|
51
|
+
empty={<Empty actions={<CategoryAddButton />} />}
|
|
52
|
+
>
|
|
53
|
+
<Datagrid>
|
|
54
|
+
<TextField source="description" />
|
|
55
|
+
<EditInDialogButton>
|
|
56
|
+
<CategoryForm />
|
|
57
|
+
</EditInDialogButton>
|
|
58
|
+
</Datagrid>
|
|
59
|
+
</List>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
export { CategoryList };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Create, Edit } from '@/';
|
|
2
|
+
import { CategoryForm, CategoryList } from '@/playground/components';
|
|
3
|
+
|
|
4
|
+
function CategoryCreate() {
|
|
5
|
+
return (
|
|
6
|
+
<Create>
|
|
7
|
+
<CategoryForm />
|
|
8
|
+
</Create>
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function CategoryEdit() {
|
|
13
|
+
return (
|
|
14
|
+
<Edit>
|
|
15
|
+
<CategoryForm />
|
|
16
|
+
</Edit>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
export const category = {
|
|
20
|
+
list: CategoryList,
|
|
21
|
+
edit: CategoryEdit,
|
|
22
|
+
create: CategoryCreate,
|
|
23
|
+
options: {
|
|
24
|
+
group: 'control-panel'
|
|
25
|
+
}
|
|
26
|
+
};
|