@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.
Files changed (192) hide show
  1. package/README.md +11 -4
  2. package/lib/esm/auth/login/LoginFlow.js.map +1 -1
  3. package/lib/esm/auth/pages/AcceptInvitationScreen.js.map +1 -1
  4. package/lib/esm/auth/pages/PasswordResetCompleteScreen.js.map +1 -1
  5. package/lib/esm/auth/pages/PasswordResetRequestScreen.js.map +1 -1
  6. package/lib/esm/components/backoffice/detail/BackofficeEntitySummaryHeader.js +28 -28
  7. package/lib/esm/components/backoffice/detail/BackofficeEntitySummaryHeader.js.map +1 -1
  8. package/lib/esm/components/backoffice/pickers/EntityIdPickerDialog.js +123 -70
  9. package/lib/esm/components/backoffice/pickers/EntityIdPickerDialog.js.map +1 -1
  10. package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js +206 -204
  11. package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js.map +1 -1
  12. package/lib/esm/hooks/useAuth.js +56 -56
  13. package/lib/esm/hooks/useAuth.js.map +1 -1
  14. package/lib/esm/hooks/useConditionalSubscription.js +18 -18
  15. package/lib/esm/hooks/useConditionalSubscription.js.map +1 -1
  16. package/lib/esm/hooks/useInfiniteConnection.js +40 -38
  17. package/lib/esm/hooks/useInfiniteConnection.js.map +1 -1
  18. package/lib/esm/i18n/locales/en/backofficeReact.js +1 -0
  19. package/lib/esm/i18n/locales/en/backofficeReact.js.map +1 -1
  20. package/lib/esm/i18n/locales/fr/backofficeReact.js +1 -0
  21. package/lib/esm/i18n/locales/fr/backofficeReact.js.map +1 -1
  22. package/lib/esm/index.js +56 -64
  23. package/lib/esm/pages/BackofficeEntityDetailPage.js +97 -97
  24. package/lib/esm/pages/BackofficeEntityDetailPage.js.map +1 -1
  25. package/lib/esm/pages/BackofficeEntityListDataPage.js +39 -31
  26. package/lib/esm/pages/BackofficeEntityListDataPage.js.map +1 -1
  27. package/lib/esm/pages/BackofficeEntityListPage.js +2 -0
  28. package/lib/esm/pages/BackofficeEntityListPage.js.map +1 -1
  29. package/lib/esm/pages/BackofficeLayoutPage.js +19 -19
  30. package/lib/esm/pages/BackofficeLayoutPage.js.map +1 -1
  31. package/lib/esm/provider/BackofficeProvider.js +33 -33
  32. package/lib/esm/router/createBackofficeRoutes.js +26 -28
  33. package/lib/esm/router/createBackofficeRoutes.js.map +1 -1
  34. package/lib/esm/storybook/relay/RelayStory.js +32 -32
  35. package/lib/esm/storybook/relay/RelayStory.js.map +1 -1
  36. package/lib/esm/storybook/relay/mockResolvers.js.map +1 -1
  37. package/lib/esm/style.css +1 -1
  38. package/lib/types/components/backoffice/detail/BackofficeEntitySummaryHeader.d.ts +1 -1
  39. package/lib/types/components/backoffice/detail/BackofficeEntitySummaryHeader.d.ts.map +1 -1
  40. package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.d.ts.map +1 -1
  41. package/lib/types/components/backoffice/scaffolds/BackofficeEntityListScaffold.d.ts +2 -0
  42. package/lib/types/components/backoffice/scaffolds/BackofficeEntityListScaffold.d.ts.map +1 -1
  43. package/lib/types/hooks/useAuth.d.ts.map +1 -1
  44. package/lib/types/hooks/useConditionalSubscription.d.ts.map +1 -1
  45. package/lib/types/hooks/useInfiniteConnection.d.ts +3 -2
  46. package/lib/types/hooks/useInfiniteConnection.d.ts.map +1 -1
  47. package/lib/types/i18n/locales/en/backofficeReact.d.ts +5 -0
  48. package/lib/types/i18n/locales/fr/backofficeReact.d.ts +5 -0
  49. package/lib/types/i18n/resources.d.ts +2 -0
  50. package/lib/types/i18n/resources.d.ts.map +1 -1
  51. package/lib/types/index.d.ts +1 -9
  52. package/lib/types/index.d.ts.map +1 -1
  53. package/lib/types/pages/BackofficeEntityListDataPage.d.ts.map +1 -1
  54. package/lib/types/pages/BackofficeEntityListPage.d.ts.map +1 -1
  55. package/lib/types/pages/BackofficeLayoutPage.d.ts.map +1 -1
  56. package/lib/types/router/createBackofficeRoutes.d.ts +3 -3
  57. package/lib/types/router/createBackofficeRoutes.d.ts.map +1 -1
  58. package/lib/types/storybook/relay/RelayStory.d.ts +1 -1
  59. package/lib/types/storybook/relay/RelayStory.d.ts.map +1 -1
  60. package/lib/types/storybook/relay/mockResolvers.d.ts +9 -1
  61. package/lib/types/storybook/relay/mockResolvers.d.ts.map +1 -1
  62. package/package.json +12 -15
  63. package/lib/esm/_virtual/_rolldown/runtime.js +0 -7
  64. package/lib/esm/components/backoffice/detail/BackofficeDetailFlagTag.js +0 -13
  65. package/lib/esm/components/backoffice/detail/BackofficeDetailFlagTag.js.map +0 -1
  66. package/lib/esm/components/backoffice/detail/BackofficeDetailTaggedValue.js +0 -12
  67. package/lib/esm/components/backoffice/detail/BackofficeDetailTaggedValue.js.map +0 -1
  68. package/lib/esm/components/backoffice/detail/BackofficeEnumLabel.js +0 -16
  69. package/lib/esm/components/backoffice/detail/BackofficeEnumLabel.js.map +0 -1
  70. package/lib/esm/components/backoffice/detail/BackofficeReferenceValue.js +0 -17
  71. package/lib/esm/components/backoffice/detail/BackofficeReferenceValue.js.map +0 -1
  72. package/lib/esm/components/backoffice/detail/BackofficeStatusGroup.js +0 -8
  73. package/lib/esm/components/backoffice/detail/BackofficeStatusGroup.js.map +0 -1
  74. package/lib/esm/components/backoffice/detail/BackofficeStatusMetaBadge.js +0 -16
  75. package/lib/esm/components/backoffice/detail/BackofficeStatusMetaBadge.js.map +0 -1
  76. package/lib/esm/components/backoffice/detail/backofficeDetailRelationLink.css.js +0 -6
  77. package/lib/esm/components/backoffice/detail/backofficeDetailRelationLink.css.js.map +0 -1
  78. package/lib/esm/components/backoffice/refs/backofficeEntityIdRef.css.js +0 -6
  79. package/lib/esm/components/backoffice/refs/backofficeEntityIdRef.css.js.map +0 -1
  80. package/lib/esm/components/backoffice/routing/BackofficeRoutePendingBar.js +0 -12
  81. package/lib/esm/components/backoffice/routing/BackofficeRoutePendingBar.js.map +0 -1
  82. package/lib/esm/components/backoffice/routing/backofficeRoutePendingBar.css.js +0 -7
  83. package/lib/esm/components/backoffice/routing/backofficeRoutePendingBar.css.js.map +0 -1
  84. package/lib/esm/hooks/useBackofficeLoadMore.js +0 -18
  85. package/lib/esm/hooks/useBackofficeLoadMore.js.map +0 -1
  86. package/lib/esm/modules/base64.js +0 -21
  87. package/lib/esm/modules/base64.js.map +0 -1
  88. package/lib/esm/node_modules/@babel/runtime/helpers/arrayLikeToArray.js +0 -15
  89. package/lib/esm/node_modules/@babel/runtime/helpers/arrayLikeToArray.js.map +0 -1
  90. package/lib/esm/node_modules/@babel/runtime/helpers/arrayWithoutHoles.js +0 -15
  91. package/lib/esm/node_modules/@babel/runtime/helpers/arrayWithoutHoles.js.map +0 -1
  92. package/lib/esm/node_modules/@babel/runtime/helpers/defineProperty.js +0 -20
  93. package/lib/esm/node_modules/@babel/runtime/helpers/defineProperty.js.map +0 -1
  94. package/lib/esm/node_modules/@babel/runtime/helpers/interopRequireDefault.js +0 -13
  95. package/lib/esm/node_modules/@babel/runtime/helpers/interopRequireDefault.js.map +0 -1
  96. package/lib/esm/node_modules/@babel/runtime/helpers/iterableToArray.js +0 -13
  97. package/lib/esm/node_modules/@babel/runtime/helpers/iterableToArray.js.map +0 -1
  98. package/lib/esm/node_modules/@babel/runtime/helpers/nonIterableSpread.js +0 -13
  99. package/lib/esm/node_modules/@babel/runtime/helpers/nonIterableSpread.js.map +0 -1
  100. package/lib/esm/node_modules/@babel/runtime/helpers/objectSpread2.js +0 -33
  101. package/lib/esm/node_modules/@babel/runtime/helpers/objectSpread2.js.map +0 -1
  102. package/lib/esm/node_modules/@babel/runtime/helpers/objectWithoutPropertiesLoose.js +0 -19
  103. package/lib/esm/node_modules/@babel/runtime/helpers/objectWithoutPropertiesLoose.js.map +0 -1
  104. package/lib/esm/node_modules/@babel/runtime/helpers/toConsumableArray.js +0 -18
  105. package/lib/esm/node_modules/@babel/runtime/helpers/toConsumableArray.js.map +0 -1
  106. package/lib/esm/node_modules/@babel/runtime/helpers/toPrimitive.js +0 -22
  107. package/lib/esm/node_modules/@babel/runtime/helpers/toPrimitive.js.map +0 -1
  108. package/lib/esm/node_modules/@babel/runtime/helpers/toPropertyKey.js +0 -17
  109. package/lib/esm/node_modules/@babel/runtime/helpers/toPropertyKey.js.map +0 -1
  110. package/lib/esm/node_modules/@babel/runtime/helpers/typeof.js +0 -18
  111. package/lib/esm/node_modules/@babel/runtime/helpers/typeof.js.map +0 -1
  112. package/lib/esm/node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js +0 -19
  113. package/lib/esm/node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js.map +0 -1
  114. package/lib/esm/node_modules/fbjs/lib/areEqual.js +0 -42
  115. package/lib/esm/node_modules/fbjs/lib/areEqual.js.map +0 -1
  116. package/lib/esm/node_modules/invariant/browser.js +0 -30
  117. package/lib/esm/node_modules/invariant/browser.js.map +0 -1
  118. package/lib/esm/node_modules/relay-test-utils/index.js +0 -11
  119. package/lib/esm/node_modules/relay-test-utils/index.js.map +0 -1
  120. package/lib/esm/node_modules/relay-test-utils/lib/RelayMockPayloadGenerator.js +0 -288
  121. package/lib/esm/node_modules/relay-test-utils/lib/RelayMockPayloadGenerator.js.map +0 -1
  122. package/lib/esm/node_modules/relay-test-utils/lib/RelayModernMockEnvironment.js +0 -183
  123. package/lib/esm/node_modules/relay-test-utils/lib/RelayModernMockEnvironment.js.map +0 -1
  124. package/lib/esm/node_modules/relay-test-utils/lib/RelayResolverTestUtils.js +0 -19
  125. package/lib/esm/node_modules/relay-test-utils/lib/RelayResolverTestUtils.js.map +0 -1
  126. package/lib/esm/node_modules/relay-test-utils/lib/index.js +0 -21
  127. package/lib/esm/node_modules/relay-test-utils/lib/index.js.map +0 -1
  128. package/lib/esm/node_modules/relay-test-utils/lib/unwrapContainer.js +0 -16
  129. package/lib/esm/node_modules/relay-test-utils/lib/unwrapContainer.js.map +0 -1
  130. package/lib/esm/relay/RelayProvider.js +0 -2
  131. package/lib/esm/relay/envHelpers.js +0 -63
  132. package/lib/esm/relay/envHelpers.js.map +0 -1
  133. package/lib/esm/relay/environment.js +0 -2
  134. package/lib/esm/relay/shortAccessTokenEnvironment.js +0 -2
  135. package/lib/esm/relay/useRelayOperationActivity.js +0 -2
  136. package/lib/esm/storybook/relay/relay-test-utils.d.js +0 -0
  137. package/lib/types/auth/AuthFlows.stories.d.ts +0 -19
  138. package/lib/types/auth/AuthFlows.stories.d.ts.map +0 -1
  139. package/lib/types/components/backoffice/billing/BackofficeBillingUsageChart.stories.d.ts +0 -41
  140. package/lib/types/components/backoffice/billing/BackofficeBillingUsageChart.stories.d.ts.map +0 -1
  141. package/lib/types/components/backoffice/detail/BackofficeDetailFlagTag.d.ts +0 -11
  142. package/lib/types/components/backoffice/detail/BackofficeDetailFlagTag.d.ts.map +0 -1
  143. package/lib/types/components/backoffice/detail/BackofficeDetailPrimitives.stories.d.ts +0 -17
  144. package/lib/types/components/backoffice/detail/BackofficeDetailPrimitives.stories.d.ts.map +0 -1
  145. package/lib/types/components/backoffice/detail/BackofficeDetailTaggedValue.d.ts +0 -13
  146. package/lib/types/components/backoffice/detail/BackofficeDetailTaggedValue.d.ts.map +0 -1
  147. package/lib/types/components/backoffice/detail/BackofficeEnumLabel.d.ts +0 -9
  148. package/lib/types/components/backoffice/detail/BackofficeEnumLabel.d.ts.map +0 -1
  149. package/lib/types/components/backoffice/detail/BackofficeReferenceValue.d.ts +0 -10
  150. package/lib/types/components/backoffice/detail/BackofficeReferenceValue.d.ts.map +0 -1
  151. package/lib/types/components/backoffice/detail/BackofficeStatusGroup.d.ts +0 -8
  152. package/lib/types/components/backoffice/detail/BackofficeStatusGroup.d.ts.map +0 -1
  153. package/lib/types/components/backoffice/detail/BackofficeStatusMetaBadge.d.ts +0 -11
  154. package/lib/types/components/backoffice/detail/BackofficeStatusMetaBadge.d.ts.map +0 -1
  155. package/lib/types/components/backoffice/detail/backofficeDetailRelationLink.css.d.ts +0 -6
  156. package/lib/types/components/backoffice/detail/backofficeDetailRelationLink.css.d.ts.map +0 -1
  157. package/lib/types/components/backoffice/errors/BackofficeErrorBoundary.stories.d.ts +0 -12
  158. package/lib/types/components/backoffice/errors/BackofficeErrorBoundary.stories.d.ts.map +0 -1
  159. package/lib/types/components/backoffice/filters/EntityIdFilterField.stories.d.ts +0 -12
  160. package/lib/types/components/backoffice/filters/EntityIdFilterField.stories.d.ts.map +0 -1
  161. package/lib/types/components/backoffice/hub/BackofficeHubTemplate.stories.d.ts +0 -49
  162. package/lib/types/components/backoffice/hub/BackofficeHubTemplate.stories.d.ts.map +0 -1
  163. package/lib/types/components/backoffice/overview/BackofficeOverviewLayout.stories.d.ts +0 -11
  164. package/lib/types/components/backoffice/overview/BackofficeOverviewLayout.stories.d.ts.map +0 -1
  165. package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.stories.d.ts +0 -12
  166. package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.stories.d.ts.map +0 -1
  167. package/lib/types/components/backoffice/refs/backofficeEntityIdRef.css.d.ts +0 -2
  168. package/lib/types/components/backoffice/refs/backofficeEntityIdRef.css.d.ts.map +0 -1
  169. package/lib/types/components/backoffice/routing/BackofficeRoutePendingBar.d.ts +0 -4
  170. package/lib/types/components/backoffice/routing/BackofficeRoutePendingBar.d.ts.map +0 -1
  171. package/lib/types/components/backoffice/routing/backofficeRoutePendingBar.css.d.ts +0 -3
  172. package/lib/types/components/backoffice/routing/backofficeRoutePendingBar.css.d.ts.map +0 -1
  173. package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.stories.d.ts +0 -11
  174. package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.stories.d.ts.map +0 -1
  175. package/lib/types/components/backoffice/tools/BackofficeTools.stories.d.ts +0 -17
  176. package/lib/types/components/backoffice/tools/BackofficeTools.stories.d.ts.map +0 -1
  177. package/lib/types/hooks/useBackofficeLoadMore.d.ts +0 -9
  178. package/lib/types/hooks/useBackofficeLoadMore.d.ts.map +0 -1
  179. package/lib/types/modules/base64.d.ts +0 -3
  180. package/lib/types/modules/base64.d.ts.map +0 -1
  181. package/lib/types/pages/BackofficeDashboardPage.stories.d.ts +0 -9
  182. package/lib/types/pages/BackofficeDashboardPage.stories.d.ts.map +0 -1
  183. package/lib/types/relay/RelayProvider.d.ts +0 -2
  184. package/lib/types/relay/RelayProvider.d.ts.map +0 -1
  185. package/lib/types/relay/envHelpers.d.ts +0 -25
  186. package/lib/types/relay/envHelpers.d.ts.map +0 -1
  187. package/lib/types/relay/environment.d.ts +0 -2
  188. package/lib/types/relay/environment.d.ts.map +0 -1
  189. package/lib/types/relay/shortAccessTokenEnvironment.d.ts +0 -5
  190. package/lib/types/relay/shortAccessTokenEnvironment.d.ts.map +0 -1
  191. package/lib/types/relay/useRelayOperationActivity.d.ts +0 -2
  192. 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 { useBackofficeRuntimePaginationFragment as n } from "../relay/typedRelayHooks.js";
