muffin-admin 2.7.3 → 2.8.2

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.
Files changed (53) hide show
  1. package/dist/MuffinAdmin.d.ts +4 -3
  2. package/dist/MuffinAdmin.js +19 -8
  3. package/dist/MuffinDashboard.d.ts +1 -4
  4. package/dist/MuffinDashboard.js +5 -3
  5. package/dist/MuffinResource.d.ts +2 -2
  6. package/dist/MuffinResource.js +8 -3
  7. package/dist/MuffinResourceCreate.d.ts +1 -4
  8. package/dist/MuffinResourceCreate.js +10 -6
  9. package/dist/MuffinResourceEdit.d.ts +1 -2
  10. package/dist/MuffinResourceEdit.js +16 -12
  11. package/dist/MuffinResourceList.d.ts +1 -2
  12. package/dist/MuffinResourceList.js +13 -8
  13. package/dist/MuffinResourceShow.d.ts +1 -2
  14. package/dist/MuffinResourceShow.js +5 -4
  15. package/dist/actions/LinkAction.js +3 -4
  16. package/dist/authprovider.js +3 -3
  17. package/dist/buildRA.d.ts +2 -3
  18. package/dist/buildRA.js +4 -1
  19. package/dist/context.d.ts +3 -0
  20. package/dist/context.js +2 -0
  21. package/dist/dataprovider.d.ts +1 -2
  22. package/dist/dataprovider.js +1 -1
  23. package/dist/hooks/index.d.ts +3 -1
  24. package/dist/hooks/index.js +3 -1
  25. package/dist/hooks/useMuffinAdminOpts.d.ts +1 -0
  26. package/dist/hooks/useMuffinAdminOpts.js +5 -0
  27. package/dist/hooks/useMuffinResourceOpts.d.ts +1 -0
  28. package/dist/hooks/useMuffinResourceOpts.js +7 -0
  29. package/dist/index.d.ts +2 -1
  30. package/dist/index.js +7 -4
  31. package/dist/tsconfig.tsbuildinfo +1 -1
  32. package/dist/types.d.ts +1 -0
  33. package/dist/utils.d.ts +1 -4
  34. package/dist/utils.js +7 -7
  35. package/package.json +1 -1
  36. package/src/MuffinAdmin.tsx +48 -28
  37. package/src/MuffinDashboard.tsx +7 -5
  38. package/src/MuffinResource.tsx +13 -17
  39. package/src/MuffinResourceCreate.tsx +11 -8
  40. package/src/MuffinResourceEdit.tsx +28 -26
  41. package/src/MuffinResourceList.tsx +28 -21
  42. package/src/MuffinResourceShow.tsx +6 -5
  43. package/src/actions/LinkAction.tsx +3 -4
  44. package/src/authprovider.ts +3 -3
  45. package/src/buildRA.tsx +6 -2
  46. package/src/context.ts +4 -0
  47. package/src/dataprovider.ts +1 -2
  48. package/src/hooks/index.ts +3 -1
  49. package/src/hooks/useMuffinAdminOpts.ts +6 -0
  50. package/src/hooks/useMuffinResourceOpts.ts +8 -0
  51. package/src/index.tsx +11 -4
  52. package/src/types.ts +1 -0
  53. package/src/utils.tsx +6 -9
