muffin-admin 3.5.0 → 3.6.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/dist/types.d.ts CHANGED
@@ -2,13 +2,14 @@ export type TProps = {
2
2
  [key: string]: any;
3
3
  };
4
4
  export type AdminAction = {
5
- view: string[];
5
+ view: ("show" | "edit" | "list" | "bulk")[];
6
6
  id: string;
7
7
  label: string;
8
8
  title: string;
9
9
  icon: string;
10
10
  action: string;
11
11
  confirm?: string | false;
12
+ schema?: AdminInput[];
12
13
  };
13
14
  export type AdminField = [string, {
14
15
  source: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muffin-admin",
3
- "version": "3.5.0",
3
+ "version": "3.6.1",
4
4
  "description": "NPM package for https://github.com/klen/muffin-admin",
5
5
  "files": [
6
6
  "src",
@@ -14,7 +14,7 @@ import {
14
14
  TopToolbar,
15
15
  } from "react-admin"
16
16
  import { buildRA } from "./buildRA"
17
- import { BulkActionButton } from "./buttons"
17
+ import { ActionButton, BulkActionButton } from "./buttons"
18
18
  import { useMuffinResourceOpts } from "./hooks"
19
19
  import { buildAdmin, findBuilder, setupAdmin } from "./utils"
20
20
 
@@ -72,12 +72,15 @@ setupAdmin(["list-grid-buttons"], MuffinListGridButtons)
72
72
 
73
73
  function MuffinListToolbar() {
74
74
  const {
75
+ actions: baseActions = [],
75
76
  list: { create },
76
77
  } = useMuffinResourceOpts()
78
+ const actions = baseActions.filter((a) => a.view.includes("list"))
77
79
  return (
78
80
  <TopToolbar>
79
81
  <SelectColumnsButton />
80
82
  <FilterButton />
83
+ {actions.length && actions.map((props) => <ActionButton key={props.id} {...props} />)}
81
84
  {create && <CreateButton />}
82
85
  <ExportButton />
83
86
  </TopToolbar>
@@ -90,7 +93,7 @@ function MuffinListBulkActions() {
90
93
  actions: baseActions = [],
91
94
  list: { remove },
92
95
  } = useMuffinResourceOpts()
93
- const actions = baseActions.filter((a) => a.view.includes("list"))
96
+ const actions = baseActions.filter((a) => a.view.includes("bulk"))
94
97
  return (
95
98
  <>
96
99
  {actions.map((props) => (
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  Button,
3
+ Form,
3
4
  useListContext,
4
5
  useRecordContext,
5
6
  useResourceContext,
@@ -7,7 +8,8 @@ import {
7
8
  } from "react-admin"
8
9
 
9
10
  import { useMemo, useState } from "react"
10
- import { useConfirmation } from "../common"
11
+ import { buildRA } from "../buildRA"
12
+ import { AdminModal, PayloadButtons, useConfirmation } from "../common"
11
13
  import { useAction } from "../hooks/useAction"
12
14
  import { AdminAction } from "../types"
13
15
  import { buildIcon, findBuilder } from "../utils"
@@ -18,7 +20,7 @@ export type ActionPayloadProps = {
18
20
  onHandle: (payload: any) => void
19
21
  }
20
22
 
21
- export function ActionButton({ icon, label, title, action, id, confirm }: AdminAction) {
23
+ export function ActionButton({ icon, label, title, action, id, confirm, schema }: AdminAction) {
22
24
  const translate = useTranslate()
23
25
  const record = useRecordContext()
24
26
  const resource = useResourceContext()
@@ -26,28 +28,26 @@ export function ActionButton({ icon, label, title, action, id, confirm }: AdminA
26
28
  const { mutate, isPending } = useAction(action)
27
29
 
28
30
  const [payloadActive, setPayloadActive] = useState(false)
29
- const [payloadResolver, setPayloadResolver] = useState<(data: any) => void>()
30
31
 
31
- const PayloadBuilder = findBuilder(["action", "payload", id, resource])
32
- const buildPayload = useMemo(() => {
33
- if (PayloadBuilder) {
34
- return new Promise((resolve) => setPayloadResolver(() => resolve))
35
- }
36
- return Promise.resolve()
37
- }, [PayloadBuilder])
32
+ const PayloadBuilder =
33
+ findBuilder(["action", "payload", id, resource]) || (schema && CommonPayload)
34
+
38
35
  const confirmMessage =
39
36
  typeof confirm === "string" ? translate(confirm) : "Do you confirm this action?"
40
37
 
38
+ const onHandle = async (payload?) => {
39
+ const process = confirm ? await confirmation.confirm({ message: confirmMessage }) : true
40
+ if (process) await mutate({ record, payload })
41
+ }
42
+
41
43
  return (
42
44
  <>
43
45
  <Button
44
46
  label={label}
45
47
  title={title}
46
- onClick={async () => {
48
+ onClick={() => {
47
49
  if (PayloadBuilder) setPayloadActive(true)
48
- const payload = await buildPayload
49
- const process = confirm ? await confirmation.confirm({ message: confirmMessage }) : true
50
- if (process) await mutate({ record, payload })
50
+ else onHandle()
51
51
  }}
52
52
  disabled={isPending}
53
53
  >
@@ -56,8 +56,10 @@ export function ActionButton({ icon, label, title, action, id, confirm }: AdminA
56
56
  {PayloadBuilder && (
57
57
  <PayloadBuilder
58
58
  active={payloadActive}
59
- onHandle={payloadResolver}
59
+ onHandle={onHandle}
60
60
  onClose={() => setPayloadActive(false)}
61
+ title={title || label}
62
+ schema={schema}
61
63
  />
62
64
  )}
63
65
  </>
@@ -108,3 +110,26 @@ export function BulkActionButton({ label, icon, title, action, id, confirm }: Ad
108
110
  </>
109
111
  )
110
112
  }
113
+
114
+ export function CommonPayload({ active, onClose, onHandle, schema, title }) {
115
+ const inputs = buildRA(schema)
116
+ const translate = useTranslate()
117
+ return (
118
+ <AdminModal
119
+ maxWidth="sm"
120
+ open={active}
121
+ onClose={onClose}
122
+ title={translate(title, { _: title })}
123
+ >
124
+ <Form
125
+ onSubmit={(data) => {
126
+ onClose()
127
+ onHandle(data)
128
+ }}
129
+ >
130
+ {inputs}
131
+ <PayloadButtons onClose={onClose} />
132
+ </Form>
133
+ </AdminModal>
134
+ )
135
+ }
@@ -0,0 +1,19 @@
1
+ import { Stack } from "@mui/material"
2
+ import { Button } from "react-admin"
3
+ import { useFormContext } from "react-hook-form"
4
+
5
+ export function PayloadButtons({ onClose }) {
6
+ const { formState } = useFormContext()
7
+ return (
8
+ <Stack direction="row" alignItems="center" justifyContent="flex-end" spacing={1}>
9
+ <Button
10
+ type="submit"
11
+ label="ra.action.confirm"
12
+ variant="contained"
13
+ disabled={!formState.isValid}
14
+ size="medium"
15
+ />
16
+ <Button label="ra.action.cancel" variant="outlined" size="medium" onClick={onClose} />
17
+ </Stack>
18
+ )
19
+ }
@@ -1,2 +1,3 @@
1
1
  export * from "./AdminModal"
2
2
  export * from "./ConfirmationProvider"
3
+ export * from "./PayloadButtons"
package/src/types.ts CHANGED
@@ -3,13 +3,14 @@ export type TProps = {
3
3
  }
4
4
 
5
5
  export type AdminAction = {
6
- view: string[]
6
+ view: ("show" | "edit" | "list" | "bulk")[]
7
7
  id: string
8
8
  label: string
9
9
  title: string
10
10
  icon: string
11
11
  action: string
12
12
  confirm?: string | false
13
+ schema?: AdminInput[]
13
14
  }
14
15
 
15
16
  export type AdminField = [string, { source: string }]
@@ -34,11 +35,11 @@ export type AdminResourceProps = {
34
35
  actions: AdminAction[]
35
36
  create: AdminInput[] | false
36
37
  edit:
37
- | {
38
- inputs: AdminInput[]
39
- remove?: boolean
40
- }
41
- | false
38
+ | {
39
+ inputs: AdminInput[]
40
+ remove?: boolean
41
+ }
42
+ | false
42
43
  list: {
43
44
  limit: number
44
45
  limitMax: number