@multiplatform.one/backoffice 7.28.1 → 7.29.0

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 (269) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/desk/DeskSurface.native.js.map +1 -1
  3. package/dist/cjs/form/DocFormScreen.cjs +167 -224
  4. package/dist/cjs/form/DocFormScreen.native.js +182 -259
  5. package/dist/cjs/form/DocFormScreen.native.js.map +1 -1
  6. package/dist/cjs/i18n/en.cjs +1 -0
  7. package/dist/cjs/i18n/en.native.js +1 -0
  8. package/dist/cjs/i18n/en.native.js.map +1 -1
  9. package/dist/cjs/list/ListBulkActionsBar.cjs +30 -18
  10. package/dist/cjs/list/ListBulkActionsBar.native.js +43 -31
  11. package/dist/cjs/list/ListBulkActionsBar.native.js.map +1 -1
  12. package/dist/cjs/list/sidebar-section.cjs +15 -7
  13. package/dist/cjs/list/sidebar-section.native.js +16 -7
  14. package/dist/cjs/list/sidebar-section.native.js.map +1 -1
  15. package/dist/cjs/report/DoctypeReportView.cjs +20 -374
  16. package/dist/cjs/report/DoctypeReportView.native.js +23 -455
  17. package/dist/cjs/report/DoctypeReportView.native.js.map +1 -1
  18. package/dist/cjs/report/QueryReportScreen.cjs +33 -23
  19. package/dist/cjs/report/QueryReportScreen.native.js +33 -23
  20. package/dist/cjs/report/QueryReportScreen.native.js.map +1 -1
  21. package/dist/cjs/report/queryReportColumns.cjs +3 -105
  22. package/dist/cjs/report/queryReportColumns.native.js +2 -129
  23. package/dist/cjs/report/queryReportColumns.native.js.map +1 -1
  24. package/dist/cjs/report/queryReportFilterBar.cjs +3 -4
  25. package/dist/cjs/report/queryReportFilterBar.native.js +3 -4
  26. package/dist/cjs/report/queryReportFilterBar.native.js.map +1 -1
  27. package/dist/cjs/report/queryReportUrlState.cjs +2 -2
  28. package/dist/cjs/report/queryReportUrlState.native.js +2 -2
  29. package/dist/cjs/report/queryReportUrlState.native.js.map +1 -1
  30. package/dist/cjs/report/report-grid.cjs +2 -426
  31. package/dist/cjs/report/report-grid.native.js +1 -479
  32. package/dist/cjs/report/report-grid.native.js.map +1 -1
  33. package/dist/cjs/report/report-toolbar.cjs +2 -228
  34. package/dist/cjs/report/report-toolbar.native.js +1 -274
  35. package/dist/cjs/report/report-toolbar.native.js.map +1 -1
  36. package/dist/cjs/report/reportShapes.cjs +12 -383
  37. package/dist/cjs/report/reportShapes.native.js +12 -501
  38. package/dist/cjs/report/reportShapes.native.js.map +1 -1
  39. package/dist/cjs/report/reportViewModel.cjs +20 -360
  40. package/dist/cjs/report/reportViewModel.native.js +19 -627
  41. package/dist/cjs/report/reportViewModel.native.js.map +1 -1
  42. package/dist/cjs/report/savedReports.cjs +2 -106
  43. package/dist/cjs/report/savedReports.native.js +1 -132
  44. package/dist/cjs/report/savedReports.native.js.map +1 -1
  45. package/dist/cjs/report/useQueryReport.cjs +11 -219
  46. package/dist/cjs/report/useQueryReport.native.js +11 -244
  47. package/dist/cjs/report/useQueryReport.native.js.map +1 -1
  48. package/dist/cjs/shared/measures.cjs +3 -5
  49. package/dist/cjs/shared/measures.native.js +3 -5
  50. package/dist/cjs/shared/measures.native.js.map +1 -1
  51. package/dist/cjs/views/ReportView.cjs +3 -256
  52. package/dist/cjs/views/ReportView.native.js +3 -382
  53. package/dist/cjs/views/ReportView.native.js.map +1 -1
  54. package/dist/cjs/views/report-controls.cjs +6 -6
  55. package/dist/cjs/views/report-controls.native.js +6 -6
  56. package/dist/cjs/views/report-controls.native.js.map +1 -1
  57. package/dist/esm/desk/DeskSurface.mjs.map +1 -1
  58. package/dist/esm/desk/DeskSurface.native.js.map +1 -1
  59. package/dist/esm/form/DocFormScreen.mjs +169 -226
  60. package/dist/esm/form/DocFormScreen.mjs.map +1 -1
  61. package/dist/esm/form/DocFormScreen.native.js +184 -261
  62. package/dist/esm/form/DocFormScreen.native.js.map +1 -1
  63. package/dist/esm/i18n/en.mjs +1 -0
  64. package/dist/esm/i18n/en.mjs.map +1 -1
  65. package/dist/esm/i18n/en.native.js +1 -0
  66. package/dist/esm/i18n/en.native.js.map +1 -1
  67. package/dist/esm/list/ListBulkActionsBar.mjs +31 -19
  68. package/dist/esm/list/ListBulkActionsBar.mjs.map +1 -1
  69. package/dist/esm/list/ListBulkActionsBar.native.js +37 -25
  70. package/dist/esm/list/ListBulkActionsBar.native.js.map +1 -1
  71. package/dist/esm/list/sidebar-section.mjs +16 -8
  72. package/dist/esm/list/sidebar-section.mjs.map +1 -1
  73. package/dist/esm/list/sidebar-section.native.js +17 -8
  74. package/dist/esm/list/sidebar-section.native.js.map +1 -1
  75. package/dist/esm/report/DoctypeReportView.mjs +21 -375
  76. package/dist/esm/report/DoctypeReportView.mjs.map +1 -1
  77. package/dist/esm/report/DoctypeReportView.native.js +24 -456
  78. package/dist/esm/report/DoctypeReportView.native.js.map +1 -1
  79. package/dist/esm/report/QueryReportScreen.mjs +26 -16
  80. package/dist/esm/report/QueryReportScreen.mjs.map +1 -1
  81. package/dist/esm/report/QueryReportScreen.native.js +26 -16
  82. package/dist/esm/report/QueryReportScreen.native.js.map +1 -1
  83. package/dist/esm/report/queryReportColumns.mjs +1 -103
  84. package/dist/esm/report/queryReportColumns.mjs.map +1 -1
  85. package/dist/esm/report/queryReportColumns.native.js +1 -117
  86. package/dist/esm/report/queryReportColumns.native.js.map +1 -1
  87. package/dist/esm/report/queryReportFilterBar.mjs +1 -2
  88. package/dist/esm/report/queryReportFilterBar.mjs.map +1 -1
  89. package/dist/esm/report/queryReportFilterBar.native.js +1 -2
  90. package/dist/esm/report/queryReportFilterBar.native.js.map +1 -1
  91. package/dist/esm/report/queryReportUrlState.mjs +1 -1
  92. package/dist/esm/report/queryReportUrlState.native.js +1 -1
  93. package/dist/esm/report/report-grid.mjs +1 -425
  94. package/dist/esm/report/report-grid.mjs.map +1 -1
  95. package/dist/esm/report/report-grid.native.js +1 -468
  96. package/dist/esm/report/report-grid.native.js.map +1 -1
  97. package/dist/esm/report/report-toolbar.mjs +2 -228
  98. package/dist/esm/report/report-toolbar.mjs.map +1 -1
  99. package/dist/esm/report/report-toolbar.native.js +2 -264
  100. package/dist/esm/report/report-toolbar.native.js.map +1 -1
  101. package/dist/esm/report/reportShapes.mjs +2 -373
  102. package/dist/esm/report/reportShapes.mjs.map +1 -1
  103. package/dist/esm/report/reportShapes.native.js +2 -491
  104. package/dist/esm/report/reportShapes.native.js.map +1 -1
  105. package/dist/esm/report/reportViewModel.mjs +2 -342
  106. package/dist/esm/report/reportViewModel.mjs.map +1 -1
  107. package/dist/esm/report/reportViewModel.native.js +2 -610
  108. package/dist/esm/report/reportViewModel.native.js.map +1 -1
  109. package/dist/esm/report/savedReports.mjs +1 -105
  110. package/dist/esm/report/savedReports.mjs.map +1 -1
  111. package/dist/esm/report/savedReports.native.js +1 -132
  112. package/dist/esm/report/savedReports.native.js.map +1 -1
  113. package/dist/esm/report/useQueryReport.mjs +2 -210
  114. package/dist/esm/report/useQueryReport.mjs.map +1 -1
  115. package/dist/esm/report/useQueryReport.native.js +2 -235
  116. package/dist/esm/report/useQueryReport.native.js.map +1 -1
  117. package/dist/esm/shared/measures.mjs +1 -3
  118. package/dist/esm/shared/measures.mjs.map +1 -1
  119. package/dist/esm/shared/measures.native.js +1 -3
  120. package/dist/esm/shared/measures.native.js.map +1 -1
  121. package/dist/esm/views/ReportView.mjs +3 -256
  122. package/dist/esm/views/ReportView.mjs.map +1 -1
  123. package/dist/esm/views/ReportView.native.js +3 -382
  124. package/dist/esm/views/ReportView.native.js.map +1 -1
  125. package/dist/esm/views/report-controls.mjs +3 -3
  126. package/dist/esm/views/report-controls.mjs.map +1 -1
  127. package/dist/esm/views/report-controls.native.js +3 -3
  128. package/dist/esm/views/report-controls.native.js.map +1 -1
  129. package/dist/jsx/desk/DeskSurface.mjs.map +1 -1
  130. package/dist/jsx/desk/DeskSurface.native.js.map +1 -1
  131. package/dist/jsx/form/DocFormScreen.mjs +169 -226
  132. package/dist/jsx/form/DocFormScreen.mjs.map +1 -1
  133. package/dist/jsx/form/DocFormScreen.native.js +182 -259
  134. package/dist/jsx/form/DocFormScreen.native.js.map +1 -1
  135. package/dist/jsx/i18n/en.mjs +1 -0
  136. package/dist/jsx/i18n/en.mjs.map +1 -1
  137. package/dist/jsx/i18n/en.native.js +1 -0
  138. package/dist/jsx/i18n/en.native.js.map +1 -1
  139. package/dist/jsx/list/ListBulkActionsBar.mjs +31 -19
  140. package/dist/jsx/list/ListBulkActionsBar.mjs.map +1 -1
  141. package/dist/jsx/list/ListBulkActionsBar.native.js +43 -31
  142. package/dist/jsx/list/ListBulkActionsBar.native.js.map +1 -1
  143. package/dist/jsx/list/sidebar-section.mjs +16 -8
  144. package/dist/jsx/list/sidebar-section.mjs.map +1 -1
  145. package/dist/jsx/list/sidebar-section.native.js +16 -7
  146. package/dist/jsx/list/sidebar-section.native.js.map +1 -1
  147. package/dist/jsx/report/DoctypeReportView.mjs +21 -375
  148. package/dist/jsx/report/DoctypeReportView.mjs.map +1 -1
  149. package/dist/jsx/report/DoctypeReportView.native.js +23 -455
  150. package/dist/jsx/report/DoctypeReportView.native.js.map +1 -1
  151. package/dist/jsx/report/QueryReportScreen.mjs +26 -16
  152. package/dist/jsx/report/QueryReportScreen.mjs.map +1 -1
  153. package/dist/jsx/report/QueryReportScreen.native.js +33 -23
  154. package/dist/jsx/report/QueryReportScreen.native.js.map +1 -1
  155. package/dist/jsx/report/queryReportColumns.mjs +1 -103
  156. package/dist/jsx/report/queryReportColumns.mjs.map +1 -1
  157. package/dist/jsx/report/queryReportColumns.native.js +2 -129
  158. package/dist/jsx/report/queryReportColumns.native.js.map +1 -1
  159. package/dist/jsx/report/queryReportFilterBar.mjs +1 -2
  160. package/dist/jsx/report/queryReportFilterBar.mjs.map +1 -1
  161. package/dist/jsx/report/queryReportFilterBar.native.js +3 -4
  162. package/dist/jsx/report/queryReportFilterBar.native.js.map +1 -1
  163. package/dist/jsx/report/queryReportUrlState.mjs +1 -1
  164. package/dist/jsx/report/queryReportUrlState.native.js +2 -2
  165. package/dist/jsx/report/queryReportUrlState.native.js.map +1 -1
  166. package/dist/jsx/report/report-grid.mjs +1 -425
  167. package/dist/jsx/report/report-grid.mjs.map +1 -1
  168. package/dist/jsx/report/report-grid.native.js +1 -479
  169. package/dist/jsx/report/report-grid.native.js.map +1 -1
  170. package/dist/jsx/report/report-toolbar.mjs +2 -228
  171. package/dist/jsx/report/report-toolbar.mjs.map +1 -1
  172. package/dist/jsx/report/report-toolbar.native.js +1 -274
  173. package/dist/jsx/report/report-toolbar.native.js.map +1 -1
  174. package/dist/jsx/report/reportShapes.mjs +2 -373
  175. package/dist/jsx/report/reportShapes.mjs.map +1 -1
  176. package/dist/jsx/report/reportShapes.native.js +12 -501
  177. package/dist/jsx/report/reportShapes.native.js.map +1 -1
  178. package/dist/jsx/report/reportViewModel.mjs +2 -342
  179. package/dist/jsx/report/reportViewModel.mjs.map +1 -1
  180. package/dist/jsx/report/reportViewModel.native.js +19 -627
  181. package/dist/jsx/report/reportViewModel.native.js.map +1 -1
  182. package/dist/jsx/report/savedReports.mjs +1 -105
  183. package/dist/jsx/report/savedReports.mjs.map +1 -1
  184. package/dist/jsx/report/savedReports.native.js +1 -132
  185. package/dist/jsx/report/savedReports.native.js.map +1 -1
  186. package/dist/jsx/report/useQueryReport.mjs +2 -210
  187. package/dist/jsx/report/useQueryReport.mjs.map +1 -1
  188. package/dist/jsx/report/useQueryReport.native.js +11 -244
  189. package/dist/jsx/report/useQueryReport.native.js.map +1 -1
  190. package/dist/jsx/shared/measures.mjs +1 -3
  191. package/dist/jsx/shared/measures.mjs.map +1 -1
  192. package/dist/jsx/shared/measures.native.js +3 -5
  193. package/dist/jsx/shared/measures.native.js.map +1 -1
  194. package/dist/jsx/views/ReportView.mjs +3 -256
  195. package/dist/jsx/views/ReportView.mjs.map +1 -1
  196. package/dist/jsx/views/ReportView.native.js +3 -382
  197. package/dist/jsx/views/ReportView.native.js.map +1 -1
  198. package/dist/jsx/views/report-controls.mjs +3 -3
  199. package/dist/jsx/views/report-controls.mjs.map +1 -1
  200. package/dist/jsx/views/report-controls.native.js +6 -6
  201. package/dist/jsx/views/report-controls.native.js.map +1 -1
  202. package/package.json +12 -12
  203. package/src/backofficeScreens.designLaw.spec.ts +0 -5
  204. package/src/desk/DeskSurface.tsx +4 -7
  205. package/src/form/DocFormScreen.chrome.spec.ts +77 -0
  206. package/src/form/DocFormScreen.guest.screen.spec.tsx +175 -0
  207. package/src/form/DocFormScreen.rights.spec.tsx +7 -3
  208. package/src/form/DocFormScreen.tsx +214 -315
  209. package/src/i18n/en.ts +1 -0
  210. package/src/list/ListBulkActionsBar.rights.spec.tsx +134 -0
  211. package/src/list/ListBulkActionsBar.screen.spec.tsx +7 -1
  212. package/src/list/ListBulkActionsBar.tsx +76 -57
  213. package/src/list/ListFilterBar.screen.spec.tsx +14 -13
  214. package/src/list/sidebar-section.tsx +11 -3
  215. package/src/report/DoctypeReportView.tsx +28 -550
  216. package/src/report/QueryReportScreen.spec.tsx +75 -1
  217. package/src/report/QueryReportScreen.tsx +38 -22
  218. package/src/report/queryReportColumns.tsx +4 -123
  219. package/src/report/queryReportFilterBar.tsx +3 -5
  220. package/src/report/queryReportUrlState.ts +1 -1
  221. package/src/report/report-grid.tsx +4 -529
  222. package/src/report/report-toolbar.tsx +4 -308
  223. package/src/report/reportShapes.ts +25 -613
  224. package/src/report/reportShim.spec.ts +162 -0
  225. package/src/report/reportViewModel.ts +32 -605
  226. package/src/report/savedReports.ts +4 -161
  227. package/src/report/useQueryReport.ts +9 -347
  228. package/src/shared/measures.ts +3 -11
  229. package/src/views/ReportView.screen.spec.tsx +25 -20
  230. package/src/views/ReportView.tsx +7 -439
  231. package/src/views/report-controls.tsx +12 -20
  232. package/types/desk/DeskSurface.d.ts.map +1 -1
  233. package/types/form/DocFormScreen.d.ts +2 -2
  234. package/types/form/DocFormScreen.d.ts.map +1 -1
  235. package/types/i18n/en.d.ts +1 -0
  236. package/types/i18n/en.d.ts.map +1 -1
  237. package/types/list/ListBulkActionsBar.d.ts.map +1 -1
  238. package/types/list/sidebar-section.d.ts.map +1 -1
  239. package/types/report/DoctypeReportView.d.ts.map +1 -1
  240. package/types/report/QueryReportScreen.d.ts +1 -1
  241. package/types/report/QueryReportScreen.d.ts.map +1 -1
  242. package/types/report/queryReportColumns.d.ts +2 -11
  243. package/types/report/queryReportColumns.d.ts.map +1 -1
  244. package/types/report/queryReportFilterBar.d.ts +1 -1
  245. package/types/report/queryReportFilterBar.d.ts.map +1 -1
  246. package/types/report/queryReportUrlState.d.ts +1 -1
  247. package/types/report/queryReportUrlState.d.ts.map +1 -1
  248. package/types/report/report-grid.d.ts +2 -19
  249. package/types/report/report-grid.d.ts.map +1 -1
  250. package/types/report/report-toolbar.d.ts +2 -29
  251. package/types/report/report-toolbar.d.ts.map +1 -1
  252. package/types/report/reportShapes.d.ts +2 -115
  253. package/types/report/reportShapes.d.ts.map +1 -1
  254. package/types/report/reportViewModel.d.ts +2 -135
  255. package/types/report/reportViewModel.d.ts.map +1 -1
  256. package/types/report/savedReports.d.ts +2 -18
  257. package/types/report/savedReports.d.ts.map +1 -1
  258. package/types/report/useQueryReport.d.ts +2 -35
  259. package/types/report/useQueryReport.d.ts.map +1 -1
  260. package/types/shared/measures.d.ts +1 -2
  261. package/types/shared/measures.d.ts.map +1 -1
  262. package/types/views/ReportView.d.ts +3 -22
  263. package/types/views/ReportView.d.ts.map +1 -1
  264. package/types/views/report-controls.d.ts +2 -5
  265. package/types/views/report-controls.d.ts.map +1 -1
  266. package/src/report/report-grid.spec.tsx +0 -175
  267. package/src/report/report-toolbar.spec.tsx +0 -90
  268. package/src/report/reportShapes.spec.ts +0 -391
  269. package/src/report/reportViewModel.spec.ts +0 -393
