@multiplatform.one/frappe-ui 7.28.1 → 7.29.1

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 (325) hide show
  1. package/dist/cjs/FrappeCalendar.cjs +3 -2
  2. package/dist/cjs/FrappeCalendar.native.js +3 -2
  3. package/dist/cjs/FrappeCalendar.native.js.map +1 -1
  4. package/dist/cjs/FrappeForm.cjs +148 -464
  5. package/dist/cjs/FrappeForm.native.js +152 -633
  6. package/dist/cjs/FrappeForm.native.js.map +1 -1
  7. package/dist/cjs/FrappeListView.cjs +5 -27
  8. package/dist/cjs/FrappeListView.native.js +11 -32
  9. package/dist/cjs/FrappeListView.native.js.map +1 -1
  10. package/dist/cjs/FrappeReportBuilder.cjs +523 -309
  11. package/dist/cjs/FrappeReportBuilder.native.js +658 -353
  12. package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
  13. package/dist/cjs/FrappeReportView.cjs +35 -234
  14. package/dist/cjs/FrappeReportView.native.js +39 -283
  15. package/dist/cjs/FrappeReportView.native.js.map +1 -1
  16. package/dist/cjs/dependsOn.cjs +2 -2
  17. package/dist/cjs/dependsOn.native.js +1 -2
  18. package/dist/cjs/dependsOn.native.js.map +1 -1
  19. package/dist/cjs/fields/shared/EditorPreviewPanes.cjs +2 -2
  20. package/dist/cjs/fields/shared/EditorPreviewPanes.native.js +2 -2
  21. package/dist/cjs/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  22. package/dist/cjs/formEngine/docPermissions.cjs +20 -0
  23. package/dist/cjs/formEngine/docPermissions.native.js +69 -0
  24. package/dist/cjs/formEngine/docPermissions.native.js.map +1 -1
  25. package/dist/cjs/formEngine/index.cjs +2 -0
  26. package/dist/cjs/formEngine/index.native.js +2 -0
  27. package/dist/cjs/formEngine/index.native.js.map +1 -1
  28. package/dist/cjs/index.cjs +67 -7
  29. package/dist/cjs/index.native.js +67 -7
  30. package/dist/cjs/index.native.js.map +1 -1
  31. package/dist/cjs/liveErrors.cjs +8 -2
  32. package/dist/cjs/liveErrors.native.js +8 -2
  33. package/dist/cjs/liveErrors.native.js.map +1 -1
  34. package/dist/cjs/measures.cjs +31 -0
  35. package/dist/cjs/measures.native.js +34 -0
  36. package/dist/cjs/measures.native.js.map +1 -0
  37. package/dist/cjs/recordShape.cjs +103 -0
  38. package/dist/cjs/recordShape.native.js +115 -0
  39. package/dist/cjs/recordShape.native.js.map +1 -0
  40. package/dist/cjs/report/ReportGrid.cjs +453 -0
  41. package/dist/cjs/report/ReportGrid.native.js +510 -0
  42. package/dist/cjs/report/ReportGrid.native.js.map +1 -0
  43. package/dist/cjs/report/ReportViewToolbar.cjs +253 -0
  44. package/dist/cjs/report/ReportViewToolbar.native.js +303 -0
  45. package/dist/cjs/report/ReportViewToolbar.native.js.map +1 -0
  46. package/dist/cjs/report/queryReport.cjs +444 -0
  47. package/dist/cjs/report/queryReport.native.js +588 -0
  48. package/dist/cjs/report/queryReport.native.js.map +1 -0
  49. package/dist/cjs/report/queryReportColumns.cjs +131 -0
  50. package/dist/cjs/report/queryReportColumns.native.js +159 -0
  51. package/dist/cjs/report/queryReportColumns.native.js.map +1 -0
  52. package/dist/cjs/report/reportViewModel.cjs +386 -0
  53. package/dist/cjs/report/reportViewModel.native.js +657 -0
  54. package/dist/cjs/report/reportViewModel.native.js.map +1 -0
  55. package/dist/cjs/report/savedReports.cjs +137 -0
  56. package/dist/cjs/report/savedReports.native.js +169 -0
  57. package/dist/cjs/report/savedReports.native.js.map +1 -0
  58. package/dist/cjs/report/useFrappeReport.cjs +184 -0
  59. package/dist/cjs/report/useFrappeReport.native.js +214 -0
  60. package/dist/cjs/report/useFrappeReport.native.js.map +1 -0
  61. package/dist/cjs/report/useQueryReport.cjs +201 -0
  62. package/dist/cjs/report/useQueryReport.native.js +233 -0
  63. package/dist/cjs/report/useQueryReport.native.js.map +1 -0
  64. package/dist/cjs/useFrappeForm.cjs +558 -0
  65. package/dist/cjs/useFrappeForm.native.js +714 -0
  66. package/dist/cjs/useFrappeForm.native.js.map +1 -0
  67. package/dist/esm/FrappeCalendar.mjs +4 -3
  68. package/dist/esm/FrappeCalendar.mjs.map +1 -1
  69. package/dist/esm/FrappeCalendar.native.js +4 -3
  70. package/dist/esm/FrappeCalendar.native.js.map +1 -1
  71. package/dist/esm/FrappeForm.mjs +151 -467
  72. package/dist/esm/FrappeForm.mjs.map +1 -1
  73. package/dist/esm/FrappeForm.native.js +155 -636
  74. package/dist/esm/FrappeForm.native.js.map +1 -1
  75. package/dist/esm/FrappeListView.mjs +6 -28
  76. package/dist/esm/FrappeListView.mjs.map +1 -1
  77. package/dist/esm/FrappeListView.native.js +12 -33
  78. package/dist/esm/FrappeListView.native.js.map +1 -1
  79. package/dist/esm/FrappeReportBuilder.mjs +526 -312
  80. package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
  81. package/dist/esm/FrappeReportBuilder.native.js +661 -356
  82. package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
  83. package/dist/esm/FrappeReportView.mjs +30 -229
  84. package/dist/esm/FrappeReportView.mjs.map +1 -1
  85. package/dist/esm/FrappeReportView.native.js +34 -278
  86. package/dist/esm/FrappeReportView.native.js.map +1 -1
  87. package/dist/esm/dependsOn.mjs +2 -2
  88. package/dist/esm/dependsOn.mjs.map +1 -1
  89. package/dist/esm/dependsOn.native.js +1 -2
  90. package/dist/esm/dependsOn.native.js.map +1 -1
  91. package/dist/esm/fields/shared/EditorPreviewPanes.mjs +2 -2
  92. package/dist/esm/fields/shared/EditorPreviewPanes.mjs.map +1 -1
  93. package/dist/esm/fields/shared/EditorPreviewPanes.native.js +2 -2
  94. package/dist/esm/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  95. package/dist/esm/formEngine/docPermissions.mjs +19 -1
  96. package/dist/esm/formEngine/docPermissions.mjs.map +1 -1
  97. package/dist/esm/formEngine/docPermissions.native.js +68 -1
  98. package/dist/esm/formEngine/docPermissions.native.js.map +1 -1
  99. package/dist/esm/formEngine/index.mjs +2 -2
  100. package/dist/esm/formEngine/index.mjs.map +1 -1
  101. package/dist/esm/formEngine/index.native.js +2 -2
  102. package/dist/esm/formEngine/index.native.js.map +1 -1
  103. package/dist/esm/index.mjs +16 -4
  104. package/dist/esm/index.mjs.map +1 -1
  105. package/dist/esm/index.native.js +16 -4
  106. package/dist/esm/index.native.js.map +1 -1
  107. package/dist/esm/liveErrors.mjs +8 -3
  108. package/dist/esm/liveErrors.mjs.map +1 -1
  109. package/dist/esm/liveErrors.native.js +8 -3
  110. package/dist/esm/liveErrors.native.js.map +1 -1
  111. package/dist/esm/measures.mjs +5 -0
  112. package/dist/esm/measures.mjs.map +1 -0
  113. package/dist/esm/measures.native.js +5 -0
  114. package/dist/esm/measures.native.js.map +1 -0
  115. package/dist/esm/recordShape.mjs +74 -0
  116. package/dist/esm/recordShape.mjs.map +1 -0
  117. package/dist/esm/recordShape.native.js +83 -0
  118. package/dist/esm/recordShape.native.js.map +1 -0
  119. package/dist/esm/report/ReportGrid.mjs +428 -0
  120. package/dist/esm/report/ReportGrid.mjs.map +1 -0
  121. package/dist/esm/report/ReportGrid.native.js +471 -0
  122. package/dist/esm/report/ReportGrid.native.js.map +1 -0
  123. package/dist/esm/report/ReportViewToolbar.mjs +228 -0
  124. package/dist/esm/report/ReportViewToolbar.mjs.map +1 -0
  125. package/dist/esm/report/ReportViewToolbar.native.js +264 -0
  126. package/dist/esm/report/ReportViewToolbar.native.js.map +1 -0
  127. package/dist/esm/report/queryReport.mjs +404 -0
  128. package/dist/esm/report/queryReport.mjs.map +1 -0
  129. package/dist/esm/report/queryReport.native.js +545 -0
  130. package/dist/esm/report/queryReport.native.js.map +1 -0
  131. package/dist/esm/report/queryReportColumns.mjs +105 -0
  132. package/dist/esm/report/queryReportColumns.mjs.map +1 -0
  133. package/dist/esm/report/queryReportColumns.native.js +119 -0
  134. package/dist/esm/report/queryReportColumns.native.js.map +1 -0
  135. package/dist/esm/report/reportViewModel.mjs +343 -0
  136. package/dist/esm/report/reportViewModel.mjs.map +1 -0
  137. package/dist/esm/report/reportViewModel.native.js +611 -0
  138. package/dist/esm/report/reportViewModel.native.js.map +1 -0
  139. package/dist/esm/report/savedReports.mjs +112 -0
  140. package/dist/esm/report/savedReports.mjs.map +1 -0
  141. package/dist/esm/report/savedReports.native.js +141 -0
  142. package/dist/esm/report/savedReports.native.js.map +1 -0
  143. package/dist/esm/report/useFrappeReport.mjs +158 -0
  144. package/dist/esm/report/useFrappeReport.mjs.map +1 -0
  145. package/dist/esm/report/useFrappeReport.native.js +185 -0
  146. package/dist/esm/report/useFrappeReport.native.js.map +1 -0
  147. package/dist/esm/report/useQueryReport.mjs +176 -0
  148. package/dist/esm/report/useQueryReport.mjs.map +1 -0
  149. package/dist/esm/report/useQueryReport.native.js +205 -0
  150. package/dist/esm/report/useQueryReport.native.js.map +1 -0
  151. package/dist/esm/useFrappeForm.mjs +533 -0
  152. package/dist/esm/useFrappeForm.mjs.map +1 -0
  153. package/dist/esm/useFrappeForm.native.js +686 -0
  154. package/dist/esm/useFrappeForm.native.js.map +1 -0
  155. package/dist/jsx/FrappeCalendar.mjs +4 -3
  156. package/dist/jsx/FrappeCalendar.mjs.map +1 -1
  157. package/dist/jsx/FrappeCalendar.native.js +3 -2
  158. package/dist/jsx/FrappeCalendar.native.js.map +1 -1
  159. package/dist/jsx/FrappeForm.mjs +151 -467
  160. package/dist/jsx/FrappeForm.mjs.map +1 -1
  161. package/dist/jsx/FrappeForm.native.js +152 -633
  162. package/dist/jsx/FrappeForm.native.js.map +1 -1
  163. package/dist/jsx/FrappeListView.mjs +6 -28
  164. package/dist/jsx/FrappeListView.mjs.map +1 -1
  165. package/dist/jsx/FrappeListView.native.js +11 -32
  166. package/dist/jsx/FrappeListView.native.js.map +1 -1
  167. package/dist/jsx/FrappeReportBuilder.mjs +526 -312
  168. package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
  169. package/dist/jsx/FrappeReportBuilder.native.js +658 -353
  170. package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
  171. package/dist/jsx/FrappeReportView.mjs +30 -229
  172. package/dist/jsx/FrappeReportView.mjs.map +1 -1
  173. package/dist/jsx/FrappeReportView.native.js +39 -283
  174. package/dist/jsx/FrappeReportView.native.js.map +1 -1
  175. package/dist/jsx/dependsOn.mjs +2 -2
  176. package/dist/jsx/dependsOn.mjs.map +1 -1
  177. package/dist/jsx/dependsOn.native.js +1 -2
  178. package/dist/jsx/dependsOn.native.js.map +1 -1
  179. package/dist/jsx/fields/shared/EditorPreviewPanes.mjs +2 -2
  180. package/dist/jsx/fields/shared/EditorPreviewPanes.mjs.map +1 -1
  181. package/dist/jsx/fields/shared/EditorPreviewPanes.native.js +2 -2
  182. package/dist/jsx/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  183. package/dist/jsx/formEngine/docPermissions.mjs +19 -1
  184. package/dist/jsx/formEngine/docPermissions.mjs.map +1 -1
  185. package/dist/jsx/formEngine/docPermissions.native.js +69 -0
  186. package/dist/jsx/formEngine/docPermissions.native.js.map +1 -1
  187. package/dist/jsx/formEngine/index.mjs +2 -2
  188. package/dist/jsx/formEngine/index.mjs.map +1 -1
  189. package/dist/jsx/formEngine/index.native.js +2 -0
  190. package/dist/jsx/formEngine/index.native.js.map +1 -1
  191. package/dist/jsx/index.js +16 -4
  192. package/dist/jsx/index.js.map +1 -1
  193. package/dist/jsx/index.mjs +16 -4
  194. package/dist/jsx/index.mjs.map +1 -1
  195. package/dist/jsx/index.native.js +67 -7
  196. package/dist/jsx/index.native.js.map +1 -1
  197. package/dist/jsx/liveErrors.mjs +8 -3
  198. package/dist/jsx/liveErrors.mjs.map +1 -1
  199. package/dist/jsx/liveErrors.native.js +8 -2
  200. package/dist/jsx/liveErrors.native.js.map +1 -1
  201. package/dist/jsx/measures.mjs +5 -0
  202. package/dist/jsx/measures.mjs.map +1 -0
  203. package/dist/jsx/measures.native.js +34 -0
  204. package/dist/jsx/measures.native.js.map +1 -0
  205. package/dist/jsx/recordShape.mjs +74 -0
  206. package/dist/jsx/recordShape.mjs.map +1 -0
  207. package/dist/jsx/recordShape.native.js +115 -0
  208. package/dist/jsx/recordShape.native.js.map +1 -0
  209. package/dist/jsx/report/ReportGrid.mjs +428 -0
  210. package/dist/jsx/report/ReportGrid.mjs.map +1 -0
  211. package/dist/jsx/report/ReportGrid.native.js +510 -0
  212. package/dist/jsx/report/ReportGrid.native.js.map +1 -0
  213. package/dist/jsx/report/ReportViewToolbar.mjs +228 -0
  214. package/dist/jsx/report/ReportViewToolbar.mjs.map +1 -0
  215. package/dist/jsx/report/ReportViewToolbar.native.js +303 -0
  216. package/dist/jsx/report/ReportViewToolbar.native.js.map +1 -0
  217. package/dist/jsx/report/queryReport.mjs +404 -0
  218. package/dist/jsx/report/queryReport.mjs.map +1 -0
  219. package/dist/jsx/report/queryReport.native.js +588 -0
  220. package/dist/jsx/report/queryReport.native.js.map +1 -0
  221. package/dist/jsx/report/queryReportColumns.mjs +105 -0
  222. package/dist/jsx/report/queryReportColumns.mjs.map +1 -0
  223. package/dist/jsx/report/queryReportColumns.native.js +159 -0
  224. package/dist/jsx/report/queryReportColumns.native.js.map +1 -0
  225. package/dist/jsx/report/reportViewModel.mjs +343 -0
  226. package/dist/jsx/report/reportViewModel.mjs.map +1 -0
  227. package/dist/jsx/report/reportViewModel.native.js +657 -0
  228. package/dist/jsx/report/reportViewModel.native.js.map +1 -0
  229. package/dist/jsx/report/savedReports.mjs +112 -0
  230. package/dist/jsx/report/savedReports.mjs.map +1 -0
  231. package/dist/jsx/report/savedReports.native.js +169 -0
  232. package/dist/jsx/report/savedReports.native.js.map +1 -0
  233. package/dist/jsx/report/useFrappeReport.mjs +158 -0
  234. package/dist/jsx/report/useFrappeReport.mjs.map +1 -0
  235. package/dist/jsx/report/useFrappeReport.native.js +214 -0
  236. package/dist/jsx/report/useFrappeReport.native.js.map +1 -0
  237. package/dist/jsx/report/useQueryReport.mjs +176 -0
  238. package/dist/jsx/report/useQueryReport.mjs.map +1 -0
  239. package/dist/jsx/report/useQueryReport.native.js +233 -0
  240. package/dist/jsx/report/useQueryReport.native.js.map +1 -0
  241. package/dist/jsx/useFrappeForm.mjs +533 -0
  242. package/dist/jsx/useFrappeForm.mjs.map +1 -0
  243. package/dist/jsx/useFrappeForm.native.js +714 -0
  244. package/dist/jsx/useFrappeForm.native.js.map +1 -0
  245. package/package.json +16 -16
  246. package/src/FrappeCalendar.tsx +8 -2
  247. package/src/FrappeForm.stories.tsx +52 -0
  248. package/src/FrappeForm.tsx +176 -565
  249. package/src/FrappeListView.cards.stories.tsx +3 -6
  250. package/src/FrappeListView.tsx +15 -55
  251. package/src/FrappeReportBuilder.stories.tsx +34 -7
  252. package/src/FrappeReportBuilder.tsx +790 -380
  253. package/src/FrappeReportView.spec.tsx +10 -6
  254. package/src/FrappeReportView.stories.tsx +20 -1
  255. package/src/FrappeReportView.tsx +89 -415
  256. package/src/dependsOn.ts +4 -1
  257. package/src/fields/shared/EditorPreviewPanes.tsx +2 -2
  258. package/src/formEngine/docPermissions.spec.ts +36 -1
  259. package/src/formEngine/docPermissions.ts +34 -0
  260. package/src/formEngine/index.ts +8 -1
  261. package/src/frappeRemainder.designLaw.spec.ts +9 -1
  262. package/src/frappeRoutes.spec.tsx +9 -0
  263. package/src/frappeViews.designLaw.spec.ts +15 -2
  264. package/src/guestFallback.spec.tsx +236 -0
  265. package/src/index.ts +117 -16
  266. package/src/liveErrors.spec.ts +10 -0
  267. package/src/liveErrors.ts +16 -3
  268. package/src/measures.ts +11 -0
  269. package/src/recordShape.spec.ts +100 -0
  270. package/src/recordShape.ts +133 -0
  271. package/src/report/ReportGrid.spec.tsx +175 -0
  272. package/src/report/ReportGrid.tsx +530 -0
  273. package/src/report/ReportViewToolbar.spec.tsx +90 -0
  274. package/src/report/ReportViewToolbar.tsx +314 -0
  275. package/src/report/queryReport.spec.ts +483 -0
  276. package/src/report/queryReport.ts +722 -0
  277. package/src/report/queryReportColumns.tsx +123 -0
  278. package/src/report/reportViewModel.spec.ts +393 -0
  279. package/src/report/reportViewModel.ts +617 -0
  280. package/src/report/savedReports.ts +172 -0
  281. package/src/report/seam.spec.ts +216 -0
  282. package/src/report/useFrappeReport.ts +241 -0
  283. package/src/report/useQueryReport.spec.tsx +131 -0
  284. package/src/report/useQueryReport.ts +309 -0
  285. package/src/useFrappeForm.spec.tsx +209 -0
  286. package/src/useFrappeForm.ts +778 -0
  287. package/types/FrappeCalendar.d.ts.map +1 -1
  288. package/types/FrappeForm.d.ts +21 -1
  289. package/types/FrappeForm.d.ts.map +1 -1
  290. package/types/FrappeListView.d.ts.map +1 -1
  291. package/types/FrappeReportBuilder.d.ts +66 -16
  292. package/types/FrappeReportBuilder.d.ts.map +1 -1
  293. package/types/FrappeReportView.d.ts +9 -127
  294. package/types/FrappeReportView.d.ts.map +1 -1
  295. package/types/dependsOn.d.ts.map +1 -1
  296. package/types/formEngine/docPermissions.d.ts +14 -0
  297. package/types/formEngine/docPermissions.d.ts.map +1 -1
  298. package/types/formEngine/index.d.ts +1 -1
  299. package/types/formEngine/index.d.ts.map +1 -1
  300. package/types/index.d.ts +15 -3
  301. package/types/index.d.ts.map +1 -1
  302. package/types/liveErrors.d.ts +9 -1
  303. package/types/liveErrors.d.ts.map +1 -1
  304. package/types/measures.d.ts +3 -0
  305. package/types/measures.d.ts.map +1 -0
  306. package/types/recordShape.d.ts +45 -0
  307. package/types/recordShape.d.ts.map +1 -0
  308. package/types/report/ReportGrid.d.ts +20 -0
  309. package/types/report/ReportGrid.d.ts.map +1 -0
  310. package/types/report/ReportViewToolbar.d.ts +31 -0
  311. package/types/report/ReportViewToolbar.d.ts.map +1 -0
  312. package/types/report/queryReport.d.ts +181 -0
  313. package/types/report/queryReport.d.ts.map +1 -0
  314. package/types/report/queryReportColumns.d.ts +12 -0
  315. package/types/report/queryReportColumns.d.ts.map +1 -0
  316. package/types/report/reportViewModel.d.ts +146 -0
  317. package/types/report/reportViewModel.d.ts.map +1 -0
  318. package/types/report/savedReports.d.ts +27 -0
  319. package/types/report/savedReports.d.ts.map +1 -0
  320. package/types/report/useFrappeReport.d.ts +60 -0
  321. package/types/report/useFrappeReport.d.ts.map +1 -0
  322. package/types/report/useQueryReport.d.ts +37 -0
  323. package/types/report/useQueryReport.d.ts.map +1 -0
  324. package/types/useFrappeForm.d.ts +142 -0
  325. package/types/useFrappeForm.d.ts.map +1 -0
