@plumile/backoffice-react 0.1.195 → 0.1.197
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/README.md +7 -0
- package/lib/esm/components/backoffice/filters/BackofficeFilterAction.js +23 -20
- package/lib/esm/components/backoffice/filters/BackofficeFilterAction.js.map +1 -1
- package/lib/esm/components/backoffice/layout/breadcrumb/buildBreadcrumbs.js.map +1 -1
- package/lib/esm/components/backoffice/links/BackofficeInlineLink.js +19 -9
- package/lib/esm/components/backoffice/links/BackofficeInlineLink.js.map +1 -1
- package/lib/esm/components/backoffice/links/BackofficeLink.js +12 -8
- package/lib/esm/components/backoffice/links/BackofficeLink.js.map +1 -1
- package/lib/esm/components/backoffice/links/resolveBackofficeLink.js +64 -45
- package/lib/esm/components/backoffice/links/resolveBackofficeLink.js.map +1 -1
- package/lib/esm/components/backoffice/refs/BackofficeRelatedCountLink.js +30 -61
- package/lib/esm/components/backoffice/refs/BackofficeRelatedCountLink.js.map +1 -1
- package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js +1 -4
- package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js.map +1 -1
- package/lib/esm/components/backoffice/scaffolds/BackofficeListFilterContext.js +18 -27
- package/lib/esm/components/backoffice/scaffolds/BackofficeListFilterContext.js.map +1 -1
- package/lib/esm/hooks/useBackofficeListUrlState.js +27 -24
- package/lib/esm/hooks/useBackofficeListUrlState.js.map +1 -1
- package/lib/esm/pages/BackofficeDashboardWidgetContent.js +194 -227
- package/lib/esm/pages/BackofficeDashboardWidgetContent.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityDetailLayoutPage.js +107 -120
- package/lib/esm/pages/BackofficeEntityDetailLayoutPage.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityListDataPage.js +2 -8
- package/lib/esm/pages/BackofficeEntityListDataPage.js.map +1 -1
- package/lib/esm/pages/resolveDashboardTargetDestination.js +17 -0
- package/lib/esm/pages/resolveDashboardTargetDestination.js.map +1 -0
- package/lib/esm/router/createBackofficeRoutes.js +88 -99
- package/lib/esm/router/createBackofficeRoutes.js.map +1 -1
- package/lib/types/components/backoffice/filters/BackofficeFilterAction.d.ts.map +1 -1
- package/lib/types/components/backoffice/layout/breadcrumb/buildBreadcrumbs.d.ts +3 -3
- package/lib/types/components/backoffice/layout/breadcrumb/buildBreadcrumbs.d.ts.map +1 -1
- package/lib/types/components/backoffice/links/BackofficeInlineLink.d.ts.map +1 -1
- package/lib/types/components/backoffice/links/BackofficeLink.d.ts.map +1 -1
- package/lib/types/components/backoffice/links/resolveBackofficeLink.d.ts.map +1 -1
- package/lib/types/components/backoffice/links/types.d.ts +19 -15
- package/lib/types/components/backoffice/links/types.d.ts.map +1 -1
- package/lib/types/components/backoffice/refs/BackofficeRelatedCountLink.d.ts.map +1 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeEntityListScaffold.d.ts.map +1 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeListFilterContext.d.ts +0 -4
- package/lib/types/components/backoffice/scaffolds/BackofficeListFilterContext.d.ts.map +1 -1
- package/lib/types/hooks/useBackofficeListUrlState.d.ts.map +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/pages/BackofficeDashboardWidgetContent.d.ts.map +1 -1
- package/lib/types/pages/BackofficeEntityDetailLayoutPage.d.ts.map +1 -1
- package/lib/types/pages/BackofficeEntityListDataPage.d.ts.map +1 -1
- package/lib/types/pages/resolveDashboardTargetDestination.d.ts +5 -0
- package/lib/types/pages/resolveDashboardTargetDestination.d.ts.map +1 -0
- package/lib/types/router/createBackofficeRoutes.d.ts +0 -2
- package/lib/types/router/createBackofficeRoutes.d.ts.map +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -77,6 +77,13 @@ packages.
|
|
|
77
77
|
time, reports per-file progress, preserves partial failures, and lets
|
|
78
78
|
applications map descriptors into their own uploaded-file shape.
|
|
79
79
|
|
|
80
|
+
List navigation is driven by the synchronous `listNavigation` contract from
|
|
81
|
+
each entity manifest. Internal list targets keep `where` and `sort` structured;
|
|
82
|
+
`BackofficeLink`, dashboard widgets, relation links, and list filter actions
|
|
83
|
+
convert them to router `filters` and `query` only at the `Link` boundary. This
|
|
84
|
+
keeps the rendered href, preload, modified click, and normal navigation aligned
|
|
85
|
+
without loading the list facet.
|
|
86
|
+
|
|
80
87
|
### Relay and mutation helpers
|
|
81
88
|
|
|
82
89
|
- `RelayProvider`
|
|
@@ -6,42 +6,45 @@ import { action as o, icon as s } from "./backofficeFilterAction.css.js";
|
|
|
6
6
|
import { jsx as c } from "react/jsx-runtime";
|
|
7
7
|
import { useTranslation as l } from "react-i18next";
|
|
8
8
|
import u from "@plumile/router/routing/Link.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { setWhereValue as p } from "@plumile/backoffice-core/filters/where.js";
|
|
9
|
+
import { SidebarSearchSvg as d } from "@plumile/ui/icons/SidebarSearchSvg.js";
|
|
10
|
+
import { setWhereValue as f } from "@plumile/backoffice-core/filters/where.js";
|
|
12
11
|
//#region src/components/backoffice/filters/BackofficeFilterAction.tsx
|
|
13
|
-
var
|
|
14
|
-
let { t:
|
|
15
|
-
if (
|
|
16
|
-
let
|
|
17
|
-
if (
|
|
18
|
-
let
|
|
12
|
+
var p = (e, t) => e(t), m = (m) => {
|
|
13
|
+
let { t: h } = l(), { t: g } = e(), { filterColumnAliases: _ } = t(), { whereKey: v, value: y, path: b, label: x, listConfig: S } = m, C = a(), w = null;
|
|
14
|
+
if (S == null ? C != null && (w = C.config) : w = S, w == null) return null;
|
|
15
|
+
let T = i(w, v, b);
|
|
16
|
+
if (T == null && b == null && (T = r(w, v, _)), T == null || !n(T, y)) return null;
|
|
17
|
+
let E = p(T.label, h), D = x ?? g("filters.actions.filterBy", { label: E }), O = /* @__PURE__ */ c(d, {
|
|
19
18
|
width: 14,
|
|
20
19
|
height: 14,
|
|
21
20
|
className: s,
|
|
22
21
|
"aria-hidden": "true"
|
|
23
22
|
});
|
|
24
|
-
if (
|
|
23
|
+
if (C != null) return /* @__PURE__ */ c("button", {
|
|
25
24
|
type: "button",
|
|
26
25
|
className: o,
|
|
27
|
-
title:
|
|
28
|
-
"aria-label":
|
|
26
|
+
title: D,
|
|
27
|
+
"aria-label": D,
|
|
29
28
|
onClick: () => {
|
|
30
|
-
|
|
29
|
+
C.applyFilter(v, y, b);
|
|
31
30
|
},
|
|
32
|
-
children:
|
|
31
|
+
children: O
|
|
33
32
|
});
|
|
34
|
-
let
|
|
33
|
+
let k = w.listNavigation.defaults.where, A = f(k, v, y, b), j = w.listNavigation.encode({ where: A });
|
|
35
34
|
return /* @__PURE__ */ c(u, {
|
|
36
|
-
to:
|
|
35
|
+
to: {
|
|
36
|
+
pathname: w.routes.list,
|
|
37
|
+
filters: j.filters,
|
|
38
|
+
query: j.query
|
|
39
|
+
},
|
|
37
40
|
className: o,
|
|
38
|
-
title:
|
|
39
|
-
"aria-label":
|
|
41
|
+
title: D,
|
|
42
|
+
"aria-label": D,
|
|
40
43
|
preloadOnHover: "code",
|
|
41
|
-
children:
|
|
44
|
+
children: O
|
|
42
45
|
});
|
|
43
46
|
};
|
|
44
47
|
//#endregion
|
|
45
|
-
export {
|
|
48
|
+
export { m as BackofficeFilterAction, m as default };
|
|
46
49
|
|
|
47
50
|
//# sourceMappingURL=BackofficeFilterAction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeFilterAction.js","names":[],"sources":["../../../../../src/components/backoffice/filters/BackofficeFilterAction.tsx"],"sourcesContent":["import { type JSX } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Link from '@plumile/router/routing/Link.js';\nimport { SidebarSearchSvg } from '@plumile/ui/icons/SidebarSearchSvg.js';\n\nimport type {\n BackofficeRuntimeResolvedListFacetConfig,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\nimport type { TFunction } from 'i18next';\nimport {
|
|
1
|
+
{"version":3,"file":"BackofficeFilterAction.js","names":[],"sources":["../../../../../src/components/backoffice/filters/BackofficeFilterAction.tsx"],"sourcesContent":["import { type JSX } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Link from '@plumile/router/routing/Link.js';\nimport { SidebarSearchSvg } from '@plumile/ui/icons/SidebarSearchSvg.js';\n\nimport type {\n BackofficeRuntimeResolvedListFacetConfig,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\nimport type { TFunction } from 'i18next';\nimport { setWhereValue } from '@plumile/backoffice-core/filters/where.js';\n\nimport {\n canFilterValue,\n resolveFilterForColumn,\n resolveFilterForWhereKey,\n} from '../../../filters/filterHelpers.js';\nimport { useBackofficeConfig } from '../../../provider/BackofficeConfigContext.js';\nimport { useBackofficeListFilterContext } from '../scaffolds/BackofficeListFilterContext.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\n\nimport * as styles from './backofficeFilterAction.css.js';\n\nexport type BackofficeFilterActionProps = {\n whereKey: string;\n value: unknown;\n path?: readonly string[];\n label?: string;\n listConfig?: BackofficeRuntimeResolvedListFacetConfig;\n};\n\ntype ListFilterContext = {\n config: BackofficeRuntimeResolvedListFacetConfig;\n applyFilter: (\n whereKey: string,\n value: unknown,\n path?: readonly string[],\n ) => void;\n};\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nexport const BackofficeFilterAction = (\n props: BackofficeFilterActionProps,\n): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { filterColumnAliases } = useBackofficeConfig();\n const { whereKey, value, path, label, listConfig } = props;\n\n const getContext =\n useBackofficeListFilterContext as () => ListFilterContext | null;\n const context = getContext();\n let config: BackofficeRuntimeResolvedListFacetConfig | null = null;\n\n if (listConfig != null) {\n config = listConfig;\n } else if (context != null) {\n config = context.config;\n }\n\n if (config == null) {\n return null;\n }\n\n let filter = resolveFilterForWhereKey(config, whereKey, path);\n if (filter == null && path == null) {\n filter = resolveFilterForColumn(config, whereKey, filterColumnAliases);\n }\n if (filter == null || !canFilterValue(filter, value)) {\n return null;\n }\n\n const filterLabel = resolveLabel(filter.label, tApp);\n const actionLabel =\n label ??\n t('filters.actions.filterBy', {\n label: filterLabel,\n });\n const icon = (\n <SidebarSearchSvg\n width={14}\n height={14}\n className={styles.icon}\n aria-hidden=\"true\"\n />\n );\n\n if (context != null) {\n return (\n <button\n type=\"button\"\n className={styles.action}\n title={actionLabel}\n aria-label={actionLabel}\n onClick={() => {\n context.applyFilter(whereKey, value, path);\n }}\n >\n {icon}\n </button>\n );\n }\n\n const baseWhere = config.listNavigation.defaults.where;\n const nextWhere = setWhereValue(baseWhere, whereKey, value, path);\n const destination = config.listNavigation.encode({ where: nextWhere });\n\n return (\n <Link\n to={{\n pathname: config.routes.list,\n filters: destination.filters,\n query: destination.query,\n }}\n className={styles.action}\n title={actionLabel}\n aria-label={actionLabel}\n preloadOnHover=\"code\"\n >\n {icon}\n </Link>\n );\n};\n\nexport default BackofficeFilterAction;\n"],"mappings":";;;;;;;;;;;AAwCA,IAAM,KAAgB,GAAkB,MAC/B,EAAM,CAAI,GAGN,KACX,MACuB;CACvB,IAAM,EAAE,GAAG,MAAS,EAAe,GAC7B,EAAE,SAAM,EAA8B,GACtC,EAAE,2BAAwB,EAAoB,GAC9C,EAAE,aAAU,UAAO,SAAM,UAAO,kBAAe,GAI/C,IAAU,EAAW,GACvB,IAA0D;CAQ9D,IANI,KAAc,OAEP,KAAW,SACpB,IAAS,EAAQ,UAFjB,IAAS,GAKP,KAAU,MACZ,OAAO;CAGT,IAAI,IAAS,EAAyB,GAAQ,GAAU,CAAI;CAI5D,IAHI,KAAU,QAAQ,KAAQ,SAC5B,IAAS,EAAuB,GAAQ,GAAU,CAAmB,IAEnE,KAAU,QAAQ,CAAC,EAAe,GAAQ,CAAK,GACjD,OAAO;CAGT,IAAM,IAAc,EAAa,EAAO,OAAO,CAAI,GAC7C,IACJ,KACA,EAAE,4BAA4B,EAC5B,OAAO,EACT,CAAC,GACG,IACJ,kBAAC,GAAD;EACE,OAAO;EACP,QAAQ;EACR,WAAW;EACX,eAAY;CACb,CAAA;CAGH,IAAI,KAAW,MACb,OACE,kBAAC,UAAD;EACE,MAAK;EACL,WAAW;EACX,OAAO;EACP,cAAY;EACZ,eAAe;GACb,EAAQ,YAAY,GAAU,GAAO,CAAI;EAC3C;EAEC,UAAA;CACK,CAAA;CAIZ,IAAM,IAAY,EAAO,eAAe,SAAS,OAC3C,IAAY,EAAc,GAAW,GAAU,GAAO,CAAI,GAC1D,IAAc,EAAO,eAAe,OAAO,EAAE,OAAO,EAAU,CAAC;CAErE,OACE,kBAAC,GAAD;EACE,IAAI;GACF,UAAU,EAAO,OAAO;GACxB,SAAS,EAAY;GACrB,OAAO,EAAY;EACrB;EACA,WAAW;EACX,OAAO;EACP,cAAY;EACZ,gBAAe;EAEd,UAAA;CACG,CAAA;AAEV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildBreadcrumbs.js","names":[],"sources":["../../../../../../src/components/backoffice/layout/breadcrumb/buildBreadcrumbs.ts"],"sourcesContent":["import type { TFunction } from 'i18next';\n\nimport type {\n BackofficeEntityManifestMap,\n
|
|
1
|
+
{"version":3,"file":"buildBreadcrumbs.js","names":[],"sources":["../../../../../../src/components/backoffice/layout/breadcrumb/buildBreadcrumbs.ts"],"sourcesContent":["import type { TFunction } from 'i18next';\n\nimport type {\n BackofficeEntityManifestMap,\n BackofficeManifestToolId,\n BackofficeResolvedDetailLayoutFacetConfig,\n BackofficeResolvedDetailPageFacetConfig,\n BackofficeRuntimeResolvedListFacetConfig,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\n\nimport type { BackofficeTopbarBreadcrumbItem } from './types.js';\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nexport const resolveEntityTitleFromDetailHeader = <\n LayoutView extends object,\n>(input: {\n layoutView: LayoutView;\n detailHeader: BackofficeResolvedDetailLayoutFacetConfig['header'];\n tApp: TFunction;\n}): string => {\n const titleValue = input.detailHeader.titleValue?.(\n input.layoutView,\n input.tApp,\n );\n const maybeId = (input.layoutView as { id?: unknown }).id;\n let normalizedId: string | null = null;\n if (typeof maybeId === 'string' && maybeId.trim() !== '') {\n normalizedId = maybeId.trim();\n }\n if (\n typeof titleValue === 'string' &&\n titleValue.trim() !== '' &&\n titleValue.trim() !== normalizedId\n ) {\n return titleValue;\n }\n\n const title = resolveLabel(input.detailHeader.title, input.tApp);\n if (title.trim() !== '') {\n return title;\n }\n\n return '';\n};\n\nexport const buildDashboardBreadcrumb = (\n t: TFunction,\n): readonly BackofficeTopbarBreadcrumbItem[] => {\n return [\n {\n kind: 'current',\n target: { kind: 'dashboard' },\n label: t('sidebar.items.dashboard'),\n },\n ];\n};\n\nexport const buildHubBreadcrumb = <\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n>(input: {\n id: string;\n title: string;\n}): readonly BackofficeTopbarBreadcrumbItem<TManifest>[] => {\n return [\n {\n kind: 'current',\n target: { kind: 'hub', hubId: input.id },\n label: input.title,\n },\n ];\n};\n\nexport const buildEntityListBreadcrumb = (\n config: BackofficeRuntimeResolvedListFacetConfig,\n tApp: TFunction,\n): readonly BackofficeTopbarBreadcrumbItem[] => {\n return [\n {\n kind: 'current',\n target: {\n kind: 'entity-list',\n entityId: config.id,\n },\n label: resolveLabel(config.label, tApp),\n },\n ];\n};\n\nexport const buildEntityDetailBreadcrumb = (input: {\n config:\n | BackofficeResolvedDetailLayoutFacetConfig\n | BackofficeResolvedDetailPageFacetConfig;\n tApp: TFunction;\n entityId: string;\n layoutView: unknown;\n pageLabel: string;\n pageId?: string;\n}): readonly BackofficeTopbarBreadcrumbItem[] => {\n const listLabel = resolveLabel(input.config.label, input.tApp);\n const entityTitle = resolveEntityTitleFromDetailHeader({\n layoutView: input.layoutView as object,\n detailHeader: input.config.header,\n tApp: input.tApp,\n });\n const currentTarget = {\n kind: 'entity-detail-page',\n entityId: input.config.id,\n id: input.entityId,\n pageId: input.pageId ?? input.pageLabel,\n } as unknown as BackofficeTopbarBreadcrumbItem['target'];\n\n return [\n {\n kind: 'link',\n target: {\n kind: 'entity-list',\n entityId: input.config.id,\n },\n label: listLabel,\n },\n {\n kind: 'link',\n target: {\n kind: 'entity-detail',\n entityId: input.config.id,\n id: input.entityId,\n },\n label: entityTitle,\n },\n {\n kind: 'current',\n target: currentTarget,\n label: input.pageLabel,\n },\n ];\n};\n\nexport const buildToolBreadcrumb = <\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n>(input: {\n id?: BackofficeManifestToolId<TManifest> | string;\n title: string;\n}): readonly BackofficeTopbarBreadcrumbItem<TManifest>[] => {\n let target: BackofficeTopbarBreadcrumbItem<TManifest>['target'] = {\n kind: 'href',\n href: `/tools/${input.title}`,\n };\n if (input.id != null) {\n target = {\n kind: 'tool',\n toolId: input.id as BackofficeManifestToolId<TManifest>,\n };\n }\n return [\n {\n kind: 'current',\n target,\n label: input.title,\n },\n ];\n};\n"],"mappings":";AAaA,IAAM,KAAgB,GAAkB,MAC/B,EAAM,CAAI,GAGN,KAEX,MAIY;CACZ,IAAM,IAAa,EAAM,aAAa,aACpC,EAAM,YACN,EAAM,IACR,GACM,IAAW,EAAM,WAAgC,IACnD,IAA8B;CAIlC,IAHI,OAAO,KAAY,YAAY,EAAQ,KAAK,MAAM,OACpD,IAAe,EAAQ,KAAK,IAG5B,OAAO,KAAe,YACtB,EAAW,KAAK,MAAM,MACtB,EAAW,KAAK,MAAM,GAEtB,OAAO;CAGT,IAAM,IAAQ,EAAa,EAAM,aAAa,OAAO,EAAM,IAAI;CAK/D,OAJI,EAAM,KAAK,MAAM,KAId,KAHE;AAIX,GAEa,KACX,MAEO,CACL;CACE,MAAM;CACN,QAAQ,EAAE,MAAM,YAAY;CAC5B,OAAO,EAAE,yBAAyB;AACpC,CACF,GAGW,KAEX,MAIO,CACL;CACE,MAAM;CACN,QAAQ;EAAE,MAAM;EAAO,OAAO,EAAM;CAAG;CACvC,OAAO,EAAM;AACf,CACF,GAGW,KACX,GACA,MAEO,CACL;CACE,MAAM;CACN,QAAQ;EACN,MAAM;EACN,UAAU,EAAO;CACnB;CACA,OAAO,EAAa,EAAO,OAAO,CAAI;AACxC,CACF,GAGW,KAA+B,MASK;CAC/C,IAAM,IAAY,EAAa,EAAM,OAAO,OAAO,EAAM,IAAI,GACvD,IAAc,EAAmC;EACrD,YAAY,EAAM;EAClB,cAAc,EAAM,OAAO;EAC3B,MAAM,EAAM;CACd,CAAC,GACK,IAAgB;EACpB,MAAM;EACN,UAAU,EAAM,OAAO;EACvB,IAAI,EAAM;EACV,QAAQ,EAAM,UAAU,EAAM;CAChC;CAEA,OAAO;EACL;GACE,MAAM;GACN,QAAQ;IACN,MAAM;IACN,UAAU,EAAM,OAAO;GACzB;GACA,OAAO;EACT;EACA;GACE,MAAM;GACN,QAAQ;IACN,MAAM;IACN,UAAU,EAAM,OAAO;IACvB,IAAI,EAAM;GACZ;GACA,OAAO;EACT;EACA;GACE,MAAM;GACN,QAAQ;GACR,OAAO,EAAM;EACf;CACF;AACF,GAEa,KAEX,MAG0D;CAC1D,IAAI,IAA8D;EAChE,MAAM;EACN,MAAM,UAAU,EAAM;CACxB;CAOA,OANI,EAAM,MAAM,SACd,IAAS;EACP,MAAM;EACN,QAAQ,EAAM;CAChB,IAEK,CACL;EACE,MAAM;EACN;EACA,OAAO,EAAM;CACf,CACF;AACF"}
|
|
@@ -5,23 +5,33 @@ import r from "@plumile/router/routing/Link.js";
|
|
|
5
5
|
//#region src/components/backoffice/links/BackofficeInlineLink.tsx
|
|
6
6
|
var i = (e, t, n) => t ?? (n || e.kind === "href" ? "none" : "code-and-data"), a = ({ target: a, label: o, className: s, title: c, ariaLabel: l, icon: u = "auto", openInNewTab: d = !1, preloadOnHover: f, endAdornment: p, onClick: m, children: h }) => {
|
|
7
7
|
let g = t(a, { label: h ?? o }), _ = {};
|
|
8
|
-
|
|
8
|
+
d && (_ = {
|
|
9
9
|
target: "_blank",
|
|
10
10
|
rel: "noreferrer"
|
|
11
|
-
})
|
|
12
|
-
|
|
11
|
+
});
|
|
12
|
+
let v = /* @__PURE__ */ n(e, {
|
|
13
|
+
icon: g.icon,
|
|
14
|
+
label: g.label,
|
|
15
|
+
showIcon: u === "auto",
|
|
16
|
+
endAdornment: p
|
|
17
|
+
});
|
|
18
|
+
return g.kind === "external" ? /* @__PURE__ */ n("a", {
|
|
19
|
+
href: g.href,
|
|
20
|
+
className: s,
|
|
21
|
+
title: c,
|
|
22
|
+
"aria-label": l,
|
|
23
|
+
onClick: m,
|
|
24
|
+
..._,
|
|
25
|
+
children: v
|
|
26
|
+
}) : /* @__PURE__ */ n(r, {
|
|
27
|
+
to: g.destination,
|
|
13
28
|
className: s,
|
|
14
29
|
title: c,
|
|
15
30
|
"aria-label": l,
|
|
16
31
|
onClick: m,
|
|
17
32
|
preloadOnHover: i(a, f, d),
|
|
18
33
|
..._,
|
|
19
|
-
children:
|
|
20
|
-
icon: g.icon,
|
|
21
|
-
label: g.label,
|
|
22
|
-
showIcon: u === "auto",
|
|
23
|
-
endAdornment: p
|
|
24
|
-
})
|
|
34
|
+
children: v
|
|
25
35
|
});
|
|
26
36
|
};
|
|
27
37
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeInlineLink.js","names":[],"sources":["../../../../../src/components/backoffice/links/BackofficeInlineLink.tsx"],"sourcesContent":["import { type JSX, type MouseEventHandler, type ReactNode } from 'react';\nimport Link, { type LinkHoverPreload } from '@plumile/router/routing/Link.js';\n\nimport type { BackofficeEntityManifestMap } from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeLinkContent } from './BackofficeLinkContent.js';\nimport type { BackofficeLinkTarget } from './types.js';\nimport { useBackofficeLink } from './useBackofficeLink.js';\n\nexport type BackofficeInlineLinkProps<\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n> = {\n target: BackofficeLinkTarget<TManifest>;\n label?: ReactNode;\n className?: string;\n title?: string;\n ariaLabel?: string;\n icon?: 'auto' | 'none';\n openInNewTab?: boolean;\n preloadOnHover?: LinkHoverPreload;\n endAdornment?: ReactNode;\n onClick?: MouseEventHandler<HTMLAnchorElement>;\n children?: ReactNode;\n};\n\nconst shouldPreloadBackofficeTarget = (\n target: BackofficeLinkTarget,\n preloadOnHover: LinkHoverPreload | undefined,\n openInNewTab: boolean,\n): LinkHoverPreload => {\n if (preloadOnHover != null) {\n return preloadOnHover;\n }\n if (openInNewTab) {\n return 'none';\n }\n if (target.kind === 'href') {\n return 'none';\n }\n return 'code-and-data';\n};\n\nexport const BackofficeInlineLink = <\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n>({\n target,\n label,\n className,\n title,\n ariaLabel,\n icon = 'auto',\n openInNewTab = false,\n preloadOnHover,\n endAdornment,\n onClick,\n children,\n}: BackofficeInlineLinkProps<TManifest>): JSX.Element => {\n const link = useBackofficeLink(target, {\n label: children ?? label,\n });\n\n let linkProps: { target?: '_blank'; rel?: 'noreferrer' } = {};\n if (openInNewTab) {\n linkProps = { target: '_blank', rel: 'noreferrer' };\n }\n\n return (\n <Link\n to={link.
|
|
1
|
+
{"version":3,"file":"BackofficeInlineLink.js","names":[],"sources":["../../../../../src/components/backoffice/links/BackofficeInlineLink.tsx"],"sourcesContent":["import { type JSX, type MouseEventHandler, type ReactNode } from 'react';\nimport Link, { type LinkHoverPreload } from '@plumile/router/routing/Link.js';\n\nimport type { BackofficeEntityManifestMap } from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeLinkContent } from './BackofficeLinkContent.js';\nimport type { BackofficeLinkTarget } from './types.js';\nimport { useBackofficeLink } from './useBackofficeLink.js';\n\nexport type BackofficeInlineLinkProps<\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n> = {\n target: BackofficeLinkTarget<TManifest>;\n label?: ReactNode;\n className?: string;\n title?: string;\n ariaLabel?: string;\n icon?: 'auto' | 'none';\n openInNewTab?: boolean;\n preloadOnHover?: LinkHoverPreload;\n endAdornment?: ReactNode;\n onClick?: MouseEventHandler<HTMLAnchorElement>;\n children?: ReactNode;\n};\n\nconst shouldPreloadBackofficeTarget = (\n target: BackofficeLinkTarget,\n preloadOnHover: LinkHoverPreload | undefined,\n openInNewTab: boolean,\n): LinkHoverPreload => {\n if (preloadOnHover != null) {\n return preloadOnHover;\n }\n if (openInNewTab) {\n return 'none';\n }\n if (target.kind === 'href') {\n return 'none';\n }\n return 'code-and-data';\n};\n\nexport const BackofficeInlineLink = <\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n>({\n target,\n label,\n className,\n title,\n ariaLabel,\n icon = 'auto',\n openInNewTab = false,\n preloadOnHover,\n endAdornment,\n onClick,\n children,\n}: BackofficeInlineLinkProps<TManifest>): JSX.Element => {\n const link = useBackofficeLink(target, {\n label: children ?? label,\n });\n\n let linkProps: { target?: '_blank'; rel?: 'noreferrer' } = {};\n if (openInNewTab) {\n linkProps = { target: '_blank', rel: 'noreferrer' };\n }\n const content = (\n <BackofficeLinkContent\n icon={link.icon}\n label={link.label}\n showIcon={icon === 'auto'}\n endAdornment={endAdornment}\n />\n );\n\n if (link.kind === 'external') {\n return (\n <a\n href={link.href}\n className={className}\n title={title}\n aria-label={ariaLabel}\n onClick={onClick}\n {...linkProps}\n >\n {content}\n </a>\n );\n }\n\n return (\n <Link\n to={link.destination}\n className={className}\n title={title}\n aria-label={ariaLabel}\n onClick={onClick}\n preloadOnHover={shouldPreloadBackofficeTarget(\n target,\n preloadOnHover,\n openInNewTab,\n )}\n {...linkProps}\n >\n {content}\n </Link>\n );\n};\n\nexport default BackofficeInlineLink;\n"],"mappings":";;;;;AAyBA,IAAM,KACJ,GACA,GACA,MAEI,MAGA,KAGA,EAAO,SAAS,SACX,SAEF,kBAGI,KAEX,EACA,WACA,UACA,cACA,UACA,cACA,UAAO,QACP,kBAAe,IACf,mBACA,iBACA,YACA,kBACuD;CACvD,IAAM,IAAO,EAAkB,GAAQ,EACrC,OAAO,KAAY,EACrB,CAAC,GAEG,IAAuD,CAAC;CAC5D,AAAI,MACF,IAAY;EAAE,QAAQ;EAAU,KAAK;CAAa;CAEpD,IAAM,IACJ,kBAAC,GAAD;EACE,MAAM,EAAK;EACX,OAAO,EAAK;EACZ,UAAU,MAAS;EACL;CACf,CAAA;CAkBH,OAfI,EAAK,SAAS,aAEd,kBAAC,KAAD;EACE,MAAM,EAAK;EACA;EACJ;EACP,cAAY;EACH;EACT,GAAI;EAEH,UAAA;CACA,CAAA,IAKL,kBAAC,GAAD;EACE,IAAI,EAAK;EACE;EACJ;EACP,cAAY;EACH;EACT,gBAAgB,EACd,GACA,GACA,CACF;EACA,GAAI;EAEH,UAAA;CACG,CAAA;AAEV"}
|
|
@@ -4,16 +4,20 @@ import { jsx as n } from "react/jsx-runtime";
|
|
|
4
4
|
import r from "@plumile/router/routing/Link.js";
|
|
5
5
|
//#region src/components/backoffice/links/BackofficeLink.tsx
|
|
6
6
|
var i = (e, t) => t ?? (e.kind === "href" ? "none" : "code-and-data"), a = ({ target: a, label: o, className: s, icon: c = "auto", preloadOnHover: l, children: u }) => {
|
|
7
|
-
let d = t(a, { label: u ?? o })
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
let d = t(a, { label: u ?? o }), f = /* @__PURE__ */ n(e, {
|
|
8
|
+
icon: d.icon,
|
|
9
|
+
label: d.label,
|
|
10
|
+
showIcon: c === "auto"
|
|
11
|
+
});
|
|
12
|
+
return d.kind === "external" ? /* @__PURE__ */ n("a", {
|
|
13
|
+
href: d.href,
|
|
14
|
+
className: s,
|
|
15
|
+
children: f
|
|
16
|
+
}) : /* @__PURE__ */ n(r, {
|
|
17
|
+
to: d.destination,
|
|
10
18
|
className: s,
|
|
11
19
|
preloadOnHover: i(a, l),
|
|
12
|
-
children:
|
|
13
|
-
icon: d.icon,
|
|
14
|
-
label: d.label,
|
|
15
|
-
showIcon: c === "auto"
|
|
16
|
-
})
|
|
20
|
+
children: f
|
|
17
21
|
});
|
|
18
22
|
};
|
|
19
23
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeLink.js","names":[],"sources":["../../../../../src/components/backoffice/links/BackofficeLink.tsx"],"sourcesContent":["import { type JSX, type ReactNode } from 'react';\nimport Link, { type LinkHoverPreload } from '@plumile/router/routing/Link.js';\n\nimport type { BackofficeEntityManifestMap } from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeLinkContent } from './BackofficeLinkContent.js';\nimport type { BackofficeLinkTarget } from './types.js';\nimport { useBackofficeLink } from './useBackofficeLink.js';\n\nexport type BackofficeLinkProps<\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n> = {\n target: BackofficeLinkTarget<TManifest>;\n label?: ReactNode;\n className?: string;\n icon?: 'auto' | 'none';\n preloadOnHover?: LinkHoverPreload;\n children?: ReactNode;\n};\n\nconst shouldPreloadBackofficeTarget = (\n target: BackofficeLinkTarget,\n preloadOnHover: LinkHoverPreload | undefined,\n): LinkHoverPreload => {\n if (preloadOnHover != null) {\n return preloadOnHover;\n }\n if (target.kind === 'href') {\n return 'none';\n }\n return 'code-and-data';\n};\n\nexport const BackofficeLink = <\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n>({\n target,\n label,\n className,\n icon = 'auto',\n preloadOnHover,\n children,\n}: BackofficeLinkProps<TManifest>): JSX.Element => {\n const link = useBackofficeLink(target, {\n label: children ?? label,\n });\n
|
|
1
|
+
{"version":3,"file":"BackofficeLink.js","names":[],"sources":["../../../../../src/components/backoffice/links/BackofficeLink.tsx"],"sourcesContent":["import { type JSX, type ReactNode } from 'react';\nimport Link, { type LinkHoverPreload } from '@plumile/router/routing/Link.js';\n\nimport type { BackofficeEntityManifestMap } from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeLinkContent } from './BackofficeLinkContent.js';\nimport type { BackofficeLinkTarget } from './types.js';\nimport { useBackofficeLink } from './useBackofficeLink.js';\n\nexport type BackofficeLinkProps<\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n> = {\n target: BackofficeLinkTarget<TManifest>;\n label?: ReactNode;\n className?: string;\n icon?: 'auto' | 'none';\n preloadOnHover?: LinkHoverPreload;\n children?: ReactNode;\n};\n\nconst shouldPreloadBackofficeTarget = (\n target: BackofficeLinkTarget,\n preloadOnHover: LinkHoverPreload | undefined,\n): LinkHoverPreload => {\n if (preloadOnHover != null) {\n return preloadOnHover;\n }\n if (target.kind === 'href') {\n return 'none';\n }\n return 'code-and-data';\n};\n\nexport const BackofficeLink = <\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n>({\n target,\n label,\n className,\n icon = 'auto',\n preloadOnHover,\n children,\n}: BackofficeLinkProps<TManifest>): JSX.Element => {\n const link = useBackofficeLink(target, {\n label: children ?? label,\n });\n const content = (\n <BackofficeLinkContent\n icon={link.icon}\n label={link.label}\n showIcon={icon === 'auto'}\n />\n );\n\n if (link.kind === 'external') {\n return (\n <a href={link.href} className={className}>\n {content}\n </a>\n );\n }\n\n return (\n <Link\n to={link.destination}\n className={className}\n preloadOnHover={shouldPreloadBackofficeTarget(target, preloadOnHover)}\n >\n {content}\n </Link>\n );\n};\n\nexport default BackofficeLink;\n"],"mappings":";;;;;AAoBA,IAAM,KACJ,GACA,MAEI,MAGA,EAAO,SAAS,SACX,SAEF,kBAGI,KAEX,EACA,WACA,UACA,cACA,UAAO,QACP,mBACA,kBACiD;CACjD,IAAM,IAAO,EAAkB,GAAQ,EACrC,OAAO,KAAY,EACrB,CAAC,GACK,IACJ,kBAAC,GAAD;EACE,MAAM,EAAK;EACX,OAAO,EAAK;EACZ,UAAU,MAAS;CACpB,CAAA;CAWH,OARI,EAAK,SAAS,aAEd,kBAAC,KAAD;EAAG,MAAM,EAAK;EAAiB;EAC5B,UAAA;CACA,CAAA,IAKL,kBAAC,GAAD;EACE,IAAI,EAAK;EACE;EACX,gBAAgB,EAA8B,GAAQ,CAAc;EAEnE,UAAA;CACG,CAAA;AAEV"}
|
|
@@ -1,89 +1,108 @@
|
|
|
1
1
|
import { joinBackofficePath as e, resolveSidebarHub as t } from "../layout/sidebarUtils.js";
|
|
2
2
|
import { resolveBackofficeTargetIcon as n } from "./resolveBackofficeTargetIcon.js";
|
|
3
|
-
import { buildBackofficeFallbackListHref as r } from "@plumile/backoffice-core/state/buildListHref.js";
|
|
4
3
|
//#region src/components/backoffice/links/resolveBackofficeLink.ts
|
|
5
|
-
var
|
|
4
|
+
var r = (e, t) => {
|
|
6
5
|
let n = e[t];
|
|
7
6
|
if (n == null) throw Error(`Unknown backoffice entity: ${t}`);
|
|
8
7
|
return n;
|
|
9
|
-
},
|
|
8
|
+
}, i = (e, n) => {
|
|
10
9
|
let r = e?.hubs?.[n];
|
|
11
10
|
if (r != null) return r.href;
|
|
12
11
|
for (let r of Object.values(e?.groups ?? {})) for (let i of r.items ?? []) if (i.kind === "hub" && i.id === n) return t(i, e).href;
|
|
13
12
|
throw Error(`Unknown backoffice hub: ${n}`);
|
|
14
|
-
},
|
|
13
|
+
}, a = (e, n, r) => {
|
|
15
14
|
let i = e?.hubs?.[n];
|
|
16
15
|
if (i != null) return i.title(r);
|
|
17
16
|
for (let i of Object.values(e?.groups ?? {})) for (let a of i.items ?? []) if (a.kind === "hub" && a.id === n) return t(a, e).title(r);
|
|
18
17
|
return n;
|
|
19
|
-
},
|
|
20
|
-
let
|
|
18
|
+
}, o = (t) => {
|
|
19
|
+
let o = t.manifest, s = t.sidebar, c = t.target, l = n({
|
|
21
20
|
target: t.target,
|
|
22
21
|
sidebar: t.sidebar
|
|
23
22
|
});
|
|
24
|
-
if (
|
|
25
|
-
let n =
|
|
23
|
+
if (c.kind === "dashboard") {
|
|
24
|
+
let n = c.id ?? "dashboard", r = t.dashboardHref ?? "/";
|
|
26
25
|
return n === "dashboard" ? {
|
|
26
|
+
kind: "internal",
|
|
27
27
|
id: "dashboard",
|
|
28
|
-
|
|
28
|
+
destination: { pathname: r },
|
|
29
29
|
label: t.label ?? t.dashboardLabel ?? "Dashboard",
|
|
30
|
-
icon:
|
|
30
|
+
icon: l
|
|
31
31
|
} : {
|
|
32
|
+
kind: "internal",
|
|
32
33
|
id: `dashboard-${n}`,
|
|
33
|
-
|
|
34
|
+
destination: { pathname: e(r, `dashboard/${n}`) },
|
|
34
35
|
label: t.label ?? n,
|
|
35
|
-
icon:
|
|
36
|
+
icon: l
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
|
-
if (
|
|
39
|
-
let e =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
if (c.kind === "entity-list") {
|
|
40
|
+
let e = r(o, c.entityId);
|
|
41
|
+
if (!e.hasList) throw Error(`Backoffice entity has no list: ${c.entityId}`);
|
|
42
|
+
let n = e.listNavigation.encode(c.state ?? {});
|
|
43
|
+
return {
|
|
44
|
+
kind: "internal",
|
|
45
|
+
id: `${c.entityId}-list`,
|
|
46
|
+
destination: {
|
|
47
|
+
pathname: e.routes.list,
|
|
48
|
+
filters: n.filters,
|
|
49
|
+
query: n.query
|
|
50
|
+
},
|
|
43
51
|
label: t.label ?? e.label(t.tApp),
|
|
44
|
-
icon:
|
|
52
|
+
icon: l
|
|
45
53
|
};
|
|
46
54
|
}
|
|
47
|
-
if (
|
|
48
|
-
let e =
|
|
55
|
+
if (c.kind === "entity-detail") {
|
|
56
|
+
let e = r(o, c.entityId);
|
|
49
57
|
return {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
58
|
+
kind: "internal",
|
|
59
|
+
id: `${c.entityId}-entity-${c.id}`,
|
|
60
|
+
destination: { pathname: e.routes.detail(c.id) },
|
|
61
|
+
label: t.label ?? c.id,
|
|
62
|
+
icon: l
|
|
54
63
|
};
|
|
55
64
|
}
|
|
56
|
-
if (
|
|
57
|
-
let e =
|
|
65
|
+
if (c.kind === "entity-detail-page") {
|
|
66
|
+
let e = r(o, c.entityId);
|
|
58
67
|
return {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
kind: "internal",
|
|
69
|
+
id: `${c.entityId}-page-${c.id}-${c.pageId}`,
|
|
70
|
+
destination: { pathname: e.routes.detailPage(c.id, c.pageId) },
|
|
71
|
+
label: t.label ?? c.pageId,
|
|
72
|
+
icon: l
|
|
63
73
|
};
|
|
64
74
|
}
|
|
65
|
-
if (
|
|
66
|
-
let e =
|
|
75
|
+
if (c.kind === "tool") {
|
|
76
|
+
let e = r(o, c.toolId);
|
|
67
77
|
return {
|
|
68
|
-
|
|
69
|
-
|
|
78
|
+
kind: "internal",
|
|
79
|
+
id: `tool-${c.toolId}`,
|
|
80
|
+
destination: { pathname: e.routes.list },
|
|
70
81
|
label: t.label ?? e.label(t.tApp),
|
|
71
|
-
icon:
|
|
82
|
+
icon: l
|
|
72
83
|
};
|
|
73
84
|
}
|
|
74
|
-
return
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
return c.kind === "hub" ? {
|
|
86
|
+
kind: "internal",
|
|
87
|
+
id: `hub-${c.hubId}`,
|
|
88
|
+
destination: { pathname: i(s, c.hubId) },
|
|
89
|
+
label: t.label ?? a(s, c.hubId, t.tApp),
|
|
90
|
+
icon: l
|
|
91
|
+
} : /^[a-z][a-z\d+.-]*:/i.test(c.href) || c.href.startsWith("//") ? {
|
|
92
|
+
kind: "external",
|
|
93
|
+
id: `href-${c.href}`,
|
|
94
|
+
href: c.href,
|
|
95
|
+
label: t.label ?? c.href,
|
|
96
|
+
icon: l
|
|
79
97
|
} : {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
98
|
+
kind: "internal",
|
|
99
|
+
id: `href-${c.href}`,
|
|
100
|
+
destination: { pathname: c.href },
|
|
101
|
+
label: t.label ?? c.href,
|
|
102
|
+
icon: l
|
|
84
103
|
};
|
|
85
104
|
};
|
|
86
105
|
//#endregion
|
|
87
|
-
export {
|
|
106
|
+
export { o as resolveBackofficeLink };
|
|
88
107
|
|
|
89
108
|
//# sourceMappingURL=resolveBackofficeLink.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveBackofficeLink.js","names":[],"sources":["../../../../../src/components/backoffice/links/resolveBackofficeLink.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { TFunction } from 'i18next';\nimport
|
|
1
|
+
{"version":3,"file":"resolveBackofficeLink.js","names":[],"sources":["../../../../../src/components/backoffice/links/resolveBackofficeLink.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { TFunction } from 'i18next';\nimport type { BackofficeEntityManifestMap } from '@plumile/backoffice-core/types.js';\n\nimport type { BackofficeSidebarConfig } from '../../../provider/types.js';\nimport {\n joinBackofficePath,\n resolveSidebarHub,\n} from '../layout/sidebarUtils.js';\nimport { resolveBackofficeTargetIcon } from './resolveBackofficeTargetIcon.js';\nimport type { BackofficeLinkTarget, BackofficeResolvedLink } from './types.js';\n\nconst requireEntity = (\n manifest: BackofficeEntityManifestMap,\n entityId: string,\n) => {\n const entity = manifest[entityId];\n if (entity == null) {\n throw new Error(`Unknown backoffice entity: ${entityId}`);\n }\n return entity;\n};\n\nconst resolveHubHref = (\n sidebar: BackofficeSidebarConfig | undefined,\n hubId: string,\n): string => {\n const registeredHub = sidebar?.hubs?.[hubId];\n if (registeredHub != null) {\n return registeredHub.href;\n }\n\n for (const group of Object.values(sidebar?.groups ?? {})) {\n for (const item of group.items ?? []) {\n if (item.kind === 'hub' && item.id === hubId) {\n return resolveSidebarHub(item, sidebar).href;\n }\n }\n }\n\n throw new Error(`Unknown backoffice hub: ${hubId}`);\n};\n\nconst resolveHubLabel = (\n sidebar: BackofficeSidebarConfig | undefined,\n hubId: string,\n tApp: TFunction,\n): string => {\n const registeredHub = sidebar?.hubs?.[hubId];\n if (registeredHub != null) {\n return registeredHub.title(tApp);\n }\n\n for (const group of Object.values(sidebar?.groups ?? {})) {\n for (const item of group.items ?? []) {\n if (item.kind === 'hub' && item.id === hubId) {\n return resolveSidebarHub(item, sidebar).title(tApp);\n }\n }\n }\n\n return hubId;\n};\n\nexport const resolveBackofficeLink = <\n TManifest extends BackofficeEntityManifestMap,\n>(input: {\n target: BackofficeLinkTarget<TManifest>;\n label?: ReactNode;\n manifest: TManifest;\n sidebar?: BackofficeSidebarConfig<TManifest>;\n tApp: TFunction;\n dashboardHref?: string;\n dashboardLabel?: string;\n}): BackofficeResolvedLink => {\n const manifest = input.manifest as BackofficeEntityManifestMap;\n const sidebar = input.sidebar as BackofficeSidebarConfig | undefined;\n const target = input.target as BackofficeLinkTarget;\n const icon = resolveBackofficeTargetIcon({\n target: input.target,\n sidebar: input.sidebar,\n });\n\n if (target.kind === 'dashboard') {\n const dashboardId = target.id ?? 'dashboard';\n const href = input.dashboardHref ?? '/';\n if (dashboardId !== 'dashboard') {\n return {\n kind: 'internal',\n id: `dashboard-${dashboardId}`,\n destination: {\n pathname: joinBackofficePath(href, `dashboard/${dashboardId}`),\n },\n label: input.label ?? dashboardId,\n icon,\n };\n }\n return {\n kind: 'internal',\n id: 'dashboard',\n destination: { pathname: href },\n label: input.label ?? input.dashboardLabel ?? 'Dashboard',\n icon,\n };\n }\n\n if (target.kind === 'entity-list') {\n const entity = requireEntity(manifest, target.entityId);\n if (!entity.hasList) {\n throw new Error(`Backoffice entity has no list: ${target.entityId}`);\n }\n const encoded = entity.listNavigation.encode(target.state ?? {});\n return {\n kind: 'internal',\n id: `${target.entityId}-list`,\n destination: {\n pathname: entity.routes.list,\n filters: encoded.filters,\n query: encoded.query,\n },\n label: input.label ?? entity.label(input.tApp),\n icon,\n };\n }\n\n if (target.kind === 'entity-detail') {\n const entity = requireEntity(manifest, target.entityId);\n return {\n kind: 'internal',\n id: `${target.entityId}-entity-${target.id}`,\n destination: { pathname: entity.routes.detail(target.id) },\n label: input.label ?? target.id,\n icon,\n };\n }\n\n if (target.kind === 'entity-detail-page') {\n const entity = requireEntity(manifest, target.entityId);\n return {\n kind: 'internal',\n id: `${target.entityId}-page-${target.id}-${target.pageId}`,\n destination: {\n pathname: entity.routes.detailPage(target.id, target.pageId),\n },\n label: input.label ?? target.pageId,\n icon,\n };\n }\n\n if (target.kind === 'tool') {\n const entity = requireEntity(manifest, target.toolId);\n return {\n kind: 'internal',\n id: `tool-${target.toolId}`,\n destination: { pathname: entity.routes.list },\n label: input.label ?? entity.label(input.tApp),\n icon,\n };\n }\n\n if (target.kind === 'hub') {\n return {\n kind: 'internal',\n id: `hub-${target.hubId}`,\n destination: { pathname: resolveHubHref(sidebar, target.hubId) },\n label: input.label ?? resolveHubLabel(sidebar, target.hubId, input.tApp),\n icon,\n };\n }\n\n if (/^[a-z][a-z\\d+.-]*:/i.test(target.href) || target.href.startsWith('//')) {\n return {\n kind: 'external',\n id: `href-${target.href}`,\n href: target.href,\n label: input.label ?? target.href,\n icon,\n };\n }\n return {\n kind: 'internal',\n id: `href-${target.href}`,\n destination: { pathname: target.href },\n label: input.label ?? target.href,\n icon,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1,78 +1,47 @@
|
|
|
1
1
|
import { useBackofficeReactTranslation as e } from "../../../i18n/useBackofficeReactTranslation.js";
|
|
2
2
|
import { useBackofficeConfig as t } from "../../../provider/BackofficeConfigContext.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { useTranslation as d } from "react-i18next";
|
|
10
|
-
import { Spinner as f } from "@plumile/ui/backoffice/atoms/spinner/Spinner.js";
|
|
11
|
-
import p from "@plumile/router/routing/RoutingContext.js";
|
|
12
|
-
import { buildBackofficeListLink as m } from "@plumile/backoffice-core/state/buildListHref.js";
|
|
3
|
+
import { BackofficeInlineLink as n } from "../links/BackofficeInlineLink.js";
|
|
4
|
+
import { BackofficeLazyEntityCount as r } from "./BackofficeLazyEntityCount.js";
|
|
5
|
+
import { count as i, countLoading as a, icon as o, link as s } from "./backofficeRelatedCountLink.css.js";
|
|
6
|
+
import { jsx as c } from "react/jsx-runtime";
|
|
7
|
+
import { useTranslation as l } from "react-i18next";
|
|
8
|
+
import { Spinner as u } from "@plumile/ui/backoffice/atoms/spinner/Spinner.js";
|
|
13
9
|
//#region src/components/backoffice/refs/BackofficeRelatedCountLink.tsx
|
|
14
|
-
var
|
|
15
|
-
let { t:
|
|
16
|
-
if (
|
|
17
|
-
let
|
|
18
|
-
entity:
|
|
19
|
-
loadingFallback: /* @__PURE__ */
|
|
20
|
-
className:
|
|
21
|
-
children: /* @__PURE__ */ u
|
|
22
|
-
ariaLabel:
|
|
10
|
+
var d = ({ count: d, entity: f, where: p }) => {
|
|
11
|
+
let { t: m } = l(), { t: h } = e(), { entities: g } = t(), _ = g[f];
|
|
12
|
+
if (_ == null) return /* @__PURE__ */ c("span", { children: d ?? 0 });
|
|
13
|
+
let v = h("relations.openFilteredList", { label: _.label(m) }), y = h("common.loading"), b = /* @__PURE__ */ c(r, {
|
|
14
|
+
entity: f,
|
|
15
|
+
loadingFallback: /* @__PURE__ */ c("span", {
|
|
16
|
+
className: a,
|
|
17
|
+
children: /* @__PURE__ */ c(u, {
|
|
18
|
+
ariaLabel: y,
|
|
23
19
|
size: 12
|
|
24
20
|
})
|
|
25
21
|
}),
|
|
26
|
-
where:
|
|
22
|
+
where: p
|
|
27
23
|
});
|
|
28
|
-
typeof
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}, j = async (e) => {
|
|
34
|
-
let t = await S.loadListEntity(g), n = m(t.config, { where: _ }), r = "";
|
|
35
|
-
n.search !== "" && (r = `?${n.search}`), e.push({
|
|
36
|
-
pathname: n.pathname,
|
|
37
|
-
search: r,
|
|
38
|
-
hash: ""
|
|
39
|
-
});
|
|
40
|
-
};
|
|
41
|
-
return /* @__PURE__ */ u(r, {
|
|
42
|
-
target: A,
|
|
43
|
-
className: c,
|
|
44
|
-
title: E,
|
|
45
|
-
ariaLabel: E,
|
|
46
|
-
onClick: (e) => {
|
|
47
|
-
if (O != null || w == null || e.defaultPrevented || e.button !== 0 || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return;
|
|
48
|
-
e.preventDefault();
|
|
49
|
-
let { history: t } = w;
|
|
50
|
-
j(t).catch(() => {
|
|
51
|
-
let e = n({
|
|
52
|
-
target: A,
|
|
53
|
-
manifest: x,
|
|
54
|
-
sidebar: C,
|
|
55
|
-
tApp: v
|
|
56
|
-
}), r = new URL(e.href, window.location.origin);
|
|
57
|
-
t.push({
|
|
58
|
-
pathname: r.pathname,
|
|
59
|
-
search: r.search,
|
|
60
|
-
hash: r.hash
|
|
61
|
-
});
|
|
62
|
-
});
|
|
24
|
+
return typeof d == "number" && Number.isFinite(d) && (b = d), /* @__PURE__ */ c(n, {
|
|
25
|
+
target: {
|
|
26
|
+
kind: "entity-list",
|
|
27
|
+
entityId: f,
|
|
28
|
+
state: { where: p }
|
|
63
29
|
},
|
|
64
|
-
|
|
65
|
-
|
|
30
|
+
className: s,
|
|
31
|
+
title: v,
|
|
32
|
+
ariaLabel: v,
|
|
33
|
+
endAdornment: /* @__PURE__ */ c("span", {
|
|
34
|
+
className: o,
|
|
66
35
|
"aria-hidden": "true",
|
|
67
36
|
children: "›"
|
|
68
37
|
}),
|
|
69
|
-
children: /* @__PURE__ */
|
|
70
|
-
className:
|
|
71
|
-
children:
|
|
38
|
+
children: /* @__PURE__ */ c("span", {
|
|
39
|
+
className: i,
|
|
40
|
+
children: b
|
|
72
41
|
})
|
|
73
42
|
});
|
|
74
43
|
};
|
|
75
44
|
//#endregion
|
|
76
|
-
export {
|
|
45
|
+
export { d as BackofficeRelatedCountLink, d as default };
|
|
77
46
|
|
|
78
47
|
//# sourceMappingURL=BackofficeRelatedCountLink.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeRelatedCountLink.js","names":[],"sources":["../../../../../src/components/backoffice/refs/BackofficeRelatedCountLink.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"BackofficeRelatedCountLink.js","names":[],"sources":["../../../../../src/components/backoffice/refs/BackofficeRelatedCountLink.tsx"],"sourcesContent":["import { type JSX, type ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Spinner } from '@plumile/ui/backoffice/atoms/spinner/Spinner.js';\nimport { useBackofficeConfig } from '../../../provider/BackofficeConfigContext.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { BackofficeInlineLink } from '../links/BackofficeInlineLink.js';\nimport type { BackofficeLinkTarget } from '../links/types.js';\nimport { BackofficeLazyEntityCount } from './BackofficeLazyEntityCount.js';\n\nimport * as styles from './backofficeRelatedCountLink.css.js';\n\nexport type BackofficeRelatedCountLinkProps<\n Where extends Record<string, unknown> = Record<string, unknown>,\n> = {\n count?: number | null | undefined;\n entity: string;\n where: Where;\n};\n\nexport const BackofficeRelatedCountLink = <\n Where extends Record<string, unknown> = Record<string, unknown>,\n>({\n count,\n entity,\n where,\n}: BackofficeRelatedCountLinkProps<Where>): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { entities } = useBackofficeConfig();\n const targetManifest = entities[entity];\n if (targetManifest == null) {\n return <span>{count ?? 0}</span>;\n }\n const entityLabel = targetManifest.label(tApp);\n const actionLabel = t('relations.openFilteredList', {\n label: entityLabel,\n });\n const loadingLabel = t('common.loading');\n let countNode: ReactNode = (\n <BackofficeLazyEntityCount\n entity={entity}\n loadingFallback={\n <span className={styles.countLoading}>\n <Spinner ariaLabel={loadingLabel} size={12} />\n </span>\n }\n where={where}\n />\n );\n if (typeof count === 'number' && Number.isFinite(count)) {\n countNode = count;\n }\n const target = {\n kind: 'entity-list',\n entityId: entity,\n state: { where },\n } as BackofficeLinkTarget;\n\n return (\n <BackofficeInlineLink\n target={target}\n className={styles.link}\n title={actionLabel}\n ariaLabel={actionLabel}\n endAdornment={\n <span className={styles.icon} aria-hidden=\"true\">\n ›\n </span>\n }\n >\n <span className={styles.count}>{countNode}</span>\n </BackofficeInlineLink>\n );\n};\n\nexport default BackofficeRelatedCountLink;\n"],"mappings":";;;;;;;;;AAoBA,IAAa,KAEX,EACA,OAAA,GACA,WACA,eACyD;CACzD,IAAM,EAAE,GAAG,MAAS,EAAe,GAC7B,EAAE,SAAM,EAA8B,GACtC,EAAE,gBAAa,EAAoB,GACnC,IAAiB,EAAS;CAChC,IAAI,KAAkB,MACpB,OAAO,kBAAC,QAAD,EAAA,UAAO,KAAS,EAAQ,CAAA;CAGjC,IAAM,IAAc,EAAE,8BAA8B,EAClD,OAFkB,EAAe,MAAM,CAEhC,EACT,CAAC,GACK,IAAe,EAAE,gBAAgB,GACnC,IACF,kBAAC,GAAD;EACU;EACR,iBACE,kBAAC,QAAD;GAAM,WAAW;GACf,UAAA,kBAAC,GAAD;IAAS,WAAW;IAAc,MAAM;GAAK,CAAA;EACzC,CAAA;EAED;CACR,CAAA;CAWH,OATI,OAAO,KAAU,YAAY,OAAO,SAAS,CAAK,MACpD,IAAY,IASZ,kBAAC,GAAD;EACU,QAAA;GAPV,MAAM;GACN,UAAU;GACV,OAAO,EAAE,SAAM;EAKL;EACR,WAAW;EACX,OAAO;EACP,WAAW;EACX,cACE,kBAAC,QAAD;GAAM,WAAW;GAAa,eAAY;GAAO,UAAA;EAE3C,CAAA;EAGR,UAAA,kBAAC,QAAD;GAAM,WAAW;GAAe,UAAA;EAAgB,CAAA;CAC5B,CAAA;AAE1B"}
|
|
@@ -67,10 +67,7 @@ var C = (e, t) => e(t), we = (e, t) => {
|
|
|
67
67
|
let n = new Date(t);
|
|
68
68
|
return Number.isNaN(n.getTime()) ? t : n.toISOString();
|
|
69
69
|
}, w = (x) => {
|
|
70
|
-
let { t: w } = le(), { t: T } = e(), { config: E, state: D, pushState: O, rows: k, getRowId: A, columns: j, gridTemplateColumns: ke, hasNextPage: M, isLoadingMore: N, isRefreshing: P = !1, onLoadMore: Ae, onRefresh: F, totalCount: I, loadedCountLabel: je, emptyState: Me, statusBanner: Ne, header: Pe, headerActions: Fe, isLoadingInitial: L = !1, variant: Ie = "page", showFilters: Le = !0 } = x, R = E.list, Re = E.
|
|
71
|
-
where: null,
|
|
72
|
-
sort: null
|
|
73
|
-
}, z = p(() => j.some((e) => e.isPrimary === !0) || j.length === 0 ? j : j.map((e, t) => {
|
|
70
|
+
let { t: w } = le(), { t: T } = e(), { config: E, state: D, pushState: O, rows: k, getRowId: A, columns: j, gridTemplateColumns: ke, hasNextPage: M, isLoadingMore: N, isRefreshing: P = !1, onLoadMore: Ae, onRefresh: F, totalCount: I, loadedCountLabel: je, emptyState: Me, statusBanner: Ne, header: Pe, headerActions: Fe, isLoadingInitial: L = !1, variant: Ie = "page", showFilters: Le = !0 } = x, R = E.list, { listDefaults: Re } = E, z = p(() => j.some((e) => e.isPrimary === !0) || j.length === 0 ? j : j.map((e, t) => {
|
|
74
71
|
let { header: n } = e;
|
|
75
72
|
return t === 0 ? {
|
|
76
73
|
...e,
|