@plumile/backoffice-react 0.1.201 → 0.1.206
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 +11 -4
- package/lib/esm/auth/login/LoginFlow.js.map +1 -1
- package/lib/esm/auth/pages/AcceptInvitationScreen.js.map +1 -1
- package/lib/esm/auth/pages/PasswordResetCompleteScreen.js.map +1 -1
- package/lib/esm/auth/pages/PasswordResetRequestScreen.js.map +1 -1
- package/lib/esm/components/backoffice/detail/BackofficeEntitySummaryHeader.js +28 -28
- package/lib/esm/components/backoffice/detail/BackofficeEntitySummaryHeader.js.map +1 -1
- package/lib/esm/components/backoffice/pickers/EntityIdPickerDialog.js +123 -70
- package/lib/esm/components/backoffice/pickers/EntityIdPickerDialog.js.map +1 -1
- package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js +206 -204
- package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js.map +1 -1
- package/lib/esm/hooks/useAuth.js +56 -56
- package/lib/esm/hooks/useAuth.js.map +1 -1
- package/lib/esm/hooks/useConditionalSubscription.js +18 -18
- package/lib/esm/hooks/useConditionalSubscription.js.map +1 -1
- package/lib/esm/hooks/useInfiniteConnection.js +40 -38
- package/lib/esm/hooks/useInfiniteConnection.js.map +1 -1
- package/lib/esm/i18n/locales/en/backofficeReact.js +1 -0
- package/lib/esm/i18n/locales/en/backofficeReact.js.map +1 -1
- package/lib/esm/i18n/locales/fr/backofficeReact.js +1 -0
- package/lib/esm/i18n/locales/fr/backofficeReact.js.map +1 -1
- package/lib/esm/index.js +56 -64
- package/lib/esm/pages/BackofficeEntityDetailPage.js +97 -97
- package/lib/esm/pages/BackofficeEntityDetailPage.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityListDataPage.js +39 -31
- package/lib/esm/pages/BackofficeEntityListDataPage.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityListPage.js +2 -0
- package/lib/esm/pages/BackofficeEntityListPage.js.map +1 -1
- package/lib/esm/pages/BackofficeLayoutPage.js +19 -19
- package/lib/esm/pages/BackofficeLayoutPage.js.map +1 -1
- package/lib/esm/provider/BackofficeProvider.js +33 -33
- package/lib/esm/router/createBackofficeRoutes.js +26 -28
- package/lib/esm/router/createBackofficeRoutes.js.map +1 -1
- package/lib/esm/storybook/relay/RelayStory.js +32 -32
- package/lib/esm/storybook/relay/RelayStory.js.map +1 -1
- package/lib/esm/storybook/relay/mockResolvers.js.map +1 -1
- package/lib/esm/style.css +1 -1
- package/lib/types/components/backoffice/detail/BackofficeEntitySummaryHeader.d.ts +1 -1
- package/lib/types/components/backoffice/detail/BackofficeEntitySummaryHeader.d.ts.map +1 -1
- package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.d.ts.map +1 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeEntityListScaffold.d.ts +2 -0
- package/lib/types/components/backoffice/scaffolds/BackofficeEntityListScaffold.d.ts.map +1 -1
- package/lib/types/hooks/useAuth.d.ts.map +1 -1
- package/lib/types/hooks/useConditionalSubscription.d.ts.map +1 -1
- package/lib/types/hooks/useInfiniteConnection.d.ts +3 -2
- package/lib/types/hooks/useInfiniteConnection.d.ts.map +1 -1
- package/lib/types/i18n/locales/en/backofficeReact.d.ts +5 -0
- package/lib/types/i18n/locales/fr/backofficeReact.d.ts +5 -0
- package/lib/types/i18n/resources.d.ts +2 -0
- package/lib/types/i18n/resources.d.ts.map +1 -1
- package/lib/types/index.d.ts +1 -9
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/pages/BackofficeEntityListDataPage.d.ts.map +1 -1
- package/lib/types/pages/BackofficeEntityListPage.d.ts.map +1 -1
- package/lib/types/pages/BackofficeLayoutPage.d.ts.map +1 -1
- package/lib/types/router/createBackofficeRoutes.d.ts +3 -3
- package/lib/types/router/createBackofficeRoutes.d.ts.map +1 -1
- package/lib/types/storybook/relay/RelayStory.d.ts +1 -1
- package/lib/types/storybook/relay/RelayStory.d.ts.map +1 -1
- package/lib/types/storybook/relay/mockResolvers.d.ts +9 -1
- package/lib/types/storybook/relay/mockResolvers.d.ts.map +1 -1
- package/package.json +12 -15
- package/lib/esm/_virtual/_rolldown/runtime.js +0 -7
- package/lib/esm/components/backoffice/detail/BackofficeDetailFlagTag.js +0 -13
- package/lib/esm/components/backoffice/detail/BackofficeDetailFlagTag.js.map +0 -1
- package/lib/esm/components/backoffice/detail/BackofficeDetailTaggedValue.js +0 -12
- package/lib/esm/components/backoffice/detail/BackofficeDetailTaggedValue.js.map +0 -1
- package/lib/esm/components/backoffice/detail/BackofficeEnumLabel.js +0 -16
- package/lib/esm/components/backoffice/detail/BackofficeEnumLabel.js.map +0 -1
- package/lib/esm/components/backoffice/detail/BackofficeReferenceValue.js +0 -17
- package/lib/esm/components/backoffice/detail/BackofficeReferenceValue.js.map +0 -1
- package/lib/esm/components/backoffice/detail/BackofficeStatusGroup.js +0 -8
- package/lib/esm/components/backoffice/detail/BackofficeStatusGroup.js.map +0 -1
- package/lib/esm/components/backoffice/detail/BackofficeStatusMetaBadge.js +0 -16
- package/lib/esm/components/backoffice/detail/BackofficeStatusMetaBadge.js.map +0 -1
- package/lib/esm/components/backoffice/detail/backofficeDetailRelationLink.css.js +0 -6
- package/lib/esm/components/backoffice/detail/backofficeDetailRelationLink.css.js.map +0 -1
- package/lib/esm/components/backoffice/refs/backofficeEntityIdRef.css.js +0 -6
- package/lib/esm/components/backoffice/refs/backofficeEntityIdRef.css.js.map +0 -1
- package/lib/esm/components/backoffice/routing/BackofficeRoutePendingBar.js +0 -12
- package/lib/esm/components/backoffice/routing/BackofficeRoutePendingBar.js.map +0 -1
- package/lib/esm/components/backoffice/routing/backofficeRoutePendingBar.css.js +0 -7
- package/lib/esm/components/backoffice/routing/backofficeRoutePendingBar.css.js.map +0 -1
- package/lib/esm/hooks/useBackofficeLoadMore.js +0 -18
- package/lib/esm/hooks/useBackofficeLoadMore.js.map +0 -1
- package/lib/esm/modules/base64.js +0 -21
- package/lib/esm/modules/base64.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/arrayLikeToArray.js +0 -15
- package/lib/esm/node_modules/@babel/runtime/helpers/arrayLikeToArray.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/arrayWithoutHoles.js +0 -15
- package/lib/esm/node_modules/@babel/runtime/helpers/arrayWithoutHoles.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/defineProperty.js +0 -20
- package/lib/esm/node_modules/@babel/runtime/helpers/defineProperty.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/interopRequireDefault.js +0 -13
- package/lib/esm/node_modules/@babel/runtime/helpers/interopRequireDefault.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/iterableToArray.js +0 -13
- package/lib/esm/node_modules/@babel/runtime/helpers/iterableToArray.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/nonIterableSpread.js +0 -13
- package/lib/esm/node_modules/@babel/runtime/helpers/nonIterableSpread.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/objectSpread2.js +0 -33
- package/lib/esm/node_modules/@babel/runtime/helpers/objectSpread2.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/objectWithoutPropertiesLoose.js +0 -19
- package/lib/esm/node_modules/@babel/runtime/helpers/objectWithoutPropertiesLoose.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/toConsumableArray.js +0 -18
- package/lib/esm/node_modules/@babel/runtime/helpers/toConsumableArray.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/toPrimitive.js +0 -22
- package/lib/esm/node_modules/@babel/runtime/helpers/toPrimitive.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/toPropertyKey.js +0 -17
- package/lib/esm/node_modules/@babel/runtime/helpers/toPropertyKey.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/typeof.js +0 -18
- package/lib/esm/node_modules/@babel/runtime/helpers/typeof.js.map +0 -1
- package/lib/esm/node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js +0 -19
- package/lib/esm/node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js.map +0 -1
- package/lib/esm/node_modules/fbjs/lib/areEqual.js +0 -42
- package/lib/esm/node_modules/fbjs/lib/areEqual.js.map +0 -1
- package/lib/esm/node_modules/invariant/browser.js +0 -30
- package/lib/esm/node_modules/invariant/browser.js.map +0 -1
- package/lib/esm/node_modules/relay-test-utils/index.js +0 -11
- package/lib/esm/node_modules/relay-test-utils/index.js.map +0 -1
- package/lib/esm/node_modules/relay-test-utils/lib/RelayMockPayloadGenerator.js +0 -288
- package/lib/esm/node_modules/relay-test-utils/lib/RelayMockPayloadGenerator.js.map +0 -1
- package/lib/esm/node_modules/relay-test-utils/lib/RelayModernMockEnvironment.js +0 -183
- package/lib/esm/node_modules/relay-test-utils/lib/RelayModernMockEnvironment.js.map +0 -1
- package/lib/esm/node_modules/relay-test-utils/lib/RelayResolverTestUtils.js +0 -19
- package/lib/esm/node_modules/relay-test-utils/lib/RelayResolverTestUtils.js.map +0 -1
- package/lib/esm/node_modules/relay-test-utils/lib/index.js +0 -21
- package/lib/esm/node_modules/relay-test-utils/lib/index.js.map +0 -1
- package/lib/esm/node_modules/relay-test-utils/lib/unwrapContainer.js +0 -16
- package/lib/esm/node_modules/relay-test-utils/lib/unwrapContainer.js.map +0 -1
- package/lib/esm/relay/RelayProvider.js +0 -2
- package/lib/esm/relay/envHelpers.js +0 -63
- package/lib/esm/relay/envHelpers.js.map +0 -1
- package/lib/esm/relay/environment.js +0 -2
- package/lib/esm/relay/shortAccessTokenEnvironment.js +0 -2
- package/lib/esm/relay/useRelayOperationActivity.js +0 -2
- package/lib/esm/storybook/relay/relay-test-utils.d.js +0 -0
- package/lib/types/auth/AuthFlows.stories.d.ts +0 -19
- package/lib/types/auth/AuthFlows.stories.d.ts.map +0 -1
- package/lib/types/components/backoffice/billing/BackofficeBillingUsageChart.stories.d.ts +0 -41
- package/lib/types/components/backoffice/billing/BackofficeBillingUsageChart.stories.d.ts.map +0 -1
- package/lib/types/components/backoffice/detail/BackofficeDetailFlagTag.d.ts +0 -11
- package/lib/types/components/backoffice/detail/BackofficeDetailFlagTag.d.ts.map +0 -1
- package/lib/types/components/backoffice/detail/BackofficeDetailPrimitives.stories.d.ts +0 -17
- package/lib/types/components/backoffice/detail/BackofficeDetailPrimitives.stories.d.ts.map +0 -1
- package/lib/types/components/backoffice/detail/BackofficeDetailTaggedValue.d.ts +0 -13
- package/lib/types/components/backoffice/detail/BackofficeDetailTaggedValue.d.ts.map +0 -1
- package/lib/types/components/backoffice/detail/BackofficeEnumLabel.d.ts +0 -9
- package/lib/types/components/backoffice/detail/BackofficeEnumLabel.d.ts.map +0 -1
- package/lib/types/components/backoffice/detail/BackofficeReferenceValue.d.ts +0 -10
- package/lib/types/components/backoffice/detail/BackofficeReferenceValue.d.ts.map +0 -1
- package/lib/types/components/backoffice/detail/BackofficeStatusGroup.d.ts +0 -8
- package/lib/types/components/backoffice/detail/BackofficeStatusGroup.d.ts.map +0 -1
- package/lib/types/components/backoffice/detail/BackofficeStatusMetaBadge.d.ts +0 -11
- package/lib/types/components/backoffice/detail/BackofficeStatusMetaBadge.d.ts.map +0 -1
- package/lib/types/components/backoffice/detail/backofficeDetailRelationLink.css.d.ts +0 -6
- package/lib/types/components/backoffice/detail/backofficeDetailRelationLink.css.d.ts.map +0 -1
- package/lib/types/components/backoffice/errors/BackofficeErrorBoundary.stories.d.ts +0 -12
- package/lib/types/components/backoffice/errors/BackofficeErrorBoundary.stories.d.ts.map +0 -1
- package/lib/types/components/backoffice/filters/EntityIdFilterField.stories.d.ts +0 -12
- package/lib/types/components/backoffice/filters/EntityIdFilterField.stories.d.ts.map +0 -1
- package/lib/types/components/backoffice/hub/BackofficeHubTemplate.stories.d.ts +0 -49
- package/lib/types/components/backoffice/hub/BackofficeHubTemplate.stories.d.ts.map +0 -1
- package/lib/types/components/backoffice/overview/BackofficeOverviewLayout.stories.d.ts +0 -11
- package/lib/types/components/backoffice/overview/BackofficeOverviewLayout.stories.d.ts.map +0 -1
- package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.stories.d.ts +0 -12
- package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.stories.d.ts.map +0 -1
- package/lib/types/components/backoffice/refs/backofficeEntityIdRef.css.d.ts +0 -2
- package/lib/types/components/backoffice/refs/backofficeEntityIdRef.css.d.ts.map +0 -1
- package/lib/types/components/backoffice/routing/BackofficeRoutePendingBar.d.ts +0 -4
- package/lib/types/components/backoffice/routing/BackofficeRoutePendingBar.d.ts.map +0 -1
- package/lib/types/components/backoffice/routing/backofficeRoutePendingBar.css.d.ts +0 -3
- package/lib/types/components/backoffice/routing/backofficeRoutePendingBar.css.d.ts.map +0 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.stories.d.ts +0 -11
- package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.stories.d.ts.map +0 -1
- package/lib/types/components/backoffice/tools/BackofficeTools.stories.d.ts +0 -17
- package/lib/types/components/backoffice/tools/BackofficeTools.stories.d.ts.map +0 -1
- package/lib/types/hooks/useBackofficeLoadMore.d.ts +0 -9
- package/lib/types/hooks/useBackofficeLoadMore.d.ts.map +0 -1
- package/lib/types/modules/base64.d.ts +0 -3
- package/lib/types/modules/base64.d.ts.map +0 -1
- package/lib/types/pages/BackofficeDashboardPage.stories.d.ts +0 -9
- package/lib/types/pages/BackofficeDashboardPage.stories.d.ts.map +0 -1
- package/lib/types/relay/RelayProvider.d.ts +0 -2
- package/lib/types/relay/RelayProvider.d.ts.map +0 -1
- package/lib/types/relay/envHelpers.d.ts +0 -25
- package/lib/types/relay/envHelpers.d.ts.map +0 -1
- package/lib/types/relay/environment.d.ts +0 -2
- package/lib/types/relay/environment.d.ts.map +0 -1
- package/lib/types/relay/shortAccessTokenEnvironment.d.ts +0 -5
- package/lib/types/relay/shortAccessTokenEnvironment.d.ts.map +0 -1
- package/lib/types/relay/useRelayOperationActivity.d.ts +0 -2
- package/lib/types/relay/useRelayOperationActivity.d.ts.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { useBackofficeReactTranslation as e } from "../i18n/useBackofficeReactTranslation.js";
|
|
2
2
|
import { BackofficeErrorBoundary as t } from "../components/backoffice/errors/BackofficeErrorBoundary.js";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
3
|
+
import n from "../hooks/useInfiniteConnection.js";
|
|
4
|
+
import { useBackofficeRuntimePaginationFragment as r } from "../relay/typedRelayHooks.js";
|
|
5
|
+
import { BackofficeLazyEntityCountLabel as i } from "../components/backoffice/refs/BackofficeLazyEntityCount.js";
|
|
6
|
+
import { BackofficeEntityListScaffold as a } from "../components/backoffice/scaffolds/BackofficeEntityListScaffold.js";
|
|
7
|
+
import { useRelayEnvironment as o } from "../relay/useRelayEnvironment.js";
|
|
8
|
+
import { useBackofficeListRefetch as s } from "../hooks/useBackofficeListRefetch.js";
|
|
9
9
|
import { useBackofficeEntityListRouteContext as c } from "./BackofficeEntityListRouteContext.js";
|
|
10
10
|
import { useCallback as l, useEffect as u, useMemo as d, useRef as f, useState as p } from "react";
|
|
11
11
|
import { InlineBanner as m } from "@plumile/ui/components/feedback/InlineBanner.js";
|
|
@@ -16,7 +16,7 @@ import { BACKOFFICE_LIST_DEFAULTS as y, BACKOFFICE_LIST_REFETCH_POLICY as b } fr
|
|
|
16
16
|
import { stableListVariablesKey as x } from "@plumile/backoffice-core/state/stableKey.js";
|
|
17
17
|
//#region src/pages/BackofficeEntityListDataPage.tsx
|
|
18
18
|
function S({ queryRef: t }) {
|
|
19
|
-
let { config:
|
|
19
|
+
let { config: o, state: p, pushState: m, headerActions: g, columns: _, gridTemplateColumns: S, getRowId: C, countFetchKey: w, bumpCountFetchKey: T, filterDrawerState: E, registerRefresh: D } = c(), O = o.list, { t: k } = e(), A = v(O.query, t), { data: j, loadNext: M, hasNext: N, isLoadingNext: P, refetch: F } = r(O.fragment, A), I = O.getConnection(j), L = d(() => I.edges.map((e) => O.toRow(e.node)), [I.edges, O]), { listDefaults: R } = o, z = p.sort ?? R.sort, { pageSize: B } = y, V = d(() => ({
|
|
20
20
|
where: p.where,
|
|
21
21
|
sort: z,
|
|
22
22
|
count: B,
|
|
@@ -25,7 +25,7 @@ function S({ queryRef: t }) {
|
|
|
25
25
|
B,
|
|
26
26
|
z,
|
|
27
27
|
p.where
|
|
28
|
-
]), H = d(() => x(V), [V]), U = f(H), { isRefreshing: W, onRefresh: G } =
|
|
28
|
+
]), H = d(() => x(V), [V]), U = f(H), { isRefreshing: W, onRefresh: G } = s({
|
|
29
29
|
refetch: F,
|
|
30
30
|
variables: V,
|
|
31
31
|
defaults: {
|
|
@@ -46,44 +46,50 @@ function S({ queryRef: t }) {
|
|
|
46
46
|
u(() => (D(K), () => {
|
|
47
47
|
D(null);
|
|
48
48
|
}), [K, D]);
|
|
49
|
-
let q =
|
|
49
|
+
let q = l((e) => {
|
|
50
|
+
M(B, { onComplete: e });
|
|
51
|
+
}, [M, B]), J = n({
|
|
52
|
+
nodes: L,
|
|
50
53
|
hasNext: N,
|
|
51
54
|
isLoadingNext: P,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
runLoadMore: q,
|
|
56
|
+
surface: `backoffice.entity-list.${o.id}`,
|
|
57
|
+
resetKey: H
|
|
58
|
+
}), Y = /* @__PURE__ */ h("span", { children: k("common.loading") });
|
|
59
|
+
L.length > 0 && (Y = /* @__PURE__ */ h("span", { children: k("list.loaded", { count: L.length }) }));
|
|
60
|
+
let X = /* @__PURE__ */ h(i, {
|
|
57
61
|
count: O.count,
|
|
58
62
|
where: p.where,
|
|
59
63
|
fetchKey: w,
|
|
60
|
-
loadingFallback:
|
|
64
|
+
loadingFallback: Y,
|
|
61
65
|
children: (e) => /* @__PURE__ */ h("span", { children: k("list.showing", {
|
|
62
66
|
shown: L.length,
|
|
63
67
|
total: e
|
|
64
68
|
}) })
|
|
65
69
|
});
|
|
66
|
-
return /* @__PURE__ */ h(
|
|
67
|
-
config:
|
|
70
|
+
return /* @__PURE__ */ h(a, {
|
|
71
|
+
config: o,
|
|
68
72
|
state: p,
|
|
69
73
|
pushState: m,
|
|
70
74
|
headerActions: g,
|
|
71
|
-
rows:
|
|
75
|
+
rows: J.nodes,
|
|
72
76
|
columns: _,
|
|
73
77
|
gridTemplateColumns: S,
|
|
74
78
|
getRowId: C,
|
|
75
|
-
hasNextPage:
|
|
76
|
-
isLoadingMore:
|
|
79
|
+
hasNextPage: J.hasNext,
|
|
80
|
+
isLoadingMore: J.isLoadingNext,
|
|
81
|
+
incrementalError: J.incrementalError,
|
|
77
82
|
isRefreshing: W,
|
|
78
|
-
onLoadMore:
|
|
83
|
+
onLoadMore: J.loadMoreSafe,
|
|
84
|
+
onRetryLoadMore: J.retryLoadMore,
|
|
79
85
|
onRefresh: K,
|
|
80
86
|
totalCount: null,
|
|
81
|
-
loadedCountLabel:
|
|
87
|
+
loadedCountLabel: X,
|
|
82
88
|
filterDrawerState: E
|
|
83
89
|
});
|
|
84
90
|
}
|
|
85
91
|
var C = ({ prepared: n }) => {
|
|
86
|
-
let { config: r, state:
|
|
92
|
+
let { config: r, state: i, pushState: s, headerActions: d, columns: v, gridTemplateColumns: b, getRowId: x, filterDrawerState: C } = c(), w = o(), { t: T } = e(), [E, D] = p(() => n.query), O = f(null), k = l(() => {
|
|
87
93
|
O.current?.dispose(), O.current = null;
|
|
88
94
|
}, []);
|
|
89
95
|
u(() => {
|
|
@@ -92,24 +98,24 @@ var C = ({ prepared: n }) => {
|
|
|
92
98
|
k();
|
|
93
99
|
}, [k]);
|
|
94
100
|
let A = l(() => {
|
|
95
|
-
let e = r.list, { listDefaults: t } = r, { pageSize: n } = y,
|
|
96
|
-
where:
|
|
97
|
-
sort:
|
|
101
|
+
let e = r.list, { listDefaults: t } = r, { pageSize: n } = y, a = {
|
|
102
|
+
where: i.where,
|
|
103
|
+
sort: i.sort ?? t.sort,
|
|
98
104
|
count: n,
|
|
99
105
|
cursor: null
|
|
100
|
-
},
|
|
106
|
+
}, o = e.buildQueryVariables(a), s = _(w, e.query, o, { fetchPolicy: "network-only" });
|
|
101
107
|
k(), O.current = s, D(s);
|
|
102
108
|
}, [
|
|
103
109
|
r,
|
|
104
110
|
k,
|
|
105
111
|
w,
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
i.sort,
|
|
113
|
+
i.where
|
|
108
114
|
]);
|
|
109
115
|
return /* @__PURE__ */ h(t, {
|
|
110
|
-
fallback: ({ reset: e }) => /* @__PURE__ */ h(
|
|
116
|
+
fallback: ({ reset: e }) => /* @__PURE__ */ h(a, {
|
|
111
117
|
config: r,
|
|
112
|
-
state:
|
|
118
|
+
state: i,
|
|
113
119
|
pushState: s,
|
|
114
120
|
headerActions: d,
|
|
115
121
|
rows: [],
|
|
@@ -118,8 +124,10 @@ var C = ({ prepared: n }) => {
|
|
|
118
124
|
getRowId: x,
|
|
119
125
|
hasNextPage: !1,
|
|
120
126
|
isLoadingMore: !1,
|
|
127
|
+
incrementalError: null,
|
|
121
128
|
isRefreshing: !1,
|
|
122
129
|
onLoadMore: () => {},
|
|
130
|
+
onRetryLoadMore: () => {},
|
|
123
131
|
onRefresh: () => {
|
|
124
132
|
e(), A();
|
|
125
133
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeEntityListDataPage.js","names":[],"sources":["../../../src/pages/BackofficeEntityListDataPage.tsx"],"sourcesContent":["import {\n type JSX,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { loadQuery, usePreloadedQuery } from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\nimport {\n BACKOFFICE_LIST_DEFAULTS,\n BACKOFFICE_LIST_REFETCH_POLICY,\n} from '@plumile/backoffice-core/constants.js';\nimport { stableListVariablesKey } from '@plumile/backoffice-core/state/stableKey.js';\nimport type { BackofficePreparedListDataRoute } from '@plumile/backoffice-core/types.js';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { InlineBanner } from '@plumile/ui/components/feedback/InlineBanner.js';\n\nimport { BackofficeErrorBoundary } from '../components/backoffice/errors/BackofficeErrorBoundary.js';\nimport { BackofficeEntityListScaffold } from '../components/backoffice/scaffolds/BackofficeEntityListScaffold.js';\nimport { BackofficeLazyEntityCountLabel } from '../components/backoffice/refs/BackofficeLazyEntityCount.js';\nimport { useBackofficeLoadMore } from '../hooks/useBackofficeLoadMore.js';\nimport { useBackofficeListRefetch } from '../hooks/useBackofficeListRefetch.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeRuntimePaginationFragment } from '../relay/typedRelayHooks.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { useBackofficeEntityListRouteContext } from './BackofficeEntityListRouteContext.js';\n\nexport type BackofficeEntityListDataPageProps = {\n prepared: BackofficePreparedListDataRoute;\n};\n\ntype BackofficeEntityConnectionListDataProps = {\n queryRef: BackofficePreparedListDataRoute['query'];\n};\n\n/**\n * Renders the Relay-backed row data under the list layout route boundary.\n */\nfunction BackofficeEntityConnectionListData({\n queryRef,\n}: BackofficeEntityConnectionListDataProps): JSX.Element | null {\n const {\n config,\n state,\n pushState,\n headerActions,\n columns,\n gridTemplateColumns,\n getRowId,\n countFetchKey,\n bumpCountFetchKey,\n filterDrawerState,\n registerRefresh,\n } = useBackofficeEntityListRouteContext();\n const listConfig = config.list;\n const { t } = useBackofficeReactTranslation();\n\n const queryData = usePreloadedQuery(listConfig.query, queryRef);\n const {\n data: fragmentData,\n loadNext,\n hasNext,\n isLoadingNext,\n refetch,\n } = useBackofficeRuntimePaginationFragment<OperationType>(\n listConfig.fragment,\n queryData,\n );\n\n const connection = listConfig.getConnection(fragmentData);\n\n const rows = useMemo(() => {\n return connection.edges.map((edge) => {\n return listConfig.toRow(edge.node);\n });\n }, [connection.edges, listConfig]);\n\n const { listDefaults } = config;\n const resolvedSort = state.sort ?? listDefaults.sort;\n const { pageSize } = BACKOFFICE_LIST_DEFAULTS;\n\n const baseVariables = useMemo(() => {\n return {\n where: state.where,\n sort: resolvedSort,\n count: pageSize,\n cursor: null,\n };\n }, [pageSize, resolvedSort, state.where]);\n const countVariablesKey = useMemo(() => {\n return stableListVariablesKey(baseVariables);\n }, [baseVariables]);\n const previousCountVariablesKeyRef = useRef(countVariablesKey);\n\n const { isRefreshing, onRefresh } = useBackofficeListRefetch({\n refetch,\n variables: baseVariables,\n defaults: {\n where: listDefaults.where,\n sort: listDefaults.sort,\n count: pageSize,\n cursor: null,\n },\n fetchPolicy: BACKOFFICE_LIST_REFETCH_POLICY,\n buildQueryVariables: listConfig.buildQueryVariables,\n });\n\n useEffect(() => {\n if (previousCountVariablesKeyRef.current === countVariablesKey) {\n return;\n }\n previousCountVariablesKeyRef.current = countVariablesKey;\n bumpCountFetchKey();\n }, [bumpCountFetchKey, countVariablesKey]);\n\n const handleRefresh = useCallback(() => {\n bumpCountFetchKey();\n onRefresh();\n }, [bumpCountFetchKey, onRefresh]);\n\n useEffect(() => {\n registerRefresh(handleRefresh);\n return () => {\n registerRefresh(null);\n };\n }, [handleRefresh, registerRefresh]);\n\n const handleLoadMore = useBackofficeLoadMore({\n hasNext,\n isLoadingNext,\n loadNext,\n count: pageSize,\n });\n\n let loadedCountFallback: JSX.Element = <span>{t('common.loading')}</span>;\n if (rows.length > 0) {\n loadedCountFallback = (\n <span>\n {t('list.loaded', {\n count: rows.length,\n })}\n </span>\n );\n }\n const loadedCountLabel = (\n <BackofficeLazyEntityCountLabel\n count={listConfig.count}\n where={state.where}\n fetchKey={countFetchKey}\n loadingFallback={loadedCountFallback}\n >\n {(totalCount) => {\n return (\n <span>\n {t('list.showing', {\n shown: rows.length,\n total: totalCount,\n })}\n </span>\n );\n }}\n </BackofficeLazyEntityCountLabel>\n );\n\n return (\n <BackofficeEntityListScaffold\n config={config}\n state={state}\n pushState={pushState}\n headerActions={headerActions}\n rows={rows}\n columns={columns}\n gridTemplateColumns={gridTemplateColumns}\n getRowId={getRowId}\n hasNextPage={hasNext}\n isLoadingMore={isLoadingNext}\n isRefreshing={isRefreshing}\n onLoadMore={handleLoadMore}\n onRefresh={handleRefresh}\n totalCount={null}\n loadedCountLabel={loadedCountLabel}\n filterDrawerState={filterDrawerState}\n />\n );\n}\n\nexport const BackofficeEntityListDataPage = ({\n prepared,\n}: BackofficeEntityListDataPageProps): JSX.Element | null => {\n const {\n config,\n state,\n pushState,\n headerActions,\n columns,\n gridTemplateColumns,\n getRowId,\n filterDrawerState,\n } = useBackofficeEntityListRouteContext();\n const relayEnvironment = useRelayEnvironment();\n const { t } = useBackofficeReactTranslation();\n const [queryRef, setQueryRef] = useState(() => {\n return prepared.query;\n });\n const ownedQueryRef = useRef<BackofficePreparedListDataRoute['query'] | null>(\n null,\n );\n\n const disposeOwnedQueryRef = useCallback(() => {\n ownedQueryRef.current?.dispose();\n ownedQueryRef.current = null;\n }, []);\n\n useEffect(() => {\n disposeOwnedQueryRef();\n setQueryRef(prepared.query);\n }, [disposeOwnedQueryRef, prepared.query]);\n\n useEffect(() => {\n return () => {\n disposeOwnedQueryRef();\n };\n }, [disposeOwnedQueryRef]);\n\n const reloadInitialQuery = useCallback(() => {\n const listConfig = config.list;\n const { listDefaults } = config;\n const { pageSize } = BACKOFFICE_LIST_DEFAULTS;\n const variablesBase = {\n where: state.where,\n sort: state.sort ?? listDefaults.sort,\n count: pageSize,\n cursor: null,\n };\n const variables = listConfig.buildQueryVariables(variablesBase);\n const nextQueryRef = loadQuery<OperationType>(\n relayEnvironment,\n listConfig.query,\n variables,\n {\n fetchPolicy: 'network-only',\n },\n );\n disposeOwnedQueryRef();\n ownedQueryRef.current = nextQueryRef;\n setQueryRef(nextQueryRef);\n }, [config, disposeOwnedQueryRef, relayEnvironment, state.sort, state.where]);\n\n return (\n <BackofficeErrorBoundary\n fallback={({ reset }) => {\n return (\n <BackofficeEntityListScaffold\n config={config}\n state={state}\n pushState={pushState}\n headerActions={headerActions}\n rows={[]}\n columns={columns}\n gridTemplateColumns={gridTemplateColumns}\n getRowId={getRowId}\n hasNextPage={false}\n isLoadingMore={false}\n isRefreshing={false}\n onLoadMore={() => {}}\n onRefresh={() => {\n reset();\n reloadInitialQuery();\n }}\n totalCount={null}\n filterDrawerState={filterDrawerState}\n emptyState={\n <InlineBanner\n tone=\"danger\"\n title={t('list.errors.title')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n reset();\n reloadInitialQuery();\n }}\n >\n {t('list.actions.retry')}\n </Button>\n }\n >\n {t('list.errors.tableFailed')}\n </InlineBanner>\n }\n />\n );\n }}\n >\n <BackofficeEntityConnectionListData queryRef={queryRef} />\n </BackofficeErrorBoundary>\n );\n};\n\nexport default BackofficeEntityListDataPage;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BackofficeEntityListDataPage.js","names":[],"sources":["../../../src/pages/BackofficeEntityListDataPage.tsx"],"sourcesContent":["import {\n type JSX,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { loadQuery, usePreloadedQuery } from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\nimport {\n BACKOFFICE_LIST_DEFAULTS,\n BACKOFFICE_LIST_REFETCH_POLICY,\n} from '@plumile/backoffice-core/constants.js';\nimport { stableListVariablesKey } from '@plumile/backoffice-core/state/stableKey.js';\nimport type { BackofficePreparedListDataRoute } from '@plumile/backoffice-core/types.js';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { InlineBanner } from '@plumile/ui/components/feedback/InlineBanner.js';\n\nimport { BackofficeErrorBoundary } from '../components/backoffice/errors/BackofficeErrorBoundary.js';\nimport { BackofficeEntityListScaffold } from '../components/backoffice/scaffolds/BackofficeEntityListScaffold.js';\nimport { BackofficeLazyEntityCountLabel } from '../components/backoffice/refs/BackofficeLazyEntityCount.js';\nimport { useInfiniteConnection } from '../hooks/useInfiniteConnection.js';\nimport { useBackofficeListRefetch } from '../hooks/useBackofficeListRefetch.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeRuntimePaginationFragment } from '../relay/typedRelayHooks.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { useBackofficeEntityListRouteContext } from './BackofficeEntityListRouteContext.js';\n\nexport type BackofficeEntityListDataPageProps = {\n prepared: BackofficePreparedListDataRoute;\n};\n\ntype BackofficeEntityConnectionListDataProps = {\n queryRef: BackofficePreparedListDataRoute['query'];\n};\n\n/**\n * Renders the Relay-backed row data under the list layout route boundary.\n */\nfunction BackofficeEntityConnectionListData({\n queryRef,\n}: BackofficeEntityConnectionListDataProps): JSX.Element | null {\n const {\n config,\n state,\n pushState,\n headerActions,\n columns,\n gridTemplateColumns,\n getRowId,\n countFetchKey,\n bumpCountFetchKey,\n filterDrawerState,\n registerRefresh,\n } = useBackofficeEntityListRouteContext();\n const listConfig = config.list;\n const { t } = useBackofficeReactTranslation();\n\n const queryData = usePreloadedQuery(listConfig.query, queryRef);\n const {\n data: fragmentData,\n loadNext,\n hasNext,\n isLoadingNext,\n refetch,\n } = useBackofficeRuntimePaginationFragment<OperationType>(\n listConfig.fragment,\n queryData,\n );\n\n const connection = listConfig.getConnection(fragmentData);\n\n const rows = useMemo(() => {\n return connection.edges.map((edge) => {\n return listConfig.toRow(edge.node);\n });\n }, [connection.edges, listConfig]);\n\n const { listDefaults } = config;\n const resolvedSort = state.sort ?? listDefaults.sort;\n const { pageSize } = BACKOFFICE_LIST_DEFAULTS;\n\n const baseVariables = useMemo(() => {\n return {\n where: state.where,\n sort: resolvedSort,\n count: pageSize,\n cursor: null,\n };\n }, [pageSize, resolvedSort, state.where]);\n const countVariablesKey = useMemo(() => {\n return stableListVariablesKey(baseVariables);\n }, [baseVariables]);\n const previousCountVariablesKeyRef = useRef(countVariablesKey);\n\n const { isRefreshing, onRefresh } = useBackofficeListRefetch({\n refetch,\n variables: baseVariables,\n defaults: {\n where: listDefaults.where,\n sort: listDefaults.sort,\n count: pageSize,\n cursor: null,\n },\n fetchPolicy: BACKOFFICE_LIST_REFETCH_POLICY,\n buildQueryVariables: listConfig.buildQueryVariables,\n });\n\n useEffect(() => {\n if (previousCountVariablesKeyRef.current === countVariablesKey) {\n return;\n }\n previousCountVariablesKeyRef.current = countVariablesKey;\n bumpCountFetchKey();\n }, [bumpCountFetchKey, countVariablesKey]);\n\n const handleRefresh = useCallback(() => {\n bumpCountFetchKey();\n onRefresh();\n }, [bumpCountFetchKey, onRefresh]);\n\n useEffect(() => {\n registerRefresh(handleRefresh);\n return () => {\n registerRefresh(null);\n };\n }, [handleRefresh, registerRefresh]);\n\n const runLoadMore = useCallback(\n (onComplete: (error: Error | null) => void) => {\n loadNext(pageSize, { onComplete });\n },\n [loadNext, pageSize],\n );\n const pagination = useInfiniteConnection({\n nodes: rows,\n hasNext,\n isLoadingNext,\n runLoadMore,\n surface: `backoffice.entity-list.${config.id}`,\n resetKey: countVariablesKey,\n });\n\n let loadedCountFallback: JSX.Element = <span>{t('common.loading')}</span>;\n if (rows.length > 0) {\n loadedCountFallback = (\n <span>\n {t('list.loaded', {\n count: rows.length,\n })}\n </span>\n );\n }\n const loadedCountLabel = (\n <BackofficeLazyEntityCountLabel\n count={listConfig.count}\n where={state.where}\n fetchKey={countFetchKey}\n loadingFallback={loadedCountFallback}\n >\n {(totalCount) => {\n return (\n <span>\n {t('list.showing', {\n shown: rows.length,\n total: totalCount,\n })}\n </span>\n );\n }}\n </BackofficeLazyEntityCountLabel>\n );\n\n return (\n <BackofficeEntityListScaffold\n config={config}\n state={state}\n pushState={pushState}\n headerActions={headerActions}\n rows={pagination.nodes}\n columns={columns}\n gridTemplateColumns={gridTemplateColumns}\n getRowId={getRowId}\n hasNextPage={pagination.hasNext}\n isLoadingMore={pagination.isLoadingNext}\n incrementalError={pagination.incrementalError}\n isRefreshing={isRefreshing}\n onLoadMore={pagination.loadMoreSafe}\n onRetryLoadMore={pagination.retryLoadMore}\n onRefresh={handleRefresh}\n totalCount={null}\n loadedCountLabel={loadedCountLabel}\n filterDrawerState={filterDrawerState}\n />\n );\n}\n\nexport const BackofficeEntityListDataPage = ({\n prepared,\n}: BackofficeEntityListDataPageProps): JSX.Element | null => {\n const {\n config,\n state,\n pushState,\n headerActions,\n columns,\n gridTemplateColumns,\n getRowId,\n filterDrawerState,\n } = useBackofficeEntityListRouteContext();\n const relayEnvironment = useRelayEnvironment();\n const { t } = useBackofficeReactTranslation();\n const [queryRef, setQueryRef] = useState(() => {\n return prepared.query;\n });\n const ownedQueryRef = useRef<BackofficePreparedListDataRoute['query'] | null>(\n null,\n );\n\n const disposeOwnedQueryRef = useCallback(() => {\n ownedQueryRef.current?.dispose();\n ownedQueryRef.current = null;\n }, []);\n\n useEffect(() => {\n disposeOwnedQueryRef();\n setQueryRef(prepared.query);\n }, [disposeOwnedQueryRef, prepared.query]);\n\n useEffect(() => {\n return () => {\n disposeOwnedQueryRef();\n };\n }, [disposeOwnedQueryRef]);\n\n const reloadInitialQuery = useCallback(() => {\n const listConfig = config.list;\n const { listDefaults } = config;\n const { pageSize } = BACKOFFICE_LIST_DEFAULTS;\n const variablesBase = {\n where: state.where,\n sort: state.sort ?? listDefaults.sort,\n count: pageSize,\n cursor: null,\n };\n const variables = listConfig.buildQueryVariables(variablesBase);\n const nextQueryRef = loadQuery<OperationType>(\n relayEnvironment,\n listConfig.query,\n variables,\n {\n fetchPolicy: 'network-only',\n },\n );\n disposeOwnedQueryRef();\n ownedQueryRef.current = nextQueryRef;\n setQueryRef(nextQueryRef);\n }, [config, disposeOwnedQueryRef, relayEnvironment, state.sort, state.where]);\n\n return (\n <BackofficeErrorBoundary\n fallback={({ reset }) => {\n return (\n <BackofficeEntityListScaffold\n config={config}\n state={state}\n pushState={pushState}\n headerActions={headerActions}\n rows={[]}\n columns={columns}\n gridTemplateColumns={gridTemplateColumns}\n getRowId={getRowId}\n hasNextPage={false}\n isLoadingMore={false}\n incrementalError={null}\n isRefreshing={false}\n onLoadMore={() => {}}\n onRetryLoadMore={() => {}}\n onRefresh={() => {\n reset();\n reloadInitialQuery();\n }}\n totalCount={null}\n filterDrawerState={filterDrawerState}\n emptyState={\n <InlineBanner\n tone=\"danger\"\n title={t('list.errors.title')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n reset();\n reloadInitialQuery();\n }}\n >\n {t('list.actions.retry')}\n </Button>\n }\n >\n {t('list.errors.tableFailed')}\n </InlineBanner>\n }\n />\n );\n }}\n >\n <BackofficeEntityConnectionListData queryRef={queryRef} />\n </BackofficeErrorBoundary>\n );\n};\n\nexport default BackofficeEntityListDataPage;\n"],"mappings":"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"}
|
|
@@ -124,8 +124,10 @@ var F = (e, t, n, r) => {
|
|
|
124
124
|
getRowId: W,
|
|
125
125
|
hasNextPage: !1,
|
|
126
126
|
isLoadingMore: !1,
|
|
127
|
+
incrementalError: null,
|
|
127
128
|
isRefreshing: !1,
|
|
128
129
|
onLoadMore: () => {},
|
|
130
|
+
onRetryLoadMore: () => {},
|
|
129
131
|
onRefresh: Y,
|
|
130
132
|
totalCount: null,
|
|
131
133
|
isLoadingInitial: !0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeEntityListPage.js","names":[],"sources":["../../../src/pages/BackofficeEntityListPage.tsx"],"sourcesContent":["import {\n Suspense,\n type JSX,\n type ReactNode,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport Link from '@plumile/router/routing/Link.js';\nimport type {\n BackofficeEntityManifestItem,\n BackofficePreparedListLayoutRoute,\n BackofficeRuntimeResolvedListFacetConfig,\n BackofficeRowFlagSpec,\n} from '@plumile/backoffice-core/types.js';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { LinkButton } from '@plumile/ui/atomic/atoms/button/LinkButton.js';\nimport {\n type DataTableColumn,\n type GetRowId,\n} from '@plumile/ui/components/data-table/DataTable.js';\nimport { TableCell } from '@plumile/ui/components/data-table/TableCell.js';\nimport { EyeSvg } from '@plumile/ui/icons/EyeSvg.js';\nimport { BackofficeEntityListScaffold } from '../components/backoffice/scaffolds/BackofficeEntityListScaffold.js';\nimport { LazyBackofficeEntityActionFormDialog } from '../components/backoffice/actions/LazyBackofficeEntityActionFormDialog.js';\nimport { buildDataTableColumns } from '../components/backoffice/columns/buildDataTableColumns.js';\nimport { RowFlagsCell } from '../components/backoffice/list/RowFlagsCell.js';\nimport { useBackofficeListUrlState } from '../hooks/useBackofficeListUrlState.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport {\n createBackofficeEntityListUiStateKey,\n useBackofficeListFilterDrawerState,\n} from '../provider/BackofficeListUiStateContext.js';\nimport * as pageStyles from './backofficeEntityListPage.css.js';\nimport { rowFlagsColumnCell } from '../components/backoffice/list/RowFlagsCell.css.js';\nimport { BackofficeRightPageLayout } from '../components/backoffice/layout/breadcrumb/BackofficeRightPageLayout.js';\nimport { buildEntityListBreadcrumb } from '../components/backoffice/layout/breadcrumb/buildBreadcrumbs.js';\nimport { BackofficeEntityListRouteProvider } from './BackofficeEntityListRouteContext.js';\nimport {\n buildActionsColumn,\n computeActionsColumnWidthPx,\n computeRowFlagsColumnWidthPx,\n isFormMutationAction,\n isRouteAction,\n resolveLabel,\n resolveActionVariant,\n resolveTrackBySize,\n type ConnectionListConfig,\n} from './BackofficeEntityListPage.helpers.js';\n\nexport type BackofficeEntityListPageProps = {\n children?: ReactNode;\n entityManifest: BackofficeEntityManifestItem;\n config: BackofficeRuntimeResolvedListFacetConfig;\n prepared: BackofficePreparedListLayoutRoute;\n};\n\nconst applyListEdgeColumns = <Row,>(\n inputColumns: readonly DataTableColumn<Row>[],\n rowFlags: readonly BackofficeRowFlagSpec<Row>[] | undefined,\n actionCount: number,\n tApp: TFunction,\n): {\n columns: readonly DataTableColumn<Row>[];\n gridTemplateColumns?: string;\n} => {\n const hasFlags = rowFlags != null && rowFlags.length > 0;\n\n let columns = inputColumns;\n if (hasFlags) {\n const flagsColumn: DataTableColumn<Row> = {\n id: '__rowFlags',\n header: '',\n className: rowFlagsColumnCell,\n mobileRole: 'badge',\n cell: (row) => {\n return <RowFlagsCell row={row} flags={rowFlags} tApp={tApp} />;\n },\n };\n\n // Ensure we never pick the flags column as \"primary\".\n const withFlags = [flagsColumn, ...inputColumns];\n const hasPrimary = withFlags.some((col) => {\n return col.isPrimary === true;\n });\n\n columns = withFlags;\n if (!hasPrimary) {\n columns = withFlags.map((col, index) => {\n if (index === 1) {\n return { ...col, isPrimary: true };\n }\n return col;\n });\n }\n }\n\n let flagCount = 0;\n if (hasFlags) {\n flagCount = rowFlags.length;\n }\n const flagsWidthPx = computeRowFlagsColumnWidthPx(flagCount);\n const actionsWidthPx = computeActionsColumnWidthPx(actionCount);\n\n // We always include the right-side \"actions\" column in list pages.\n let leftColumnCount = 0;\n if (hasFlags) {\n leftColumnCount = 1;\n }\n const middleCount = columns.length - leftColumnCount - 1;\n\n const middleTracks = columns\n .slice(leftColumnCount, leftColumnCount + Math.max(0, middleCount))\n .map((column) => {\n return resolveTrackBySize(column as DataTableColumn<unknown>, '1fr');\n })\n .join(' ');\n\n let gridTemplateColumns = '';\n if (hasFlags) {\n gridTemplateColumns = `${flagsWidthPx}px ${middleTracks} ${actionsWidthPx}px`;\n } else {\n gridTemplateColumns = `${middleTracks} ${actionsWidthPx}px`;\n }\n\n return { columns, gridTemplateColumns };\n};\n\nconst BackofficeEntityConnectionListPage = ({\n children,\n config,\n breadcrumb,\n}: Omit<BackofficeEntityListPageProps, 'config' | 'prepared'> & {\n config: ConnectionListConfig;\n breadcrumb: ReturnType<typeof buildEntityListBreadcrumb>;\n}): JSX.Element | null => {\n const listConfig = config.list;\n\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const [activeFormActionId, setActiveFormActionId] = useState<string | null>(\n null,\n );\n const [countFetchKey, setCountFetchKey] = useState(0);\n const refreshRef = useRef<(() => void) | null>(null);\n\n const registerRefresh = useCallback((refresh: (() => void) | null) => {\n refreshRef.current = refresh;\n }, []);\n\n const { columns, gridTemplateColumns } = useMemo((): {\n columns: readonly DataTableColumn<unknown>[];\n gridTemplateColumns?: string;\n } => {\n const baseColumns = buildDataTableColumns(listConfig.columns, {\n tApp,\n t,\n });\n const actionsColumn = buildActionsColumn({\n ariaLabel: t('actions.view'),\n fallback: t('common.notAvailable'),\n className: pageStyles.actionsColumnCell,\n resolveDetailHref: (id) => {\n return config.routes.detail(id);\n },\n renderAction: ({ href, ariaLabel }) => {\n return (\n <TableCell.Actions>\n <Link\n to={href}\n className={pageStyles.actionTrigger}\n aria-label={ariaLabel}\n title={ariaLabel}\n preloadOnHover=\"code\"\n >\n <EyeSvg width={16} height={16} />\n </Link>\n </TableCell.Actions>\n );\n },\n });\n const allColumns = [...baseColumns, actionsColumn];\n return applyListEdgeColumns(allColumns, listConfig.rowFlags, 1, tApp);\n }, [config.routes, listConfig.columns, listConfig.rowFlags, t, tApp]);\n\n const getRowId = useCallback<GetRowId<unknown>>(\n (row) => {\n return listConfig.getRowId(row);\n },\n [listConfig],\n );\n\n const { state, pushState } = useBackofficeListUrlState(config);\n const listUiStateKey = useMemo(() => {\n return createBackofficeEntityListUiStateKey(config.id);\n }, [config.id]);\n const filterDrawerState = useBackofficeListFilterDrawerState(listUiStateKey);\n\n const handleRefreshRequest = useCallback(() => {\n setCountFetchKey((current) => {\n return current + 1;\n });\n refreshRef.current?.();\n }, []);\n\n const listActions = useMemo(() => {\n return config.listActions ?? [];\n }, [config.listActions]);\n const visibleActions = useMemo(() => {\n return listActions.filter((action) => {\n if (action.isVisible == null) {\n return true;\n }\n return action.isVisible(null);\n });\n }, [listActions]);\n\n const headerActions = useMemo(() => {\n if (visibleActions.length === 0) {\n return undefined;\n }\n return (\n <div className={pageStyles.headerActions}>\n {visibleActions.map((action, index) => {\n const { variant: actionVariant } = action;\n const label = resolveLabel(action.label, tApp);\n let ariaLabel = label;\n if (action.ariaLabel != null) {\n ariaLabel = resolveLabel(action.ariaLabel, tApp);\n }\n const variant = resolveActionVariant(actionVariant, index);\n const size = action.size ?? 'small';\n const isDisabled = action.isDisabled?.(null) === true;\n\n if (isRouteAction(action)) {\n const href = action.to(null);\n return (\n <LinkButton\n key={action.id}\n to={href}\n variant={variant}\n size={size}\n isDisabled={isDisabled}\n aria-label={ariaLabel}\n preloadOnHover=\"code-and-data\"\n >\n {label}\n </LinkButton>\n );\n }\n\n if (isFormMutationAction(action)) {\n return (\n <Button\n key={action.id}\n type=\"button\"\n variant={variant}\n size={size}\n disabled={isDisabled}\n onClick={() => {\n setActiveFormActionId(action.id);\n }}\n aria-label={ariaLabel}\n >\n {label}\n </Button>\n );\n }\n\n return null;\n })}\n </div>\n );\n }, [tApp, visibleActions]);\n\n const activeFormAction = listActions.find((action) => {\n return action.id === activeFormActionId;\n });\n\n const renderLoadingScaffold = () => {\n return (\n <BackofficeEntityListScaffold\n config={config}\n state={state}\n pushState={pushState}\n headerActions={headerActions}\n rows={[]}\n columns={columns}\n gridTemplateColumns={gridTemplateColumns}\n getRowId={getRowId}\n hasNextPage={false}\n isLoadingMore={false}\n isRefreshing={false}\n onLoadMore={() => {}}\n onRefresh={handleRefreshRequest}\n totalCount={null}\n isLoadingInitial\n filterDrawerState={filterDrawerState}\n />\n );\n };\n\n const contextValue = useMemo(() => {\n return {\n config,\n state,\n pushState,\n headerActions,\n columns,\n gridTemplateColumns,\n getRowId,\n countFetchKey,\n filterDrawerState,\n bumpCountFetchKey: () => {\n setCountFetchKey((current) => {\n return current + 1;\n });\n },\n registerRefresh,\n };\n }, [\n columns,\n config,\n countFetchKey,\n filterDrawerState,\n getRowId,\n gridTemplateColumns,\n headerActions,\n pushState,\n registerRefresh,\n state,\n ]);\n\n return (\n <BackofficeRightPageLayout breadcrumb={breadcrumb}>\n <BackofficeEntityListRouteProvider value={contextValue}>\n <Suspense fallback={renderLoadingScaffold()}>{children}</Suspense>\n </BackofficeEntityListRouteProvider>\n {activeFormAction != null && isFormMutationAction(activeFormAction) && (\n <LazyBackofficeEntityActionFormDialog\n isOpen\n action={activeFormAction}\n node={null}\n onClose={() => {\n setActiveFormActionId(null);\n }}\n onSuccess={handleRefreshRequest}\n />\n )}\n </BackofficeRightPageLayout>\n );\n};\n\nexport const BackofficeEntityListPage = ({\n children,\n entityManifest,\n config,\n}: BackofficeEntityListPageProps): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const breadcrumb = buildEntityListBreadcrumb(config, tApp);\n\n return (\n <BackofficeEntityConnectionListPage\n children={children}\n entityManifest={entityManifest}\n config={config}\n breadcrumb={breadcrumb}\n />\n );\n};\n\nexport default BackofficeEntityListPage;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BackofficeEntityListPage.js","names":[],"sources":["../../../src/pages/BackofficeEntityListPage.tsx"],"sourcesContent":["import {\n Suspense,\n type JSX,\n type ReactNode,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport Link from '@plumile/router/routing/Link.js';\nimport type {\n BackofficeEntityManifestItem,\n BackofficePreparedListLayoutRoute,\n BackofficeRuntimeResolvedListFacetConfig,\n BackofficeRowFlagSpec,\n} from '@plumile/backoffice-core/types.js';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { LinkButton } from '@plumile/ui/atomic/atoms/button/LinkButton.js';\nimport {\n type DataTableColumn,\n type GetRowId,\n} from '@plumile/ui/components/data-table/DataTable.js';\nimport { TableCell } from '@plumile/ui/components/data-table/TableCell.js';\nimport { EyeSvg } from '@plumile/ui/icons/EyeSvg.js';\nimport { BackofficeEntityListScaffold } from '../components/backoffice/scaffolds/BackofficeEntityListScaffold.js';\nimport { LazyBackofficeEntityActionFormDialog } from '../components/backoffice/actions/LazyBackofficeEntityActionFormDialog.js';\nimport { buildDataTableColumns } from '../components/backoffice/columns/buildDataTableColumns.js';\nimport { RowFlagsCell } from '../components/backoffice/list/RowFlagsCell.js';\nimport { useBackofficeListUrlState } from '../hooks/useBackofficeListUrlState.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport {\n createBackofficeEntityListUiStateKey,\n useBackofficeListFilterDrawerState,\n} from '../provider/BackofficeListUiStateContext.js';\nimport * as pageStyles from './backofficeEntityListPage.css.js';\nimport { rowFlagsColumnCell } from '../components/backoffice/list/RowFlagsCell.css.js';\nimport { BackofficeRightPageLayout } from '../components/backoffice/layout/breadcrumb/BackofficeRightPageLayout.js';\nimport { buildEntityListBreadcrumb } from '../components/backoffice/layout/breadcrumb/buildBreadcrumbs.js';\nimport { BackofficeEntityListRouteProvider } from './BackofficeEntityListRouteContext.js';\nimport {\n buildActionsColumn,\n computeActionsColumnWidthPx,\n computeRowFlagsColumnWidthPx,\n isFormMutationAction,\n isRouteAction,\n resolveLabel,\n resolveActionVariant,\n resolveTrackBySize,\n type ConnectionListConfig,\n} from './BackofficeEntityListPage.helpers.js';\n\nexport type BackofficeEntityListPageProps = {\n children?: ReactNode;\n entityManifest: BackofficeEntityManifestItem;\n config: BackofficeRuntimeResolvedListFacetConfig;\n prepared: BackofficePreparedListLayoutRoute;\n};\n\nconst applyListEdgeColumns = <Row,>(\n inputColumns: readonly DataTableColumn<Row>[],\n rowFlags: readonly BackofficeRowFlagSpec<Row>[] | undefined,\n actionCount: number,\n tApp: TFunction,\n): {\n columns: readonly DataTableColumn<Row>[];\n gridTemplateColumns?: string;\n} => {\n const hasFlags = rowFlags != null && rowFlags.length > 0;\n\n let columns = inputColumns;\n if (hasFlags) {\n const flagsColumn: DataTableColumn<Row> = {\n id: '__rowFlags',\n header: '',\n className: rowFlagsColumnCell,\n mobileRole: 'badge',\n cell: (row) => {\n return <RowFlagsCell row={row} flags={rowFlags} tApp={tApp} />;\n },\n };\n\n // Ensure we never pick the flags column as \"primary\".\n const withFlags = [flagsColumn, ...inputColumns];\n const hasPrimary = withFlags.some((col) => {\n return col.isPrimary === true;\n });\n\n columns = withFlags;\n if (!hasPrimary) {\n columns = withFlags.map((col, index) => {\n if (index === 1) {\n return { ...col, isPrimary: true };\n }\n return col;\n });\n }\n }\n\n let flagCount = 0;\n if (hasFlags) {\n flagCount = rowFlags.length;\n }\n const flagsWidthPx = computeRowFlagsColumnWidthPx(flagCount);\n const actionsWidthPx = computeActionsColumnWidthPx(actionCount);\n\n // We always include the right-side \"actions\" column in list pages.\n let leftColumnCount = 0;\n if (hasFlags) {\n leftColumnCount = 1;\n }\n const middleCount = columns.length - leftColumnCount - 1;\n\n const middleTracks = columns\n .slice(leftColumnCount, leftColumnCount + Math.max(0, middleCount))\n .map((column) => {\n return resolveTrackBySize(column as DataTableColumn<unknown>, '1fr');\n })\n .join(' ');\n\n let gridTemplateColumns = '';\n if (hasFlags) {\n gridTemplateColumns = `${flagsWidthPx}px ${middleTracks} ${actionsWidthPx}px`;\n } else {\n gridTemplateColumns = `${middleTracks} ${actionsWidthPx}px`;\n }\n\n return { columns, gridTemplateColumns };\n};\n\nconst BackofficeEntityConnectionListPage = ({\n children,\n config,\n breadcrumb,\n}: Omit<BackofficeEntityListPageProps, 'config' | 'prepared'> & {\n config: ConnectionListConfig;\n breadcrumb: ReturnType<typeof buildEntityListBreadcrumb>;\n}): JSX.Element | null => {\n const listConfig = config.list;\n\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const [activeFormActionId, setActiveFormActionId] = useState<string | null>(\n null,\n );\n const [countFetchKey, setCountFetchKey] = useState(0);\n const refreshRef = useRef<(() => void) | null>(null);\n\n const registerRefresh = useCallback((refresh: (() => void) | null) => {\n refreshRef.current = refresh;\n }, []);\n\n const { columns, gridTemplateColumns } = useMemo((): {\n columns: readonly DataTableColumn<unknown>[];\n gridTemplateColumns?: string;\n } => {\n const baseColumns = buildDataTableColumns(listConfig.columns, {\n tApp,\n t,\n });\n const actionsColumn = buildActionsColumn({\n ariaLabel: t('actions.view'),\n fallback: t('common.notAvailable'),\n className: pageStyles.actionsColumnCell,\n resolveDetailHref: (id) => {\n return config.routes.detail(id);\n },\n renderAction: ({ href, ariaLabel }) => {\n return (\n <TableCell.Actions>\n <Link\n to={href}\n className={pageStyles.actionTrigger}\n aria-label={ariaLabel}\n title={ariaLabel}\n preloadOnHover=\"code\"\n >\n <EyeSvg width={16} height={16} />\n </Link>\n </TableCell.Actions>\n );\n },\n });\n const allColumns = [...baseColumns, actionsColumn];\n return applyListEdgeColumns(allColumns, listConfig.rowFlags, 1, tApp);\n }, [config.routes, listConfig.columns, listConfig.rowFlags, t, tApp]);\n\n const getRowId = useCallback<GetRowId<unknown>>(\n (row) => {\n return listConfig.getRowId(row);\n },\n [listConfig],\n );\n\n const { state, pushState } = useBackofficeListUrlState(config);\n const listUiStateKey = useMemo(() => {\n return createBackofficeEntityListUiStateKey(config.id);\n }, [config.id]);\n const filterDrawerState = useBackofficeListFilterDrawerState(listUiStateKey);\n\n const handleRefreshRequest = useCallback(() => {\n setCountFetchKey((current) => {\n return current + 1;\n });\n refreshRef.current?.();\n }, []);\n\n const listActions = useMemo(() => {\n return config.listActions ?? [];\n }, [config.listActions]);\n const visibleActions = useMemo(() => {\n return listActions.filter((action) => {\n if (action.isVisible == null) {\n return true;\n }\n return action.isVisible(null);\n });\n }, [listActions]);\n\n const headerActions = useMemo(() => {\n if (visibleActions.length === 0) {\n return undefined;\n }\n return (\n <div className={pageStyles.headerActions}>\n {visibleActions.map((action, index) => {\n const { variant: actionVariant } = action;\n const label = resolveLabel(action.label, tApp);\n let ariaLabel = label;\n if (action.ariaLabel != null) {\n ariaLabel = resolveLabel(action.ariaLabel, tApp);\n }\n const variant = resolveActionVariant(actionVariant, index);\n const size = action.size ?? 'small';\n const isDisabled = action.isDisabled?.(null) === true;\n\n if (isRouteAction(action)) {\n const href = action.to(null);\n return (\n <LinkButton\n key={action.id}\n to={href}\n variant={variant}\n size={size}\n isDisabled={isDisabled}\n aria-label={ariaLabel}\n preloadOnHover=\"code-and-data\"\n >\n {label}\n </LinkButton>\n );\n }\n\n if (isFormMutationAction(action)) {\n return (\n <Button\n key={action.id}\n type=\"button\"\n variant={variant}\n size={size}\n disabled={isDisabled}\n onClick={() => {\n setActiveFormActionId(action.id);\n }}\n aria-label={ariaLabel}\n >\n {label}\n </Button>\n );\n }\n\n return null;\n })}\n </div>\n );\n }, [tApp, visibleActions]);\n\n const activeFormAction = listActions.find((action) => {\n return action.id === activeFormActionId;\n });\n\n const renderLoadingScaffold = () => {\n return (\n <BackofficeEntityListScaffold\n config={config}\n state={state}\n pushState={pushState}\n headerActions={headerActions}\n rows={[]}\n columns={columns}\n gridTemplateColumns={gridTemplateColumns}\n getRowId={getRowId}\n hasNextPage={false}\n isLoadingMore={false}\n incrementalError={null}\n isRefreshing={false}\n onLoadMore={() => {}}\n onRetryLoadMore={() => {}}\n onRefresh={handleRefreshRequest}\n totalCount={null}\n isLoadingInitial\n filterDrawerState={filterDrawerState}\n />\n );\n };\n\n const contextValue = useMemo(() => {\n return {\n config,\n state,\n pushState,\n headerActions,\n columns,\n gridTemplateColumns,\n getRowId,\n countFetchKey,\n filterDrawerState,\n bumpCountFetchKey: () => {\n setCountFetchKey((current) => {\n return current + 1;\n });\n },\n registerRefresh,\n };\n }, [\n columns,\n config,\n countFetchKey,\n filterDrawerState,\n getRowId,\n gridTemplateColumns,\n headerActions,\n pushState,\n registerRefresh,\n state,\n ]);\n\n return (\n <BackofficeRightPageLayout breadcrumb={breadcrumb}>\n <BackofficeEntityListRouteProvider value={contextValue}>\n <Suspense fallback={renderLoadingScaffold()}>{children}</Suspense>\n </BackofficeEntityListRouteProvider>\n {activeFormAction != null && isFormMutationAction(activeFormAction) && (\n <LazyBackofficeEntityActionFormDialog\n isOpen\n action={activeFormAction}\n node={null}\n onClose={() => {\n setActiveFormActionId(null);\n }}\n onSuccess={handleRefreshRequest}\n />\n )}\n </BackofficeRightPageLayout>\n );\n};\n\nexport const BackofficeEntityListPage = ({\n children,\n entityManifest,\n config,\n}: BackofficeEntityListPageProps): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const breadcrumb = buildEntityListBreadcrumb(config, tApp);\n\n return (\n <BackofficeEntityConnectionListPage\n children={children}\n entityManifest={entityManifest}\n config={config}\n breadcrumb={breadcrumb}\n />\n );\n};\n\nexport default BackofficeEntityListPage;\n"],"mappings":"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"}
|
|
@@ -7,18 +7,18 @@ import { BackofficePermissionsProvider as o } from "../components/backoffice/lay
|
|
|
7
7
|
import { buildSidebarSections as s } from "../components/backoffice/layout/buildSidebarSections.js";
|
|
8
8
|
import te from "../components/backoffice/layout/mapViewerToSidebarProfileView.js";
|
|
9
9
|
import { BackofficeContentBoundary as ne } from "../components/backoffice/routing/BackofficeContentBoundary.js";
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import ae from "../hooks/
|
|
13
|
-
import oe from "
|
|
14
|
-
import { useCallback as se, useContext as ce, useEffect as c, useMemo as l, useState as u } from "react";
|
|
10
|
+
import { useRelayEnvironment as re } from "../relay/useRelayEnvironment.js";
|
|
11
|
+
import ie from "../hooks/useBackofficeSidebarPins.js";
|
|
12
|
+
import ae from "../hooks/useSidebarGroupCollapse.js";
|
|
13
|
+
import { useCallback as oe, useContext as se, useEffect as c, useMemo as l, useState as u } from "react";
|
|
15
14
|
import { jsx as d } from "react/jsx-runtime";
|
|
16
|
-
import { useTranslation as
|
|
17
|
-
import { commitMutation as
|
|
18
|
-
import { ToastProvider as
|
|
19
|
-
import
|
|
20
|
-
import { GlobalSearchInput as
|
|
21
|
-
import
|
|
15
|
+
import { useTranslation as ce } from "react-i18next";
|
|
16
|
+
import { commitMutation as le, usePreloadedQuery as f } from "react-relay";
|
|
17
|
+
import { ToastProvider as ue } from "@plumile/ui/atomic/molecules/toast/ToastProvider.js";
|
|
18
|
+
import de from "@plumile/router/routing/RoutingContext.js";
|
|
19
|
+
import { GlobalSearchInput as fe } from "@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js";
|
|
20
|
+
import pe from "@plumile/router/routing/useLocation.js";
|
|
21
|
+
import { resetRelayStore as me } from "@plumile/relay/environment.js";
|
|
22
22
|
import { AdminShellLayout as he } from "@plumile/ui/admin/templates/admin_shell_layout/AdminShellLayout.js";
|
|
23
23
|
import { SidebarProfileMenu as p } from "@plumile/ui/components/navigation/sidebar/SidebarProfileMenu.js";
|
|
24
24
|
//#region src/pages/BackofficeLayoutPage.tsx
|
|
@@ -41,7 +41,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
41
41
|
window.localStorage.setItem(e, JSON.stringify(t));
|
|
42
42
|
} catch {}
|
|
43
43
|
}, m = ({ children: f, permissions: m, authStatus: h, activeGroupId: g }) => {
|
|
44
|
-
let { t: _ } =
|
|
44
|
+
let { t: _ } = ce(), { t: v } = t(), { pathname: y } = pe(), b = se(de), x = re(), { auth: S, basePath: C, dashboards: w, entities: T, sidebar: E } = n(), [D, be] = u(""), O = E?.preferences?.storageKey ?? _e, k = E?.preferences?.persistCollapsed === !0, [A, xe] = u(() => {
|
|
45
45
|
if (!k || typeof window > "u") return !1;
|
|
46
46
|
try {
|
|
47
47
|
return window.localStorage.getItem(`${O}:collapsed`) === "true";
|
|
@@ -89,7 +89,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
89
89
|
L,
|
|
90
90
|
_
|
|
91
91
|
]);
|
|
92
|
-
let H = E?.pinnedItems?.enabled === !0, { pins: Ee, toggle: De, reorder: Oe } =
|
|
92
|
+
let H = E?.pinnedItems?.enabled === !0, { pins: Ee, toggle: De, reorder: Oe } = ie({
|
|
93
93
|
enabled: H,
|
|
94
94
|
storageKey: E?.pinnedItems?.storageKey,
|
|
95
95
|
visibleEntityIds: Te
|
|
@@ -97,7 +97,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
97
97
|
H && (U = Ee, W = De, G = Oe);
|
|
98
98
|
let K;
|
|
99
99
|
E?.preferences?.storageKey != null && (K = `${E.preferences.storageKey}:groups`);
|
|
100
|
-
let { collapsedByGroupId: q, setCollapsed: J } =
|
|
100
|
+
let { collapsedByGroupId: q, setCollapsed: J } = ae({
|
|
101
101
|
groupIds: Ce,
|
|
102
102
|
activeGroupId: g,
|
|
103
103
|
defaultCollapsedByGroupId: we,
|
|
@@ -169,12 +169,12 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
169
169
|
W,
|
|
170
170
|
v,
|
|
171
171
|
_
|
|
172
|
-
]), Y =
|
|
172
|
+
]), Y = oe(() => {
|
|
173
173
|
j || (M(!0), (async () => {
|
|
174
174
|
try {
|
|
175
175
|
let t = await S.logout.load();
|
|
176
176
|
await new Promise((e, n) => {
|
|
177
|
-
|
|
177
|
+
le(x, {
|
|
178
178
|
mutation: t.logoutMutation,
|
|
179
179
|
variables: {},
|
|
180
180
|
onCompleted: () => {
|
|
@@ -184,7 +184,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
184
184
|
n(e);
|
|
185
185
|
}
|
|
186
186
|
});
|
|
187
|
-
}), localStorage.removeItem("auth_token"), localStorage.removeItem("remember_me"),
|
|
187
|
+
}), localStorage.removeItem("auth_token"), localStorage.removeItem("remember_me"), me(), b?.history.push({ pathname: e(C) });
|
|
188
188
|
} finally {
|
|
189
189
|
M(!1);
|
|
190
190
|
}
|
|
@@ -220,13 +220,13 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
|
|
|
220
220
|
isSigningOut: j
|
|
221
221
|
}), Q = null;
|
|
222
222
|
N != null && (Q = /* @__PURE__ */ d(ne, { children: f }));
|
|
223
|
-
let $ = /* @__PURE__ */ d(
|
|
223
|
+
let $ = /* @__PURE__ */ d(fe, {
|
|
224
224
|
value: D,
|
|
225
225
|
onChange: be,
|
|
226
226
|
placeholder: v("sidebar.search.placeholder"),
|
|
227
227
|
ariaLabel: v("sidebar.search.placeholder")
|
|
228
228
|
});
|
|
229
|
-
return /* @__PURE__ */ d(
|
|
229
|
+
return /* @__PURE__ */ d(ue, { children: /* @__PURE__ */ d(he, {
|
|
230
230
|
sidebar: {
|
|
231
231
|
sections: ke,
|
|
232
232
|
search: $,
|
|
@@ -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 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 { GlobalSearchInput } from '@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js';\nimport { SidebarProfileMenu } from '@plumile/ui/components/navigation/sidebar/SidebarProfileMenu.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 dashboards,\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 pinningEnabled = sidebar?.pinnedItems?.enabled === true;\n\n const {\n pins,\n toggle: togglePin,\n reorder: reorderPin,\n } = useBackofficeSidebarPins({\n enabled: pinningEnabled,\n storageKey: sidebar?.pinnedItems?.storageKey,\n visibleEntityIds,\n });\n\n let sidebarPinnedEntityIds: readonly string[] | undefined;\n let sidebarTogglePin: ((entityId: string) => void) | undefined;\n let sidebarReorderPin: ((fromId: string, toId: string) => void) | undefined;\n if (pinningEnabled) {\n sidebarPinnedEntityIds = pins;\n sidebarTogglePin = togglePin;\n sidebarReorderPin = reorderPin;\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 dashboards,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: sidebarPinnedEntityIds,\n recentItems,\n onTogglePin: sidebarTogglePin,\n onReorderPin: sidebarReorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n dashboards,\n pathname,\n permissions,\n recentItems,\n setCollapsed,\n sidebar,\n sidebarPinnedEntityIds,\n sidebarQuery,\n sidebarReorderPin,\n sidebarTogglePin,\n t,\n tApp,\n ]);\n\n const mobileSections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n dashboards,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: sidebarPinnedEntityIds,\n recentItems,\n onTogglePin: sidebarTogglePin,\n onReorderPin: sidebarReorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n dashboards,\n pathname,\n permissions,\n recentItems,\n setCollapsed,\n sidebar,\n sidebarPinnedEntityIds,\n sidebarQuery,\n sidebarReorderPin,\n sidebarTogglePin,\n t,\n tApp,\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 <SidebarProfileMenu\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 <SidebarProfileMenu\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 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 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 contentScrollMode=\"contained\"\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":";;;;;;;;;;;;;;;;;;;;;;;;AAwEA,IAAM,KAAmC,mCACnC,KAAoC,8BAEpC,MACJ,MAC2C;CAC3C,IAAI,OAAO,SAAW,KACpB,OAAO,CAAC;CAEV,IAAI;EACF,IAAM,IAAM,OAAO,aAAa,QAAQ,CAAU;EAClD,IAAI,KAAO,MACT,OAAO,CAAC;EAEV,IAAM,IAAS,KAAK,MAAM,CAAG;EAI7B,OAHK,MAAM,QAAQ,CAAM,IAGlB,EAAO,QAAQ,MAA8C;GAClE,IAAoB,OAAO,KAAS,aAAhC,GACF,OAAO;GAET,IAAM,IAAY;GAClB,QACG,EAAU,SAAS,YAAY,EAAU,SAAS,WACnD,OAAO,EAAU,MAAO,YACxB,OAAO,EAAU,SAAU,YAC3B,OAAO,EAAU,QAAS,YAC1B,OAAO,EAAU,aAAc;EAEnC,CAAC,IAdQ,CAAC;CAeZ,QAAQ;EACN,OAAO,CAAC;CACV;AACF,GAEM,MACJ,GACA,MACS;CACL,aAAO,SAAW,MAGtB,IAAI;EACF,OAAO,aAAa,QAAQ,GAAY,KAAK,UAAU,CAAK,CAAC;CAC/D,QAAQ,CAER;AACF,GAEM,KAAyB,EAC7B,aACA,gBACA,eACA,uBACmC;CACnC,IAAM,EAAE,GAAG,MAAS,GAAe,GAC7B,EAAE,SAAM,EAA8B,GACtC,EAAE,gBAAa,GAAY,GAC3B,IAAU,GAAW,EAAc,GACnC,IAAmB,GAAoB,GACvC,EACJ,MAAM,GACN,aACA,eACA,aACA,eACE,EAAoB,GAClB,CAAC,GAAc,MAAmB,EAAS,EAAE,GAC7C,IACJ,GAAS,aAAa,cAAc,IAChC,IACJ,GAAS,aAAa,qBAAqB,IACvC,CAAC,GAAoB,MAAyB,QAAe;EACjE,IAAI,CAAC,KAA2B,OAAO,SAAW,KAChD,OAAO;EAET,IAAI;GACF,OACE,OAAO,aAAa,QAClB,GAAG,EAA6B,WAClC,MAAM;EAEV,QAAQ;GACN,OAAO;EACT;CACF,CAAC,GACK,CAAC,GAAc,KAAmB,EAAS,EAAK,GAChD,CAAC,GAAc,KAAmB,EAAgC,IAAI,GACtE,IAAoB,GAAS,aAC7B,IAAqB,GAAmB,YAAY,IACpD,IACJ,GAAmB,cAAc,IAC7B,IAAsB,GAAmB,YAAY,GACrD,CAAC,GAAa,MAAkB,QAG/B,IAGE,GAAgB,CAAqB,IAFnC,CAAC,CAGX;CAED,QAAgB;EACV,OAAC,KAA2B,OAAO,SAAW,MAGlD,IAAI;GACF,OAAO,aAAa,QAClB,GAAG,EAA6B,aAChC,OAAO,CAAkB,CAC3B;EACF,QAAQ,CAER;CACF,GAAG;EACD;EACA;EACA;CACF,CAAC;CAED,IAAM,IAAS,QACN,EAAqB,GAAU,CAAO,GAC5C,CAAC,GAAU,CAAO,CAAC,GAEhB,KAAW,QACR,OAAO,KAAK,CAAM,GACxB,CAAC,CAAM,CAAC,GAEL,KAA4B,QACzB,OAAO,YACZ,OAAO,QAAQ,CAAM,CAAC,CAAC,KAAK,CAAC,GAAS,OAC7B,CAAC,GAAS,EAAM,UAAU,oBAAoB,EAAI,CAC1D,CACH,GACC,CAAC,CAAM,CAAC,GAEL,KAAmB,QAChB,GAAwB,GAAQ,GAAU,GAAS,CAAW,GACpE;EAAC;EAAU;EAAQ;EAAa;CAAO,CAAC,GAErC,IAAiB,QACd,EAAsB,GAAU,CAAQ,GAC9C,CAAC,GAAU,CAAQ,CAAC;CAEvB,QAAgB;EACd,IAAI,CAAC,KAAsB,KAAkB,MAC3C;EAEF,IAAM,IAAS,EAAS;EAIxB,IAHI,KAAU,QAGV,EAAO,SAAS,UAAU,CAAC,EAAO,SACpC;EAEF,IAAM,IAAO,EAAO,OAAO,MACvB,IAA4C;EAChD,AAAI,EAAO,SAAS,WAClB,IAAO;EAET,IAAM,IAAoC;GACxC;GACA,IAAI;GACJ,OAAO,EAAO,MAAM,CAAI;GACxB;GACA,WAAW,KAAK,IAAI;EACtB;EACA,IAAgB,MAAS;GACvB,IAAM,IAAO,CACX,GACA,GAAG,EAAK,QAAQ,MACP,EAAM,OAAO,EAAK,MAAM,EAAM,SAAS,EAAK,IACpD,CACH,CAAC,CAAC,MAAM,GAAG,CAAmB;GAE9B,OADA,GAAiB,GAAuB,CAAI,GACrC;EACT,CAAC;CACH,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,IAAM,IAAiB,GAAS,aAAa,YAAY,IAEnD,EACJ,UACA,QAAQ,IACR,SAAS,OACP,GAAyB;EAC3B,SAAS;EACT,YAAY,GAAS,aAAa;EAClC;CACF,CAAC,GAEG,GACA,GACA;CACJ,AAAI,MACF,IAAyB,IACzB,IAAmB,IACnB,IAAoB;CAGtB,IAAI;CACJ,AAAI,GAAS,aAAa,cAAc,SACtC,IAA0B,GAAG,EAAQ,YAAY,WAAW;CAG9D,IAAM,EAAE,uBAAoB,oBAAiB,GAAwB;EACnE;EACA;EACA;EACA,SAAS,GAAS,aAAa,kBAAkB;EACjD,YAAY;CACd,CAAC,GAEK,KAAW,QACR,EAAqB;EAC1B;EACA;EACA;EACA;EACA;EACA;EACA,aAAa;EACb;EACA;EACA,iBAAiB;EACjB;EACA,aAAa;EACb,cAAc;EACd;EACA,wBAAwB;EACxB,kBAAkB;CACpB,CAAC,GACA;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,GAEK,KAAiB,QACd,EAAqB;EAC1B;EACA;EACA;EACA;EACA;EACA;EACA,aAAa;EACb;EACA;EACA,iBAAiB;EACjB;EACA,aAAa;EACb,cAAc;EACd;EACA,wBAAwB;EACxB,kBAAkB;CACpB,CAAC,GACA;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,GAEK,IAAgB,SAAkB;EAClC,MASJ,EAAgB,EAAI,IA0BpB,YAxB8C;GAC5C,IAAI;IACF,IAAM,IAAS,MAAM,EAAW,OAAO,KAAK;IAgB5C,AAfA,MAAM,IAAI,SAAe,GAAS,MAAW;KAC3C,GAA+B,GAAkB;MAC/C,UAAU,EAAO;MACjB,WAAW,CAAC;MACZ,mBAAmB;OACjB,EAAQ;MACV;MACA,UAAU,MAAU;OAClB,EAAO,CAAK;MACd;KACF,CAAC;IACH,CAAC,GACD,aAAa,WAAW,YAAY,GACpC,aAAa,WAAW,aAAa,GACrC,GAAgB,GAChB,GAAS,QAAQ,KAAK,EAAE,UAAU,EAAuB,CAAQ,EAAE,CAAC;GACtE,UAAU;IACR,EAAgB,EAAK;GACvB;EACF,EAEA,CAAW,CAAC,CAAC,YAAY,CAEzB,CAAC;CACH,GAAG;EAAC,EAAW;EAAQ;EAAU;EAAc;EAAkB;CAAO,CAAC,GAEnE,IAAS,GAAY,MAAM,MAC3B,IAAiB,QACd,GAA8B;EACnC;EACA,kBAAkB,EAAE,6BAA6B;CACnD,CAAC,GACA,CAAC,GAAG,CAAM,CAAC,GAER,KACJ,kBAAC,GAAD;EACE,WAAW;EACX,QAAQ;EACR,QAAQ;GACN,cAAc,EAAE,uBAAuB;GACvC,eAAe,EAAE,+BAA+B;GAChD,SAAS,EAAE,iCAAiC;EAC9C;EACA,WAAW;EACG;CACf,CAAA,GAGG,KACJ,kBAAC,GAAD;EACE,WAAW;EACX,QAAQ;EACR,QAAQ;GACN,cAAc,EAAE,uBAAuB;GACvC,eAAe,EAAE,+BAA+B;GAChD,SAAS,EAAE,iCAAiC;EAC9C;EACA,WAAW;EACG;CACf,CAAA,GAGC,IAAkC;CACtC,AAAI,KAAgB,SAClB,IACE,kBAAC,IAAD,EAA4B,YAAoC,CAAA;CAIpE,IAAM,IACJ,kBAAC,IAAD;EACE,OAAO;EACP,UAAU;EACV,aAAa,EAAE,4BAA4B;EAC3C,WAAW,EAAE,4BAA4B;CAC1C,CAAA;CAGH,OACE,kBAAC,IAAD,EAAA,UACE,kBAAC,IAAD;EACE,SAAS;GACP;GACA,QAAQ;GACR,QAAQ;GACR,aAAa;GACb,mBAAmB;GACnB,qBAAqB,EAAE,iCAAiC;GACxD,mBAAmB,EAAE,+BAA+B;GACpD,qBAAqB,EAAE,6BAA6B;EACtD;EACA,eAAe;GACb,UAAU;GACV,QAAQ;GACR,QAAQ;GACR,aAAa;GACb,oBAAoB;GACpB,qBAAqB,EAAE,6BAA6B;EACtD;EACA,QAAQ,EACN,YAAY,kBAAC,OAAD,EAAK,KAAK,EAAkB,CAAA,EAC1C;EACA,mBAAkB;EAElB,UAAA,kBAAC,GAAD;GAA4C;GAC1C,UAAA,kBAAC,GAAD;IACE,OAAO;KACL,QAAQ;KACR,eAAe;KACf,gBAAgB,EAAE,yBAAyB;IAC7C;IAEC,UAAA;GACoC,CAAA;EACV,CAAA;CACf,CAAA,EACL,CAAA;AAEnB,GAaM,KAAyB,EAC7B,aACA,qBACA,aACA,eACA,uBAC6C;CAC7C,IAAM,IAAc,EAAkB,GAAkB,CAAQ;CAEhE,OACE,kBAAC,GAAD;EACe;EACD;EACG;EAEd;CACoB,CAAA;AAE3B,GAEa,KAAwB,EACnC,aACA,qBACA,aACA,eACA,uBAEI,KAAoB,QAAQ,KAAY,OAExC,kBAAC,GAAD;CACoB;CACR;CACE;CACG;CAEd;AACoB,CAAA,IAKzB,kBAAC,GAAD;CACE,aAAa;CACD;CACG;CAEd;AACoB,CAAA"}
|
|
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';\nimport { resetRelayStore } from '@plumile/relay/environment.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 { GlobalSearchInput } from '@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js';\nimport { SidebarProfileMenu } from '@plumile/ui/components/navigation/sidebar/SidebarProfileMenu.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 { 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 dashboards,\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 pinningEnabled = sidebar?.pinnedItems?.enabled === true;\n\n const {\n pins,\n toggle: togglePin,\n reorder: reorderPin,\n } = useBackofficeSidebarPins({\n enabled: pinningEnabled,\n storageKey: sidebar?.pinnedItems?.storageKey,\n visibleEntityIds,\n });\n\n let sidebarPinnedEntityIds: readonly string[] | undefined;\n let sidebarTogglePin: ((entityId: string) => void) | undefined;\n let sidebarReorderPin: ((fromId: string, toId: string) => void) | undefined;\n if (pinningEnabled) {\n sidebarPinnedEntityIds = pins;\n sidebarTogglePin = togglePin;\n sidebarReorderPin = reorderPin;\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 dashboards,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: sidebarPinnedEntityIds,\n recentItems,\n onTogglePin: sidebarTogglePin,\n onReorderPin: sidebarReorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n dashboards,\n pathname,\n permissions,\n recentItems,\n setCollapsed,\n sidebar,\n sidebarPinnedEntityIds,\n sidebarQuery,\n sidebarReorderPin,\n sidebarTogglePin,\n t,\n tApp,\n ]);\n\n const mobileSections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n dashboards,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: sidebarPinnedEntityIds,\n recentItems,\n onTogglePin: sidebarTogglePin,\n onReorderPin: sidebarReorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n dashboards,\n pathname,\n permissions,\n recentItems,\n setCollapsed,\n sidebar,\n sidebarPinnedEntityIds,\n sidebarQuery,\n sidebarReorderPin,\n sidebarTogglePin,\n t,\n tApp,\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 <SidebarProfileMenu\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 <SidebarProfileMenu\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 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 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 contentScrollMode=\"contained\"\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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"}
|