@@ -1,229 +1,423 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useDocTypeMeta, useFrappeDoctypeEvents } from "@multiplatform.one/frappe";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { BarChart, EmptyState, ScrollView, Spinner, YStack, isWeb, notify } from "@multiplatform.one/components";
3
+ import { Order, frappeFieldTypes, useDocTypeMeta } from "@multiplatform.one/frappe";
4
+ import { Button } from "@multiplatform.one/forms";
3
5
  import { downloadBlob } from "@multiplatform.one/platform";
4
- import { ReportBuilder, PopoverContent, Separator } from "@multiplatform.one/components";
5
- import { Button, Input, Spinner, formCommonColors } from "@multiplatform.one/forms";
6
6
  import { storage } from "@multiplatform.one/store";
7
- import React, { useMemo, useState, useCallback, useEffect, useRef } from "react";
8
- import { useTranslation } from "react-i18next";
9
- import { Popover, Text, XStack, YStack } from "tamagui";
10
- import { FloppyDiskIcon, FolderOpenIcon, TrashIcon } from "@phosphor-icons/react";
7
+ import { DataTablePagination } from "@multiplatform.one/table";
11
8
  import { useResolvedKnobs } from "@multiplatform.one/theme";
9
+ import React, { useCallback, useEffect, useMemo, useState } from "react";
10
+ import { useTranslation } from "react-i18next";
11
+ import { FrappeNotConfigured } from "./FrappeNotConfigured.native.js";
12
12
  import { useFrappeConfig } from "./FrappeProvider.native.js";
