muffin-admin 1.36.4 → 1.36.6
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/esm/admin.js +71 -0
- package/dist/esm/authprovider.js +191 -0
- package/dist/esm/buttons/ActionButton.js +81 -0
- package/dist/esm/buttons/LinkButton.js +23 -0
- package/dist/esm/dashboard.js +60 -0
- package/dist/esm/dataprovider.js +296 -0
- package/dist/esm/fields/AvatarField.js +29 -0
- package/dist/esm/fields/FKField.js +27 -0
- package/dist/esm/fields/JsonField.js +28 -0
- package/dist/esm/hooks/useAction.js +8 -0
- package/dist/esm/index.js +40 -0
- package/dist/esm/inputs/FKInput.js +33 -0
- package/dist/esm/inputs/JsonInput.js +63 -0
- package/dist/esm/resources.js +38 -0
- package/dist/esm/ui.js +71 -0
- package/dist/esm/utils.js +38 -0
- package/dist/esm/views/create.js +16 -0
- package/dist/esm/views/edit.js +37 -0
- package/dist/esm/views/list.js +64 -0
- package/dist/esm/views/show.js +26 -0
- package/dist/esm/web.js +2 -0
- package/package.json +7 -11
- package/src/admin.jsx +78 -0
- package/src/authprovider.js +85 -0
- package/src/buttons/ActionButton.jsx +99 -0
- package/src/buttons/LinkButton.jsx +20 -0
- package/src/dashboard.jsx +74 -0
- package/src/dataprovider.js +94 -0
- package/src/fields/AvatarField.jsx +33 -0
- package/src/fields/FKField.jsx +27 -0
- package/src/fields/JsonField.jsx +26 -0
- package/src/hooks/useAction.js +9 -0
- package/src/index.js +14 -0
- package/src/inputs/FKInput.jsx +41 -0
- package/src/inputs/JsonInput.jsx +62 -0
- package/src/resources.jsx +36 -0
- package/src/ui.jsx +107 -0
- package/src/utils.js +38 -0
- package/src/views/create.jsx +30 -0
- package/src/views/edit.jsx +41 -0
- package/src/views/list.jsx +86 -0
- package/src/views/show.jsx +42 -0
- package/src/web.js +3 -0
- package/.eslintrc.json +0 -44
- package/Makefile +0 -18
- package/jsconfig.json +0 -9
- package/webpack.config.js +0 -45
- /package/dist/{admin.js → cjs/admin.js} +0 -0
- /package/dist/{authprovider.js → cjs/authprovider.js} +0 -0
- /package/dist/{buttons → cjs/buttons}/ActionButton.js +0 -0
- /package/dist/{buttons → cjs/buttons}/LinkButton.js +0 -0
- /package/dist/{dashboard.js → cjs/dashboard.js} +0 -0
- /package/dist/{dataprovider.js → cjs/dataprovider.js} +0 -0
- /package/dist/{fields → cjs/fields}/AvatarField.js +0 -0
- /package/dist/{fields → cjs/fields}/FKField.js +0 -0
- /package/dist/{fields → cjs/fields}/JsonField.js +0 -0
- /package/dist/{hooks → cjs/hooks}/useAction.js +0 -0
- /package/dist/{index.js → cjs/index.js} +0 -0
- /package/dist/{inputs → cjs/inputs}/FKInput.js +0 -0
- /package/dist/{inputs → cjs/inputs}/JsonInput.js +0 -0
- /package/dist/{resources.js → cjs/resources.js} +0 -0
- /package/dist/{ui.js → cjs/ui.js} +0 -0
- /package/dist/{utils.js → cjs/utils.js} +0 -0
- /package/dist/{views → cjs/views}/create.js +0 -0
- /package/dist/{views → cjs/views}/edit.js +0 -0
- /package/dist/{views → cjs/views}/list.js +0 -0
- /package/dist/{views → cjs/views}/show.js +0 -0
- /package/dist/{web.js → cjs/web.js} +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { ReferenceField, TextField } from "react-admin"
|
|
3
|
+
|
|
4
|
+
const FKField = ({ refSource, refID, link, reference, source, ...props }) => {
|
|
5
|
+
return (
|
|
6
|
+
<ReferenceField
|
|
7
|
+
link={link || "show"}
|
|
8
|
+
reference={reference}
|
|
9
|
+
source={source}
|
|
10
|
+
{...props}
|
|
11
|
+
>
|
|
12
|
+
<>
|
|
13
|
+
<TextField source={refSource} />
|
|
14
|
+
{" (#"}
|
|
15
|
+
<TextField source={refID || "id"} />
|
|
16
|
+
{")"}
|
|
17
|
+
</>
|
|
18
|
+
</ReferenceField>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
FKField.displayName = "FKField"
|
|
23
|
+
FKField.defaultProps = {
|
|
24
|
+
addLabel: true,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default FKField
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import get from "lodash/get"
|
|
2
|
+
|
|
3
|
+
import React, { useState } from "react"
|
|
4
|
+
import { Button, FunctionField, useRecordContext } from "react-admin"
|
|
5
|
+
|
|
6
|
+
export default function JsonField({ label, source }) {
|
|
7
|
+
const [expand, setExpand] = useState(false)
|
|
8
|
+
const record = useRecordContext()
|
|
9
|
+
const src = JSON.stringify(get(record, source), null, 2)
|
|
10
|
+
const retval = (
|
|
11
|
+
<div>
|
|
12
|
+
<p></p>
|
|
13
|
+
{label}
|
|
14
|
+
<Button
|
|
15
|
+
variant="contained"
|
|
16
|
+
color="primary"
|
|
17
|
+
size="small"
|
|
18
|
+
label={expand ? "colapse" : "expand"}
|
|
19
|
+
onClick={() => setExpand(!expand)}
|
|
20
|
+
/>
|
|
21
|
+
<p>{expand && <pre>{src}</pre>}</p>
|
|
22
|
+
</div>
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
return <FunctionField render={() => retval} />
|
|
26
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useDataProvider } from "react-admin"
|
|
2
|
+
import { useMutation } from "react-query"
|
|
3
|
+
|
|
4
|
+
export default function useAction(resource, action) {
|
|
5
|
+
const dataProvider = useDataProvider()
|
|
6
|
+
return useMutation((params) =>
|
|
7
|
+
dataProvider.runAction(resource, action, params)
|
|
8
|
+
)
|
|
9
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createRoot } from "react-dom/client"
|
|
2
|
+
|
|
3
|
+
import "./admin"
|
|
4
|
+
import { processAdmin } from "./utils"
|
|
5
|
+
|
|
6
|
+
export * from "./utils"
|
|
7
|
+
|
|
8
|
+
export async function initAdmin(prefix = "") {
|
|
9
|
+
const response = await fetch(`${prefix}/ra.json`)
|
|
10
|
+
const props = await response.json()
|
|
11
|
+
const container = document.getElementById("root")
|
|
12
|
+
const root = createRoot(container)
|
|
13
|
+
root.render(processAdmin("admin", props))
|
|
14
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { ReferenceInput, AutocompleteInput } from "react-admin"
|
|
3
|
+
|
|
4
|
+
const FKInput = ({
|
|
5
|
+
refProp,
|
|
6
|
+
refSource,
|
|
7
|
+
fullWidth,
|
|
8
|
+
reference,
|
|
9
|
+
source,
|
|
10
|
+
...props
|
|
11
|
+
}) => {
|
|
12
|
+
let filterToQuery = (search) => {
|
|
13
|
+
let filters = {}
|
|
14
|
+
filters[refProp] = search
|
|
15
|
+
return filters
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
refSource = refSource || "id"
|
|
19
|
+
|
|
20
|
+
let renderText = (record) => {
|
|
21
|
+
let pk = record[refSource]
|
|
22
|
+
return (pk && `${record[refProp]} (#${pk})`) || ""
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<ReferenceInput
|
|
27
|
+
reference={reference}
|
|
28
|
+
source={source}
|
|
29
|
+
filterToQuery={filterToQuery}
|
|
30
|
+
{...props}
|
|
31
|
+
>
|
|
32
|
+
<AutocompleteInput
|
|
33
|
+
source={refSource}
|
|
34
|
+
optionText={renderText}
|
|
35
|
+
fullWidth={fullWidth}
|
|
36
|
+
/>
|
|
37
|
+
</ReferenceInput>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default FKInput
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { TextInput } from "react-admin"
|
|
3
|
+
import isJSON from "validator/lib/isJSON"
|
|
4
|
+
|
|
5
|
+
const DEFAULT_ERRORTEXT = "Invalid JSON"
|
|
6
|
+
|
|
7
|
+
const parseFunction = (json) => {
|
|
8
|
+
let retval = json
|
|
9
|
+
try {
|
|
10
|
+
retval = JSON.parse(json)
|
|
11
|
+
} finally {
|
|
12
|
+
return retval
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
* `JsonInput` validates if the entered value is JSON or not. If entered value is not a invalid JSON, `JsonInput` will throw an error.
|
|
19
|
+
* Default error message is: `Invalid JSON` and can be overridden using `errortext` prop.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* <JsonInput source='config' label='JSON Config' errortext='Enter a valid JSON'/>
|
|
23
|
+
*
|
|
24
|
+
* or use translate function:
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* <JsonInput source='config' label={translate('resources.resource_name.fields.config')} errortext={translate('myroot.validate.json')}/>
|
|
28
|
+
*
|
|
29
|
+
* By default, `JsonInput` parses and returns the entered string as object. Instead, to send string directly, please pass `parse` prop as `false`
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* <JsonInput source='config' label='JSON Config' parse={false}/>
|
|
33
|
+
*/
|
|
34
|
+
export default function JsonInput(props) {
|
|
35
|
+
const {
|
|
36
|
+
validate = [],
|
|
37
|
+
errortext = DEFAULT_ERRORTEXT,
|
|
38
|
+
multiline = true,
|
|
39
|
+
parse = true,
|
|
40
|
+
...rest
|
|
41
|
+
} = props
|
|
42
|
+
// const errorobj = { message: errortext }
|
|
43
|
+
|
|
44
|
+
const validateJSON = (value) => {
|
|
45
|
+
if (!value || typeof value === "object") return undefined
|
|
46
|
+
return isJSON(value) ? undefined : errortext
|
|
47
|
+
}
|
|
48
|
+
validate.push(validateJSON)
|
|
49
|
+
rest.validate = validate
|
|
50
|
+
|
|
51
|
+
const formatJSON = (json) => {
|
|
52
|
+
let retval = json
|
|
53
|
+
if (retval && typeof retval === "object")
|
|
54
|
+
retval = JSON.stringify(retval, null, 2)
|
|
55
|
+
return retval
|
|
56
|
+
}
|
|
57
|
+
rest.format = formatJSON
|
|
58
|
+
//
|
|
59
|
+
if (parse) rest.parse = parseFunction
|
|
60
|
+
if (multiline) rest.multiline = true
|
|
61
|
+
return <TextInput {...rest} />
|
|
62
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { Resource } from "react-admin"
|
|
4
|
+
import * as icons from "@mui/icons-material"
|
|
5
|
+
|
|
6
|
+
import { checkParams, processAdmin, setupAdmin } from "./utils"
|
|
7
|
+
import "./views/list"
|
|
8
|
+
import "./views/show"
|
|
9
|
+
import "./views/edit"
|
|
10
|
+
import "./views/create"
|
|
11
|
+
|
|
12
|
+
// Initialize Resources Components
|
|
13
|
+
setupAdmin("resources", (resources) =>
|
|
14
|
+
resources.map((res) => processAdmin("resource", res, res.name))
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
// Initialize a resource's component
|
|
18
|
+
setupAdmin(
|
|
19
|
+
"resource",
|
|
20
|
+
checkParams((props, res) => {
|
|
21
|
+
let { create, edit, icon, list, name, show, ...resProps } = props
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Resource
|
|
25
|
+
key={name}
|
|
26
|
+
name={name}
|
|
27
|
+
icon={icons[icon]}
|
|
28
|
+
create={processAdmin("create", create, res)}
|
|
29
|
+
edit={processAdmin("edit", edit, res)}
|
|
30
|
+
list={processAdmin("list", list, res)}
|
|
31
|
+
show={processAdmin("show", show, res)}
|
|
32
|
+
{...resProps}
|
|
33
|
+
/>
|
|
34
|
+
)
|
|
35
|
+
})
|
|
36
|
+
)
|
package/src/ui.jsx
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { required } from "react-admin"
|
|
4
|
+
import {
|
|
5
|
+
BooleanField,
|
|
6
|
+
ChipField,
|
|
7
|
+
DateField,
|
|
8
|
+
EmailField,
|
|
9
|
+
ImageField,
|
|
10
|
+
FileField,
|
|
11
|
+
NumberField,
|
|
12
|
+
RichTextField,
|
|
13
|
+
TextField,
|
|
14
|
+
UrlField,
|
|
15
|
+
SelectField,
|
|
16
|
+
ArrayField,
|
|
17
|
+
ReferenceField,
|
|
18
|
+
ReferenceManyField,
|
|
19
|
+
ReferenceArrayField,
|
|
20
|
+
} from "react-admin"
|
|
21
|
+
import {
|
|
22
|
+
BooleanInput,
|
|
23
|
+
NullableBooleanInput,
|
|
24
|
+
DateInput,
|
|
25
|
+
DateTimeInput,
|
|
26
|
+
ImageInput,
|
|
27
|
+
FileInput,
|
|
28
|
+
NumberInput,
|
|
29
|
+
PasswordInput,
|
|
30
|
+
TextInput,
|
|
31
|
+
AutocompleteInput,
|
|
32
|
+
RadioButtonGroupInput,
|
|
33
|
+
SelectInput,
|
|
34
|
+
ArrayInput,
|
|
35
|
+
AutocompleteArrayInput,
|
|
36
|
+
CheckboxGroupInput,
|
|
37
|
+
ReferenceArrayInput,
|
|
38
|
+
ReferenceInput,
|
|
39
|
+
} from "react-admin"
|
|
40
|
+
|
|
41
|
+
import AvatarField from "./fields/AvatarField"
|
|
42
|
+
import FKField from "./fields/FKField"
|
|
43
|
+
import FKInput from "./inputs/FKInput"
|
|
44
|
+
import JsonField from "./fields/JsonField"
|
|
45
|
+
import JsonInput from "./inputs/JsonInput"
|
|
46
|
+
|
|
47
|
+
const ui = {
|
|
48
|
+
// Fields
|
|
49
|
+
BooleanField,
|
|
50
|
+
ChipField,
|
|
51
|
+
DateField,
|
|
52
|
+
EmailField,
|
|
53
|
+
ImageField,
|
|
54
|
+
FileField,
|
|
55
|
+
NumberField,
|
|
56
|
+
RichTextField,
|
|
57
|
+
TextField,
|
|
58
|
+
UrlField,
|
|
59
|
+
SelectField,
|
|
60
|
+
ArrayField,
|
|
61
|
+
ReferenceField,
|
|
62
|
+
ReferenceManyField,
|
|
63
|
+
ReferenceArrayField,
|
|
64
|
+
AvatarField,
|
|
65
|
+
JsonField,
|
|
66
|
+
FKField,
|
|
67
|
+
|
|
68
|
+
// Inputs
|
|
69
|
+
BooleanInput,
|
|
70
|
+
NullableBooleanInput,
|
|
71
|
+
DateInput,
|
|
72
|
+
DateTimeInput,
|
|
73
|
+
ImageInput,
|
|
74
|
+
FileInput,
|
|
75
|
+
NumberInput,
|
|
76
|
+
PasswordInput,
|
|
77
|
+
TextInput,
|
|
78
|
+
AutocompleteInput,
|
|
79
|
+
RadioButtonGroupInput,
|
|
80
|
+
SelectInput,
|
|
81
|
+
ArrayInput,
|
|
82
|
+
AutocompleteArrayInput,
|
|
83
|
+
CheckboxGroupInput,
|
|
84
|
+
ReferenceArrayInput,
|
|
85
|
+
ReferenceInput,
|
|
86
|
+
JsonInput,
|
|
87
|
+
FKInput,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const initRAItems = (itemsProps) =>
|
|
91
|
+
itemsProps.map((item) => {
|
|
92
|
+
const Item = ui[item[0]],
|
|
93
|
+
props = { ...item[1] }
|
|
94
|
+
|
|
95
|
+
if (props.required) {
|
|
96
|
+
props.validate = required()
|
|
97
|
+
delete props.required
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
props.fullWidth = props.fullWidth ?? true
|
|
101
|
+
|
|
102
|
+
if (props.children) props.children = initRAItems(props.children)[0]
|
|
103
|
+
|
|
104
|
+
return <Item key={props.source} {...props} />
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
export default initRAItems
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
|
|
3
|
+
import { isValidElement } from "react"
|
|
4
|
+
import { fetchUtils } from "ra-core"
|
|
5
|
+
import { stringify } from "query-string"
|
|
6
|
+
|
|
7
|
+
const parts = {}
|
|
8
|
+
|
|
9
|
+
export const setupAdmin = (part, gen) => (parts[part] = gen)
|
|
10
|
+
|
|
11
|
+
export const checkParams = (fn) => (props, res) => {
|
|
12
|
+
if (!props || isValidElement(props)) return props
|
|
13
|
+
return fn(props, res)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const processAdmin = (type, props, res) => {
|
|
17
|
+
if (process.env.NODE_ENV == "development")
|
|
18
|
+
console.log(`${type}${res ? "-" + res : ""}`, props)
|
|
19
|
+
|
|
20
|
+
if (parts[`${type}-${res}`]) return parts[`${type}-${res}`](props, res)
|
|
21
|
+
if (parts[type]) return parts[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 = {
|
|
33
|
+
...opts,
|
|
34
|
+
headers: new Headers({ ...requestHeaders, ...opts.headers }),
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return fetchUtils.fetchJson(url, opts)
|
|
38
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { Create, SimpleForm, TopToolbar, ListButton } from "react-admin"
|
|
4
|
+
|
|
5
|
+
import initRAItems from "../ui"
|
|
6
|
+
import { checkParams, processAdmin, setupAdmin } from "../utils"
|
|
7
|
+
|
|
8
|
+
// Initialize a create component
|
|
9
|
+
setupAdmin(
|
|
10
|
+
"create",
|
|
11
|
+
checkParams(
|
|
12
|
+
(inputs, res) =>
|
|
13
|
+
function MACreate(props) {
|
|
14
|
+
const Actions = (
|
|
15
|
+
<TopToolbar>
|
|
16
|
+
<ListButton />
|
|
17
|
+
</TopToolbar>
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Create actions={Actions} {...props}>
|
|
22
|
+
<SimpleForm>
|
|
23
|
+
{processAdmin("create-inputs", inputs, res)}
|
|
24
|
+
</SimpleForm>
|
|
25
|
+
</Create>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
setupAdmin("create-inputs", initRAItems)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Edit,
|
|
5
|
+
ListButton,
|
|
6
|
+
ShowButton,
|
|
7
|
+
SimpleForm,
|
|
8
|
+
TopToolbar,
|
|
9
|
+
} from "react-admin"
|
|
10
|
+
|
|
11
|
+
import initRAItems from "../ui"
|
|
12
|
+
import { checkParams, processAdmin, setupAdmin } from "../utils"
|
|
13
|
+
import { ActionButton } from "../buttons/ActionButton"
|
|
14
|
+
|
|
15
|
+
// Initialize an edit component
|
|
16
|
+
setupAdmin(
|
|
17
|
+
"edit",
|
|
18
|
+
checkParams(
|
|
19
|
+
({ actions, inputs }, res) =>
|
|
20
|
+
function MAEdit(props) {
|
|
21
|
+
const Actions = ({ basePath, resource, ...baseProps }) => (
|
|
22
|
+
<TopToolbar>
|
|
23
|
+
{actions.map((props, idx) => {
|
|
24
|
+
let aProps = { resource, basePath, ...baseProps, ...props }
|
|
25
|
+
return <ActionButton key={idx} {...aProps} />
|
|
26
|
+
})}
|
|
27
|
+
<ListButton />
|
|
28
|
+
<ShowButton />
|
|
29
|
+
</TopToolbar>
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Edit actions={<Actions />} {...props}>
|
|
34
|
+
<SimpleForm>{processAdmin("edit-inputs", inputs, res)}</SimpleForm>
|
|
35
|
+
</Edit>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
setupAdmin("edit-inputs", initRAItems)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
BulkDeleteButton,
|
|
5
|
+
Datagrid,
|
|
6
|
+
EditButton,
|
|
7
|
+
Filter,
|
|
8
|
+
List,
|
|
9
|
+
Pagination,
|
|
10
|
+
} from "react-admin"
|
|
11
|
+
import uniq from "lodash/uniq"
|
|
12
|
+
import sortBy from "lodash/sortBy"
|
|
13
|
+
|
|
14
|
+
import initRAItems from "../ui"
|
|
15
|
+
import { checkParams, processAdmin, setupAdmin } from "../utils"
|
|
16
|
+
import { BulkActionButton } from "../buttons/ActionButton"
|
|
17
|
+
|
|
18
|
+
const defaultPagination = <Pagination rowsPerPageOptions={[10, 25, 50, 100]} />
|
|
19
|
+
|
|
20
|
+
// Initiliaze a list component
|
|
21
|
+
setupAdmin(
|
|
22
|
+
"list",
|
|
23
|
+
checkParams((props, res) => {
|
|
24
|
+
let {
|
|
25
|
+
children,
|
|
26
|
+
filters,
|
|
27
|
+
edit,
|
|
28
|
+
pagination,
|
|
29
|
+
show,
|
|
30
|
+
limit,
|
|
31
|
+
limitMax,
|
|
32
|
+
actions,
|
|
33
|
+
...listProps
|
|
34
|
+
} = props
|
|
35
|
+
|
|
36
|
+
children = processAdmin("list-fields", children, res)
|
|
37
|
+
if (edit) children.push(<EditButton key="edit-button" />)
|
|
38
|
+
|
|
39
|
+
pagination = pagination || (
|
|
40
|
+
<Pagination
|
|
41
|
+
rowsPerPageOptions={sortBy(uniq([10, 25, 50, 100, limit, limitMax]))}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
return function MAList(props) {
|
|
46
|
+
let Filters = (props) => (
|
|
47
|
+
<Filter {...props}>{processAdmin("list-filters", filters, res)}</Filter>
|
|
48
|
+
)
|
|
49
|
+
let Actions = processAdmin("list-bulkActions", actions)
|
|
50
|
+
|
|
51
|
+
props = { ...props, ...listProps }
|
|
52
|
+
return (
|
|
53
|
+
<List
|
|
54
|
+
filters={<Filters />}
|
|
55
|
+
bulkActionButtons={<Actions />}
|
|
56
|
+
perPage={limit}
|
|
57
|
+
pagination={pagination || defaultPagination}
|
|
58
|
+
{...props}
|
|
59
|
+
>
|
|
60
|
+
<Datagrid rowClick={show ? "show" : null}>{children}</Datagrid>
|
|
61
|
+
</List>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
setupAdmin(
|
|
68
|
+
"list-bulkActions",
|
|
69
|
+
(actions) =>
|
|
70
|
+
function MABulkActions(props) {
|
|
71
|
+
let buttons = actions.map((action, idx) => {
|
|
72
|
+
let aProps = { ...action, ...props }
|
|
73
|
+
return <BulkActionButton key={idx} {...aProps} />
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<>
|
|
78
|
+
{buttons}
|
|
79
|
+
<BulkDeleteButton {...props} />
|
|
80
|
+
</>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
setupAdmin("list-filters", initRAItems)
|
|
86
|
+
setupAdmin("list-fields", initRAItems)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ListButton,
|
|
5
|
+
EditButton,
|
|
6
|
+
Show,
|
|
7
|
+
SimpleShowLayout,
|
|
8
|
+
TopToolbar,
|
|
9
|
+
} from "react-admin"
|
|
10
|
+
|
|
11
|
+
import initRAItems from "../ui"
|
|
12
|
+
import { checkParams, processAdmin, setupAdmin } from "../utils"
|
|
13
|
+
import { ActionButton } from "../buttons/ActionButton"
|
|
14
|
+
|
|
15
|
+
// Initiliaze a show component
|
|
16
|
+
setupAdmin(
|
|
17
|
+
"show",
|
|
18
|
+
checkParams(
|
|
19
|
+
({ actions, fields }, resource) =>
|
|
20
|
+
function MAShow(props) {
|
|
21
|
+
const Actions = () => (
|
|
22
|
+
<TopToolbar>
|
|
23
|
+
{actions.map((props, idx) => {
|
|
24
|
+
return <ActionButton key={idx} resource={resource} {...props} />
|
|
25
|
+
})}
|
|
26
|
+
<ListButton />
|
|
27
|
+
<EditButton />
|
|
28
|
+
</TopToolbar>
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Show actions={<Actions />} {...props}>
|
|
33
|
+
<SimpleShowLayout>
|
|
34
|
+
{processAdmin("show-fields", fields, resource)}
|
|
35
|
+
</SimpleShowLayout>
|
|
36
|
+
</Show>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
setupAdmin("show-fields", initRAItems)
|
package/src/web.js
ADDED
package/.eslintrc.json
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"root": true,
|
|
3
|
-
"extends": [
|
|
4
|
-
"eslint:recommended",
|
|
5
|
-
"plugin:react/recommended",
|
|
6
|
-
"prettier"
|
|
7
|
-
],
|
|
8
|
-
"parser": "@babel/eslint-parser",
|
|
9
|
-
"settings": {
|
|
10
|
-
"react": {
|
|
11
|
-
"version": "detect"
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
"parserOptions": {
|
|
15
|
-
"ecmaFeatures": {
|
|
16
|
-
"jsx": true,
|
|
17
|
-
"experimentalObjectRestSpread": true
|
|
18
|
-
},
|
|
19
|
-
"ecmaVersion": 2020,
|
|
20
|
-
"sourceType": "module",
|
|
21
|
-
"babelOptions": {
|
|
22
|
-
"presets": [
|
|
23
|
-
"@babel/preset-react"
|
|
24
|
-
],
|
|
25
|
-
"rootMode": "upward"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
"plugins": [
|
|
29
|
-
"prettier",
|
|
30
|
-
"react"
|
|
31
|
-
],
|
|
32
|
-
"env": {
|
|
33
|
-
"browser": true,
|
|
34
|
-
"es6": true,
|
|
35
|
-
"jest": true,
|
|
36
|
-
"node": true
|
|
37
|
-
},
|
|
38
|
-
"rules": {
|
|
39
|
-
"no-console": "warn",
|
|
40
|
-
"no-debugger": "warn",
|
|
41
|
-
"prettier/prettier": "warn",
|
|
42
|
-
"react/prop-types": "off"
|
|
43
|
-
}
|
|
44
|
-
}
|
package/Makefile
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
all: node_modules
|
|
2
|
-
$(CURDIR)/node_modules/.bin/webpack
|
|
3
|
-
|
|
4
|
-
node_modules: package.json
|
|
5
|
-
npm install
|
|
6
|
-
touch node_modules
|
|
7
|
-
|
|
8
|
-
npm: node_modules
|
|
9
|
-
$(CURDIR)/node_modules/.bin/babel src --out-dir dist
|
|
10
|
-
|
|
11
|
-
pypi:
|
|
12
|
-
$(CURDIR)/node_modules/.bin/webpack
|
|
13
|
-
|
|
14
|
-
watch: node_modules
|
|
15
|
-
$(CURDIR)/node_modules/.bin/webpack --watch
|
|
16
|
-
|
|
17
|
-
dev: node_modules
|
|
18
|
-
NODE_ENV=development $(CURDIR)/node_modules/.bin/webpack serve
|
package/jsconfig.json
DELETED
package/webpack.config.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
const path = require("path"),
|
|
2
|
-
webpack = require("webpack"),
|
|
3
|
-
mode = process.env.NODE_ENV
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
entry: "./src/web",
|
|
7
|
-
|
|
8
|
-
output: {
|
|
9
|
-
filename: "main.js",
|
|
10
|
-
path: path.resolve(__dirname, "../muffin_admin"),
|
|
11
|
-
publicPath: "/admin",
|
|
12
|
-
},
|
|
13
|
-
|
|
14
|
-
module: {
|
|
15
|
-
rules: [
|
|
16
|
-
{
|
|
17
|
-
test: /\.jsx?$/,
|
|
18
|
-
exclude: /node_modules/,
|
|
19
|
-
use: {
|
|
20
|
-
loader: "babel-loader",
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
plugins: [new webpack.EnvironmentPlugin({ NODE_ENV: "production" })],
|
|
27
|
-
|
|
28
|
-
mode: mode || "production",
|
|
29
|
-
devtool: mode == "development" && "inline-source-map",
|
|
30
|
-
|
|
31
|
-
resolve: {
|
|
32
|
-
extensions: [".jsx", ".js"],
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
devServer: {
|
|
36
|
-
hot: true,
|
|
37
|
-
open: true,
|
|
38
|
-
proxy: [
|
|
39
|
-
{
|
|
40
|
-
context: ["!*.js"],
|
|
41
|
-
target: "http://localhost:5555",
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
}
|
|
File without changes
|