muffin-admin 3.4.2 → 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;
@@ -24,7 +25,6 @@ export type AdminShowLink = {
24
25
  field?: string;
25
26
  };
26
27
  export type AdminShowProps = {
27
- actions: AdminAction[];
28
28
  fields: AdminField[];
29
29
  links: [string, AdminShowLink][];
30
30
  edit?: boolean;
@@ -33,16 +33,15 @@ export type AdminResourceProps = {
33
33
  name: string;
34
34
  icon?: string;
35
35
  label: string;
36
+ actions: AdminAction[];
36
37
  create: AdminInput[] | false;
37
38
  edit: {
38
- actions: AdminAction[];
39
39
  inputs: AdminInput[];
40
40
  remove?: boolean;
41
41
  } | false;
42
42
  list: {
43
43
  limit: number;
44
44
  limitMax: number;
45
- actions: AdminAction[];
46
45
  create: boolean;
47
46
  filters: AdminInput[];
48
47
  fields: AdminField[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muffin-admin",
3
- "version": "3.4.2",
3
+ "version": "3.6.1",
4
4
  "description": "NPM package for https://github.com/klen/muffin-admin",
5
5
  "files": [
6
6
  "src",
@@ -63,9 +63,9 @@ export function MuffinEditToolbar() {
63
63
  setupAdmin(["edit-toolbar"], MuffinEditToolbar)
64
64
 
65
65
  export function MuffinEditActions() {
66
- const { edit } = useMuffinResourceOpts()
66
+ const { edit, actions: baseActions = [] } = useMuffinResourceOpts()
67
67
  if (!edit) return null
68
- const { actions = [] } = edit
68
+ const actions = baseActions.filter((a => a.view.includes("edit")))
69
69
  return (
70
70
  <>
71
71
  {actions.map((props, idx) => (
@@ -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>
@@ -87,8 +90,10 @@ setupAdmin(["list-toolbar"], MuffinListToolbar)
87
90
 
88
91
  function MuffinListBulkActions() {
89
92
  const {
90
- list: { actions, remove },
93
+ actions: baseActions = [],
94
+ list: { remove },
91
95
  } = useMuffinResourceOpts()
96
+ const actions = baseActions.filter((a) => a.view.includes("bulk"))
92
97
  return (
93
98
  <>
94
99
  {actions.map((props) => (
@@ -39,8 +39,8 @@ export function MuffinShowToolbar() {
39
39
  setupAdmin(["show-toolbar"], MuffinShowToolbar)
40
40
 
41
41
  export function MuffinShowActions() {
42
- const { show } = useMuffinResourceOpts()
43
- const { actions } = show
42
+ const { actions: baseActions = [] } = useMuffinResourceOpts()
43
+ const actions = baseActions.filter((a) => a.view.includes("show"))
44
44
  return actions.map((props) => <ActionButton key={props.id} {...props} />)
45
45
  }
46
46
 
@@ -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 }]
@@ -22,7 +23,6 @@ export type AdminShowLink = {
22
23
  field?: string
23
24
  }
24
25
  export type AdminShowProps = {
25
- actions: AdminAction[]
26
26
  fields: AdminField[]
27
27
  links: [string, AdminShowLink][]
28
28
  edit?: boolean
@@ -32,10 +32,10 @@ export type AdminResourceProps = {
32
32
  name: string
33
33
  icon?: string
34
34
  label: string
35
+ actions: AdminAction[]
35
36
  create: AdminInput[] | false
36
37
  edit:
37
38
  | {
38
- actions: AdminAction[]
39
39
  inputs: AdminInput[]
40
40
  remove?: boolean
41
41
  }
@@ -43,7 +43,6 @@ export type AdminResourceProps = {
43
43
  list: {
44
44
  limit: number
45
45
  limitMax: number
46
- actions: AdminAction[]
47
46
  create: boolean
48
47
  filters: AdminInput[]
49
48
  fields: AdminField[]