13
+ import { isPermissionError, refusalReason } from "./liveErrors.native.js";
14
+ import { recordKeyLabel, useRecordShape } from "./recordShape.native.js";
15
+ import { ReportGrid } from "./report/ReportGrid.native.js";
16
+ import { ReportViewToolbar } from "./report/ReportViewToolbar.native.js";
17
+ import { DEFAULT_REPORT_PAGE_SIZE, REPORT_PAGE_SIZES, buildGridRows, buildReportCsv, columnFilterTuples, computeTotals, defaultReportFieldnames, orderReportRows, reportColumnsFromMeta, resolveSelectedColumns } from "./report/reportViewModel.native.js";
18
+ import { useSavedReports } from "./report/savedReports.native.js";
13
19
  import { useFrappeRows } from "./useFrappeRows.native.js";
14
- function getSavedReportsKey(doctype) {
15
- return `frappe-report-${doctype}`;
20
+ function _instanceof(left, right) {
21
+ "@swc/helpers - instanceof";
22
+
23
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
24
+ return !!right[Symbol.hasInstance](left);
25
+ } else {
26
+ return left instanceof right;
27
+ }
28
+ }
29
+ function _type_of(obj) {
30
+ "@swc/helpers - typeof";
31
+
32
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
33
+ }
34
+ var EMPTY_FILTERS = [];
35
+ var COLUMN_FILTER_DEBOUNCE_MS = 350;
36
+ function columnsStorageKey(doctype) {
37
+ return `backoffice.report.columns.${doctype}`;
16
38
  }
