diff --git a/packages/core/src/contexts/resource/types.ts b/packages/core/src/contexts/resource/types.ts index 8edd12085bb64..7ce326590fd5f 100644 --- a/packages/core/src/contexts/resource/types.ts +++ b/packages/core/src/contexts/resource/types.ts @@ -12,6 +12,7 @@ export interface IResourceComponents { clone?: ResourceRoutePath; edit?: ResourceRoutePath; show?: ResourceRoutePath; + custom?: Array; } export type AnyString = string & { __ignore?: never }; diff --git a/packages/core/src/contexts/router/types.ts b/packages/core/src/contexts/router/types.ts index 19499d32aa8b1..8a781af9d5442 100644 --- a/packages/core/src/contexts/router/types.ts +++ b/packages/core/src/contexts/router/types.ts @@ -29,7 +29,7 @@ import type { BaseKey, CrudFilter, CrudSort } from "../data/types"; import type { IResourceItem } from "../resource/types"; -export type Action = "create" | "edit" | "list" | "show" | "clone"; +export type Action = "create" | "edit" | "list" | "show" | "clone" | "custom"; export type GoConfig = { to?: string; diff --git a/packages/core/src/definitions/helpers/router/get-action-routes-from-resource.ts b/packages/core/src/definitions/helpers/router/get-action-routes-from-resource.ts index 218388126b2a2..55fcb19175236 100644 --- a/packages/core/src/definitions/helpers/router/get-action-routes-from-resource.ts +++ b/packages/core/src/definitions/helpers/router/get-action-routes-from-resource.ts @@ -20,15 +20,29 @@ export const getActionRoutesFromResource = ( const actionList: Action[] = ["list", "show", "edit", "create", "clone"]; actionList.forEach((action) => { - const route: string | undefined = resource[action]; + const route = resource[action]; - if (route) { - actions.push({ - action, - resource, - route: `/${route.replace(/^\//, "")}`, + if (!route) return; + + if (action === "custom") { + const customRoutes = route as string[]; + + return customRoutes.forEach((r) => { + actions.push({ + action, + resource, + route: `/${r.replace(/^\//, "")}`, + }); }); } + + const regularRoute = route as string; + + return actions.push({ + action, + resource, + route: `/${regularRoute.replace(/^\//, "")}`, + }); }); return actions; diff --git a/packages/core/src/hooks/button/navigation-button/index.tsx b/packages/core/src/hooks/button/navigation-button/index.tsx index 60f757867a6f4..7a5fedb8488e1 100644 --- a/packages/core/src/hooks/button/navigation-button/index.tsx +++ b/packages/core/src/hooks/button/navigation-button/index.tsx @@ -69,6 +69,7 @@ export function useNavigationButton( switch (props.action) { case "create": case "list": + case "custom": return navigation[`${props.action}Url`](resource, props.meta); default: if (!id) return ""; diff --git a/packages/core/src/hooks/navigation/index.ts b/packages/core/src/hooks/navigation/index.ts index 559f76fbee3ee..afb166b6bfb44 100644 --- a/packages/core/src/hooks/navigation/index.ts +++ b/packages/core/src/hooks/navigation/index.ts @@ -165,6 +165,31 @@ export const useNavigation = () => { }) as string; }; + const customUrl = ( + resource: string | IResourceItem, + meta: MetaQuery = {}, + ) => { + const resourceItem = + typeof resource === "string" + ? pickResource(resource, resources) ?? { name: resource } + : resource; + + const customActionRoute = getActionRoutesFromResource( + resourceItem, + resources, + ).find((r) => r.action === "custom")?.route; + + if (!customActionRoute) { + return ""; + } + + return go({ + to: composeRoute(customActionRoute, resourceItem?.meta, parsed, meta), + type: "path", + query: meta.query, + }) as string; + }; + const create = ( resource: string | IResourceItem, type: HistoryType = "push", @@ -208,6 +233,14 @@ export const useNavigation = () => { handleUrl(listUrl(resource, meta), type); }; + const custom = ( + resource: string | IResourceItem, + type: HistoryType = "push", + meta: MetaQuery = {}, + ) => { + handleUrl(createUrl(resource, meta), type); + }; + return { create, createUrl, @@ -219,5 +252,7 @@ export const useNavigation = () => { showUrl, list, listUrl, + custom, + customUrl, }; };