muffin-admin 1.29.0 → 1.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +44 -0
- package/Makefile +7 -0
- package/dist/admin.js +82 -0
- package/dist/authprovider.js +250 -0
- package/dist/buttons/ActionButton.js +110 -0
- package/dist/buttons/LinkButton.js +44 -0
- package/dist/dashboard.js +70 -0
- package/dist/dataprovider.js +379 -0
- package/dist/fields/AvatarField.js +46 -0
- package/dist/fields/FKField.js +43 -0
- package/dist/fields/JsonField.js +51 -0
- package/dist/hooks/useAction.js +17 -0
- package/dist/index.js +20 -0
- package/dist/inputs/FKInput.js +53 -0
- package/dist/inputs/JsonInput.js +82 -0
- package/dist/resources.js +57 -0
- package/dist/ui.js +95 -0
- package/dist/utils.js +67 -0
- package/dist/views/create.js +25 -0
- package/dist/views/edit.js +53 -0
- package/dist/views/list.js +83 -0
- package/dist/views/show.js +36 -0
- package/dist/web.js +33 -0
- package/jsconfig.json +9 -0
- package/package.json +20 -8
- package/webpack.config.js +8 -6
- package/admin.jsx +0 -56
- package/authprovider.js +0 -79
- package/buttons/ActionButton.jsx +0 -68
- package/buttons/LinkButton.jsx +0 -21
- package/dashboard.jsx +0 -57
- package/dataprovider.js +0 -81
- package/fields/AvatarField.jsx +0 -25
- package/fields/FKField.jsx +0 -24
- package/index.js +0 -12
- package/inputs/FKInput.jsx +0 -30
- package/resources.jsx +0 -27
- package/ui.jsx +0 -51
- package/utils.js +0 -35
- package/views/create.jsx +0 -26
- package/views/edit.jsx +0 -34
- package/views/list.jsx +0 -56
- package/views/show.jsx +0 -34
package/authprovider.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import Cookies from 'js-cookie'
|
|
2
|
-
import { makeRequest, requestHeaders } from './utils';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export default (props) => {
|
|
6
|
-
|
|
7
|
-
const { identityURL, authorizeURL, logoutURL, required, storage, storage_name } = props;
|
|
8
|
-
|
|
9
|
-
const authorize = (name, value) => {
|
|
10
|
-
if (value === undefined) {
|
|
11
|
-
return storage == 'localstorage' ? localStorage.getItem(name) : Cookies.get(name);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (storage == 'localstorage') requestHeaders['Authorization'] = value;
|
|
15
|
-
storage == 'localstorage' ? localStorage.setItem(name, value) : Cookies.set(name, value);
|
|
16
|
-
return value;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Initialize request headers
|
|
20
|
-
authorize(storage_name, authorize(storage_name));
|
|
21
|
-
|
|
22
|
-
let getIdentity = async () => {
|
|
23
|
-
if (identityURL) {
|
|
24
|
-
let {json} = await makeRequest(identityURL);
|
|
25
|
-
return json;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (required) return {
|
|
30
|
-
|
|
31
|
-
getIdentity,
|
|
32
|
-
|
|
33
|
-
checkAuth: async (data) => {
|
|
34
|
-
const auth = authorize(storage_name);
|
|
35
|
-
if (!auth) throw {message: 'Authorization required'}
|
|
36
|
-
|
|
37
|
-
if (!identityURL) return auth;
|
|
38
|
-
|
|
39
|
-
let user = await getIdentity();
|
|
40
|
-
if (!user) throw {message: 'Authorization required'};
|
|
41
|
-
|
|
42
|
-
return user;
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
checkError: async (error) => {
|
|
46
|
-
const {message, status, body} = error;
|
|
47
|
-
|
|
48
|
-
if (status == 401 || status == 403) {
|
|
49
|
-
// Clean storage
|
|
50
|
-
authorize(storage_name, '');
|
|
51
|
-
|
|
52
|
-
throw {message: 'Invalid authorization', redirectTo: logoutURL, logoutUser: !logoutURL};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
login: async (data) => {
|
|
58
|
-
if (!authorizeURL) throw {message: 'Authorization is not supported'}
|
|
59
|
-
|
|
60
|
-
let {json} = await makeRequest(authorizeURL, {data, method: 'POST'})
|
|
61
|
-
authorize(storage_name, json);
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
logout: async () => {
|
|
65
|
-
|
|
66
|
-
// Clean storage
|
|
67
|
-
authorize(storage_name, '');
|
|
68
|
-
|
|
69
|
-
if (logoutURL) window.location = logoutURL;
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
getPermissions: (data) => {
|
|
73
|
-
const role = authorize(storage_name + '_role');
|
|
74
|
-
return role ? Promise.resolve(role) : Promise.reject();
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
}
|
package/buttons/ActionButton.jsx
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import { Button, CreateButton, useRefresh, useUnselectAll, useMutation, useNotify } from 'react-admin';
|
|
4
|
-
import * as icons from "@material-ui/icons"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export const BulkActionButton = ({label, icon, title, action, resource, selectedIds, ...props}) => {
|
|
8
|
-
const refresh = useRefresh(), unselectAll = useUnselectAll(),
|
|
9
|
-
notify = useNotify(), [mutate, { loading }] = useMutation(),
|
|
10
|
-
Icon = icons[icon];
|
|
11
|
-
|
|
12
|
-
let onClick = event => {
|
|
13
|
-
mutate({
|
|
14
|
-
resource,
|
|
15
|
-
type: 'runAction',
|
|
16
|
-
payload: {action, ids: selectedIds},
|
|
17
|
-
}, {
|
|
18
|
-
onSuccess: res => {
|
|
19
|
-
if (res && res.data && res.data.message) notify(res.data.message, 'success');
|
|
20
|
-
refresh();
|
|
21
|
-
unselectAll(resource);
|
|
22
|
-
},
|
|
23
|
-
onFailure: err => {
|
|
24
|
-
notify(typeof err === 'string' ? err : err.message, 'error')
|
|
25
|
-
}
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<Button label={ label } title={ title } onClick={ onClick } disabled={ loading }>
|
|
31
|
-
{ Icon && <Icon /> }
|
|
32
|
-
</Button>
|
|
33
|
-
)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const ActionButton = ({icon, label, title, record, resource, action}) => {
|
|
37
|
-
const refresh = useRefresh(), notify = useNotify(),
|
|
38
|
-
[mutate, { loading }] = useMutation(), Icon = icons[icon];
|
|
39
|
-
|
|
40
|
-
let onClick = event => {
|
|
41
|
-
mutate({
|
|
42
|
-
resource,
|
|
43
|
-
type: 'runAction',
|
|
44
|
-
payload: {action, record},
|
|
45
|
-
}, {
|
|
46
|
-
onSuccess: res => {
|
|
47
|
-
let data = res && res.data;
|
|
48
|
-
|
|
49
|
-
if (data && data.redirectTo) window.location = data.redirectTo;
|
|
50
|
-
if (data && data.message) notify(data.message, 'success');
|
|
51
|
-
|
|
52
|
-
refresh();
|
|
53
|
-
},
|
|
54
|
-
onFailure: err => {
|
|
55
|
-
notify(typeof err === 'string' ? err : err.message, 'error')
|
|
56
|
-
}
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<Button label={ label } title={ title } onClick={ onClick } disabled={ loading }>
|
|
62
|
-
{ Icon && <Icon /> }
|
|
63
|
-
</Button>
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export default ActionButton
|
package/buttons/LinkButton.jsx
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import { Button } from 'react-admin';
|
|
4
|
-
import { Link } from 'react-router-dom';
|
|
5
|
-
import * as icons from "@material-ui/icons"
|
|
6
|
-
|
|
7
|
-
// import LinkButton from '../buttons/LinkButton'
|
|
8
|
-
// <LinkButton label="Messages" icon="Message" resource="message" filters={{ user: data.id }} />
|
|
9
|
-
//
|
|
10
|
-
const LinkButton = ({label, icon, title, resource, filters, ...props}) => {
|
|
11
|
-
let Icon = icons[icon] || icon, linkParams = {pathname: `/${resource}`};
|
|
12
|
-
if (filters) linkParams.search = `filter=${JSON.stringify(filters)}`;
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<Button label={ label } title={ title } component={ Link } to={ linkParams }>
|
|
16
|
-
{ Icon && <Icon /> }
|
|
17
|
-
</Button>
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export default LinkButton
|
package/dashboard.jsx
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { Grid, Card, CardContent, Typography, Table, TableBody, TableRow, TableCell } from "@material-ui/core";
|
|
4
|
-
import ReactJSON from "react-json-view";
|
|
5
|
-
|
|
6
|
-
import { setupAdmin } from './utils';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const AdminTableView = ({src}) => (
|
|
10
|
-
<Table>
|
|
11
|
-
<TableBody>{
|
|
12
|
-
src.map((row, idx) =>
|
|
13
|
-
<TableRow key={ idx } hover>{
|
|
14
|
-
row.map((cell, idx) =>
|
|
15
|
-
<TableCell key={ idx }>{ cell }</TableCell>
|
|
16
|
-
)
|
|
17
|
-
}</TableRow>
|
|
18
|
-
)
|
|
19
|
-
}</TableBody>
|
|
20
|
-
</Table>
|
|
21
|
-
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
const AdminCard = ({ src }) => {
|
|
25
|
-
if (Array.isArray(src)) {
|
|
26
|
-
return (
|
|
27
|
-
<Grid container item spacing={ 2 }>
|
|
28
|
-
{ src.map((card, idx) => <AdminCard key={ idx } src={ card } />) }
|
|
29
|
-
</Grid>
|
|
30
|
-
)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
let {title, value} = src;
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<Grid item xs>
|
|
37
|
-
<Card>
|
|
38
|
-
<CardContent>
|
|
39
|
-
<Typography variant="h5" component="h2" m={ 2 } style={{ textAlign: 'center' }}>{title}</Typography>
|
|
40
|
-
{
|
|
41
|
-
Array.isArray(value) && <AdminTableView src={ value } /> || <ReactJSON src={ value } />
|
|
42
|
-
}
|
|
43
|
-
</CardContent>
|
|
44
|
-
</Card>
|
|
45
|
-
</Grid>
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Process dashboard
|
|
50
|
-
setupAdmin('dashboard', props => {
|
|
51
|
-
if (!props) return;
|
|
52
|
-
|
|
53
|
-
return () =>
|
|
54
|
-
<Grid container spacing={ 1 }>
|
|
55
|
-
<AdminCard src={ props } />
|
|
56
|
-
</Grid>
|
|
57
|
-
})
|
package/dataprovider.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { makeRequest } from './utils';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export default (apiUrl) => {
|
|
5
|
-
|
|
6
|
-
const methods = {
|
|
7
|
-
|
|
8
|
-
getList: async (resource, {filter, pagination, sort}) => {
|
|
9
|
-
const query = {};
|
|
10
|
-
if (filter) query.where = JSON.stringify(filter);
|
|
11
|
-
if (pagination) {
|
|
12
|
-
const {page, perPage: limit} = pagination;
|
|
13
|
-
query.limit = limit;
|
|
14
|
-
query.offset = limit * (page - 1);
|
|
15
|
-
}
|
|
16
|
-
if (sort) {
|
|
17
|
-
const {field, order} = sort;
|
|
18
|
-
query.sort = order == 'ASC' ? field : `-${field}`;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const {headers, json} = await makeRequest(`${apiUrl}/${resource}`, {query});
|
|
22
|
-
return {
|
|
23
|
-
data: json,
|
|
24
|
-
total: parseInt(headers.get('x-total'), 10),
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
getOne: async (resource, {id}) => {
|
|
30
|
-
const {json} = await makeRequest(`${apiUrl}/${resource}/${id}`);
|
|
31
|
-
return {data: json};
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
create: async (resource, {data}) => {
|
|
35
|
-
const {json} = await makeRequest(`${apiUrl}/${resource}`, {data, method: 'POST'});
|
|
36
|
-
return {data: json};
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
update: async (resource, {id, data}) => {
|
|
40
|
-
const {json} = await makeRequest(`${apiUrl}/${resource}/${id}`, {data, method: 'PUT'});
|
|
41
|
-
return {data: json};
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
updateMany: async (resource, {ids, data}) => {
|
|
45
|
-
await Promise.all(ids.map(id => methods.update(resource, {id, data})));
|
|
46
|
-
return {data: ids};
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
delete: async (resource, {id}) => {
|
|
50
|
-
const {json} = await makeRequest(`${apiUrl}/${resource}/${id}`, {method: 'DELETE'});
|
|
51
|
-
return {data: {id}};
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
deleteMany: async (resource, {ids}) => {
|
|
55
|
-
const {json} = await makeRequest(`${apiUrl}/${resource}`, {data: ids, method: 'DELETE'});
|
|
56
|
-
return {data: ids};
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
getMany: (resource, {ids}) => {
|
|
60
|
-
return methods.getList(resource, {filter: {id: {"$in": ids}}});
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
getManyReference: async (resource, {target, id, filter, ...opts}) => {
|
|
64
|
-
filter = filter || {};
|
|
65
|
-
filter[target] = id;
|
|
66
|
-
return await methods.getList(resource, {filter, ...opts});
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
runAction: async (resource, props) => {
|
|
70
|
-
let {action, payload, ids, record} = props;
|
|
71
|
-
action = action.replace(/^\/+/, '')
|
|
72
|
-
if (record) { action = action.replace(/\{([^}]+)\}/, (_, field) => record[field]) }
|
|
73
|
-
const {json} = await makeRequest(`${apiUrl}/${action}`, {query: {ids}, method: 'POST', data: payload});
|
|
74
|
-
return {data: json};
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
return methods;
|
|
80
|
-
|
|
81
|
-
}
|
package/fields/AvatarField.jsx
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import get from 'lodash/get';
|
|
4
|
-
import { useRecordContext } from 'ra-core';
|
|
5
|
-
import Avatar from '@material-ui/core/Avatar';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const AvatarField = ({ source, record, alt, style, nameProp, ...props }) => {
|
|
9
|
-
|
|
10
|
-
let sourceValue = get(record, source),
|
|
11
|
-
letters = null,
|
|
12
|
-
name = record[nameProp];
|
|
13
|
-
|
|
14
|
-
if (name) letters = name.trim(' ').split(/\s+/).slice(0, 2).map( n => n[0].toUpperCase() ).join('');
|
|
15
|
-
|
|
16
|
-
return <Avatar src={ record[source] } alt={ alt } style={ style }>{ letters }</Avatar>
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
AvatarField.displayName = 'AvatarField';
|
|
21
|
-
AvatarField.defaultProps = {
|
|
22
|
-
addLabel: true,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export default AvatarField;
|
package/fields/FKField.jsx
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { ReferenceField, TextField } from 'react-admin'
|
|
4
|
-
|
|
5
|
-
const FKField = ({refSource, refID, link, ...props}) => {
|
|
6
|
-
return (
|
|
7
|
-
<ReferenceField link={ link || 'show' } { ...props }>
|
|
8
|
-
<>
|
|
9
|
-
<TextField source={ refSource } />
|
|
10
|
-
{ " (#" }
|
|
11
|
-
<TextField source={ refID || 'id' } />
|
|
12
|
-
{ ")" }
|
|
13
|
-
</>
|
|
14
|
-
</ReferenceField>
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
FKField.displayName = 'FKField';
|
|
19
|
-
FKField.defaultProps = {
|
|
20
|
-
addLabel: true,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export default FKField;
|
|
24
|
-
|
package/index.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import ReactDOM from 'react-dom';
|
|
2
|
-
|
|
3
|
-
import { setupAdmin, processAdmin } from './utils.js'
|
|
4
|
-
|
|
5
|
-
import './admin.jsx';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let initAdmin = globalThis.initAdmin = (props) => ReactDOM.render(processAdmin('admin', props), document.getElementById('root'))
|
|
9
|
-
|
|
10
|
-
export { setupAdmin, processAdmin }
|
|
11
|
-
|
|
12
|
-
export default initAdmin
|
package/inputs/FKInput.jsx
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { ReferenceInput, AutocompleteInput } from 'react-admin'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const FKInput = ({refProp, refSource, ...props}) => {
|
|
7
|
-
|
|
8
|
-
let filterToQuery = search => {
|
|
9
|
-
let filters = {};
|
|
10
|
-
filters[refProp] = search;
|
|
11
|
-
return filters;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
refSource = refSource || 'id';
|
|
15
|
-
|
|
16
|
-
let renderText = record => {
|
|
17
|
-
let pk = record[refSource];
|
|
18
|
-
return pk && `${record[refProp]} (#${pk})` || "";
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<ReferenceInput { ...props } filterToQuery={ filterToQuery }>
|
|
23
|
-
<AutocompleteInput source={ refSource } optionText={ renderText } />
|
|
24
|
-
</ReferenceInput>
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export default FKInput;
|
package/resources.jsx
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { Resource } from "react-admin";
|
|
4
|
-
import * as icons from "@material-ui/icons"
|
|
5
|
-
|
|
6
|
-
import { checkParams, processAdmin, initRAItems, setupAdmin } from './utils'
|
|
7
|
-
|
|
8
|
-
import './views/list.jsx'
|
|
9
|
-
import './views/show.jsx'
|
|
10
|
-
import './views/edit.jsx'
|
|
11
|
-
import './views/create.jsx'
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// Initialize Resources Components
|
|
15
|
-
setupAdmin('resources', resources => resources.map(res => processAdmin('resource', res, res.name)));
|
|
16
|
-
|
|
17
|
-
// Initialize a resource's component
|
|
18
|
-
setupAdmin('resource', checkParams((props, res) => {
|
|
19
|
-
let { create, edit, icon, list, name, show, ...resProps } = props;
|
|
20
|
-
|
|
21
|
-
return <Resource key={ name } name={ name } icon={ icons[icon] }
|
|
22
|
-
create={ processAdmin('create', create, res) }
|
|
23
|
-
edit={ processAdmin('edit', edit, res) }
|
|
24
|
-
list={ processAdmin('list', list, res) }
|
|
25
|
-
show={ processAdmin('show', show, res) }
|
|
26
|
-
{ ...resProps } />;
|
|
27
|
-
}));
|
package/ui.jsx
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { required } from 'react-admin';
|
|
4
|
-
import { BooleanField, ChipField, DateField, EmailField, ImageField, FileField, NumberField, RichTextField, TextField, UrlField, SelectField, ArrayField, ReferenceField, ReferenceManyField, ReferenceArrayField } from "react-admin";
|
|
5
|
-
import { BooleanInput, NullableBooleanInput, DateInput, DateTimeInput, ImageInput, FileInput, NumberInput, PasswordInput, TextInput, AutocompleteInput, RadioButtonGroupInput, SelectInput, ArrayInput, AutocompleteArrayInput, CheckboxGroupInput, ReferenceArrayInput, ReferenceInput } from "react-admin";
|
|
6
|
-
import { JsonField, JsonInput } from "react-admin-json-view";
|
|
7
|
-
|
|
8
|
-
import AvatarField from "./fields/AvatarField.jsx"
|
|
9
|
-
import FKField from "./fields/FKField.jsx"
|
|
10
|
-
import FKInput from "./inputs/FKInput.jsx"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
// Fix JsonField
|
|
14
|
-
JsonField.displayName = 'JsonField';
|
|
15
|
-
JsonField.defaultProps = {
|
|
16
|
-
addLabel: true,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const ui = {
|
|
20
|
-
|
|
21
|
-
// Fields
|
|
22
|
-
BooleanField, ChipField, DateField, EmailField, ImageField, FileField,
|
|
23
|
-
NumberField, RichTextField, TextField, UrlField, SelectField, ArrayField,
|
|
24
|
-
ReferenceField, ReferenceManyField, ReferenceArrayField, AvatarField,
|
|
25
|
-
JsonField, FKField,
|
|
26
|
-
|
|
27
|
-
// Inputs
|
|
28
|
-
BooleanInput, NullableBooleanInput, DateInput, DateTimeInput, ImageInput,
|
|
29
|
-
FileInput, NumberInput, PasswordInput, TextInput, AutocompleteInput,
|
|
30
|
-
RadioButtonGroupInput, SelectInput, ArrayInput, AutocompleteArrayInput,
|
|
31
|
-
CheckboxGroupInput, ReferenceArrayInput, ReferenceInput, JsonInput, FKInput,
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const initRAItems = itemsProps => itemsProps.map((item) => {
|
|
36
|
-
const Item = ui[item[0]],
|
|
37
|
-
props = {...item[1]};
|
|
38
|
-
|
|
39
|
-
if (props.required) {
|
|
40
|
-
props.validate = required();
|
|
41
|
-
delete props.required
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
props.fullWidth = props.fullWidth ?? true
|
|
45
|
-
|
|
46
|
-
if (props.children) props.children = initRAItems(props.children)[0];
|
|
47
|
-
|
|
48
|
-
return <Item key={ props.source } { ...props } />
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
export default initRAItems
|
package/utils.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { fetchUtils } from 'ra-core';
|
|
4
|
-
import { stringify } from 'query-string';
|
|
5
|
-
import { required } from 'react-admin';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const admin = globalThis.admin = globalThis.admin || {};
|
|
9
|
-
|
|
10
|
-
export const setupAdmin = globalThis.setupAdmin = (type, fn) => admin[type] = fn
|
|
11
|
-
export const checkParams = (fn) => (props, res) => {
|
|
12
|
-
if (!props || React.isValidElement(props)) return props;
|
|
13
|
-
return fn(props, res);
|
|
14
|
-
}
|
|
15
|
-
export const processAdmin = (type, props, res) => {
|
|
16
|
-
let callbacks = [], result = props;
|
|
17
|
-
|
|
18
|
-
if (process.env.NODE_ENV == 'development') console.log(`${type}${ res ? '-' + res : ''}`, props);
|
|
19
|
-
|
|
20
|
-
if (admin[`${type}-${res}`]) return admin[`${type}-${res}`](props, res);
|
|
21
|
-
if (admin[type]) return admin[type](props, res);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const requestHeaders = {};
|
|
25
|
-
|
|
26
|
-
export const makeRequest = (url, params) => {
|
|
27
|
-
let {data, query, ...opts} = params || {};
|
|
28
|
-
|
|
29
|
-
if (data) opts.body = JSON.stringify(data);
|
|
30
|
-
if (query) url = `${url}?${stringify(query)}`;
|
|
31
|
-
|
|
32
|
-
opts = {...opts, headers: new Headers({...requestHeaders, ...opts.headers})}
|
|
33
|
-
|
|
34
|
-
return fetchUtils.fetchJson(url, opts);
|
|
35
|
-
}
|
package/views/create.jsx
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { Create, SimpleForm, TopToolbar, ListButton } from "react-admin";
|
|
4
|
-
|
|
5
|
-
import initRAItems from '../ui.jsx'
|
|
6
|
-
import { checkParams, processAdmin, setupAdmin } from '../utils'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// Initialize a create component
|
|
10
|
-
setupAdmin('create', checkParams((inputs, res) => props => {
|
|
11
|
-
|
|
12
|
-
const Actions = ({basePath}) => (
|
|
13
|
-
<TopToolbar>
|
|
14
|
-
<ListButton basePath={ basePath } />
|
|
15
|
-
</TopToolbar>
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<Create actions={ <Actions /> } {...props}>
|
|
20
|
-
<SimpleForm children={ processAdmin('create-inputs', inputs, res) } />
|
|
21
|
-
</Create>
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
));
|
|
25
|
-
setupAdmin('create-inputs', initRAItems);
|
|
26
|
-
|
package/views/edit.jsx
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { Edit, ListButton, ShowButton, SimpleForm, TopToolbar } from "react-admin";
|
|
4
|
-
|
|
5
|
-
import initRAItems from '../ui.jsx'
|
|
6
|
-
import { checkParams, processAdmin, setupAdmin } from '../utils'
|
|
7
|
-
|
|
8
|
-
import { ActionButton } from '../buttons/ActionButton.jsx'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// Initialize an edit component
|
|
12
|
-
setupAdmin('edit', checkParams(({actions, inputs}, res) => props => {
|
|
13
|
-
|
|
14
|
-
const Actions = ({basePath, data, resource, ...baseProps}) => (
|
|
15
|
-
<TopToolbar>
|
|
16
|
-
{
|
|
17
|
-
actions.map((props, idx) => {
|
|
18
|
-
let aProps = {resource, basePath, ...baseProps, ...props};
|
|
19
|
-
return <ActionButton key={ idx } {...aProps} />
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
<ListButton basePath={ basePath } />
|
|
23
|
-
<ShowButton basePath={basePath} record={data} />
|
|
24
|
-
</TopToolbar>
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<Edit actions={ <Actions /> } { ...props }>
|
|
29
|
-
<SimpleForm children={ processAdmin('edit-inputs', inputs, res) } />
|
|
30
|
-
</Edit>
|
|
31
|
-
)
|
|
32
|
-
}));
|
|
33
|
-
|
|
34
|
-
setupAdmin('edit-inputs', initRAItems);
|
package/views/list.jsx
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
BulkDeleteButton,
|
|
5
|
-
Datagrid,
|
|
6
|
-
EditButton,
|
|
7
|
-
Filter,
|
|
8
|
-
List,
|
|
9
|
-
Pagination,
|
|
10
|
-
Show,
|
|
11
|
-
} from "react-admin";
|
|
12
|
-
import uniq from "lodash/uniq";
|
|
13
|
-
import sortBy from "lodash/sortBy";
|
|
14
|
-
|
|
15
|
-
import initRAItems from '../ui.jsx'
|
|
16
|
-
import { checkParams, processAdmin, setupAdmin } from '../utils'
|
|
17
|
-
import { BulkActionButton } from '../buttons/ActionButton.jsx'
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const defaultPagination = <Pagination rowsPerPageOptions={[10, 25, 50, 100]} />;
|
|
21
|
-
|
|
22
|
-
// Initiliaze a list component
|
|
23
|
-
setupAdmin('list', checkParams((props, res) => {
|
|
24
|
-
let {children, filters, edit, pagination, show, limit, limitMax, actions, ...listProps } = props;
|
|
25
|
-
|
|
26
|
-
children = processAdmin('list-fields', children, res);
|
|
27
|
-
if (edit) children.push(<EditButton key="edit-button" />);
|
|
28
|
-
|
|
29
|
-
pagination = pagination || <Pagination rowsPerPageOptions={sortBy(uniq([10, 25, 50, 100, limit, limitMax]))} />
|
|
30
|
-
|
|
31
|
-
return props => {
|
|
32
|
-
let Filters = (props) => <Filter { ...props } children={ processAdmin('list-filters', filters, res) } />
|
|
33
|
-
let Actions = processAdmin('list-bulkActions', actions);
|
|
34
|
-
|
|
35
|
-
props = { ...props, ...listProps };
|
|
36
|
-
return (
|
|
37
|
-
<List filters={ <Filters /> } bulkActionButtons={ <Actions /> } perPage={ limit } pagination={ pagination || defaultPagination } { ...props }>
|
|
38
|
-
<Datagrid rowClick={ show ? "show" : null } children={ children } />
|
|
39
|
-
</List>
|
|
40
|
-
)
|
|
41
|
-
};
|
|
42
|
-
}));
|
|
43
|
-
|
|
44
|
-
setupAdmin('list-bulkActions', actions => props => {
|
|
45
|
-
let buttons = actions.map((action, idx) => {
|
|
46
|
-
let aProps = { ...action, ...props };
|
|
47
|
-
return <BulkActionButton key={idx} {...aProps} />
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
return <>
|
|
51
|
-
{ buttons }
|
|
52
|
-
<BulkDeleteButton {...props} />
|
|
53
|
-
</>
|
|
54
|
-
});
|
|
55
|
-
setupAdmin('list-filters', initRAItems);
|
|
56
|
-
setupAdmin('list-fields', initRAItems);
|
package/views/show.jsx
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { ListButton, EditButton, Show, SimpleShowLayout, TopToolbar } from "react-admin";
|
|
4
|
-
|
|
5
|
-
import initRAItems from '../ui.jsx'
|
|
6
|
-
import { checkParams, processAdmin, setupAdmin } from '../utils'
|
|
7
|
-
|
|
8
|
-
import { ActionButton } from '../buttons/ActionButton.jsx'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// Initiliaze a show component
|
|
12
|
-
setupAdmin('show', checkParams(({actions, fields}, res) => props => {
|
|
13
|
-
|
|
14
|
-
const Actions = ({basePath, data, resource, ...baseProps}) => (
|
|
15
|
-
<TopToolbar>
|
|
16
|
-
{
|
|
17
|
-
actions.map((props, idx) => {
|
|
18
|
-
let aProps = {resource, basePath, record: data, ...baseProps, ...props};
|
|
19
|
-
return <ActionButton key={ idx } {...aProps} />
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
<ListButton basePath={ basePath } />
|
|
23
|
-
<EditButton basePath={basePath} record={data} />
|
|
24
|
-
</TopToolbar>
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<Show actions={ <Actions /> } {...props}>
|
|
29
|
-
<SimpleShowLayout children={ processAdmin('show-fields', fields, res) } />
|
|
30
|
-
</Show>
|
|
31
|
-
)
|
|
32
|
-
}));
|
|
33
|
-
|
|
34
|
-
setupAdmin('show-fields', initRAItems);
|