@plumile/backoffice-react 0.1.108 → 0.1.112
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/auth/AuthRefreshNotice.js +2 -2
- package/lib/esm/auth/AuthRefreshNotice.js.map +1 -1
- package/lib/esm/auth/authRefreshNotice.css.js +1 -0
- package/lib/esm/auth/authRefreshNotice.css.js.map +1 -1
- package/lib/esm/auth/login/EmailCapturePanel.js +12 -9
- package/lib/esm/auth/login/EmailCapturePanel.js.map +1 -1
- package/lib/esm/auth/login/LoginFlow.js +10 -10
- package/lib/esm/auth/login/LoginFlow.js.map +1 -1
- package/lib/esm/auth/login/MethodChooser.js +14 -12
- package/lib/esm/auth/login/MethodChooser.js.map +1 -1
- package/lib/esm/auth/login/MfaChallengeForm.js +13 -10
- package/lib/esm/auth/login/MfaChallengeForm.js.map +1 -1
- package/lib/esm/auth/login/OidcButtons.js +4 -4
- package/lib/esm/auth/login/OidcButtons.js.map +1 -1
- package/lib/esm/auth/login/PasskeyLoginForm.js +13 -10
- package/lib/esm/auth/login/PasskeyLoginForm.js.map +1 -1
- package/lib/esm/auth/login/PasswordLoginPanel.js +8 -8
- package/lib/esm/auth/login/PasswordLoginPanel.js.map +1 -1
- package/lib/esm/auth/login/loginPage.css.js.map +1 -1
- package/lib/esm/auth/pages/AcceptInvitationScreen.js +18 -14
- package/lib/esm/auth/pages/AcceptInvitationScreen.js.map +1 -1
- package/lib/esm/auth/pages/PasswordResetCompleteScreen.js +16 -12
- package/lib/esm/auth/pages/PasswordResetCompleteScreen.js.map +1 -1
- package/lib/esm/auth/pages/PasswordResetRequestScreen.js +15 -11
- package/lib/esm/auth/pages/PasswordResetRequestScreen.js.map +1 -1
- package/lib/esm/auth/pages/VerifyEmailScreen.js +13 -11
- package/lib/esm/auth/pages/VerifyEmailScreen.js.map +1 -1
- package/lib/esm/components/backoffice/actions/BackofficeEntityActionFormDialog.js +66 -54
- package/lib/esm/components/backoffice/actions/BackofficeEntityActionFormDialog.js.map +1 -1
- package/lib/esm/components/backoffice/actions/LazyBackofficeEntityActionFormDialog.js +8 -8
- package/lib/esm/components/backoffice/actions/LazyBackofficeEntityActionFormDialog.js.map +1 -1
- package/lib/esm/components/backoffice/actions/backofficeEntityActionFormDialog.css.js.map +1 -1
- package/lib/esm/components/backoffice/actions/toastViewAction.js.map +1 -1
- package/lib/esm/components/backoffice/columns/buildDataTableColumns.js +13 -12
- package/lib/esm/components/backoffice/columns/buildDataTableColumns.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeCopyButton.js +3 -3
- package/lib/esm/components/backoffice/detail/BackofficeCopyButton.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailBadgeRow.js +8 -8
- package/lib/esm/components/backoffice/detail/BackofficeDetailBadgeRow.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailErrorList.js +12 -11
- package/lib/esm/components/backoffice/detail/BackofficeDetailErrorList.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailField.js +8 -7
- package/lib/esm/components/backoffice/detail/BackofficeDetailField.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailFlagTag.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailFlagTag.js +6 -6
- package/lib/esm/components/backoffice/detail/BackofficeDetailFlagTag.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailHeader.js +3 -3
- package/lib/esm/components/backoffice/detail/BackofficeDetailHeader.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailPage.js +3 -3
- package/lib/esm/components/backoffice/detail/BackofficeDetailPage.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailPayload.js +4 -4
- package/lib/esm/components/backoffice/detail/BackofficeDetailPayload.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailRelationLink.js +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailRelationLink.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailRelationListBlock.js +30 -29
- package/lib/esm/components/backoffice/detail/BackofficeDetailRelationListBlock.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailTable.js +3 -3
- package/lib/esm/components/backoffice/detail/BackofficeDetailTable.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailTaggedValue.js +5 -5
- package/lib/esm/components/backoffice/detail/BackofficeDetailTaggedValue.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeEntitySummaryHeader.js +21 -19
- package/lib/esm/components/backoffice/detail/BackofficeEntitySummaryHeader.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeKpiStrip.js +9 -6
- package/lib/esm/components/backoffice/detail/BackofficeKpiStrip.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeLifecycleTimelineSection.js +7 -7
- package/lib/esm/components/backoffice/detail/BackofficeLifecycleTimelineSection.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficePayloadInspectorSection.js +8 -8
- package/lib/esm/components/backoffice/detail/BackofficePayloadInspectorSection.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeReferenceValue.js +5 -5
- package/lib/esm/components/backoffice/detail/BackofficeReferenceValue.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeRelationsSummaryGrid.js +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeRelationsSummaryGrid.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeStatusMetaBadge.js +4 -4
- package/lib/esm/components/backoffice/detail/BackofficeStatusMetaBadge.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeUsageCostBreakdown.js +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeUsageCostBreakdown.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeAuditMetadataPanel.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeDetailBadgeRow.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeDetailErrorList.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeDetailField.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeDetailLayout.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeDetailRelationLink.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeDetailRelationList.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeDetailSection.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeDetailTaggedValue.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeEntitySummaryHeader.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeKpiStrip.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeLifecycleTimelineSection.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficePayloadInspectorSection.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeReferenceValue.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeRelationsSummaryGrid.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeScopeStack.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeStatusMetaBadge.css.js.map +1 -1
- package/lib/esm/components/backoffice/detail/backofficeUsageCostBreakdown.css.js.map +1 -1
- package/lib/esm/components/backoffice/filters/BackofficeFilterAction.js +12 -12
- package/lib/esm/components/backoffice/filters/BackofficeFilterAction.js.map +1 -1
- package/lib/esm/components/backoffice/filters/DeferredFilterSearchInput.js +11 -9
- package/lib/esm/components/backoffice/filters/DeferredFilterSearchInput.js.map +1 -1
- package/lib/esm/components/backoffice/filters/EntityFilterValue.js +16 -8
- package/lib/esm/components/backoffice/filters/EntityFilterValue.js.map +1 -1
- package/lib/esm/components/backoffice/filters/EntityIdFilterField.js +86 -53
- package/lib/esm/components/backoffice/filters/EntityIdFilterField.js.map +1 -1
- package/lib/esm/components/backoffice/filters/backofficeFilterAction.css.js.map +1 -1
- package/lib/esm/components/backoffice/filters/deferredFilterSearchInput.css.js.map +1 -1
- package/lib/esm/components/backoffice/filters/entityIdFilterField.css.js +2 -2
- package/lib/esm/components/backoffice/filters/entityIdFilterField.css.js.map +1 -1
- package/lib/esm/components/backoffice/hub/BackofficeHubTemplate.js +25 -23
- package/lib/esm/components/backoffice/hub/BackofficeHubTemplate.js.map +1 -1
- package/lib/esm/components/backoffice/hub/backofficeHubTemplate.css.js.map +1 -1
- package/lib/esm/components/backoffice/layout/backofficeSidebarActions.css.js.map +1 -1
- package/lib/esm/components/backoffice/layout/breadcrumb/BackofficeTopbarBreadcrumb.js +14 -14
- package/lib/esm/components/backoffice/layout/breadcrumb/BackofficeTopbarBreadcrumb.js.map +1 -1
- package/lib/esm/components/backoffice/layout/breadcrumb/backofficeTopbarBreadcrumb.css.js.map +1 -1
- package/lib/esm/components/backoffice/layout/buildSidebarSections.js +42 -37
- package/lib/esm/components/backoffice/layout/buildSidebarSections.js.map +1 -1
- package/lib/esm/components/backoffice/layout/mapViewerToSidebarProfileView.js.map +1 -1
- package/lib/esm/components/backoffice/links/BackofficeInlineLink.js +1 -1
- package/lib/esm/components/backoffice/links/BackofficeInlineLink.js.map +1 -1
- package/lib/esm/components/backoffice/links/BackofficeLink.js +1 -1
- package/lib/esm/components/backoffice/links/BackofficeLink.js.map +1 -1
- package/lib/esm/components/backoffice/links/backofficeLink.css.js.map +1 -1
- package/lib/esm/components/backoffice/lists/BackofficeListToolbar.js +1 -1
- package/lib/esm/components/backoffice/lists/BackofficeListToolbar.js.map +1 -1
- package/lib/esm/components/backoffice/lists/backofficeListToolbar.css.js.map +1 -1
- package/lib/esm/components/backoffice/overview/BackofficeOverviewLayout.js +1 -1
- package/lib/esm/components/backoffice/overview/BackofficeOverviewLayout.js.map +1 -1
- package/lib/esm/components/backoffice/overview/backofficeOverviewLayout.css.js.map +1 -1
- package/lib/esm/components/backoffice/pickers/EntityIdPickerDialog.js +31 -27
- package/lib/esm/components/backoffice/pickers/EntityIdPickerDialog.js.map +1 -1
- package/lib/esm/components/backoffice/pickers/entityIdPickerDialog.css.js +2 -2
- package/lib/esm/components/backoffice/pickers/entityIdPickerDialog.css.js.map +1 -1
- package/lib/esm/components/backoffice/pickers/shared/EntityPickerList.js +26 -20
- package/lib/esm/components/backoffice/pickers/shared/EntityPickerList.js.map +1 -1
- package/lib/esm/components/backoffice/pickers/shared/EntityPickerShell.js +4 -4
- package/lib/esm/components/backoffice/pickers/shared/EntityPickerShell.js.map +1 -1
- package/lib/esm/components/backoffice/refs/BackofficeRelatedCountLink.js +1 -1
- package/lib/esm/components/backoffice/refs/BackofficeRelatedCountLink.js.map +1 -1
- package/lib/esm/components/backoffice/refs/backofficeEntityIdRef.css.js.map +1 -1
- package/lib/esm/components/backoffice/refs/backofficeRelatedCountLink.css.js.map +1 -1
- package/lib/esm/components/backoffice/routing/BackofficeContentError.js +6 -5
- package/lib/esm/components/backoffice/routing/BackofficeContentError.js.map +1 -1
- package/lib/esm/components/backoffice/routing/BackofficeContentFallback.js +10 -10
- package/lib/esm/components/backoffice/routing/BackofficeContentFallback.js.map +1 -1
- package/lib/esm/components/backoffice/routing/BackofficeRouteFallback.js +10 -10
- package/lib/esm/components/backoffice/routing/BackofficeRouteFallback.js.map +1 -1
- package/lib/esm/components/backoffice/routing/backofficeContentBoundary.css.js.map +1 -1
- package/lib/esm/components/backoffice/routing/backofficeContentError.css.js.map +1 -1
- package/lib/esm/components/backoffice/routing/backofficeContentFallback.css.js.map +1 -1
- package/lib/esm/components/backoffice/routing/backofficeRouteFallback.css.js.map +1 -1
- package/lib/esm/components/backoffice/routing/backofficeRoutePendingBar.css.js.map +1 -1
- package/lib/esm/components/backoffice/scaffolds/BackofficeEntityDetailScaffold.js +3 -3
- package/lib/esm/components/backoffice/scaffolds/BackofficeEntityDetailScaffold.js.map +1 -1
- package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js +198 -181
- package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js.map +1 -1
- package/lib/esm/components/backoffice/scaffolds/BackofficeTabbedDetailShell.js +6 -5
- package/lib/esm/components/backoffice/scaffolds/BackofficeTabbedDetailShell.js.map +1 -1
- package/lib/esm/components/backoffice/scaffolds/backofficeEntityListScaffold.css.js.map +1 -1
- package/lib/esm/components/backoffice/scaffolds/backofficeTabbedDetailShell.css.js.map +1 -1
- package/lib/esm/components/backoffice/shared/BackofficeFilterableCell.js +10 -9
- package/lib/esm/components/backoffice/shared/BackofficeFilterableCell.js.map +1 -1
- package/lib/esm/components/backoffice/shared/BackofficeInlineFilterRow.js +1 -1
- package/lib/esm/components/backoffice/shared/BackofficeInlineFilterRow.js.map +1 -1
- package/lib/esm/components/backoffice/shared/backofficeFilterableCell.css.js.map +1 -1
- package/lib/esm/components/backoffice/shared/backofficeInlineFilterRow.css.js.map +1 -1
- package/lib/esm/components/backoffice/tools/BackofficeToolsDocPanel.js +11 -9
- package/lib/esm/components/backoffice/tools/BackofficeToolsDocPanel.js.map +1 -1
- package/lib/esm/components/backoffice/tools/BackofficeToolsErrorFallback.js +7 -7
- package/lib/esm/components/backoffice/tools/BackofficeToolsErrorFallback.js.map +1 -1
- package/lib/esm/components/backoffice/tools/BackofficeToolsJsonForm.js +17 -12
- package/lib/esm/components/backoffice/tools/BackofficeToolsJsonForm.js.map +1 -1
- package/lib/esm/components/backoffice/tools/BackofficeToolsQueryBoundary.js +10 -10
- package/lib/esm/components/backoffice/tools/BackofficeToolsQueryBoundary.js.map +1 -1
- package/lib/esm/components/backoffice/tools/backofficeToolsDocPanel.css.js.map +1 -1
- package/lib/esm/components/backoffice/tools/backofficeToolsForm.css.js.map +1 -1
- package/lib/esm/components/backoffice/tools/backofficeToolsJsonForm.css.js.map +1 -1
- package/lib/esm/hooks/useBackofficeListUrlState.js +2 -1
- package/lib/esm/hooks/useBackofficeListUrlState.js.map +1 -1
- package/lib/esm/pages/BackofficeAcceptInvitationPage.js +1 -1
- package/lib/esm/pages/BackofficeAcceptInvitationPage.js.map +1 -1
- package/lib/esm/pages/BackofficeDashboardPage.js +72 -68
- package/lib/esm/pages/BackofficeDashboardPage.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityDetailLayoutPage.js +1 -1
- package/lib/esm/pages/BackofficeEntityDetailLayoutPage.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityDetailPage.js +207 -184
- package/lib/esm/pages/BackofficeEntityDetailPage.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityDetailUnknownPageRedirect.js +1 -1
- package/lib/esm/pages/BackofficeEntityDetailUnknownPageRedirect.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityListPage.helpers.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityListPage.js +143 -139
- package/lib/esm/pages/BackofficeEntityListPage.js.map +1 -1
- package/lib/esm/pages/BackofficeHubPage.js +10 -9
- package/lib/esm/pages/BackofficeHubPage.js.map +1 -1
- package/lib/esm/pages/BackofficeLayoutPage.js +44 -39
- package/lib/esm/pages/BackofficeLayoutPage.js.map +1 -1
- package/lib/esm/pages/BackofficeLoginPage.js +1 -1
- package/lib/esm/pages/BackofficeLoginPage.js.map +1 -1
- package/lib/esm/pages/BackofficePasswordResetCompletePage.js +1 -1
- package/lib/esm/pages/BackofficePasswordResetCompletePage.js.map +1 -1
- package/lib/esm/pages/BackofficeVerifyEmailPage.js +1 -1
- package/lib/esm/pages/BackofficeVerifyEmailPage.js.map +1 -1
- package/lib/esm/pages/backofficeDashboardPage.css.js.map +1 -1
- package/lib/esm/pages/backofficeEntityDetailPage.css.js.map +1 -1
- package/lib/esm/pages/backofficeEntityListPage.css.js.map +1 -1
- package/lib/esm/pages/dashboard/DashboardMetricGroup.js +10 -9
- package/lib/esm/pages/dashboard/DashboardMetricGroup.js.map +1 -1
- package/lib/esm/pages/dashboard/DashboardPanel.js +3 -3
- package/lib/esm/pages/dashboard/DashboardPanel.js.map +1 -1
- package/lib/esm/pages/dashboard/DashboardQuickActions.js +2 -2
- package/lib/esm/pages/dashboard/DashboardQuickActions.js.map +1 -1
- package/lib/esm/pages/dashboard/DashboardStatusList.js +1 -1
- package/lib/esm/pages/dashboard/DashboardStatusList.js.map +1 -1
- package/lib/esm/pages/dashboard/dashboardMetricGroup.css.js.map +1 -1
- package/lib/esm/pages/dashboard/dashboardPanel.css.js.map +1 -1
- package/lib/esm/pages/dashboard/dashboardQuickActions.css.js.map +1 -1
- package/lib/esm/pages/dashboard/dashboardStatusList.css.js.map +1 -1
- package/lib/esm/pages/detail/buildTabsItems.js.map +1 -1
- package/lib/esm/provider/BackofficeProvider.js +22 -20
- package/lib/esm/provider/BackofficeProvider.js.map +1 -1
- package/lib/esm/router/createBackofficeRoutes.js +33 -30
- package/lib/esm/router/createBackofficeRoutes.js.map +1 -1
- package/lib/esm/storybook/relay/RelayStory.css.js.map +1 -1
- package/lib/esm/style.css +1 -1
- package/lib/types/auth/AuthFlows.stories.d.ts +19 -0
- package/lib/types/auth/AuthFlows.stories.d.ts.map +1 -0
- package/lib/types/auth/AuthRefreshNotice.d.ts +1 -1
- package/lib/types/auth/AuthRefreshNotice.d.ts.map +1 -1
- package/lib/types/auth/authRefreshNotice.css.d.ts.map +1 -1
- package/lib/types/auth/login/EmailCapturePanel.d.ts.map +1 -1
- package/lib/types/auth/login/MethodChooser.d.ts.map +1 -1
- package/lib/types/auth/login/MfaChallengeForm.d.ts.map +1 -1
- package/lib/types/auth/login/PasskeyLoginForm.d.ts.map +1 -1
- package/lib/types/auth/login/PasswordLoginPanel.d.ts +1 -1
- package/lib/types/auth/login/PasswordLoginPanel.d.ts.map +1 -1
- package/lib/types/auth/login/loginPage.css.d.ts.map +1 -1
- package/lib/types/auth/pages/AcceptInvitationScreen.d.ts.map +1 -1
- package/lib/types/auth/pages/PasswordResetCompleteScreen.d.ts.map +1 -1
- package/lib/types/auth/pages/PasswordResetRequestScreen.d.ts.map +1 -1
- package/lib/types/auth/pages/VerifyEmailScreen.d.ts.map +1 -1
- package/lib/types/components/backoffice/actions/BackofficeEntityActionFormDialog.d.ts.map +1 -1
- package/lib/types/components/backoffice/actions/toastViewAction.d.ts +1 -1
- package/lib/types/components/backoffice/actions/toastViewAction.d.ts.map +1 -1
- package/lib/types/components/backoffice/columns/buildDataTableColumns.d.ts +1 -1
- package/lib/types/components/backoffice/columns/buildDataTableColumns.d.ts.map +1 -1
- package/lib/types/components/backoffice/detail/BackofficeCopyButton.d.ts +1 -1
- package/lib/types/components/backoffice/detail/BackofficeCopyButton.d.ts.map +1 -1
- package/lib/types/components/backoffice/detail/BackofficeDetailErrorList.d.ts.map +1 -1
- package/lib/types/components/backoffice/detail/BackofficeDetailField.d.ts.map +1 -1
- package/lib/types/components/backoffice/detail/BackofficeDetailFlagTag.d.ts +1 -1
- package/lib/types/components/backoffice/detail/BackofficeDetailFlagTag.d.ts.map +1 -1
- package/lib/types/components/backoffice/detail/BackofficeDetailPrimitives.stories.d.ts +17 -0
- package/lib/types/components/backoffice/detail/BackofficeDetailPrimitives.stories.d.ts.map +1 -0
- package/lib/types/components/backoffice/detail/BackofficeDetailRelationListBlock.d.ts.map +1 -1
- package/lib/types/components/backoffice/detail/BackofficeDetailTable.d.ts +1 -1
- package/lib/types/components/backoffice/detail/BackofficeDetailTable.d.ts.map +1 -1
- package/lib/types/components/backoffice/detail/BackofficeEntitySummaryHeader.d.ts.map +1 -1
- package/lib/types/components/backoffice/detail/BackofficeKpiStrip.d.ts.map +1 -1
- package/lib/types/components/backoffice/detail/backofficeDetailRelationLink.css.d.ts.map +1 -1
- package/lib/types/components/backoffice/filters/DeferredFilterSearchInput.d.ts.map +1 -1
- package/lib/types/components/backoffice/filters/EntityFilterValue.d.ts +5 -1
- package/lib/types/components/backoffice/filters/EntityFilterValue.d.ts.map +1 -1
- package/lib/types/components/backoffice/filters/EntityIdFilterField.d.ts +1 -0
- package/lib/types/components/backoffice/filters/EntityIdFilterField.d.ts.map +1 -1
- package/lib/types/components/backoffice/filters/backofficeFilterAction.css.d.ts.map +1 -1
- package/lib/types/components/backoffice/filters/entityIdFilterField.css.d.ts +5 -2
- package/lib/types/components/backoffice/filters/entityIdFilterField.css.d.ts.map +1 -1
- package/lib/types/components/backoffice/hub/BackofficeHubTemplate.d.ts.map +1 -1
- package/lib/types/components/backoffice/hub/BackofficeHubTemplate.stories.d.ts +48 -0
- package/lib/types/components/backoffice/hub/BackofficeHubTemplate.stories.d.ts.map +1 -0
- package/lib/types/components/backoffice/hub/backofficeHubTemplate.css.d.ts.map +1 -1
- package/lib/types/components/backoffice/layout/backofficeSidebarActions.css.d.ts.map +1 -1
- package/lib/types/components/backoffice/layout/breadcrumb/backofficeTopbarBreadcrumb.css.d.ts.map +1 -1
- package/lib/types/components/backoffice/layout/buildSidebarSections.d.ts +1 -1
- package/lib/types/components/backoffice/layout/buildSidebarSections.d.ts.map +1 -1
- package/lib/types/components/backoffice/layout/mapViewerToSidebarProfileView.d.ts +1 -1
- package/lib/types/components/backoffice/layout/mapViewerToSidebarProfileView.d.ts.map +1 -1
- package/lib/types/components/backoffice/lists/BackofficeListToolbar.stories.d.ts +13 -0
- package/lib/types/components/backoffice/lists/BackofficeListToolbar.stories.d.ts.map +1 -0
- package/lib/types/components/backoffice/overview/BackofficeOverviewLayout.stories.d.ts.map +1 -1
- package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.d.ts.map +1 -1
- package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.stories.d.ts +11 -0
- package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.stories.d.ts.map +1 -0
- package/lib/types/components/backoffice/pickers/entityIdPickerDialog.css.d.ts +2 -0
- package/lib/types/components/backoffice/pickers/entityIdPickerDialog.css.d.ts.map +1 -1
- package/lib/types/components/backoffice/pickers/shared/EntityPickerList.d.ts.map +1 -1
- package/lib/types/components/backoffice/refs/backofficeRelatedCountLink.css.d.ts.map +1 -1
- package/lib/types/components/backoffice/routing/BackofficeContentError.d.ts.map +1 -1
- package/lib/types/components/backoffice/routing/backofficeRoutePendingBar.css.d.ts.map +1 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeEntityListScaffold.d.ts +1 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeEntityListScaffold.d.ts.map +1 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.d.ts +1 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.d.ts.map +1 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.stories.d.ts.map +1 -1
- package/lib/types/components/backoffice/shared/BackofficeFilterableCell.d.ts.map +1 -1
- package/lib/types/components/backoffice/shared/backofficeFilterableCell.css.d.ts.map +1 -1
- package/lib/types/components/backoffice/tools/BackofficeTools.stories.d.ts +17 -0
- package/lib/types/components/backoffice/tools/BackofficeTools.stories.d.ts.map +1 -0
- package/lib/types/components/backoffice/tools/BackofficeToolsDocPanel.d.ts.map +1 -1
- package/lib/types/components/backoffice/tools/BackofficeToolsJsonForm.d.ts.map +1 -1
- package/lib/types/components/backoffice/tools/backofficeToolsDocPanel.css.d.ts.map +1 -1
- package/lib/types/hooks/useBackofficeListUrlState.d.ts.map +1 -1
- package/lib/types/pages/BackofficeEntityDetailPage.d.ts.map +1 -1
- package/lib/types/pages/BackofficeEntityListPage.helpers.d.ts +2 -1
- package/lib/types/pages/BackofficeEntityListPage.helpers.d.ts.map +1 -1
- package/lib/types/pages/BackofficeHubPage.d.ts.map +1 -1
- package/lib/types/pages/BackofficeLayoutPage.d.ts.map +1 -1
- package/lib/types/pages/backofficeEntityDetailPage.css.d.ts.map +1 -1
- package/lib/types/pages/dashboard/DashboardMetricGroup.d.ts.map +1 -1
- package/lib/types/pages/dashboard/dashboardMetricGroup.css.d.ts.map +1 -1
- package/lib/types/pages/dashboard/dashboardPanel.css.d.ts.map +1 -1
- package/lib/types/pages/dashboard/dashboardQuickActions.css.d.ts.map +1 -1
- package/lib/types/pages/dashboard/dashboardStatusList.css.d.ts.map +1 -1
- package/lib/types/pages/detail/buildTabsItems.d.ts +1 -1
- package/lib/types/pages/detail/buildTabsItems.d.ts.map +1 -1
- package/lib/types/provider/BackofficeProvider.d.ts.map +1 -1
- package/lib/types/provider/types.d.ts +2 -1
- package/lib/types/provider/types.d.ts.map +1 -1
- package/lib/types/router/createBackofficeRoutes.d.ts +2 -1
- package/lib/types/router/createBackofficeRoutes.d.ts.map +1 -1
- package/package.json +14 -10
|
@@ -6,12 +6,13 @@ import { useBackofficePermissions as i } from "../components/backoffice/layout/B
|
|
|
6
6
|
import { BackofficeRightPageLayout as a } from "../components/backoffice/layout/breadcrumb/BackofficeRightPageLayout.js";
|
|
7
7
|
import { buildHubBreadcrumb as o } from "../components/backoffice/layout/breadcrumb/buildBreadcrumbs.js";
|
|
8
8
|
import { useMemo as s, useState as c } from "react";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { jsx as l } from "react/jsx-runtime";
|
|
10
|
+
import { useTranslation as u } from "react-i18next";
|
|
11
|
+
import { DetailPageTemplate as d } from "@plumile/ui/backoffice/templates/detail_page_template/DetailPageTemplate.js";
|
|
12
|
+
import { SidebarTasksSvg as f } from "@plumile/ui/icons/SidebarTasksSvg.js";
|
|
12
13
|
//#region src/pages/BackofficeHubPage.tsx
|
|
13
14
|
var p = (e, t) => {
|
|
14
|
-
if (e != null) return /* @__PURE__ */
|
|
15
|
+
if (e != null) return /* @__PURE__ */ l(e, {
|
|
15
16
|
width: t,
|
|
16
17
|
height: t,
|
|
17
18
|
"aria-hidden": "true"
|
|
@@ -23,7 +24,7 @@ var p = (e, t) => {
|
|
|
23
24
|
id: t.id
|
|
24
25
|
}, r) !== !1;
|
|
25
26
|
}, h = ({ prepared: h }) => {
|
|
26
|
-
let { t: g } =
|
|
27
|
+
let { t: g } = u(), { t: _ } = e(), { entities: v, sidebar: y } = t(), b = i(), [x, S] = c(""), { hub: C } = h, w = n(C.title, g), T;
|
|
27
28
|
C.description != null && (T = n(C.description, g));
|
|
28
29
|
let E = o({
|
|
29
30
|
id: C.id,
|
|
@@ -93,20 +94,20 @@ var p = (e, t) => {
|
|
|
93
94
|
value: x,
|
|
94
95
|
onChange: S,
|
|
95
96
|
placeholder: k
|
|
96
|
-
}), /* @__PURE__ */
|
|
97
|
+
}), /* @__PURE__ */ l(a, {
|
|
97
98
|
breadcrumb: E,
|
|
98
|
-
children: /* @__PURE__ */ d
|
|
99
|
+
children: /* @__PURE__ */ l(d, {
|
|
99
100
|
header: {
|
|
100
101
|
title: w,
|
|
101
102
|
subtitle: N
|
|
102
103
|
},
|
|
103
|
-
children: /* @__PURE__ */
|
|
104
|
+
children: /* @__PURE__ */ l(r, {
|
|
104
105
|
groups: F,
|
|
105
106
|
search: I,
|
|
106
107
|
emptyState: {
|
|
107
108
|
title: j,
|
|
108
109
|
description: M,
|
|
109
|
-
icon: /* @__PURE__ */
|
|
110
|
+
icon: /* @__PURE__ */ l(f, {
|
|
110
111
|
width: 28,
|
|
111
112
|
height: 28,
|
|
112
113
|
"aria-hidden": "true"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeHubPage.js","names":[],"sources":["../../../src/pages/BackofficeHubPage.tsx"],"sourcesContent":["import { useMemo, useState, type JSX, type ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { DetailPageTemplate
|
|
1
|
+
{"version":3,"file":"BackofficeHubPage.js","names":[],"sources":["../../../src/pages/BackofficeHubPage.tsx"],"sourcesContent":["import { useMemo, useState, type JSX, type ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { DetailPageTemplate } from '@plumile/ui/backoffice/templates/detail_page_template/DetailPageTemplate.js';\nimport { SidebarTasksSvg } from '@plumile/ui/icons/SidebarTasksSvg.js';\nimport type { BackofficeEntityManifestMap } from '@plumile/backoffice-core/types.js';\n\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { BackofficeIconComponent } from '../provider/types.js';\nimport type { BackofficePreparedHubRoute } from '../router/createBackofficeRoutes.js';\nimport {\n BackofficeHubTemplate,\n type BackofficeHubTemplateGroup,\n type BackofficeHubTemplateSearch,\n} from '../components/backoffice/hub/BackofficeHubTemplate.js';\nimport { BackofficeRightPageLayout } from '../components/backoffice/layout/breadcrumb/BackofficeRightPageLayout.js';\nimport { buildHubBreadcrumb } from '../components/backoffice/layout/breadcrumb/buildBreadcrumbs.js';\nimport { useBackofficePermissions } from '../components/backoffice/layout/BackofficePermissionsContext.js';\nimport { resolveLabel } from '../components/backoffice/layout/sidebarUtils.js';\n\nexport type BackofficeHubPageProps = {\n prepared: BackofficePreparedHubRoute;\n};\n\ntype HubPageItemView = {\n id: string;\n kind: 'entity' | 'tool';\n label: string;\n href: string;\n icon: ReactNode;\n};\n\ntype HubPageGroupView = {\n id: string;\n title: string;\n description: string | null;\n icon: ReactNode | undefined;\n items: readonly HubPageItemView[];\n};\n\nconst renderIcon = (\n Icon: BackofficeIconComponent | undefined,\n size: number,\n): ReactNode | undefined => {\n if (Icon == null) {\n return undefined;\n }\n return <Icon width={size} height={size} aria-hidden=\"true\" />;\n};\n\nconst isItemVisible = (input: {\n entity: BackofficeEntityManifestMap[string] | null | undefined;\n kind: 'entity' | 'tool';\n permissions: unknown;\n sidebar: ReturnType<typeof useBackofficeConfig>['sidebar'];\n}): boolean => {\n const { entity, kind, permissions, sidebar } = input;\n if (entity == null) {\n return false;\n }\n if (kind === 'entity' && entity.kind !== 'tool' && !entity.hasList) {\n return false;\n }\n const isVisible = sidebar?.isItemVisible?.(\n {\n kind,\n id: entity.id,\n },\n permissions,\n );\n return isVisible !== false;\n};\n\nexport const BackofficeHubPage = ({\n prepared,\n}: BackofficeHubPageProps): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { entities, sidebar } = useBackofficeConfig();\n const permissions = useBackofficePermissions();\n const [search, setSearch] = useState('');\n const { hub } = prepared;\n const title = resolveLabel(hub.title, tApp);\n let description: string | undefined;\n if (hub.description != null) {\n description = resolveLabel(hub.description, tApp);\n }\n const breadcrumb = buildHubBreadcrumb({ id: hub.id, title });\n const normalizedSearch = search.trim().toLowerCase();\n const searchEnabled = hub.search?.enabled !== false;\n let searchPlaceholder = t('hub.search.placeholder');\n if (hub.search?.placeholder != null) {\n searchPlaceholder = resolveLabel(hub.search.placeholder, tApp);\n }\n\n const groups = useMemo<readonly HubPageGroupView[]>(() => {\n return hub.groups\n .map((group) => {\n const items = group.items\n .map((item): HubPageItemView | null => {\n const entity = entities[item.id];\n if (entity == null) {\n return null;\n }\n if (\n !isItemVisible({\n entity,\n kind: item.kind,\n permissions,\n sidebar,\n })\n ) {\n return null;\n }\n const entityConfig = entity;\n const label = resolveLabel(entityConfig.label, tApp);\n if (\n normalizedSearch !== '' &&\n !label.toLowerCase().includes(normalizedSearch)\n ) {\n return null;\n }\n return {\n id: item.id,\n kind: item.kind,\n label,\n href: entityConfig.routes.list,\n icon: renderIcon(item.icon, 20),\n };\n })\n .filter((item): item is HubPageItemView => {\n return item != null;\n });\n let groupDescription: string | null = null;\n if (group.description != null) {\n groupDescription = resolveLabel(group.description, tApp);\n }\n return {\n id: group.id,\n title: resolveLabel(group.title, tApp),\n description: groupDescription,\n icon: renderIcon(group.icon, 18),\n items,\n };\n })\n .filter((group) => {\n return group.items.length > 0;\n });\n }, [entities, hub.groups, normalizedSearch, permissions, sidebar, tApp]);\n\n let emptyTitle = t('hub.empty.title');\n if (hub.emptyState?.title != null) {\n emptyTitle = resolveLabel(hub.emptyState.title, tApp);\n }\n let emptyDescription = t('hub.empty.description');\n if (hub.emptyState?.description != null) {\n emptyDescription = resolveLabel(hub.emptyState.description, tApp);\n }\n let subtitle = t('hub.subtitle');\n if (description != null) {\n subtitle = description;\n }\n const hasMixedKinds = groups.some((group) => {\n const kinds = new Set(\n group.items.map((item) => {\n return item.kind;\n }),\n );\n return kinds.size > 1;\n });\n\n const templateGroups = useMemo<readonly BackofficeHubTemplateGroup[]>(() => {\n return groups.map((group) => {\n return {\n id: group.id,\n title: group.title,\n description: group.description,\n icon: group.icon,\n items: group.items.map((item) => {\n let metaLabel: string | null = null;\n if (hasMixedKinds) {\n metaLabel = t('hub.itemKinds.entity');\n if (item.kind === 'tool') {\n metaLabel = t('hub.itemKinds.tool');\n }\n }\n return {\n id: item.id,\n kind: item.kind,\n label: item.label,\n href: item.href,\n icon: item.icon,\n metaLabel,\n };\n }),\n };\n });\n }, [groups, hasMixedKinds, t]);\n\n let searchConfig: BackofficeHubTemplateSearch | undefined;\n if (searchEnabled) {\n searchConfig = {\n value: search,\n onChange: setSearch,\n placeholder: searchPlaceholder,\n };\n }\n\n return (\n <BackofficeRightPageLayout breadcrumb={breadcrumb}>\n <DetailPageTemplate\n header={{\n title,\n subtitle,\n }}\n >\n <BackofficeHubTemplate\n groups={templateGroups}\n search={searchConfig}\n emptyState={{\n title: emptyTitle,\n description: emptyDescription,\n icon: <SidebarTasksSvg width={28} height={28} aria-hidden=\"true\" />,\n }}\n />\n </DetailPageTemplate>\n </BackofficeRightPageLayout>\n );\n};\n\nexport default BackofficeHubPage;\n"],"mappings":"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"}
|
|
@@ -7,16 +7,21 @@ import { buildSidebarSections as a } from "../components/backoffice/layout/build
|
|
|
7
7
|
import ne from "../components/backoffice/layout/mapViewerToSidebarProfileView.js";
|
|
8
8
|
import { BackofficeContentBoundary as re } from "../components/backoffice/routing/BackofficeContentBoundary.js";
|
|
9
9
|
import { resetRelayStore as ie } from "../relay/environment.js";
|
|
10
|
-
import { useRelayEnvironment as
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import { getBackofficeLoginPath as
|
|
14
|
-
import { useCallback as
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import
|
|
10
|
+
import { useRelayEnvironment as o } from "../relay/useRelayEnvironment.js";
|
|
11
|
+
import ae from "../hooks/useBackofficeSidebarPins.js";
|
|
12
|
+
import oe from "../hooks/useSidebarGroupCollapse.js";
|
|
13
|
+
import { getBackofficeLoginPath as se } from "../router/backofficeAuthPaths.js";
|
|
14
|
+
import { useCallback as ce, useContext as le, useEffect as s, useMemo as c, useState as l } from "react";
|
|
15
|
+
import { jsx as u } from "react/jsx-runtime";
|
|
16
|
+
import { useTranslation as ue } from "react-i18next";
|
|
17
|
+
import { commitMutation as de, usePreloadedQuery as d } from "react-relay";
|
|
18
|
+
import { ToastProvider as f } from "@plumile/ui/atomic/molecules/toast/ToastProvider.js";
|
|
19
|
+
import fe from "@plumile/router/routing/RoutingContext.js";
|
|
20
|
+
import { GlobalSearchInput as pe } from "@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js";
|
|
21
|
+
import me from "@plumile/router/routing/useLocation.js";
|
|
22
|
+
import { AdminShellLayout as he } from "@plumile/ui/admin/templates/admin_shell_layout/AdminShellLayout.js";
|
|
23
|
+
import { EnvironmentBadge as p } from "@plumile/ui/backoffice/atoms/environment_badge/EnvironmentBadge.js";
|
|
24
|
+
import { BackofficeSidebarProfileMenu as m } from "@plumile/ui/backoffice/molecules/sidebar_profile_menu/BackofficeSidebarProfileMenu.js";
|
|
20
25
|
//#region src/pages/BackofficeLayoutPage.tsx
|
|
21
26
|
var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", ve = (e) => {
|
|
22
27
|
if (typeof window > "u") return [];
|
|
@@ -36,16 +41,16 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
36
41
|
if (!(typeof window > "u")) try {
|
|
37
42
|
window.localStorage.setItem(e, JSON.stringify(t));
|
|
38
43
|
} catch {}
|
|
39
|
-
}, g = ({ children:
|
|
40
|
-
let { t: y } =
|
|
44
|
+
}, g = ({ children: d, permissions: g, authStatus: _, activeGroupId: v }) => {
|
|
45
|
+
let { t: y } = ue(), { t: b } = e(), { pathname: x } = me(), S = le(fe), C = o(), { auth: w, basePath: T, entities: E, sidebar: D } = t(), [O, ye] = l(""), k = D?.preferences?.storageKey ?? _e, A = D?.preferences?.persistCollapsed === !0, [j, be] = l(() => {
|
|
41
46
|
if (!A || typeof window > "u") return !1;
|
|
42
47
|
try {
|
|
43
48
|
return window.localStorage.getItem(`${k}:collapsed`) === "true";
|
|
44
49
|
} catch {
|
|
45
50
|
return !1;
|
|
46
51
|
}
|
|
47
|
-
}), [M, N] =
|
|
48
|
-
|
|
52
|
+
}), [M, N] = l(!1), [P, xe] = l(null), F = D?.recentItems, I = F?.enabled === !0, L = F?.storageKey ?? ge, R = F?.maxItems ?? 8, [z, Se] = l(() => I ? ve(L) : []);
|
|
53
|
+
s(() => {
|
|
49
54
|
if (!(!A || typeof window > "u")) try {
|
|
50
55
|
window.localStorage.setItem(`${k}:collapsed`, String(j));
|
|
51
56
|
} catch {}
|
|
@@ -54,13 +59,13 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
54
59
|
A,
|
|
55
60
|
k
|
|
56
61
|
]);
|
|
57
|
-
let B =
|
|
62
|
+
let B = c(() => i(E, D), [E, D]), Ce = c(() => Object.keys(B), [B]), we = c(() => Object.fromEntries(Object.entries(B).map(([e, t]) => [e, t.behavior?.defaultCollapsed ?? !0])), [B]), Te = c(() => ee(B, E, D, g), [
|
|
58
63
|
E,
|
|
59
64
|
B,
|
|
60
65
|
g,
|
|
61
66
|
D
|
|
62
|
-
]), V =
|
|
63
|
-
|
|
67
|
+
]), V = c(() => r(x, E), [E, x]);
|
|
68
|
+
s(() => {
|
|
64
69
|
if (!I || V == null) return;
|
|
65
70
|
let e = E[V];
|
|
66
71
|
if (e == null || e.kind !== "tool" && !e.hasList) return;
|
|
@@ -85,19 +90,19 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
85
90
|
L,
|
|
86
91
|
y
|
|
87
92
|
]);
|
|
88
|
-
let { pins: H, toggle: U, reorder: W } =
|
|
93
|
+
let { pins: H, toggle: U, reorder: W } = ae({
|
|
89
94
|
enabled: D?.pinnedItems?.enabled === !0,
|
|
90
95
|
storageKey: D?.pinnedItems?.storageKey,
|
|
91
96
|
visibleEntityIds: Te
|
|
92
97
|
}), G;
|
|
93
98
|
D?.preferences?.storageKey != null && (G = `${D.preferences.storageKey}:groups`);
|
|
94
|
-
let { collapsedByGroupId: K, setCollapsed: q } =
|
|
99
|
+
let { collapsedByGroupId: K, setCollapsed: q } = oe({
|
|
95
100
|
groupIds: Ce,
|
|
96
101
|
activeGroupId: v,
|
|
97
102
|
defaultCollapsedByGroupId: we,
|
|
98
103
|
persist: D?.preferences?.persistGroups === !0,
|
|
99
104
|
storageKey: G
|
|
100
|
-
}), Ee =
|
|
105
|
+
}), Ee = c(() => a({
|
|
101
106
|
basePath: T,
|
|
102
107
|
pathname: x,
|
|
103
108
|
entities: E,
|
|
@@ -128,7 +133,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
128
133
|
b,
|
|
129
134
|
y,
|
|
130
135
|
U
|
|
131
|
-
]), De =
|
|
136
|
+
]), De = c(() => a({
|
|
132
137
|
basePath: T,
|
|
133
138
|
pathname: x,
|
|
134
139
|
entities: E,
|
|
@@ -159,12 +164,12 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
159
164
|
b,
|
|
160
165
|
y,
|
|
161
166
|
U
|
|
162
|
-
]), J =
|
|
167
|
+
]), J = c(() => import.meta.env?.DEV === !0 ? "dev" : "prod", []), Y = ce(() => {
|
|
163
168
|
M || (N(!0), (async () => {
|
|
164
169
|
try {
|
|
165
170
|
let e = await w.logout.load();
|
|
166
171
|
await new Promise((t, n) => {
|
|
167
|
-
|
|
172
|
+
de(C, {
|
|
168
173
|
mutation: e.logoutMutation,
|
|
169
174
|
variables: {},
|
|
170
175
|
onCompleted: () => {
|
|
@@ -174,7 +179,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
174
179
|
n(e);
|
|
175
180
|
}
|
|
176
181
|
});
|
|
177
|
-
}), localStorage.removeItem("auth_token"), localStorage.removeItem("remember_me"), ie(), S?.history.push({ pathname:
|
|
182
|
+
}), localStorage.removeItem("auth_token"), localStorage.removeItem("remember_me"), ie(), S?.history.push({ pathname: se(T) });
|
|
178
183
|
} finally {
|
|
179
184
|
N(!1);
|
|
180
185
|
}
|
|
@@ -185,10 +190,10 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
185
190
|
M,
|
|
186
191
|
C,
|
|
187
192
|
S
|
|
188
|
-
]), X = _?.me ?? null, Z =
|
|
193
|
+
]), X = _?.me ?? null, Z = c(() => ne({
|
|
189
194
|
viewer: X,
|
|
190
195
|
unknownUserLabel: b("sidebar.profile.unknownUser")
|
|
191
|
-
}), [b, X]), Oe = /* @__PURE__ */
|
|
196
|
+
}), [b, X]), Oe = /* @__PURE__ */ u(m, {
|
|
192
197
|
collapsed: !1,
|
|
193
198
|
viewer: Z,
|
|
194
199
|
labels: {
|
|
@@ -198,7 +203,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
198
203
|
},
|
|
199
204
|
onSignOut: Y,
|
|
200
205
|
isSigningOut: M
|
|
201
|
-
}), ke = /* @__PURE__ */
|
|
206
|
+
}), ke = /* @__PURE__ */ u(m, {
|
|
202
207
|
collapsed: !1,
|
|
203
208
|
viewer: Z,
|
|
204
209
|
labels: {
|
|
@@ -209,17 +214,17 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
209
214
|
onSignOut: Y,
|
|
210
215
|
isSigningOut: M
|
|
211
216
|
}), Q = null;
|
|
212
|
-
P != null && (Q = /* @__PURE__ */
|
|
213
|
-
let $ = /* @__PURE__ */
|
|
217
|
+
P != null && (Q = /* @__PURE__ */ u(re, { children: d }));
|
|
218
|
+
let $ = /* @__PURE__ */ u(pe, {
|
|
214
219
|
value: O,
|
|
215
220
|
onChange: ye,
|
|
216
221
|
placeholder: b("sidebar.search.placeholder"),
|
|
217
222
|
ariaLabel: b("sidebar.search.placeholder")
|
|
218
223
|
});
|
|
219
|
-
return /* @__PURE__ */
|
|
224
|
+
return /* @__PURE__ */ u(f, { children: /* @__PURE__ */ u(he, {
|
|
220
225
|
sidebar: {
|
|
221
226
|
sections: Ee,
|
|
222
|
-
header: /* @__PURE__ */ p
|
|
227
|
+
header: /* @__PURE__ */ u(p, { environment: J }),
|
|
223
228
|
search: $,
|
|
224
229
|
footer: Oe,
|
|
225
230
|
isCollapsed: j,
|
|
@@ -230,17 +235,17 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
230
235
|
},
|
|
231
236
|
mobileSidebar: {
|
|
232
237
|
sections: De,
|
|
233
|
-
header: /* @__PURE__ */ p
|
|
238
|
+
header: /* @__PURE__ */ u(p, { environment: J }),
|
|
234
239
|
search: $,
|
|
235
240
|
footer: ke,
|
|
236
241
|
isCollapsed: !1,
|
|
237
242
|
hideCollapseToggle: !0,
|
|
238
243
|
navigationAriaLabel: b("sidebar.navigationAriaLabel")
|
|
239
244
|
},
|
|
240
|
-
topbar: { breadcrumb: /* @__PURE__ */
|
|
241
|
-
children: /* @__PURE__ */
|
|
245
|
+
topbar: { breadcrumb: /* @__PURE__ */ u("div", { ref: xe }) },
|
|
246
|
+
children: /* @__PURE__ */ u(te, {
|
|
242
247
|
permissions: g,
|
|
243
|
-
children: /* @__PURE__ */
|
|
248
|
+
children: /* @__PURE__ */ u(n, {
|
|
244
249
|
value: {
|
|
245
250
|
target: P,
|
|
246
251
|
dashboardHref: T,
|
|
@@ -250,18 +255,18 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
250
255
|
})
|
|
251
256
|
})
|
|
252
257
|
}) });
|
|
253
|
-
}, _ = ({ children: e, permissionsQuery: t, prepared: n, authStatus: r, activeGroupId: i }) => /* @__PURE__ */
|
|
254
|
-
permissions:
|
|
258
|
+
}, _ = ({ children: e, permissionsQuery: t, prepared: n, authStatus: r, activeGroupId: i }) => /* @__PURE__ */ u(g, {
|
|
259
|
+
permissions: d(t, n),
|
|
255
260
|
authStatus: r,
|
|
256
261
|
activeGroupId: i,
|
|
257
262
|
children: e
|
|
258
|
-
}), v = ({ children: e, permissionsQuery: t, prepared: n, authStatus: r, activeGroupId: i }) => t != null && n != null ? /* @__PURE__ */
|
|
263
|
+
}), v = ({ children: e, permissionsQuery: t, prepared: n, authStatus: r, activeGroupId: i }) => t != null && n != null ? /* @__PURE__ */ u(_, {
|
|
259
264
|
permissionsQuery: t,
|
|
260
265
|
prepared: n,
|
|
261
266
|
authStatus: r,
|
|
262
267
|
activeGroupId: i,
|
|
263
268
|
children: e
|
|
264
|
-
}) : /* @__PURE__ */
|
|
269
|
+
}) : /* @__PURE__ */ u(g, {
|
|
265
270
|
permissions: null,
|
|
266
271
|
authStatus: r,
|
|
267
272
|
activeGroupId: i,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeLayoutPage.js","names":[],"sources":["../../../src/pages/BackofficeLayoutPage.tsx"],"sourcesContent":["import {\n useEffect,\n useMemo,\n type JSX,\n type ReactNode,\n useCallback,\n useContext,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n usePreloadedQuery,\n type PreloadedQuery,\n} from 'react-relay';\nimport type {\n GraphQLTaggedNode,\n MutationParameters,\n OperationType,\n} from 'relay-runtime';\nimport { RoutingContext, useLocation } from '@plumile/router';\n\nimport {\n AdminShellLayout,\n BackofficeSidebarProfileMenu,\n EnvironmentBadge,\n GlobalSearchInput,\n ToastProvider,\n} from '@plumile/ui';\n\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { LogoutResponse, LogoutVariables } from '../hooks/useAuth.js';\nimport { useBackofficeSidebarPins } from '../hooks/useBackofficeSidebarPins.js';\nimport { useSidebarGroupCollapse } from '../hooks/useSidebarGroupCollapse.js';\nimport { buildSidebarSections } from '../components/backoffice/layout/buildSidebarSections.js';\nimport { BackofficeContentBoundary } from '../components/backoffice/routing/BackofficeContentBoundary.js';\nimport {\n resolveActiveEntityId,\n resolveSidebarGroups,\n resolveVisibleEntityIds,\n} from '../components/backoffice/layout/sidebarUtils.js';\nimport { BackofficeTopbarPortalContextProvider } from '../components/backoffice/layout/breadcrumb/BackofficeTopbarPortalContext.js';\nimport { BackofficePermissionsProvider } from '../components/backoffice/layout/BackofficePermissionsContext.js';\nimport {\n mapViewerToSidebarProfileView,\n type BackofficeViewerIdentity,\n} from '../components/backoffice/layout/mapViewerToSidebarProfileView.js';\nimport { resetRelayStore } from '../relay/environment.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { getBackofficeLoginPath } from '../router/backofficeAuthPaths.js';\nimport type { BackofficeSidebarRecentItem } from '../provider/types.js';\n\nexport type BackofficeLayoutPageProps = {\n children: ReactNode;\n permissionsQuery?: GraphQLTaggedNode;\n prepared?: PreloadedQuery<OperationType> | null;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\ntype LayoutShellProps = {\n children: ReactNode;\n permissions: unknown;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst DEFAULT_RECENT_ITEMS_STORAGE_KEY = 'plumile:backoffice:recent-items';\nconst DEFAULT_SIDEBAR_PREFS_STORAGE_KEY = 'plumile:backoffice:sidebar';\n\nconst readRecentItems = (\n storageKey: string,\n): readonly BackofficeSidebarRecentItem[] => {\n if (typeof window === 'undefined') {\n return [];\n }\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (raw == null) {\n return [];\n }\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) {\n return [];\n }\n return parsed.filter((item): item is BackofficeSidebarRecentItem => {\n if (item == null || typeof item !== 'object') {\n return false;\n }\n const candidate = item as Partial<BackofficeSidebarRecentItem>;\n return (\n (candidate.kind === 'entity' || candidate.kind === 'tool') &&\n typeof candidate.id === 'string' &&\n typeof candidate.label === 'string' &&\n typeof candidate.href === 'string' &&\n typeof candidate.visitedAt === 'number'\n );\n });\n } catch {\n return [];\n }\n};\n\nconst writeRecentItems = (\n storageKey: string,\n items: readonly BackofficeSidebarRecentItem[],\n): void => {\n if (typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(storageKey, JSON.stringify(items));\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n};\n\nconst BackofficeLayoutShell = ({\n children,\n permissions,\n authStatus,\n activeGroupId,\n}: LayoutShellProps): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { pathname } = useLocation();\n const routing = useContext(RoutingContext);\n const relayEnvironment = useRelayEnvironment();\n const {\n auth: authConfig,\n basePath,\n entities,\n sidebar,\n } = useBackofficeConfig();\n const [sidebarQuery, setSidebarQuery] = useState('');\n const sidebarPreferencesStorageKey =\n sidebar?.preferences?.storageKey ?? DEFAULT_SIDEBAR_PREFS_STORAGE_KEY;\n const persistSidebarCollapsed =\n sidebar?.preferences?.persistCollapsed === true;\n const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return false;\n }\n try {\n return (\n window.localStorage.getItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n ) === 'true'\n );\n } catch {\n return false;\n }\n });\n const [isSigningOut, setIsSigningOut] = useState(false);\n const [topbarTarget, setTopbarTarget] = useState<HTMLDivElement | null>(null);\n const recentItemsConfig = sidebar?.recentItems;\n const recentItemsEnabled = recentItemsConfig?.enabled === true;\n const recentItemsStorageKey =\n recentItemsConfig?.storageKey ?? DEFAULT_RECENT_ITEMS_STORAGE_KEY;\n const recentItemsMaxItems = recentItemsConfig?.maxItems ?? 8;\n const [recentItems, setRecentItems] = useState<\n readonly BackofficeSidebarRecentItem[]\n >(() => {\n if (!recentItemsEnabled) {\n return [];\n }\n return readRecentItems(recentItemsStorageKey);\n });\n\n useEffect(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n String(isSidebarCollapsed),\n );\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n }, [\n isSidebarCollapsed,\n persistSidebarCollapsed,\n sidebarPreferencesStorageKey,\n ]);\n\n const groups = useMemo(() => {\n return resolveSidebarGroups(entities, sidebar);\n }, [entities, sidebar]);\n\n const groupIds = useMemo(() => {\n return Object.keys(groups);\n }, [groups]);\n\n const defaultCollapsedByGroupId = useMemo(() => {\n return Object.fromEntries(\n Object.entries(groups).map(([groupId, group]) => {\n return [groupId, group.behavior?.defaultCollapsed ?? true];\n }),\n );\n }, [groups]);\n\n const visibleEntityIds = useMemo(() => {\n return resolveVisibleEntityIds(groups, entities, sidebar, permissions);\n }, [entities, groups, permissions, sidebar]);\n\n const activeEntityId = useMemo(() => {\n return resolveActiveEntityId(pathname, entities);\n }, [entities, pathname]);\n\n useEffect(() => {\n if (!recentItemsEnabled || activeEntityId == null) {\n return;\n }\n const config = entities[activeEntityId];\n if (config == null) {\n return;\n }\n if (config.kind !== 'tool' && !config.hasList) {\n return;\n }\n const href = config.routes.list;\n let kind: BackofficeSidebarRecentItem['kind'] = 'entity';\n if (config.kind === 'tool') {\n kind = 'tool';\n }\n const item: BackofficeSidebarRecentItem = {\n kind,\n id: activeEntityId,\n label: config.label(tApp),\n href,\n visitedAt: Date.now(),\n };\n setRecentItems((prev) => {\n const next = [\n item,\n ...prev.filter((entry) => {\n return entry.id !== item.id || entry.kind !== item.kind;\n }),\n ].slice(0, recentItemsMaxItems);\n writeRecentItems(recentItemsStorageKey, next);\n return next;\n });\n }, [\n activeEntityId,\n entities,\n recentItemsEnabled,\n recentItemsMaxItems,\n recentItemsStorageKey,\n tApp,\n ]);\n\n const {\n pins,\n toggle: togglePin,\n reorder: reorderPin,\n } = useBackofficeSidebarPins({\n enabled: sidebar?.pinnedItems?.enabled === true,\n storageKey: sidebar?.pinnedItems?.storageKey,\n visibleEntityIds,\n });\n\n let groupCollapseStorageKey: string | undefined;\n if (sidebar?.preferences?.storageKey != null) {\n groupCollapseStorageKey = `${sidebar.preferences.storageKey}:groups`;\n }\n\n const { collapsedByGroupId, setCollapsed } = useSidebarGroupCollapse({\n groupIds,\n activeGroupId,\n defaultCollapsedByGroupId,\n persist: sidebar?.preferences?.persistGroups === true,\n storageKey: groupCollapseStorageKey,\n });\n\n const sections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: pins,\n recentItems,\n onTogglePin: togglePin,\n onReorderPin: reorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n pathname,\n permissions,\n pins,\n recentItems,\n reorderPin,\n setCollapsed,\n sidebar,\n sidebarQuery,\n t,\n tApp,\n togglePin,\n ]);\n\n const mobileSections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: pins,\n recentItems,\n onTogglePin: togglePin,\n onReorderPin: reorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n pathname,\n permissions,\n pins,\n recentItems,\n reorderPin,\n setCollapsed,\n sidebar,\n sidebarQuery,\n t,\n tApp,\n togglePin,\n ]);\n\n const environment = useMemo(() => {\n const meta = import.meta as unknown as { env?: Record<string, unknown> };\n if (meta.env?.DEV === true) {\n return 'dev' as const;\n }\n return 'prod' as const;\n }, []);\n\n const handleSignOut = useCallback(() => {\n if (isSigningOut) {\n return;\n }\n\n type LogoutMutation = MutationParameters & {\n response: LogoutResponse;\n variables: LogoutVariables;\n };\n\n setIsSigningOut(true);\n\n const runSignOut = async (): Promise<void> => {\n try {\n const config = await authConfig.logout.load();\n await new Promise<void>((resolve, reject) => {\n commitMutation<LogoutMutation>(relayEnvironment, {\n mutation: config.logoutMutation,\n variables: {},\n onCompleted: () => {\n resolve();\n },\n onError: (error) => {\n reject(error);\n },\n });\n });\n localStorage.removeItem('auth_token');\n localStorage.removeItem('remember_me');\n resetRelayStore();\n routing?.history.push({ pathname: getBackofficeLoginPath(basePath) });\n } finally {\n setIsSigningOut(false);\n }\n };\n\n runSignOut().catch(() => {\n /* noop */\n });\n }, [authConfig.logout, basePath, isSigningOut, relayEnvironment, routing]);\n\n const viewer = authStatus?.me ?? null;\n const sidebarProfile = useMemo(() => {\n return mapViewerToSidebarProfileView({\n viewer,\n unknownUserLabel: t('sidebar.profile.unknownUser'),\n });\n }, [t, viewer]);\n\n const sidebarFooter = (\n <BackofficeSidebarProfileMenu\n collapsed={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n const mobileSidebarFooter = (\n <BackofficeSidebarProfileMenu\n collapsed={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n let contentNode: JSX.Element | null = null;\n if (topbarTarget != null) {\n contentNode = (\n <BackofficeContentBoundary>{children}</BackofficeContentBoundary>\n );\n }\n\n const sidebarSearchNode = (\n <GlobalSearchInput\n value={sidebarQuery}\n onChange={setSidebarQuery}\n placeholder={t('sidebar.search.placeholder')}\n ariaLabel={t('sidebar.search.placeholder')}\n />\n );\n\n return (\n <ToastProvider>\n <AdminShellLayout\n sidebar={{\n sections,\n header: <EnvironmentBadge environment={environment} />,\n search: sidebarSearchNode,\n footer: sidebarFooter,\n isCollapsed: isSidebarCollapsed,\n onCollapsedChange: setIsSidebarCollapsed,\n collapseToggleLabel: t('sidebar.actions.collapseSidebar'),\n expandToggleLabel: t('sidebar.actions.expandSidebar'),\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n mobileSidebar={{\n sections: mobileSections,\n header: <EnvironmentBadge environment={environment} />,\n search: sidebarSearchNode,\n footer: mobileSidebarFooter,\n isCollapsed: false,\n hideCollapseToggle: true,\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n topbar={{\n breadcrumb: <div ref={setTopbarTarget} />,\n }}\n >\n <BackofficePermissionsProvider permissions={permissions}>\n <BackofficeTopbarPortalContextProvider\n value={{\n target: topbarTarget,\n dashboardHref: basePath,\n dashboardLabel: t('sidebar.items.dashboard'),\n }}\n >\n {contentNode}\n </BackofficeTopbarPortalContextProvider>\n </BackofficePermissionsProvider>\n </AdminShellLayout>\n </ToastProvider>\n );\n};\n\ntype LayoutWithPermissionsProps = {\n children: ReactNode;\n permissionsQuery: GraphQLTaggedNode;\n prepared: PreloadedQuery<OperationType>;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst LayoutWithPermissions = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: LayoutWithPermissionsProps): JSX.Element => {\n const permissions = usePreloadedQuery(permissionsQuery, prepared);\n\n return (\n <BackofficeLayoutShell\n permissions={permissions}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport const BackofficeLayoutPage = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: BackofficeLayoutPageProps): JSX.Element => {\n if (permissionsQuery != null && prepared != null) {\n return (\n <LayoutWithPermissions\n permissionsQuery={permissionsQuery}\n prepared={prepared}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </LayoutWithPermissions>\n );\n }\n\n return (\n <BackofficeLayoutShell\n permissions={null}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport default BackofficeLayoutPage;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BackofficeLayoutPage.js","names":[],"sources":["../../../src/pages/BackofficeLayoutPage.tsx"],"sourcesContent":["import {\n useEffect,\n useMemo,\n type JSX,\n type ReactNode,\n useCallback,\n useContext,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n usePreloadedQuery,\n type PreloadedQuery,\n} from 'react-relay';\nimport type {\n GraphQLTaggedNode,\n MutationParameters,\n OperationType,\n} from 'relay-runtime';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\nimport useLocation from '@plumile/router/routing/useLocation.js';\n\nimport { AdminShellLayout } from '@plumile/ui/admin/templates/admin_shell_layout/AdminShellLayout.js';\nimport { ToastProvider } from '@plumile/ui/atomic/molecules/toast/ToastProvider.js';\nimport { EnvironmentBadge } from '@plumile/ui/backoffice/atoms/environment_badge/EnvironmentBadge.js';\nimport { GlobalSearchInput } from '@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js';\nimport { BackofficeSidebarProfileMenu } from '@plumile/ui/backoffice/molecules/sidebar_profile_menu/BackofficeSidebarProfileMenu.js';\n\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { LogoutResponse, LogoutVariables } from '../hooks/useAuth.js';\nimport { useBackofficeSidebarPins } from '../hooks/useBackofficeSidebarPins.js';\nimport { useSidebarGroupCollapse } from '../hooks/useSidebarGroupCollapse.js';\nimport { buildSidebarSections } from '../components/backoffice/layout/buildSidebarSections.js';\nimport { BackofficeContentBoundary } from '../components/backoffice/routing/BackofficeContentBoundary.js';\nimport {\n resolveActiveEntityId,\n resolveSidebarGroups,\n resolveVisibleEntityIds,\n} from '../components/backoffice/layout/sidebarUtils.js';\nimport { BackofficeTopbarPortalContextProvider } from '../components/backoffice/layout/breadcrumb/BackofficeTopbarPortalContext.js';\nimport { BackofficePermissionsProvider } from '../components/backoffice/layout/BackofficePermissionsContext.js';\nimport {\n mapViewerToSidebarProfileView,\n type BackofficeViewerIdentity,\n} from '../components/backoffice/layout/mapViewerToSidebarProfileView.js';\nimport { resetRelayStore } from '../relay/environment.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { getBackofficeLoginPath } from '../router/backofficeAuthPaths.js';\nimport type { BackofficeSidebarRecentItem } from '../provider/types.js';\n\nexport type BackofficeLayoutPageProps = {\n children: ReactNode;\n permissionsQuery?: GraphQLTaggedNode;\n prepared?: PreloadedQuery<OperationType> | null;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\ntype LayoutShellProps = {\n children: ReactNode;\n permissions: unknown;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst DEFAULT_RECENT_ITEMS_STORAGE_KEY = 'plumile:backoffice:recent-items';\nconst DEFAULT_SIDEBAR_PREFS_STORAGE_KEY = 'plumile:backoffice:sidebar';\n\nconst readRecentItems = (\n storageKey: string,\n): readonly BackofficeSidebarRecentItem[] => {\n if (typeof window === 'undefined') {\n return [];\n }\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (raw == null) {\n return [];\n }\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) {\n return [];\n }\n return parsed.filter((item): item is BackofficeSidebarRecentItem => {\n if (item == null || typeof item !== 'object') {\n return false;\n }\n const candidate = item as Partial<BackofficeSidebarRecentItem>;\n return (\n (candidate.kind === 'entity' || candidate.kind === 'tool') &&\n typeof candidate.id === 'string' &&\n typeof candidate.label === 'string' &&\n typeof candidate.href === 'string' &&\n typeof candidate.visitedAt === 'number'\n );\n });\n } catch {\n return [];\n }\n};\n\nconst writeRecentItems = (\n storageKey: string,\n items: readonly BackofficeSidebarRecentItem[],\n): void => {\n if (typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(storageKey, JSON.stringify(items));\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n};\n\nconst BackofficeLayoutShell = ({\n children,\n permissions,\n authStatus,\n activeGroupId,\n}: LayoutShellProps): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { pathname } = useLocation();\n const routing = useContext(RoutingContext);\n const relayEnvironment = useRelayEnvironment();\n const {\n auth: authConfig,\n basePath,\n entities,\n sidebar,\n } = useBackofficeConfig();\n const [sidebarQuery, setSidebarQuery] = useState('');\n const sidebarPreferencesStorageKey =\n sidebar?.preferences?.storageKey ?? DEFAULT_SIDEBAR_PREFS_STORAGE_KEY;\n const persistSidebarCollapsed =\n sidebar?.preferences?.persistCollapsed === true;\n const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return false;\n }\n try {\n return (\n window.localStorage.getItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n ) === 'true'\n );\n } catch {\n return false;\n }\n });\n const [isSigningOut, setIsSigningOut] = useState(false);\n const [topbarTarget, setTopbarTarget] = useState<HTMLDivElement | null>(null);\n const recentItemsConfig = sidebar?.recentItems;\n const recentItemsEnabled = recentItemsConfig?.enabled === true;\n const recentItemsStorageKey =\n recentItemsConfig?.storageKey ?? DEFAULT_RECENT_ITEMS_STORAGE_KEY;\n const recentItemsMaxItems = recentItemsConfig?.maxItems ?? 8;\n const [recentItems, setRecentItems] = useState<\n readonly BackofficeSidebarRecentItem[]\n >(() => {\n if (!recentItemsEnabled) {\n return [];\n }\n return readRecentItems(recentItemsStorageKey);\n });\n\n useEffect(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n String(isSidebarCollapsed),\n );\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n }, [\n isSidebarCollapsed,\n persistSidebarCollapsed,\n sidebarPreferencesStorageKey,\n ]);\n\n const groups = useMemo(() => {\n return resolveSidebarGroups(entities, sidebar);\n }, [entities, sidebar]);\n\n const groupIds = useMemo(() => {\n return Object.keys(groups);\n }, [groups]);\n\n const defaultCollapsedByGroupId = useMemo(() => {\n return Object.fromEntries(\n Object.entries(groups).map(([groupId, group]) => {\n return [groupId, group.behavior?.defaultCollapsed ?? true];\n }),\n );\n }, [groups]);\n\n const visibleEntityIds = useMemo(() => {\n return resolveVisibleEntityIds(groups, entities, sidebar, permissions);\n }, [entities, groups, permissions, sidebar]);\n\n const activeEntityId = useMemo(() => {\n return resolveActiveEntityId(pathname, entities);\n }, [entities, pathname]);\n\n useEffect(() => {\n if (!recentItemsEnabled || activeEntityId == null) {\n return;\n }\n const config = entities[activeEntityId];\n if (config == null) {\n return;\n }\n if (config.kind !== 'tool' && !config.hasList) {\n return;\n }\n const href = config.routes.list;\n let kind: BackofficeSidebarRecentItem['kind'] = 'entity';\n if (config.kind === 'tool') {\n kind = 'tool';\n }\n const item: BackofficeSidebarRecentItem = {\n kind,\n id: activeEntityId,\n label: config.label(tApp),\n href,\n visitedAt: Date.now(),\n };\n setRecentItems((prev) => {\n const next = [\n item,\n ...prev.filter((entry) => {\n return entry.id !== item.id || entry.kind !== item.kind;\n }),\n ].slice(0, recentItemsMaxItems);\n writeRecentItems(recentItemsStorageKey, next);\n return next;\n });\n }, [\n activeEntityId,\n entities,\n recentItemsEnabled,\n recentItemsMaxItems,\n recentItemsStorageKey,\n tApp,\n ]);\n\n const {\n pins,\n toggle: togglePin,\n reorder: reorderPin,\n } = useBackofficeSidebarPins({\n enabled: sidebar?.pinnedItems?.enabled === true,\n storageKey: sidebar?.pinnedItems?.storageKey,\n visibleEntityIds,\n });\n\n let groupCollapseStorageKey: string | undefined;\n if (sidebar?.preferences?.storageKey != null) {\n groupCollapseStorageKey = `${sidebar.preferences.storageKey}:groups`;\n }\n\n const { collapsedByGroupId, setCollapsed } = useSidebarGroupCollapse({\n groupIds,\n activeGroupId,\n defaultCollapsedByGroupId,\n persist: sidebar?.preferences?.persistGroups === true,\n storageKey: groupCollapseStorageKey,\n });\n\n const sections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: pins,\n recentItems,\n onTogglePin: togglePin,\n onReorderPin: reorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n pathname,\n permissions,\n pins,\n recentItems,\n reorderPin,\n setCollapsed,\n sidebar,\n sidebarQuery,\n t,\n tApp,\n togglePin,\n ]);\n\n const mobileSections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: pins,\n recentItems,\n onTogglePin: togglePin,\n onReorderPin: reorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n pathname,\n permissions,\n pins,\n recentItems,\n reorderPin,\n setCollapsed,\n sidebar,\n sidebarQuery,\n t,\n tApp,\n togglePin,\n ]);\n\n const environment = useMemo(() => {\n const meta = import.meta as unknown as { env?: Record<string, unknown> };\n if (meta.env?.DEV === true) {\n return 'dev' as const;\n }\n return 'prod' as const;\n }, []);\n\n const handleSignOut = useCallback(() => {\n if (isSigningOut) {\n return;\n }\n\n type LogoutMutation = MutationParameters & {\n response: LogoutResponse;\n variables: LogoutVariables;\n };\n\n setIsSigningOut(true);\n\n const runSignOut = async (): Promise<void> => {\n try {\n const config = await authConfig.logout.load();\n await new Promise<void>((resolve, reject) => {\n commitMutation<LogoutMutation>(relayEnvironment, {\n mutation: config.logoutMutation,\n variables: {},\n onCompleted: () => {\n resolve();\n },\n onError: (error) => {\n reject(error);\n },\n });\n });\n localStorage.removeItem('auth_token');\n localStorage.removeItem('remember_me');\n resetRelayStore();\n routing?.history.push({ pathname: getBackofficeLoginPath(basePath) });\n } finally {\n setIsSigningOut(false);\n }\n };\n\n runSignOut().catch(() => {\n /* noop */\n });\n }, [authConfig.logout, basePath, isSigningOut, relayEnvironment, routing]);\n\n const viewer = authStatus?.me ?? null;\n const sidebarProfile = useMemo(() => {\n return mapViewerToSidebarProfileView({\n viewer,\n unknownUserLabel: t('sidebar.profile.unknownUser'),\n });\n }, [t, viewer]);\n\n const sidebarFooter = (\n <BackofficeSidebarProfileMenu\n collapsed={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n const mobileSidebarFooter = (\n <BackofficeSidebarProfileMenu\n collapsed={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n let contentNode: JSX.Element | null = null;\n if (topbarTarget != null) {\n contentNode = (\n <BackofficeContentBoundary>{children}</BackofficeContentBoundary>\n );\n }\n\n const sidebarSearchNode = (\n <GlobalSearchInput\n value={sidebarQuery}\n onChange={setSidebarQuery}\n placeholder={t('sidebar.search.placeholder')}\n ariaLabel={t('sidebar.search.placeholder')}\n />\n );\n\n return (\n <ToastProvider>\n <AdminShellLayout\n sidebar={{\n sections,\n header: <EnvironmentBadge environment={environment} />,\n search: sidebarSearchNode,\n footer: sidebarFooter,\n isCollapsed: isSidebarCollapsed,\n onCollapsedChange: setIsSidebarCollapsed,\n collapseToggleLabel: t('sidebar.actions.collapseSidebar'),\n expandToggleLabel: t('sidebar.actions.expandSidebar'),\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n mobileSidebar={{\n sections: mobileSections,\n header: <EnvironmentBadge environment={environment} />,\n search: sidebarSearchNode,\n footer: mobileSidebarFooter,\n isCollapsed: false,\n hideCollapseToggle: true,\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n topbar={{\n breadcrumb: <div ref={setTopbarTarget} />,\n }}\n >\n <BackofficePermissionsProvider permissions={permissions}>\n <BackofficeTopbarPortalContextProvider\n value={{\n target: topbarTarget,\n dashboardHref: basePath,\n dashboardLabel: t('sidebar.items.dashboard'),\n }}\n >\n {contentNode}\n </BackofficeTopbarPortalContextProvider>\n </BackofficePermissionsProvider>\n </AdminShellLayout>\n </ToastProvider>\n );\n};\n\ntype LayoutWithPermissionsProps = {\n children: ReactNode;\n permissionsQuery: GraphQLTaggedNode;\n prepared: PreloadedQuery<OperationType>;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst LayoutWithPermissions = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: LayoutWithPermissionsProps): JSX.Element => {\n const permissions = usePreloadedQuery(permissionsQuery, prepared);\n\n return (\n <BackofficeLayoutShell\n permissions={permissions}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport const BackofficeLayoutPage = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: BackofficeLayoutPageProps): JSX.Element => {\n if (permissionsQuery != null && prepared != null) {\n return (\n <LayoutWithPermissions\n permissionsQuery={permissionsQuery}\n prepared={prepared}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </LayoutWithPermissions>\n );\n }\n\n return (\n <BackofficeLayoutShell\n permissions={null}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport default BackofficeLayoutPage;\n"],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ import { getBackofficePasswordResetPath as o } from "../router/backofficeAuthPat
|
|
|
8
8
|
import { useCallback as s, useContext as c, useRef as l } from "react";
|
|
9
9
|
import { jsx as u } from "react/jsx-runtime";
|
|
10
10
|
import * as d from "react-relay";
|
|
11
|
-
import
|
|
11
|
+
import f from "@plumile/router/routing/RoutingContext.js";
|
|
12
12
|
//#region src/pages/BackofficeLoginPage.tsx
|
|
13
13
|
var { usePreloadedQuery: p } = d, m = ({ prepared: d }) => {
|
|
14
14
|
let m = c(f), { auth: h, basePath: g } = n(), _ = a(), v = i(), y = r(), b = l(!1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeLoginPage.js","names":[],"sources":["../../../src/pages/BackofficeLoginPage.tsx"],"sourcesContent":["import { useCallback, useContext, useRef, type JSX } from 'react';\nimport * as ReactRelay from 'react-relay';\nimport type { PreloadedQuery } from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport
|
|
1
|
+
{"version":3,"file":"BackofficeLoginPage.js","names":[],"sources":["../../../src/pages/BackofficeLoginPage.tsx"],"sourcesContent":["import { useCallback, useContext, useRef, type JSX } from 'react';\nimport * as ReactRelay from 'react-relay';\nimport type { PreloadedQuery } from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\n\nimport type { OidcProviderKind } from '../modules/sharedSchemaTypes.js';\nimport { LoginFlow } from '../auth/login/LoginFlow.js';\nimport { synchronizeAuthStatusQuery } from '../auth/login/synchronizeAuthStatusQuery.js';\nimport { useBackofficeAuth } from '../hooks/useBackofficeAuth.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport { useBackofficeAuthLoginConfig } from '../provider/useBackofficeLazyValue.js';\nimport { getBackofficePasswordResetPath } from '../router/backofficeAuthPaths.js';\n\nconst { usePreloadedQuery } = ReactRelay;\n\nexport type BackofficeLoginPageProps = {\n prepared: { query: PreloadedQuery<OperationType> };\n};\n\nexport const BackofficeLoginPage = ({\n prepared,\n}: BackofficeLoginPageProps): JSX.Element => {\n const routerContext = useContext(RoutingContext);\n const { auth: authConfig, basePath } = useBackofficeConfig();\n const auth = useBackofficeAuthLoginConfig();\n const authState = useBackofficeAuth();\n const relayEnvironment = useRelayEnvironment();\n const isPostLoginSyncInFlightRef = useRef(false);\n\n const data = usePreloadedQuery(auth.loginQuery, prepared.query);\n const oidcProviders =\n (data as { oidcProviders?: readonly OidcProviderKind[] }).oidcProviders ??\n [];\n\n const handleLoginSuccess = useCallback((): void => {\n if (isPostLoginSyncInFlightRef.current) {\n return;\n }\n\n isPostLoginSyncInFlightRef.current = true;\n const runPostLoginSync = async (): Promise<void> => {\n try {\n const sessionAuth = await authConfig.session.load();\n if (sessionAuth.authStatusQuery == null) {\n routerContext?.history.push({\n pathname: basePath,\n });\n return;\n }\n\n await authConfig.lifecycle?.onLoginSuccess?.();\n\n const isLoggedIn = await synchronizeAuthStatusQuery<OperationType>(\n relayEnvironment,\n sessionAuth.authStatusQuery,\n );\n if (!isLoggedIn) {\n return;\n }\n routerContext?.history.push({\n pathname: basePath,\n });\n } catch {\n // Keep user on login page if post-login auth sync fails.\n } finally {\n isPostLoginSyncInFlightRef.current = false;\n }\n };\n\n runPostLoginSync().catch(() => {});\n }, [\n authConfig.lifecycle,\n authConfig.session,\n basePath,\n relayEnvironment,\n routerContext?.history,\n ]);\n\n const handleForgotPassword = useCallback(() => {\n routerContext?.history.push({\n pathname: getBackofficePasswordResetPath(basePath),\n });\n }, [basePath, routerContext?.history]);\n\n return (\n <LoginFlow\n auth={authState}\n oidcProviders={oidcProviders}\n onLoginSuccess={handleLoginSuccess}\n onForgotPassword={handleForgotPassword}\n />\n );\n};\n\nexport default BackofficeLoginPage;\n"],"mappings":";;;;;;;;;;;;AAeA,IAAM,EAAE,mBAAA,MAAsB,GAMjB,KAAuB,EAClC,kBAC2C;CAC3C,IAAM,IAAgB,EAAW,EAAe,EAC1C,EAAE,MAAM,GAAY,gBAAa,GAAqB,EACtD,IAAO,GAA8B,EACrC,IAAY,GAAmB,EAC/B,IAAmB,GAAqB,EACxC,IAA6B,EAAO,GAAM;CAyDhD,OACE,kBAAC,GAAD;EACE,MAAM;EACS,eA1DN,EAAkB,EAAK,YAAY,EAAS,MAEtD,CAAyD,iBAC1D,EAAE;EAwDA,gBAtDuB,QAAwB;GAC7C,EAA2B,YAI/B,EAA2B,UAAU,KA8BrC,YA7BoD;IAClD,IAAI;KACF,IAAM,IAAc,MAAM,EAAW,QAAQ,MAAM;KACnD,IAAI,EAAY,mBAAmB,MAAM;MACvC,GAAe,QAAQ,KAAK,EAC1B,UAAU,GACX,CAAC;MACF;;KASF,IANA,MAAM,EAAW,WAAW,kBAAkB,EAM1C,CAAC,MAJoB,EACvB,GACA,EAAY,gBACb,EAEC;KAEF,GAAe,QAAQ,KAAK,EAC1B,UAAU,GACX,CAAC;YACI,WAEE;KACR,EAA2B,UAAU;;OAIvB,CAAC,YAAY,GAAG;KACjC;GACD,EAAW;GACX,EAAW;GACX;GACA;GACA,GAAe;GAChB,CAYmB;EAChB,kBAXyB,QAAkB;GAC7C,GAAe,QAAQ,KAAK,EAC1B,UAAU,EAA+B,EAAS,EACnD,CAAC;KACD,CAAC,GAAU,GAAe,QAAQ,CAOf;EAClB,CAAA"}
|
|
@@ -7,7 +7,7 @@ import { getBackofficeLoginPath as o } from "../router/backofficeAuthPaths.js";
|
|
|
7
7
|
import { useCallback as s, useContext as c } from "react";
|
|
8
8
|
import { jsx as l } from "react/jsx-runtime";
|
|
9
9
|
import * as u from "react-relay";
|
|
10
|
-
import
|
|
10
|
+
import d from "@plumile/router/routing/RoutingContext.js";
|
|
11
11
|
//#region src/pages/BackofficePasswordResetCompletePage.tsx
|
|
12
12
|
var { useMutation: f } = u, p = () => {
|
|
13
13
|
let u = c(d), { basePath: p } = i(), m = a(), { t: h } = e(), [g] = f(m.completePasswordResetMutation);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficePasswordResetCompletePage.js","names":[],"sources":["../../../src/pages/BackofficePasswordResetCompletePage.tsx"],"sourcesContent":["import { useCallback, useContext, type JSX } from 'react';\nimport * as ReactRelay from 'react-relay';\nimport type { MutationParameters } from 'relay-runtime';\nimport
|
|
1
|
+
{"version":3,"file":"BackofficePasswordResetCompletePage.js","names":[],"sources":["../../../src/pages/BackofficePasswordResetCompletePage.tsx"],"sourcesContent":["import { useCallback, useContext, type JSX } from 'react';\nimport * as ReactRelay from 'react-relay';\nimport type { MutationParameters } from 'relay-runtime';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\n\nimport { PasswordResetCompleteScreen } from '../auth/pages/PasswordResetCompleteScreen.js';\nimport {\n type MutationPayloadBase,\n requireField,\n resolveMutationOutcome,\n} from '../relay/mutationResult.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport { useBackofficeAuthPasswordResetCompleteConfig } from '../provider/useBackofficeLazyValue.js';\nimport { getBackofficeLoginPath } from '../router/backofficeAuthPaths.js';\n\nconst { useMutation } = ReactRelay;\n\ntype CompletePasswordResetErrorReason =\n | 'INVALID_TOKEN'\n | 'TOKEN_EXPIRED'\n | 'PASSWORD_POLICY_VIOLATION'\n | 'INTERNAL_ERROR';\n\ntype CompletePasswordResetMutationPayload =\n MutationPayloadBase<CompletePasswordResetErrorReason> & {\n success?: boolean | null;\n };\n\nexport const BackofficePasswordResetCompletePage = (): JSX.Element => {\n const routerContext = useContext(RoutingContext);\n const { basePath } = useBackofficeConfig();\n const auth = useBackofficeAuthPasswordResetCompleteConfig();\n const { t } = useBackofficeReactTranslation();\n type CompletePasswordResetMutation = MutationParameters & {\n response: {\n completePasswordReset?: CompletePasswordResetMutationPayload | null;\n };\n variables: { input: { newPassword: string; token: string } };\n };\n const [commitReset] = useMutation<CompletePasswordResetMutation>(\n auth.completePasswordResetMutation,\n );\n\n const handleBackToLogin = useCallback(() => {\n routerContext?.history.push({ pathname: getBackofficeLoginPath(basePath) });\n }, [basePath, routerContext?.history]);\n\n const handleCompleteReset = useCallback(\n async (input: { newPassword: string; token: string }): Promise<boolean> => {\n const invalidMessage = t('auth.passwordResetComplete.errors.invalid');\n const defaultErrorMessage = invalidMessage;\n\n return new Promise((resolve, reject) => {\n commitReset({\n variables: {\n input,\n },\n onCompleted: (response) => {\n const outcome = resolveMutationOutcome(\n response.completePasswordReset ?? null,\n {\n defaultErrorMessage,\n mapReason: (reason) => {\n switch (reason) {\n case 'INVALID_TOKEN':\n return invalidMessage;\n case 'TOKEN_EXPIRED':\n return t('auth.passwordResetComplete.errors.expired');\n case 'PASSWORD_POLICY_VIOLATION':\n return t(\n 'auth.passwordResetComplete.errors.policyViolation',\n );\n case 'INTERNAL_ERROR':\n return invalidMessage;\n default:\n return null;\n }\n },\n },\n );\n if (!outcome.ok) {\n reject(new Error(outcome.message));\n return;\n }\n\n const successResult = requireField(\n outcome.payload.success ?? null,\n defaultErrorMessage,\n );\n if (!successResult.ok) {\n reject(new Error(successResult.message));\n return;\n }\n resolve(successResult.value);\n },\n onError: () => {\n reject(new Error(defaultErrorMessage));\n },\n });\n });\n },\n [commitReset, t],\n );\n\n return (\n <PasswordResetCompleteScreen\n onBackToLogin={handleBackToLogin}\n onCompletePasswordReset={handleCompleteReset}\n />\n );\n};\n\nexport default BackofficePasswordResetCompletePage;\n"],"mappings":";;;;;;;;;;;AAgBA,IAAM,EAAE,mBAAgB,GAaX,UAAyD;CACpE,IAAM,IAAgB,EAAW,EAAe,EAC1C,EAAE,gBAAa,GAAqB,EACpC,IAAO,GAA8C,EACrD,EAAE,SAAM,GAA+B,EAOvC,CAAC,KAAe,EACpB,EAAK,8BACN;CA+DD,OACE,kBAAC,GAAD;EACE,eA/DsB,QAAkB;GAC1C,GAAe,QAAQ,KAAK,EAAE,UAAU,EAAuB,EAAS,EAAE,CAAC;KAC1E,CAAC,GAAU,GAAe,QAAQ,CA6DlB;EACf,yBA5DwB,EAC1B,OAAO,MAAoE;GACzE,IAAM,IAAiB,EAAE,4CAA4C,EAC/D,IAAsB;GAE5B,OAAO,IAAI,SAAS,GAAS,MAAW;IACtC,EAAY;KACV,WAAW,EACT,UACD;KACD,cAAc,MAAa;MACzB,IAAM,IAAU,EACd,EAAS,yBAAyB,MAClC;OACE;OACA,YAAY,MAAW;QACrB,QAAQ,GAAR;SACE,KAAK,iBACH,OAAO;SACT,KAAK,iBACH,OAAO,EAAE,4CAA4C;SACvD,KAAK,6BACH,OAAO,EACL,oDACD;SACH,KAAK,kBACH,OAAO;SACT,SACE,OAAO;;;OAGd,CACF;MACD,IAAI,CAAC,EAAQ,IAAI;OACf,EAAW,MAAM,EAAQ,QAAQ,CAAC;OAClC;;MAGF,IAAM,IAAgB,EACpB,EAAQ,QAAQ,WAAW,MAC3B,EACD;MACD,IAAI,CAAC,EAAc,IAAI;OACrB,EAAW,MAAM,EAAc,QAAQ,CAAC;OACxC;;MAEF,EAAQ,EAAc,MAAM;;KAE9B,eAAe;MACb,EAAW,MAAM,EAAoB,CAAC;;KAEzC,CAAC;KACF;KAEJ,CAAC,GAAa,EAAE,CAMW;EACzB,CAAA"}
|
|
@@ -7,7 +7,7 @@ import { getBackofficeLoginPath as o } from "../router/backofficeAuthPaths.js";
|
|
|
7
7
|
import { useCallback as s, useContext as c } from "react";
|
|
8
8
|
import { jsx as l } from "react/jsx-runtime";
|
|
9
9
|
import * as u from "react-relay";
|
|
10
|
-
import
|
|
10
|
+
import d from "@plumile/router/routing/RoutingContext.js";
|
|
11
11
|
//#region src/pages/BackofficeVerifyEmailPage.tsx
|
|
12
12
|
var { useMutation: f } = u, p = () => {
|
|
13
13
|
let u = c(d), { basePath: p } = i(), m = a(), { t: h } = e(), [g] = f(m.verifyEmailMutation);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeVerifyEmailPage.js","names":[],"sources":["../../../src/pages/BackofficeVerifyEmailPage.tsx"],"sourcesContent":["import { useCallback, useContext, type JSX } from 'react';\nimport * as ReactRelay from 'react-relay';\nimport type { MutationParameters } from 'relay-runtime';\nimport
|
|
1
|
+
{"version":3,"file":"BackofficeVerifyEmailPage.js","names":[],"sources":["../../../src/pages/BackofficeVerifyEmailPage.tsx"],"sourcesContent":["import { useCallback, useContext, type JSX } from 'react';\nimport * as ReactRelay from 'react-relay';\nimport type { MutationParameters } from 'relay-runtime';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\n\nimport { VerifyEmailScreen } from '../auth/pages/VerifyEmailScreen.js';\nimport {\n type MutationPayloadBase,\n requireField,\n resolveMutationOutcome,\n} from '../relay/mutationResult.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport { useBackofficeAuthVerifyEmailConfig } from '../provider/useBackofficeLazyValue.js';\nimport { getBackofficeLoginPath } from '../router/backofficeAuthPaths.js';\n\nconst { useMutation } = ReactRelay;\n\ntype VerifyEmailErrorReason =\n | 'INVALID_TOKEN'\n | 'TOKEN_EXPIRED'\n | 'ALREADY_VERIFIED'\n | 'INTERNAL_ERROR';\n\ntype VerifyEmailMutationPayload =\n MutationPayloadBase<VerifyEmailErrorReason> & {\n success?: boolean | null;\n };\n\nexport const BackofficeVerifyEmailPage = (): JSX.Element => {\n const routerContext = useContext(RoutingContext);\n const { basePath } = useBackofficeConfig();\n const auth = useBackofficeAuthVerifyEmailConfig();\n const { t } = useBackofficeReactTranslation();\n type VerifyEmailMutation = MutationParameters & {\n response: { verifyEmail?: VerifyEmailMutationPayload | null };\n variables: { input: { token: string } };\n };\n const [commitVerify] = useMutation<VerifyEmailMutation>(\n auth.verifyEmailMutation,\n );\n\n const handleBackToLogin = useCallback(() => {\n routerContext?.history.push({ pathname: getBackofficeLoginPath(basePath) });\n }, [basePath, routerContext?.history]);\n\n const handleVerifyEmail = useCallback(\n async (input: { token: string }): Promise<boolean> => {\n const invalidMessage = t('auth.verifyEmail.errors.invalid');\n const defaultErrorMessage = invalidMessage;\n\n return new Promise((resolve, reject) => {\n commitVerify({\n variables: {\n input,\n },\n onCompleted: (response) => {\n const outcome = resolveMutationOutcome(\n response.verifyEmail ?? null,\n {\n defaultErrorMessage,\n mapReason: (reason) => {\n switch (reason) {\n case 'INVALID_TOKEN':\n return invalidMessage;\n case 'TOKEN_EXPIRED':\n return t('auth.verifyEmail.errors.expired');\n case 'ALREADY_VERIFIED':\n return t('auth.verifyEmail.errors.alreadyVerified');\n case 'INTERNAL_ERROR':\n return invalidMessage;\n default:\n return null;\n }\n },\n },\n );\n if (!outcome.ok) {\n reject(new Error(outcome.message));\n return;\n }\n\n const successResult = requireField(\n outcome.payload.success ?? null,\n defaultErrorMessage,\n );\n if (!successResult.ok) {\n reject(new Error(successResult.message));\n return;\n }\n resolve(successResult.value);\n },\n onError: () => {\n reject(new Error(defaultErrorMessage));\n },\n });\n });\n },\n [commitVerify, t],\n );\n\n return (\n <VerifyEmailScreen\n onBackToLogin={handleBackToLogin}\n onVerifyEmail={handleVerifyEmail}\n />\n );\n};\n\nexport default BackofficeVerifyEmailPage;\n"],"mappings":";;;;;;;;;;;AAgBA,IAAM,EAAE,mBAAgB,GAaX,UAA+C;CAC1D,IAAM,IAAgB,EAAW,EAAe,EAC1C,EAAE,gBAAa,GAAqB,EACpC,IAAO,GAAoC,EAC3C,EAAE,SAAM,GAA+B,EAKvC,CAAC,KAAgB,EACrB,EAAK,oBACN;CA6DD,OACE,kBAAC,GAAD;EACE,eA7DsB,QAAkB;GAC1C,GAAe,QAAQ,KAAK,EAAE,UAAU,EAAuB,EAAS,EAAE,CAAC;KAC1E,CAAC,GAAU,GAAe,QAAQ,CA2DlB;EACf,eA1DsB,EACxB,OAAO,MAA+C;GACpD,IAAM,IAAiB,EAAE,kCAAkC,EACrD,IAAsB;GAE5B,OAAO,IAAI,SAAS,GAAS,MAAW;IACtC,EAAa;KACX,WAAW,EACT,UACD;KACD,cAAc,MAAa;MACzB,IAAM,IAAU,EACd,EAAS,eAAe,MACxB;OACE;OACA,YAAY,MAAW;QACrB,QAAQ,GAAR;SACE,KAAK,iBACH,OAAO;SACT,KAAK,iBACH,OAAO,EAAE,kCAAkC;SAC7C,KAAK,oBACH,OAAO,EAAE,0CAA0C;SACrD,KAAK,kBACH,OAAO;SACT,SACE,OAAO;;;OAGd,CACF;MACD,IAAI,CAAC,EAAQ,IAAI;OACf,EAAW,MAAM,EAAQ,QAAQ,CAAC;OAClC;;MAGF,IAAM,IAAgB,EACpB,EAAQ,QAAQ,WAAW,MAC3B,EACD;MACD,IAAI,CAAC,EAAc,IAAI;OACrB,EAAW,MAAM,EAAc,QAAQ,CAAC;OACxC;;MAEF,EAAQ,EAAc,MAAM;;KAE9B,eAAe;MACb,EAAW,MAAM,EAAoB,CAAC;;KAEzC,CAAC;KACF;KAEJ,CAAC,GAAc,EAAE,CAMA;EACf,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backofficeDashboardPage.css.js","names":[],"sources":["../../../src/pages/backofficeDashboardPage.css.ts"],"sourcesContent":["import { sprinkles } from '@plumile/ui';\n\nexport const tileBody = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n});\n\nexport const loadingBody = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n color: 'textMuted',\n fontSize: 'sm',\n});\n\nexport const tileCount = sprinkles({\n fontSize: '3xl',\n fontWeight: 'bold',\n lineHeight: 1,\n});\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"backofficeDashboardPage.css.js","names":[],"sources":["../../../src/pages/backofficeDashboardPage.css.ts"],"sourcesContent":["import { sprinkles } from '@plumile/ui/theme/sprinkles.css.js';\n\nexport const tileBody = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n});\n\nexport const loadingBody = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n color: 'textMuted',\n fontSize: 'sm',\n});\n\nexport const tileCount = sprinkles({\n fontSize: '3xl',\n fontWeight: 'bold',\n lineHeight: 1,\n});\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backofficeEntityDetailPage.css.js","names":[],"sources":["../../../src/pages/backofficeEntityDetailPage.css.ts"],"sourcesContent":["import { style } from '@vanilla-extract/css';\nimport { sprinkles
|
|
1
|
+
{"version":3,"file":"backofficeEntityDetailPage.css.js","names":[],"sources":["../../../src/pages/backofficeEntityDetailPage.css.ts"],"sourcesContent":["import { style } from '@vanilla-extract/css';\nimport { sprinkles } from '@plumile/ui/theme/sprinkles.css.js';\nimport { vars } from '@plumile/ui/theme/themeContract.js';\n\nexport const headerActions = sprinkles({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: 2,\n flexWrap: 'wrap',\n minWidth: 0,\n});\n\nexport const headerActionGroup = sprinkles({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: 2,\n flexWrap: 'wrap',\n});\n\nexport const headerRelationGroup = style([\n sprinkles({\n display: 'flex',\n alignItems: 'center',\n }),\n {\n '@media': {\n 'screen and (min-width: 768px)': {\n paddingLeft: vars.spacing[2],\n borderLeft: `1px solid ${vars.colors.borderSubtle}`,\n },\n },\n },\n]);\n\nexport const headerBlock = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 3,\n});\n\nexport const headerMeta = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n flexWrap: 'wrap',\n});\n\nexport const headerMetaList = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n});\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backofficeEntityListPage.css.js","names":[],"sources":["../../../src/pages/backofficeEntityListPage.css.ts"],"sourcesContent":["import { style } from '@vanilla-extract/css';\nimport { sprinkles } from '@plumile/ui';\n\nexport const headerActions = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n flexWrap: 'wrap',\n});\n\nexport const actionsColumnCell = style({\n justifyContent: 'flex-end',\n});\n\nexport const actionTrigger = style({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '2rem',\n height: '2rem',\n flexShrink: 0,\n});\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"backofficeEntityListPage.css.js","names":[],"sources":["../../../src/pages/backofficeEntityListPage.css.ts"],"sourcesContent":["import { style } from '@vanilla-extract/css';\nimport { sprinkles } from '@plumile/ui/theme/sprinkles.css.js';\n\nexport const headerActions = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n flexWrap: 'wrap',\n});\n\nexport const actionsColumnCell = style({\n justifyContent: 'flex-end',\n});\n\nexport const actionTrigger = style({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '2rem',\n height: '2rem',\n flexShrink: 0,\n});\n"],"mappings":""}
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { card as e, group as t, link as n } from "./dashboardMetricGroup.css.js";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
2
|
+
import { Fragment as r, jsx as i } from "react/jsx-runtime";
|
|
3
|
+
import a from "@plumile/router/routing/Link.js";
|
|
4
|
+
import { MetricCard as o } from "@plumile/ui/components/dashboard/metric_card/MetricCard.js";
|
|
5
|
+
import { MetricTileGroup as s } from "@plumile/ui/components/dashboard/metric_tile_group/MetricTileGroup.js";
|
|
5
6
|
//#region src/pages/dashboard/DashboardMetricGroup.tsx
|
|
6
|
-
var c = ({ metrics: c, emptyState: l = null }) => c.length === 0 ? /* @__PURE__ */
|
|
7
|
+
var c = ({ metrics: c, emptyState: l = null }) => c.length === 0 ? /* @__PURE__ */ i(r, { children: l }) : /* @__PURE__ */ i(s, {
|
|
7
8
|
className: t,
|
|
8
|
-
children: c.map((t,
|
|
9
|
-
let
|
|
9
|
+
children: c.map((t, r) => {
|
|
10
|
+
let s = `${t.id}-${r}`, c = /* @__PURE__ */ i(o, {
|
|
10
11
|
className: e,
|
|
11
12
|
label: t.label,
|
|
12
13
|
value: t.value,
|
|
13
14
|
hint: t.hint
|
|
14
|
-
},
|
|
15
|
-
return t.href == null ? c : /* @__PURE__ */
|
|
15
|
+
}, s);
|
|
16
|
+
return t.href == null ? c : /* @__PURE__ */ i(a, {
|
|
16
17
|
to: t.href,
|
|
17
18
|
className: n,
|
|
18
19
|
children: c
|
|
19
|
-
},
|
|
20
|
+
}, s);
|
|
20
21
|
})
|
|
21
22
|
});
|
|
22
23
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardMetricGroup.js","names":[],"sources":["../../../../src/pages/dashboard/DashboardMetricGroup.tsx"],"sourcesContent":["import { type JSX, type ReactNode } from 'react';\nimport
|
|
1
|
+
{"version":3,"file":"DashboardMetricGroup.js","names":[],"sources":["../../../../src/pages/dashboard/DashboardMetricGroup.tsx"],"sourcesContent":["import { type JSX, type ReactNode } from 'react';\nimport Link from '@plumile/router/routing/Link.js';\nimport { MetricCard } from '@plumile/ui/components/dashboard/metric_card/MetricCard.js';\nimport { MetricTileGroup } from '@plumile/ui/components/dashboard/metric_tile_group/MetricTileGroup.js';\n\nimport * as styles from './dashboardMetricGroup.css.js';\n\nexport type DashboardMetricItem = {\n id: string;\n label: ReactNode;\n value: ReactNode;\n hint?: ReactNode;\n href?: string;\n};\n\nexport type DashboardMetricGroupProps = {\n metrics: readonly DashboardMetricItem[];\n emptyState?: ReactNode;\n};\n\nexport const DashboardMetricGroup = ({\n metrics,\n emptyState = null,\n}: DashboardMetricGroupProps): JSX.Element => {\n if (metrics.length === 0) {\n return <>{emptyState}</>;\n }\n\n return (\n <MetricTileGroup className={styles.group}>\n {metrics.map((metric, index) => {\n const key = `${metric.id}-${index}`;\n const card = (\n <MetricCard\n key={key}\n className={styles.card}\n label={metric.label}\n value={metric.value}\n hint={metric.hint}\n />\n );\n\n if (metric.href == null) {\n return card;\n }\n\n return (\n <Link key={key} to={metric.href} className={styles.link}>\n {card}\n </Link>\n );\n })}\n </MetricTileGroup>\n );\n};\n"],"mappings":";;;;;;AAoBA,IAAa,KAAwB,EACnC,YACA,gBAAa,WAET,EAAQ,WAAW,IACd,kBAAA,GAAA,EAAA,UAAG,GAAc,CAAA,GAIxB,kBAAC,GAAD;CAAiB,WAAW;WACzB,EAAQ,KAAK,GAAQ,MAAU;EAC9B,IAAM,IAAM,GAAG,EAAO,GAAG,GAAG,KACtB,IACJ,kBAAC,GAAD;GAEE,WAAW;GACX,OAAO,EAAO;GACd,OAAO,EAAO;GACd,MAAM,EAAO;GACb,EALK,EAKL;EAOJ,OAJI,EAAO,QAAQ,OACV,IAIP,kBAAC,GAAD;GAAgB,IAAI,EAAO;GAAM,WAAW;aACzC;GACI,EAFI,EAEJ;GAET;CACc,CAAA"}
|