4
- import { BackofficeLazyEntityCountLabel as r } from "../components/backoffice/refs/BackofficeLazyEntityCount.js";
5
- import { BackofficeEntityListScaffold as i } from "../components/backoffice/scaffolds/BackofficeEntityListScaffold.js";
6
- import { useRelayEnvironment as a } from "../relay/useRelayEnvironment.js";
7
- import { useBackofficeListRefetch as o } from "../hooks/useBackofficeListRefetch.js";
8
- import { useBackofficeLoadMore as s } from "../hooks/useBackofficeLoadMore.js";
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: a, state: p, pushState: m, headerActions: g, columns: _, gridTemplateColumns: S, getRowId: C, countFetchKey: w, bumpCountFetchKey: T, filterDrawerState: E, registerRefresh: D } = c(), O = a.list, { t: k } = e(), A = v(O.query, t), { data: j, loadNext: M, hasNext: N, isLoadingNext: P, refetch: F } = n(O.fragment, A), I = O.getConnection(j), L = d(() => I.edges.map((e) => O.toRow(e.node)), [I.edges, O]), { listDefaults: R } = a, z = p.sort ?? R.sort, { pageSize: B } = y, V = d(() => ({
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 } = o({
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 = s({
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
- loadNext: M,
53
- count: B
54
- }), J = /* @__PURE__ */ h("span", { children: k("common.loading") });
55
- L.length > 0 && (J = /* @__PURE__ */ h("span", { children: k("list.loaded", { count: L.length }) }));
56
- let Y = /* @__PURE__ */ h(r, {
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: J,
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(i, {
67
- config: a,
70
+ return /* @__PURE__ */ h(a, {
71
+ config: o,
68
72
  state: p,
69
73
  pushState: m,
70
74
  headerActions: g,
71
- rows: L,
75
+ rows: J.nodes,
72
76
  columns: _,
73
77
  gridTemplateColumns: S,
74
78
  getRowId: C,
75
- hasNextPage: N,
76
- isLoadingMore: P,
79
+ hasNextPage: J.hasNext,
80
+ isLoadingMore: J.isLoadingNext,
81
+ incrementalError: J.incrementalError,
77
82
  isRefreshing: W,
78
- onLoadMore: q,
83
+ onLoadMore: J.loadMoreSafe,
84
+ onRetryLoadMore: J.retryLoadMore,
79
85
  onRefresh: K,
80
86
  totalCount: null,
81
- loadedCountLabel: Y,
87
+ loadedCountLabel: X,
82
88
  filterDrawerState: E
83
89
  });
84
90
  }
85
91
  var C = ({ prepared: n }) => {
86
- let { config: r, state: o, pushState: s, headerActions: d, columns: v, gridTemplateColumns: b, getRowId: x, filterDrawerState: C } = c(), w = a(), { t: T } = e(), [E, D] = p(() => n.query), O = f(null), k = l(() => {
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, i = {
96
- where: o.where,
97
- sort: o.sort ?? t.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
- }, a = e.buildQueryVariables(i), s = _(w, e.query, a, { fetchPolicy: "network-only" });
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
- o.sort,
107
- o.where
112
+ i.sort,
113
+ i.where
108
114
  ]);
109
115
  return /* @__PURE__ */ h(t, {
110
- fallback: ({ reset: e }) => /* @__PURE__ */ h(i, {
116
+ fallback: ({ reset: e }) => /* @__PURE__ */ h(a, {
111
117
  config: r,
112
- state: o,
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 { resetRelayStore as re } from "../relay/environment.js";
11
- import { useRelayEnvironment as ie } from "../relay/useRelayEnvironment.js";
12
- import ae from "../hooks/useBackofficeSidebarPins.js";
13
- import oe from "../hooks/useSidebarGroupCollapse.js";
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 le } from "react-i18next";
17
- import { commitMutation as ue, usePreloadedQuery as f } from "react-relay";
18
- import { ToastProvider as de } from "@plumile/ui/atomic/molecules/toast/ToastProvider.js";
19
- import fe from "@plumile/router/routing/RoutingContext.js";
20
- import { GlobalSearchInput as pe } from "@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js";
21
- import me from "@plumile/router/routing/useLocation.js";
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: _ } = le(), { t: v } = t(), { pathname: y } = me(), b = ce(fe), x = ie(), { 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(() => {
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 } = ae({
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 } = oe({
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 = se(() => {
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
- ue(x, {
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"), re(), b?.history.push({ pathname: e(C) });
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(pe, {
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(de, { children: /* @__PURE__ */ d(he, {
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":"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"}
1
+ {"version":3,"file":"BackofficeLayoutPage.js","names":[],"sources":["../../../src/pages/BackofficeLayoutPage.tsx"],"sourcesContent":["import {\n useEffect,\n useMemo,\n type JSX,\n type ReactNode,\n useCallback,\n useContext,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n usePreloadedQuery,\n type PreloadedQuery,\n} from 'react-relay';\nimport type {\n GraphQLTaggedNode,\n MutationParameters,\n OperationType,\n} from 'relay-runtime';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\nimport useLocation from '@plumile/router/routing/useLocation.js';\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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"}