17
- async function loadSavedReports(doctype) {
39
+ async function readStoredColumns(doctype) {
18
40
  try {
19
- var raw = await Promise.resolve(storage.getItem(getSavedReportsKey(doctype)));
20
- if (raw) return JSON.parse(raw);
41
+ var raw = await Promise.resolve(storage.getItem(columnsStorageKey(doctype)));
42
+ if (!raw) return void 0;
43
+ var parsed = JSON.parse(raw);
44
+ if (Array.isArray(parsed) && parsed.every(function (entry) {
45
+ return typeof entry === "string";
46
+ })) {
47
+ return parsed;
48
+ }
21
49
  } catch (unused) {}
22
- return [];
50
+ return void 0;
23
51
  }
24
- async function persistSavedReports(doctype, reports) {
52
+ function persistStoredColumns(doctype, fieldnames) {
25
53
  try {
26
- await Promise.resolve(storage.setItem(getSavedReportsKey(doctype), JSON.stringify(reports)));
54
+ void Promise.resolve(storage.setItem(columnsStorageKey(doctype), JSON.stringify(fieldnames)));
27
55
  } catch (unused) {}
28
56
  }
57
+ function toReportFilters(filters) {
58
+ if (!filters) return void 0;
59
+ if (Array.isArray(filters)) return filters.length > 0 ? filters : void 0;
60
+ var tuples = Object.entries(filters).map(function (param) {
61
+ var [field, value] = param;
62
+ return [field, "=", value];
63
+ });
64
+ return tuples.length > 0 ? tuples : void 0;
65
+ }
66
+ function initialFieldnames(columns) {
67
+ if (!columns) return null;
68
+ var fieldnames = columns.flatMap(function (column) {
69
+ return typeof column === "string" ? [column] : column.enabled ? [column.fieldname] : [];
70
+ });
71
+ return fieldnames.length > 0 ? fieldnames : null;
72
+ }
73
+ function asFieldType(fieldtype) {
74
+ var _frappeFieldTypes_find;
75
+ return (_frappeFieldTypes_find = frappeFieldTypes.find(function (known) {
76
+ return known === fieldtype;
77
+ })) !== null && _frappeFieldTypes_find !== void 0 ? _frappeFieldTypes_find : "Data";
78
+ }
79
+ function refusedMetaFields(initialColumns, recordFields) {
80
+ var declared = (initialColumns !== null && initialColumns !== void 0 ? initialColumns : []).map(function (column) {
81
+ return typeof column === "string" ? {
82
+ fieldname: column,
83
+ label: recordKeyLabel(column),
84
+ fieldtype: "Data"
85
+ } : {
86
+ fieldname: column.fieldname,
87
+ label: column.label,
88
+ fieldtype: asFieldType(column.fieldtype)
89
+ };
90
+ });
91
+ return (declared.length > 0 ? declared : recordFields !== null && recordFields !== void 0 ? recordFields : []).filter(function (field) {
92
+ return field.fieldname !== "name";
93
+ }).map(function (field) {
94
+ return {
95
+ ...field,
96
+ read_only: 1,
97
+ in_list_view: 1
98
+ };
99
+ });
100
+ }
101
+ function asError(error) {
102
+ return _instanceof(error, Error) ? error : new Error(String(error));
103
+ }
104
+ function groupField(groupBy) {
105
+ if (!groupBy) return null;
106
+ return typeof groupBy === "string" ? groupBy : groupBy.field;
107
+ }
108
+ function aggregateGroups(rows, field, config) {
109
+ var groups = /* @__PURE__ */new Map();
110
+ var _iteratorNormalCompletion = true,
111
+ _didIteratorError = false,
112
+ _iteratorError = void 0;
113
+ try {
114
+ for (var _iterator = rows[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
115
+ var row = _step.value;
116
+ var key = row[field] === null || row[field] === void 0 ? "" : String(row[field]);
117
+ var bucket = groups.get(key);
118
+ if (bucket) bucket.push(row);else groups.set(key, [row]);
119
+ }
120
+ } catch (err) {
121
+ _didIteratorError = true;
122
+ _iteratorError = err;
123
+ } finally {
124
+ try {
125
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
126
+ _iterator.return();
127
+ }
128
+ } finally {
129
+ if (_didIteratorError) {
130
+ throw _iteratorError;
131
+ }
132
+ }
133
+ }
134
+ var numbers = function numbers2(group) {
135
+ return group.map(function (row2) {
136
+ return Number((config === null || config === void 0 ? void 0 : config.aggregationField) ? row2[config.aggregationField] : 0) || 0;
137
+ });
138
+ };
139
+ return [...groups.entries()].map(function (param) {
140
+ var [label, group] = param;
141
+ switch ((config === null || config === void 0 ? void 0 : config.aggregationField) ? config.aggregation : "count") {
142
+ case "sum":
143
+ return {
144
+ label,
145
+ value: numbers(group).reduce(function (sum, value) {
146
+ return sum + value;
147
+ }, 0)
148
+ };
149
+ case "avg":
150
+ return {
151
+ label,
152
+ value: numbers(group).reduce(function (sum, value) {
153
+ return sum + value;
154
+ }, 0) / group.length
155
+ };
156
+ case "min":
157
+ return {
158
+ label,
159
+ value: Math.min(...numbers(group))
160
+ };
161
+ case "max":
162
+ return {
163
+ label,
164
+ value: Math.max(...numbers(group))
165
+ };
166
+ default:
167
+ return {
168
+ label,
169
+ value: group.length
170
+ };
171
+ }
172
+ });
173
+ }
29
174
  function canDownloadCsv() {
30
175
  return typeof document !== "undefined" && typeof document.createElement === "function" && typeof Blob !== "undefined" && typeof URL !== "undefined" && typeof URL.createObjectURL === "function";
31
176
  }
32
- function FrappeReportBuilder(param) {
177
+ function FrappeReportBuilder(props) {
178
+ var _props_baseURL;
179
+ var config = useFrappeConfig();
180
+ if (!((_props_baseURL = props.baseURL) !== null && _props_baseURL !== void 0 ? _props_baseURL : config === null || config === void 0 ? void 0 : config.baseURL) && !(config === null || config === void 0 ? void 0 : config.fixtures)) {
181
+ return /* @__PURE__ */_jsx(FrappeNotConfigured, {
182
+ doctype: props.doctype
183
+ });
184
+ }
185
+ return /* @__PURE__ */_jsx(FrappeReportBuilderBody, {
186
+ ...props
187
+ });
188
+ }
189
+ function FrappeReportBuilderBody(param) {
33
190
  var {
34
191
  doctype,
192
+ filters,
193
+ scopeFilters,
194
+ onClearFilters,
35
195
  initialColumns,
36
196
  initialGroupBy,
37
- filters,
38
197
  showChart = false,
39
- onExport,
198
+ onOpenRow,
40
199
  onRowPress,
200
+ onOpenLink,
201
+ report: reportProp,
202
+ onReportChange,
203
+ onExport,
204
+ loading: loadingFallback,
205
+ error: errorFallback,
41
206
  baseURL,
42
207
  auth,
43
208
  syncOptions,
44
209
  ...stackProps
45
210
  } = param;
46
- var config = useFrappeConfig();
47
- var {
48
- knobProps
49
- } = useResolvedKnobs();
211
+ var _ref, _ref1, _ref2;
50
212
  var {
51
213
  t
52
214
  } = useTranslation();
215
+ var {
216
+ knobProps
217
+ } = useResolvedKnobs();
218
+ var config = useFrappeConfig();
53
219
  var finalBaseURL = baseURL !== null && baseURL !== void 0 ? baseURL : config === null || config === void 0 ? void 0 : config.baseURL;
54
220
  var finalAuth = auth !== null && auth !== void 0 ? auth : config === null || config === void 0 ? void 0 : config.auth;
55
221
  var finalSyncOptions = syncOptions !== null && syncOptions !== void 0 ? syncOptions : config === null || config === void 0 ? void 0 : config.syncOptions;
56
- if (!finalBaseURL && !(config === null || config === void 0 ? void 0 : config.fixtures)) {
57
- throw new Error("FrappeReportBuilder requires baseURL prop or FrappeProvider with baseURL or fixtures");
58
- }
59
- var connectionConfig = {
60
- baseURL: finalBaseURL,
61
- socketPort: config === null || config === void 0 ? void 0 : config.socketPort,
62
- siteName: config === null || config === void 0 ? void 0 : config.siteName,
63
- socketBaseURL: config === null || config === void 0 ? void 0 : config.socketBaseURL,
64
- auth: finalAuth,
65
- syncOptions: finalSyncOptions,
66
- realtime: config === null || config === void 0 ? void 0 : config.realtime,
67
- fixtures: config === null || config === void 0 ? void 0 : config.fixtures
68
- };
222
+ var fixtureMode = Boolean(config === null || config === void 0 ? void 0 : config.fixtures);
223
+ var connection = useMemo(function () {
224
+ return {
225
+ baseURL: finalBaseURL,
226
+ socketPort: config === null || config === void 0 ? void 0 : config.socketPort,
227
+ siteName: config === null || config === void 0 ? void 0 : config.siteName,
228
+ socketBaseURL: config === null || config === void 0 ? void 0 : config.socketBaseURL,
229
+ auth: finalAuth,
230
+ syncOptions: finalSyncOptions,
231
+ realtime: config === null || config === void 0 ? void 0 : config.realtime,
232
+ fixtures: config === null || config === void 0 ? void 0 : config.fixtures
233
+ };
234
+ }, [finalBaseURL, config === null || config === void 0 ? void 0 : config.socketPort, config === null || config === void 0 ? void 0 : config.siteName, config === null || config === void 0 ? void 0 : config.socketBaseURL, finalAuth, finalSyncOptions, config === null || config === void 0 ? void 0 : config.realtime, config === null || config === void 0 ? void 0 : config.fixtures]);
69
235
  var {
70
236
  meta,
71
- isLoading: isMetaLoading,
237
+ isLoading: metaLoading,
72
238
  error: metaError
73
- } = useDocTypeMeta(connectionConfig, doctype);
239
+ } = useDocTypeMeta(connection, doctype);
240
+ var metaRefused = !meta && metaError !== void 0 && isPermissionError(metaError);
241
+ var initialColumnsJson = JSON.stringify(initialColumns !== null && initialColumns !== void 0 ? initialColumns : []);
242
+ var declaresColumns = initialColumnsJson !== "[]";
243
+ var recordShape = useRecordShape(connection, doctype, metaRefused && !declaresColumns);
244
+ var layoutMeta = useMemo(function () {
245
+ if (meta) return meta;
246
+ if (!metaRefused) return void 0;
247
+ var fields = refusedMetaFields(JSON.parse(initialColumnsJson), recordShape.fields);
248
+ return fields.length > 0 ? {
249
+ fields
250
+ } : void 0;
251
+ }, [meta, metaRefused, initialColumnsJson, recordShape.fields]);
252
+ var readsWithoutMeta = !meta && layoutMeta !== void 0;
253
+ var savedReports = useSavedReports(doctype, useMemo(function () {
254
+ var _connection_baseURL;
255
+ return {
256
+ baseURL: metaRefused ? "" : (_connection_baseURL = connection.baseURL) !== null && _connection_baseURL !== void 0 ? _connection_baseURL : "",
257
+ auth: connection.auth,
258
+ fixtures: connection.fixtures
259
+ };
260
+ }, [metaRefused, connection.baseURL, connection.auth, connection.fixtures]));
261
+ var [internalReport, setInternalReport] = useState(null);
262
+ var currentReport = reportProp !== void 0 ? reportProp : internalReport;
74
263
  var allColumns = useMemo(function () {
75
- if (initialColumns) return initialColumns;
76
- if (!meta) return [];
77
- return meta.fields.filter(function (f) {
78
- return f.fieldtype !== "Section Break" && f.fieldtype !== "Column Break" && f.fieldtype !== "Tab Break";
79
- }).map(function (f) {
80
- return {
81
- fieldname: f.fieldname,
82
- label: f.label || f.fieldname,
83
- fieldtype: f.fieldtype,
84
- enabled: !!f.in_list_view
85
- };
264
+ var columns = reportColumnsFromMeta(layoutMeta);
265
+ if (!readsWithoutMeta || !layoutMeta) return columns;
266
+ var own = new Set(layoutMeta.fields.map(function (field) {
267
+ return field.fieldname;
268
+ }));
269
+ return columns.filter(function (column) {
270
+ return column.fieldname === "name" || own.has(column.fieldname);
86
271
  });
87
- }, [initialColumns, meta]);
88
- var fetchFields = useMemo(function () {
89
- var fieldNames = allColumns.map(function (c) {
90
- return c.fieldname;
272
+ }, [layoutMeta, readsWithoutMeta]);
273
+ var defaultFieldnames = useMemo(function () {
274
+ return readsWithoutMeta && layoutMeta ? ["name", ...layoutMeta.fields.map(function (field) {
275
+ return field.fieldname;
276
+ })] : defaultReportFieldnames(layoutMeta);
277
+ }, [layoutMeta, readsWithoutMeta]);
278
+ var initialColumnsKey = JSON.stringify(initialFieldnames(initialColumns));
279
+ var startFieldnames = useMemo(function () {
280
+ return JSON.parse(initialColumnsKey);
281
+ }, [initialColumnsKey]);
282
+ var [storedColumns, setStoredColumns] = useState(void 0);
283
+ var [selectedOverride, setSelectedOverride] = useState(null);
284
+ useEffect(function () {
285
+ if (fixtureMode) return;
286
+ var cancelled = false;
287
+ void readStoredColumns(doctype).then(function (stored) {
288
+ if (!cancelled) setStoredColumns(stored);
91
289
  });
92
- if (!fieldNames.includes("name")) {
93
- fieldNames.unshift("name");
94
- }
95
- return fieldNames;
96
- }, [allColumns]);
97
- var {
98
- rows,
99
- isQueryLoading: isLoading,
100
- isError
101
- } = useFrappeRows(connectionConfig, doctype, {
102
- fields: fetchFields,
103
- filters,
104
- limit: null
105
- });
106
- var data = rows;
107
- var [isLiveStale, setIsLiveStale] = useState(false);
108
- var staleTimerRef = useRef(void 0);
109
- var clearStaleTimer = useCallback(function () {
110
- if (staleTimerRef.current) {
111
- clearTimeout(staleTimerRef.current);
112
- staleTimerRef.current = void 0;
113
- }
114
- }, []);
115
- useFrappeDoctypeEvents(connectionConfig, doctype, function (event) {
116
- if (event.type !== "doc_update" && event.type !== "list_update" && event.type !== "doc_deleted" && event.type !== "doc_changed") {
117
- return;
118
- }
119
- setIsLiveStale(true);
120
- clearStaleTimer();
121
- staleTimerRef.current = setTimeout(function () {
122
- return setIsLiveStale(false);
123
- }, 2500);
124
- });
125
- var isFirstData = useRef(true);
290
+ return function () {
291
+ cancelled = true;
292
+ };
293
+ }, [doctype, fixtureMode]);
294
+ var selectedFieldnames = (_ref = (_ref1 = selectedOverride !== null && selectedOverride !== void 0 ? selectedOverride : startFieldnames) !== null && _ref1 !== void 0 ? _ref1 : storedColumns) !== null && _ref !== void 0 ? _ref : defaultFieldnames;
295
+ var selectedColumns = useMemo(function () {
296
+ return resolveSelectedColumns(allColumns, selectedFieldnames);
297
+ }, [allColumns, selectedFieldnames]);
298
+ var filtersKey = JSON.stringify(filters !== null && filters !== void 0 ? filters : null);
299
+ var propFilters = useMemo(function () {
300
+ return toReportFilters(JSON.parse(filtersKey));
301
+ }, [filtersKey]);
302
+ var [filtersCleared, setFiltersCleared] = useState(false);
303
+ var [reportFilters, setReportFilters] = useState(null);
304
+ var baseFilters = filtersCleared ? EMPTY_FILTERS : (_ref2 = reportFilters !== null && reportFilters !== void 0 ? reportFilters : propFilters) !== null && _ref2 !== void 0 ? _ref2 : EMPTY_FILTERS;
305
+ var [filterDrafts, setFilterDrafts] = useState({});
306
+ var [committedFilters, setCommittedFilters] = useState({});
126
307
  useEffect(function () {
127
- if (isFirstData.current) {
128
- isFirstData.current = false;
129
- return;
130
- }
131
- setIsLiveStale(false);
132
- clearStaleTimer();
133
- }, [data, clearStaleTimer]);
308
+ var handle = setTimeout(function () {
309
+ setCommittedFilters(function (previous) {
310
+ return JSON.stringify(previous) === JSON.stringify(filterDrafts) ? previous : filterDrafts;
311
+ });
312
+ }, COLUMN_FILTER_DEBOUNCE_MS);
313
+ return function () {
314
+ return clearTimeout(handle);
315
+ };
316
+ }, [filterDrafts]);
317
+ var columnTuples = useMemo(function () {
318
+ return columnFilterTuples(selectedColumns, committedFilters);
319
+ }, [selectedColumns, committedFilters]);
320
+ var scopeKey = JSON.stringify(scopeFilters !== null && scopeFilters !== void 0 ? scopeFilters : []);
321
+ var scope = useMemo(function () {
322
+ return JSON.parse(scopeKey);
323
+ }, [scopeKey]);
324
+ var effectiveFilters = useMemo(function () {
325
+ return [...scope, ...baseFilters, ...columnTuples];
326
+ }, [scope, baseFilters, columnTuples]);
327
+ var metaSort = useMemo(function () {
328
+ return {
329
+ field: ((meta === null || meta === void 0 ? void 0 : meta.sort_field) || "modified").split(" ")[0],
330
+ order: ((meta === null || meta === void 0 ? void 0 : meta.sort_order) || "DESC").toLowerCase() === "asc" ? "asc" : "desc"
331
+ };
332
+ }, [meta === null || meta === void 0 ? void 0 : meta.sort_field, meta === null || meta === void 0 ? void 0 : meta.sort_order]);
333
+ var [sortOverride, setSortOverride] = useState(null);
334
+ var sort = sortOverride !== null && sortOverride !== void 0 ? sortOverride : metaSort;
335
+ var startGroupBy = groupField(initialGroupBy);
336
+ var chartConfig = (typeof initialGroupBy === "undefined" ? "undefined" : _type_of(initialGroupBy)) === "object" ? initialGroupBy : void 0;
337
+ var [groupBy, setGroupBy] = useState(startGroupBy);
338
+ var [pageSize, setPageSize] = useState(DEFAULT_REPORT_PAGE_SIZE);
339
+ var [page, setPage] = useState(0);
134
340
  useEffect(function () {
135
- return clearStaleTimer;
136
- }, [clearStaleTimer]);
137
- var [groupBy, setGroupBy] = useState(initialGroupBy !== null && initialGroupBy !== void 0 ? initialGroupBy : null);
138
- var [enabledColumns, setEnabledColumns] = useState([]);
341
+ setSelectedOverride(null);
342
+ setStoredColumns(void 0);
343
+ setSortOverride(null);
344
+ setGroupBy(startGroupBy);
345
+ setPage(0);
346
+ setPageSize(DEFAULT_REPORT_PAGE_SIZE);
347
+ setFilterDrafts({});
348
+ setCommittedFilters({});
349
+ setFiltersCleared(false);
350
+ setReportFilters(null);
351
+ },
352
+ // startGroupBy is the mount-time seed; only a doctype swap re-seeds.
353
+ // eslint-disable-next-line react-hooks/exhaustive-deps
354
+ [doctype]);
139
355
  useEffect(function () {
140
- if (allColumns.length > 0 && enabledColumns.length === 0) {
141
- var initial = allColumns.filter(function (c) {
142
- return c.enabled;
143
- }).map(function (c) {
144
- return c.fieldname;
145
- });
146
- if (initial.length === 0) {
147
- setEnabledColumns(allColumns.slice(0, 5).map(function (c) {
148
- return c.fieldname;
149
- }));
150
- } else {
151
- setEnabledColumns(initial);
152
- }
153
- }
154
- }, [allColumns, enabledColumns.length]);
155
- var [savedReports, setSavedReports] = useState([]);
156
- var [saveDialogOpen, setSaveDialogOpen] = useState(false);
157
- var [saveReportName, setSaveReportName] = useState("");
356
+ return setFiltersCleared(false);
357
+ }, [filtersKey]);
358
+ var effectiveFiltersKey = useMemo(function () {
359
+ return JSON.stringify(effectiveFilters);
360
+ }, [effectiveFilters]);
158
361
  useEffect(function () {
362
+ setPage(0);
363
+ }, [effectiveFiltersKey, pageSize, groupBy]);
364
+ useEffect(function () {
365
+ if (!currentReport) {
366
+ setReportFilters(null);
367
+ return;
368
+ }
159
369
  var cancelled = false;
160
- void async function () {
161
- var reports = await loadSavedReports(doctype);
162
- if (!cancelled) {
163
- setSavedReports(reports);
370
+ void savedReports.load(currentReport).then(function (saved) {
371
+ var _saved_groupBy;
372
+ if (cancelled || !saved) return;
373
+ setSelectedOverride(saved.fieldnames.length > 0 ? saved.fieldnames : null);
374
+ setReportFilters(saved.filters);
375
+ setFilterDrafts({});
376
+ setCommittedFilters({});
377
+ setFiltersCleared(false);
378
+ if (saved.sort) setSortOverride(saved.sort);
379
+ if (saved.pageSize && REPORT_PAGE_SIZES.some(function (size) {
380
+ return size === saved.pageSize;
381
+ })) {
382
+ setPageSize(saved.pageSize);
164
383
  }
165
- }();
384
+ setGroupBy((_saved_groupBy = saved.groupBy) !== null && _saved_groupBy !== void 0 ? _saved_groupBy : null);
385
+ });
166
386
  return function () {
167
387
  cancelled = true;
168
388
  };
169
- }, [doctype]);
170
- var handleSaveReport = useCallback(function () {
171
- if (!saveReportName.trim()) return;
172
- var report = {
173
- name: saveReportName.trim(),
174
- columns: enabledColumns,
175
- groupBy,
176
- filters
177
- };
178
- var updated = [...savedReports.filter(function (r) {
179
- return r.name !== report.name;
180
- }), report];
181
- setSavedReports(updated);
182
- void persistSavedReports(doctype, updated);
183
- setSaveDialogOpen(false);
184
- setSaveReportName("");
185
- }, [saveReportName, enabledColumns, groupBy, filters, savedReports, doctype]);
186
- var handleLoadReport = useCallback(function (report) {
187
- setEnabledColumns(report.columns);
188
- setGroupBy(report.groupBy);
189
- }, []);
190
- var handleDeleteReport = useCallback(function (name) {
191
- var updated = savedReports.filter(function (r) {
192
- return r.name !== name;
193
- });
194
- setSavedReports(updated);
195
- void persistSavedReports(doctype, updated);
196
- }, [savedReports, doctype]);
197
- var handleExport = useCallback(function (exportData) {
198
- if (onExport) {
199
- onExport(exportData);
200
- return;
201
- }
202
- var cols = allColumns.filter(function (c) {
203
- return enabledColumns.includes(c.fieldname);
204
- });
205
- var headers = cols.map(function (c) {
206
- return c.label;
389
+ },
390
+ // savedReports.load changes identity with its report list; reloading the
391
+ // config on list refreshes would clobber in-progress edits — key on the
392
+ // selected report (and doctype via load's closure) only.
393
+ // eslint-disable-next-line react-hooks/exhaustive-deps
394
+ [currentReport, doctype]);
395
+ var handleToggleColumn = useCallback(function (fieldname) {
396
+ setSelectedOverride(function (previous) {
397
+ var _ref3, _ref12;
398
+ var current = (_ref3 = (_ref12 = previous !== null && previous !== void 0 ? previous : startFieldnames) !== null && _ref12 !== void 0 ? _ref12 : storedColumns) !== null && _ref3 !== void 0 ? _ref3 : defaultFieldnames;
399
+ var next = current.includes(fieldname) ? current.length === 1 ? current : current.filter(function (entry) {
400
+ return entry !== fieldname;
401
+ }) : [...current, fieldname];
402
+ if (!fixtureMode && !currentReport) persistStoredColumns(doctype, next);
403
+ return next;
207
404
  });
208
- var csvRows = [headers.join(",")];
405
+ }, [startFieldnames, storedColumns, defaultFieldnames, fixtureMode, currentReport, doctype]);
406
+ var handleResetColumns = useCallback(function () {
407
+ setSelectedOverride(defaultFieldnames);
408
+ setStoredColumns(void 0);
409
+ if (!fixtureMode) persistStoredColumns(doctype, defaultFieldnames);
410
+ }, [defaultFieldnames, fixtureMode, doctype]);
411
+ var fetchFields = useMemo(function () {
412
+ var fields = /* @__PURE__ */new Set(["name", sort.field]);
209
413
  var _iteratorNormalCompletion = true,
210
414
  _didIteratorError = false,
211
415
  _iteratorError = void 0;
212
416
  try {
213
- var _loop = function () {
214
- var row = _step.value;
215
- var values = cols.map(function (col) {
216
- var val = row[col.fieldname];
217
- if (val === null || val === void 0) return "";
218
- var str = String(val);
219
- if (str.includes(",") || str.includes('"') || str.includes("\n")) {
220
- return `"${str.replace(/"/g, '""')}"`;
221
- }
222
- return str;
223
- });
224
- csvRows.push(values.join(","));
225
- };
226
- for (var _iterator = exportData[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) _loop();
417
+ for (var _iterator = selectedColumns[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
418
+ var column = _step.value;
419
+ fields.add(column.fieldname);
420
+ }
227
421
  } catch (err) {
228
422
  _didIteratorError = true;
229
423
  _iteratorError = err;
@@ -238,211 +432,322 @@ function FrappeReportBuilder(param) {
238
432
  }
239
433
  }
240
434
  }
241
- var csvContent = csvRows.join("\n");
242
- var blob = new Blob([csvContent], {
243
- type: "text/csv;charset=utf-8;"
435
+ if (groupBy) fields.add(groupBy);
436
+ if (chartConfig === null || chartConfig === void 0 ? void 0 : chartConfig.aggregationField) fields.add(chartConfig.aggregationField);
437
+ return [...fields];
438
+ }, [selectedColumns, sort.field, groupBy, chartConfig === null || chartConfig === void 0 ? void 0 : chartConfig.aggregationField]);
439
+ var orderBy = useMemo(function () {
440
+ return [{
441
+ field: sort.field,
442
+ order: sort.order === "asc" ? Order.Asc : Order.Desc
443
+ }];
444
+ }, [sort.field, sort.order]);
445
+ var {
446
+ rows: rowsData,
447
+ syncError,
448
+ isLoading: rowsLoading
449
+ } = useFrappeRows(connection, doctype, {
450
+ fields: fetchFields,
451
+ filters: effectiveFilters,
452
+ orderBy,
453
+ limit: null,
454
+ enabled: layoutMeta !== void 0,
455
+ mapError: asError
456
+ });
457
+ var orderedRows = useMemo(function () {
458
+ return orderReportRows(rowsData, sort, groupBy);
459
+ }, [rowsData, sort, groupBy]);
460
+ var total = orderedRows.length;
461
+ var pageCount = Math.max(1, Math.ceil(total / pageSize));
462
+ var effectivePage = Math.min(page, pageCount - 1);
463
+ var gridRows = useMemo(function () {
464
+ return buildGridRows(orderedRows, effectivePage * pageSize, pageSize, groupBy);
465
+ }, [orderedRows, effectivePage, pageSize, groupBy]);
466
+ var totals = useMemo(function () {
467
+ return computeTotals(selectedColumns, orderedRows);
468
+ }, [selectedColumns, orderedRows]);
469
+ var groupByColumn = groupBy ? allColumns.find(function (column) {
470
+ return column.fieldname === groupBy;
471
+ }) : void 0;
472
+ var chartData = useMemo(function () {
473
+ return showChart && groupBy ? aggregateGroups(orderedRows, groupBy, chartConfig) : [];
474
+ }, [showChart, groupBy, orderedRows, chartConfig]);
475
+ var rowsPressable = Boolean(onOpenRow || onRowPress);
476
+ var handleOpenRow = useCallback(function (name) {
477
+ onOpenRow === null || onOpenRow === void 0 ? void 0 : onOpenRow(name);
478
+ if (onRowPress) {
479
+ var index = orderedRows.findIndex(function (row) {
480
+ return row.name === name;
481
+ });
482
+ if (index >= 0) onRowPress(orderedRows[index], index);
483
+ }
484
+ }, [onOpenRow, onRowPress, orderedRows]);
485
+ var handleSelectReport = useCallback(function (name) {
486
+ if (reportProp === void 0) setInternalReport(name);
487
+ onReportChange === null || onReportChange === void 0 ? void 0 : onReportChange(name);
488
+ if (!name) {
489
+ setReportFilters(null);
490
+ setSelectedOverride(null);
491
+ setSortOverride(null);
492
+ setGroupBy(null);
493
+ }
494
+ }, [reportProp, onReportChange]);
495
+ var handleClearBaseFilters = useCallback(function () {
496
+ setFiltersCleared(true);
497
+ if (propFilters && !reportFilters) onClearFilters === null || onClearFilters === void 0 ? void 0 : onClearFilters();
498
+ }, [propFilters, reportFilters, onClearFilters]);
499
+ var handleSaveReport = useCallback(function (name) {
500
+ void savedReports.save(name, {
501
+ fieldnames: [...selectedFieldnames],
502
+ filters: effectiveFilters,
503
+ sort,
504
+ pageSize,
505
+ groupBy,
506
+ addTotals: totals.length > 0
507
+ }).then(function (savedName) {
508
+ notify({
509
+ severity: "success",
510
+ scope: "page",
511
+ body: t("report.saveDone", {
512
+ defaultValue: "Saved report \u201C{{name}}\u201D",
513
+ name: savedName
514
+ })
515
+ });
516
+ if (savedName !== currentReport) handleSelectReport(savedName);
517
+ }).catch(function (error) {
518
+ notify({
519
+ severity: "error",
520
+ scope: "page",
521
+ body: _instanceof(error, Error) ? error.message : t("report.saveFailed", "Could not save the report")
522
+ });
244
523
  });
245
- downloadBlob(blob, `${doctype}_report.csv`);
246
- }, [allColumns, enabledColumns, onExport, doctype]);
524
+ }, [savedReports, selectedFieldnames, effectiveFilters, sort, pageSize, groupBy, totals.length, currentReport, handleSelectReport, t]);
525
+ var handleDeleteReport = useCallback(function (name) {
526
+ void savedReports.remove(name).then(function () {
527
+ notify({
528
+ severity: "success",
529
+ scope: "page",
530
+ body: t("report.deleteDone", {
531
+ defaultValue: "Deleted report \u201C{{name}}\u201D",
532
+ name
533
+ })
534
+ });
535
+ if (name === currentReport) handleSelectReport(null);
536
+ }).catch(function (error) {
537
+ notify({
538
+ severity: "error",
539
+ scope: "page",
540
+ body: _instanceof(error, Error) ? error.message : t("report.deleteFailed", "Could not delete the report")
541
+ });
542
+ });
543
+ }, [savedReports, currentReport, handleSelectReport, t]);
247
544
  var exportEnabled = Boolean(onExport) || canDownloadCsv();
248
- if (isMetaLoading) {
249
- return /* @__PURE__ */_jsxs(YStack, {
250
- ...knobProps.panelPadding,
251
- alignItems: "center",
252
- justifyContent: "center",
253
- gap: "$2",
254
- ...stackProps,
255
- children: [/* @__PURE__ */_jsx(Spinner, {
256
- size: "large"
257
- }), /* @__PURE__ */_jsx(Text, {
258
- color: "$color10",
259
- children: t("Loading {{doctype}} schema...", {
260
- doctype
545
+ var handleExport = useCallback(function () {
546
+ if (onExport) {
547
+ onExport(orderedRows);
548
+ return;
549
+ }
550
+ downloadBlob(new Blob([buildReportCsv(selectedColumns, orderedRows)], {
551
+ type: "text/csv;charset=utf-8;"
552
+ }), `${doctype}_report.csv`);
553
+ notify({
554
+ severity: "success",
555
+ scope: "page",
556
+ body: t("report.exportDone", {
557
+ count: orderedRows.length,
558
+ defaultValue_one: "Exported {{count}} row to CSV",
559
+ defaultValue_other: "Exported {{count}} rows to CSV"
560
+ })
561
+ });
562
+ }, [onExport, selectedColumns, orderedRows, doctype, t]);
563
+ var handleColumnFilterChange = useCallback(function (fieldname, value) {
564
+ setFilterDrafts(function (previous) {
565
+ if (value === "") {
566
+ if (!(fieldname in previous)) return previous;
567
+ var {
568
+ [fieldname]: _dropped,
569
+ ...rest
570
+ } = previous;
571
+ return rest;
572
+ }
573
+ return {
574
+ ...previous,
575
+ [fieldname]: value
576
+ };
577
+ });
578
+ }, []);
579
+ var handleClearColumnFilters = useCallback(function () {
580
+ setFilterDrafts({});
581
+ setCommittedFilters({});
582
+ }, []);
583
+ if (metaLoading && !meta) {
584
+ return /* @__PURE__ */_jsx(_Fragment, {
585
+ children: loadingFallback !== null && loadingFallback !== void 0 ? loadingFallback : /* @__PURE__ */_jsx(YStack, {
586
+ flex: 1,
587
+ alignItems: "center",
588
+ justifyContent: "center",
589
+ ...stackProps,
590
+ children: /* @__PURE__ */_jsx(Spinner, {
591
+ size: "large"
261
592
  })
262
- })]
593
+ })
263
594
  });
264
595
  }
265
- if (metaError && !meta) {
266
- return /* @__PURE__ */_jsxs(YStack, {
267
- ...knobProps.panelPadding,
268
- alignItems: "center",
269
- ...knobProps.gap,
270
- ...stackProps,
271
- children: [/* @__PURE__ */_jsx(Text, {
272
- color: "$red11",
273
- children: t("Failed to load {{doctype}} schema", {
274
- doctype
596
+ if (metaError && metaRefused && !layoutMeta) {
597
+ if (recordShape.status === "pending") {
598
+ return /* @__PURE__ */_jsx(_Fragment, {
599
+ children: loadingFallback !== null && loadingFallback !== void 0 ? loadingFallback : /* @__PURE__ */_jsx(YStack, {
600
+ flex: 1,
601
+ alignItems: "center",
602
+ justifyContent: "center",
603
+ ...stackProps,
604
+ children: /* @__PURE__ */_jsx(Spinner, {
605
+ size: "large"
606
+ })
275
607
  })
276
- }), /* @__PURE__ */_jsx(Text, {
277
- color: "$color10",
278
- fontSize: "$2",
279
- children: metaError.message
280
- })]
608
+ });
609
+ }
610
+ return /* @__PURE__ */_jsx(_Fragment, {
611
+ children: errorFallback ? errorFallback(metaError) : /* @__PURE__ */_jsx(EmptyState, {
612
+ testID: "frappe-report-not-permitted",
613
+ title: t("report.notPermitted", {
614
+ defaultValue: "You can't open the {{doctype}} report",
615
+ doctype
616
+ }),
617
+ description: refusalReason(metaError)
618
+ })
281
619
  });
282
620
  }
283
- if (isLoading) {
284
- return /* @__PURE__ */_jsxs(YStack, {
285
- ...knobProps.panelPadding,
286
- alignItems: "center",
287
- gap: "$1",
288
- ...stackProps,
289
- children: [/* @__PURE__ */_jsx(Spinner, {
290
- size: "small"
291
- }), /* @__PURE__ */_jsx(Text, {
292
- color: "$color10",
293
- fontSize: "$2",
294
- children: t("Loading data...")
295
- })]
621
+ if (metaError && !meta && !readsWithoutMeta) {
622
+ return /* @__PURE__ */_jsx(_Fragment, {
623
+ children: errorFallback ? errorFallback(metaError) : /* @__PURE__ */_jsx(EmptyState, {
624
+ intent: "error",
625
+ title: t("report.metaFailed", {
626
+ defaultValue: "Couldn't load the {{doctype}} report",
627
+ doctype
628
+ }),
629
+ description: metaError.message
630
+ })
296
631
  });
297
632
  }
298
- if (isError) {
299
- return /* @__PURE__ */_jsxs(YStack, {
300
- ...knobProps.panelPadding,
633
+ var body;
634
+ if (syncError && isPermissionError(syncError)) {
635
+ body = /* @__PURE__ */_jsx(EmptyState, {
636
+ testID: "frappe-report-not-permitted",
637
+ title: t("report.notPermitted", {
638
+ defaultValue: "You can't open the {{doctype}} report",
639
+ doctype
640
+ }),
641
+ description: refusalReason(syncError)
642
+ });
643
+ } else if (syncError) {
644
+ body = /* @__PURE__ */_jsx(EmptyState, {
645
+ intent: "error",
646
+ title: t("report.loadFailed", "Couldn't load report rows"),
647
+ description: syncError.message
648
+ });
649
+ } else if (rowsLoading && total === 0) {
650
+ body = /* @__PURE__ */_jsx(YStack, {
651
+ flex: 1,
301
652
  alignItems: "center",
653
+ justifyContent: "center",
654
+ children: /* @__PURE__ */_jsx(Spinner, {
655
+ size: "large"
656
+ })
657
+ });
658
+ } else if (total === 0) {
659
+ var hasFilters = effectiveFilters.length > 0;
660
+ body = /* @__PURE__ */_jsx(EmptyState, {
661
+ title: t("report.emptyTitle", "No results"),
662
+ description: hasFilters ? t("report.emptyFiltered", "No rows match the current filters") : t("report.emptyDescription", {
663
+ defaultValue: "There are no {{doctype}} records yet",
664
+ doctype
665
+ }),
666
+ action: hasFilters ? /* @__PURE__ */_jsx(Button, {
667
+ size: "$3",
668
+ onPress: function onPress() {
669
+ handleClearColumnFilters();
670
+ handleClearBaseFilters();
671
+ },
672
+ children: t("report.clearAllFilters", "Clear all filters")
673
+ }) : void 0
674
+ });
675
+ } else {
676
+ body = /* @__PURE__ */_jsxs(YStack, {
677
+ flex: 1,
678
+ minWidth: 0,
302
679
  ...knobProps.gap,
303
- ...stackProps,
304
- children: [/* @__PURE__ */_jsx(Text, {
305
- color: "$red11",
306
- children: t("Failed to load {{doctype}} data", {
307
- doctype
680
+ children: [chartData.length > 0 && /* @__PURE__ */_jsx(YStack, {
681
+ ...knobProps.surface,
682
+ ...knobProps.containerRadius,
683
+ ...knobProps.panelPadding,
684
+ children: /* @__PURE__ */_jsx(BarChart, {
685
+ data: chartData
308
686
  })
309
- }), /* @__PURE__ */_jsx(Text, {
310
- color: "$color10",
311
- fontSize: "$2",
312
- children: t("The live query could not load report rows.")
687
+ }), /* @__PURE__ */_jsx(ReportGrid, {
688
+ columns: selectedColumns,
689
+ rows: gridRows,
690
+ sort,
691
+ onSortChange: setSortOverride,
692
+ columnFilters: filterDrafts,
693
+ onColumnFilterChange: handleColumnFilterChange,
694
+ onOpenRow: rowsPressable ? handleOpenRow : void 0,
695
+ onOpenLink,
696
+ totals,
697
+ groupByColumn
313
698
  })]
314
699
  });
315
700
  }
316
- return /* @__PURE__ */_jsxs(YStack, {
701
+ var content = /* @__PURE__ */_jsxs(YStack, {
317
702
  flex: 1,
318
- ...knobProps.borderRadius,
703
+ minWidth: 0,
319
704
  ...stackProps,
320
- children: [/* Frappe-specific toolbar: Save/Load reports */
321
- /* @__PURE__ */_jsxs(XStack, {
322
- ...knobProps.panelPadding,
323
- ...knobProps.surface,
324
- ...knobProps.gap,
325
- alignItems: "center",
326
- borderBottomWidth: 1,
327
- borderBottomColor: "$borderColor",
328
- children: [/* Subtle stale affordance while a post-event refresh reconciles */
329
- isLiveStale ? /* @__PURE__ */_jsxs(XStack, {
330
- gap: "$2",
331
- alignItems: "center",
332
- children: [/* @__PURE__ */_jsx(Spinner, {
333
- size: "small",
334
- "aria-label": t("Updating")
335
- }), /* @__PURE__ */_jsx(Text, {
336
- ...knobProps.label,
337
- color: formCommonColors.muted,
338
- children: t("Updating...")
339
- })]
340
- }) : null, /* @__PURE__ */_jsx(XStack, {
341
- flex: 1
342
- }), /* Save */
343
- /* @__PURE__ */_jsxs(Popover, {
344
- placement: "bottom-end",
345
- open: saveDialogOpen,
346
- onOpenChange: setSaveDialogOpen,
347
- children: [/* @__PURE__ */_jsx(Popover.Trigger, {
348
- asChild: true,
349
- children: /* @__PURE__ */_jsx(Button, {
350
- size: "$2",
351
- icon: FloppyDiskIcon,
352
- children: t("Save")
353
- })
354
- }), /* @__PURE__ */_jsx(PopoverContent, {
355
- children: /* @__PURE__ */_jsxs(YStack, {
356
- ...knobProps.gap,
357
- minWidth: 220,
358
- children: [/* @__PURE__ */_jsx(Text, {
359
- ...knobProps.label,
360
- fontWeight: "400",
361
- children: t("Save Report")
362
- }), /* @__PURE__ */_jsx(Input, {
363
- label: t("Report name"),
364
- labelHidden: true,
365
- placeholder: t("Report name"),
366
- value: saveReportName,
367
- onChangeText: setSaveReportName,
368
- inputProps: {
369
- onSubmitEditing: handleSaveReport
370
- }
371
- }), /* @__PURE__ */_jsx(Button, {
372
- size: "$2",
373
- onPress: handleSaveReport,
374
- disabled: !saveReportName.trim(),
375
- children: t("Save")
376
- })]
377
- })
378
- })]
379
- }), /* Load */
380
- savedReports.length > 0 && /* @__PURE__ */_jsxs(Popover, {
381
- placement: "bottom-end",
382
- children: [/* @__PURE__ */_jsx(Popover.Trigger, {
383
- asChild: true,
384
- children: /* @__PURE__ */_jsx(Button, {
385
- size: "$2",
386
- icon: FolderOpenIcon,
387
- children: t("Load")
388
- })
389
- }), /* @__PURE__ */_jsx(PopoverContent, {
390
- children: /* @__PURE__ */_jsxs(YStack, {
391
- ...knobProps.gap,
392
- minWidth: 180,
393
- children: [/* @__PURE__ */_jsx(Text, {
394
- ...knobProps.label,
395
- fontWeight: "400",
396
- color: formCommonColors.muted,
397
- children: t("Saved Reports")
398
- }), /* @__PURE__ */_jsx(Separator, {}), savedReports.map(function (report) {
399
- return /* @__PURE__ */_jsxs(XStack, {
400
- alignItems: "center",
401
- justifyContent: "space-between",
402
- padding: "$2",
403
- ...knobProps.containerRadius,
404
- hoverStyle: {
405
- backgroundColor: "$color2"
406
- },
407
- cursor: "pointer",
408
- onPress: function onPress() {
409
- return handleLoadReport(report);
410
- },
411
- children: [/* @__PURE__ */_jsx(Text, {
412
- ...knobProps.body,
413
- flex: 1,
414
- children: report.name
415
- }), /* @__PURE__ */_jsx(Button, {
416
- size: "$2",
417
- circular: true,
418
- chromeless: true,
419
- icon: TrashIcon,
420
- onPress: function onPress(e) {
421
- e.stopPropagation();
422
- handleDeleteReport(report.name);
423
- },
424
- "aria-label": t("Delete {{name}}", {
425
- name: report.name
426
- })
427
- })]
428
- }, report.name);
429
- })]
430
- })
431
- })]
432
- })]
433
- }), /* Delegate to generic ReportBuilder */
434
- /* @__PURE__ */_jsx(ReportBuilder, {
705
+ children: [/* @__PURE__ */_jsx(ReportViewToolbar, {
435
706
  columns: allColumns,
436
- data,
437
- groupBy: groupBy !== null && groupBy !== void 0 ? groupBy : void 0,
707
+ selected: selectedFieldnames,
708
+ onToggleColumn: handleToggleColumn,
709
+ onResetColumns: handleResetColumns,
710
+ groupBy,
438
711
  onGroupByChange: setGroupBy,
439
- onColumnsChange: setEnabledColumns,
712
+ baseFilters,
713
+ onClearBaseFilters: baseFilters.length > 0 ? handleClearBaseFilters : void 0,
714
+ columnFilterCount: columnTuples.length,
715
+ onClearColumnFilters: handleClearColumnFilters,
716
+ savedReports: savedReports.reports,
717
+ currentReport,
718
+ onSelectReport: handleSelectReport,
719
+ onSaveReport: readsWithoutMeta ? void 0 : handleSaveReport,
720
+ onDeleteReport: readsWithoutMeta ? void 0 : handleDeleteReport,
440
721
  onExport: exportEnabled ? handleExport : void 0,
441
- onRowPress,
442
- showChart,
443
- flex: 1
722
+ exportDisabled: total === 0
723
+ }), /* @__PURE__ */_jsx(YStack, {
724
+ flex: 1,
725
+ minWidth: 0,
726
+ paddingHorizontal: "$3",
727
+ children: body
728
+ }), total > 0 && !syncError && /* @__PURE__ */_jsx(YStack, {
729
+ paddingHorizontal: "$3",
730
+ paddingVertical: "$2",
731
+ children: /* @__PURE__ */_jsx(DataTablePagination, {
732
+ pagination: {
733
+ pageIndex: effectivePage,
734
+ pageSize,
735
+ totalCount: total,
736
+ totalPages: pageCount
737
+ },
738
+ onPaginationChange: function onPaginationChange(next) {
739
+ setPage(next.pageIndex);
740
+ setPageSize(next.pageSize);
741
+ },
742
+ pageSizeOptions: [...REPORT_PAGE_SIZES],
743
+ compact: true
744
+ })
444
745
  })]
445
746
  });
747
+ return isWeb ? content : /* @__PURE__ */_jsx(ScrollView, {
748
+ flex: 1,
749
+ children: content
750
+ });
446
751
  }
447
752
  export { FrappeReportBuilder };
448
753
  //# sourceMappingURL=FrappeReportBuilder.native.js.map