@@ -1,439 +1,7 @@
1
- // Desk "report" view parity. FrappeReportBuilder stays the grid engine
2
- // (meta-driven columns, live rows, group rendering with aggregation +
3
- // chart, save/load, Export button); the desk chrome it lacks is composed
4
- // around it from report-controls.tsx:
5
- // - column add/remove picker across all meta fields (+ synthetic ID
6
- // column). The generic ReportBuilder's own column/group-by toggle
7
- // handlers are dead code and its enabled-column state is mount-only,
8
- // so selection is driven through `initialColumns`/`initialGroupBy`
9
- // plus a remount key.
10
- // - `?f=` URL param (urlencoded JSON FrappeFilters) → base filters
11
- // (chips + clear); FrappeReportBuilder accepts filter tuples directly.
12
- // - page-size selector (20/100/500) + pagination: a parallel name-window
13
- // query (name + sort + numeric fields) orders the full filtered result
14
- // client-side, and the current page is handed to the grid as a
15
- // `["name","in",names]` filter — the builder reacts to filter-prop
16
- // changes without remounting. Small results (≤ page size) skip the
17
- // window entirely and keep the pure live path.
18
- // - totals strip over the full filtered result (ReportBuilder has no
19
- // totals row) and an "Open" record jump in the footer.
20
- // - grid rows click through to the form via onRowPress (threaded
21
- // through FrappeReportBuilder → ReportBuilder).
22
- // - CSV export via onExport: current page rows / enabled columns,
23
- // web-guarded (Blob + anchor download); native shows an honest toast.
24
- // Known gaps vs desk (component limitations, documented for integrator):
25
- // - the component's own Save/Load applies loaded configs to its internal
26
- // state only — this screen's pickers stay the source of truth
27
- // - CSV exports the loaded page, not a server-side full export
28
- import { isWeb, notify, YStack } from "@multiplatform.one/components";
29
- import {
30
- Order,
31
- useFrappeCollection,
32
- useLiveQuery,
33
- type UseFrappeCollectionConfig,
34
- } from "@multiplatform.one/frappe";
35
- import {
36
- FrappeReportBuilder,
37
- type GroupByConfig,
38
- type ReportColumn,
39
- } from "@multiplatform.one/frappe-ui";
40
- import { downloadBlob } from "@multiplatform.one/platform";
41
- import { useResolvedKnobs } from "@multiplatform.one/theme";
42
- import { useCallback, useEffect, useMemo, useState } from "react";
43
- import { useTranslation } from "react-i18next";
44
- import { useBackofficeNavigator, useBackofficePaths } from "../config/BackofficeProvider";
45
- import { useDeskScope } from "../desk/scope";
46
- import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
47
- import type { FrappeFilters } from "../shared/types";
48
- import { useViewConnection } from "./connection";
49
- import {
50
- REPORT_NUMERIC_FIELDTYPES,
51
- ReportFooter,
52
- ReportToolbar,
53
- type ReportRecordRef,
54
- type ReportTotal,
55
- } from "./report-controls";
56
- import { useViewMeta } from "./viewMeta";
57
- import { ViewError, ViewLoading } from "./ViewStates";
58
-
59
- export interface ReportViewProps {
60
- /** Proper-cased doctype name (e.g. "ToDo", "Sales Order") */
61
- doctype: string;
62
- /**
63
- * Raw `?f=` search-param value (urlencoded JSON FrappeFilters), read by
64
- * the route wrapper (DoctypeViewScreen) — the screen itself stays
65
- * search-param free so it mounts outside a One navigation container
66
- * (stories/tests).
67
- */
68
- filtersParam?: string;
69
- /** Base filters when no `?f=` URL param is present (stories/tests). */
70
- initialFilters?: FrappeFilters;
71
- }
72
-
73
- const LAYOUT_FIELDTYPES = new Set(["Section Break", "Column Break", "Tab Break"]);
74
- const EMPTY_FILTERS: FrappeFilters = [];
75
- const DEFAULT_PAGE_SIZE = 20;
76
-
77
- type StatsRow = { name: string; doctype: string } & Record<string, unknown>;
78
-
79
- /**
80
- * Parse the `?f=` search param: urlencoded JSON FrappeFilters
81
- * (e.g. `?f=%5B%5B%22status%22%2C%22%3D%22%2C%22Open%22%5D%5D`).
82
- * The router usually decodes the param already, so the raw value is tried
83
- * first. Malformed input degrades to "no filters" (honest default).
84
- */
85
- export function parseReportFiltersParam(raw: unknown): FrappeFilters | undefined {
86
- if (typeof raw !== "string" || !raw) return undefined;
87
- const candidates = [raw];
88
- try {
89
- const decoded = decodeURIComponent(raw);
90
- if (decoded !== raw) candidates.push(decoded);
91
- } catch {
92
- // raw is not percent-encoded — the direct candidate covers it
93
- }
94
- for (const candidate of candidates) {
95
- try {
96
- const parsed: unknown = JSON.parse(candidate);
97
- if (!Array.isArray(parsed)) continue;
98
- const filters: FrappeFilters = [];
99
- for (const tuple of parsed) {
100
- if (
101
- Array.isArray(tuple) &&
102
- tuple.length === 3 &&
103
- typeof tuple[0] === "string" &&
104
- typeof tuple[1] === "string"
105
- ) {
106
- filters.push([tuple[0], tuple[1], tuple[2]]);
107
- }
108
- }
109
- if (filters.length > 0) return filters;
110
- } catch {
111
- // not JSON — try the next candidate
112
- }
113
- }
114
- return undefined;
115
- }
116
-
117
- function isNullish(value: unknown): value is null | undefined {
118
- return value === null || value === undefined;
119
- }
120
-
121
- function compareValues(a: unknown, b: unknown): number {
122
- if (isNullish(a) && isNullish(b)) return 0;
123
- if (isNullish(a)) return 1;
124
- if (isNullish(b)) return -1;
125
- if (typeof a === "number" && typeof b === "number") return a - b;
126
- const left = String(a);
127
- const right = String(b);
128
- return left < right ? -1 : left > right ? 1 : 0;
129
- }
130
-
131
- export function ReportView({ doctype, filtersParam, initialFilters }: ReportViewProps) {
132
- const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
133
- const navigator = useBackofficeNavigator();
134
- const paths = useBackofficePaths();
135
- const { knobProps } = useResolvedKnobs();
136
- const deskScope = useDeskScope();
137
- const connection = useViewConnection();
138
- const { meta, isLoading: isMetaLoading, error: metaError } = useViewMeta(doctype);
139
-
140
- // ---------------------------------------------------------------------
141
- // Base filters: ?f= URL param wins, then the initialFilters prop.
142
- // ---------------------------------------------------------------------
143
- const urlFilters = useMemo(() => parseReportFiltersParam(filtersParam), [filtersParam]);
144
- const [filtersCleared, setFiltersCleared] = useState(false);
145
- useEffect(() => setFiltersCleared(false), [filtersParam, doctype]);
146
- const baseFilters = filtersCleared
147
- ? EMPTY_FILTERS
148
- : (urlFilters ?? initialFilters ?? EMPTY_FILTERS);
149
- // Desk scope (GL-5) ANDs into both queries, invisible to the filter chips
150
- // and not clearable by the user.
151
- const queryFilters = useMemo(() => [...deskScope, ...baseFilters], [deskScope, baseFilters]);
152
- const handleClearFilters = useCallback(() => {
153
- setFiltersCleared(true);
154
- // Drop the ?f= param from the URL so the cleared state survives reloads.
155
- if (urlFilters) navigator.replace(paths.view(doctype, "report"));
156
- }, [urlFilters, navigator, paths, doctype]);
157
-
158
- // ---------------------------------------------------------------------
159
- // Columns: all non-layout meta fields, plus a synthetic ID column.
160
- // Initial selection = in_list_view fields (+ name), desk parity.
161
- // ---------------------------------------------------------------------
162
- const allColumns = useMemo<ReportColumn[]>(() => {
163
- if (!meta) return [];
164
- const idColumn: ReportColumn = {
165
- fieldname: "name",
166
- label: t("report.idColumn", "ID"),
167
- fieldtype: "Data",
168
- enabled: true,
169
- };
170
- return [
171
- idColumn,
172
- ...meta.fields
173
- .filter((field) => field.fieldname && !LAYOUT_FIELDTYPES.has(field.fieldtype))
174
- .map((field) => ({
175
- fieldname: field.fieldname,
176
- label: field.label || field.fieldname,
177
- fieldtype: field.fieldtype as string,
178
- enabled: Boolean(field.in_list_view),
179
- })),
180
- ];
181
- }, [meta, t]);
182
-
183
- const defaultSelected = useMemo(
184
- () => allColumns.filter((column) => column.enabled).map((column) => column.fieldname),
185
- [allColumns],
186
- );
187
- const [selectedOverride, setSelectedOverride] = useState<string[] | null>(null);
188
- const selected = selectedOverride ?? defaultSelected;
189
-
190
- const handleToggleColumn = useCallback(
191
- (fieldname: string) => {
192
- setSelectedOverride((previous) => {
193
- const current = previous ?? defaultSelected;
194
- if (current.includes(fieldname)) {
195
- // Keep at least one column visible (the toolbar disables the last
196
- // enabled row too — this guard covers races).
197
- if (current.length === 1) return current;
198
- return current.filter((entry) => entry !== fieldname);
199
- }
200
- return [...current, fieldname];
201
- });
202
- },
203
- [defaultSelected],
204
- );
205
-
206
- const builderColumns = useMemo<ReportColumn[]>(
207
- () => allColumns.map((column) => ({ ...column, enabled: selected.includes(column.fieldname) })),
208
- [allColumns, selected],
209
- );
210
-
211
- // ---------------------------------------------------------------------
212
- // Group-by + paging state. Reset per doctype; page resets on any change
213
- // that alters result membership.
214
- // ---------------------------------------------------------------------
215
- const [groupBy, setGroupBy] = useState<GroupByConfig | null>(null);
216
- const [pageSize, setPageSize] = useState<number>(DEFAULT_PAGE_SIZE);
217
- const [page, setPage] = useState(0);
218
-
219
- useEffect(() => {
220
- setSelectedOverride(null);
221
- setGroupBy(null);
222
- setPage(0);
223
- }, [doctype]);
224
-
225
- const filtersKey = useMemo(() => JSON.stringify(queryFilters), [queryFilters]);
226
- useEffect(() => {
227
- setPage(0);
228
- }, [filtersKey, pageSize]);
229
-
230
- // ---------------------------------------------------------------------
231
- // Parallel stats query: names (ordered by the doctype sort field) drive
232
- // pagination windows; numeric fields drive the totals strip; the title
233
- // field feeds the open-record jump. Kept independent of the column
234
- // selection so toggles never resubscribe it.
235
- // ---------------------------------------------------------------------
236
- const numericColumns = useMemo(
237
- () => allColumns.filter((column) => REPORT_NUMERIC_FIELDTYPES.has(column.fieldtype)),
238
- [allColumns],
239
- );
240
- const titleField = meta?.title_field;
241
- const sortField = (meta?.sort_field || "modified").split(" ")[0];
242
- const sortAscending = (meta?.sort_order || "DESC").toLowerCase() === "asc";
243
-
244
- const statsFields = useMemo(() => {
245
- const fields = new Set<string>(["name", sortField]);
246
- if (titleField) fields.add(titleField);
247
- for (const column of numericColumns) fields.add(column.fieldname);
248
- return [...fields];
249
- }, [sortField, titleField, numericColumns]);
250
-
251
- const [statsError, setStatsError] = useState<Error | null>(null);
252
- const handleStatsError = useCallback((error: unknown) => {
253
- setStatsError(error instanceof Error ? error : new Error(String(error)));
254
- }, []);
255
-
256
- // ViewConnection carries syncOptions as `unknown`; the shapes match the
257
- // collection config (same FrappeProvider source) — assert once here.
258
- const statsConfig = useMemo(
259
- () => (connection && meta ? (connection as unknown as UseFrappeCollectionConfig) : undefined),
260
- [connection, meta],
261
- );
262
- const statsCollection = useFrappeCollection<StatsRow>(statsConfig, doctype, {
263
- fields: statsFields,
264
- filters: queryFilters,
265
- orderBy: { field: sortField, order: sortAscending ? Order.Asc : Order.Desc },
266
- onSyncError: handleStatsError,
267
- });
268
- useEffect(() => setStatsError(null), [statsCollection]);
269
- const { data: statsData, isLoading: statsLoading } = useLiveQuery(
270
- (q) => (statsCollection ? q.from({ _stats: statsCollection }) : null),
271
- [statsCollection],
272
- );
273
-
274
- // Live-query row order is not guaranteed — order deterministically by the
275
- // doctype sort field (name tiebreak) so page windows are stable.
276
- const statsRows = useMemo(() => {
277
- const rows = [...((statsData as StatsRow[] | undefined) ?? [])];
278
- const direction = sortAscending ? 1 : -1;
279
- rows.sort((a, b) => {
280
- const left = a[sortField];
281
- const right = b[sortField];
282
- const ordered =
283
- isNullish(left) || isNullish(right)
284
- ? compareValues(left, right)
285
- : direction * compareValues(left, right);
286
- return ordered || compareValues(a.name, b.name);
287
- });
288
- return rows;
289
- }, [statsData, sortField, sortAscending]);
290
-
291
- const statsReady = Boolean(statsError) || !statsLoading;
292
- const total = statsRows.length;
293
- const pageCount = Math.max(1, Math.ceil(total / pageSize));
294
- const effectivePage = Math.min(page, pageCount - 1);
295
- // Small results (or a failed stats query) skip the window: the grid keeps
296
- // the pure live path and refreshes rows in place on realtime events.
297
- const needsWindow = !statsError && total > pageSize;
298
- const pageRows = useMemo(
299
- () =>
300
- needsWindow
301
- ? statsRows.slice(effectivePage * pageSize, (effectivePage + 1) * pageSize)
302
- : statsRows,
303
- [needsWindow, statsRows, effectivePage, pageSize],
304
- );
305
-
306
- const builderFilters = useMemo<FrappeFilters>(() => {
307
- if (!needsWindow) return queryFilters;
308
- return [...queryFilters, ["name", "in", pageRows.map((row) => row.name)]];
309
- }, [needsWindow, queryFilters, pageRows]);
310
-
311
- // ---------------------------------------------------------------------
312
- // Footer inputs: open-record jump + totals over the FULL filtered result
313
- // (not just the page) — desk totals-row parity.
314
- // ---------------------------------------------------------------------
315
- const records = useMemo<ReportRecordRef[]>(
316
- () =>
317
- pageRows.map((row) => ({
318
- name: row.name,
319
- title:
320
- titleField && !isNullish(row[titleField]) && row[titleField] !== ""
321
- ? String(row[titleField])
322
- : row.name,
323
- })),
324
- [pageRows, titleField],
325
- );
326
-
327
- const totals = useMemo<ReportTotal[]>(() => {
328
- if (total === 0) return [];
329
- return builderColumns
330
- .filter((column) => column.enabled && REPORT_NUMERIC_FIELDTYPES.has(column.fieldtype))
331
- .map((column) => ({
332
- label: column.label,
333
- fieldtype: column.fieldtype,
334
- value: statsRows.reduce((sum, row) => sum + (Number(row[column.fieldname]) || 0), 0),
335
- }));
336
- }, [builderColumns, statsRows, total]);
337
-
338
- const handleOpenRecord = useCallback(
339
- (name: string) => {
340
- navigator.navigate(paths.form(doctype, name));
341
- },
342
- [navigator, paths, doctype],
343
- );
344
-
345
- // ---------------------------------------------------------------------
346
- // CSV export: enabled columns of the rows the grid currently holds.
347
- // Web-only (Blob + anchor download); native gets an honest toast.
348
- // ---------------------------------------------------------------------
349
- const handleExport = useCallback(
350
- (exportData: Record<string, unknown>[]) => {
351
- if (!isWeb) {
352
- notify({
353
- severity: "warning",
354
- scope: "page",
355
- body: t(
356
- "report.exportUnsupported",
357
- "CSV export needs a browser download — not available on this platform yet",
358
- ),
359
- });
360
- return;
361
- }
362
- const enabledColumns = builderColumns.filter((column) => column.enabled);
363
- const escapeCell = (value: unknown): string => {
364
- if (value === null || value === undefined) return "";
365
- const text = String(value);
366
- return /[",\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
367
- };
368
- const lines = [
369
- enabledColumns.map((column) => escapeCell(column.label)).join(","),
370
- ...exportData.map((row) =>
371
- enabledColumns.map((column) => escapeCell(row[column.fieldname])).join(","),
372
- ),
373
- ];
374
- downloadBlob(
375
- new Blob([lines.join("\n")], { type: "text/csv;charset=utf-8;" }),
376
- `${doctype}_report.csv`,
377
- );
378
- },
379
- [builderColumns, doctype, t],
380
- );
381
-
382
- // ---------------------------------------------------------------------
383
- // Render
384
- // ---------------------------------------------------------------------
385
- if (isMetaLoading) return <ViewLoading />;
386
- if (metaError && !meta) return <ViewError doctype={doctype} error={metaError} />;
387
-
388
- // ReportBuilder initializes its enabled-column set (and FrappeReportBuilder
389
- // its group-by state) at mount only — remount on selection/group changes.
390
- const builderKey = `${doctype}::${[...selected].sort().join("|")}::${
391
- groupBy ? `${groupBy.field}:${groupBy.aggregation}:${groupBy.aggregationField ?? ""}` : "none"
392
- }`;
393
-
394
- return (
395
- <YStack flex={1} {...knobProps.gap}>
396
- <ReportToolbar
397
- columns={builderColumns}
398
- onToggleColumn={handleToggleColumn}
399
- groupBy={groupBy}
400
- onGroupByChange={setGroupBy}
401
- pageSize={pageSize}
402
- onPageSizeChange={setPageSize}
403
- filters={baseFilters}
404
- onClearFilters={baseFilters.length > 0 ? handleClearFilters : undefined}
405
- />
406
- {statsReady ? (
407
- <FrappeReportBuilder
408
- key={builderKey}
409
- doctype={doctype}
410
- initialColumns={builderColumns}
411
- initialGroupBy={groupBy ?? undefined}
412
- filters={builderFilters}
413
- showChart
414
- onExport={handleExport}
415
- onRowPress={(row) => {
416
- if (typeof row.name === "string" && row.name) {
417
- navigator.navigate(paths.form(doctype, row.name));
418
- }
419
- }}
420
- flex={1}
421
- />
422
- ) : (
423
- <ViewLoading />
424
- )}
425
- {!statsError && statsReady && (
426
- <ReportFooter
427
- page={effectivePage}
428
- pageCount={pageCount}
429
- pageSize={pageSize}
430
- totalItems={total}
431
- onPageChange={setPage}
432
- records={records}
433
- onOpenRecord={handleOpenRecord}
434
- totals={totals}
435
- />
436
- )}
437
- </YStack>
438
- );
439
- }
1
+ // The compatibility name for the desk's report view. It used to compose its
2
+ // own grid around the old FrappeReportBuilder; the desk report is
3
+ // DoctypeReportView (FrappeReportBuilder under the desk's navigation) and
4
+ // this name renders exactly that now (MPO-15, GL-28).
5
+ export { parseReportFiltersParam } from "@multiplatform.one/frappe-ui";
6
+ export { DoctypeReportView as ReportView } from "../report/DoctypeReportView";
7
+ export type { DoctypeReportViewProps as ReportViewProps } from "../report/DoctypeReportView";
@@ -1,12 +1,10 @@
1
- // Report-view chrome around FrappeReportBuilder. The component owns the
2
- // grid, group rendering, save/load and the Export button, but exposes no
3
- // interactive picker / pagination / row-click UI (its column-toggle and
4
- // group-by handlers are dead code) — so the desk chrome lives here:
1
+ // The toolbar and footer the old compatibility ReportView composed around
2
+ // the generic ReportBuilder. That view is DoctypeReportView now (MPO-15,
3
+ // GL-28) and renders neither; both stay exported for hosts that built on
4
+ // them:
5
5
  // - ReportToolbar: column add/remove picker across all meta fields,
6
6
  // group-by + aggregation pickers, page-size selector, filter chips
7
- // - ReportFooter: totals strip (desk "Show Totals" parity, computed over
8
- // the full filtered result), an "Open" record jump (interim affordance
9
- // for the missing per-row click-through), numbered pagination
7
+ // - ReportFooter: totals strip, an "Open" record jump, numbered pagination
10
8
  import {
11
9
  Button,
12
10
  Chip,
@@ -16,7 +14,12 @@ import {
16
14
  XStack,
17
15
  YStack,
18
16
  } from "@multiplatform.one/components";
19
- import type { GroupByConfig, ReportColumn } from "@multiplatform.one/frappe-ui";
17
+ import {
18
+ REPORT_NUMERIC_FIELDTYPES,
19
+ REPORT_PAGE_SIZES,
20
+ type GroupByConfig,
21
+ type ReportColumn,
22
+ } from "@multiplatform.one/frappe-ui";
20
23
  import {
21
24
  formatCurrency,
22
25
  formatNumber,
@@ -29,18 +32,7 @@ import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
29
32
  import type { FrappeFilters } from "../shared/types";
30
33
  import { overlayListMaxHeight } from "../shared/measures";
31
34
 
32
- /** Field types the report can total / aggregate (mirrors ReportBuilder). */
33
- export const REPORT_NUMERIC_FIELDTYPES = new Set([
34
- "Int",
35
- "Float",
36
- "Currency",
37
- "Percent",
38
- "Rating",
39
- "Duration",
40
- ]);
41
-
42
- /** Desk report page lengths. */
43
- export const REPORT_PAGE_SIZES = [20, 100, 500] as const;
35
+ export { REPORT_NUMERIC_FIELDTYPES, REPORT_PAGE_SIZES } from "@multiplatform.one/frappe-ui";
44
36
 
45
37
  const AGGREGATIONS: GroupByConfig["aggregation"][] = ["count", "sum", "avg", "min", "max"];
46
38
 
@@ -1 +1 @@
1
- {"version":3,"file":"DeskSurface.d.ts","sourceRoot":"","sources":["../../src/desk/DeskSurface.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAW,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAKrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AAEjD,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,4DAA4D;AAC5D,MAAM,MAAM,mBAAmB,GAC3B,aAAa,CAAC,gBAAgB,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAEpD,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAoCzF,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,gEAAgE;IAChE,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACnC;AAED,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,SAAS,EACT,QAAQ,EACR,cAAc,EACd,KAAK,GACN,EAAE,oBAAoB,2CAuCtB;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,4CAMjC"}
1
+ {"version":3,"file":"DeskSurface.d.ts","sourceRoot":"","sources":["../../src/desk/DeskSurface.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAW,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAKrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AAEjD,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,4DAA4D;AAC5D,MAAM,MAAM,mBAAmB,GAC3B,aAAa,CAAC,gBAAgB,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAEpD,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAoCzF,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,gEAAgE;IAChE,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACnC;AAED,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,SAAS,EACT,QAAQ,EACR,cAAc,EACd,KAAK,GACN,EAAE,oBAAoB,2CAoCtB;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,4CAMjC"}
@@ -16,9 +16,9 @@ export interface DocFormScreenProps {
16
16
  name: string;
17
17
  /** Force the whole form read-only regardless of permissions. */
18
18
  readOnly?: boolean;
19
- /** Hide form sections/tabs by Section/Tab Break fieldname or label. */
19
+ /** Hide form sections/tabs by Section/Tab Break name or label. */
20
20
  hiddenSections?: readonly string[];
21
- /** Hide individual fields by fieldname. */
21
+ /** Hide individual fields by name. */
22
22
  hiddenFields?: readonly string[];
23
23
  /** Create-mode field prefill (merged over meta defaults). */
24
24
  defaults?: Record<string, unknown>;
@@ -1 +1 @@
1
- {"version":3,"file":"DocFormScreen.d.ts","sourceRoot":"","sources":["../../src/form/DocFormScreen.tsx"],"names":[],"mappings":"AA0CA,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,8BAA8B,CAAC;AAqCtC,oDAAoD;AACpD,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uEAAuE;IACvE,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,2CAA2C;IAC3C,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,+EAA+E;IAC/E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACpE,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,wDAAwD;IACxD,eAAe,CAAC,EAAE,sBAAsB,CAAC;CAC1C;AAID,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,SAAS,EACT,eAAe,GAChB,EAAE,kBAAkB,2CAqgCpB"}
1
+ {"version":3,"file":"DocFormScreen.d.ts","sourceRoot":"","sources":["../../src/form/DocFormScreen.tsx"],"names":[],"mappings":"AA8CA,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,8BAA8B,CAAC;AAiCtC,oDAAoD;AACpD,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kEAAkE;IAClE,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,sCAAsC;IACtC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,+EAA+E;IAC/E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACpE,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,wDAAwD;IACxD,eAAe,CAAC,EAAE,sBAAsB,CAAC;CAC1C;AAMD,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,SAAS,EACT,eAAe,GAChB,EAAE,kBAAkB,2CA85BpB"}
@@ -269,6 +269,7 @@ export declare const en: {
269
269
  readonly executionTime: "ran in {{seconds}}s";
270
270
  readonly filtersRequiredDescription: "Set the required filter(s) to run this report: {{filters}}";
271
271
  readonly filtersRequiredTitle: "Filters required";
272
+ readonly notPermitted: "You can't run \"{{report}}\"";
272
273
  readonly refresh: "Refresh";
273
274
  readonly retry: "Retry";
274
275
  readonly rowCount: "{{count}} row(s)";
@@ -1 +1 @@
1
- {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4aL,CAAC"}
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6aL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ListBulkActionsBar.d.ts","sourceRoot":"","sources":["../../src/list/ListBulkActionsBar.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAS5D,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,8BAA8B;IAC9B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,mEAAmE;IACnE,gBAAgB,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,IAAI,EACJ,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GACjB,EAAE,uBAAuB,kDAuUzB"}
1
+ {"version":3,"file":"ListBulkActionsBar.d.ts","sourceRoot":"","sources":["../../src/list/ListBulkActionsBar.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAU5D,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,8BAA8B;IAC9B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,mEAAmE;IACnE,gBAAgB,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,IAAI,EACJ,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GACjB,EAAE,uBAAuB,kDAyVzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-section.d.ts","sourceRoot":"","sources":["../../src/list/sidebar-section.tsx"],"names":[],"mappings":"AAyBA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI3E,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;wEACwE;AACxE,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,2CAuB3F;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CAM7E;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,oBAAoB,2CA8CtF;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,sBAAsB,CAAC,EAAE,IAAQ,EAAE,EAAE,2BAA2B,2CAkB/E"}
1
+ {"version":3,"file":"sidebar-section.d.ts","sourceRoot":"","sources":["../../src/list/sidebar-section.tsx"],"names":[],"mappings":"AA0BA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI3E,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAWD;wEACwE;AACxE,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,2CAqB3F;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CAM7E;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,oBAAoB,2CA8CtF;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,sBAAsB,CAAC,EAAE,IAAQ,EAAE,EAAE,2BAA2B,2CAkB/E"}
@@ -1 +1 @@
1
- {"version":3,"file":"DoctypeReportView.d.ts","sourceRoot":"","sources":["../../src/report/DoctypeReportView.tsx"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAuBrD,MAAM,WAAW,sBAAsB;IACrC,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,cAAc,CAAC,EAAE,aAAa,CAAC;CAChC;AA+BD,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,YAAY,EACZ,cAAc,GACf,EAAE,sBAAsB,2CAifxB"}
1
+ {"version":3,"file":"DoctypeReportView.d.ts","sourceRoot":"","sources":["../../src/report/DoctypeReportView.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,MAAM,WAAW,sBAAsB;IACrC,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,cAAc,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,YAAY,EACZ,cAAc,GACf,EAAE,sBAAsB,2CAgDxB"}
@@ -1,4 +1,4 @@
1
- import { type QueryReportFilters, type QueryReportFixture } from "./useQueryReport";
1
+ import { type QueryReportFilters, type QueryReportFixture } from "@multiplatform.one/frappe-ui";
2
2
  export interface QueryReportScreenProps {
3
3
  /** Report document name (proper-cased, e.g. "Permitted Documents For User"). */
4
4
  reportName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"QueryReportScreen.d.ts","sourceRoot":"","sources":["../../src/report/QueryReportScreen.tsx"],"names":[],"mappings":"AAwCA,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EAIxB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,sBAAsB;IACrC,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,mFAAmF;IACnF,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACpC,wCAAwC;IACxC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAID,wBAAgB,iBAAiB,CAAC,EAChC,UAAU,EACV,OAAO,EACP,cAAc,EACd,aAAa,EACb,SAAS,GACV,EAAE,sBAAsB,2CAwRxB"}
1
+ {"version":3,"file":"QueryReportScreen.d.ts","sourceRoot":"","sources":["../../src/report/QueryReportScreen.tsx"],"names":[],"mappings":"AAiCA,OAAO,EAQL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACxB,MAAM,8BAA8B,CAAC;AAQtC,MAAM,WAAW,sBAAsB;IACrC,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,mFAAmF;IACnF,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACpC,wCAAwC;IACxC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAID,wBAAgB,iBAAiB,CAAC,EAChC,UAAU,EACV,OAAO,EACP,cAAc,EACd,aAAa,EACb,SAAS,GACV,EAAE,sBAAsB,2CAuSxB"}
@@ -1,12 +1,3 @@
1
- import type { DataTableColumn } from "@multiplatform.one/table";
2
- import { type QueryReportColumn, type QueryReportRow } from "./useQueryReport";
3
- export interface BuildQueryReportColumnsArgs {
4
- columns: readonly QueryReportColumn[];
5
- /** Open a Link cell's target document (doctype comes from column options). */
6
- onOpenLink?: (doctype: string, name: string) => void;
7
- }
8
- /** Build DataTable columns for a query-report run result. */
9
- export declare function buildQueryReportColumns({ columns, onOpenLink, }: BuildQueryReportColumnsArgs): DataTableColumn<QueryReportRow>[];
10
- /** CSV over the full run result (Desk Export, not just the current page). */
11
- export declare function buildQueryReportCsv(columns: readonly QueryReportColumn[], rows: readonly QueryReportRow[]): string;
1
+ export { buildQueryReportColumns, buildQueryReportCsv } from "@multiplatform.one/frappe-ui";
2
+ export type { BuildQueryReportColumnsArgs } from "@multiplatform.one/frappe-ui";
12
3
  //# sourceMappingURL=queryReportColumns.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queryReportColumns.d.ts","sourceRoot":"","sources":["../../src/report/queryReportColumns.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAa,MAAM,kBAAkB,CAAC;AAI1F,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACtC,8EAA8E;IAC9E,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtD;AA0ED,6DAA6D;AAC7D,wBAAgB,uBAAuB,CAAC,EACtC,OAAO,EACP,UAAU,GACX,EAAE,2BAA2B,GAAG,eAAe,CAAC,cAAc,CAAC,EAAE,CAWjE;AAQD,6EAA6E;AAC7E,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS,iBAAiB,EAAE,EACrC,IAAI,EAAE,SAAS,cAAc,EAAE,GAC9B,MAAM,CAKR"}
1
+ {"version":3,"file":"queryReportColumns.d.ts","sourceRoot":"","sources":["../../src/report/queryReportColumns.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC5F,YAAY,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC"}
@@ -1,4 +1,4 @@
1
- import { type QueryReportFilterMeta, type QueryReportFilters } from "./reportShapes";
1
+ import { type QueryReportFilterMeta, type QueryReportFilters } from "@multiplatform.one/frappe-ui";
2
2
  export declare function queryReportFilterLabel(filter: QueryReportFilterMeta): string;
3
3
  /** Discrete kinds commit the run as soon as the value lands (Desk/Metabase). */
4
4
  export declare function queryReportFilterAppliesOnChange(filter: QueryReportFilterMeta): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"queryReportFilterBar.d.ts","sourceRoot":"","sources":["../../src/report/queryReportFilterBar.tsx"],"names":[],"mappings":"AAiCA,OAAO,EAGL,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACxB,MAAM,gBAAgB,CAAC;AAExB,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAE5E;AAED,gFAAgF;AAChF,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAGvF;AAED,8FAA8F;AAC9F,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,QAAQ,EAAE,MAAM,GACf,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAIzC;AAwJD,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC7C,OAAO,EAAE,kBAAkB,CAAC;IAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC7C;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,yBAAyB,2CAuG/F"}
1
+ {"version":3,"file":"queryReportFilterBar.d.ts","sourceRoot":"","sources":["../../src/report/queryReportFilterBar.tsx"],"names":[],"mappings":"AA0BA,OAAO,EAQL,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACxB,MAAM,8BAA8B,CAAC;AAEtC,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAE5E;AAED,gFAAgF;AAChF,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAGvF;AAED,8FAA8F;AAC9F,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,QAAQ,EAAE,MAAM,GACf,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAIzC;AAwJD,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC7C,OAAO,EAAE,kBAAkB,CAAC;IAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC7C;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,yBAAyB,2CAuG/F"}
@@ -12,7 +12,7 @@
12
12
  * `setParams` (history REPLACE, no remount) and adopts inbound param changes
13
13
  * (deep links, back/forward), so reload and shared links reproduce the run.
14
14
  */
15
- import { type QueryReportFilters } from "./reportShapes";
15
+ import { type QueryReportFilters } from "@multiplatform.one/frappe-ui";
16
16
  /**
17
17
  * Parse the `?filters=` deep-link value. The router usually decodes the
18
18
  * param already, so the raw value is tried first (same contract as the
@@ -1 +1 @@
1
- {"version":3,"file":"queryReportUrlState.d.ts","sourceRoot":"","sources":["../../src/report/queryReportUrlState.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAE7E;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GACjC,kBAAkB,CA0BpB;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAUhG"}
1
+ {"version":3,"file":"queryReportUrlState.d.ts","sourceRoot":"","sources":["../../src/report/queryReportUrlState.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAE3F;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GACjC,kBAAkB,CA0BpB;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAUhG"}