@plumile/backoffice-react 0.1.84 → 0.1.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +113 -77
- package/lib/esm/{AcceptInvitationScreen-5-0EtE15.js → AcceptInvitationScreen-dnOvRx4Z.js} +2 -2
- package/lib/esm/{AcceptInvitationScreen-5-0EtE15.js.map → AcceptInvitationScreen-dnOvRx4Z.js.map} +1 -1
- package/lib/esm/{BackofficeAcceptInvitationPage-FPbn31YK.js → BackofficeAcceptInvitationPage-CGht2ka0.js} +3 -9
- package/lib/esm/{BackofficeAcceptInvitationPage-FPbn31YK.js.map → BackofficeAcceptInvitationPage-CGht2ka0.js.map} +1 -1
- package/lib/esm/{BackofficeDashboardPage-C7lIVeA1.js → BackofficeDashboardPage-h1OWb_rV.js} +31 -32
- package/lib/esm/BackofficeDashboardPage-h1OWb_rV.js.map +1 -0
- package/lib/esm/BackofficeEntityDetailPage-CIyGKwVP.js +1044 -0
- package/lib/esm/BackofficeEntityDetailPage-CIyGKwVP.js.map +1 -0
- package/lib/esm/BackofficeEntityListPage-DmZozSNk.js +402 -0
- package/lib/esm/BackofficeEntityListPage-DmZozSNk.js.map +1 -0
- package/lib/esm/{BackofficeLayoutPage-Da4y2B0i.js → BackofficeLayoutPage-DtFDn_nU.js} +2 -2
- package/lib/esm/BackofficeLayoutPage-DtFDn_nU.js.map +1 -0
- package/lib/esm/{BackofficeLoginPage-Dc61SyMV.js → BackofficeLoginPage-BvOPqbKO.js} +3 -8
- package/lib/esm/{BackofficeLoginPage-Dc61SyMV.js.map → BackofficeLoginPage-BvOPqbKO.js.map} +1 -1
- package/lib/esm/{BackofficePasswordResetCompletePage-CvoHqhBS.js → BackofficePasswordResetCompletePage-ZLhghfhC.js} +1 -2
- package/lib/esm/{BackofficePasswordResetCompletePage-CvoHqhBS.js.map → BackofficePasswordResetCompletePage-ZLhghfhC.js.map} +1 -1
- package/lib/esm/{BackofficePasswordResetRequestPage-DDNcCf3_.js → BackofficePasswordResetRequestPage-BLNHQD79.js} +1 -3
- package/lib/esm/{BackofficePasswordResetRequestPage-DDNcCf3_.js.map → BackofficePasswordResetRequestPage-BLNHQD79.js.map} +1 -1
- package/lib/esm/{BackofficeRightPageLayout-F8ipegrl.js → BackofficeRightPageLayout-DZQvIHnj.js} +2 -2
- package/lib/esm/{BackofficeRightPageLayout-F8ipegrl.js.map → BackofficeRightPageLayout-DZQvIHnj.js.map} +1 -1
- package/lib/esm/EntityIdPickerDialog-DbTnDU4v.js.map +1 -1
- package/lib/esm/backoffice-react.js +164 -167
- package/lib/esm/backoffice-react.js.map +1 -1
- package/lib/esm/{environment-BJeJTbIN.js → environment-BXoBq_6e.js} +72 -73
- package/lib/esm/environment-BXoBq_6e.js.map +1 -0
- package/lib/esm/{synchronizeAuthStatusQuery-Dr6AEFhi.js → synchronizeAuthStatusQuery-By_lNCnP.js} +2 -2
- package/lib/esm/{synchronizeAuthStatusQuery-Dr6AEFhi.js.map → synchronizeAuthStatusQuery-By_lNCnP.js.map} +1 -1
- package/lib/esm/{useAuth-CjdysxLB.js → useAuth-OVPPa9bO.js} +2 -2
- package/lib/esm/useAuth-OVPPa9bO.js.map +1 -0
- package/lib/esm/{useBackofficeAuth-BshabGXc.js → useBackofficeAuth-BvEoEqnB.js} +2 -2
- package/lib/esm/{useBackofficeAuth-BshabGXc.js.map → useBackofficeAuth-BvEoEqnB.js.map} +1 -1
- package/lib/types/hooks/useBackofficeSidebarPins.d.ts +4 -0
- package/lib/types/hooks/useBackofficeSidebarPins.d.ts.map +1 -1
- package/lib/types/i18n/createI18nInstance.d.ts +8 -0
- package/lib/types/i18n/createI18nInstance.d.ts.map +1 -1
- package/lib/types/i18n/mergeResourceLanguages.d.ts +4 -0
- package/lib/types/i18n/mergeResourceLanguages.d.ts.map +1 -1
- package/lib/types/modules/base64.d.ts.map +1 -1
- package/lib/types/pages/BackofficeDashboardPage.d.ts.map +1 -1
- package/lib/types/pages/BackofficeDashboardPage.helpers.d.ts +9 -0
- package/lib/types/pages/BackofficeDashboardPage.helpers.d.ts.map +1 -0
- package/lib/types/pages/BackofficeEntityDetailPage.d.ts.map +1 -1
- package/lib/types/pages/BackofficeEntityDetailPage.helpers.d.ts +14 -0
- package/lib/types/pages/BackofficeEntityDetailPage.helpers.d.ts.map +1 -0
- package/lib/types/pages/BackofficeEntityDetailPage.view-helpers.d.ts +150 -0
- package/lib/types/pages/BackofficeEntityDetailPage.view-helpers.d.ts.map +1 -0
- package/lib/types/pages/BackofficeEntityListPage.d.ts.map +1 -1
- package/lib/types/pages/BackofficeEntityListPage.helpers.d.ts +29 -0
- package/lib/types/pages/BackofficeEntityListPage.helpers.d.ts.map +1 -0
- package/lib/types/provider/entityRegistry.d.ts +5 -0
- package/lib/types/provider/entityRegistry.d.ts.map +1 -1
- package/lib/types/provider/useBackofficeEntityLoader.d.ts +5 -0
- package/lib/types/provider/useBackofficeEntityLoader.d.ts.map +1 -1
- package/lib/types/relay/envHelpers.d.ts +6 -0
- package/lib/types/relay/envHelpers.d.ts.map +1 -1
- package/lib/types/relay/environment.d.ts +26 -0
- package/lib/types/relay/environment.d.ts.map +1 -1
- package/lib/types/router/createBackofficeRoutes.d.ts +12 -1
- package/lib/types/router/createBackofficeRoutes.d.ts.map +1 -1
- package/package.json +12 -12
- package/lib/esm/BackofficeDashboardPage-C7lIVeA1.js.map +0 -1
- package/lib/esm/BackofficeEntityDetailPage-BljQmWsw.js +0 -991
- package/lib/esm/BackofficeEntityDetailPage-BljQmWsw.js.map +0 -1
- package/lib/esm/BackofficeEntityListPage-BneDsGo-.js +0 -385
- package/lib/esm/BackofficeEntityListPage-BneDsGo-.js.map +0 -1
- package/lib/esm/BackofficeLayoutPage-Da4y2B0i.js.map +0 -1
- package/lib/esm/environment-BJeJTbIN.js.map +0 -1
- package/lib/esm/useAuth-CjdysxLB.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,84 +1,122 @@
|
|
|
1
1
|
# @plumile/backoffice-react
|
|
2
2
|
|
|
3
|
-
React provider and
|
|
3
|
+
React provider, auth screens, routing scaffolds, and Relay helpers for
|
|
4
|
+
Plumile-style backoffice applications.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
+
## Status
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
Specialized public package. This package is best suited to teams building a
|
|
9
|
+
Plumile-style backoffice with entity manifests, Relay, and the shared UI layer.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
## Purpose
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
- `@plumile/backoffice-core` for manifests, facets and shared types
|
|
13
|
+
`@plumile/backoffice-react` is the React integration layer on top of:
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
- `@plumile/backoffice-core` for manifests, facets, and shared types
|
|
16
|
+
- `@plumile/ui` for the visual system
|
|
17
|
+
- `@plumile/router` for internal routing and instrumentation
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
It contains:
|
|
20
|
+
|
|
21
|
+
- `BackofficeProvider`
|
|
22
|
+
- auth screens and login flow helpers
|
|
19
23
|
- routing and page scaffolds
|
|
20
24
|
- backoffice hooks
|
|
21
|
-
- Relay
|
|
22
|
-
- entity
|
|
25
|
+
- Relay environment and mutation helpers
|
|
26
|
+
- entity loading helpers and related UI building blocks
|
|
23
27
|
|
|
24
|
-
It
|
|
28
|
+
It does not try to become:
|
|
25
29
|
|
|
26
|
-
- a
|
|
27
|
-
- a
|
|
28
|
-
- a
|
|
30
|
+
- a generic React application framework
|
|
31
|
+
- a second standalone component library
|
|
32
|
+
- a container for product-specific business logic
|
|
29
33
|
|
|
30
|
-
##
|
|
34
|
+
## Installation
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
```bash
|
|
37
|
+
npm install @plumile/backoffice-react
|
|
38
|
+
```
|
|
34
39
|
|
|
35
|
-
|
|
40
|
+
Peer dependencies:
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
```bash
|
|
43
|
+
npm install react react-dom react-i18next i18next react-relay relay-runtime
|
|
44
|
+
```
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
This package also depends on the Plumile router, UI, and backoffice-core
|
|
47
|
+
packages.
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
import {
|
|
44
|
-
createDevtoolsBridgeInstrumentation,
|
|
45
|
-
createPerformanceTimelineInstrumentation,
|
|
46
|
-
} from '@plumile/router';
|
|
47
|
-
import { BackofficeProvider } from '@plumile/backoffice-react';
|
|
49
|
+
## Main Public Surface
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
createDevtoolsBridgeInstrumentation(),
|
|
51
|
-
createPerformanceTimelineInstrumentation(),
|
|
52
|
-
];
|
|
51
|
+
### Provider and configuration
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
instrumentations={instrumentations}
|
|
59
|
-
/>;
|
|
60
|
-
```
|
|
53
|
+
- `BackofficeProvider`
|
|
54
|
+
- `useBackofficeConfig`
|
|
55
|
+
- `createBackofficeLazyValue`
|
|
56
|
+
- config types such as `BackofficeAuthConfig` and `BackofficeGraphQLConfig`
|
|
61
57
|
|
|
62
|
-
|
|
63
|
-
behaves exactly as before.
|
|
58
|
+
### Auth and session flows
|
|
64
59
|
|
|
65
|
-
|
|
60
|
+
- `LoginFlow`
|
|
61
|
+
- `AcceptInvitationScreen`
|
|
62
|
+
- `PasswordResetRequestScreen`
|
|
63
|
+
- `PasswordResetCompleteScreen`
|
|
64
|
+
- `VerifyEmailScreen`
|
|
65
|
+
- `createUseAuth`
|
|
66
66
|
|
|
67
|
-
###
|
|
67
|
+
### Hooks and backoffice helpers
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
- `useBackofficeListUrlState`
|
|
70
|
+
- `useConditionalSubscription`
|
|
71
|
+
- `useCopyToClipboard`
|
|
72
|
+
- `useRefetchNeededReload`
|
|
73
|
+
|
|
74
|
+
### Relay and mutation helpers
|
|
75
|
+
|
|
76
|
+
- `RelayProvider`
|
|
77
|
+
- `configureRelayEnvironment`
|
|
78
|
+
- `getEnvironment`
|
|
79
|
+
- `resetRelayStore`
|
|
80
|
+
- `resolveMutationOutcome`
|
|
81
|
+
- `resolveAgentStartOutcome`
|
|
82
|
+
- `requireField`
|
|
83
|
+
- `requireLinkedRecordId`
|
|
84
|
+
|
|
85
|
+
### Backoffice-specific UI scaffolds
|
|
86
|
+
|
|
87
|
+
- `BackofficeOverviewLayout`
|
|
88
|
+
- `BackofficeTabbedDetailShell`
|
|
89
|
+
- detail and filter components
|
|
90
|
+
- picker and layout helpers
|
|
91
|
+
|
|
92
|
+
For the complete export list, see [`src/index.ts`](./src/index.ts).
|
|
93
|
+
|
|
94
|
+
## Quick Start
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
71
97
|
import { BackofficeProvider } from '@plumile/backoffice-react';
|
|
72
98
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
99
|
+
export function App(): JSX.Element {
|
|
100
|
+
return (
|
|
101
|
+
<BackofficeProvider
|
|
102
|
+
entityManifest={entityManifest}
|
|
103
|
+
auth={auth}
|
|
104
|
+
graphql={graphql}
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
79
108
|
```
|
|
80
109
|
|
|
81
|
-
|
|
110
|
+
## Instrumentation
|
|
111
|
+
|
|
112
|
+
`BackofficeProvider` forwards router instrumentations to the internal
|
|
113
|
+
`createRouter(...)` call. This is useful when you want to expose:
|
|
114
|
+
|
|
115
|
+
- the Plumile Router DevTools bridge
|
|
116
|
+
- Performance Timeline marks and measures in Chrome DevTools
|
|
117
|
+
- custom router instrumentation for local diagnostics
|
|
118
|
+
|
|
119
|
+
Example:
|
|
82
120
|
|
|
83
121
|
```ts
|
|
84
122
|
import {
|
|
@@ -87,12 +125,10 @@ import {
|
|
|
87
125
|
} from '@plumile/router';
|
|
88
126
|
import { BackofficeProvider } from '@plumile/backoffice-react';
|
|
89
127
|
|
|
90
|
-
const instrumentations = [
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
instrumentations.push(createPerformanceTimelineInstrumentation());
|
|
95
|
-
}
|
|
128
|
+
const instrumentations = [
|
|
129
|
+
createDevtoolsBridgeInstrumentation(),
|
|
130
|
+
createPerformanceTimelineInstrumentation(),
|
|
131
|
+
];
|
|
96
132
|
|
|
97
133
|
<BackofficeProvider
|
|
98
134
|
entityManifest={entityManifest}
|
|
@@ -102,25 +138,25 @@ if (import.meta.env.DEV) {
|
|
|
102
138
|
/>;
|
|
103
139
|
```
|
|
104
140
|
|
|
105
|
-
|
|
141
|
+
If `instrumentations` is omitted, routing still works normally.
|
|
106
142
|
|
|
107
|
-
|
|
108
|
-
import {
|
|
109
|
-
createConsoleLoggerInstrumentation,
|
|
110
|
-
createDevtoolsBridgeInstrumentation,
|
|
111
|
-
createPerformanceTimelineInstrumentation,
|
|
112
|
-
} from '@plumile/router';
|
|
143
|
+
## Validation Notes
|
|
113
144
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
145
|
+
- public helpers that are pure or mostly pure should have focused unit tests
|
|
146
|
+
- provider behavior should remain covered by React tests
|
|
147
|
+
- package documentation should describe the main composition flows rather than
|
|
148
|
+
every low-level implementation detail
|
|
149
|
+
|
|
150
|
+
## Limitations
|
|
151
|
+
|
|
152
|
+
- this package assumes Plumile entity manifests and backoffice routing concepts
|
|
153
|
+
- Relay integration is built around Plumile conventions, not every possible
|
|
154
|
+
Relay application architecture
|
|
155
|
+
- consumers should keep domain-specific business components outside this package
|
|
120
156
|
|
|
121
|
-
|
|
157
|
+
## Related Docs
|
|
122
158
|
|
|
123
|
-
-
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
159
|
+
- [Backoffice Core README](../backoffice-core/README.md)
|
|
160
|
+
- [UI README](../ui/README.md)
|
|
161
|
+
- [Router README](../router/README.md)
|
|
162
|
+
- [Documentation Index](../../docs/index.md)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as e, d as t, f as n, s as r } from "./loginPage.css-CBJ1Ozm5.js";
|
|
2
|
-
import { o as i } from "./useAuth-
|
|
2
|
+
import { o as i } from "./useAuth-OVPPa9bO.js";
|
|
3
3
|
import { t as a } from "./AuthPanel-DiHejPoq.js";
|
|
4
4
|
import { useCallback as o, useMemo as s, useState as c } from "react";
|
|
5
5
|
import { AuthLayout as l, Button as u, FormError as d, FormField as f } from "@plumile/ui";
|
|
@@ -113,4 +113,4 @@ var h = ({ auth: h, onSuccessRedirect: g, onBackToLogin: _, token: v }) => {
|
|
|
113
113
|
//#endregion
|
|
114
114
|
export { h as t };
|
|
115
115
|
|
|
116
|
-
//# sourceMappingURL=AcceptInvitationScreen-
|
|
116
|
+
//# sourceMappingURL=AcceptInvitationScreen-dnOvRx4Z.js.map
|
package/lib/esm/{AcceptInvitationScreen-5-0EtE15.js.map → AcceptInvitationScreen-dnOvRx4Z.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AcceptInvitationScreen-
|
|
1
|
+
{"version":3,"file":"AcceptInvitationScreen-dnOvRx4Z.js","names":[],"sources":["../../src/auth/pages/AcceptInvitationScreen.tsx"],"sourcesContent":["/* eslint-disable no-ternary */\nimport {\n useCallback,\n useMemo,\n useState,\n type FormEvent,\n type JSX,\n} from 'react';\nimport { useSharedTranslation } from '../../i18n/useSharedTranslation.js';\n\nimport { AuthLayout, Button, FormError, FormField } from '@plumile/ui';\n\nimport type { UseAuthReturn } from '../../hooks/useAuth.js';\nimport { MfaChallengeForm } from '../login/MfaChallengeForm.js';\nimport AuthPanel from '../login/AuthPanel.js';\nimport * as styles from '../login/loginPage.css.js';\n\ntype AcceptanceState = 'pending' | 'mfa' | 'completed' | 'error' | 'idle';\n\ntype Props = {\n auth: UseAuthReturn;\n onSuccessRedirect: () => void;\n onBackToLogin: () => void;\n token?: string;\n};\n\nexport const AcceptInvitationScreen = ({\n auth,\n onSuccessRedirect,\n onBackToLogin,\n token,\n}: Props): JSX.Element => {\n const { t } = useSharedTranslation();\n const { acceptInvitation } = auth;\n const [status, setStatus] = useState<AcceptanceState>('idle');\n const [password, setPassword] = useState('');\n const [passwordConfirmation, setPasswordConfirmation] = useState('');\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n const resolvedToken = useMemo(() => {\n if (token != null) {\n return token;\n }\n if (typeof window === 'undefined') {\n return '';\n }\n const params = new URLSearchParams(window.location.search);\n return params.get('token') ?? '';\n }, [token]);\n\n const handleSubmit = useCallback(\n (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (resolvedToken === '') {\n setErrorMessage(t('auth.acceptInvitation.errors.missingToken'));\n setStatus('error');\n return;\n }\n\n if (password !== passwordConfirmation) {\n setErrorMessage(t('auth.acceptInvitation.errors.passwordMismatch'));\n setStatus('error');\n return;\n }\n\n setStatus('pending');\n setErrorMessage(null);\n setIsSubmitting(true);\n\n // eslint-disable-next-line no-void\n void acceptInvitation({\n token: resolvedToken,\n password,\n passwordConfirmation,\n })\n .then((result) => {\n if (result === 'mfa-required') {\n setStatus('mfa');\n return;\n }\n setStatus('completed');\n onSuccessRedirect();\n })\n .catch((error) => {\n setStatus('error');\n if (error instanceof Error) {\n setErrorMessage(error.message);\n } else if (typeof error === 'string') {\n setErrorMessage(error);\n } else {\n setErrorMessage(t('auth.acceptInvitation.errors.default'));\n }\n })\n .finally(() => {\n setIsSubmitting(false);\n });\n },\n [\n acceptInvitation,\n onSuccessRedirect,\n password,\n passwordConfirmation,\n resolvedToken,\n t,\n ],\n );\n\n const handleMfaSuccess = useCallback(() => {\n setStatus('completed');\n onSuccessRedirect();\n }, [onSuccessRedirect]);\n\n const handleRetry = useCallback(() => {\n setStatus('idle');\n setErrorMessage(null);\n setIsSubmitting(false);\n }, []);\n\n if (status === 'mfa') {\n return (\n <AuthLayout\n title={t('auth.acceptInvitation.mfaTitle')}\n subtitle={t('auth.acceptInvitation.mfaSubtitle')}\n >\n <MfaChallengeForm\n auth={auth}\n onSuccess={handleMfaSuccess}\n onBack={() => {\n auth.reset();\n handleRetry();\n }}\n />\n </AuthLayout>\n );\n }\n\n let content: JSX.Element;\n if (status === 'completed') {\n content = (\n <div className={styles.stack}>\n <p className={styles.helper}>\n {t('auth.acceptInvitation.status.success')}\n </p>\n </div>\n );\n } else {\n content = (\n <AuthPanel description={t('auth.acceptInvitation.subtitle')}>\n <form className={styles.formSurface} onSubmit={handleSubmit} noValidate>\n {errorMessage != null ? <FormError>{errorMessage}</FormError> : null}\n <FormField\n label={t('auth.acceptInvitation.form.passwordLabel')}\n name=\"password\"\n type=\"password\"\n value={password}\n onChange={(event) => {\n setPassword(event.target.value);\n setErrorMessage(null);\n if (status === 'error') {\n setStatus('idle');\n }\n }}\n placeholder={t('auth.acceptInvitation.form.passwordPlaceholder')}\n autoComplete=\"new-password\"\n required\n />\n <FormField\n label={t('auth.acceptInvitation.form.confirmLabel')}\n name=\"password-confirmation\"\n type=\"password\"\n value={passwordConfirmation}\n onChange={(event) => {\n setPasswordConfirmation(event.target.value);\n setErrorMessage(null);\n if (status === 'error') {\n setStatus('idle');\n }\n }}\n placeholder={t('auth.acceptInvitation.form.confirmPlaceholder')}\n autoComplete=\"new-password\"\n required\n />\n <Button type=\"submit\" isLoading={isSubmitting}>\n {status === 'pending'\n ? t('auth.acceptInvitation.status.workingButton')\n : t('auth.acceptInvitation.form.submit')}\n </Button>\n <Button type=\"button\" variant=\"secondary\" onClick={onBackToLogin}>\n {t('auth.acceptInvitation.actions.backToLogin')}\n </Button>\n </form>\n </AuthPanel>\n );\n }\n\n return (\n <AuthLayout title={t('auth.acceptInvitation.title')}>{content}</AuthLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import "./environment-BJeJTbIN.js";
|
|
2
|
-
import "./useRelayEnvironment-vQ86aW-n.js";
|
|
3
1
|
import { n as e } from "./BackofficeConfigContext-R0t1owTI.js";
|
|
4
|
-
import "./
|
|
5
|
-
import "./
|
|
6
|
-
import "./AuthPanel-DiHejPoq.js";
|
|
7
|
-
import { t } from "./AcceptInvitationScreen-5-0EtE15.js";
|
|
8
|
-
import "./mutationResult-CcQMY13J.js";
|
|
9
|
-
import { t as n } from "./useBackofficeAuth-BshabGXc.js";
|
|
2
|
+
import { t } from "./AcceptInvitationScreen-dnOvRx4Z.js";
|
|
3
|
+
import { t as n } from "./useBackofficeAuth-BvEoEqnB.js";
|
|
10
4
|
import { t as r } from "./backofficeAuthPaths-BiJvoI5Q.js";
|
|
11
5
|
import { useCallback as i, useContext as a } from "react";
|
|
12
6
|
import { RoutingContext as o } from "@plumile/router";
|
|
@@ -27,4 +21,4 @@ var c = () => {
|
|
|
27
21
|
//#endregion
|
|
28
22
|
export { c as BackofficeAcceptInvitationPage, c as default };
|
|
29
23
|
|
|
30
|
-
//# sourceMappingURL=BackofficeAcceptInvitationPage-
|
|
24
|
+
//# sourceMappingURL=BackofficeAcceptInvitationPage-CGht2ka0.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeAcceptInvitationPage-
|
|
1
|
+
{"version":3,"file":"BackofficeAcceptInvitationPage-CGht2ka0.js","names":[],"sources":["../../src/pages/BackofficeAcceptInvitationPage.tsx"],"sourcesContent":["import { useCallback, useContext, type JSX } from 'react';\nimport { RoutingContext } from '@plumile/router';\n\nimport { AcceptInvitationScreen } from '../auth/pages/AcceptInvitationScreen.js';\nimport { useBackofficeAuth } from '../hooks/useBackofficeAuth.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport { getBackofficeLoginPath } from '../router/backofficeAuthPaths.js';\n\nexport const BackofficeAcceptInvitationPage = (): JSX.Element => {\n const routerContext = useContext(RoutingContext);\n const { basePath } = useBackofficeConfig();\n const auth = useBackofficeAuth();\n\n const handleSuccessRedirect = useCallback(() => {\n routerContext?.history.push({ pathname: basePath });\n }, [basePath, routerContext?.history]);\n\n const handleBackToLogin = useCallback(() => {\n routerContext?.history.push({ pathname: getBackofficeLoginPath(basePath) });\n }, [basePath, routerContext?.history]);\n\n return (\n <AcceptInvitationScreen\n auth={auth}\n onSuccessRedirect={handleSuccessRedirect}\n onBackToLogin={handleBackToLogin}\n />\n );\n};\n\nexport default BackofficeAcceptInvitationPage;\n"],"mappings":";;;;;;;;AAQA,IAAa,UAAoD;CAC/D,IAAM,IAAgB,EAAW,EAAe,EAC1C,EAAE,gBAAa,GAAqB;AAW1C,QACE,kBAAC,GAAD;EACQ,MAZG,GAAmB;EAa5B,mBAX0B,QAAkB;AAC9C,MAAe,QAAQ,KAAK,EAAE,UAAU,GAAU,CAAC;KAClD,CAAC,GAAU,GAAe,QAAQ,CAAC;EAUlC,eARsB,QAAkB;AAC1C,MAAe,QAAQ,KAAK,EAAE,UAAU,EAAuB,EAAS,EAAE,CAAC;KAC1E,CAAC,GAAU,GAAe,QAAQ,CAAC;EAOlC,CAAA"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { n as e } from "./BackofficeConfigContext-R0t1owTI.js";
|
|
2
2
|
import { n as t, t as n } from "./useBackofficeReactTranslation-WfXU8kCf.js";
|
|
3
|
-
import { n as r, t as i } from "./BackofficeRightPageLayout-
|
|
4
|
-
import "./BackofficeTopbarPortalContext-iD7dm4_h.js";
|
|
3
|
+
import { n as r, t as i } from "./BackofficeRightPageLayout-DZQvIHnj.js";
|
|
5
4
|
import { a } from "./useBackofficeLazyValue-Dnii1_dE.js";
|
|
6
5
|
import { t as o } from "./buildBreadcrumbs-CqF9Nh6x.js";
|
|
7
6
|
import { Suspense as s } from "react";
|
|
@@ -10,8 +9,8 @@ import { Link as l } from "@plumile/router";
|
|
|
10
9
|
import { DataTable as u, DetailPageTemplate as d, InfoTile as f } from "@plumile/ui";
|
|
11
10
|
import * as p from "react-relay";
|
|
12
11
|
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
13
|
-
//#region src/pages/
|
|
14
|
-
var g =
|
|
12
|
+
//#region src/pages/BackofficeDashboardPage.helpers.ts
|
|
13
|
+
var g = (e, t) => e(t), _ = (e, t) => {
|
|
15
14
|
switch (e.kind) {
|
|
16
15
|
case "entityCount":
|
|
17
16
|
case "shortcut": return e.label;
|
|
@@ -19,23 +18,23 @@ var g = "txvbqb9iy txvbqbbz7 txvbqbaop", _ = "txvbqb9ip txvbqbai7 txvbqbao7", v
|
|
|
19
18
|
case "textBlock": return e.title;
|
|
20
19
|
default: return t.title;
|
|
21
20
|
}
|
|
22
|
-
},
|
|
21
|
+
}, v = (e) => "query" in e && e.query != null, y = "txvbqb9iy txvbqbbz7 txvbqbaop", b = "txvbqb9ip txvbqbai7 txvbqbao7", x = "txvbqba7 txvbqbamy txvbqbehy", S = "txvbqb9ip txvbqbajy txvbqbqi7 txvbqb8vg", { useLazyLoadQuery: C } = p, w = ({ widget: t, globalData: i }) => {
|
|
23
22
|
let { t: a } = c(), { t: o } = n(), { entities: s } = e(), d = (e) => "resolve" in t && t.resolve != null ? t.resolve(e) : null;
|
|
24
23
|
if (t.kind === "textBlock") return /* @__PURE__ */ m(f, {
|
|
25
|
-
title:
|
|
24
|
+
title: g(t.title, a),
|
|
26
25
|
children: /* @__PURE__ */ m("div", {
|
|
27
|
-
className:
|
|
28
|
-
children:
|
|
26
|
+
className: b,
|
|
27
|
+
children: g(t.body, a)
|
|
29
28
|
})
|
|
30
29
|
});
|
|
31
30
|
if (t.kind === "shortcut") {
|
|
32
31
|
let e = s[t.entityId];
|
|
33
32
|
if (e == null) return null;
|
|
34
|
-
let n =
|
|
33
|
+
let n = g(t.label, a);
|
|
35
34
|
return e.kind === "tool" ? /* @__PURE__ */ m(f, {
|
|
36
35
|
title: n,
|
|
37
36
|
children: /* @__PURE__ */ m("div", {
|
|
38
|
-
className:
|
|
37
|
+
className: S,
|
|
39
38
|
children: /* @__PURE__ */ m(l, {
|
|
40
39
|
to: e.routes.list,
|
|
41
40
|
children: o("dashboard.actions.openTool")
|
|
@@ -44,7 +43,7 @@ var g = "txvbqb9iy txvbqbbz7 txvbqbaop", _ = "txvbqb9ip txvbqbai7 txvbqbao7", v
|
|
|
44
43
|
}) : /* @__PURE__ */ m(f, {
|
|
45
44
|
title: n,
|
|
46
45
|
children: /* @__PURE__ */ m("div", {
|
|
47
|
-
className:
|
|
46
|
+
className: S,
|
|
48
47
|
children: /* @__PURE__ */ m(l, {
|
|
49
48
|
to: e.routes.list,
|
|
50
49
|
children: o("dashboard.actions.openList")
|
|
@@ -64,7 +63,7 @@ var g = "txvbqb9iy txvbqbbz7 txvbqbaop", _ = "txvbqb9ip txvbqbai7 txvbqbao7", v
|
|
|
64
63
|
}
|
|
65
64
|
});
|
|
66
65
|
return /* @__PURE__ */ m(f, {
|
|
67
|
-
title:
|
|
66
|
+
title: g(t.title, a),
|
|
68
67
|
children: /* @__PURE__ */ m(u, {
|
|
69
68
|
columns: n,
|
|
70
69
|
rows: e.rows,
|
|
@@ -83,14 +82,14 @@ var g = "txvbqb9iy txvbqbbz7 txvbqbaop", _ = "txvbqb9ip txvbqbai7 txvbqbao7", v
|
|
|
83
82
|
if (e?.kind !== "list-detail") return null;
|
|
84
83
|
let n = d(i), r = o("common.notAvailable");
|
|
85
84
|
return typeof n?.count == "number" && (r = n.count), /* @__PURE__ */ m(f, {
|
|
86
|
-
title:
|
|
85
|
+
title: g(t.label, a),
|
|
87
86
|
children: /* @__PURE__ */ h("div", {
|
|
88
|
-
className:
|
|
87
|
+
className: b,
|
|
89
88
|
children: [/* @__PURE__ */ m("div", {
|
|
90
|
-
className:
|
|
89
|
+
className: x,
|
|
91
90
|
children: r
|
|
92
91
|
}), /* @__PURE__ */ m("div", {
|
|
93
|
-
className:
|
|
92
|
+
className: S,
|
|
94
93
|
children: /* @__PURE__ */ m(l, {
|
|
95
94
|
to: e.routes.list,
|
|
96
95
|
children: o("dashboard.actions.openList")
|
|
@@ -102,34 +101,34 @@ var g = "txvbqb9iy txvbqbbz7 txvbqbaop", _ = "txvbqb9ip txvbqbai7 txvbqbao7", v
|
|
|
102
101
|
return null;
|
|
103
102
|
}, T = ({ widget: e }) => /* @__PURE__ */ m(w, {
|
|
104
103
|
widget: e,
|
|
105
|
-
globalData:
|
|
104
|
+
globalData: C(e.query, {}, { fetchPolicy: "store-or-network" })
|
|
106
105
|
}), E = ({ config: e, globalData: r }) => {
|
|
107
106
|
let { t: i } = c(), { t: a } = n();
|
|
108
107
|
return /* @__PURE__ */ m(d, {
|
|
109
108
|
header: {
|
|
110
|
-
title:
|
|
111
|
-
subtitle: (e.subtitle == null ? void 0 :
|
|
109
|
+
title: g(e.title, i),
|
|
110
|
+
subtitle: (e.subtitle == null ? void 0 : g(e.subtitle, i)) ?? a("dashboard.subtitle")
|
|
112
111
|
},
|
|
113
112
|
children: /* @__PURE__ */ m("div", {
|
|
114
|
-
className:
|
|
113
|
+
className: y,
|
|
115
114
|
children: e.widgets.map((n) => {
|
|
116
|
-
let o =
|
|
115
|
+
let o = v(n) ? /* @__PURE__ */ m(T, { widget: n }) : /* @__PURE__ */ m(w, {
|
|
117
116
|
widget: n,
|
|
118
117
|
globalData: r
|
|
119
118
|
});
|
|
120
119
|
return /* @__PURE__ */ m(t, {
|
|
121
120
|
fallback: () => /* @__PURE__ */ m(f, {
|
|
122
|
-
title:
|
|
121
|
+
title: g(_(n, e), i),
|
|
123
122
|
children: /* @__PURE__ */ m("div", {
|
|
124
|
-
className:
|
|
123
|
+
className: b,
|
|
125
124
|
children: a("common.notAvailable")
|
|
126
125
|
})
|
|
127
126
|
}),
|
|
128
127
|
children: /* @__PURE__ */ m(s, {
|
|
129
128
|
fallback: /* @__PURE__ */ m(f, {
|
|
130
|
-
title:
|
|
129
|
+
title: g(_(n, e), i),
|
|
131
130
|
children: /* @__PURE__ */ m("div", {
|
|
132
|
-
className:
|
|
131
|
+
className: b,
|
|
133
132
|
children: a("common.loading")
|
|
134
133
|
})
|
|
135
134
|
}),
|
|
@@ -141,13 +140,13 @@ var g = "txvbqb9iy txvbqbbz7 txvbqbaop", _ = "txvbqb9ip txvbqbai7 txvbqbao7", v
|
|
|
141
140
|
});
|
|
142
141
|
}, D = ({ config: e }) => /* @__PURE__ */ m(E, {
|
|
143
142
|
config: e,
|
|
144
|
-
globalData:
|
|
143
|
+
globalData: C(e.query, {}, { fetchPolicy: "store-or-network" })
|
|
145
144
|
}), O = () => {
|
|
146
145
|
let { t } = c(), { t: r } = n(), { entities: s } = e(), u = a(), p = o(r);
|
|
147
146
|
if (u == null) {
|
|
148
147
|
let e = Object.values(s).filter((e) => e.kind === "list-detail" && e.hasList).map((e) => ({
|
|
149
148
|
config: e,
|
|
150
|
-
label:
|
|
149
|
+
label: g(e.label, t)
|
|
151
150
|
})).sort((e, t) => e.label.localeCompare(t.label));
|
|
152
151
|
return /* @__PURE__ */ m(i, {
|
|
153
152
|
breadcrumb: p,
|
|
@@ -157,16 +156,16 @@ var g = "txvbqb9iy txvbqbbz7 txvbqbaop", _ = "txvbqb9ip txvbqbai7 txvbqbao7", v
|
|
|
157
156
|
subtitle: r("dashboard.subtitle")
|
|
158
157
|
},
|
|
159
158
|
children: /* @__PURE__ */ m("div", {
|
|
160
|
-
className:
|
|
159
|
+
className: y,
|
|
161
160
|
children: e.map(({ config: e, label: t }) => /* @__PURE__ */ m(f, {
|
|
162
161
|
title: t,
|
|
163
162
|
children: /* @__PURE__ */ h("div", {
|
|
164
|
-
className:
|
|
163
|
+
className: b,
|
|
165
164
|
children: [/* @__PURE__ */ m("div", {
|
|
166
|
-
className:
|
|
165
|
+
className: x,
|
|
167
166
|
children: r("common.notAvailable")
|
|
168
167
|
}), /* @__PURE__ */ m("div", {
|
|
169
|
-
className:
|
|
168
|
+
className: S,
|
|
170
169
|
children: /* @__PURE__ */ m(l, {
|
|
171
170
|
to: e.routes.list,
|
|
172
171
|
children: r("dashboard.actions.openList")
|
|
@@ -192,4 +191,4 @@ var g = "txvbqb9iy txvbqbbz7 txvbqbaop", _ = "txvbqb9ip txvbqbai7 txvbqbao7", v
|
|
|
192
191
|
//#endregion
|
|
193
192
|
export { O as BackofficeDashboardPage, O as default };
|
|
194
193
|
|
|
195
|
-
//# sourceMappingURL=BackofficeDashboardPage-
|
|
194
|
+
//# sourceMappingURL=BackofficeDashboardPage-h1OWb_rV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BackofficeDashboardPage-h1OWb_rV.js","names":[],"sources":["../../src/pages/BackofficeDashboardPage.helpers.ts","../../src/pages/backofficeDashboardPage.css.ts","../../src/pages/BackofficeDashboardPage.tsx"],"sourcesContent":["import type {\n BackofficeDashboardConfig,\n BackofficeDashboardWidget,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\nimport type { TFunction } from 'i18next';\nimport type { GraphQLTaggedNode } from 'relay-runtime';\n\nexport const resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nexport const getWidgetLabel = (\n widget: BackofficeDashboardWidget,\n config: BackofficeDashboardConfig,\n): I18nLabel => {\n switch (widget.kind) {\n case 'entityCount':\n case 'shortcut':\n return widget.label;\n case 'tablePreview':\n case 'textBlock':\n return widget.title;\n default:\n return config.title;\n }\n};\n\nexport const hasWidgetQuery = (\n widget: BackofficeDashboardWidget,\n): widget is BackofficeDashboardWidget & { query: GraphQLTaggedNode } => {\n return 'query' in widget && widget.query != null;\n};\n","import { sprinkles } from '@plumile/ui';\n\nexport const tilesGrid = sprinkles({\n display: 'grid',\n gridTemplateColumns: 'autoFillMinmax320',\n gap: 4,\n});\n\nexport const tileBody = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n});\n\nexport const tileCount = sprinkles({\n fontSize: '3xl',\n fontWeight: 'bold',\n lineHeight: 1,\n});\n\nexport const links = sprinkles({\n display: 'flex',\n flexWrap: 'wrap',\n rowGap: 2,\n columnGap: 3,\n});\n","/* eslint-disable no-ternary */\nimport { type JSX, Suspense } from 'react';\nimport { Link } from '@plumile/router';\nimport type {\n BackofficeDashboardConfig,\n BackofficeDashboardWidget,\n} from '@plumile/backoffice-core/types.js';\nimport { DataTable, DetailPageTemplate, InfoTile } from '@plumile/ui';\nimport { useTranslation } from 'react-i18next';\nimport * as ReactRelay from 'react-relay';\nimport type { GraphQLTaggedNode, OperationType } from 'relay-runtime';\n\nimport { BackofficeErrorBoundary } from '../components/backoffice/errors/BackofficeErrorBoundary.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport { useBackofficeDashboardConfig } from '../provider/useBackofficeLazyValue.js';\nimport { buildDataTableColumns } from '../components/backoffice/columns/buildDataTableColumns.js';\nimport { BackofficeRightPageLayout } from '../components/backoffice/layout/breadcrumb/BackofficeRightPageLayout.js';\nimport { buildDashboardBreadcrumb } from '../components/backoffice/layout/breadcrumb/buildBreadcrumbs.js';\nimport {\n getWidgetLabel,\n hasWidgetQuery,\n resolveLabel,\n} from './BackofficeDashboardPage.helpers.js';\n\nimport * as styles from './backofficeDashboardPage.css.js';\n\nconst { useLazyLoadQuery } = ReactRelay;\n\ntype WidgetContentProps = {\n widget: BackofficeDashboardWidget;\n globalData: unknown;\n};\n\nconst WidgetContent = ({\n widget,\n globalData,\n}: WidgetContentProps): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { entities } = useBackofficeConfig();\n\n const resolveData = (data: unknown): unknown => {\n if ('resolve' in widget && widget.resolve != null) {\n return widget.resolve(data);\n }\n return null;\n };\n\n if (widget.kind === 'textBlock') {\n const title = resolveLabel(widget.title, tApp);\n const body = resolveLabel(widget.body, tApp);\n return (\n <InfoTile title={title}>\n <div className={styles.tileBody}>{body}</div>\n </InfoTile>\n );\n }\n\n if (widget.kind === 'shortcut') {\n const entity = entities[widget.entityId];\n if (entity == null) {\n return null;\n }\n const title = resolveLabel(widget.label, tApp);\n if (entity.kind === 'tool') {\n return (\n <InfoTile title={title}>\n <div className={styles.links}>\n <Link to={entity.routes.list}>\n {t('dashboard.actions.openTool')}\n </Link>\n </div>\n </InfoTile>\n );\n }\n return (\n <InfoTile title={title}>\n <div className={styles.links}>\n <Link to={entity.routes.list}>{t('dashboard.actions.openList')}</Link>\n </div>\n </InfoTile>\n );\n }\n\n if (widget.kind === 'tablePreview') {\n const resolved = resolveData(globalData) as {\n columns: readonly unknown[];\n rows: readonly unknown[];\n } | null;\n if (resolved == null) {\n return null;\n }\n const columns = buildDataTableColumns(resolved.columns as never, {\n tApp,\n t,\n resolveEntityHref: (entityId, refId) => {\n const entityConfig = entities[entityId];\n if (entityConfig == null) {\n return null;\n }\n return entityConfig.routes.detail(refId);\n },\n });\n const title = resolveLabel(widget.title, tApp);\n return (\n <InfoTile title={title}>\n <DataTable\n columns={columns}\n rows={resolved.rows}\n getRowId={(row, index) => {\n if (row != null && typeof row === 'object') {\n const record = row as Record<string, unknown>;\n const { id } = record;\n if (typeof id === 'string' && id.trim() !== '') {\n return id;\n }\n }\n return String(index);\n }}\n />\n </InfoTile>\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (widget.kind === 'entityCount') {\n const entityManifest = entities[widget.entityId];\n if (entityManifest?.kind !== 'list-detail') {\n return null;\n }\n const resolved = resolveData(globalData) as { count: number | null } | null;\n let countLabel: number | string = t('common.notAvailable');\n if (typeof resolved?.count === 'number') {\n countLabel = resolved.count;\n }\n const title = resolveLabel(widget.label, tApp);\n return (\n <InfoTile title={title}>\n <div className={styles.tileBody}>\n <div className={styles.tileCount}>{countLabel}</div>\n <div className={styles.links}>\n <Link to={entityManifest.routes.list}>\n {t('dashboard.actions.openList')}\n </Link>\n </div>\n </div>\n </InfoTile>\n );\n }\n\n return null;\n};\n\ntype WidgetWithQueryProps = {\n widget: BackofficeDashboardWidget & { query: GraphQLTaggedNode };\n};\n\nconst WidgetWithQuery = ({ widget }: WidgetWithQueryProps): JSX.Element => {\n const data = useLazyLoadQuery<OperationType>(\n widget.query,\n {},\n {\n fetchPolicy: 'store-or-network',\n },\n );\n\n return <WidgetContent widget={widget} globalData={data} />;\n};\n\ntype DashboardContentProps = {\n config: BackofficeDashboardConfig;\n globalData: unknown;\n};\n\nconst DashboardContent = ({\n config,\n globalData,\n}: DashboardContentProps): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n\n const title = resolveLabel(config.title, tApp);\n const subtitle =\n config.subtitle != null ? resolveLabel(config.subtitle, tApp) : undefined;\n\n return (\n <DetailPageTemplate\n header={{\n title,\n subtitle: subtitle ?? t('dashboard.subtitle'),\n }}\n >\n <div className={styles.tilesGrid}>\n {config.widgets.map((widget) => {\n const content = hasWidgetQuery(widget) ? (\n <WidgetWithQuery widget={widget} />\n ) : (\n <WidgetContent widget={widget} globalData={globalData} />\n );\n\n return (\n <BackofficeErrorBoundary\n key={widget.id}\n fallback={() => {\n return (\n <InfoTile\n title={resolveLabel(getWidgetLabel(widget, config), tApp)}\n >\n <div className={styles.tileBody}>\n {t('common.notAvailable')}\n </div>\n </InfoTile>\n );\n }}\n >\n <Suspense\n fallback={\n <InfoTile\n title={resolveLabel(getWidgetLabel(widget, config), tApp)}\n >\n <div className={styles.tileBody}>{t('common.loading')}</div>\n </InfoTile>\n }\n >\n {content}\n </Suspense>\n </BackofficeErrorBoundary>\n );\n })}\n </div>\n </DetailPageTemplate>\n );\n};\n\ntype DashboardWithQueryProps = {\n config: BackofficeDashboardConfig;\n};\n\nconst DashboardWithQuery = ({\n config,\n}: DashboardWithQueryProps): JSX.Element => {\n const data = useLazyLoadQuery<OperationType>(\n config.query as never,\n {},\n { fetchPolicy: 'store-or-network' },\n );\n\n return <DashboardContent config={config} globalData={data} />;\n};\n\nexport const BackofficeDashboardPage = (): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { entities } = useBackofficeConfig();\n const dashboard = useBackofficeDashboardConfig();\n const breadcrumb = buildDashboardBreadcrumb(t);\n\n if (dashboard == null) {\n const items = Object.values(entities)\n .filter((config) => {\n return config.kind === 'list-detail' && config.hasList;\n })\n .map((config) => {\n return {\n config,\n label: resolveLabel(config.label, tApp),\n };\n })\n .sort((left, right) => {\n return left.label.localeCompare(right.label);\n });\n\n return (\n <BackofficeRightPageLayout breadcrumb={breadcrumb}>\n <DetailPageTemplate\n header={{\n title: t('dashboard.title'),\n subtitle: t('dashboard.subtitle'),\n }}\n >\n <div className={styles.tilesGrid}>\n {items.map(({ config, label }) => {\n return (\n <InfoTile key={config.id} title={label}>\n <div className={styles.tileBody}>\n <div className={styles.tileCount}>\n {t('common.notAvailable')}\n </div>\n <div className={styles.links}>\n <Link to={config.routes.list}>\n {t('dashboard.actions.openList')}\n </Link>\n </div>\n </div>\n </InfoTile>\n );\n })}\n </div>\n </DetailPageTemplate>\n </BackofficeRightPageLayout>\n );\n }\n\n if (dashboard.query != null) {\n return (\n <BackofficeRightPageLayout breadcrumb={breadcrumb}>\n <DashboardWithQuery config={dashboard} />\n </BackofficeRightPageLayout>\n );\n }\n\n return (\n <BackofficeRightPageLayout breadcrumb={breadcrumb}>\n <DashboardContent config={dashboard} globalData={null} />\n </BackofficeRightPageLayout>\n );\n};\n\nexport default BackofficeDashboardPage;\n"],"mappings":";;;;;;;;;;;;AAQA,IAAa,KAAgB,GAAkB,MACtC,EAAM,EAAK,EAGP,KACX,GACA,MACc;AACd,SAAQ,EAAO,MAAf;EACE,KAAK;EACL,KAAK,WACH,QAAO,EAAO;EAChB,KAAK;EACL,KAAK,YACH,QAAO,EAAO;EAChB,QACE,QAAO,EAAO;;GAIP,KACX,MAEO,WAAW,KAAU,EAAO,SAAS,mKEJxC,EAAE,wBAAqB,GAOvB,KAAiB,EACrB,WACA,oBAC4C;CAC5C,IAAM,EAAE,GAAG,MAAS,GAAgB,EAC9B,EAAE,SAAM,GAA+B,EACvC,EAAE,gBAAa,GAAqB,EAEpC,KAAe,MACf,aAAa,KAAU,EAAO,WAAW,OACpC,EAAO,QAAQ,EAAK,GAEtB;AAGT,KAAI,EAAO,SAAS,YAGlB,QACE,kBAAC,GAAD;EAAiB,OAHL,EAAa,EAAO,OAAO,EAAK;YAI1C,kBAAC,OAAD;GAAK,WAAW;aAHP,EAAa,EAAO,MAAM,EAAK;GAGK,CAAA;EACpC,CAAA;AAIf,KAAI,EAAO,SAAS,YAAY;EAC9B,IAAM,IAAS,EAAS,EAAO;AAC/B,MAAI,KAAU,KACZ,QAAO;EAET,IAAM,IAAQ,EAAa,EAAO,OAAO,EAAK;AAY9C,SAXI,EAAO,SAAS,SAEhB,kBAAC,GAAD;GAAiB;aACf,kBAAC,OAAD;IAAK,WAAW;cACd,kBAAC,GAAD;KAAM,IAAI,EAAO,OAAO;eACrB,EAAE,6BAA6B;KAC3B,CAAA;IACH,CAAA;GACG,CAAA,GAIb,kBAAC,GAAD;GAAiB;aACf,kBAAC,OAAD;IAAK,WAAW;cACd,kBAAC,GAAD;KAAM,IAAI,EAAO,OAAO;eAAO,EAAE,6BAA6B;KAAQ,CAAA;IAClE,CAAA;GACG,CAAA;;AAIf,KAAI,EAAO,SAAS,gBAAgB;EAClC,IAAM,IAAW,EAAY,EAAW;AAIxC,MAAI,KAAY,KACd,QAAO;EAET,IAAM,IAAU,EAAsB,EAAS,SAAkB;GAC/D;GACA;GACA,oBAAoB,GAAU,MAAU;IACtC,IAAM,IAAe,EAAS;AAI9B,WAHI,KAAgB,OACX,OAEF,EAAa,OAAO,OAAO,EAAM;;GAE3C,CAAC;AAEF,SACE,kBAAC,GAAD;GAAiB,OAFL,EAAa,EAAO,OAAO,EAAK;aAG1C,kBAAC,GAAD;IACW;IACT,MAAM,EAAS;IACf,WAAW,GAAK,MAAU;AACxB,SAAmB,OAAO,KAAQ,YAA9B,GAAwC;MAE1C,IAAM,EAAE,UADO;AAEf,UAAI,OAAO,KAAO,YAAY,EAAG,MAAM,KAAK,GAC1C,QAAO;;AAGX,YAAO,OAAO,EAAM;;IAEtB,CAAA;GACO,CAAA;;AAKf,KAAI,EAAO,SAAS,eAAe;EACjC,IAAM,IAAiB,EAAS,EAAO;AACvC,MAAI,GAAgB,SAAS,cAC3B,QAAO;EAET,IAAM,IAAW,EAAY,EAAW,EACpC,IAA8B,EAAE,sBAAsB;AAK1D,SAJI,OAAO,GAAU,SAAU,aAC7B,IAAa,EAAS,QAItB,kBAAC,GAAD;GAAiB,OAFL,EAAa,EAAO,OAAO,EAAK;aAG1C,kBAAC,OAAD;IAAK,WAAW;cAAhB,CACE,kBAAC,OAAD;KAAK,WAAW;eAAmB;KAAiB,CAAA,EACpD,kBAAC,OAAD;KAAK,WAAW;eACd,kBAAC,GAAD;MAAM,IAAI,EAAe,OAAO;gBAC7B,EAAE,6BAA6B;MAC3B,CAAA;KACH,CAAA,CACF;;GACG,CAAA;;AAIf,QAAO;GAOH,KAAmB,EAAE,gBASlB,kBAAC,GAAD;CAAuB;CAAQ,YARzB,EACX,EAAO,OACP,EAAE,EACF,EACE,aAAa,oBACd,CACF;CAEyD,CAAA,EAQtD,KAAoB,EACxB,WACA,oBACwC;CACxC,IAAM,EAAE,GAAG,MAAS,GAAgB,EAC9B,EAAE,SAAM,GAA+B;AAM7C,QACE,kBAAC,GAAD;EACE,QAAQ;GACN,OAPQ,EAAa,EAAO,OAAO,EAAK;GAQxC,WANJ,EAAO,YAAY,OAA6C,KAAA,IAAtC,EAAa,EAAO,UAAU,EAAK,KAMnC,EAAE,qBAAqB;GAC9C;YAED,kBAAC,OAAD;GAAK,WAAW;aACb,EAAO,QAAQ,KAAK,MAAW;IAC9B,IAAM,IAAU,EAAe,EAAO,GACpC,kBAAC,GAAD,EAAyB,WAAU,CAAA,GAEnC,kBAAC,GAAD;KAAuB;KAAoB;KAAc,CAAA;AAG3D,WACE,kBAAC,GAAD;KAEE,gBAEI,kBAAC,GAAD;MACE,OAAO,EAAa,EAAe,GAAQ,EAAO,EAAE,EAAK;gBAEzD,kBAAC,OAAD;OAAK,WAAW;iBACb,EAAE,sBAAsB;OACrB,CAAA;MACG,CAAA;eAIf,kBAAC,GAAD;MACE,UACE,kBAAC,GAAD;OACE,OAAO,EAAa,EAAe,GAAQ,EAAO,EAAE,EAAK;iBAEzD,kBAAC,OAAD;QAAK,WAAW;kBAAkB,EAAE,iBAAiB;QAAO,CAAA;OACnD,CAAA;gBAGZ;MACQ,CAAA;KACa,EAxBnB,EAAO,GAwBY;KAE5B;GACE,CAAA;EACa,CAAA;GAQnB,KAAsB,EAC1B,gBAQO,kBAAC,GAAD;CAA0B;CAAQ,YAN5B,EACX,EAAO,OACP,EAAE,EACF,EAAE,aAAa,oBAAoB,CACpC;CAE4D,CAAA,EAGlD,UAA6C;CACxD,IAAM,EAAK,MAAS,GAAgB,EAC9B,EAAE,SAAM,GAA+B,EACvC,EAAE,gBAAa,GAAqB,EACpC,IAAY,GAA8B,EAC1C,IAAa,EAAyB,EAAE;AAE9C,KAAI,KAAa,MAAM;EACrB,IAAM,IAAQ,OAAO,OAAO,EAAS,CAClC,QAAQ,MACA,EAAO,SAAS,iBAAiB,EAAO,QAC/C,CACD,KAAK,OACG;GACL;GACA,OAAO,EAAa,EAAO,OAAO,EAAK;GACxC,EACD,CACD,MAAM,GAAM,MACJ,EAAK,MAAM,cAAc,EAAM,MAAM,CAC5C;AAEJ,SACE,kBAAC,GAAD;GAAuC;aACrC,kBAAC,GAAD;IACE,QAAQ;KACN,OAAO,EAAE,kBAAkB;KAC3B,UAAU,EAAE,qBAAqB;KAClC;cAED,kBAAC,OAAD;KAAK,WAAW;eACb,EAAM,KAAK,EAAE,WAAQ,eAElB,kBAAC,GAAD;MAA0B,OAAO;gBAC/B,kBAAC,OAAD;OAAK,WAAW;iBAAhB,CACE,kBAAC,OAAD;QAAK,WAAW;kBACb,EAAE,sBAAsB;QACrB,CAAA,EACN,kBAAC,OAAD;QAAK,WAAW;kBACd,kBAAC,GAAD;SAAM,IAAI,EAAO,OAAO;mBACrB,EAAE,6BAA6B;SAC3B,CAAA;QACH,CAAA,CACF;;MACG,EAXI,EAAO,GAWX,CAEb;KACE,CAAA;IACa,CAAA;GACK,CAAA;;AAYhC,QARI,EAAU,SAAS,OASrB,kBAAC,GAAD;EAAuC;YACrC,kBAAC,GAAD;GAAkB,QAAQ;GAAW,YAAY;GAAQ,CAAA;EAC/B,CAAA,GAT1B,kBAAC,GAAD;EAAuC;YACrC,kBAAC,GAAD,EAAoB,QAAQ,GAAa,CAAA;EACf,CAAA"}
|