@plumile/backoffice-react 0.1.166 → 0.1.168

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 (65) hide show
  1. package/lib/esm/auth/authRefreshNotice.css.js +1 -0
  2. package/lib/esm/auth/login/loginPage.css.js +0 -1
  3. package/lib/esm/components/backoffice/detail/BackofficeDetailRelationListBlock.js +50 -49
  4. package/lib/esm/components/backoffice/detail/BackofficeDetailRelationListBlock.js.map +1 -1
  5. package/lib/esm/components/backoffice/detail/backofficeDetailRelationLink.css.js +1 -0
  6. package/lib/esm/components/backoffice/filters/backofficeFilterAction.css.js +0 -1
  7. package/lib/esm/components/backoffice/layout/breadcrumb/buildBreadcrumbs.js +7 -7
  8. package/lib/esm/components/backoffice/layout/breadcrumb/buildBreadcrumbs.js.map +1 -1
  9. package/lib/esm/components/backoffice/pickers/EntityIdPickerDialog.js +49 -48
  10. package/lib/esm/components/backoffice/pickers/EntityIdPickerDialog.js.map +1 -1
  11. package/lib/esm/components/backoffice/scaffolds/BackofficeEntityDetailNotFound.js +27 -0
  12. package/lib/esm/components/backoffice/scaffolds/BackofficeEntityDetailNotFound.js.map +1 -0
  13. package/lib/esm/components/backoffice/scaffolds/BackofficeEntityDetailScaffold.js +12 -8
  14. package/lib/esm/components/backoffice/scaffolds/BackofficeEntityDetailScaffold.js.map +1 -1
  15. package/lib/esm/hooks/useBackofficeListUrlState.js.map +1 -1
  16. package/lib/esm/i18n/locales/en/backofficeReact.js +6 -2
  17. package/lib/esm/i18n/locales/en/backofficeReact.js.map +1 -1
  18. package/lib/esm/i18n/locales/fr/backofficeReact.js +6 -2
  19. package/lib/esm/i18n/locales/fr/backofficeReact.js.map +1 -1
  20. package/lib/esm/pages/BackofficeDashboardWidgetContent.js.map +1 -1
  21. package/lib/esm/pages/BackofficeEntityDetailLayoutPage.js +107 -81
  22. package/lib/esm/pages/BackofficeEntityDetailLayoutPage.js.map +1 -1
  23. package/lib/esm/pages/BackofficeEntityDetailPage.js +206 -203
  24. package/lib/esm/pages/BackofficeEntityDetailPage.js.map +1 -1
  25. package/lib/esm/pages/BackofficeEntityDetailPage.view-helpers.js +1 -1
  26. package/lib/esm/pages/BackofficeEntityDetailPage.view-helpers.js.map +1 -1
  27. package/lib/esm/pages/BackofficeEntityDetailUnknownPageRedirect.js.map +1 -1
  28. package/lib/esm/pages/BackofficeEntityListPage.js +91 -90
  29. package/lib/esm/pages/BackofficeEntityListPage.js.map +1 -1
  30. package/lib/esm/provider/entityRegistry.js.map +1 -1
  31. package/lib/esm/relay/createInlineDataReader.js +2 -2
  32. package/lib/esm/relay/createInlineReader.js +3 -3
  33. package/lib/esm/relay/createInlineReader.js.map +1 -1
  34. package/lib/esm/relay/environment.js +37 -12
  35. package/lib/esm/relay/environment.js.map +1 -1
  36. package/lib/esm/relay/typedRelayHooks.js +7 -0
  37. package/lib/esm/relay/typedRelayHooks.js.map +1 -0
  38. package/lib/esm/router/createBackofficeRoutes.js.map +1 -1
  39. package/lib/types/components/backoffice/detail/BackofficeDetailRelationListBlock.d.ts.map +1 -1
  40. package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.d.ts +1 -1
  41. package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.d.ts.map +1 -1
  42. package/lib/types/components/backoffice/scaffolds/BackofficeEntityDetailNotFound.d.ts +9 -0
  43. package/lib/types/components/backoffice/scaffolds/BackofficeEntityDetailNotFound.d.ts.map +1 -0
  44. package/lib/types/components/backoffice/scaffolds/BackofficeEntityDetailScaffold.d.ts +6 -1
  45. package/lib/types/components/backoffice/scaffolds/BackofficeEntityDetailScaffold.d.ts.map +1 -1
  46. package/lib/types/hooks/useBackofficeListUrlState.d.ts.map +1 -1
  47. package/lib/types/i18n/resources.d.ts +4 -0
  48. package/lib/types/i18n/resources.d.ts.map +1 -1
  49. package/lib/types/pages/BackofficeDashboardWidgetContent.d.ts.map +1 -1
  50. package/lib/types/pages/BackofficeEntityDetailLayoutPage.d.ts.map +1 -1
  51. package/lib/types/pages/BackofficeEntityDetailPage.d.ts.map +1 -1
  52. package/lib/types/pages/BackofficeEntityDetailPage.view-helpers.d.ts +9 -5
  53. package/lib/types/pages/BackofficeEntityDetailPage.view-helpers.d.ts.map +1 -1
  54. package/lib/types/pages/BackofficeEntityListPage.d.ts.map +1 -1
  55. package/lib/types/provider/entityRegistry.d.ts.map +1 -1
  56. package/lib/types/relay/createInlineDataReader.d.ts +1 -1
  57. package/lib/types/relay/createInlineDataReader.d.ts.map +1 -1
  58. package/lib/types/relay/createInlineReader.d.ts +0 -1
  59. package/lib/types/relay/createInlineReader.d.ts.map +1 -1
  60. package/lib/types/relay/environment.d.ts +19 -0
  61. package/lib/types/relay/environment.d.ts.map +1 -1
  62. package/lib/types/relay/typedRelayHooks.d.ts +11 -0
  63. package/lib/types/relay/typedRelayHooks.d.ts.map +1 -0
  64. package/lib/types/router/createBackofficeRoutes.d.ts.map +1 -1
  65. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeEntityDetailPage.js","names":[],"sources":["../../../src/pages/BackofficeEntityDetailPage.tsx"],"sourcesContent":["/* eslint-disable no-ternary */\nimport { type JSX, type ReactNode, useContext, useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n type PreloadedQuery,\n useFragment,\n usePreloadedQuery,\n} from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\nimport { resolveMutationOutcome } from '../relay/mutationResult.js';\nimport { setWhereValue } from '@plumile/backoffice-core/filters/where.js';\nimport {\n buildBackofficeFallbackListHref,\n buildBackofficeListHref,\n buildBackofficeListLink,\n} from '@plumile/backoffice-core/state/buildListHref.js';\n\nimport { BACKOFFICE_DATE_TIME_OPTIONS } from '@plumile/backoffice-core/constants.js';\nimport type {\n BackofficeResolvedDetailLayoutFacetConfigBase,\n BackofficeResolvedDetailPageFacetConfig,\n BackofficeResolvedDetailPageFacetConfigBase,\n} from '@plumile/backoffice-core/types.js';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { LinkButton } from '@plumile/ui/atomic/atoms/button/LinkButton.js';\nimport { FormattedDate } from '@plumile/ui/atomic/atoms/formatted-date/FormattedDate.js';\nimport { useToast } from '@plumile/ui/atomic/molecules/toast/ToastProvider.js';\nimport { Tag } from '@plumile/ui/backoffice/atoms/tag/Tag.js';\nimport { BackofficeDetailSection } from '@plumile/ui/backoffice/molecules/backoffice_detail_section/BackofficeDetailSection.js';\nimport { BackofficeKeyValueList } from '@plumile/ui/backoffice/molecules/backoffice_key_value_list/BackofficeKeyValueList.js';\nimport { BackofficePayloadViewer } from '@plumile/ui/backoffice/molecules/backoffice_payload_viewer/BackofficePayloadViewer.js';\nimport {\n BackofficeRelationsMenu,\n type BackofficeRelationsMenuItem,\n} from '@plumile/ui/backoffice/molecules/backoffice_relations_menu/BackofficeRelationsMenu.js';\nimport { BackofficeScopeStack } from '@plumile/ui/backoffice/molecules/backoffice_scope_stack/BackofficeScopeStack.js';\nimport { AuditTimeline } from '@plumile/ui/backoffice/organisms/audit_timeline/AuditTimeline.js';\nimport { MetricCard } from '@plumile/ui/components/dashboard/metric_card/MetricCard.js';\nimport { MetricTileGroup } from '@plumile/ui/components/dashboard/metric_tile_group/MetricTileGroup.js';\nimport { DataTable } from '@plumile/ui/components/data-table/DataTable.js';\nimport { ChatCheckSvg } from '@plumile/ui/icons/ChatCheckSvg.js';\nimport { KeyOffSvg } from '@plumile/ui/icons/KeyOffSvg.js';\nimport { KeySvg } from '@plumile/ui/icons/KeySvg.js';\nimport { LockOpenSvg } from '@plumile/ui/icons/LockOpenSvg.js';\nimport { LockSvg } from '@plumile/ui/icons/LockSvg.js';\nimport { RobotCheckSvg } from '@plumile/ui/icons/RobotCheckSvg.js';\nimport { RobotXSvg } from '@plumile/ui/icons/RobotXSvg.js';\nimport { RocketOffSvg } from '@plumile/ui/icons/RocketOffSvg.js';\nimport { RocketSvg } from '@plumile/ui/icons/RocketSvg.js';\nimport { SettingsCheckSvg } from '@plumile/ui/icons/SettingsCheckSvg.js';\nimport { SettingsXSvg } from '@plumile/ui/icons/SettingsXSvg.js';\nimport { ShieldLockSvg } from '@plumile/ui/icons/ShieldLockSvg.js';\nimport { ShieldOffSvg } from '@plumile/ui/icons/ShieldOffSvg.js';\nimport { XBadgeSvg } from '@plumile/ui/icons/XBadgeSvg.js';\nimport Link from '@plumile/router/routing/Link.js';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\n\nimport { buildDataTableColumns } from '../components/backoffice/columns/buildDataTableColumns.js';\nimport { BackofficeEntityDetailScaffold } from '../components/backoffice/scaffolds/BackofficeEntityDetailScaffold.js';\nimport { BackofficeDetailBadgeRow } from '../components/backoffice/detail/BackofficeDetailBadgeRow.js';\nimport { BackofficeDetailFlagTag } from '../components/backoffice/detail/BackofficeDetailFlagTag.js';\nimport { BackofficeDetailTaggedValue } from '../components/backoffice/detail/BackofficeDetailTaggedValue.js';\nimport { BackofficeLifecycleTimelineSection } from '../components/backoffice/detail/BackofficeLifecycleTimelineSection.js';\nimport { BackofficeRelationsSummaryGrid } from '../components/backoffice/detail/BackofficeRelationsSummaryGrid.js';\nimport * as detailLayoutStyles from '../components/backoffice/detail/backofficeDetailLayout.css.js';\nimport { LazyBackofficeEntityActionFormDialog } from '../components/backoffice/actions/LazyBackofficeEntityActionFormDialog.js';\nimport {\n resolveToastSpec,\n resolveToastViewActions,\n} from '../components/backoffice/actions/toastViewAction.js';\nimport * as pageStyles from './backofficeEntityDetailPage.css.js';\nimport { useBackofficeFormats } from '../i18n/useBackofficeFormats.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { useBackofficeEntityDetailLayoutContext } from './detail/BackofficeEntityDetailLayoutContext.js';\nimport { resolveVisibleDetailPages } from './detail/pageResolution.js';\nimport {\n extractMutationPayload,\n isFormMutationAction,\n isMutationAction,\n isRouteAction,\n resolveLabel,\n} from './BackofficeEntityDetailPage.helpers.js';\nimport {\n buildFieldItems,\n renderBlocks,\n type FlagIconName,\n} from './BackofficeEntityDetailPage.view-helpers.js';\nimport { BackofficeRedirect } from './BackofficeRedirect.js';\nimport { BackofficeLazyEntityCount } from '../components/backoffice/refs/BackofficeLazyEntityCount.js';\n\nexport type BackofficeEntityDetailPageProps = {\n config: BackofficeResolvedDetailLayoutFacetConfigBase;\n prepared: {\n id: string;\n detailId?: string;\n pageConfig: BackofficeResolvedDetailPageFacetConfigBase;\n pageQuery: PreloadedQuery<OperationType>;\n pageId: string;\n pagePath: string;\n };\n};\n\nconst renderFlagIcon = (iconName: FlagIconName): JSX.Element => {\n const iconSize = 14;\n switch (iconName) {\n case 'shield-lock':\n return (\n <ShieldLockSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'shield-off':\n return (\n <ShieldOffSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'settings-check':\n return (\n <SettingsCheckSvg\n width={iconSize}\n height={iconSize}\n aria-hidden=\"true\"\n />\n );\n case 'settings-x':\n return (\n <SettingsXSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'x-badge':\n return (\n <XBadgeSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'chat-check':\n return (\n <ChatCheckSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'key':\n return <KeySvg width={iconSize} height={iconSize} aria-hidden=\"true\" />;\n case 'key-off':\n return (\n <KeyOffSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'lock':\n return <LockSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />;\n case 'lock-open':\n return (\n <LockOpenSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'robot-check':\n return (\n <RobotCheckSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'robot-x':\n return (\n <RobotXSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'rocket':\n return (\n <RocketSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'rocket-off':\n return (\n <RocketOffSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n default:\n throw new Error(`Unsupported flag icon: ${String(iconName)}`);\n }\n};\n\nconst resolveDetailPlacement = (item: {\n placement?: 'primary' | 'secondary' | 'main' | 'side' | 'fullWidth';\n presentation?: {\n group?: string;\n desktop?: 'primary' | 'secondary' | 'fullWidth';\n };\n kind?: string;\n fields?: readonly {\n presentation?: {\n group?: string;\n desktop?: 'primary' | 'secondary' | 'fullWidth';\n };\n }[];\n}): 'primary' | 'secondary' => {\n if (item.presentation?.desktop === 'secondary') {\n return 'secondary';\n }\n if (\n item.presentation?.group === 'scope' ||\n item.presentation?.group === 'status'\n ) {\n return 'secondary';\n }\n const fieldGroups =\n item.fields?.map((field) => {\n return field.presentation?.group;\n }) ?? [];\n if (\n fieldGroups.length > 0 &&\n fieldGroups.every((group) => {\n return group === 'scope' || group === 'status';\n })\n ) {\n return 'secondary';\n }\n if (item.placement === 'side') {\n return 'secondary';\n }\n if (item.placement === 'secondary') {\n return 'secondary';\n }\n return 'primary';\n};\n\nconst BackofficeEntityDetailPageContent = ({\n config,\n prepared,\n}: {\n config: BackofficeResolvedDetailPageFacetConfig;\n prepared: {\n pageQuery: PreloadedQuery<OperationType>;\n id: string;\n detailId?: string;\n pageId: string;\n pagePath: string;\n };\n}): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { formatNumber, formatCurrency, formatCurrencyTitle, formatPercent } =\n useBackofficeFormats();\n const { entities, entityRegistry } = useBackofficeConfig();\n const routing = useContext(RoutingContext);\n const environment = useRelayEnvironment();\n const toast = useToast();\n const [actionState, setActionState] = useState<Record<string, boolean>>({});\n const [activeFormActionId, setActiveFormActionId] = useState<string | null>(\n null,\n );\n const setActionLoading = (actionId: string, isLoading: boolean) => {\n setActionState((prev) => {\n if (prev[actionId] === isLoading) {\n return prev;\n }\n return { ...prev, [actionId]: isLoading };\n });\n };\n\n const { page } = config;\n\n const pageQueryData = usePreloadedQuery(page.query, prepared.pageQuery);\n const pageNodeRef = page.resolveNode(pageQueryData, {\n id: prepared.id,\n detailId: prepared.detailId,\n });\n const hasPageNode = pageNodeRef != null;\n const resolvedNode = useFragment(page.fragment, pageNodeRef as never);\n const relationEntityListRoutes = useMemo(() => {\n return Object.fromEntries(\n page.content\n .flatMap((block) => {\n if (block.kind !== 'fieldSet') {\n return [];\n }\n\n return block.fields.flatMap((field) => {\n if (field.type !== 'relation') {\n return [];\n }\n return [field.relation.target];\n });\n })\n .flatMap((entityId) => {\n const entityManifest = entities[entityId];\n if (entityManifest?.hasList !== true) {\n return [];\n }\n return [[entityId, entityManifest.routes.list]];\n }),\n );\n }, [entities, page.content]);\n\n if (!hasPageNode) {\n return <BackofficeRedirect to={config.routes.list} />;\n }\n\n return (\n <BackofficeEntityDetailScaffold\n node={resolvedNode}\n render={(node) => {\n const view = page.toView(node);\n const resolveEntityHref = (entityId: string, refId: string) => {\n const entityConfig = entities[entityId];\n if (entityConfig == null) {\n return null;\n }\n return entityConfig.routes.detail(refId);\n };\n const resolveRelationItem = ({\n id,\n label,\n relation,\n listRoute,\n value,\n where,\n }: {\n id: string;\n label: string;\n relation: {\n target: string;\n filterId?: string;\n whereKey: string;\n path?: readonly string[];\n };\n listRoute: string;\n value: string;\n where: Record<string, unknown>;\n }): BackofficeRelationsMenuItem => {\n const { target, filterId, whereKey, path } = relation;\n const loadedEntity = entityRegistry.getLoadedListEntity(target);\n return {\n id,\n label,\n count: <BackofficeLazyEntityCount entity={target} where={where} />,\n href:\n loadedEntity == null\n ? buildBackofficeFallbackListHref(listRoute, where, [\n {\n id:\n filterId ??\n (path == null\n ? whereKey\n : `${whereKey}.${path.join('.')}`),\n value,\n },\n ])\n : buildBackofficeListHref(loadedEntity.config, { where }),\n onClick: async (event) => {\n if (\n routing == null ||\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.altKey ||\n event.ctrlKey ||\n event.shiftKey\n ) {\n return;\n }\n\n event.preventDefault();\n\n const listEntity = await entityRegistry.loadListEntity(target);\n const next = buildBackofficeListLink(listEntity.config, {\n where,\n });\n\n routing.history.push({\n pathname: next.pathname,\n search: next.search === '' ? '' : `?${next.search}`,\n hash: '',\n });\n },\n };\n };\n\n const actions = page.actions ?? [];\n let headerActionButtons: ReactNode[] = [];\n if (actions.length > 0) {\n const visibleActions = actions.filter((action) => {\n if (action.isVisible == null) {\n return true;\n }\n return action.isVisible(view);\n });\n\n if (visibleActions.length > 0) {\n headerActionButtons = visibleActions.map((action) => {\n const label = resolveLabel(action.label, tApp);\n const ariaLabel =\n action.ariaLabel != null\n ? resolveLabel(action.ariaLabel, tApp)\n : label;\n const variant = action.variant ?? 'secondary';\n const size = action.size ?? 'small';\n const isLoading = actionState[action.id] ?? false;\n const isDisabled =\n isLoading || action.isDisabled?.(view) === true;\n\n if (isRouteAction(action)) {\n const href = action.to(view);\n return (\n <LinkButton\n key={action.id}\n to={href}\n variant={variant}\n size={size}\n isDisabled={isDisabled}\n aria-label={ariaLabel}\n preloadOnMouseEnter\n >\n {label}\n </LinkButton>\n );\n }\n\n if (isFormMutationAction(action)) {\n return (\n <Button\n key={action.id}\n type=\"button\"\n variant={variant}\n size={size}\n isLoading={false}\n disabled={isDisabled}\n onClick={() => {\n setActiveFormActionId(action.id);\n }}\n aria-label={ariaLabel}\n >\n {label}\n </Button>\n );\n }\n\n if (isMutationAction(action)) {\n const handleClick = () => {\n if (isLoading) {\n return;\n }\n const variables = action.getVariables(view);\n setActionLoading(action.id, true);\n commitMutation(environment, {\n mutation: action.mutation,\n variables,\n updater: (store) => {\n action.updater?.(store, view);\n },\n onCompleted: (response) => {\n setActionLoading(action.id, false);\n const mutationPayload = extractMutationPayload(response);\n if (mutationPayload != null) {\n let defaultErrorMessage = t(\n 'actions.form.errors.invalidPayload',\n );\n if (action.toasts?.error?.message != null) {\n defaultErrorMessage = resolveLabel(\n action.toasts.error.message,\n tApp,\n );\n } else if (action.toasts?.error?.title != null) {\n defaultErrorMessage = resolveLabel(\n action.toasts.error.title,\n tApp,\n );\n }\n\n const outcome = resolveMutationOutcome(\n mutationPayload,\n {\n defaultErrorMessage,\n mapReason: (reason) => {\n const mapped = action.mapErrorReason?.(\n reason,\n view,\n );\n if (mapped == null) {\n return null;\n }\n if (typeof mapped === 'function') {\n return resolveLabel(mapped, tApp);\n }\n return String(mapped);\n },\n },\n );\n if (!outcome.ok) {\n const error = new Error(outcome.message);\n action.onError?.(error, view);\n if (action.toasts?.error != null) {\n const toastSpec = resolveToastSpec(\n action.toasts.error,\n tApp,\n );\n toast.error(toastSpec.title, toastSpec.message);\n }\n return;\n }\n }\n\n action.onCompleted?.(response, view);\n if (action.toasts?.success != null) {\n const toastSpec = resolveToastSpec(\n action.toasts.success,\n tApp,\n );\n const toastActions = resolveToastViewActions({\n toast: action.toasts.success,\n response,\n node: view,\n tApp,\n entities,\n defaultLabel: t('actions.view'),\n navigateTo: (to) => {\n routing?.history.push({ pathname: to });\n },\n });\n toast.push({\n kind: 'info',\n title: toastSpec.title,\n message: toastSpec.message,\n actions: toastActions,\n });\n }\n },\n onError: (error) => {\n setActionLoading(action.id, false);\n action.onError?.(error, view);\n if (action.toasts?.error != null) {\n const toastSpec = resolveToastSpec(\n action.toasts.error,\n tApp,\n );\n toast.error(toastSpec.title, toastSpec.message);\n }\n },\n });\n };\n\n return (\n <Button\n key={action.id}\n type=\"button\"\n variant={variant}\n size={size}\n isLoading={isLoading}\n disabled={isDisabled}\n onClick={handleClick}\n aria-label={ariaLabel}\n >\n {label}\n </Button>\n );\n }\n\n return null;\n });\n }\n }\n\n const activeFormAction = actions.find((action) => {\n return action.id === activeFormActionId;\n });\n\n const { content } = page;\n\n const primaryNodes: ReactNode[] = [];\n const secondaryNodes: ReactNode[] = [];\n const relationMenuItems: BackofficeRelationsMenuItem[] = [];\n\n content.forEach((item, index) => {\n const placement = resolveDetailPlacement(item);\n const targetNodes =\n placement === 'secondary' ? secondaryNodes : primaryNodes;\n\n if (item.kind === 'fieldSet') {\n const sectionLabel = resolveLabel(item.title, tApp);\n const description =\n item.description != null\n ? resolveLabel(item.description, tApp)\n : undefined;\n const { items, relationItems, customNodes } = buildFieldItems(\n item.fields,\n view,\n {\n tApp,\n t,\n resolveEntityHref,\n formatNumber,\n formatCurrency,\n formatCurrencyTitle,\n formatPercent,\n relationEntityListRoutes,\n resolveRelationItem,\n setWhereValue,\n renderTag: (tone, label) => {\n return <Tag tone={tone}>{label}</Tag>;\n },\n renderBadgeRow: (items) => {\n return <BackofficeDetailBadgeRow items={items} />;\n },\n renderDate: (value, fallback) => {\n return (\n <FormattedDate\n value={value}\n options={BACKOFFICE_DATE_TIME_OPTIONS}\n fallback={fallback}\n />\n );\n },\n renderFlagTag: (tag) => {\n return (\n <BackofficeDetailFlagTag\n tone={tag.tone}\n icon={\n tag.iconName != null\n ? renderFlagIcon(tag.iconName)\n : undefined\n }\n label={tag.label}\n />\n );\n },\n renderLink: (href, label) => {\n return (\n <Link to={href} preloadOnMouseEnter>\n {label}\n </Link>\n );\n },\n renderTaggedValue: (tag, value) => {\n return (\n <BackofficeDetailTaggedValue\n tag={tag as never}\n value={value}\n />\n );\n },\n wrapCustomNode: (id, custom) => {\n return <div key={id}>{custom}</div>;\n },\n },\n );\n relationItems.forEach((relation) => {\n if (\n !relationMenuItems.some((entry) => {\n return entry.id === relation.id;\n })\n ) {\n relationMenuItems.push(relation);\n }\n });\n\n const hasContent = items.length > 0 || customNodes.length > 0;\n\n if (!hasContent) {\n return;\n }\n\n targetNodes.push(\n <BackofficeDetailSection\n key={`${sectionLabel}-${index}`}\n title={sectionLabel}\n description={description}\n items={items.length > 0 ? items : undefined}\n >\n {customNodes}\n </BackofficeDetailSection>,\n );\n return;\n }\n\n const rendered = renderBlocks([item], view, {\n tApp,\n t,\n resolveEntityHref,\n keyPrefix: String(index),\n renderLink: (href, label) => {\n return (\n <Link to={href} preloadOnMouseEnter>\n {label}\n </Link>\n );\n },\n renderDate: (value, fallback) => {\n return (\n <FormattedDate\n value={value}\n options={BACKOFFICE_DATE_TIME_OPTIONS}\n fallback={fallback}\n />\n );\n },\n renderTag: (tone, label) => {\n return <Tag tone={tone}>{label}</Tag>;\n },\n renderMetricGroup: ({\n key,\n title,\n description,\n density,\n items,\n }) => {\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n {items.length > 0 && (\n <MetricTileGroup\n density={density ?? 'comfortable'}\n minColumn=\"180\"\n >\n {items.map((metric) => {\n return (\n <MetricCard\n key={metric.id}\n label={metric.label}\n value={metric.value}\n hint={metric.hint}\n tone={metric.tone ?? 'neutral'}\n density={density ?? 'comfortable'}\n copyValue={metric.copyValue}\n copyLabel={t('common.actions.copy')}\n copiedLabel={t('common.actions.copied')}\n />\n );\n })}\n </MetricTileGroup>\n )}\n </BackofficeDetailSection>\n );\n },\n renderTimeline: ({ key, title, description, events }) => {\n return (\n <BackofficeLifecycleTimelineSection\n key={key}\n title={title}\n description={description}\n events={events}\n />\n );\n },\n renderAuditTimeline: ({ key, title, description, events }) => {\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <AuditTimeline events={events} />\n </BackofficeDetailSection>\n );\n },\n renderRelations: ({ key, title, items }) => {\n return (\n <BackofficeRelationsSummaryGrid\n key={key}\n title={title}\n items={items}\n />\n );\n },\n renderContextStack: ({ key, title, items }) => {\n return (\n <BackofficeScopeStack key={key} title={title} items={items} />\n );\n },\n renderCustomSection: (key, title, child) => {\n return (\n <BackofficeDetailSection key={key} title={title}>\n {child}\n </BackofficeDetailSection>\n );\n },\n wrapCustomNode: (key, custom) => {\n return <div key={key}>{custom}</div>;\n },\n resolveTableColumns: (columns) => {\n return buildDataTableColumns(columns as never, {\n tApp,\n t,\n });\n },\n renderTable: ({ key, title, description, columns, rows }) => {\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <DataTable\n columns={columns as never}\n rows={rows}\n getRowId={(row, rowIndex) => {\n if (row != null && typeof row === 'object') {\n const record = row as Record<string, unknown>;\n const maybeId = record.id;\n if (\n typeof maybeId === 'string' &&\n maybeId.trim() !== ''\n ) {\n return maybeId;\n }\n }\n return String(rowIndex);\n }}\n />\n </BackofficeDetailSection>\n );\n },\n renderPayload: ({ key, title, description, content, format }) => {\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <BackofficePayloadViewer\n content={content}\n format={format as never}\n emptyState={t('common.notAvailable')}\n />\n </BackofficeDetailSection>\n );\n },\n renderKeyValueListSection: ({ key, title, description, items }) => {\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <BackofficeKeyValueList items={items} />\n </BackofficeDetailSection>\n );\n },\n });\n const blockNode = rendered[0];\n if (blockNode != null) {\n targetNodes.push(blockNode);\n }\n });\n\n const relationsMenuNode =\n relationMenuItems.length > 0 ? (\n <BackofficeRelationsMenu\n label={t('relations.menu.label')}\n items={relationMenuItems}\n />\n ) : null;\n\n const tabActionsNode =\n headerActionButtons.length > 0 || relationsMenuNode != null ? (\n <div className={pageStyles.headerActions}>\n {headerActionButtons.length > 0 && (\n <div className={pageStyles.headerActionGroup}>\n {headerActionButtons}\n </div>\n )}\n {relationsMenuNode != null && (\n <div className={pageStyles.headerRelationGroup}>\n {relationsMenuNode}\n </div>\n )}\n </div>\n ) : null;\n\n const hasAside = secondaryNodes.length > 0;\n const contentNode = hasAside ? (\n <div className={detailLayoutStyles.layout}>\n <div className={detailLayoutStyles.primary}>{primaryNodes}</div>\n <aside className={detailLayoutStyles.secondary}>\n {secondaryNodes}\n </aside>\n </div>\n ) : (\n <div className={detailLayoutStyles.stacked}>{primaryNodes}</div>\n );\n\n return (\n <>\n {tabActionsNode}\n {contentNode}\n {activeFormAction != null &&\n isFormMutationAction(activeFormAction) && (\n <LazyBackofficeEntityActionFormDialog\n isOpen\n action={activeFormAction}\n node={view}\n onClose={() => {\n setActiveFormActionId(null);\n }}\n />\n )}\n </>\n );\n }}\n />\n );\n};\n\nexport const BackofficeEntityDetailPage = ({\n config,\n prepared,\n}: BackofficeEntityDetailPageProps): JSX.Element => {\n const { layoutView } = useBackofficeEntityDetailLayoutContext();\n\n const resolvedPages = resolveVisibleDetailPages({\n mainPage: config.pages.mainPage,\n subPages: config.pages.subPages,\n activePagePath: prepared.pagePath,\n node: layoutView as never,\n });\n\n if (!resolvedPages.hasVisiblePages || resolvedPages.activePage == null) {\n return <BackofficeRedirect to={config.routes.list} />;\n }\n\n if (resolvedPages.activePage.id !== prepared.pageId) {\n return (\n <BackofficeRedirect\n to={config.routes.detailPage(prepared.id, resolvedPages.activePage.id)}\n />\n );\n }\n\n return (\n <BackofficeEntityDetailPageContent\n config={prepared.pageConfig}\n prepared={prepared}\n />\n );\n};\n\nexport default BackofficeEntityDetailPage;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BackofficeEntityDetailPage.js","names":[],"sources":["../../../src/pages/BackofficeEntityDetailPage.tsx"],"sourcesContent":["/* eslint-disable no-ternary */\nimport { type JSX, type ReactNode, useContext, useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n type PreloadedQuery,\n usePreloadedQuery,\n} from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\nimport { resolveMutationOutcome } from '../relay/mutationResult.js';\nimport { setWhereValue } from '@plumile/backoffice-core/filters/where.js';\nimport {\n buildBackofficeFallbackListHref,\n buildBackofficeListHref,\n buildBackofficeListLink,\n} from '@plumile/backoffice-core/state/buildListHref.js';\n\nimport { BACKOFFICE_DATE_TIME_OPTIONS } from '@plumile/backoffice-core/constants.js';\nimport type {\n BackofficeResolvedDetailLayoutFacetConfigBase,\n BackofficeResolvedDetailPageFacetConfig,\n BackofficeResolvedDetailPageFacetConfigBase,\n} from '@plumile/backoffice-core/types.js';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { LinkButton } from '@plumile/ui/atomic/atoms/button/LinkButton.js';\nimport { FormattedDate } from '@plumile/ui/atomic/atoms/formatted-date/FormattedDate.js';\nimport { useToast } from '@plumile/ui/atomic/molecules/toast/ToastProvider.js';\nimport { Tag } from '@plumile/ui/backoffice/atoms/tag/Tag.js';\nimport { BackofficeDetailSection } from '@plumile/ui/backoffice/molecules/backoffice_detail_section/BackofficeDetailSection.js';\nimport { BackofficeKeyValueList } from '@plumile/ui/backoffice/molecules/backoffice_key_value_list/BackofficeKeyValueList.js';\nimport { BackofficePayloadViewer } from '@plumile/ui/backoffice/molecules/backoffice_payload_viewer/BackofficePayloadViewer.js';\nimport {\n BackofficeRelationsMenu,\n type BackofficeRelationsMenuItem,\n} from '@plumile/ui/backoffice/molecules/backoffice_relations_menu/BackofficeRelationsMenu.js';\nimport { BackofficeScopeStack } from '@plumile/ui/backoffice/molecules/backoffice_scope_stack/BackofficeScopeStack.js';\nimport { AuditTimeline } from '@plumile/ui/backoffice/organisms/audit_timeline/AuditTimeline.js';\nimport { MetricCard } from '@plumile/ui/components/dashboard/metric_card/MetricCard.js';\nimport { MetricTileGroup } from '@plumile/ui/components/dashboard/metric_tile_group/MetricTileGroup.js';\nimport { DataTable } from '@plumile/ui/components/data-table/DataTable.js';\nimport { ChatCheckSvg } from '@plumile/ui/icons/ChatCheckSvg.js';\nimport { KeyOffSvg } from '@plumile/ui/icons/KeyOffSvg.js';\nimport { KeySvg } from '@plumile/ui/icons/KeySvg.js';\nimport { LockOpenSvg } from '@plumile/ui/icons/LockOpenSvg.js';\nimport { LockSvg } from '@plumile/ui/icons/LockSvg.js';\nimport { RobotCheckSvg } from '@plumile/ui/icons/RobotCheckSvg.js';\nimport { RobotXSvg } from '@plumile/ui/icons/RobotXSvg.js';\nimport { RocketOffSvg } from '@plumile/ui/icons/RocketOffSvg.js';\nimport { RocketSvg } from '@plumile/ui/icons/RocketSvg.js';\nimport { SettingsCheckSvg } from '@plumile/ui/icons/SettingsCheckSvg.js';\nimport { SettingsXSvg } from '@plumile/ui/icons/SettingsXSvg.js';\nimport { ShieldLockSvg } from '@plumile/ui/icons/ShieldLockSvg.js';\nimport { ShieldOffSvg } from '@plumile/ui/icons/ShieldOffSvg.js';\nimport { XBadgeSvg } from '@plumile/ui/icons/XBadgeSvg.js';\nimport Link from '@plumile/router/routing/Link.js';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\n\nimport { buildDataTableColumns } from '../components/backoffice/columns/buildDataTableColumns.js';\nimport { BackofficeEntityDetailScaffold } from '../components/backoffice/scaffolds/BackofficeEntityDetailScaffold.js';\nimport { useBackofficeEntityDetailNotFoundState } from '../components/backoffice/scaffolds/BackofficeEntityDetailNotFound.js';\nimport { BackofficeDetailBadgeRow } from '../components/backoffice/detail/BackofficeDetailBadgeRow.js';\nimport { BackofficeDetailFlagTag } from '../components/backoffice/detail/BackofficeDetailFlagTag.js';\nimport { BackofficeDetailTaggedValue } from '../components/backoffice/detail/BackofficeDetailTaggedValue.js';\nimport { BackofficeLifecycleTimelineSection } from '../components/backoffice/detail/BackofficeLifecycleTimelineSection.js';\nimport { BackofficeRelationsSummaryGrid } from '../components/backoffice/detail/BackofficeRelationsSummaryGrid.js';\nimport * as detailLayoutStyles from '../components/backoffice/detail/backofficeDetailLayout.css.js';\nimport { LazyBackofficeEntityActionFormDialog } from '../components/backoffice/actions/LazyBackofficeEntityActionFormDialog.js';\nimport {\n resolveToastSpec,\n resolveToastViewActions,\n} from '../components/backoffice/actions/toastViewAction.js';\nimport * as pageStyles from './backofficeEntityDetailPage.css.js';\nimport { useBackofficeFormats } from '../i18n/useBackofficeFormats.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport { useBackofficeFragment } from '../relay/typedRelayHooks.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { useBackofficeEntityDetailLayoutContext } from './detail/BackofficeEntityDetailLayoutContext.js';\nimport { resolveVisibleDetailPages } from './detail/pageResolution.js';\nimport {\n extractMutationPayload,\n isFormMutationAction,\n isMutationAction,\n isRouteAction,\n resolveLabel,\n} from './BackofficeEntityDetailPage.helpers.js';\nimport {\n buildFieldItems,\n renderBlocks,\n type FlagIconName,\n} from './BackofficeEntityDetailPage.view-helpers.js';\nimport { BackofficeRedirect } from './BackofficeRedirect.js';\nimport { BackofficeLazyEntityCount } from '../components/backoffice/refs/BackofficeLazyEntityCount.js';\n\nexport type BackofficeEntityDetailPageProps = {\n config: BackofficeResolvedDetailLayoutFacetConfigBase;\n prepared: {\n id: string;\n detailId?: string;\n pageConfig: BackofficeResolvedDetailPageFacetConfigBase;\n pageQuery: PreloadedQuery<OperationType>;\n pageId: string;\n pagePath: string;\n };\n};\n\nconst renderFlagIcon = (iconName: FlagIconName): JSX.Element => {\n const iconSize = 14;\n switch (iconName) {\n case 'shield-lock':\n return (\n <ShieldLockSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'shield-off':\n return (\n <ShieldOffSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'settings-check':\n return (\n <SettingsCheckSvg\n width={iconSize}\n height={iconSize}\n aria-hidden=\"true\"\n />\n );\n case 'settings-x':\n return (\n <SettingsXSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'x-badge':\n return (\n <XBadgeSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'chat-check':\n return (\n <ChatCheckSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'key':\n return <KeySvg width={iconSize} height={iconSize} aria-hidden=\"true\" />;\n case 'key-off':\n return (\n <KeyOffSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'lock':\n return <LockSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />;\n case 'lock-open':\n return (\n <LockOpenSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'robot-check':\n return (\n <RobotCheckSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'robot-x':\n return (\n <RobotXSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'rocket':\n return (\n <RocketSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n case 'rocket-off':\n return (\n <RocketOffSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n );\n default:\n throw new Error(`Unsupported flag icon: ${String(iconName)}`);\n }\n};\n\nconst resolveDetailPlacement = (item: {\n placement?: 'primary' | 'secondary' | 'main' | 'side' | 'fullWidth';\n presentation?: {\n group?: string;\n desktop?: 'primary' | 'secondary' | 'fullWidth';\n };\n kind?: string;\n fields?: readonly {\n presentation?: {\n group?: string;\n desktop?: 'primary' | 'secondary' | 'fullWidth';\n };\n }[];\n}): 'primary' | 'secondary' => {\n if (item.presentation?.desktop === 'secondary') {\n return 'secondary';\n }\n if (\n item.presentation?.group === 'scope' ||\n item.presentation?.group === 'status'\n ) {\n return 'secondary';\n }\n const fieldGroups =\n item.fields?.map((field) => {\n return field.presentation?.group;\n }) ?? [];\n if (\n fieldGroups.length > 0 &&\n fieldGroups.every((group) => {\n return group === 'scope' || group === 'status';\n })\n ) {\n return 'secondary';\n }\n if (item.placement === 'side') {\n return 'secondary';\n }\n if (item.placement === 'secondary') {\n return 'secondary';\n }\n return 'primary';\n};\n\nconst BackofficeEntityDetailPageContent = ({\n config,\n prepared,\n}: {\n config: BackofficeResolvedDetailPageFacetConfig;\n prepared: {\n pageQuery: PreloadedQuery<OperationType>;\n id: string;\n detailId?: string;\n pageId: string;\n pagePath: string;\n };\n}): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { formatNumber, formatCurrency, formatCurrencyTitle, formatPercent } =\n useBackofficeFormats();\n const { entities, entityRegistry } = useBackofficeConfig();\n const routing = useContext(RoutingContext);\n const environment = useRelayEnvironment();\n const toast = useToast();\n const [actionState, setActionState] = useState<Record<string, boolean>>({});\n const [activeFormActionId, setActiveFormActionId] = useState<string | null>(\n null,\n );\n const setActionLoading = (actionId: string, isLoading: boolean) => {\n setActionState((prev) => {\n if (prev[actionId] === isLoading) {\n return prev;\n }\n return { ...prev, [actionId]: isLoading };\n });\n };\n\n const { page } = config;\n const notFound = useBackofficeEntityDetailNotFoundState({\n listHref: config.routes.list,\n });\n\n const pageQueryData = usePreloadedQuery(page.query, prepared.pageQuery);\n const pageNodeRef = page.resolveNode(pageQueryData, {\n id: prepared.id,\n detailId: prepared.detailId,\n });\n const resolvedNode = useBackofficeFragment<\n unknown,\n { __typename: string } | null | undefined\n >(page.fragment, pageNodeRef);\n const relationEntityListRoutes = useMemo(() => {\n return Object.fromEntries(\n page.content\n .flatMap((block) => {\n if (block.kind !== 'fieldSet') {\n return [];\n }\n\n return block.fields.flatMap((field) => {\n if (field.type !== 'relation') {\n return [];\n }\n return [field.relation.target];\n });\n })\n .flatMap((entityId) => {\n const entityManifest = entities[entityId];\n if (entityManifest?.hasList !== true) {\n return [];\n }\n return [[entityId, entityManifest.routes.list]];\n }),\n );\n }, [entities, page.content]);\n\n return (\n <BackofficeEntityDetailScaffold\n node={resolvedNode}\n notFound={notFound}\n render={(node) => {\n const view = page.toView(node);\n const resolveEntityHref = (entityId: string, refId: string) => {\n const entityConfig = entities[entityId];\n if (entityConfig == null) {\n return null;\n }\n return entityConfig.routes.detail(refId);\n };\n const resolveRelationItem = ({\n id,\n label,\n relation,\n listRoute,\n value,\n where,\n }: {\n id: string;\n label: string;\n relation: {\n target: string;\n filterId?: string;\n whereKey: string;\n path?: readonly string[];\n };\n listRoute: string;\n value: string;\n where: Record<string, unknown>;\n }): BackofficeRelationsMenuItem => {\n const { target, filterId, whereKey, path } = relation;\n const loadedEntity = entityRegistry.getLoadedListEntity(target);\n return {\n id,\n label,\n count: <BackofficeLazyEntityCount entity={target} where={where} />,\n href:\n loadedEntity == null\n ? buildBackofficeFallbackListHref(listRoute, where, [\n {\n id:\n filterId ??\n (path == null\n ? whereKey\n : `${whereKey}.${path.join('.')}`),\n value,\n },\n ])\n : buildBackofficeListHref(loadedEntity.config, { where }),\n onClick: async (event) => {\n if (\n routing == null ||\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.altKey ||\n event.ctrlKey ||\n event.shiftKey\n ) {\n return;\n }\n\n event.preventDefault();\n\n const listEntity = await entityRegistry.loadListEntity(target);\n const next = buildBackofficeListLink(listEntity.config, {\n where,\n });\n\n routing.history.push({\n pathname: next.pathname,\n search: next.search === '' ? '' : `?${next.search}`,\n hash: '',\n });\n },\n };\n };\n\n const actions = page.actions ?? [];\n let headerActionButtons: ReactNode[] = [];\n if (actions.length > 0) {\n const visibleActions = actions.filter((action) => {\n if (action.isVisible == null) {\n return true;\n }\n return action.isVisible(view);\n });\n\n if (visibleActions.length > 0) {\n headerActionButtons = visibleActions.map((action) => {\n const label = resolveLabel(action.label, tApp);\n const ariaLabel =\n action.ariaLabel != null\n ? resolveLabel(action.ariaLabel, tApp)\n : label;\n const variant = action.variant ?? 'secondary';\n const size = action.size ?? 'small';\n const isLoading = actionState[action.id] ?? false;\n const isDisabled =\n isLoading || action.isDisabled?.(view) === true;\n\n if (isRouteAction(action)) {\n const href = action.to(view);\n return (\n <LinkButton\n key={action.id}\n to={href}\n variant={variant}\n size={size}\n isDisabled={isDisabled}\n aria-label={ariaLabel}\n preloadOnMouseEnter\n >\n {label}\n </LinkButton>\n );\n }\n\n if (isFormMutationAction(action)) {\n return (\n <Button\n key={action.id}\n type=\"button\"\n variant={variant}\n size={size}\n isLoading={false}\n disabled={isDisabled}\n onClick={() => {\n setActiveFormActionId(action.id);\n }}\n aria-label={ariaLabel}\n >\n {label}\n </Button>\n );\n }\n\n if (isMutationAction(action)) {\n const handleClick = () => {\n if (isLoading) {\n return;\n }\n const variables = action.getVariables(view);\n setActionLoading(action.id, true);\n commitMutation(environment, {\n mutation: action.mutation,\n variables,\n updater: (store) => {\n action.updater?.(store, view);\n },\n onCompleted: (response) => {\n setActionLoading(action.id, false);\n const mutationPayload = extractMutationPayload(response);\n if (mutationPayload != null) {\n let defaultErrorMessage = t(\n 'actions.form.errors.invalidPayload',\n );\n if (action.toasts?.error?.message != null) {\n defaultErrorMessage = resolveLabel(\n action.toasts.error.message,\n tApp,\n );\n } else if (action.toasts?.error?.title != null) {\n defaultErrorMessage = resolveLabel(\n action.toasts.error.title,\n tApp,\n );\n }\n\n const outcome = resolveMutationOutcome(\n mutationPayload,\n {\n defaultErrorMessage,\n mapReason: (reason) => {\n const mapped = action.mapErrorReason?.(\n reason,\n view,\n );\n if (mapped == null) {\n return null;\n }\n if (typeof mapped === 'function') {\n return resolveLabel(mapped, tApp);\n }\n return String(mapped);\n },\n },\n );\n if (!outcome.ok) {\n const error = new Error(outcome.message);\n action.onError?.(error, view);\n if (action.toasts?.error != null) {\n const toastSpec = resolveToastSpec(\n action.toasts.error,\n tApp,\n );\n toast.error(toastSpec.title, toastSpec.message);\n }\n return;\n }\n }\n\n action.onCompleted?.(response, view);\n if (action.toasts?.success != null) {\n const toastSpec = resolveToastSpec(\n action.toasts.success,\n tApp,\n );\n const toastActions = resolveToastViewActions({\n toast: action.toasts.success,\n response,\n node: view,\n tApp,\n entities,\n defaultLabel: t('actions.view'),\n navigateTo: (to) => {\n routing?.history.push({ pathname: to });\n },\n });\n toast.push({\n kind: 'info',\n title: toastSpec.title,\n message: toastSpec.message,\n actions: toastActions,\n });\n }\n },\n onError: (error) => {\n setActionLoading(action.id, false);\n action.onError?.(error, view);\n if (action.toasts?.error != null) {\n const toastSpec = resolveToastSpec(\n action.toasts.error,\n tApp,\n );\n toast.error(toastSpec.title, toastSpec.message);\n }\n },\n });\n };\n\n return (\n <Button\n key={action.id}\n type=\"button\"\n variant={variant}\n size={size}\n isLoading={isLoading}\n disabled={isDisabled}\n onClick={handleClick}\n aria-label={ariaLabel}\n >\n {label}\n </Button>\n );\n }\n\n return null;\n });\n }\n }\n\n const activeFormAction = actions.find((action) => {\n return action.id === activeFormActionId;\n });\n\n const { content } = page;\n\n const primaryNodes: ReactNode[] = [];\n const secondaryNodes: ReactNode[] = [];\n const relationMenuItems: BackofficeRelationsMenuItem[] = [];\n\n content.forEach((item, index) => {\n const placement = resolveDetailPlacement(item);\n const targetNodes =\n placement === 'secondary' ? secondaryNodes : primaryNodes;\n\n if (item.kind === 'fieldSet') {\n const sectionLabel = resolveLabel(item.title, tApp);\n const description =\n item.description != null\n ? resolveLabel(item.description, tApp)\n : undefined;\n const { items, relationItems, customNodes } = buildFieldItems(\n item.fields,\n view,\n {\n tApp,\n t,\n resolveEntityHref,\n formatNumber,\n formatCurrency,\n formatCurrencyTitle,\n formatPercent,\n relationEntityListRoutes,\n resolveRelationItem,\n setWhereValue,\n renderTag: (tone, label) => {\n return <Tag tone={tone}>{label}</Tag>;\n },\n renderBadgeRow: (items) => {\n return <BackofficeDetailBadgeRow items={items} />;\n },\n renderDate: (value, fallback) => {\n return (\n <FormattedDate\n value={value}\n options={BACKOFFICE_DATE_TIME_OPTIONS}\n fallback={fallback}\n />\n );\n },\n renderFlagTag: (tag) => {\n return (\n <BackofficeDetailFlagTag\n tone={tag.tone}\n icon={\n tag.iconName != null\n ? renderFlagIcon(tag.iconName)\n : undefined\n }\n label={tag.label}\n />\n );\n },\n renderLink: (href, label) => {\n return (\n <Link to={href} preloadOnMouseEnter>\n {label}\n </Link>\n );\n },\n renderTaggedValue: (tag, value) => {\n return (\n <BackofficeDetailTaggedValue tag={tag} value={value} />\n );\n },\n wrapCustomNode: (id, custom) => {\n return <div key={id}>{custom}</div>;\n },\n },\n );\n relationItems.forEach((relation) => {\n if (\n !relationMenuItems.some((entry) => {\n return entry.id === relation.id;\n })\n ) {\n relationMenuItems.push(relation);\n }\n });\n\n const hasContent = items.length > 0 || customNodes.length > 0;\n\n if (!hasContent) {\n return;\n }\n\n targetNodes.push(\n <BackofficeDetailSection\n key={`${sectionLabel}-${index}`}\n title={sectionLabel}\n description={description}\n items={items.length > 0 ? items : undefined}\n >\n {customNodes}\n </BackofficeDetailSection>,\n );\n return;\n }\n\n const rendered = renderBlocks([item], view, {\n tApp,\n t,\n resolveEntityHref,\n keyPrefix: String(index),\n renderLink: (href, label) => {\n return (\n <Link to={href} preloadOnMouseEnter>\n {label}\n </Link>\n );\n },\n renderDate: (value, fallback) => {\n return (\n <FormattedDate\n value={value}\n options={BACKOFFICE_DATE_TIME_OPTIONS}\n fallback={fallback}\n />\n );\n },\n renderTag: (tone, label) => {\n return <Tag tone={tone}>{label}</Tag>;\n },\n renderMetricGroup: ({\n key,\n title,\n description,\n density,\n items,\n }) => {\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n {items.length > 0 && (\n <MetricTileGroup\n density={density ?? 'comfortable'}\n minColumn=\"180\"\n >\n {items.map((metric) => {\n return (\n <MetricCard\n key={metric.id}\n label={metric.label}\n value={metric.value}\n hint={metric.hint}\n tone={metric.tone ?? 'neutral'}\n density={density ?? 'comfortable'}\n copyValue={metric.copyValue}\n copyLabel={t('common.actions.copy')}\n copiedLabel={t('common.actions.copied')}\n />\n );\n })}\n </MetricTileGroup>\n )}\n </BackofficeDetailSection>\n );\n },\n renderTimeline: ({ key, title, description, events }) => {\n return (\n <BackofficeLifecycleTimelineSection\n key={key}\n title={title}\n description={description}\n events={events}\n />\n );\n },\n renderAuditTimeline: ({ key, title, description, events }) => {\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <AuditTimeline events={events} />\n </BackofficeDetailSection>\n );\n },\n renderRelations: ({ key, title, items }) => {\n return (\n <BackofficeRelationsSummaryGrid\n key={key}\n title={title}\n items={items}\n />\n );\n },\n renderContextStack: ({ key, title, items }) => {\n return (\n <BackofficeScopeStack key={key} title={title} items={items} />\n );\n },\n renderCustomSection: (key, title, child) => {\n return (\n <BackofficeDetailSection key={key} title={title}>\n {child}\n </BackofficeDetailSection>\n );\n },\n wrapCustomNode: (key, custom) => {\n return <div key={key}>{custom}</div>;\n },\n resolveTableColumns: (columns) => {\n return buildDataTableColumns(columns, {\n tApp,\n t,\n });\n },\n renderTable: ({ key, title, description, columns, rows }) => {\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <DataTable\n columns={columns}\n rows={rows}\n getRowId={(row, rowIndex) => {\n if (row != null && typeof row === 'object') {\n const record = row as Record<string, unknown>;\n const maybeId = record.id;\n if (\n typeof maybeId === 'string' &&\n maybeId.trim() !== ''\n ) {\n return maybeId;\n }\n }\n return String(rowIndex);\n }}\n />\n </BackofficeDetailSection>\n );\n },\n renderPayload: ({ key, title, description, content, format }) => {\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <BackofficePayloadViewer\n content={content}\n format={format}\n emptyState={t('common.notAvailable')}\n />\n </BackofficeDetailSection>\n );\n },\n renderKeyValueListSection: ({ key, title, description, items }) => {\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <BackofficeKeyValueList items={items} />\n </BackofficeDetailSection>\n );\n },\n });\n const blockNode = rendered[0];\n if (blockNode != null) {\n targetNodes.push(blockNode);\n }\n });\n\n const relationsMenuNode =\n relationMenuItems.length > 0 ? (\n <BackofficeRelationsMenu\n label={t('relations.menu.label')}\n items={relationMenuItems}\n />\n ) : null;\n\n const tabActionsNode =\n headerActionButtons.length > 0 || relationsMenuNode != null ? (\n <div className={pageStyles.headerActions}>\n {headerActionButtons.length > 0 && (\n <div className={pageStyles.headerActionGroup}>\n {headerActionButtons}\n </div>\n )}\n {relationsMenuNode != null && (\n <div className={pageStyles.headerRelationGroup}>\n {relationsMenuNode}\n </div>\n )}\n </div>\n ) : null;\n\n const hasAside = secondaryNodes.length > 0;\n const contentNode = hasAside ? (\n <div className={detailLayoutStyles.layout}>\n <div className={detailLayoutStyles.primary}>{primaryNodes}</div>\n <aside className={detailLayoutStyles.secondary}>\n {secondaryNodes}\n </aside>\n </div>\n ) : (\n <div className={detailLayoutStyles.stacked}>{primaryNodes}</div>\n );\n\n return (\n <>\n {tabActionsNode}\n {contentNode}\n {activeFormAction != null &&\n isFormMutationAction(activeFormAction) && (\n <LazyBackofficeEntityActionFormDialog\n isOpen\n action={activeFormAction}\n node={view}\n onClose={() => {\n setActiveFormActionId(null);\n }}\n />\n )}\n </>\n );\n }}\n />\n );\n};\n\nexport const BackofficeEntityDetailPage = ({\n config,\n prepared,\n}: BackofficeEntityDetailPageProps): JSX.Element => {\n const { layoutView } = useBackofficeEntityDetailLayoutContext();\n\n const resolvedPages = resolveVisibleDetailPages({\n mainPage: config.pages.mainPage,\n subPages: config.pages.subPages,\n activePagePath: prepared.pagePath,\n node: layoutView,\n });\n\n if (!resolvedPages.hasVisiblePages || resolvedPages.activePage == null) {\n return <BackofficeRedirect to={config.routes.list} />;\n }\n\n if (resolvedPages.activePage.id !== prepared.pageId) {\n return (\n <BackofficeRedirect\n to={config.routes.detailPage(prepared.id, resolvedPages.activePage.id)}\n />\n );\n }\n\n return (\n <BackofficeEntityDetailPageContent\n config={prepared.pageConfig}\n prepared={prepared}\n />\n );\n};\n\nexport default BackofficeEntityDetailPage;\n"],"mappings":"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"}