package/dist/types.d.ts CHANGED
@@ -42,6 +42,7 @@ export type AdminResourceProps = {
42
42
  limit: number;
43
43
  limitMax: number;
44
44
  actions: AdminAction[];
45
+ create: boolean;
45
46
  filters: AdminInput[];
46
47
  fields: AdminField[];
47
48
  show: boolean;
package/dist/utils.d.ts CHANGED
@@ -1,9 +1,6 @@
1
- /// <reference types="react" />
2
- import { AdminOpts } from "./types";
3
- export declare function setupAdmin<T>(adminType: string[], fc: (opts: any, props?: any) => T): void;
1
+ export declare function setupAdmin<T>(adminType: string[], fc: (props: any) => T): void;
4
2
  export declare function buildAdmin(adminType: string[], props?: {}): any;
5
3
  export declare function findBuilder(adminType: string[]): (props: any) => any;
6
- export declare const AdminPropsContext: import("react").Context<AdminOpts>;
7
4
  export type APIParams = {
8
5
  method?: string;
9
6
  query?: {
package/dist/utils.js CHANGED
@@ -13,31 +13,31 @@ import { jsx as _jsx } from "react/jsx-runtime";
13
13
  import * as icons from "@mui/icons-material";
14
14
  import { stringify } from "query-string";
15
15
  import { fetchUtils } from "ra-core";
16
- import { createContext } from "react";
17
16
  const builders = new Map();
18
17
  export function setupAdmin(adminType, fc) {
19
18
  const key = adminType.join("/");
20
19
  builders.set(key, fc);
21
20
  }
22
21
  export function buildAdmin(adminType, props = {}) {
23
- if (process.env.NODE_ENV == "development")
24
- console.log(adminType, props);
25
22
  const builder = findBuilder(adminType);
23
+ if (process.env.NODE_ENV == "development")
24
+ console.log(props);
26
25
  if (builder)
27
26
  return builder(props);
28
27
  console.warn(`No admin renderer found for ${adminType.join("/")}`);
29
28
  return null;
30
29
  }
31
30
  export function findBuilder(adminType) {
31
+ if (process.env.NODE_ENV == "development")
32
+ console.log(adminType);
32
33
  const key = [...adminType];
33
34
  while (key.length) {
34
- const render = builders.get(key.join("/"));
35
- if (render)
36
- return render;
35
+ const builder = builders.get(key.join("/"));
36
+ if (builder)
37
+ return builder;
37
38
  key.pop();
38
39
  }
39
40
  }
40
- export const AdminPropsContext = createContext(null);
41
41
  export const requestHeaders = {};
42
42
  export function makeRequest(url, params = {}) {
43
43
  const _a = params || {}, { data, query } = _a, opts = __rest(_a, ["data", "query"]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muffin-admin",
3
- "version": "2.7.3",
3
+ "version": "2.8.2",
4
4
  "description": "NPM package for https://github.com/klen/muffin-admin",
5
5
  "files": [
6
6
  "src",
@@ -2,19 +2,56 @@ import IconButton from "@mui/material/IconButton"
2
2
  import SvgIcon from "@mui/material/SvgIcon"
3
3
  import Tooltip from "@mui/material/Tooltip"
4
4
  import Typography from "@mui/material/Typography"
5
- import { Admin, AdminProps, AppBar, DataProvider, Layout, Login } from "react-admin"
6
- import { AdminOpts } from "./types"
7
- import { AdminPropsContext, buildAdmin, findBuilder, findIcon, setupAdmin } from "./utils"
8
-
9
- export function MuffinAdmin(opts: AdminOpts, props: AdminProps) {
10
- const { resources, auth, appBarLinks, adminProps, dashboard } = opts
11
- const children = resources?.map((resource) =>
12
- buildAdmin(["resource", resource.name], { ...resource })
13
- )
5
+ import {
6
+ Admin,
7
+ AdminProps,
8
+ AppBar,
9
+ AppBarProps,
10
+ AuthProvider,
11
+ DataProvider,
12
+ Layout,
13
+ LayoutProps,
14
+ Login,
15
+ } from "react-admin"
16
+
17
+ import { useMuffinAdminOpts } from "./hooks"
18
+ import { buildAdmin, findBuilder, findIcon, setupAdmin } from "./utils"
19
+
20
+ export function MuffinAdmin(props: AdminProps) {
21
+ const opts = useMuffinAdminOpts()
22
+ const { resources = [], auth, adminProps, apiUrl } = opts
14
23
 
15
24
  document.title = adminProps?.title || "Muffin Admin"
25
+ const authProvider = findBuilder(["authprovider"])(auth) as AuthProvider
26
+ const dataProvider = findBuilder(["dataprovider"])(apiUrl) as DataProvider
27
+
28
+ return (
29
+ <Admin
30
+ requireAuth={auth.required}
31
+ authProvider={authProvider}
32
+ dataProvider={dataProvider}
33
+ layout={findBuilder(["layout"])}
34
+ loginPage={findBuilder(["loginpage"])}
35
+ dashboard={findBuilder(["dashboard"])}
36
+ darkTheme={{ palette: { mode: "dark" } }}
37
+ {...props}
38
+ >
39
+ {resources?.map(({ name }) => buildAdmin(["resource", name], { name }))}
40
+ </Admin>
41
+ )
42
+ }
43
+
44
+ setupAdmin(["admin"], MuffinAdmin)
16
45
 
17
- const appBar = (props) => (
46
+ export function MuffinAdminLayout(props: LayoutProps) {
47
+ return <Layout {...props} appBar={findBuilder(["appbar"])} />
48
+ }
49
+
50
+ setupAdmin(["layout"], MuffinAdminLayout)
51
+
52
+ export function MuffinAppBar(props: AppBarProps) {
53
+ const { appBarLinks } = useMuffinAdminOpts()
54
+ return (
18
55
  <AppBar {...props}>
19
56
  <Typography
20
57
  variant="h6"
@@ -36,26 +73,9 @@ export function MuffinAdmin(opts: AdminOpts, props: AdminProps) {
36
73
  ))}
37
74
  </AppBar>
38
75
  )
39
-
40
- return (
41
- <AdminPropsContext.Provider value={opts}>
42
- <Admin
43
- authProvider={buildAdmin(["authprovider"], auth)}
44
- dataProvider={buildAdmin(["dataprovider"], opts) as unknown as DataProvider}
45
- layout={(props) => <Layout {...props} appBar={appBar} />}
46
- loginPage={findBuilder(["loginpage"])}
47
- dashboard={dashboard ? buildAdmin(["dashboard"], dashboard) : null}
48
- requireAuth={auth.required}
49
- darkTheme={{ palette: { mode: "dark" } }}
50
- {...props}
51
- >
52
- {children}
53
- </Admin>
54
- </AdminPropsContext.Provider>
55
- )
56
76
  }
57
77
 
58
- setupAdmin(["admin"], MuffinAdmin)
78
+ setupAdmin(["appbar"], MuffinAppBar)
59
79
 
60
80
  // Initialize login page
61
81
  setupAdmin(["loginpage"], Login)
@@ -6,17 +6,21 @@ import TableBody from "@mui/material/TableBody"
6
6
  import TableCell from "@mui/material/TableCell"
7
7
  import TableRow from "@mui/material/TableRow"
8
8
  import Typography from "@mui/material/Typography"
9
- import { AdminDashboardBlock, AdminOpts } from "./types"
9
+ import { useMuffinAdminOpts } from "./hooks"
10
+ import { AdminDashboardBlock } from "./types"
10
11
  import { setupAdmin } from "./utils"
11
12
 
12
- export function MuffinDashboard({ src }: { src: AdminOpts["dashboard"] }) {
13
+ export function MuffinDashboard() {
14
+ const { dashboard } = useMuffinAdminOpts()
13
15
  return (
14
16
  <Grid container spacing={1}>
15
- <AdminCards src={src} />
17
+ <AdminCards src={dashboard} />
16
18
  </Grid>
17
19
  )
18
20
  }
19
21
 
22
+ setupAdmin(["dashboard"], MuffinDashboard)
23
+
20
24
  function AdminCards({ src }: { src: AdminDashboardBlock | AdminDashboardBlock[] }) {
21
25
  if (Array.isArray(src))
22
26
  return (
@@ -60,5 +64,3 @@ const AdminTableView = ({ src }) => (
60
64
  </TableBody>
61
65
  </Table>
62
66
  )
63
-
64
- setupAdmin(["dashboard"], (dashboard) => () => <MuffinDashboard src={dashboard} />)
@@ -1,25 +1,21 @@
1
- import { Resource } from "react-admin"
2
- import { AdminResourceProps } from "./types"
3
- import { buildAdmin, findIcon, setupAdmin } from "./utils"
1
+ import { Resource, ResourceProps } from "react-admin"
2
+ import { useMuffinAdminOpts } from "./hooks"
3
+ import { findBuilder, findIcon, setupAdmin } from "./utils"
4
+
5
+ export function MuffinResource({ name, ...props }: ResourceProps) {
6
+ const adminOpts = useMuffinAdminOpts()
7
+ const opts = adminOpts?.resources.find((r) => r.name == name)
8
+ if (!opts) return null
4
9
 
5
- export function MuffinResource({
6
- name,
7
- create: createProps,
8
- edit: editProps,
9
- list: listProps,
10
- show: showProps,
11
- icon,
12
- ...props
13
- }: AdminResourceProps) {
14
10
  return (
15
11
  <Resource
16
12
  key={name}
17
13
  name={name}
18
- icon={findIcon(icon)}
19
- create={createProps ? buildAdmin(["create", name], createProps) : undefined}
20
- edit={editProps ? buildAdmin(["edit", name], editProps) : undefined}
21
- list={buildAdmin(["list", name], listProps)}
22
- show={buildAdmin(["show", name], showProps)}
14
+ icon={findIcon(opts.icon)}
15
+ create={findBuilder(["create", name])}
16
+ edit={findBuilder(["edit", name])}
17
+ list={findBuilder(["list", name])}
18
+ show={findBuilder(["show", name])}
23
19
  {...props}
24
20
  />
25
21
  )
@@ -1,19 +1,22 @@
1
- import { Create, ListButton, SimpleForm, TopToolbar, useResourceContext } from "react-admin"
1
+ import { Create, ListButton, SimpleForm, TopToolbar } from "react-admin"
2
2
  import { buildRA } from "./buildRA"
3
- import { AdminResourceProps } from "./types"
4
- import { buildAdmin, setupAdmin } from "./utils"
3
+ import { useMuffinResourceOpts } from "./hooks"
4
+ import { buildAdmin, findBuilder, setupAdmin } from "./utils"
5
5
 
6
- export function MuffinResourceCreate({ inputs }: { inputs: AdminResourceProps["create"] }) {
7
- const resourceName = useResourceContext()
6
+ export function MuffinResourceCreate() {
7
+ const { name, create } = useMuffinResourceOpts()
8
+ if (!create) return null
9
+
10
+ const Actions = findBuilder(["create-actions", name])
8
11
 
9
12
  return (
10
- <Create actions={buildAdmin(["create-actions", resourceName])}>
11
- <SimpleForm>{buildAdmin(["create-inputs", resourceName], inputs)}</SimpleForm>
13
+ <Create actions={<Actions />}>
14
+ <SimpleForm>{buildAdmin(["create-inputs", name], create)}</SimpleForm>
12
15
  </Create>
13
16
  )
14
17
  }
15
18
 
16
- setupAdmin(["create"], (inputs) => <MuffinResourceCreate inputs={inputs} />)
19
+ setupAdmin(["create"], MuffinResourceCreate)
17
20
 
18
21
  setupAdmin(["create-actions"], () => (
19
22
  <TopToolbar>
@@ -1,4 +1,3 @@
1
- import { useContext } from "react"
2
1
  import {
3
2
  DeleteButton,
4
3
  Edit,
@@ -8,28 +7,25 @@ import {
8
7
  SimpleForm,
9
8
  Toolbar,
10
9
  TopToolbar,
11
- useResourceContext,
12
10
  } from "react-admin"
13
11
  import { buildRA } from "./buildRA"
14
12
  import { ActionButton } from "./buttons"
15
- import { AdminAction, AdminOpts, AdminResourceProps } from "./types"
16
- import { AdminPropsContext, buildAdmin, setupAdmin } from "./utils"
13
+ import { useMuffinAdminOpts, useMuffinResourceOpts } from "./hooks"
14
+ import { AdminAction } from "./types"
15
+ import { buildAdmin, findBuilder, setupAdmin } from "./utils"
17
16
 
18
- export function MuffinResourceEdit(props: AdminResourceProps["edit"]) {
19
- const resourceName = useResourceContext()
17
+ export function MuffinResourceEdit() {
20
18
  const {
21
- adminProps: { mutationMode },
22
- } = useContext(AdminPropsContext) as AdminOpts
19
+ adminProps: { mutationMode = "optimistic" },
20
+ } = useMuffinAdminOpts()
21
+ const { edit, name } = useMuffinResourceOpts()
22
+ if (!edit) return null
23
23
 
24
- if (!props) return null
25
- const { actions, inputs, remove, ...opts } = props
24
+ const { actions, inputs, remove, ...opts } = edit
25
+ const Actions = findBuilder(["edit-actions", name])
26
26
 
27
27
  return (
28
- <Edit
29
- actions={buildAdmin(["edit-actions", resourceName], actions)}
30
- mutationMode={mutationMode || "optimistic"}
31
- {...opts}
32
- >
28
+ <Edit actions={<Actions actions={actions} />} mutationMode={mutationMode} {...opts}>
33
29
  <SimpleForm
34
30
  toolbar={
35
31
  <Toolbar>
@@ -44,20 +40,26 @@ export function MuffinResourceEdit(props: AdminResourceProps["edit"]) {
44
40
  </Toolbar>
45
41
  }
46
42
  >
47
- {buildAdmin(["edit-inputs", resourceName], inputs)}
43
+ {buildAdmin(["edit-inputs", name], inputs)}
48
44
  </SimpleForm>
49
45
  </Edit>
50
46
  )
51
47
  }
52
48
 
53
- setupAdmin(["edit"], (props) => <MuffinResourceEdit {...props} />)
54
- setupAdmin(["edit-actions"], (actions: AdminAction[]) => (
55
- <TopToolbar>
56
- {actions.map((props, idx) => (
57
- <ActionButton key={idx} {...props} />
58
- ))}
59
- <ListButton />
60
- <ShowButton />
61
- </TopToolbar>
62
- ))
49
+ setupAdmin(["edit"], MuffinResourceEdit)
50
+
51
+ function MuffinResourceEditActions({ actions }: { actions: AdminAction[] }) {
52
+ return (
53
+ <TopToolbar>
54
+ {actions.map((props, idx) => (
55
+ <ActionButton key={idx} {...props} />
56
+ ))}
57
+ <ListButton />
58
+ <ShowButton />
59
+ </TopToolbar>
60
+ )
61
+ }
62
+
63
+ setupAdmin(["edit-actions"], MuffinResourceEditActions)
64
+
63
65
  setupAdmin(["edit-inputs"], buildRA)
@@ -1,45 +1,50 @@
1
1
  import sortBy from "lodash/sortBy"
2
2
  import uniq from "lodash/uniq"
3
- import {
4
- BulkDeleteButton,
5
- Datagrid,
6
- EditButton,
7
- List,
8
- Pagination,
9
- useResourceContext,
10
- } from "react-admin"
3
+ import { BulkDeleteButton, Datagrid, EditButton, List, ListActions, Pagination } from "react-admin"
11
4
  import { buildRA } from "./buildRA"
12
5
  import { BulkActionButton } from "./buttons"
13
- import { AdminAction, AdminResourceProps } from "./types"
14
- import { buildAdmin, setupAdmin } from "./utils"
6
+ import { useMuffinResourceOpts } from "./hooks"
7
+ import { AdminAction } from "./types"
8
+ import { buildAdmin, findBuilder, setupAdmin } from "./utils"
9
+
10
+ export function MuffinResourceList() {
11
+ const { name, list } = useMuffinResourceOpts()
12
+ const { fields, create, edit, show, limit, limitMax, filters, actions, remove, sort } = list
13
+
14
+ const Actions = findBuilder(["list-actions", name])
15
15
 
16
- export function MuffinResourceList(props: AdminResourceProps["list"]) {
17
- const resourceName = useResourceContext()
18
- const { fields, edit, show, limit, limitMax, filters, actions, remove, sort } = props
19
16
  return (
20
17
  <List
21
18
  sort={sort}
22
19
  perPage={limit}
23
- filters={buildAdmin(["list-filters", resourceName], filters) || undefined}
24
- bulkActionButtons={buildAdmin(["list-actions", resourceName], { actions, remove })}
20
+ actions={<ListActions hasCreate={create} />}
21
+ filters={buildAdmin(["list-filters", name], filters)}
22
+ bulkActionButtons={<Actions actions={actions} remove={remove} />}
25
23
  pagination={
26
24
  <Pagination rowsPerPageOptions={sortBy(uniq([10, 25, 50, 100, limit, limitMax]))} />
27
25
  }
28
26
  >
29
27
  <Datagrid rowClick={show ? "show" : edit ? "edit" : false}>
30
- {buildAdmin(["list-fields", resourceName], fields)}
28
+ {buildAdmin(["list-fields", name], fields)}
31
29
  {edit && <EditButton />}
32
30
  </Datagrid>
33
31
  </List>
34
32
  )
35
33
  }
36
34
 
37
- setupAdmin(["list"], (props) => <MuffinResourceList {...props} />)
35
+ setupAdmin(["list"], MuffinResourceList)
38
36
  setupAdmin(["list-fields"], buildRA)
37
+
39
38
  setupAdmin(["list-filters"], buildRA)
40
- setupAdmin(
41
- ["list-actions"],
42
- ({ actions, remove }: { actions: AdminAction[]; remove?: boolean }) => (
39
+
40
+ function MuffinResourceListActions({
41
+ actions,
42
+ remove,
43
+ }: {
44
+ actions: AdminAction[]
45
+ remove?: boolean
46
+ }) {
47
+ return (
43
48
  <>
44
49
  {actions.map((props) => (
45
50
  <BulkActionButton key={props.id} {...props} />
@@ -47,4 +52,6 @@ setupAdmin(
47
52
  {remove && <BulkDeleteButton />}
48
53
  </>
49
54
  )
50
- )
55
+ }
56
+
57
+ setupAdmin(["list-actions"], MuffinResourceListActions)
@@ -9,16 +9,17 @@ import {
9
9
  import { LinkAction } from "./actions"
10
10
  import { buildRA } from "./buildRA"
11
11
  import { ActionButton } from "./buttons"
12
+ import { useMuffinResourceOpts } from "./hooks"
12
13
  import { AdminAction, AdminShowProps } from "./types"
13
14
  import { buildAdmin, findBuilder, setupAdmin } from "./utils"
14
15
 
15
- export function MuffinResourceShow(props: AdminShowProps) {
16
- const resourceName = useResourceContext()
17
- const ShowActions = findBuilder(["show-actions", resourceName])
16
+ export function MuffinResourceShow() {
17
+ const { show, name } = useMuffinResourceOpts()
18
+ const ShowActions = findBuilder(["show-actions", name])
18
19
 
19
20
  return (
20
- <Show actions={<ShowActions {...props} />}>
21
- <SimpleShowLayout>{buildAdmin(["show-fields", resourceName], props)}</SimpleShowLayout>
21
+ <Show actions={<ShowActions {...show} />}>
22
+ <SimpleShowLayout>{buildAdmin(["show-fields", name], show)}</SimpleShowLayout>
22
23
  </Show>
23
24
  )
24
25
  }
@@ -1,16 +1,15 @@
1
- import { useContext } from "react"
2
1
  import { useRecordContext, useResourceContext } from "react-admin"
3
2
  import LinkButton from "../buttons/LinkButton"
3
+ import { useMuffinAdminOpts } from "../hooks"
4
4
  import { AdminShowLink } from "../types"
5
- import { AdminPropsContext } from "../utils"
6
5
 
7
6
  export function LinkAction({ field, icon, ...props }: AdminShowLink & { resource: string }) {
8
- const adminProps = useContext(AdminPropsContext)
7
+ const { resources } = useMuffinAdminOpts()
9
8
  const record = useRecordContext()
10
9
  const currentResource = useResourceContext()
11
10
  if (!record) return null
12
11
 
13
- const resource = adminProps?.resources.find((r) => r.name === props.resource)
12
+ const resource = resources.find((r) => r.name === props.resource)
14
13
 
15
14
  return (
16
15
  <LinkButton
@@ -1,5 +1,5 @@
1
1
  import Cookies from "js-cookie"
2
- import { buildAdmin, makeRequest, requestHeaders, setupAdmin } from "."
2
+ import { findBuilder, makeRequest, requestHeaders, setupAdmin } from "."
3
3
  import { AdminOpts } from "./types"
4
4
 
5
5
  setupAdmin(
@@ -19,8 +19,8 @@ setupAdmin(["auth-storage-set"], ({ storage }) => (name, value) => {
19
19
  export function MuffinAuthProvider(props: AdminOpts["auth"]) {
20
20
  const { identityURL, authorizeURL, logoutURL, required, storageName } = props
21
21
 
22
- const authGet = buildAdmin(["auth-storage-get"], props)
23
- const authSet = buildAdmin(["auth-storage-set"], props)
22
+ const authGet = findBuilder(["auth-storage-get"])(props)
23
+ const authSet = findBuilder(["auth-storage-set"])(props)
24
24
 
25
25
  // Initialize request headers
26
26
  authSet(storageName, authGet(storageName))
package/src/buildRA.tsx CHANGED
@@ -37,7 +37,7 @@ import {
37
37
  import { AvatarField, EditableBooleanField, FKField, JsonField } from "./fields"
38
38
  import { FKInput, JsonInput } from "./inputs"
39
39
 
40
- export const UI: Record<string, JSX.ElementType> = {
40
+ const UI: Record<string, JSX.ElementType> = {
41
41
  // Fields
42
42
  BooleanField,
43
43
  ChipField,
@@ -97,6 +97,10 @@ export function buildRAComponent(name, props) {
97
97
  return <Item key={props.source} {...props} />
98
98
  }
99
99
 
100
- export function buildRA(items) {
100
+ export function buildRA(items: [string, Record<string, any>][]) {
101
101
  return items.map((item) => buildRAComponent(item[0], item[1]))
102
102
  }
103
+
104
+ export function registerUI(name, component) {
105
+ UI[name] = component
106
+ }
package/src/context.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { createContext } from "react"
2
+ import { AdminOpts } from "./types"
3
+
4
+ export const MuffinAdminContext = createContext<AdminOpts>(null)
@@ -1,7 +1,6 @@
1
- import { AdminOpts } from "./types"
2
1
  import { APIParams, makeRequest, setupAdmin } from "./utils"
3
2
 
4
- export function MuffinDataprovider({ apiUrl }: AdminOpts) {
3
+ export function MuffinDataprovider(apiUrl: string) {
5
4
  async function request(url: string, options?: APIParams) {
6
5
  if (!url.startsWith("/")) url = `${apiUrl}/${url}`
7
6
  const { json, headers } = await makeRequest(url, options)
@@ -1 +1,3 @@
1
- export * from './useAction'
1
+ export * from "./useAction"
2
+ export * from "./useMuffinAdminOpts"
3
+ export * from "./useMuffinResourceOpts"
@@ -0,0 +1,6 @@
1
+ import { useContext } from "react"
2
+ import { MuffinAdminContext } from "../context"
3
+
4
+ export function useMuffinAdminOpts() {
5
+ return useContext(MuffinAdminContext)
6
+ }
@@ -0,0 +1,8 @@
1
+ import { useResourceContext } from "react-admin"
2
+ import { useMuffinAdminOpts } from "./useMuffinAdminOpts"
3
+
4
+ export function useMuffinResourceOpts() {
5
+ const resource = useResourceContext()
6
+ const { resources } = useMuffinAdminOpts()
7
+ return resources.find((r) => r.name === resource)
8
+ }
package/src/index.tsx CHANGED
@@ -1,5 +1,8 @@
1
1
  import { createRoot } from "react-dom/client"
2
- import { buildAdmin } from "./utils"
2
+ import { MuffinAdmin } from "./MuffinAdmin"
3
+ import { MuffinAdminContext } from "./context"
4
+
5
+ export * from "./utils"
3
6
 
4
7
  export * from "./MuffinAdmin"
5
8
  export * from "./MuffinDashboard"
@@ -12,17 +15,21 @@ export * from "./actions"
12
15
  export * from "./authprovider"
13
16
  export * from "./buildRA"
14
17
  export * from "./buttons"
18
+ export * from "./context"
15
19
  export * from "./dataprovider"
16
20
  export * from "./fields"
17
21
  export * from "./hooks"
18
22
  export * from "./types"
19
- export * from "./utils"
20
23
 
21
24
  export async function initAdmin(prefix = "", containerId: string = "root") {
22
25
  const response = await fetch(`${prefix}/ra.json`)
23
- const props = await response.json()
26
+ const adminOpts = await response.json()
24
27
  const container = document.getElementById(containerId)
25
28
  if (!container) throw new Error(`Container #${containerId} not found`)
26
29
  const root = createRoot(container)
27
- root.render(buildAdmin(["admin"], props))
30
+ root.render(
31
+ <MuffinAdminContext.Provider value={adminOpts}>
32
+ <MuffinAdmin />
33
+ </MuffinAdminContext.Provider>
34
+ )
28
35
  }
package/src/types.ts CHANGED
@@ -43,6 +43,7 @@ export type AdminResourceProps = {
43
43
  limit: number
44
44
  limitMax: number
45
45
  actions: AdminAction[]
46
+ create: boolean
46
47
  filters: AdminInput[]
47
48
  fields: AdminField[]
48
49
  // Enable show button
package/src/utils.tsx CHANGED
@@ -1,36 +1,33 @@
1
1
  import * as icons from "@mui/icons-material"
2
2
  import { stringify } from "query-string"
3
3
  import { fetchUtils } from "ra-core"
4
- import { createContext } from "react"
5
- import { AdminOpts } from "./types"
6
4
 
7
5
  const builders = new Map<string, (props) => any>()
8
6
 
9
- export function setupAdmin<T>(adminType: string[], fc: (opts, props?) => T) {
7
+ export function setupAdmin<T>(adminType: string[], fc: (props) => T) {
10
8
  const key = adminType.join("/")
11
9
  builders.set(key, fc)
12
10
  }
13
11
 
14
12
  export function buildAdmin(adminType: string[], props = {}) {
15
- if (process.env.NODE_ENV == "development") console.log(adminType, props)
16
13
  const builder = findBuilder(adminType)
14
+ if (process.env.NODE_ENV == "development") console.log(props)
17
15
  if (builder) return builder(props)
18
16
 
19
17
  console.warn(`No admin renderer found for ${adminType.join("/")}`)
20
18
  return null
21
19
  }
22
20
 
23
- export function findBuilder(adminType: string[]) {
21
+ export function findBuilder(adminType: string[]): (props) => any {
22
+ if (process.env.NODE_ENV == "development") console.log(adminType)
24
23
  const key = [...adminType]
25
24
  while (key.length) {
26
- const render = builders.get(key.join("/"))
27
- if (render) return render
25
+ const builder = builders.get(key.join("/"))
26
+ if (builder) return builder
28
27
  key.pop()
29
28
  }
30
29
  }
31
30
 
32
- export const AdminPropsContext = createContext<AdminOpts | null>(null)
33
-
34
31
  export type APIParams = {
35
32
  method?: string
36
33
  query?: {