muffin-admin 9.5.4 → 11.0.0

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
@@ -45,6 +45,7 @@ export type AdminPayloadProps = {
45
45
  help?: string;
46
46
  };
47
47
  export type AdminResourceProps = {
48
+ key: string;
48
49
  name: string;
49
50
  group?: string;
50
51
  icon?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muffin-admin",
3
- "version": "9.5.4",
3
+ "version": "11.0.0",
4
4
  "description": "NPM package for https://github.com/klen/muffin-admin",
5
5
  "files": [
6
6
  "src",
@@ -25,18 +25,18 @@
25
25
  "dependencies": {
26
26
  "date-fns": "^4.1.0",
27
27
  "js-cookie": "^3.0.5",
28
- "ra-language-russian": "^4.14.2",
29
- "react": "^18.3.1",
30
- "react-admin": "^5.4.0",
28
+ "ra-language-russian": "^5.4.4",
29
+ "react": "^19.1.1",
30
+ "react-admin": "^5.10.0",
31
31
  "react-datepicker": "^8.1.0",
32
- "react-dom": "^18.3.1",
32
+ "react-dom": "^19.1.1",
33
33
  "validator": "^13.12.0"
34
34
  },
35
35
  "devDependencies": {
36
- "@types/lodash": "^4.17.10",
37
- "@types/node": "20.14.2",
38
- "@types/react": "18.3.3",
39
- "@types/react-dom": "18.3.0",
36
+ "@types/lodash": "^4.17.20",
37
+ "@types/node": "24.1.0",
38
+ "@types/react": "19.1.9",
39
+ "@types/react-dom": "19.1.7",
40
40
  "@types/react-window": "^1.8.8",
41
41
  "@typescript-eslint/eslint-plugin": "^7.12.0",
42
42
  "@typescript-eslint/parser": "^7.12.0",
@@ -43,7 +43,7 @@ setupAdmin(["dashboard-content"], () => null)
43
43
  function AdminCards({ src }: { src: AdminDashboardBlock | AdminDashboardBlock[] }) {
44
44
  if (Array.isArray(src))
45
45
  return (
46
- <Grid container item spacing={2}>
46
+ <Grid container spacing={2}>
47
47
  {src.map((card, idx) => (
48
48
  <AdminCards key={idx} src={card} />
49
49
  ))}
@@ -55,23 +55,21 @@ function AdminCards({ src }: { src: AdminDashboardBlock | AdminDashboardBlock[]
55
55
 
56
56
  function DashboardCard({ title, value }: AdminDashboardBlock) {
57
57
  return (
58
- <Grid item xs>
59
- <Card>
60
- <CardContent>
61
- <Typography variant="h5" component="h2" m={2} style={{ textAlign: "center" }}>
62
- {title}
63
- </Typography>
64
- {(Array.isArray(value) && <AdminTableView src={value} />) || (
65
- <pre>{JSON.stringify(value, null, 2)}</pre>
66
- )}
67
- </CardContent>
68
- </Card>
69
- </Grid>
58
+ <Card>
59
+ <CardContent>
60
+ <Typography variant="h5" component="h2" m={2} style={{ textAlign: "center" }}>
61
+ {title}
62
+ </Typography>
63
+ {(Array.isArray(value) && <AdminTableView src={value} />) || (
64
+ <pre>{JSON.stringify(value, null, 2)}</pre>
65
+ )}
66
+ </CardContent>
67
+ </Card>
70
68
  )
71
69
  }
72
70
 
73
71
  const AdminTableView = ({ src }) => (
74
- <Table>
72
+ <Table width="100%" sx={{ tableLayout: "fixed" }}>
75
73
  <TableBody>
76
74
  {src.map((row: any, idx: number) => (
77
75
  <TableRow key={idx} hover>
@@ -20,7 +20,7 @@ export function MuffinEdit({ children }: PropsWithChildren) {
20
20
  adminProps: { mutationMode = "optimistic" },
21
21
  } = useMuffinAdminOpts()
22
22
 
23
- const { edit, name } = useMuffinResourceOpts()
23
+ const { edit, name, key } = useMuffinResourceOpts()
24
24
  if (!edit) return null
25
25
 
26
26
  const Actions = findBuilder(["edit-toolbar", name])
@@ -28,7 +28,7 @@ export function MuffinEdit({ children }: PropsWithChildren) {
28
28
  const FormToolbar = findBuilder(["edit-form-toolbar", name])
29
29
 
30
30
  return (
31
- <Edit actions={<Actions />} mutationMode={mutationMode}>
31
+ <Edit actions={<Actions />} mutationMode={mutationMode} queryOptions={{ meta: { key } }}>
32
32
  {children}
33
33
  <SimpleForm toolbar={<FormToolbar />}>
34
34
  <Inputs />
@@ -23,7 +23,7 @@ import { AdminInput } from "./types"
23
23
  import { buildAdmin, findBuilder, setupAdmin } from "./utils"
24
24
 
25
25
  export function MuffinList({ children }: PropsWithChildren) {
26
- const { name, list } = useMuffinResourceOpts()
26
+ const { name, list, key } = useMuffinResourceOpts()
27
27
  const { limit, limitMax, limitTotal, sort, filters } = list
28
28
 
29
29
  const DataGrid = findBuilder(["list-grid", name])
@@ -36,6 +36,7 @@ export function MuffinList({ children }: PropsWithChildren) {
36
36
  perPage={limit}
37
37
  filters={raFilters}
38
38
  actions={<Toolbar />}
39
+ queryOptions={{ meta: { key } }}
39
40
  pagination={
40
41
  <Pagination rowsPerPageOptions={sortBy(uniq([10, 25, 50, 100, limit, limitMax]))} />
41
42
  }
@@ -44,7 +45,13 @@ export function MuffinList({ children }: PropsWithChildren) {
44
45
  <DataGrid />
45
46
  </List>
46
47
  ) : (
47
- <InfiniteList sort={sort} perPage={limit} actions={<Toolbar />} filters={raFilters}>
48
+ <InfiniteList
49
+ sort={sort}
50
+ perPage={limit}
51
+ filters={raFilters}
52
+ actions={<Toolbar />}
53
+ queryOptions={{ meta: { key } }}
54
+ >
48
55
  {children}
49
56
  <DataGrid />
50
57
  </InfiniteList>
@@ -7,11 +7,11 @@ import { useMuffinResourceOpts } from "./hooks"
7
7
  import { buildAdmin, findBuilder, setupAdmin } from "./utils"
8
8
 
9
9
  export function MuffinShow({ children }: PropsWithChildren) {
10
- const { show, name } = useMuffinResourceOpts()
10
+ const { show, name, key } = useMuffinResourceOpts()
11
11
  const ShowToolbar = findBuilder(["show-toolbar", name])
12
12
 
13
13
  return (
14
- <Show actions={<ShowToolbar />}>
14
+ <Show actions={<ShowToolbar />} queryOptions={{ meta: { key } }}>
15
15
  <SimpleShowLayout>{buildAdmin(["show-fields", name], show)}</SimpleShowLayout>
16
16
  {children}
17
17
  </Show>
@@ -1,6 +1,10 @@
1
1
  import { TID } from "./types"
2
2
  import { APIParams, makeRequest, prepareFilters, setupAdmin } from "./utils"
3
3
 
4
+ type TQueryMeta = {
5
+ key?: string
6
+ }
7
+
4
8
  export function MuffinDataprovider(apiUrl: string) {
5
9
  async function request(url: string, options?: APIParams) {
6
10
  if (!url.startsWith("/")) url = `${apiUrl}/${url}`
@@ -10,7 +14,7 @@ export function MuffinDataprovider(apiUrl: string) {
10
14
 
11
15
  const methods = {
12
16
  request,
13
- getList: async (resource: string, params: any) => {
17
+ getList: async (resource: string, { meta, ...params }: any) => {
14
18
  const { filter, pagination, sort } = params
15
19
  const query: APIParams["query"] = {}
16
20
  if (filter) query.where = prepareFilters(filter)
@@ -24,6 +28,14 @@ export function MuffinDataprovider(apiUrl: string) {
24
28
  query.sort = order == "ASC" ? field : `-${field}`
25
29
  }
26
30
  const { headers, data } = await request(resource, { query })
31
+
32
+ // React-admin requires item to have an `id` field
33
+ if (meta?.key) {
34
+ for (const item of data) {
35
+ item.id = item.id ?? item[meta.key]
36
+ }
37
+ }
38
+
27
39
  if (pagination)
28
40
  return {
29
41
  data,
@@ -37,8 +49,13 @@ export function MuffinDataprovider(apiUrl: string) {
37
49
  return { data }
38
50
  },
39
51
 
40
- getOne: async (resource: string, { id }: { id: TID }) => {
41
- return await request(`${resource}/${id}`)
52
+ getOne: async (resource: string, { id, meta }: { id: TID; meta?: TQueryMeta }) => {
53
+ const response = await request(`${resource}/${id}`)
54
+ const { data } = response
55
+ if (meta?.key) {
56
+ data.id = data.id ?? data[meta.key]
57
+ }
58
+ return response
42
59
  },
43
60
 
44
61
  create: async (resource: string, { data }) => {
@@ -76,7 +93,7 @@ export function MuffinDataprovider(apiUrl: string) {
76
93
  getMany: (resource: string, props: { ids: TID[]; meta: any }) => {
77
94
  const { ids, meta } = props
78
95
  const key = meta?.key || "id"
79
- return methods.getList(resource, { filter: { [key]: { $in: ids } } })
96
+ return methods.getList(resource, { filter: { [key]: { $in: ids } }, meta })
80
97
  },
81
98
 
82
99
  getManyReference: async (resource: string, { target, id, filter, ...opts }) => {
@@ -1,6 +1,7 @@
1
1
  import { ReferenceField, TextField } from "react-admin"
2
2
 
3
3
  export function FKField({ reference, refSource, refKey, link, source, ...props }) {
4
+ refKey = refKey || "id"
4
5
  return (
5
6
  <ReferenceField
6
7
  source={source}
@@ -11,9 +12,13 @@ export function FKField({ reference, refSource, refKey, link, source, ...props }
11
12
  >
12
13
  <>
13
14
  <TextField source={refSource} />
14
- {" (#"}
15
- <TextField source={refKey || "id"} />
16
- {")"}
15
+ {refSource !== refKey && (
16
+ <>
17
+ {" (#"}
18
+ <TextField source={refKey} />
19
+ {")"}
20
+ </>
21
+ )}
17
22
  </>
18
23
  </ReferenceField>
19
24
  )
package/src/index.tsx CHANGED
@@ -37,4 +37,4 @@ export async function initAdmin(prefix = "", containerId: string = "root") {
37
37
  )
38
38
  }
39
39
 
40
- export const VERSION = "9.5.4"
40
+ export const VERSION = "11.0.0"
@@ -10,13 +10,19 @@ export function FKInput({ refKey, refSource, fullWidth, reference, source, ...pr
10
10
 
11
11
  refKey = refKey || "id"
12
12
  const renderText = (record) => {
13
- const pk = record[refKey]
14
- if (refKey == refSource) return `#${pk}`
15
- return (pk && `${record[refSource]} (#${pk})`) || ""
13
+ const key = record[refKey]
14
+ if (refKey == refSource) return `#${key}`
15
+ return (key && `${record[refSource]} (#${key})`) || ""
16
16
  }
17
17
 
18
18
  return (
19
- <ReferenceInput reference={reference} source={source}>
19
+ <ReferenceInput
20
+ reference={reference}
21
+ source={source}
22
+ queryOptions={{
23
+ meta: { key: refKey },
24
+ }}
25
+ >
20
26
  <AutocompleteInput
21
27
  source={refKey}
22
28
  optionText={renderText}
package/src/types.ts CHANGED
@@ -81,6 +81,7 @@ export type AdminPayloadProps = {
81
81
  }
82
82
 
83
83
  export type AdminResourceProps = {
84
+ key: string
84
85
  name: string
85
86
  group?: string
86
87
  icon?: string