@@ -576,7 +576,7 @@ var l = (e, t, n) => {
576
576
  title: p,
577
577
  description: m,
578
578
  content: t.value(r),
579
- format: t.format
579
+ format: t.format ?? "json"
580
580
  });
581
581
  });
582
582
  };
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeEntityDetailPage.view-helpers.js","names":[],"sources":["../../../src/pages/BackofficeEntityDetailPage.view-helpers.ts"],"sourcesContent":["/* eslint-disable no-ternary */\nimport type {\n BackofficeBadgeItem,\n BackofficeDetailBlockSpec,\n BackofficeDetailFieldSpec,\n BackofficeDetailHeaderConfig,\n BackofficeDetailHeaderMetaSpec,\n BackofficeDetailHeaderStatusSpec,\n BackofficeFieldSize,\n BackofficeFlagVariant,\n BackofficeInlineValueSpec,\n BackofficeRuntimeRelationFilterSpec,\n BackofficeTone,\n BackofficeValueLabel,\n} from '@plumile/backoffice-core/types.js';\nimport type { TFunction } from 'i18next';\nimport { Fragment, createElement, type ReactNode } from 'react';\n\nimport {\n isEmptyText,\n resolveLabel,\n resolveBadgeTone,\n resolveRelationValue,\n resolveValueLabel,\n} from './BackofficeEntityDetailPage.helpers.js';\nimport {\n normalizeTechnicalIdentifier,\n TechnicalIdentifierValue,\n type TechnicalIdentifierVariant,\n} from '../components/backoffice/technical/TechnicalIdentifierValue.js';\n\nexport type ResolvedFieldItem = {\n id: string;\n label: string;\n size: BackofficeFieldSize;\n value: ReactNode;\n copyValue?: string;\n fullWidth?: boolean;\n};\n\nexport type ResolvedHeaderItem = {\n id: string;\n label: string;\n value: ReactNode;\n};\n\nexport type FlagIconName =\n | 'shield-lock'\n | 'shield-off'\n | 'settings-check'\n | 'settings-x'\n | 'x-badge'\n | 'chat-check'\n | 'key'\n | 'key-off'\n | 'lock'\n | 'lock-open'\n | 'robot-check'\n | 'robot-x'\n | 'rocket'\n | 'rocket-off';\n\nexport type ResolvedFlagTag = {\n tone: 'neutral' | 'info' | 'success' | 'warning' | 'danger';\n label: string;\n iconName?: FlagIconName;\n};\n\nexport const resolveFlagTag = (\n variant: BackofficeFlagVariant,\n value: boolean,\n t: TFunction,\n): ResolvedFlagTag => {\n switch (variant) {\n case 'yesNo':\n return value\n ? { tone: 'success', label: t('common.boolean.yes') }\n : { tone: 'neutral', label: t('common.boolean.no') };\n case 'capability':\n return value\n ? {\n tone: 'success',\n label: t('flags.capability.allowed'),\n iconName: 'shield-lock',\n }\n : {\n tone: 'neutral',\n label: t('flags.capability.denied'),\n iconName: 'shield-off',\n };\n case 'enabled':\n return value\n ? {\n tone: 'success',\n label: t('flags.enabled.enabled'),\n iconName: 'settings-check',\n }\n : {\n tone: 'neutral',\n label: t('flags.enabled.disabled'),\n iconName: 'settings-x',\n };\n case 'failure':\n return value\n ? {\n tone: 'danger',\n label: t('flags.failure.failed'),\n iconName: 'x-badge',\n }\n : {\n tone: 'success',\n label: t('flags.failure.ok'),\n iconName: 'chat-check',\n };\n case 'encrypted':\n return value\n ? {\n tone: 'info',\n label: t('flags.encrypted.encrypted'),\n iconName: 'key',\n }\n : {\n tone: 'neutral',\n label: t('flags.encrypted.notEncrypted'),\n iconName: 'key-off',\n };\n case 'locked':\n return value\n ? {\n tone: 'warning',\n label: t('flags.locked.locked'),\n iconName: 'lock',\n }\n : {\n tone: 'success',\n label: t('flags.locked.unlocked'),\n iconName: 'lock-open',\n };\n case 'default':\n return value\n ? { tone: 'info', label: t('flags.default.default') }\n : { tone: 'neutral', label: t('flags.default.notDefault') };\n case 'agentManaged':\n return value\n ? {\n tone: 'info',\n label: t('flags.agentManaged.agentManaged'),\n iconName: 'robot-check',\n }\n : {\n tone: 'neutral',\n label: t('flags.agentManaged.userManaged'),\n iconName: 'robot-x',\n };\n case 'deployedProduction':\n return value\n ? {\n tone: 'success',\n label: t('flags.deployedProduction.deployed'),\n iconName: 'rocket',\n }\n : {\n tone: 'neutral',\n label: t('flags.deployedProduction.notDeployed'),\n iconName: 'rocket-off',\n };\n case 'forced':\n return value\n ? { tone: 'warning', label: t('flags.forced.forced') }\n : { tone: 'neutral', label: t('flags.forced.normal') };\n default:\n throw new Error(`Unsupported flag variant: ${String(variant)}`);\n }\n};\n\nexport const resolveInlineValue = (\n value: BackofficeInlineValueSpec,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n },\n): ReactNode => {\n const { tApp, t, resolveEntityHref, renderLink } = options;\n const fallback = t('common.notAvailable');\n\n if (value.type === 'text') {\n const resolved = resolveValueLabel(value.value, tApp);\n return isEmptyText(resolved) ? fallback : resolved;\n }\n\n if (value.type === 'entityRef') {\n const { id } = value;\n if (id == null || id.trim() === '') {\n return fallback;\n }\n const resolvedLabel = resolveValueLabel(value.label, tApp);\n const label =\n resolvedLabel != null && String(resolvedLabel).trim() !== ''\n ? resolvedLabel\n : null;\n if (label == null) {\n return fallback;\n }\n const href = resolveEntityHref?.(value.entity, id) ?? null;\n return href != null ? renderLink(href, label) : label;\n }\n\n const { href } = value;\n if (href == null || href.trim() === '') {\n return fallback;\n }\n const label = resolveValueLabel(value.label, tApp);\n if (isEmptyText(label)) {\n return fallback;\n }\n return renderLink(href, label);\n};\n\nexport const resolveHeaderMeta = <Node>(\n meta: BackofficeDetailHeaderMetaSpec<Node>,\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n renderDate: (\n value: string | number | null | undefined,\n fallback: string,\n ) => ReactNode;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n },\n): ReactNode => {\n const { tApp, t, resolveEntityHref, renderDate, renderLink } = options;\n const fallback = t('common.notAvailable');\n\n if (meta.type === 'dateTime') {\n return renderDate(meta.value(node), fallback);\n }\n\n if (meta.type === 'entityRef') {\n const idValue = meta.id(node);\n if (idValue == null || idValue.trim() === '') {\n return fallback;\n }\n const labelValue = resolveValueLabel(meta.value?.(node), tApp);\n const label =\n labelValue != null && String(labelValue).trim() !== ''\n ? labelValue\n : null;\n if (label == null) {\n return fallback;\n }\n const href = resolveEntityHref?.(meta.entity, idValue) ?? null;\n return href != null ? renderLink(href, label) : label;\n }\n\n if (meta.type === 'link') {\n const href = meta.href(node);\n const labelValue = resolveValueLabel(meta.value(node), tApp);\n if (href == null || href.trim() === '' || isEmptyText(labelValue)) {\n return fallback;\n }\n return renderLink(href, labelValue);\n }\n\n const value = resolveValueLabel(meta.value(node), tApp);\n return isEmptyText(value) ? fallback : value;\n};\n\nexport const resolveHeaderStatus = <Node>(\n status: BackofficeDetailHeaderStatusSpec<Node>,\n node: Node,\n tApp: TFunction,\n renderers: {\n renderBadgeRow: (items: readonly BackofficeBadgeItem[]) => ReactNode;\n renderTag: (\n tone: ReturnType<typeof resolveBadgeTone<Node>>,\n label: string,\n ) => ReactNode;\n },\n): ReactNode | undefined => {\n if (status.type === 'badgeRow') {\n const items = status.items(node).map((item) => {\n const resolvedLabel = resolveValueLabel(item.label, tApp);\n const label = resolvedLabel == null ? '' : String(resolvedLabel);\n return { ...item, label };\n });\n if (items.length === 0) {\n return undefined;\n }\n return renderers.renderBadgeRow(items);\n }\n\n const value = resolveValueLabel(status.value(node), tApp);\n const label = value == null ? '' : String(value);\n if (label.trim() === '') {\n return undefined;\n }\n const tone = resolveBadgeTone(status.tone, node);\n return renderers.renderTag(tone, label);\n};\n\nexport const buildFieldItems = <Node, RelationItem>(\n fields: readonly BackofficeDetailFieldSpec<Node>[],\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n formatNumber: (value: number | null | undefined) => string;\n formatCurrency: (value: number | null | undefined) => string;\n formatCurrencyTitle?: (value: number | null | undefined) => string | null;\n formatPercent: (value: number | null | undefined) => string;\n relationEntityListRoutes: Record<string, string>;\n resolveRelationItem: (args: {\n id: string;\n label: string;\n relation: BackofficeRuntimeRelationFilterSpec;\n listRoute: string;\n value: string;\n where: Record<string, unknown>;\n }) => RelationItem;\n setWhereValue: (\n where: Record<string, unknown> | null,\n whereKey: string,\n value: string,\n path?: readonly string[],\n ) => Record<string, unknown> | null;\n renderTag: (\n tone: ReturnType<typeof resolveBadgeTone<Node>>,\n label: string,\n ) => ReactNode;\n renderBadgeRow: (items: readonly BackofficeBadgeItem[]) => ReactNode;\n renderDate: (\n value: string | number | null | undefined,\n fallback: string,\n ) => ReactNode;\n renderFlagTag: (tag: ResolvedFlagTag) => ReactNode;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n renderTaggedValue: (tag: unknown, value: ReactNode) => ReactNode;\n wrapCustomNode: (id: string, node: ReactNode) => ReactNode;\n },\n): {\n items: ResolvedFieldItem[];\n relationItems: RelationItem[];\n customNodes: ReactNode[];\n} => {\n const {\n tApp,\n t,\n resolveEntityHref,\n formatNumber,\n formatCurrency,\n formatCurrencyTitle,\n formatPercent,\n relationEntityListRoutes,\n resolveRelationItem,\n setWhereValue,\n renderTag,\n renderBadgeRow,\n renderDate,\n renderFlagTag,\n renderLink,\n renderTaggedValue,\n wrapCustomNode,\n } = options;\n const items: ResolvedFieldItem[] = [];\n const relationItems: RelationItem[] = [];\n const customNodes: ReactNode[] = [];\n const fallback = t('common.notAvailable');\n\n fields.forEach((field, index) => {\n const id = `${field.type}-${index}`;\n\n switch (field.type) {\n case 'text': {\n const value = resolveValueLabel(field.value(node), tApp);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value,\n copyValue: field.copyValue?.(node) ?? undefined,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'badge': {\n const value = resolveValueLabel(field.value(node), tApp);\n const label = value != null ? String(value) : '';\n const tone = resolveBadgeTone(field.tone, node);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: label.trim() !== '' ? renderTag(tone, label) : null,\n });\n break;\n }\n case 'badgeRow': {\n const badgeItems = field.items(node).map((item) => {\n const resolvedLabel = resolveValueLabel(item.label, tApp);\n const label = resolvedLabel == null ? '' : String(resolvedLabel);\n return { ...item, label };\n });\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: badgeItems.length > 0 ? renderBadgeRow(badgeItems) : null,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'dateTime': {\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: renderDate(field.value(node), fallback),\n });\n break;\n }\n case 'number': {\n const value = field.value(node);\n let formatted: ReactNode | null = null;\n if (value != null) {\n if (field.format === 'currency') {\n const label = formatCurrency(value);\n formatted = createElement(\n 'span',\n { title: formatCurrencyTitle?.(value) ?? undefined },\n label,\n );\n } else if (field.format === 'percent') {\n formatted = formatPercent(value);\n } else {\n formatted = formatNumber(value);\n }\n }\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: formatted,\n });\n break;\n }\n case 'flag': {\n const value = field.value(node);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value:\n value != null\n ? renderFlagTag(resolveFlagTag(field.variant, value, t))\n : null,\n });\n break;\n }\n case 'entityRef': {\n const idValue = field.id(node);\n let value: ReactNode | null = null;\n if (idValue != null && idValue.trim() !== '') {\n const labelValue = field.value?.(node);\n const label =\n labelValue != null && labelValue.trim() !== '' ? labelValue : null;\n const href = resolveEntityHref?.(field.entity, idValue) ?? null;\n if (label != null) {\n value = href != null ? renderLink(href, label) : label;\n }\n }\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: value ?? fallback,\n });\n break;\n }\n case 'technicalIdentifier': {\n const value = field.value(node);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value:\n value == null\n ? null\n : createElement(TechnicalIdentifierValue, {\n value,\n copyValue: field.copyValue?.(node) ?? undefined,\n variant: field.variant,\n copyLabel: t('common.actions.copy'),\n }),\n copyValue: field.copyValue?.(node) ?? undefined,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'link': {\n const href = field.href(node);\n const labelValue = field.value(node);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value:\n href != null && href.trim() !== '' && !isEmptyText(labelValue)\n ? renderLink(href, labelValue)\n : null,\n });\n break;\n }\n case 'taggedValue': {\n const tag = field.tag(node);\n const valueNode = resolveInlineValue(field.value(node), {\n tApp,\n t,\n resolveEntityHref,\n renderLink,\n });\n const resolvedTag =\n tag == null\n ? null\n : {\n ...tag,\n label: (() => {\n const labelValue = resolveValueLabel(tag.label, tApp);\n return labelValue == null ? '' : String(labelValue);\n })(),\n };\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value:\n resolvedTag != null || valueNode != null\n ? renderTaggedValue(resolvedTag, valueNode)\n : null,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'relation': {\n const value = resolveRelationValue(field.value(node));\n if (value == null) {\n break;\n }\n const listRoute = relationEntityListRoutes[field.relation.target];\n if (listRoute == null) {\n break;\n }\n const where = setWhereValue(\n null,\n field.relation.whereKey,\n value,\n field.relation.path,\n );\n if (where == null) {\n break;\n }\n relationItems.push(\n resolveRelationItem({\n id,\n label: resolveLabel(field.label, tApp),\n relation: field.relation,\n listRoute,\n value,\n where,\n }),\n );\n break;\n }\n case 'custom': {\n const custom = field.render(node) as ReactNode;\n if (custom == null) {\n break;\n }\n if (field.label != null) {\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: custom,\n fullWidth: field.fullWidth,\n });\n break;\n }\n customNodes.push(wrapCustomNode(id, custom));\n break;\n }\n default:\n break;\n }\n });\n\n return { items, relationItems, customNodes };\n};\n\nexport const resolveHeaderItems = <Node>(\n header: BackofficeDetailHeaderConfig<Node>,\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n renderDate: (\n value: string | number | null | undefined,\n fallback: string,\n ) => ReactNode;\n renderTag: (\n tone: ReturnType<typeof resolveBadgeTone<Node>>,\n label: string,\n ) => ReactNode;\n renderBadgeRow: (items: readonly BackofficeBadgeItem[]) => ReactNode;\n },\n): {\n title: string;\n subtitle?: ReactNode;\n badges?: ReactNode;\n status?: ReactNode;\n items?: readonly ResolvedHeaderItem[];\n} => {\n const {\n tApp,\n t,\n resolveEntityHref,\n renderLink,\n renderDate,\n renderTag,\n renderBadgeRow,\n } = options;\n const resolvedTitle =\n header.titleValue?.(node, tApp) ?? resolveLabel(header.title, tApp);\n const rawNodeId =\n node != null &&\n typeof node === 'object' &&\n 'id' in node &&\n typeof node.id === 'string'\n ? node.id.trim()\n : null;\n const title =\n resolvedTitle.trim() === '' ||\n (rawNodeId != null && resolvedTitle.trim() === rawNodeId)\n ? resolveLabel(header.title, tApp)\n : resolvedTitle;\n\n let subtitleNode: ReactNode | undefined;\n if (header.subtitleItems != null && header.subtitleItems.length > 0) {\n const { subtitleItems } = header;\n const separator = header.subtitleSeparator ?? ' / ';\n const parts: ReactNode[] = [];\n subtitleItems.forEach((item, index) => {\n parts.push(\n createElement(\n 'span',\n { key: item.id },\n resolveInlineValue(item.value(node), {\n tApp,\n t,\n resolveEntityHref,\n renderLink,\n }),\n ),\n );\n if (index < subtitleItems.length - 1) {\n parts.push(createElement('span', { key: `${item.id}-sep` }, separator));\n }\n });\n subtitleNode = createElement('span', null, ...parts);\n } else {\n const subtitleValue =\n header.subtitleValue?.(node, tApp) ??\n (header.subtitle != null ? resolveLabel(header.subtitle, tApp) : null);\n subtitleNode =\n subtitleValue != null && subtitleValue.trim() !== ''\n ? subtitleValue\n : undefined;\n }\n\n const badgeNodes: ReactNode[] = [];\n header.badges?.forEach((badge, index) => {\n const label = resolveLabel(badge.label, tApp);\n const resolvedValue = resolveValueLabel(badge.value(node), tApp);\n const value = resolvedValue == null ? '' : String(resolvedValue);\n if (value.trim() === '') {\n return;\n }\n badgeNodes.push(\n renderTag(resolveBadgeTone(badge.tone, node), `${label}: ${value}`),\n );\n if (typeof badgeNodes[badgeNodes.length - 1] === 'object') {\n badgeNodes[badgeNodes.length - 1] = createElement(\n Fragment,\n { key: `${label}-${index}` },\n badgeNodes[badgeNodes.length - 1],\n );\n }\n });\n\n const status =\n header.status != null\n ? resolveHeaderStatus(header.status, node, tApp, {\n renderBadgeRow,\n renderTag,\n })\n : undefined;\n\n const items = header.meta?.map((meta, index) => {\n const label = resolveLabel(meta.label, tApp);\n return {\n id: `${label}-${index}`,\n label,\n value: resolveHeaderMeta(meta, node, {\n tApp,\n t,\n resolveEntityHref,\n renderDate,\n renderLink,\n }),\n };\n });\n\n return {\n title,\n subtitle: subtitleNode,\n badges:\n badgeNodes.length > 0\n ? createElement(Fragment, null, ...badgeNodes)\n : undefined,\n status,\n items,\n };\n};\n\nconst renderTimelinePayload = (payload: unknown): ReactNode | undefined => {\n if (payload == null) {\n return undefined;\n }\n if (\n typeof payload === 'string' ||\n typeof payload === 'number' ||\n typeof payload === 'boolean'\n ) {\n return String(payload);\n }\n\n try {\n return createElement('pre', null, JSON.stringify(payload, null, 2));\n } catch {\n const fallback =\n payload instanceof Error ? payload.message : '[unserializable payload]';\n return createElement('pre', null, fallback);\n }\n};\n\nconst resolveTechnicalVariant = (\n refKind: 'id' | 'slug' | 'path' | 'url' | 'hash' | 'external' | 'text',\n): TechnicalIdentifierVariant | null => {\n if (refKind === 'id' || refKind === 'hash' || refKind === 'external') {\n return refKind;\n }\n return null;\n};\n\nconst renderReferenceValue = (args: {\n value: BackofficeValueLabel;\n href?: string | null;\n refKind: 'id' | 'slug' | 'path' | 'url' | 'hash' | 'external' | 'text';\n copyValue?: string | null;\n tApp: TFunction;\n t: TFunction;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n}): ReactNode => {\n const { value, href, refKind, copyValue, tApp, t, renderLink } = args;\n const resolvedValue = resolveValueLabel(value, tApp);\n const technicalVariant = resolveTechnicalVariant(refKind);\n if (technicalVariant != null) {\n const normalized = normalizeTechnicalIdentifier(resolvedValue);\n if (normalized == null) {\n return t('common.notAvailable');\n }\n return createElement(TechnicalIdentifierValue, {\n value: normalized,\n copyValue: copyValue ?? normalized,\n variant: technicalVariant,\n copyLabel: t('common.actions.copy'),\n });\n }\n if (href != null && href.trim() !== '' && !isEmptyText(resolvedValue)) {\n return renderLink(href, resolvedValue);\n }\n return resolvedValue ?? t('common.notAvailable');\n};\n\nexport const renderBlocks = <Node>(\n blocks: readonly BackofficeDetailBlockSpec<Node>[] | undefined,\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref: (entityId: string, refId: string) => string | null;\n keyPrefix?: string;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n renderDate: (\n value: string | number | Date | null | undefined,\n fallback: string,\n ) => ReactNode;\n renderTag: (tone: BackofficeTone, label: string) => ReactNode;\n renderMetricGroup: (args: {\n key: string;\n title: string;\n description?: string;\n density?: 'compact' | 'comfortable';\n items: readonly {\n id: string;\n label: string;\n value: ReactNode;\n hint?: ReactNode;\n tone?: BackofficeTone;\n copyValue?: string;\n }[];\n }) => ReactNode;\n renderTimeline: (args: {\n key: string;\n title: string;\n description?: string;\n events: readonly {\n id: string;\n label: string;\n timestamp?: ReactNode;\n description?: ReactNode;\n actor?: ReactNode;\n tone?: BackofficeTone;\n payload?: ReactNode;\n }[];\n }) => ReactNode;\n renderAuditTimeline: (args: {\n key: string;\n title: string;\n description?: string;\n events: readonly {\n id: string;\n title: ReactNode;\n time?: ReactNode;\n actor?: ReactNode;\n source?: ReactNode;\n }[];\n }) => ReactNode;\n renderRelations: (args: {\n key: string;\n title: string;\n description?: string;\n items: readonly {\n id: string;\n label: string;\n count?: ReactNode;\n href?: string;\n description?: ReactNode;\n tone?: BackofficeTone;\n }[];\n }) => ReactNode;\n renderContextStack: (args: {\n key: string;\n title: string;\n items: readonly {\n id: string;\n label: string;\n value: ReactNode | null | undefined;\n }[];\n }) => ReactNode;\n renderCustomSection: (\n key: string,\n title: string,\n child: ReactNode,\n ) => ReactNode;\n wrapCustomNode: (key: string, node: ReactNode) => ReactNode;\n resolveTableColumns: (columns: readonly unknown[]) => unknown;\n renderTable: (args: {\n key: string;\n title: string;\n description?: string;\n columns: unknown;\n rows: readonly unknown[];\n }) => ReactNode;\n renderPayload: (args: {\n key: string;\n title: string;\n description?: string;\n content: unknown;\n format?: string;\n }) => ReactNode;\n renderKeyValueListSection: (args: {\n key: string;\n title: string;\n description?: string;\n items: readonly { id: string; label: string; value: ReactNode }[];\n }) => ReactNode;\n },\n): ReactNode[] => {\n const { tApp, t, keyPrefix } = options;\n if (blocks == null || blocks.length === 0) {\n return [];\n }\n\n return blocks.map((block, index): ReactNode => {\n const key =\n keyPrefix != null\n ? `${keyPrefix}-${block.kind}-${index}`\n : `${block.kind}-${index}`;\n\n if (block.kind === 'custom') {\n const custom = block.render(node) as ReactNode;\n if (custom == null) {\n return null;\n }\n if (block.label != null) {\n return options.renderCustomSection(\n key,\n resolveLabel(block.label, tApp),\n custom,\n );\n }\n return options.wrapCustomNode(key, custom);\n }\n\n const title =\n 'title' in block\n ? resolveLabel(block.title, tApp)\n : resolveLabel(block.label, tApp);\n const description =\n block.description != null\n ? resolveLabel(block.description, tApp)\n : undefined;\n\n if (block.kind === 'summary') {\n return options.renderKeyValueListSection({\n key,\n title,\n description,\n items: block.items.map((item) => {\n const value = resolveValueLabel(item.value(node), tApp);\n const href = item.href?.(node);\n const tone = item.tone?.(node);\n let valueNode: ReactNode = value ?? t('common.notAvailable');\n if (href != null && href.trim() !== '' && !isEmptyText(value)) {\n valueNode = options.renderLink(href, value);\n } else if (tone != null && !isEmptyText(value)) {\n valueNode = options.renderTag(tone, String(value));\n }\n return {\n id: item.id,\n label: resolveLabel(item.label, tApp),\n value: valueNode,\n };\n }),\n });\n }\n\n if (block.kind === 'metrics') {\n return options.renderMetricGroup({\n key,\n title,\n description,\n density: block.density,\n items: block.items.map((item) => {\n const formattedValue = item.formattedValue?.(node);\n const value = resolveValueLabel(item.value(node), tApp);\n return {\n id: item.id,\n label: resolveLabel(item.label, tApp),\n value: formattedValue ?? value ?? t('common.notAvailable'),\n hint: resolveValueLabel(item.hint?.(node), tApp),\n tone: item.tone?.(node),\n copyValue: item.copyValue?.(node) ?? undefined,\n };\n }),\n });\n }\n\n if (block.kind === 'states') {\n return options.renderKeyValueListSection({\n key,\n title,\n description,\n items: block.states.map((state) => {\n const display = state.getDisplay(state.value(node), node);\n return {\n id: state.id,\n label: resolveLabel(state.label, tApp),\n value: options.renderTag(\n display.tone,\n String(\n resolveValueLabel(display.label, tApp) ??\n t('common.notAvailable'),\n ),\n ),\n };\n }),\n });\n }\n\n if (block.kind === 'context') {\n return options.renderContextStack({\n key,\n title,\n items: block.items.map((item) => {\n const value = resolveValueLabel(item.value(node), tApp);\n const href = item.href?.(node);\n return {\n id: item.id,\n label: resolveLabel(item.label, tApp),\n value:\n href != null && href.trim() !== '' && !isEmptyText(value)\n ? options.renderLink(href, value)\n : value,\n };\n }),\n });\n }\n\n if (block.kind === 'relations') {\n return options.renderRelations({\n key,\n title,\n description,\n items: block.items.map((item) => {\n return {\n id: item.id,\n label: resolveLabel(item.label, tApp),\n count: item.count?.(node) ?? null,\n href: item.href?.(node) ?? undefined,\n description: resolveValueLabel(item.description?.(node), tApp),\n tone: item.tone?.(node),\n };\n }),\n });\n }\n\n if (block.kind === 'timeline') {\n return options.renderTimeline({\n key,\n title,\n description,\n events: block.events.map((event) => {\n const state = event.state?.(node);\n const stateLabel =\n state == null ? null : resolveValueLabel(state.label, tApp);\n const stateText = stateLabel == null ? null : String(stateLabel);\n return {\n id: event.id,\n label:\n stateText == null || stateText.trim() === ''\n ? resolveLabel(event.label, tApp)\n : `${resolveLabel(event.label, tApp)}: ${stateText}`,\n timestamp:\n event.timestamp == null\n ? undefined\n : options.renderDate(\n event.timestamp(node),\n t('common.notAvailable'),\n ),\n description: resolveValueLabel(event.description?.(node), tApp),\n actor: resolveValueLabel(event.actor?.(node), tApp),\n tone: state?.tone,\n payload: renderTimelinePayload(event.payload?.(node)),\n };\n }),\n });\n }\n\n if (block.kind === 'audit') {\n return options.renderAuditTimeline({\n key,\n title,\n description,\n events: block.items.map((item) => {\n const actor = resolveValueLabel(item.actor?.(node), tApp);\n const source = resolveValueLabel(item.source?.(node), tApp);\n return {\n id: item.id,\n title: resolveLabel(item.label, tApp),\n time: options.renderDate(\n item.timestamp?.(node),\n t('common.notAvailable'),\n ),\n actor: isEmptyText(actor) ? undefined : actor,\n source: isEmptyText(source) ? undefined : source,\n };\n }),\n });\n }\n\n if (block.kind === 'references') {\n return options.renderKeyValueListSection({\n key,\n title,\n description,\n items: block.references.map((reference) => {\n const href = reference.href?.(node);\n return {\n id: reference.id,\n label: resolveLabel(reference.label, tApp),\n value: renderReferenceValue({\n value: reference.value(node),\n href,\n refKind: reference.refKind ?? 'text',\n copyValue: reference.copyValue?.(node) ?? undefined,\n tApp,\n t,\n renderLink: options.renderLink,\n }),\n };\n }),\n });\n }\n\n if (block.kind === 'actionResult') {\n const items: { id: string; label: string; value: ReactNode }[] = [];\n const status = block.status?.(node);\n if (status != null) {\n items.push({\n id: `${block.id}-status`,\n label: t('detail.actionResult.status'),\n value: options.renderTag(\n status.tone,\n String(\n resolveValueLabel(status.label, tApp) ?? t('common.notAvailable'),\n ),\n ),\n });\n }\n const message = resolveValueLabel(block.message?.(node), tApp);\n if (!isEmptyText(message)) {\n items.push({\n id: `${block.id}-message`,\n label: t('detail.actionResult.message'),\n value: message,\n });\n }\n block.references?.forEach((reference) => {\n items.push({\n id: reference.id,\n label: resolveLabel(reference.label, tApp),\n value: renderReferenceValue({\n value: reference.value(node),\n href: reference.href?.(node),\n refKind: reference.refKind ?? 'text',\n copyValue: reference.copyValue?.(node) ?? undefined,\n tApp,\n t,\n renderLink: options.renderLink,\n }),\n });\n });\n return options.renderKeyValueListSection({\n key,\n title,\n description,\n items,\n });\n }\n\n if (block.kind === 'technicalFacts') {\n return options.renderKeyValueListSection({\n key,\n title,\n description,\n items: block.facts.map((fact) => {\n const value = resolveValueLabel(fact.value(node), tApp);\n const href = fact.href?.(node);\n const copyValue = fact.copyValue?.(node) ?? undefined;\n return {\n id: fact.id,\n label: resolveLabel(fact.label, tApp),\n value:\n copyValue != null && copyValue.trim() !== ''\n ? createElement(TechnicalIdentifierValue, {\n value: value ?? copyValue,\n copyValue,\n variant: 'external',\n copyLabel: t('common.actions.copy'),\n })\n : href != null && href.trim() !== '' && !isEmptyText(value)\n ? options.renderLink(href, value)\n : (value ?? t('common.notAvailable')),\n };\n }),\n });\n }\n\n if (block.kind === 'table') {\n return options.renderTable({\n key,\n title,\n description,\n columns: options.resolveTableColumns(\n block.columns as readonly unknown[],\n ),\n rows: block.rows(node) as readonly unknown[],\n });\n }\n\n return options.renderPayload({\n key,\n title,\n description,\n content: block.value(node),\n format: block.format,\n });\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"BackofficeEntityDetailPage.view-helpers.js","names":[],"sources":["../../../src/pages/BackofficeEntityDetailPage.view-helpers.ts"],"sourcesContent":["/* eslint-disable no-ternary */\nimport type {\n BackofficeBadgeItem,\n BackofficeColumnSpec,\n BackofficeDetailBlockSpec,\n BackofficeDetailFieldSpec,\n BackofficeDetailHeaderConfig,\n BackofficeDetailHeaderMetaSpec,\n BackofficeDetailHeaderStatusSpec,\n BackofficeFieldSize,\n BackofficeFlagVariant,\n BackofficeInlineValueSpec,\n BackofficePayloadFormat,\n BackofficeRuntimeRelationFilterSpec,\n BackofficeTone,\n BackofficeValueLabel,\n} from '@plumile/backoffice-core/types.js';\nimport type { DataTableColumn } from '@plumile/ui/components/data-table/DataTable.js';\nimport type { TFunction } from 'i18next';\nimport { Fragment, createElement, type ReactNode } from 'react';\n\nimport {\n isEmptyText,\n resolveLabel,\n resolveBadgeTone,\n resolveRelationValue,\n resolveValueLabel,\n} from './BackofficeEntityDetailPage.helpers.js';\nimport {\n normalizeTechnicalIdentifier,\n TechnicalIdentifierValue,\n type TechnicalIdentifierVariant,\n} from '../components/backoffice/technical/TechnicalIdentifierValue.js';\n\nexport type ResolvedFieldItem = {\n id: string;\n label: string;\n size: BackofficeFieldSize;\n value: ReactNode;\n copyValue?: string;\n fullWidth?: boolean;\n};\n\nexport type ResolvedHeaderItem = {\n id: string;\n label: string;\n value: ReactNode;\n};\n\nexport type FlagIconName =\n | 'shield-lock'\n | 'shield-off'\n | 'settings-check'\n | 'settings-x'\n | 'x-badge'\n | 'chat-check'\n | 'key'\n | 'key-off'\n | 'lock'\n | 'lock-open'\n | 'robot-check'\n | 'robot-x'\n | 'rocket'\n | 'rocket-off';\n\nexport type ResolvedFlagTag = {\n tone: 'neutral' | 'info' | 'success' | 'warning' | 'danger';\n label: string;\n iconName?: FlagIconName;\n};\n\nexport const resolveFlagTag = (\n variant: BackofficeFlagVariant,\n value: boolean,\n t: TFunction,\n): ResolvedFlagTag => {\n switch (variant) {\n case 'yesNo':\n return value\n ? { tone: 'success', label: t('common.boolean.yes') }\n : { tone: 'neutral', label: t('common.boolean.no') };\n case 'capability':\n return value\n ? {\n tone: 'success',\n label: t('flags.capability.allowed'),\n iconName: 'shield-lock',\n }\n : {\n tone: 'neutral',\n label: t('flags.capability.denied'),\n iconName: 'shield-off',\n };\n case 'enabled':\n return value\n ? {\n tone: 'success',\n label: t('flags.enabled.enabled'),\n iconName: 'settings-check',\n }\n : {\n tone: 'neutral',\n label: t('flags.enabled.disabled'),\n iconName: 'settings-x',\n };\n case 'failure':\n return value\n ? {\n tone: 'danger',\n label: t('flags.failure.failed'),\n iconName: 'x-badge',\n }\n : {\n tone: 'success',\n label: t('flags.failure.ok'),\n iconName: 'chat-check',\n };\n case 'encrypted':\n return value\n ? {\n tone: 'info',\n label: t('flags.encrypted.encrypted'),\n iconName: 'key',\n }\n : {\n tone: 'neutral',\n label: t('flags.encrypted.notEncrypted'),\n iconName: 'key-off',\n };\n case 'locked':\n return value\n ? {\n tone: 'warning',\n label: t('flags.locked.locked'),\n iconName: 'lock',\n }\n : {\n tone: 'success',\n label: t('flags.locked.unlocked'),\n iconName: 'lock-open',\n };\n case 'default':\n return value\n ? { tone: 'info', label: t('flags.default.default') }\n : { tone: 'neutral', label: t('flags.default.notDefault') };\n case 'agentManaged':\n return value\n ? {\n tone: 'info',\n label: t('flags.agentManaged.agentManaged'),\n iconName: 'robot-check',\n }\n : {\n tone: 'neutral',\n label: t('flags.agentManaged.userManaged'),\n iconName: 'robot-x',\n };\n case 'deployedProduction':\n return value\n ? {\n tone: 'success',\n label: t('flags.deployedProduction.deployed'),\n iconName: 'rocket',\n }\n : {\n tone: 'neutral',\n label: t('flags.deployedProduction.notDeployed'),\n iconName: 'rocket-off',\n };\n case 'forced':\n return value\n ? { tone: 'warning', label: t('flags.forced.forced') }\n : { tone: 'neutral', label: t('flags.forced.normal') };\n default:\n throw new Error(`Unsupported flag variant: ${String(variant)}`);\n }\n};\n\nexport const resolveInlineValue = (\n value: BackofficeInlineValueSpec,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n },\n): ReactNode => {\n const { tApp, t, resolveEntityHref, renderLink } = options;\n const fallback = t('common.notAvailable');\n\n if (value.type === 'text') {\n const resolved = resolveValueLabel(value.value, tApp);\n return isEmptyText(resolved) ? fallback : resolved;\n }\n\n if (value.type === 'entityRef') {\n const { id } = value;\n if (id == null || id.trim() === '') {\n return fallback;\n }\n const resolvedLabel = resolveValueLabel(value.label, tApp);\n const label =\n resolvedLabel != null && String(resolvedLabel).trim() !== ''\n ? resolvedLabel\n : null;\n if (label == null) {\n return fallback;\n }\n const href = resolveEntityHref?.(value.entity, id) ?? null;\n return href != null ? renderLink(href, label) : label;\n }\n\n const { href } = value;\n if (href == null || href.trim() === '') {\n return fallback;\n }\n const label = resolveValueLabel(value.label, tApp);\n if (isEmptyText(label)) {\n return fallback;\n }\n return renderLink(href, label);\n};\n\nexport const resolveHeaderMeta = <Node>(\n meta: BackofficeDetailHeaderMetaSpec<Node>,\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n renderDate: (\n value: string | number | null | undefined,\n fallback: string,\n ) => ReactNode;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n },\n): ReactNode => {\n const { tApp, t, resolveEntityHref, renderDate, renderLink } = options;\n const fallback = t('common.notAvailable');\n\n if (meta.type === 'dateTime') {\n return renderDate(meta.value(node), fallback);\n }\n\n if (meta.type === 'entityRef') {\n const idValue = meta.id(node);\n if (idValue == null || idValue.trim() === '') {\n return fallback;\n }\n const labelValue = resolveValueLabel(meta.value?.(node), tApp);\n const label =\n labelValue != null && String(labelValue).trim() !== ''\n ? labelValue\n : null;\n if (label == null) {\n return fallback;\n }\n const href = resolveEntityHref?.(meta.entity, idValue) ?? null;\n return href != null ? renderLink(href, label) : label;\n }\n\n if (meta.type === 'link') {\n const href = meta.href(node);\n const labelValue = resolveValueLabel(meta.value(node), tApp);\n if (href == null || href.trim() === '' || isEmptyText(labelValue)) {\n return fallback;\n }\n return renderLink(href, labelValue);\n }\n\n const value = resolveValueLabel(meta.value(node), tApp);\n return isEmptyText(value) ? fallback : value;\n};\n\nexport const resolveHeaderStatus = <Node>(\n status: BackofficeDetailHeaderStatusSpec<Node>,\n node: Node,\n tApp: TFunction,\n renderers: {\n renderBadgeRow: (items: readonly BackofficeBadgeItem[]) => ReactNode;\n renderTag: (\n tone: ReturnType<typeof resolveBadgeTone<Node>>,\n label: string,\n ) => ReactNode;\n },\n): ReactNode | undefined => {\n if (status.type === 'badgeRow') {\n const items = status.items(node).map((item) => {\n const resolvedLabel = resolveValueLabel(item.label, tApp);\n const label = resolvedLabel == null ? '' : String(resolvedLabel);\n return { ...item, label };\n });\n if (items.length === 0) {\n return undefined;\n }\n return renderers.renderBadgeRow(items);\n }\n\n const value = resolveValueLabel(status.value(node), tApp);\n const label = value == null ? '' : String(value);\n if (label.trim() === '') {\n return undefined;\n }\n const tone = resolveBadgeTone(status.tone, node);\n return renderers.renderTag(tone, label);\n};\n\nexport const buildFieldItems = <Node, RelationItem>(\n fields: readonly BackofficeDetailFieldSpec<Node>[],\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n formatNumber: (value: number | null | undefined) => string;\n formatCurrency: (value: number | null | undefined) => string;\n formatCurrencyTitle?: (value: number | null | undefined) => string | null;\n formatPercent: (value: number | null | undefined) => string;\n relationEntityListRoutes: Record<string, string>;\n resolveRelationItem: (args: {\n id: string;\n label: string;\n relation: BackofficeRuntimeRelationFilterSpec;\n listRoute: string;\n value: string;\n where: Record<string, unknown>;\n }) => RelationItem;\n setWhereValue: (\n where: Record<string, unknown> | null,\n whereKey: string,\n value: string,\n path?: readonly string[],\n ) => Record<string, unknown> | null;\n renderTag: (\n tone: ReturnType<typeof resolveBadgeTone<Node>>,\n label: string,\n ) => ReactNode;\n renderBadgeRow: (items: readonly BackofficeBadgeItem[]) => ReactNode;\n renderDate: (\n value: string | number | null | undefined,\n fallback: string,\n ) => ReactNode;\n renderFlagTag: (tag: ResolvedFlagTag) => ReactNode;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n renderTaggedValue: (\n tag: {\n label: string;\n tone?: ReturnType<typeof resolveBadgeTone<Node>>;\n } | null,\n value: ReactNode,\n ) => ReactNode;\n wrapCustomNode: (id: string, node: ReactNode) => ReactNode;\n },\n): {\n items: ResolvedFieldItem[];\n relationItems: RelationItem[];\n customNodes: ReactNode[];\n} => {\n const {\n tApp,\n t,\n resolveEntityHref,\n formatNumber,\n formatCurrency,\n formatCurrencyTitle,\n formatPercent,\n relationEntityListRoutes,\n resolveRelationItem,\n setWhereValue,\n renderTag,\n renderBadgeRow,\n renderDate,\n renderFlagTag,\n renderLink,\n renderTaggedValue,\n wrapCustomNode,\n } = options;\n const items: ResolvedFieldItem[] = [];\n const relationItems: RelationItem[] = [];\n const customNodes: ReactNode[] = [];\n const fallback = t('common.notAvailable');\n\n fields.forEach((field, index) => {\n const id = `${field.type}-${index}`;\n\n switch (field.type) {\n case 'text': {\n const value = resolveValueLabel(field.value(node), tApp);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value,\n copyValue: field.copyValue?.(node) ?? undefined,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'badge': {\n const value = resolveValueLabel(field.value(node), tApp);\n const label = value != null ? String(value) : '';\n const tone = resolveBadgeTone(field.tone, node);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: label.trim() !== '' ? renderTag(tone, label) : null,\n });\n break;\n }\n case 'badgeRow': {\n const badgeItems = field.items(node).map((item) => {\n const resolvedLabel = resolveValueLabel(item.label, tApp);\n const label = resolvedLabel == null ? '' : String(resolvedLabel);\n return { ...item, label };\n });\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: badgeItems.length > 0 ? renderBadgeRow(badgeItems) : null,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'dateTime': {\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: renderDate(field.value(node), fallback),\n });\n break;\n }\n case 'number': {\n const value = field.value(node);\n let formatted: ReactNode | null = null;\n if (value != null) {\n if (field.format === 'currency') {\n const label = formatCurrency(value);\n formatted = createElement(\n 'span',\n { title: formatCurrencyTitle?.(value) ?? undefined },\n label,\n );\n } else if (field.format === 'percent') {\n formatted = formatPercent(value);\n } else {\n formatted = formatNumber(value);\n }\n }\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: formatted,\n });\n break;\n }\n case 'flag': {\n const value = field.value(node);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value:\n value != null\n ? renderFlagTag(resolveFlagTag(field.variant, value, t))\n : null,\n });\n break;\n }\n case 'entityRef': {\n const idValue = field.id(node);\n let value: ReactNode | null = null;\n if (idValue != null && idValue.trim() !== '') {\n const labelValue = field.value?.(node);\n const label =\n labelValue != null && labelValue.trim() !== '' ? labelValue : null;\n const href = resolveEntityHref?.(field.entity, idValue) ?? null;\n if (label != null) {\n value = href != null ? renderLink(href, label) : label;\n }\n }\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: value ?? fallback,\n });\n break;\n }\n case 'technicalIdentifier': {\n const value = field.value(node);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value:\n value == null\n ? null\n : createElement(TechnicalIdentifierValue, {\n value,\n copyValue: field.copyValue?.(node) ?? undefined,\n variant: field.variant,\n copyLabel: t('common.actions.copy'),\n }),\n copyValue: field.copyValue?.(node) ?? undefined,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'link': {\n const href = field.href(node);\n const labelValue = field.value(node);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value:\n href != null && href.trim() !== '' && !isEmptyText(labelValue)\n ? renderLink(href, labelValue)\n : null,\n });\n break;\n }\n case 'taggedValue': {\n const tag = field.tag(node);\n const valueNode = resolveInlineValue(field.value(node), {\n tApp,\n t,\n resolveEntityHref,\n renderLink,\n });\n const resolvedTag =\n tag == null\n ? null\n : {\n ...tag,\n label: (() => {\n const labelValue = resolveValueLabel(tag.label, tApp);\n return labelValue == null ? '' : String(labelValue);\n })(),\n };\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value:\n resolvedTag != null || valueNode != null\n ? renderTaggedValue(resolvedTag, valueNode)\n : null,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'relation': {\n const value = resolveRelationValue(field.value(node));\n if (value == null) {\n break;\n }\n const listRoute = relationEntityListRoutes[field.relation.target];\n if (listRoute == null) {\n break;\n }\n const where = setWhereValue(\n null,\n field.relation.whereKey,\n value,\n field.relation.path,\n );\n if (where == null) {\n break;\n }\n relationItems.push(\n resolveRelationItem({\n id,\n label: resolveLabel(field.label, tApp),\n relation: field.relation,\n listRoute,\n value,\n where,\n }),\n );\n break;\n }\n case 'custom': {\n const custom = field.render(node) as ReactNode;\n if (custom == null) {\n break;\n }\n if (field.label != null) {\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: custom,\n fullWidth: field.fullWidth,\n });\n break;\n }\n customNodes.push(wrapCustomNode(id, custom));\n break;\n }\n default:\n break;\n }\n });\n\n return { items, relationItems, customNodes };\n};\n\nexport const resolveHeaderItems = <Node>(\n header: BackofficeDetailHeaderConfig<Node>,\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n renderDate: (\n value: string | number | null | undefined,\n fallback: string,\n ) => ReactNode;\n renderTag: (\n tone: ReturnType<typeof resolveBadgeTone<Node>>,\n label: string,\n ) => ReactNode;\n renderBadgeRow: (items: readonly BackofficeBadgeItem[]) => ReactNode;\n },\n): {\n title: string;\n subtitle?: ReactNode;\n badges?: ReactNode;\n status?: ReactNode;\n items?: readonly ResolvedHeaderItem[];\n} => {\n const {\n tApp,\n t,\n resolveEntityHref,\n renderLink,\n renderDate,\n renderTag,\n renderBadgeRow,\n } = options;\n const resolvedTitle =\n header.titleValue?.(node, tApp) ?? resolveLabel(header.title, tApp);\n const rawNodeId =\n node != null &&\n typeof node === 'object' &&\n 'id' in node &&\n typeof node.id === 'string'\n ? node.id.trim()\n : null;\n const title =\n resolvedTitle.trim() === '' ||\n (rawNodeId != null && resolvedTitle.trim() === rawNodeId)\n ? resolveLabel(header.title, tApp)\n : resolvedTitle;\n\n let subtitleNode: ReactNode | undefined;\n if (header.subtitleItems != null && header.subtitleItems.length > 0) {\n const { subtitleItems } = header;\n const separator = header.subtitleSeparator ?? ' / ';\n const parts: ReactNode[] = [];\n subtitleItems.forEach((item, index) => {\n parts.push(\n createElement(\n 'span',\n { key: item.id },\n resolveInlineValue(item.value(node), {\n tApp,\n t,\n resolveEntityHref,\n renderLink,\n }),\n ),\n );\n if (index < subtitleItems.length - 1) {\n parts.push(createElement('span', { key: `${item.id}-sep` }, separator));\n }\n });\n subtitleNode = createElement('span', null, ...parts);\n } else {\n const subtitleValue =\n header.subtitleValue?.(node, tApp) ??\n (header.subtitle != null ? resolveLabel(header.subtitle, tApp) : null);\n subtitleNode =\n subtitleValue != null && subtitleValue.trim() !== ''\n ? subtitleValue\n : undefined;\n }\n\n const badgeNodes: ReactNode[] = [];\n header.badges?.forEach((badge, index) => {\n const label = resolveLabel(badge.label, tApp);\n const resolvedValue = resolveValueLabel(badge.value(node), tApp);\n const value = resolvedValue == null ? '' : String(resolvedValue);\n if (value.trim() === '') {\n return;\n }\n badgeNodes.push(\n renderTag(resolveBadgeTone(badge.tone, node), `${label}: ${value}`),\n );\n if (typeof badgeNodes[badgeNodes.length - 1] === 'object') {\n badgeNodes[badgeNodes.length - 1] = createElement(\n Fragment,\n { key: `${label}-${index}` },\n badgeNodes[badgeNodes.length - 1],\n );\n }\n });\n\n const status =\n header.status != null\n ? resolveHeaderStatus(header.status, node, tApp, {\n renderBadgeRow,\n renderTag,\n })\n : undefined;\n\n const items = header.meta?.map((meta, index) => {\n const label = resolveLabel(meta.label, tApp);\n return {\n id: `${label}-${index}`,\n label,\n value: resolveHeaderMeta(meta, node, {\n tApp,\n t,\n resolveEntityHref,\n renderDate,\n renderLink,\n }),\n };\n });\n\n return {\n title,\n subtitle: subtitleNode,\n badges:\n badgeNodes.length > 0\n ? createElement(Fragment, null, ...badgeNodes)\n : undefined,\n status,\n items,\n };\n};\n\nconst renderTimelinePayload = (payload: unknown): ReactNode | undefined => {\n if (payload == null) {\n return undefined;\n }\n if (\n typeof payload === 'string' ||\n typeof payload === 'number' ||\n typeof payload === 'boolean'\n ) {\n return String(payload);\n }\n\n try {\n return createElement('pre', null, JSON.stringify(payload, null, 2));\n } catch {\n const fallback =\n payload instanceof Error ? payload.message : '[unserializable payload]';\n return createElement('pre', null, fallback);\n }\n};\n\nconst resolveTechnicalVariant = (\n refKind: 'id' | 'slug' | 'path' | 'url' | 'hash' | 'external' | 'text',\n): TechnicalIdentifierVariant | null => {\n if (refKind === 'id' || refKind === 'hash' || refKind === 'external') {\n return refKind;\n }\n return null;\n};\n\nconst renderReferenceValue = (args: {\n value: BackofficeValueLabel;\n href?: string | null;\n refKind: 'id' | 'slug' | 'path' | 'url' | 'hash' | 'external' | 'text';\n copyValue?: string | null;\n tApp: TFunction;\n t: TFunction;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n}): ReactNode => {\n const { value, href, refKind, copyValue, tApp, t, renderLink } = args;\n const resolvedValue = resolveValueLabel(value, tApp);\n const technicalVariant = resolveTechnicalVariant(refKind);\n if (technicalVariant != null) {\n const normalized = normalizeTechnicalIdentifier(resolvedValue);\n if (normalized == null) {\n return t('common.notAvailable');\n }\n return createElement(TechnicalIdentifierValue, {\n value: normalized,\n copyValue: copyValue ?? normalized,\n variant: technicalVariant,\n copyLabel: t('common.actions.copy'),\n });\n }\n if (href != null && href.trim() !== '' && !isEmptyText(resolvedValue)) {\n return renderLink(href, resolvedValue);\n }\n return resolvedValue ?? t('common.notAvailable');\n};\n\nexport const renderBlocks = <Node>(\n blocks: readonly BackofficeDetailBlockSpec<Node>[] | undefined,\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref: (entityId: string, refId: string) => string | null;\n keyPrefix?: string;\n renderLink: (href: string, label: ReactNode) => ReactNode;\n renderDate: (\n value: string | number | Date | null | undefined,\n fallback: string,\n ) => ReactNode;\n renderTag: (tone: BackofficeTone, label: string) => ReactNode;\n renderMetricGroup: (args: {\n key: string;\n title: string;\n description?: string;\n density?: 'compact' | 'comfortable';\n items: readonly {\n id: string;\n label: string;\n value: ReactNode;\n hint?: ReactNode;\n tone?: BackofficeTone;\n copyValue?: string;\n }[];\n }) => ReactNode;\n renderTimeline: (args: {\n key: string;\n title: string;\n description?: string;\n events: readonly {\n id: string;\n label: string;\n timestamp?: ReactNode;\n description?: ReactNode;\n actor?: ReactNode;\n tone?: BackofficeTone;\n payload?: ReactNode;\n }[];\n }) => ReactNode;\n renderAuditTimeline: (args: {\n key: string;\n title: string;\n description?: string;\n events: readonly {\n id: string;\n title: ReactNode;\n time?: ReactNode;\n actor?: ReactNode;\n source?: ReactNode;\n }[];\n }) => ReactNode;\n renderRelations: (args: {\n key: string;\n title: string;\n description?: string;\n items: readonly {\n id: string;\n label: string;\n count?: ReactNode;\n href?: string;\n description?: ReactNode;\n tone?: BackofficeTone;\n }[];\n }) => ReactNode;\n renderContextStack: (args: {\n key: string;\n title: string;\n items: readonly {\n id: string;\n label: string;\n value: ReactNode | null | undefined;\n }[];\n }) => ReactNode;\n renderCustomSection: (\n key: string,\n title: string,\n child: ReactNode,\n ) => ReactNode;\n wrapCustomNode: (key: string, node: ReactNode) => ReactNode;\n resolveTableColumns: (\n columns: readonly BackofficeColumnSpec[],\n ) => readonly DataTableColumn<unknown>[];\n renderTable: (args: {\n key: string;\n title: string;\n description?: string;\n columns: readonly DataTableColumn<unknown>[];\n rows: readonly unknown[];\n }) => ReactNode;\n renderPayload: (args: {\n key: string;\n title: string;\n description?: string;\n content: unknown;\n format: BackofficePayloadFormat;\n }) => ReactNode;\n renderKeyValueListSection: (args: {\n key: string;\n title: string;\n description?: string;\n items: readonly { id: string; label: string; value: ReactNode }[];\n }) => ReactNode;\n },\n): ReactNode[] => {\n const { tApp, t, keyPrefix } = options;\n if (blocks == null || blocks.length === 0) {\n return [];\n }\n\n return blocks.map((block, index): ReactNode => {\n const key =\n keyPrefix != null\n ? `${keyPrefix}-${block.kind}-${index}`\n : `${block.kind}-${index}`;\n\n if (block.kind === 'custom') {\n const custom = block.render(node) as ReactNode;\n if (custom == null) {\n return null;\n }\n if (block.label != null) {\n return options.renderCustomSection(\n key,\n resolveLabel(block.label, tApp),\n custom,\n );\n }\n return options.wrapCustomNode(key, custom);\n }\n\n const title =\n 'title' in block\n ? resolveLabel(block.title, tApp)\n : resolveLabel(block.label, tApp);\n const description =\n block.description != null\n ? resolveLabel(block.description, tApp)\n : undefined;\n\n if (block.kind === 'summary') {\n return options.renderKeyValueListSection({\n key,\n title,\n description,\n items: block.items.map((item) => {\n const value = resolveValueLabel(item.value(node), tApp);\n const href = item.href?.(node);\n const tone = item.tone?.(node);\n let valueNode: ReactNode = value ?? t('common.notAvailable');\n if (href != null && href.trim() !== '' && !isEmptyText(value)) {\n valueNode = options.renderLink(href, value);\n } else if (tone != null && !isEmptyText(value)) {\n valueNode = options.renderTag(tone, String(value));\n }\n return {\n id: item.id,\n label: resolveLabel(item.label, tApp),\n value: valueNode,\n };\n }),\n });\n }\n\n if (block.kind === 'metrics') {\n return options.renderMetricGroup({\n key,\n title,\n description,\n density: block.density,\n items: block.items.map((item) => {\n const formattedValue = item.formattedValue?.(node);\n const value = resolveValueLabel(item.value(node), tApp);\n return {\n id: item.id,\n label: resolveLabel(item.label, tApp),\n value: formattedValue ?? value ?? t('common.notAvailable'),\n hint: resolveValueLabel(item.hint?.(node), tApp),\n tone: item.tone?.(node),\n copyValue: item.copyValue?.(node) ?? undefined,\n };\n }),\n });\n }\n\n if (block.kind === 'states') {\n return options.renderKeyValueListSection({\n key,\n title,\n description,\n items: block.states.map((state) => {\n const display = state.getDisplay(state.value(node), node);\n return {\n id: state.id,\n label: resolveLabel(state.label, tApp),\n value: options.renderTag(\n display.tone,\n String(\n resolveValueLabel(display.label, tApp) ??\n t('common.notAvailable'),\n ),\n ),\n };\n }),\n });\n }\n\n if (block.kind === 'context') {\n return options.renderContextStack({\n key,\n title,\n items: block.items.map((item) => {\n const value = resolveValueLabel(item.value(node), tApp);\n const href = item.href?.(node);\n return {\n id: item.id,\n label: resolveLabel(item.label, tApp),\n value:\n href != null && href.trim() !== '' && !isEmptyText(value)\n ? options.renderLink(href, value)\n : value,\n };\n }),\n });\n }\n\n if (block.kind === 'relations') {\n return options.renderRelations({\n key,\n title,\n description,\n items: block.items.map((item) => {\n return {\n id: item.id,\n label: resolveLabel(item.label, tApp),\n count: item.count?.(node) ?? null,\n href: item.href?.(node) ?? undefined,\n description: resolveValueLabel(item.description?.(node), tApp),\n tone: item.tone?.(node),\n };\n }),\n });\n }\n\n if (block.kind === 'timeline') {\n return options.renderTimeline({\n key,\n title,\n description,\n events: block.events.map((event) => {\n const state = event.state?.(node);\n const stateLabel =\n state == null ? null : resolveValueLabel(state.label, tApp);\n const stateText = stateLabel == null ? null : String(stateLabel);\n return {\n id: event.id,\n label:\n stateText == null || stateText.trim() === ''\n ? resolveLabel(event.label, tApp)\n : `${resolveLabel(event.label, tApp)}: ${stateText}`,\n timestamp:\n event.timestamp == null\n ? undefined\n : options.renderDate(\n event.timestamp(node),\n t('common.notAvailable'),\n ),\n description: resolveValueLabel(event.description?.(node), tApp),\n actor: resolveValueLabel(event.actor?.(node), tApp),\n tone: state?.tone,\n payload: renderTimelinePayload(event.payload?.(node)),\n };\n }),\n });\n }\n\n if (block.kind === 'audit') {\n return options.renderAuditTimeline({\n key,\n title,\n description,\n events: block.items.map((item) => {\n const actor = resolveValueLabel(item.actor?.(node), tApp);\n const source = resolveValueLabel(item.source?.(node), tApp);\n return {\n id: item.id,\n title: resolveLabel(item.label, tApp),\n time: options.renderDate(\n item.timestamp?.(node),\n t('common.notAvailable'),\n ),\n actor: isEmptyText(actor) ? undefined : actor,\n source: isEmptyText(source) ? undefined : source,\n };\n }),\n });\n }\n\n if (block.kind === 'references') {\n return options.renderKeyValueListSection({\n key,\n title,\n description,\n items: block.references.map((reference) => {\n const href = reference.href?.(node);\n return {\n id: reference.id,\n label: resolveLabel(reference.label, tApp),\n value: renderReferenceValue({\n value: reference.value(node),\n href,\n refKind: reference.refKind ?? 'text',\n copyValue: reference.copyValue?.(node) ?? undefined,\n tApp,\n t,\n renderLink: options.renderLink,\n }),\n };\n }),\n });\n }\n\n if (block.kind === 'actionResult') {\n const items: { id: string; label: string; value: ReactNode }[] = [];\n const status = block.status?.(node);\n if (status != null) {\n items.push({\n id: `${block.id}-status`,\n label: t('detail.actionResult.status'),\n value: options.renderTag(\n status.tone,\n String(\n resolveValueLabel(status.label, tApp) ?? t('common.notAvailable'),\n ),\n ),\n });\n }\n const message = resolveValueLabel(block.message?.(node), tApp);\n if (!isEmptyText(message)) {\n items.push({\n id: `${block.id}-message`,\n label: t('detail.actionResult.message'),\n value: message,\n });\n }\n block.references?.forEach((reference) => {\n items.push({\n id: reference.id,\n label: resolveLabel(reference.label, tApp),\n value: renderReferenceValue({\n value: reference.value(node),\n href: reference.href?.(node),\n refKind: reference.refKind ?? 'text',\n copyValue: reference.copyValue?.(node) ?? undefined,\n tApp,\n t,\n renderLink: options.renderLink,\n }),\n });\n });\n return options.renderKeyValueListSection({\n key,\n title,\n description,\n items,\n });\n }\n\n if (block.kind === 'technicalFacts') {\n return options.renderKeyValueListSection({\n key,\n title,\n description,\n items: block.facts.map((fact) => {\n const value = resolveValueLabel(fact.value(node), tApp);\n const href = fact.href?.(node);\n const copyValue = fact.copyValue?.(node) ?? undefined;\n return {\n id: fact.id,\n label: resolveLabel(fact.label, tApp),\n value:\n copyValue != null && copyValue.trim() !== ''\n ? createElement(TechnicalIdentifierValue, {\n value: value ?? copyValue,\n copyValue,\n variant: 'external',\n copyLabel: t('common.actions.copy'),\n })\n : href != null && href.trim() !== '' && !isEmptyText(value)\n ? options.renderLink(href, value)\n : (value ?? t('common.notAvailable')),\n };\n }),\n });\n }\n\n if (block.kind === 'table') {\n return options.renderTable({\n key,\n title,\n description,\n columns: options.resolveTableColumns(block.columns),\n rows: block.rows(node) as readonly unknown[],\n });\n }\n\n return options.renderPayload({\n key,\n title,\n description,\n content: block.value(node),\n format: block.format ?? 'json',\n });\n });\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeEntityDetailUnknownPageRedirect.js","names":[],"sources":["../../../src/pages/BackofficeEntityDetailUnknownPageRedirect.tsx"],"sourcesContent":["import { type JSX } from 'react';\n\nimport type {\n BackofficeEntityManifestItem,\n BackofficeResolvedDetailLayoutFacetConfig,\n} from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeRedirect } from './BackofficeRedirect.js';\nimport { useBackofficeEntityDetailLayoutContext } from './detail/BackofficeEntityDetailLayoutContext.js';\nimport { resolveVisibleDetailPages } from './detail/pageResolution.js';\n\nexport type BackofficeEntityDetailUnknownPageRedirectProps = {\n entityManifest: BackofficeEntityManifestItem;\n config: BackofficeResolvedDetailLayoutFacetConfig;\n prepared: {\n id: string;\n pagePath: string;\n };\n};\n\nexport const BackofficeEntityDetailUnknownPageRedirect = ({\n config,\n prepared,\n}: BackofficeEntityDetailUnknownPageRedirectProps): JSX.Element => {\n const { layoutView } = useBackofficeEntityDetailLayoutContext();\n\n const resolvedPages = resolveVisibleDetailPages({\n mainPage: config.pages.mainPage,\n subPages: config.pages.subPages,\n activePagePath: prepared.pagePath,\n node: layoutView as never,\n });\n\n if (!resolvedPages.hasVisiblePages || resolvedPages.activePage == null) {\n return <BackofficeRedirect to={config.routes.list} />;\n }\n\n return (\n <BackofficeRedirect\n to={config.routes.detailPage(prepared.id, resolvedPages.activePage.id)}\n />\n );\n};\n\nexport default BackofficeEntityDetailUnknownPageRedirect;\n"],"mappings":";;;;;AAoBA,IAAa,KAA6C,EACxD,WACA,kBACiE;CACjE,IAAM,EAAE,kBAAe,EAAuC,GAExD,IAAgB,EAA0B;EAC9C,UAAU,EAAO,MAAM;EACvB,UAAU,EAAO,MAAM;EACvB,gBAAgB,EAAS;EACzB,MAAM;CACR,CAAC;CAMD,OAJI,CAAC,EAAc,mBAAmB,EAAc,cAAc,OACzD,kBAAC,GAAD,EAAoB,IAAI,EAAO,OAAO,KAAO,CAAA,IAIpD,kBAAC,GAAD,EACE,IAAI,EAAO,OAAO,WAAW,EAAS,IAAI,EAAc,WAAW,EAAE,EACtE,CAAA;AAEL"}
1
+ {"version":3,"file":"BackofficeEntityDetailUnknownPageRedirect.js","names":[],"sources":["../../../src/pages/BackofficeEntityDetailUnknownPageRedirect.tsx"],"sourcesContent":["import { type JSX } from 'react';\n\nimport type {\n BackofficeEntityManifestItem,\n BackofficeResolvedDetailLayoutFacetConfig,\n} from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeRedirect } from './BackofficeRedirect.js';\nimport { useBackofficeEntityDetailLayoutContext } from './detail/BackofficeEntityDetailLayoutContext.js';\nimport { resolveVisibleDetailPages } from './detail/pageResolution.js';\n\nexport type BackofficeEntityDetailUnknownPageRedirectProps = {\n entityManifest: BackofficeEntityManifestItem;\n config: BackofficeResolvedDetailLayoutFacetConfig;\n prepared: {\n id: string;\n pagePath: string;\n };\n};\n\nexport const BackofficeEntityDetailUnknownPageRedirect = ({\n config,\n prepared,\n}: BackofficeEntityDetailUnknownPageRedirectProps): JSX.Element => {\n const { layoutView } = useBackofficeEntityDetailLayoutContext();\n\n const resolvedPages = resolveVisibleDetailPages({\n mainPage: config.pages.mainPage,\n subPages: config.pages.subPages,\n activePagePath: prepared.pagePath,\n node: layoutView,\n });\n\n if (!resolvedPages.hasVisiblePages || resolvedPages.activePage == null) {\n return <BackofficeRedirect to={config.routes.list} />;\n }\n\n return (\n <BackofficeRedirect\n to={config.routes.detailPage(prepared.id, resolvedPages.activePage.id)}\n />\n );\n};\n\nexport default BackofficeEntityDetailUnknownPageRedirect;\n"],"mappings":";;;;;AAoBA,IAAa,KAA6C,EACxD,WACA,kBACiE;CACjE,IAAM,EAAE,kBAAe,EAAuC,GAExD,IAAgB,EAA0B;EAC9C,UAAU,EAAO,MAAM;EACvB,UAAU,EAAO,MAAM;EACvB,gBAAgB,EAAS;EACzB,MAAM;CACR,CAAC;CAMD,OAJI,CAAC,EAAc,mBAAmB,EAAc,cAAc,OACzD,kBAAC,GAAD,EAAoB,IAAI,EAAO,OAAO,KAAO,CAAA,IAIpD,kBAAC,GAAD,EACE,IAAI,EAAO,OAAO,WAAW,EAAS,IAAI,EAAc,WAAW,EAAE,EACtE,CAAA;AAEL"}