@applica-software-guru/react-admin 1.5.262 → 1.5.264
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/ra-forms/TableForm/AddTableRow.d.ts +4 -0
- package/dist/components/ra-forms/TableForm/AddTableRow.d.ts.map +1 -0
- package/dist/components/ra-forms/TableForm/CreateButton.d.ts +12 -0
- package/dist/components/ra-forms/TableForm/CreateButton.d.ts.map +1 -0
- package/dist/components/ra-forms/TableForm/EditButton.d.ts +3 -0
- package/dist/components/ra-forms/TableForm/EditButton.d.ts.map +1 -0
- package/dist/components/ra-forms/TableForm/Field.d.ts +8 -0
- package/dist/components/ra-forms/TableForm/Field.d.ts.map +1 -0
- package/dist/components/ra-forms/TableForm/TableFormIterator.d.ts +97 -5
- package/dist/components/ra-forms/TableForm/TableFormIterator.d.ts.map +1 -1
- package/dist/components/ra-forms/TableForm/TableFormIteratorItem.d.ts +5 -2
- package/dist/components/ra-forms/TableForm/TableFormIteratorItem.d.ts.map +1 -1
- package/dist/components/ra-forms/TableForm/TableFormIteratorItemContext.d.ts +1 -0
- package/dist/components/ra-forms/TableForm/TableFormIteratorItemContext.d.ts.map +1 -1
- package/dist/components/ra-forms/TableForm/index.d.ts +4 -0
- package/dist/components/ra-forms/TableForm/index.d.ts.map +1 -1
- package/dist/react-admin.cjs.js +52 -52
- package/dist/react-admin.cjs.js.gz +0 -0
- package/dist/react-admin.cjs.js.map +1 -1
- package/dist/react-admin.es.js +8392 -8397
- package/dist/react-admin.es.js.gz +0 -0
- package/dist/react-admin.es.js.map +1 -1
- package/dist/react-admin.umd.js +51 -51
- package/dist/react-admin.umd.js.gz +0 -0
- package/dist/react-admin.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ra-forms/TableForm/AddTableRow.tsx +34 -0
- package/src/components/ra-forms/TableForm/CreateButton.tsx +58 -0
- package/src/components/ra-forms/TableForm/EditButton.tsx +42 -0
- package/src/components/ra-forms/TableForm/Field.tsx +23 -0
- package/src/components/ra-forms/TableForm/TableFormIterator.tsx +147 -65
- package/src/components/ra-forms/TableForm/TableFormIteratorItem.tsx +37 -7
- package/src/components/ra-forms/TableForm/TableFormIteratorItemContext.ts +1 -0
- package/src/components/ra-forms/TableForm/index.ts +4 -0
- package/src/components/ra-inputs/LabeledInput.tsx +1 -1
package/package.json
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { PlusCircleOutlined } from '@ant-design/icons';
|
|
2
|
+
import { IconButton, Stack, Typography, useTheme } from '@mui/material';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
function AddTableRow(props: any): JSX.Element {
|
|
6
|
+
const { label, disableAdd, onClick, inset } = props;
|
|
7
|
+
const theme = useTheme();
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
const tableBorderColor = theme.palette.mode === 'dark' ? theme.palette.grey.A400 : theme.palette.grey.A800;
|
|
10
|
+
const iconColor = theme.palette.mode === 'light' ? '#000000' : '#FFFFFF';
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<Stack
|
|
14
|
+
justifyContent={'space-between'}
|
|
15
|
+
alignItems={'center'}
|
|
16
|
+
flexDirection={'row'}
|
|
17
|
+
sx={inset ? { p: 2.5 } : { pt: 2 }}
|
|
18
|
+
>
|
|
19
|
+
{label !== false && <Typography>{label}</Typography>}
|
|
20
|
+
{!disableAdd &&
|
|
21
|
+
(React.isValidElement(props?.customButton) ? (
|
|
22
|
+
React.cloneElement(props?.customButton, {
|
|
23
|
+
onClick: onClick
|
|
24
|
+
})
|
|
25
|
+
) : (
|
|
26
|
+
<IconButton color="secondary" sx={{ border: `1px solid ${tableBorderColor}` }} onClick={onClick}>
|
|
27
|
+
<PlusCircleOutlined style={{ color: iconColor }} />
|
|
28
|
+
</IconButton>
|
|
29
|
+
))}
|
|
30
|
+
</Stack>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { AddTableRow };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { AddTableRow } from './AddTableRow';
|
|
2
|
+
import { Dialog } from '@mui/material';
|
|
3
|
+
import { CreateContextProvider, SaveHandler } from 'ra-core';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { useArrayInput } from 'react-admin';
|
|
6
|
+
|
|
7
|
+
interface CreateButtonProps {
|
|
8
|
+
label: string;
|
|
9
|
+
disableAdd?: boolean;
|
|
10
|
+
inset?: boolean;
|
|
11
|
+
source?: string;
|
|
12
|
+
template?: any;
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function CreateButton(props: CreateButtonProps): JSX.Element {
|
|
17
|
+
const { label, disableAdd, inset, source, template } = props;
|
|
18
|
+
const [open, setOpen] = React.useState(false);
|
|
19
|
+
const { append } = useArrayInput();
|
|
20
|
+
|
|
21
|
+
const toggleOpen = React.useCallback(() => {
|
|
22
|
+
setOpen((prev) => !prev);
|
|
23
|
+
}, [setOpen]);
|
|
24
|
+
|
|
25
|
+
const handleSave = React.useCallback(
|
|
26
|
+
(data: any) => {
|
|
27
|
+
setOpen(false);
|
|
28
|
+
append(data);
|
|
29
|
+
return Promise.resolve();
|
|
30
|
+
},
|
|
31
|
+
[setOpen, append]
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
{React.cloneElement(<AddTableRow />, {
|
|
37
|
+
label,
|
|
38
|
+
source,
|
|
39
|
+
disableAdd,
|
|
40
|
+
template,
|
|
41
|
+
onClick: toggleOpen,
|
|
42
|
+
inset
|
|
43
|
+
})}
|
|
44
|
+
<Dialog open={open} onClose={toggleOpen} maxWidth="xs">
|
|
45
|
+
<CreateContextProvider
|
|
46
|
+
// @ts-ignore
|
|
47
|
+
value={{
|
|
48
|
+
save: handleSave as SaveHandler<any>
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
{props.children}
|
|
52
|
+
</CreateContextProvider>
|
|
53
|
+
</Dialog>
|
|
54
|
+
</>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { CreateButton };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useTableFormIteratorItem } from './TableFormIteratorItemContext';
|
|
2
|
+
import { Button, Dialog } from '@mui/material';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { EditContextProvider, SaveHandler, useArrayInput, useTranslate } from 'react-admin';
|
|
5
|
+
|
|
6
|
+
function EditButton(props: any) {
|
|
7
|
+
const { children } = props;
|
|
8
|
+
const { item, index } = useTableFormIteratorItem();
|
|
9
|
+
const [open, setOpen] = React.useState(false);
|
|
10
|
+
const { update } = useArrayInput();
|
|
11
|
+
const translate = useTranslate();
|
|
12
|
+
|
|
13
|
+
const handleSave: SaveHandler<any> = React.useCallback(
|
|
14
|
+
(data) => {
|
|
15
|
+
setOpen(false);
|
|
16
|
+
update(index, data);
|
|
17
|
+
return Promise.resolve();
|
|
18
|
+
},
|
|
19
|
+
[index, update]
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<>
|
|
24
|
+
<Button color="primary" onClick={() => setOpen(true)} sx={{ justifyContent: 'flex-start' }}>
|
|
25
|
+
{translate('ra.action.edit')}
|
|
26
|
+
</Button>
|
|
27
|
+
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="xs" fullWidth>
|
|
28
|
+
<EditContextProvider
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
value={{
|
|
31
|
+
record: item,
|
|
32
|
+
save: handleSave
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</EditContextProvider>
|
|
37
|
+
</Dialog>
|
|
38
|
+
</>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { EditButton };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { Children } from 'react';
|
|
2
|
+
import { useRecordContext } from 'react-admin';
|
|
3
|
+
import { useFormContext } from 'react-hook-form';
|
|
4
|
+
|
|
5
|
+
interface FieldProps {
|
|
6
|
+
source: string;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface ChildProps {
|
|
11
|
+
source: string;
|
|
12
|
+
record: Record<string, any>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function Field({ source, children }: FieldProps): JSX.Element | null {
|
|
16
|
+
const Child = Children.only(children) as React.ReactElement<ChildProps>;
|
|
17
|
+
const { getValues } = useFormContext();
|
|
18
|
+
const record = useRecordContext({ record: getValues() });
|
|
19
|
+
|
|
20
|
+
return React.isValidElement(Child) ? React.cloneElement(Child, { source, record }) : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { Field };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { Field } from './Field';
|
|
2
|
+
import { AddTableRow } from './AddTableRow';
|
|
3
|
+
import { CreateButton } from './CreateButton';
|
|
4
|
+
import { EditButton } from './EditButton';
|
|
1
5
|
import { ActionsMenu } from '@/components/ActionsMenu';
|
|
2
6
|
import { TableFormIteratorContext } from '@/components/ra-forms/TableForm/TableFormIteratorContext';
|
|
3
7
|
import { TableFormIteratorItem } from '@/components/ra-forms/TableForm/TableFormIteratorItem';
|
|
4
|
-
import { PlusCircleOutlined } from '@ant-design/icons';
|
|
5
8
|
import {
|
|
6
|
-
IconButton,
|
|
7
9
|
Paper,
|
|
8
|
-
Stack,
|
|
9
10
|
SxProps,
|
|
10
11
|
Table,
|
|
11
12
|
TableBody,
|
|
@@ -16,23 +17,25 @@ import {
|
|
|
16
17
|
Typography
|
|
17
18
|
} from '@mui/material';
|
|
18
19
|
import { styled, useTheme } from '@mui/material/styles';
|
|
19
|
-
import
|
|
20
|
-
import { FormDataConsumer, RaRecord, useRecordContext, useTranslate, useTranslateLabel } from 'ra-core';
|
|
20
|
+
import { FormDataConsumer, RaRecord, useTranslate, useTranslateLabel } from 'ra-core';
|
|
21
21
|
import * as React from 'react';
|
|
22
22
|
import { Children, ReactElement, ReactNode, useCallback, useMemo, useRef, useState } from 'react';
|
|
23
23
|
import { Confirm, useArrayInput } from 'react-admin';
|
|
24
24
|
import { UseFieldArrayReturn, useFormContext } from 'react-hook-form';
|
|
25
|
+
import { Tooltip } from '@/components/@extended';
|
|
25
26
|
|
|
26
27
|
/**
|
|
28
|
+
* How to use TableFormIterator:
|
|
27
29
|
*
|
|
28
30
|
* @example
|
|
29
31
|
* <Grid container>
|
|
30
32
|
* <Grid item xs={12}>
|
|
31
33
|
* <ArrayInput label={false} source="descriptor.fields">
|
|
32
|
-
* <TableFormIterator
|
|
34
|
+
* <TableFormIterator label="Property catalog">
|
|
33
35
|
* <TextInput label="Name" source={'name'} validate={required()} />
|
|
34
|
-
* <TextInput source={'denomination'} helperText={false} />
|
|
36
|
+
* <TextInput label="Denomination" source={'denomination'} helperText={false} />
|
|
35
37
|
* <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
|
|
38
|
+
* {...}
|
|
36
39
|
* </TableFormIterator>
|
|
37
40
|
* </ArrayInput>
|
|
38
41
|
* </Grid>
|
|
@@ -50,15 +53,14 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
|
|
|
50
53
|
className,
|
|
51
54
|
empty,
|
|
52
55
|
template = {},
|
|
56
|
+
addButton = <AddTableRow />,
|
|
53
57
|
inset
|
|
54
58
|
} = props;
|
|
55
59
|
const [confirmIsOpen, setConfirmIsOpen] = useState<boolean>(false);
|
|
56
60
|
const { fields, remove, replace, append } = useArrayInput(props);
|
|
57
61
|
const { resetField } = useFormContext();
|
|
58
|
-
|
|
59
62
|
const theme = useTheme();
|
|
60
63
|
const translate = useTranslate();
|
|
61
|
-
const record = useRecordContext(props);
|
|
62
64
|
const initialDefaultValue = useRef(template || {});
|
|
63
65
|
|
|
64
66
|
const translateLabel = useTranslateLabel();
|
|
@@ -129,9 +131,6 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
|
|
|
129
131
|
setConfirmIsOpen(false);
|
|
130
132
|
}, [replace]);
|
|
131
133
|
|
|
132
|
-
// @ts-ignore
|
|
133
|
-
const records = get(record, source);
|
|
134
|
-
|
|
135
134
|
const context = useMemo(
|
|
136
135
|
() => ({
|
|
137
136
|
total: fields.length,
|
|
@@ -149,12 +148,15 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
|
|
|
149
148
|
// @ts-ignore
|
|
150
149
|
<TableFormIteratorContext.Provider value={context}>
|
|
151
150
|
<div className={className}>
|
|
152
|
-
{React.cloneElement(
|
|
151
|
+
{React.cloneElement(addButton, {
|
|
153
152
|
label,
|
|
154
153
|
source,
|
|
155
154
|
disableAdd,
|
|
156
155
|
template,
|
|
157
|
-
onClick:
|
|
156
|
+
onClick:
|
|
157
|
+
addButton?.type !== CreateButton
|
|
158
|
+
? handleAddButtonClick((props?.addButton as any)?.props?.onClick)
|
|
159
|
+
: undefined,
|
|
158
160
|
inset
|
|
159
161
|
})}
|
|
160
162
|
|
|
@@ -173,30 +175,44 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
|
|
|
173
175
|
<TableRow>
|
|
174
176
|
{/** @ts-ignore */}
|
|
175
177
|
{Children.map(children, (input: ReactElement, index) => {
|
|
178
|
+
if (input.type === EditButton) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
176
181
|
if (!React.isValidElement<any>(input)) {
|
|
177
182
|
return null;
|
|
178
183
|
}
|
|
184
|
+
|
|
185
|
+
const columnText = (
|
|
186
|
+
<Typography display={'flex'} variant="subtitle1" color="text.primary" textTransform="none">
|
|
187
|
+
{translateLabel({ ...input.props, resource })}
|
|
188
|
+
</Typography>
|
|
189
|
+
);
|
|
190
|
+
|
|
179
191
|
return (
|
|
180
192
|
<TableCell key={index}>
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
193
|
+
{input.props.title ? (
|
|
194
|
+
// @ts-ignore
|
|
195
|
+
<Tooltip title={input.props.title} arrow>
|
|
196
|
+
{columnText}
|
|
197
|
+
</Tooltip>
|
|
198
|
+
) : (
|
|
199
|
+
columnText
|
|
200
|
+
)}
|
|
184
201
|
</TableCell>
|
|
185
202
|
);
|
|
186
203
|
})}
|
|
187
204
|
|
|
188
|
-
{!disableRemove &&
|
|
189
|
-
|
|
190
|
-
<
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
))}
|
|
205
|
+
{!disableRemove && showClearAllButton ? (
|
|
206
|
+
<TableCell key="actions" sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
|
207
|
+
<ActionsMenu horizontal>
|
|
208
|
+
<Typography color="error" onClick={() => setConfirmIsOpen(true)}>
|
|
209
|
+
{translate('ra.action.delete')}
|
|
210
|
+
</Typography>
|
|
211
|
+
</ActionsMenu>
|
|
212
|
+
</TableCell>
|
|
213
|
+
) : (
|
|
214
|
+
<TableCell key="empty_actions" />
|
|
215
|
+
)}
|
|
200
216
|
</TableRow>
|
|
201
217
|
</TableHead>
|
|
202
218
|
|
|
@@ -223,7 +239,7 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
|
|
|
223
239
|
index={index}
|
|
224
240
|
member={`${source}.${index}`}
|
|
225
241
|
onRemoveField={removeField}
|
|
226
|
-
record={(
|
|
242
|
+
record={(fields && fields[index]) || {}}
|
|
227
243
|
// @ts-ignore
|
|
228
244
|
resource={resource}
|
|
229
245
|
// @ts-ignore
|
|
@@ -251,35 +267,6 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
|
|
|
251
267
|
) : null;
|
|
252
268
|
}
|
|
253
269
|
|
|
254
|
-
function AddTableRow(props: any): JSX.Element {
|
|
255
|
-
const { label, disableAdd, onClick, inset } = props;
|
|
256
|
-
const theme = useTheme();
|
|
257
|
-
// @ts-ignore
|
|
258
|
-
const tableBorderColor = theme.palette.mode === 'dark' ? theme.palette.grey.A400 : theme.palette.grey.A800;
|
|
259
|
-
const iconColor = theme.palette.mode === 'light' ? '#000000' : '#FFFFFF';
|
|
260
|
-
|
|
261
|
-
return (
|
|
262
|
-
<Stack
|
|
263
|
-
justifyContent={'space-between'}
|
|
264
|
-
alignItems={'center'}
|
|
265
|
-
flexDirection={'row'}
|
|
266
|
-
sx={inset ? { p: 2.5 } : { pt: 2 }}
|
|
267
|
-
>
|
|
268
|
-
{label !== false && <Typography>{label}</Typography>}
|
|
269
|
-
{!disableAdd &&
|
|
270
|
-
(React.isValidElement(props?.addButton) ? (
|
|
271
|
-
React.cloneElement(props?.addButton, {
|
|
272
|
-
onClick: onClick
|
|
273
|
-
})
|
|
274
|
-
) : (
|
|
275
|
-
<IconButton color="secondary" sx={{ border: `1px solid ${tableBorderColor}` }} onClick={onClick}>
|
|
276
|
-
<PlusCircleOutlined style={{ color: iconColor }} />
|
|
277
|
-
</IconButton>
|
|
278
|
-
))}
|
|
279
|
-
</Stack>
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
270
|
const TableFormIterator = styled(RawTableFormIterator, { slot: 'Root' })(({ theme }) => ({
|
|
284
271
|
'& > div.MuiPaper-root': {
|
|
285
272
|
overflowX: 'auto',
|
|
@@ -302,12 +289,23 @@ interface TableFormIteratorProps extends Partial<UseFieldArrayReturn> {
|
|
|
302
289
|
disableAdd?: boolean;
|
|
303
290
|
disableRemove?: boolean;
|
|
304
291
|
enableClearAll?: boolean;
|
|
292
|
+
/**
|
|
293
|
+
* Adding the template prop will allow to set a default value for the new row.
|
|
294
|
+
*
|
|
295
|
+
* @example
|
|
296
|
+
* <Grid container>
|
|
297
|
+
* <Grid item xs={12}>
|
|
298
|
+
* <ArrayInput label={false} source="descriptor.fields">
|
|
299
|
+
* <TableFormIterator template={{ property: 'FIELD' }} label="Property catalog">
|
|
300
|
+
* <TextInput label="Name" source={'name'} validate={required()} />
|
|
301
|
+
* <TextInput source={'denomination'} helperText={false} />
|
|
302
|
+
* <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
|
|
303
|
+
* </TableFormIterator>
|
|
304
|
+
* </ArrayInput>
|
|
305
|
+
* </Grid>
|
|
306
|
+
* </Grid>
|
|
307
|
+
*/
|
|
305
308
|
template?: object;
|
|
306
|
-
meta?: {
|
|
307
|
-
// the type defined in FieldArrayRenderProps says error is boolean, which is wrong.
|
|
308
|
-
error?: any;
|
|
309
|
-
submitFailed?: boolean;
|
|
310
|
-
};
|
|
311
309
|
record?: RaRecord;
|
|
312
310
|
label?: string | boolean;
|
|
313
311
|
resource?: string;
|
|
@@ -317,5 +315,89 @@ interface TableFormIteratorProps extends Partial<UseFieldArrayReturn> {
|
|
|
317
315
|
inset?: boolean;
|
|
318
316
|
}
|
|
319
317
|
|
|
320
|
-
|
|
318
|
+
type ITableForm = typeof TableFormIterator & {
|
|
319
|
+
/**
|
|
320
|
+
* TableFormiterator allows to insert an addButton which will render the default btn and open a dialog with the form fields passed as children.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* <Grid container>
|
|
324
|
+
* <Grid item xs={12}>
|
|
325
|
+
* <ArrayInput label={false} source="descriptor.fields">
|
|
326
|
+
* <TableFormIterator
|
|
327
|
+
* addButton={<TableFormIterator.CreateButton>
|
|
328
|
+
* <TextInput label="Name" source={'name'} validate={required()} />
|
|
329
|
+
* <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
|
|
330
|
+
* </TableFormIterator.CreateButton>}
|
|
331
|
+
* label="Property catalog">
|
|
332
|
+
* <TextInput label="Name" source={'name'} validate={required()} />
|
|
333
|
+
* <TextInput label="Denomination" source={'denomination'} helperText={false} />
|
|
334
|
+
* <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
|
|
335
|
+
* </TableFormIterator>
|
|
336
|
+
* </ArrayInput>
|
|
337
|
+
* </Grid>
|
|
338
|
+
* </Grid>
|
|
339
|
+
*/
|
|
340
|
+
CreateButton: typeof CreateButton;
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* TableFormiterator allows a child EditButton which will render an edit button in the ActionsMenu of each row.
|
|
344
|
+
* The EditButton will open a dialog with the form fields passed as children.
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* <Grid container>
|
|
348
|
+
* <Grid item xs={12}>
|
|
349
|
+
* <ArrayInput label={false} source="descriptor.fields">
|
|
350
|
+
* <TableFormIterator label="Property catalog">
|
|
351
|
+
*
|
|
352
|
+
* <TableFormIterator.EditButton>
|
|
353
|
+
* <TextInput label="Name" source={'name'} validate={required()} />
|
|
354
|
+
* <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
|
|
355
|
+
* </TableFormIterator.EditButton>
|
|
356
|
+
*
|
|
357
|
+
* <TextInput label="Name" source={'name'} validate={required()} />
|
|
358
|
+
* <TextInput label="Denomination" source={'denomination'} helperText={false} />
|
|
359
|
+
* <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
|
|
360
|
+
* </TableFormIterator>
|
|
361
|
+
* </ArrayInput>
|
|
362
|
+
* </Grid>
|
|
363
|
+
* </Grid>
|
|
364
|
+
*/
|
|
365
|
+
EditButton: typeof EditButton;
|
|
366
|
+
/**
|
|
367
|
+
* TableFormiterator allows a child Field which will render a read-only field in the Table with a custom record context.
|
|
368
|
+
* The record context will overwritthe by getValues() of useFormContext() hook.
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* <Grid container>
|
|
372
|
+
* <Grid item xs={12}>
|
|
373
|
+
* <ArrayInput label={false} source="descriptor.fields">
|
|
374
|
+
* <TableFormIterator label="Property catalog">
|
|
375
|
+
*
|
|
376
|
+
* <TableFormIterator.EditButton>
|
|
377
|
+
* <TextInput label="Name" source={'name'} validate={required()} />
|
|
378
|
+
* <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
|
|
379
|
+
* </TableFormIterator.EditButton>
|
|
380
|
+
*
|
|
381
|
+
* <TableFormIterator.Field source="name">
|
|
382
|
+
* <TextField />
|
|
383
|
+
* </TableFormIterator.Field>
|
|
384
|
+
* <TableFormIterator.Field source="type">
|
|
385
|
+
* <TextField />
|
|
386
|
+
* </TableFormIterator.Field>
|
|
387
|
+
* {...}
|
|
388
|
+
* </TableFormIterator>
|
|
389
|
+
* </ArrayInput>
|
|
390
|
+
* </Grid>
|
|
391
|
+
* </Grid>
|
|
392
|
+
*/
|
|
393
|
+
Field: typeof Field;
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const DefaultTableForm = TableFormIterator as ITableForm;
|
|
397
|
+
|
|
398
|
+
DefaultTableForm.CreateButton = CreateButton;
|
|
399
|
+
DefaultTableForm.EditButton = EditButton;
|
|
400
|
+
DefaultTableForm.Field = Field;
|
|
401
|
+
|
|
402
|
+
export { DefaultTableForm as TableFormIterator };
|
|
321
403
|
export type { TableFormIteratorProps };
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
+
import { EditButton } from './EditButton';
|
|
1
2
|
import { ActionsMenu } from '@/components/ActionsMenu';
|
|
2
3
|
import { useTableFormIterator } from '@/components/ra-forms/TableForm/TableFormIteratorContext';
|
|
3
4
|
import {
|
|
4
5
|
TableFormIteratorItemContext,
|
|
5
6
|
TableFormIteratorItemContextValue
|
|
6
7
|
} from '@/components/ra-forms/TableForm/TableFormIteratorItemContext';
|
|
7
|
-
import { Stack, TableCell
|
|
8
|
+
import { Button, Stack, TableCell } from '@mui/material';
|
|
8
9
|
import { RaRecord } from 'ra-core';
|
|
9
10
|
import { Children, ReactElement, ReactNode, cloneElement, isValidElement, useMemo } from 'react';
|
|
10
11
|
import * as React from 'react';
|
|
11
12
|
import { Confirm, useTranslate } from 'react-admin';
|
|
12
13
|
|
|
13
14
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
14
|
-
|
|
15
|
-
const { children, disabled, disableRemove = false, index, member, resource } = props;
|
|
15
|
+
const TableFormIteratorItem = React.forwardRef((props: TableFormIteratorItemProps, _: any) => {
|
|
16
|
+
const { children, disabled, disableRemove = false, index, member, resource, record } = props;
|
|
16
17
|
const translate = useTranslate();
|
|
17
18
|
const [confirmIsOpen, setConfirmIsOpen] = React.useState<boolean>(false);
|
|
18
19
|
const { total, remove } = useTableFormIterator();
|
|
@@ -27,15 +28,31 @@ export const TableFormIteratorItem = React.forwardRef((props: TableFormIteratorI
|
|
|
27
28
|
() => ({
|
|
28
29
|
index,
|
|
29
30
|
total,
|
|
31
|
+
item: record,
|
|
30
32
|
remove: () => remove(index)
|
|
31
33
|
}),
|
|
32
|
-
[index, total, remove]
|
|
34
|
+
[index, total, remove, record]
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const renderEditButton = useMemo(
|
|
38
|
+
() =>
|
|
39
|
+
Children.map(children, (Child) => {
|
|
40
|
+
if (isValidElement(Child) && Child?.type === EditButton) {
|
|
41
|
+
return React.isValidElement(Child) ? Child : null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return null;
|
|
45
|
+
}),
|
|
46
|
+
[children]
|
|
33
47
|
);
|
|
34
48
|
|
|
35
49
|
return (
|
|
36
50
|
<TableFormIteratorItemContext.Provider value={context}>
|
|
37
51
|
{/** @ts-ignore */}
|
|
38
52
|
{Children.map(children, (input: ReactElement, index2) => {
|
|
53
|
+
if (input.type === EditButton) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
39
56
|
if (!isValidElement<any>(input)) {
|
|
40
57
|
return null;
|
|
41
58
|
}
|
|
@@ -58,13 +75,22 @@ export const TableFormIteratorItem = React.forwardRef((props: TableFormIteratorI
|
|
|
58
75
|
<TableCell>
|
|
59
76
|
<Stack direction="row" spacing={1} justifyContent="center" alignItems="center">
|
|
60
77
|
<ActionsMenu horizontal>
|
|
61
|
-
<
|
|
78
|
+
<Button onClick={() => setConfirmIsOpen(true)} color="error" sx={{ justifyContent: 'flex-start' }}>
|
|
62
79
|
{translate('ra.action.delete')}
|
|
63
|
-
</
|
|
80
|
+
</Button>
|
|
81
|
+
{renderEditButton}
|
|
64
82
|
</ActionsMenu>
|
|
65
83
|
</Stack>
|
|
66
84
|
</TableCell>
|
|
67
85
|
)}
|
|
86
|
+
{disableRemove && renderEditButton ? (
|
|
87
|
+
<TableCell>
|
|
88
|
+
<Stack direction="row" spacing={1} justifyContent="center" alignItems="center">
|
|
89
|
+
<ActionsMenu horizontal>{renderEditButton}</ActionsMenu>
|
|
90
|
+
</Stack>
|
|
91
|
+
</TableCell>
|
|
92
|
+
) : null}
|
|
93
|
+
|
|
68
94
|
{/** @ts-ignore */}
|
|
69
95
|
{children.length > 0 && (
|
|
70
96
|
<Confirm
|
|
@@ -79,7 +105,7 @@ export const TableFormIteratorItem = React.forwardRef((props: TableFormIteratorI
|
|
|
79
105
|
);
|
|
80
106
|
});
|
|
81
107
|
|
|
82
|
-
|
|
108
|
+
type TableFormIteratorItemProps = {
|
|
83
109
|
children?: ReactNode;
|
|
84
110
|
disabled?: boolean;
|
|
85
111
|
disableRemove?: boolean;
|
|
@@ -88,6 +114,10 @@ export type TableFormIteratorItemProps = {
|
|
|
88
114
|
onRemoveField: (index: number) => void;
|
|
89
115
|
record: RaRecord;
|
|
90
116
|
removeButton?: ReactElement;
|
|
117
|
+
editAction?: ReactElement;
|
|
91
118
|
resource: string;
|
|
92
119
|
source: string;
|
|
93
120
|
};
|
|
121
|
+
|
|
122
|
+
export { TableFormIteratorItem };
|
|
123
|
+
export type { TableFormIteratorItemProps };
|