@manta-eu/react 0.11.0 → 0.13.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 (592) hide show
  1. package/README.md +59 -0
  2. package/dist/components/AppErrorBoundary.d.ts.map +1 -1
  3. package/dist/components/AppErrorBoundary.js +14 -11
  4. package/dist/components/AppErrorBoundary.js.map +1 -1
  5. package/dist/components/app-gate/AppGate.d.ts +8 -0
  6. package/dist/components/app-gate/AppGate.d.ts.map +1 -0
  7. package/dist/components/app-gate/AppGate.js +68 -0
  8. package/dist/components/app-gate/AppGate.js.map +1 -0
  9. package/dist/components/app-gate/AwaitingDatastoreStatus.d.ts +7 -0
  10. package/dist/components/app-gate/AwaitingDatastoreStatus.d.ts.map +1 -0
  11. package/dist/components/app-gate/AwaitingDatastoreStatus.js +19 -0
  12. package/dist/components/app-gate/AwaitingDatastoreStatus.js.map +1 -0
  13. package/dist/components/app-gate/EnterDatastoreRoute.d.ts +2 -0
  14. package/dist/components/app-gate/EnterDatastoreRoute.d.ts.map +1 -0
  15. package/dist/components/app-gate/EnterDatastoreRoute.js +25 -0
  16. package/dist/components/app-gate/EnterDatastoreRoute.js.map +1 -0
  17. package/dist/components/app-gate/ErrorRoute.d.ts +2 -0
  18. package/dist/components/app-gate/ErrorRoute.d.ts.map +1 -0
  19. package/dist/components/app-gate/ErrorRoute.js +27 -0
  20. package/dist/components/app-gate/ErrorRoute.js.map +1 -0
  21. package/dist/components/app-gate/FailureAlert.d.ts +5 -0
  22. package/dist/components/app-gate/FailureAlert.d.ts.map +1 -0
  23. package/dist/components/app-gate/FailureAlert.js +9 -0
  24. package/dist/components/app-gate/FailureAlert.js.map +1 -0
  25. package/dist/components/app-gate/NoDatastoreAccess.d.ts +8 -0
  26. package/dist/components/app-gate/NoDatastoreAccess.d.ts.map +1 -0
  27. package/dist/components/app-gate/NoDatastoreAccess.js +9 -0
  28. package/dist/components/app-gate/NoDatastoreAccess.js.map +1 -0
  29. package/dist/components/app-gate/NotFoundRoute.d.ts +2 -0
  30. package/dist/components/app-gate/NotFoundRoute.d.ts.map +1 -0
  31. package/dist/components/app-gate/NotFoundRoute.js +9 -0
  32. package/dist/components/app-gate/NotFoundRoute.js.map +1 -0
  33. package/dist/components/app-gate/PendingInvitations.d.ts +5 -0
  34. package/dist/components/app-gate/PendingInvitations.d.ts.map +1 -0
  35. package/dist/components/app-gate/PendingInvitations.js +58 -0
  36. package/dist/components/app-gate/PendingInvitations.js.map +1 -0
  37. package/dist/components/app-gate/ServiceError.d.ts +8 -0
  38. package/dist/components/app-gate/ServiceError.d.ts.map +1 -0
  39. package/dist/components/app-gate/ServiceError.js +10 -0
  40. package/dist/components/app-gate/ServiceError.js.map +1 -0
  41. package/dist/components/app-gate/index.d.ts +3 -0
  42. package/dist/components/app-gate/index.d.ts.map +1 -0
  43. package/dist/components/app-gate/index.js +3 -0
  44. package/dist/components/app-gate/index.js.map +1 -0
  45. package/dist/components/app-gate/sdk-route-elements.d.ts +23 -0
  46. package/dist/components/app-gate/sdk-route-elements.d.ts.map +1 -0
  47. package/dist/components/app-gate/sdk-route-elements.js +35 -0
  48. package/dist/components/app-gate/sdk-route-elements.js.map +1 -0
  49. package/dist/components/app-shell/AppShell.d.ts +7 -0
  50. package/dist/components/app-shell/AppShell.d.ts.map +1 -0
  51. package/dist/components/app-shell/AppShell.js +10 -0
  52. package/dist/components/app-shell/AppShell.js.map +1 -0
  53. package/dist/components/app-shell/AppShellRoutes.d.ts +9 -0
  54. package/dist/components/app-shell/AppShellRoutes.d.ts.map +1 -0
  55. package/dist/components/app-shell/AppShellRoutes.js +20 -0
  56. package/dist/components/app-shell/AppShellRoutes.js.map +1 -0
  57. package/dist/components/app-shell/GroupDatastores.d.ts +8 -0
  58. package/dist/components/app-shell/GroupDatastores.d.ts.map +1 -0
  59. package/dist/components/app-shell/GroupDatastores.js +15 -0
  60. package/dist/components/app-shell/GroupDatastores.js.map +1 -0
  61. package/dist/components/app-shell/GroupRoute.d.ts +2 -0
  62. package/dist/components/app-shell/GroupRoute.d.ts.map +1 -0
  63. package/dist/components/app-shell/GroupRoute.js +22 -0
  64. package/dist/components/app-shell/GroupRoute.js.map +1 -0
  65. package/dist/components/app-shell/index.d.ts +3 -0
  66. package/dist/components/app-shell/index.d.ts.map +1 -0
  67. package/dist/components/app-shell/index.js +3 -0
  68. package/dist/components/app-shell/index.js.map +1 -0
  69. package/dist/components/authenticated-chat/index.d.ts +1 -2
  70. package/dist/components/authenticated-chat/index.d.ts.map +1 -1
  71. package/dist/components/authenticated-chat/index.js +1 -12
  72. package/dist/components/authenticated-chat/index.js.map +1 -1
  73. package/dist/components/chat-view/Chat.d.ts +2 -1
  74. package/dist/components/chat-view/Chat.d.ts.map +1 -1
  75. package/dist/components/chat-view/Chat.js +3 -2
  76. package/dist/components/chat-view/Chat.js.map +1 -1
  77. package/dist/components/chat-view/MessageItem.d.ts.map +1 -1
  78. package/dist/components/chat-view/MessageItem.js +4 -2
  79. package/dist/components/chat-view/MessageItem.js.map +1 -1
  80. package/dist/components/chat-view/tool-part-rendering.d.ts +1 -0
  81. package/dist/components/chat-view/tool-part-rendering.d.ts.map +1 -1
  82. package/dist/components/chat-view/tool-part-rendering.js +8 -1
  83. package/dist/components/chat-view/tool-part-rendering.js.map +1 -1
  84. package/dist/components/chip/index.d.ts +1 -0
  85. package/dist/components/chip/index.d.ts.map +1 -1
  86. package/dist/components/chip/index.js +2 -1
  87. package/dist/components/chip/index.js.map +1 -1
  88. package/dist/components/embedded-chat/index.d.ts +1 -1
  89. package/dist/components/embedded-chat/index.d.ts.map +1 -1
  90. package/dist/components/embedded-chat/index.js +1 -1
  91. package/dist/components/embedded-chat/index.js.map +1 -1
  92. package/dist/components/input/input-date-time.d.ts +6 -0
  93. package/dist/components/input/input-date-time.d.ts.map +1 -1
  94. package/dist/components/input/input-date-time.js +2 -1
  95. package/dist/components/input/input-date-time.js.map +1 -1
  96. package/dist/components/input/input-date.d.ts +22 -0
  97. package/dist/components/input/input-date.d.ts.map +1 -1
  98. package/dist/components/input/input-date.js +28 -14
  99. package/dist/components/input/input-date.js.map +1 -1
  100. package/dist/components/input/input-time.d.ts +9 -0
  101. package/dist/components/input/input-time.d.ts.map +1 -1
  102. package/dist/components/input/input-time.js +29 -18
  103. package/dist/components/input/input-time.js.map +1 -1
  104. package/dist/components/layouts/RouteLayout.d.ts +0 -9
  105. package/dist/components/layouts/RouteLayout.d.ts.map +1 -1
  106. package/dist/components/layouts/RouteLayout.js +7 -4
  107. package/dist/components/layouts/RouteLayout.js.map +1 -1
  108. package/dist/components/layouts/Sidebar.d.ts +1 -8
  109. package/dist/components/layouts/Sidebar.d.ts.map +1 -1
  110. package/dist/components/layouts/Sidebar.js +7 -14
  111. package/dist/components/layouts/Sidebar.js.map +1 -1
  112. package/dist/components/plan-limits/PlanLimitsDialog.d.ts +20 -0
  113. package/dist/components/plan-limits/PlanLimitsDialog.d.ts.map +1 -0
  114. package/dist/components/plan-limits/PlanLimitsDialog.js +109 -0
  115. package/dist/components/plan-limits/PlanLimitsDialog.js.map +1 -0
  116. package/dist/components/plan-limits/index.d.ts +4 -0
  117. package/dist/components/plan-limits/index.d.ts.map +1 -0
  118. package/dist/components/plan-limits/index.js +2 -0
  119. package/dist/components/plan-limits/index.js.map +1 -0
  120. package/dist/components/plan-limits/plan-limits-client.d.ts +15 -0
  121. package/dist/components/plan-limits/plan-limits-client.d.ts.map +1 -0
  122. package/dist/components/plan-limits/plan-limits-client.js +44 -0
  123. package/dist/components/plan-limits/plan-limits-client.js.map +1 -0
  124. package/dist/components/plan-limits/plan-limits-model.d.ts +66 -0
  125. package/dist/components/plan-limits/plan-limits-model.d.ts.map +1 -0
  126. package/dist/components/plan-limits/plan-limits-model.js +123 -0
  127. package/dist/components/plan-limits/plan-limits-model.js.map +1 -0
  128. package/dist/components/plan-limits/plan-limits-save.d.ts +31 -0
  129. package/dist/components/plan-limits/plan-limits-save.d.ts.map +1 -0
  130. package/dist/components/plan-limits/plan-limits-save.js +43 -0
  131. package/dist/components/plan-limits/plan-limits-save.js.map +1 -0
  132. package/dist/components/planning/PlanLimitsAction.d.ts +6 -0
  133. package/dist/components/planning/PlanLimitsAction.d.ts.map +1 -0
  134. package/dist/components/planning/PlanLimitsAction.js +19 -0
  135. package/dist/components/planning/PlanLimitsAction.js.map +1 -0
  136. package/dist/components/slider/index.d.ts.map +1 -1
  137. package/dist/components/slider/index.js +2 -1
  138. package/dist/components/slider/index.js.map +1 -1
  139. package/dist/datastore-picker/datastore-picker-rows.d.ts +7 -0
  140. package/dist/datastore-picker/datastore-picker-rows.d.ts.map +1 -1
  141. package/dist/datastore-picker/datastore-picker-rows.js +26 -22
  142. package/dist/datastore-picker/datastore-picker-rows.js.map +1 -1
  143. package/dist/globals.css +85 -2
  144. package/dist/hooks/use-action-plans-list.d.ts +3 -0
  145. package/dist/hooks/use-action-plans-list.d.ts.map +1 -1
  146. package/dist/hooks/use-action-plans-list.js +8 -9
  147. package/dist/hooks/use-action-plans-list.js.map +1 -1
  148. package/dist/hooks/use-activity-feed.d.ts +10 -1
  149. package/dist/hooks/use-activity-feed.d.ts.map +1 -1
  150. package/dist/hooks/use-activity-feed.js +9 -11
  151. package/dist/hooks/use-activity-feed.js.map +1 -1
  152. package/dist/hooks/use-entity.d.ts +4 -3
  153. package/dist/hooks/use-entity.d.ts.map +1 -1
  154. package/dist/hooks/use-entity.js +4 -4
  155. package/dist/hooks/use-entity.js.map +1 -1
  156. package/dist/hooks/use-manual-actions.d.ts +1 -1
  157. package/dist/hooks/use-manual-actions.d.ts.map +1 -1
  158. package/dist/hooks/use-manual-actions.js +5 -5
  159. package/dist/hooks/use-manual-actions.js.map +1 -1
  160. package/dist/hooks/use-unsaved-changes-warning.d.ts +2 -0
  161. package/dist/hooks/use-unsaved-changes-warning.d.ts.map +1 -0
  162. package/dist/hooks/use-unsaved-changes-warning.js +13 -0
  163. package/dist/hooks/use-unsaved-changes-warning.js.map +1 -0
  164. package/dist/hooks/useAuth.d.ts.map +1 -1
  165. package/dist/hooks/useAuth.js +4 -3
  166. package/dist/hooks/useAuth.js.map +1 -1
  167. package/dist/hooks/useChatPanelSync.d.ts.map +1 -1
  168. package/dist/hooks/useChatPanelSync.js +2 -3
  169. package/dist/hooks/useChatPanelSync.js.map +1 -1
  170. package/dist/hooks/useDatastoreSelection.d.ts.map +1 -1
  171. package/dist/hooks/useDatastoreSelection.js +11 -4
  172. package/dist/hooks/useDatastoreSelection.js.map +1 -1
  173. package/dist/hooks/useExecuteAction.d.ts +1 -0
  174. package/dist/hooks/useExecuteAction.d.ts.map +1 -1
  175. package/dist/hooks/useExecuteAction.js.map +1 -1
  176. package/dist/hooks/useLoginRedirect.d.ts +6 -0
  177. package/dist/hooks/useLoginRedirect.d.ts.map +1 -0
  178. package/dist/hooks/useLoginRedirect.js +51 -0
  179. package/dist/hooks/useLoginRedirect.js.map +1 -0
  180. package/dist/hooks/usePlanLimits.d.ts +18 -0
  181. package/dist/hooks/usePlanLimits.d.ts.map +1 -0
  182. package/dist/hooks/usePlanLimits.js +56 -0
  183. package/dist/hooks/usePlanLimits.js.map +1 -0
  184. package/dist/ldo-ui.d.ts +1 -1
  185. package/dist/ldo-ui.d.ts.map +1 -1
  186. package/dist/ldo-ui.js.map +1 -1
  187. package/dist/lib/app-tools.d.ts +18 -0
  188. package/dist/lib/app-tools.d.ts.map +1 -0
  189. package/dist/lib/app-tools.js +42 -0
  190. package/dist/lib/app-tools.js.map +1 -0
  191. package/dist/lib/chat-types.d.ts +3 -0
  192. package/dist/lib/chat-types.d.ts.map +1 -1
  193. package/dist/lib/chat-types.js.map +1 -1
  194. package/dist/lib/datastore-route-table.d.ts +3 -0
  195. package/dist/lib/datastore-route-table.d.ts.map +1 -1
  196. package/dist/lib/datastore-route-table.js +6 -0
  197. package/dist/lib/datastore-route-table.js.map +1 -1
  198. package/dist/lib/graphql-error.d.ts +2 -0
  199. package/dist/lib/graphql-error.d.ts.map +1 -0
  200. package/dist/lib/graphql-error.js +7 -0
  201. package/dist/lib/graphql-error.js.map +1 -0
  202. package/dist/lib/update-notice.d.ts +2 -1
  203. package/dist/lib/update-notice.d.ts.map +1 -1
  204. package/dist/lib/update-notice.js +8 -2
  205. package/dist/lib/update-notice.js.map +1 -1
  206. package/dist/providers/ActiveChatProvider.d.ts +2 -0
  207. package/dist/providers/ActiveChatProvider.d.ts.map +1 -1
  208. package/dist/providers/ActiveChatProvider.js +6 -3
  209. package/dist/providers/ActiveChatProvider.js.map +1 -1
  210. package/dist/providers/ActiveDatastoreProvider.d.ts +12 -0
  211. package/dist/providers/ActiveDatastoreProvider.d.ts.map +1 -1
  212. package/dist/providers/ActiveDatastoreProvider.js +114 -11
  213. package/dist/providers/ActiveDatastoreProvider.js.map +1 -1
  214. package/dist/providers/AuthContext.d.ts +1 -0
  215. package/dist/providers/AuthContext.d.ts.map +1 -1
  216. package/dist/providers/AuthContext.js.map +1 -1
  217. package/dist/providers/KnowledgeGraphStateContext.d.ts +2 -2
  218. package/dist/providers/KnowledgeGraphStateContext.d.ts.map +1 -1
  219. package/dist/providers/KnowledgeGraphStateProvider.d.ts.map +1 -1
  220. package/dist/providers/KnowledgeGraphStateProvider.js +8 -49
  221. package/dist/providers/KnowledgeGraphStateProvider.js.map +1 -1
  222. package/dist/providers/MantaClientProvider.d.ts.map +1 -1
  223. package/dist/providers/MantaClientProvider.js +3 -3
  224. package/dist/providers/MantaClientProvider.js.map +1 -1
  225. package/dist/providers/index.d.ts +3 -1
  226. package/dist/providers/index.d.ts.map +1 -1
  227. package/dist/providers/index.js +2 -2
  228. package/dist/providers/index.js.map +1 -1
  229. package/dist/routes/activity/detail/ActivityDetailRoute.d.ts.map +1 -1
  230. package/dist/routes/activity/detail/ActivityDetailRoute.js +1 -3
  231. package/dist/routes/activity/detail/ActivityDetailRoute.js.map +1 -1
  232. package/dist/routes/activity/index.d.ts.map +1 -1
  233. package/dist/routes/activity/index.js +1 -3
  234. package/dist/routes/activity/index.js.map +1 -1
  235. package/dist/routes/chat/index.d.ts +2 -21
  236. package/dist/routes/chat/index.d.ts.map +1 -1
  237. package/dist/routes/chat/index.js +4 -2
  238. package/dist/routes/chat/index.js.map +1 -1
  239. package/dist/routes/data-collection/index.d.ts.map +1 -1
  240. package/dist/routes/data-collection/index.js +1 -3
  241. package/dist/routes/data-collection/index.js.map +1 -1
  242. package/dist/routes/data-explorer/components/DataExplorerLayout.d.ts.map +1 -1
  243. package/dist/routes/data-explorer/components/DataExplorerLayout.js +1 -3
  244. package/dist/routes/data-explorer/components/DataExplorerLayout.js.map +1 -1
  245. package/dist/routes/data-explorer/components/class-detail/UsedByRules.js +2 -2
  246. package/dist/routes/data-explorer/components/class-detail/UsedByRules.js.map +1 -1
  247. package/dist/routes/datastores/index.d.ts.map +1 -1
  248. package/dist/routes/datastores/index.js +2 -2
  249. package/dist/routes/datastores/index.js.map +1 -1
  250. package/dist/routes/explain/index.d.ts.map +1 -1
  251. package/dist/routes/explain/index.js +1 -3
  252. package/dist/routes/explain/index.js.map +1 -1
  253. package/dist/routes/integrations/components/connect-forms/DashConnectForm.d.ts.map +1 -1
  254. package/dist/routes/integrations/components/connect-forms/DashConnectForm.js +0 -1
  255. package/dist/routes/integrations/components/connect-forms/DashConnectForm.js.map +1 -1
  256. package/dist/routes/integrations/components/connect-forms/GoogleAdsConnectForm.d.ts.map +1 -1
  257. package/dist/routes/integrations/components/connect-forms/GoogleAdsConnectForm.js +0 -1
  258. package/dist/routes/integrations/components/connect-forms/GoogleAdsConnectForm.js.map +1 -1
  259. package/dist/routes/integrations/components/connect-forms/GoogleAnalyticsConnectForm.d.ts.map +1 -1
  260. package/dist/routes/integrations/components/connect-forms/GoogleAnalyticsConnectForm.js +0 -1
  261. package/dist/routes/integrations/components/connect-forms/GoogleAnalyticsConnectForm.js.map +1 -1
  262. package/dist/routes/integrations/components/connect-forms/GoogleMerchantCenterConnectForm.d.ts.map +1 -1
  263. package/dist/routes/integrations/components/connect-forms/GoogleMerchantCenterConnectForm.js +0 -1
  264. package/dist/routes/integrations/components/connect-forms/GoogleMerchantCenterConnectForm.js.map +1 -1
  265. package/dist/routes/integrations/components/connect-forms/InferalCredentialConnectForm.d.ts +0 -1
  266. package/dist/routes/integrations/components/connect-forms/InferalCredentialConnectForm.d.ts.map +1 -1
  267. package/dist/routes/integrations/components/connect-forms/InferalCredentialConnectForm.js +3 -2
  268. package/dist/routes/integrations/components/connect-forms/InferalCredentialConnectForm.js.map +1 -1
  269. package/dist/routes/integrations/components/connect-forms/KlaviyoConnectForm.d.ts.map +1 -1
  270. package/dist/routes/integrations/components/connect-forms/KlaviyoConnectForm.js +0 -1
  271. package/dist/routes/integrations/components/connect-forms/KlaviyoConnectForm.js.map +1 -1
  272. package/dist/routes/integrations/components/connect-forms/MicrosoftAdsConnectForm.d.ts.map +1 -1
  273. package/dist/routes/integrations/components/connect-forms/MicrosoftAdsConnectForm.js +0 -1
  274. package/dist/routes/integrations/components/connect-forms/MicrosoftAdsConnectForm.js.map +1 -1
  275. package/dist/routes/integrations/components/connect-forms/OAuthSetupConnectForm.d.ts +0 -1
  276. package/dist/routes/integrations/components/connect-forms/OAuthSetupConnectForm.d.ts.map +1 -1
  277. package/dist/routes/integrations/components/connect-forms/OAuthSetupConnectForm.js +4 -3
  278. package/dist/routes/integrations/components/connect-forms/OAuthSetupConnectForm.js.map +1 -1
  279. package/dist/routes/integrations/components/connect-forms/TriplewhaleConnectForm.d.ts.map +1 -1
  280. package/dist/routes/integrations/components/connect-forms/TriplewhaleConnectForm.js +0 -1
  281. package/dist/routes/integrations/components/connect-forms/TriplewhaleConnectForm.js.map +1 -1
  282. package/dist/routes/integrations/components/connect-forms/WoocommerceConnectForm.d.ts.map +1 -1
  283. package/dist/routes/integrations/components/connect-forms/WoocommerceConnectForm.js +0 -1
  284. package/dist/routes/integrations/components/connect-forms/WoocommerceConnectForm.js.map +1 -1
  285. package/dist/routes/integrations/types.d.ts +2 -1
  286. package/dist/routes/integrations/types.d.ts.map +1 -1
  287. package/dist/routes/integrations/types.js +16 -0
  288. package/dist/routes/integrations/types.js.map +1 -1
  289. package/dist/routes/memories/components/DateValueInput.d.ts +16 -0
  290. package/dist/routes/memories/components/DateValueInput.d.ts.map +1 -0
  291. package/dist/routes/memories/components/DateValueInput.js +35 -0
  292. package/dist/routes/memories/components/DateValueInput.js.map +1 -0
  293. package/dist/routes/memories/components/EntityValuePicker.d.ts +11 -0
  294. package/dist/routes/memories/components/EntityValuePicker.d.ts.map +1 -0
  295. package/dist/routes/memories/components/EntityValuePicker.js +61 -0
  296. package/dist/routes/memories/components/EntityValuePicker.js.map +1 -0
  297. package/dist/routes/memories/components/FieldLabel.d.ts +12 -0
  298. package/dist/routes/memories/components/FieldLabel.d.ts.map +1 -0
  299. package/dist/routes/memories/components/FieldLabel.js +12 -0
  300. package/dist/routes/memories/components/FieldLabel.js.map +1 -0
  301. package/dist/routes/memories/components/ImportanceSlider.d.ts +2 -0
  302. package/dist/routes/memories/components/ImportanceSlider.d.ts.map +1 -1
  303. package/dist/routes/memories/components/ImportanceSlider.js +4 -1
  304. package/dist/routes/memories/components/ImportanceSlider.js.map +1 -1
  305. package/dist/routes/memories/components/MemoriesFilters.d.ts +2 -2
  306. package/dist/routes/memories/components/MemoriesFilters.d.ts.map +1 -1
  307. package/dist/routes/memories/components/MemoriesFilters.js.map +1 -1
  308. package/dist/routes/memories/components/MemoriesPanel.d.ts.map +1 -1
  309. package/dist/routes/memories/components/MemoriesPanel.js +4 -0
  310. package/dist/routes/memories/components/MemoriesPanel.js.map +1 -1
  311. package/dist/routes/memories/components/MemoriesTabPanel.d.ts +2 -2
  312. package/dist/routes/memories/components/MemoriesTabPanel.d.ts.map +1 -1
  313. package/dist/routes/memories/components/MemoryActions.d.ts +2 -0
  314. package/dist/routes/memories/components/MemoryActions.d.ts.map +1 -1
  315. package/dist/routes/memories/components/MemoryActions.js +3 -3
  316. package/dist/routes/memories/components/MemoryActions.js.map +1 -1
  317. package/dist/routes/memories/components/MemoryFields.d.ts +15 -3
  318. package/dist/routes/memories/components/MemoryFields.d.ts.map +1 -1
  319. package/dist/routes/memories/components/MemoryFields.js +34 -5
  320. package/dist/routes/memories/components/MemoryFields.js.map +1 -1
  321. package/dist/routes/memories/components/MemoryFormDialog.d.ts +6 -3
  322. package/dist/routes/memories/components/MemoryFormDialog.d.ts.map +1 -1
  323. package/dist/routes/memories/components/MemoryFormDialog.js +105 -59
  324. package/dist/routes/memories/components/MemoryFormDialog.js.map +1 -1
  325. package/dist/routes/memories/components/MemoryPropertyFields.d.ts +10 -0
  326. package/dist/routes/memories/components/MemoryPropertyFields.d.ts.map +1 -0
  327. package/dist/routes/memories/components/MemoryPropertyFields.js +67 -0
  328. package/dist/routes/memories/components/MemoryPropertyFields.js.map +1 -0
  329. package/dist/routes/memories/components/RuleDraftDialog.d.ts +7 -0
  330. package/dist/routes/memories/components/RuleDraftDialog.d.ts.map +1 -0
  331. package/dist/routes/memories/components/RuleDraftDialog.js +20 -0
  332. package/dist/routes/memories/components/RuleDraftDialog.js.map +1 -0
  333. package/dist/routes/memories/components/SchemasTab.d.ts +17 -2
  334. package/dist/routes/memories/components/SchemasTab.d.ts.map +1 -1
  335. package/dist/routes/memories/components/SchemasTab.js +146 -28
  336. package/dist/routes/memories/components/SchemasTab.js.map +1 -1
  337. package/dist/routes/memories/components/badges.d.ts +7 -0
  338. package/dist/routes/memories/components/badges.d.ts.map +1 -1
  339. package/dist/routes/memories/components/badges.js +11 -3
  340. package/dist/routes/memories/components/badges.js.map +1 -1
  341. package/dist/routes/memories/hooks/useMemoryColumns.d.ts +4 -2
  342. package/dist/routes/memories/hooks/useMemoryColumns.d.ts.map +1 -1
  343. package/dist/routes/memories/hooks/useMemoryColumns.js +31 -15
  344. package/dist/routes/memories/hooks/useMemoryColumns.js.map +1 -1
  345. package/dist/routes/memories/index.d.ts +2 -1
  346. package/dist/routes/memories/index.d.ts.map +1 -1
  347. package/dist/routes/memories/index.js +72 -30
  348. package/dist/routes/memories/index.js.map +1 -1
  349. package/dist/routes/memories/memory-mutation-input.d.ts.map +1 -1
  350. package/dist/routes/memories/memory-mutation-input.js +5 -2
  351. package/dist/routes/memories/memory-mutation-input.js.map +1 -1
  352. package/dist/routes/memories/memory-property-values.d.ts +13 -0
  353. package/dist/routes/memories/memory-property-values.d.ts.map +1 -0
  354. package/dist/routes/memories/memory-property-values.js +40 -0
  355. package/dist/routes/memories/memory-property-values.js.map +1 -0
  356. package/dist/routes/memories/schemas/AllowedValuesField.d.ts +14 -0
  357. package/dist/routes/memories/schemas/AllowedValuesField.d.ts.map +1 -0
  358. package/dist/routes/memories/schemas/AllowedValuesField.js +64 -0
  359. package/dist/routes/memories/schemas/AllowedValuesField.js.map +1 -0
  360. package/dist/routes/memories/schemas/MemorySchemaPage.d.ts +127 -0
  361. package/dist/routes/memories/schemas/MemorySchemaPage.d.ts.map +1 -0
  362. package/dist/routes/memories/schemas/MemorySchemaPage.js +285 -0
  363. package/dist/routes/memories/schemas/MemorySchemaPage.js.map +1 -0
  364. package/dist/routes/memories/schemas/SchemaChangeReviewDialog.d.ts +20 -0
  365. package/dist/routes/memories/schemas/SchemaChangeReviewDialog.d.ts.map +1 -0
  366. package/dist/routes/memories/schemas/SchemaChangeReviewDialog.js +54 -0
  367. package/dist/routes/memories/schemas/SchemaChangeReviewDialog.js.map +1 -0
  368. package/dist/routes/memories/schemas/SchemaConfirmDialog.d.ts +15 -0
  369. package/dist/routes/memories/schemas/SchemaConfirmDialog.d.ts.map +1 -0
  370. package/dist/routes/memories/schemas/SchemaConfirmDialog.js +8 -0
  371. package/dist/routes/memories/schemas/SchemaConfirmDialog.js.map +1 -0
  372. package/dist/routes/memories/schemas/SchemaDetailPage.d.ts +15 -0
  373. package/dist/routes/memories/schemas/SchemaDetailPage.d.ts.map +1 -0
  374. package/dist/routes/memories/schemas/SchemaDetailPage.js +74 -0
  375. package/dist/routes/memories/schemas/SchemaDetailPage.js.map +1 -0
  376. package/dist/routes/memories/schemas/SchemaEditorForm.d.ts +10 -0
  377. package/dist/routes/memories/schemas/SchemaEditorForm.d.ts.map +1 -0
  378. package/dist/routes/memories/schemas/SchemaEditorForm.js +242 -0
  379. package/dist/routes/memories/schemas/SchemaEditorForm.js.map +1 -0
  380. package/dist/routes/memories/schemas/SchemaTemplatesDialog.d.ts +13 -0
  381. package/dist/routes/memories/schemas/SchemaTemplatesDialog.d.ts.map +1 -0
  382. package/dist/routes/memories/schemas/SchemaTemplatesDialog.js +13 -0
  383. package/dist/routes/memories/schemas/SchemaTemplatesDialog.js.map +1 -0
  384. package/dist/routes/memories/schemas/ValueTypeSelect.d.ts +12 -0
  385. package/dist/routes/memories/schemas/ValueTypeSelect.d.ts.map +1 -0
  386. package/dist/routes/memories/schemas/ValueTypeSelect.js +10 -0
  387. package/dist/routes/memories/schemas/ValueTypeSelect.js.map +1 -0
  388. package/dist/routes/memories/schemas/schema-form.d.ts +72 -0
  389. package/dist/routes/memories/schemas/schema-form.d.ts.map +1 -0
  390. package/dist/routes/memories/schemas/schema-form.js +279 -0
  391. package/dist/routes/memories/schemas/schema-form.js.map +1 -0
  392. package/dist/routes/memories/schemas/schema-impact.d.ts +13 -0
  393. package/dist/routes/memories/schemas/schema-impact.d.ts.map +1 -0
  394. package/dist/routes/memories/schemas/schema-impact.js +40 -0
  395. package/dist/routes/memories/schemas/schema-impact.js.map +1 -0
  396. package/dist/routes/memories/schemas/schema-route.d.ts +18 -0
  397. package/dist/routes/memories/schemas/schema-route.d.ts.map +1 -0
  398. package/dist/routes/memories/schemas/schema-route.js +21 -0
  399. package/dist/routes/memories/schemas/schema-route.js.map +1 -0
  400. package/dist/routes/memories/schemas/schema-rule-context.d.ts +17 -0
  401. package/dist/routes/memories/schemas/schema-rule-context.d.ts.map +1 -0
  402. package/dist/routes/memories/schemas/schema-rule-context.js +83 -0
  403. package/dist/routes/memories/schemas/schema-rule-context.js.map +1 -0
  404. package/dist/routes/memories/schemas/schema-table.d.ts +11 -0
  405. package/dist/routes/memories/schemas/schema-table.d.ts.map +1 -0
  406. package/dist/routes/memories/schemas/schema-table.js +34 -0
  407. package/dist/routes/memories/schemas/schema-table.js.map +1 -0
  408. package/dist/routes/memories/schemas/useMemorySchemaMutations.d.ts +32 -0
  409. package/dist/routes/memories/schemas/useMemorySchemaMutations.d.ts.map +1 -0
  410. package/dist/routes/memories/schemas/useMemorySchemaMutations.js +31 -0
  411. package/dist/routes/memories/schemas/useMemorySchemaMutations.js.map +1 -0
  412. package/dist/routes/memories/schemas/useSchemaChangeReview.d.ts +51 -0
  413. package/dist/routes/memories/schemas/useSchemaChangeReview.d.ts.map +1 -0
  414. package/dist/routes/memories/schemas/useSchemaChangeReview.js +175 -0
  415. package/dist/routes/memories/schemas/useSchemaChangeReview.js.map +1 -0
  416. package/dist/routes/memories/schemas/useSchemaLifecycle.d.ts +46 -0
  417. package/dist/routes/memories/schemas/useSchemaLifecycle.d.ts.map +1 -0
  418. package/dist/routes/memories/schemas/useSchemaLifecycle.js +93 -0
  419. package/dist/routes/memories/schemas/useSchemaLifecycle.js.map +1 -0
  420. package/dist/routes/memories/schemas/useSchemasTab.d.ts +18 -0
  421. package/dist/routes/memories/schemas/useSchemasTab.d.ts.map +1 -0
  422. package/dist/routes/memories/schemas/useSchemasTab.js +92 -0
  423. package/dist/routes/memories/schemas/useSchemasTab.js.map +1 -0
  424. package/dist/routes/plans/index.d.ts.map +1 -1
  425. package/dist/routes/plans/index.js +2 -2
  426. package/dist/routes/plans/index.js.map +1 -1
  427. package/dist/routes/rules/components/CreateRuleChatModal.d.ts +7 -1
  428. package/dist/routes/rules/components/CreateRuleChatModal.d.ts.map +1 -1
  429. package/dist/routes/rules/components/CreateRuleChatModal.js +9 -4
  430. package/dist/routes/rules/components/CreateRuleChatModal.js.map +1 -1
  431. package/dist/routes/rules/components/RuleValueControls.d.ts.map +1 -1
  432. package/dist/routes/rules/components/RuleValueControls.js +3 -24
  433. package/dist/routes/rules/components/RuleValueControls.js.map +1 -1
  434. package/dist/routes/rules/components/rule-value-input.d.ts +11 -0
  435. package/dist/routes/rules/components/rule-value-input.d.ts.map +1 -0
  436. package/dist/routes/rules/components/rule-value-input.js +24 -0
  437. package/dist/routes/rules/components/rule-value-input.js.map +1 -0
  438. package/dist/routes/rules/components/rules.utils.d.ts +5 -0
  439. package/dist/routes/rules/components/rules.utils.d.ts.map +1 -1
  440. package/dist/routes/rules/components/rules.utils.js +18 -3
  441. package/dist/routes/rules/components/rules.utils.js.map +1 -1
  442. package/dist/routes/rules/pages.d.ts +1 -1
  443. package/dist/routes/rules/pages.d.ts.map +1 -1
  444. package/dist/routes/rules/pages.js +1 -1
  445. package/dist/routes/rules/pages.js.map +1 -1
  446. package/dist/shared/graph-derived-queries.d.ts.map +1 -1
  447. package/dist/shared/graph-derived-queries.js +4 -1
  448. package/dist/shared/graph-derived-queries.js.map +1 -1
  449. package/dist/worker/index.d.ts +22 -0
  450. package/dist/worker/index.d.ts.map +1 -0
  451. package/dist/worker/index.js +110 -0
  452. package/dist/worker/index.js.map +1 -0
  453. package/dist/worker/policy.d.ts +21 -0
  454. package/dist/worker/policy.d.ts.map +1 -0
  455. package/dist/worker/policy.js +42 -0
  456. package/dist/worker/policy.js.map +1 -0
  457. package/dist/worker/proxy.d.ts +14 -0
  458. package/dist/worker/proxy.d.ts.map +1 -0
  459. package/dist/worker/proxy.js +58 -0
  460. package/dist/worker/proxy.js.map +1 -0
  461. package/dist/worker/session.d.ts +24 -0
  462. package/dist/worker/session.d.ts.map +1 -0
  463. package/dist/worker/session.js +72 -0
  464. package/dist/worker/session.js.map +1 -0
  465. package/package.json +52 -7
  466. package/src/app-subpaths.json +9 -1
  467. package/src/components/AppErrorBoundary.tsx +14 -11
  468. package/src/components/app-gate/AppGate.tsx +122 -0
  469. package/src/components/app-gate/AwaitingDatastoreStatus.tsx +35 -0
  470. package/src/components/app-gate/EnterDatastoreRoute.tsx +30 -0
  471. package/src/components/app-gate/ErrorRoute.tsx +43 -0
  472. package/src/components/app-gate/FailureAlert.tsx +15 -0
  473. package/src/components/app-gate/NoDatastoreAccess.tsx +26 -0
  474. package/src/components/app-gate/NotFoundRoute.tsx +20 -0
  475. package/src/components/app-gate/PendingInvitations.tsx +134 -0
  476. package/src/components/app-gate/ServiceError.tsx +27 -0
  477. package/src/components/app-gate/index.ts +2 -0
  478. package/src/components/app-gate/sdk-route-elements.tsx +46 -0
  479. package/src/components/app-shell/AppShell.tsx +22 -0
  480. package/src/components/app-shell/AppShellRoutes.tsx +34 -0
  481. package/src/components/app-shell/GroupDatastores.tsx +28 -0
  482. package/src/components/app-shell/GroupRoute.tsx +34 -0
  483. package/src/components/app-shell/index.ts +2 -0
  484. package/src/components/authenticated-chat/index.tsx +1 -34
  485. package/src/components/chat-view/Chat.tsx +9 -3
  486. package/src/components/chat-view/MessageItem.tsx +10 -2
  487. package/src/components/chat-view/tool-part-rendering.ts +10 -1
  488. package/src/components/chip/index.tsx +8 -1
  489. package/src/components/embedded-chat/index.tsx +2 -1
  490. package/src/components/input/input-date-time.tsx +10 -3
  491. package/src/components/input/input-date.tsx +93 -21
  492. package/src/components/input/input-time.tsx +59 -26
  493. package/src/components/layouts/RouteLayout.tsx +11 -50
  494. package/src/components/layouts/Sidebar.tsx +21 -23
  495. package/src/components/plan-limits/PlanLimitsDialog.tsx +331 -0
  496. package/src/components/plan-limits/index.tsx +3 -0
  497. package/src/components/plan-limits/plan-limits-client.ts +71 -0
  498. package/src/components/plan-limits/plan-limits-model.ts +180 -0
  499. package/src/components/plan-limits/plan-limits-save.ts +68 -0
  500. package/src/components/planning/PlanLimitsAction.tsx +44 -0
  501. package/src/components/slider/index.tsx +2 -1
  502. package/src/datastore-picker/datastore-picker-rows.ts +36 -20
  503. package/src/hooks/use-action-plans-list.ts +20 -12
  504. package/src/hooks/use-activity-feed.ts +30 -14
  505. package/src/hooks/use-entity.ts +11 -6
  506. package/src/hooks/use-manual-actions.ts +11 -6
  507. package/src/hooks/use-unsaved-changes-warning.ts +12 -0
  508. package/src/hooks/useAuth.ts +5 -3
  509. package/src/hooks/useChatPanelSync.ts +2 -3
  510. package/src/hooks/useDatastoreSelection.ts +10 -4
  511. package/src/hooks/useExecuteAction.ts +2 -0
  512. package/src/hooks/useLoginRedirect.ts +66 -0
  513. package/src/hooks/usePlanLimits.ts +97 -0
  514. package/src/ldo-ui.ts +1 -0
  515. package/src/lib/app-tools.ts +63 -0
  516. package/src/lib/chat-types.ts +5 -0
  517. package/src/lib/datastore-route-table.ts +9 -0
  518. package/src/lib/graphql-error.ts +7 -0
  519. package/src/lib/update-notice.ts +12 -2
  520. package/src/providers/ActiveChatProvider.tsx +8 -3
  521. package/src/providers/ActiveDatastoreProvider.tsx +179 -9
  522. package/src/providers/AuthContext.ts +1 -0
  523. package/src/providers/KnowledgeGraphStateContext.ts +2 -2
  524. package/src/providers/KnowledgeGraphStateProvider.tsx +13 -65
  525. package/src/providers/MantaClientProvider.tsx +8 -3
  526. package/src/providers/index.tsx +7 -4
  527. package/src/routes/activity/detail/ActivityDetailRoute.tsx +1 -10
  528. package/src/routes/activity/index.tsx +1 -10
  529. package/src/routes/chat/index.tsx +11 -47
  530. package/src/routes/data-collection/index.tsx +1 -11
  531. package/src/routes/data-explorer/components/DataExplorerLayout.tsx +1 -11
  532. package/src/routes/data-explorer/components/class-detail/UsedByRules.tsx +2 -2
  533. package/src/routes/datastores/index.tsx +3 -9
  534. package/src/routes/explain/index.tsx +1 -11
  535. package/src/routes/integrations/components/connect-forms/DashConnectForm.tsx +0 -1
  536. package/src/routes/integrations/components/connect-forms/GoogleAdsConnectForm.tsx +0 -1
  537. package/src/routes/integrations/components/connect-forms/GoogleAnalyticsConnectForm.tsx +0 -1
  538. package/src/routes/integrations/components/connect-forms/GoogleMerchantCenterConnectForm.tsx +0 -1
  539. package/src/routes/integrations/components/connect-forms/InferalCredentialConnectForm.tsx +5 -3
  540. package/src/routes/integrations/components/connect-forms/KlaviyoConnectForm.tsx +0 -1
  541. package/src/routes/integrations/components/connect-forms/MicrosoftAdsConnectForm.tsx +0 -1
  542. package/src/routes/integrations/components/connect-forms/OAuthSetupConnectForm.tsx +7 -7
  543. package/src/routes/integrations/components/connect-forms/TriplewhaleConnectForm.tsx +0 -1
  544. package/src/routes/integrations/components/connect-forms/WoocommerceConnectForm.tsx +0 -1
  545. package/src/routes/integrations/types.ts +22 -6
  546. package/src/routes/memories/components/DateValueInput.tsx +72 -0
  547. package/src/routes/memories/components/EntityValuePicker.tsx +132 -0
  548. package/src/routes/memories/components/FieldLabel.tsx +49 -0
  549. package/src/routes/memories/components/ImportanceSlider.tsx +5 -1
  550. package/src/routes/memories/components/MemoriesFilters.tsx +2 -2
  551. package/src/routes/memories/components/MemoriesPanel.tsx +7 -3
  552. package/src/routes/memories/components/MemoriesTabPanel.tsx +2 -2
  553. package/src/routes/memories/components/MemoryActions.tsx +26 -2
  554. package/src/routes/memories/components/MemoryFields.tsx +75 -12
  555. package/src/routes/memories/components/MemoryFormDialog.tsx +305 -199
  556. package/src/routes/memories/components/MemoryPropertyFields.tsx +288 -0
  557. package/src/routes/memories/components/RuleDraftDialog.tsx +35 -0
  558. package/src/routes/memories/components/SchemasTab.tsx +481 -118
  559. package/src/routes/memories/components/badges.tsx +16 -4
  560. package/src/routes/memories/hooks/useMemoryColumns.tsx +69 -35
  561. package/src/routes/memories/index.tsx +125 -51
  562. package/src/routes/memories/memory-mutation-input.ts +5 -2
  563. package/src/routes/memories/memory-property-values.ts +83 -0
  564. package/src/routes/memories/schemas/AllowedValuesField.tsx +188 -0
  565. package/src/routes/memories/schemas/MemorySchemaPage.tsx +476 -0
  566. package/src/routes/memories/schemas/SchemaChangeReviewDialog.tsx +290 -0
  567. package/src/routes/memories/schemas/SchemaConfirmDialog.tsx +62 -0
  568. package/src/routes/memories/schemas/SchemaDetailPage.tsx +373 -0
  569. package/src/routes/memories/schemas/SchemaEditorForm.tsx +990 -0
  570. package/src/routes/memories/schemas/SchemaTemplatesDialog.tsx +81 -0
  571. package/src/routes/memories/schemas/ValueTypeSelect.tsx +37 -0
  572. package/src/routes/memories/schemas/schema-form.ts +360 -0
  573. package/src/routes/memories/schemas/schema-impact.ts +66 -0
  574. package/src/routes/memories/schemas/schema-route.ts +30 -0
  575. package/src/routes/memories/schemas/schema-rule-context.ts +103 -0
  576. package/src/routes/memories/schemas/schema-table.ts +54 -0
  577. package/src/routes/memories/schemas/useMemorySchemaMutations.ts +49 -0
  578. package/src/routes/memories/schemas/useSchemaChangeReview.ts +238 -0
  579. package/src/routes/memories/schemas/useSchemaLifecycle.tsx +151 -0
  580. package/src/routes/memories/schemas/useSchemasTab.ts +119 -0
  581. package/src/routes/plans/index.tsx +3 -14
  582. package/src/routes/rules/components/CreateRuleChatModal.tsx +46 -22
  583. package/src/routes/rules/components/RuleValueControls.tsx +3 -35
  584. package/src/routes/rules/components/rule-value-input.ts +34 -0
  585. package/src/routes/rules/components/rules.utils.ts +25 -3
  586. package/src/routes/rules/pages.ts +5 -1
  587. package/src/shared/graph-derived-queries.ts +6 -0
  588. package/src/themes/manta-dark.css +4 -0
  589. package/src/worker/index.ts +175 -0
  590. package/src/worker/policy.ts +62 -0
  591. package/src/worker/proxy.ts +101 -0
  592. package/src/worker/session.ts +111 -0
@@ -0,0 +1,331 @@
1
+ import { humanCount } from "@manta-eu/lib/humanize";
2
+ import { isPresent } from "@manta-eu/lib/present";
3
+ import { format, isValid, parse } from "date-fns";
4
+ import { useEffect, useId, useMemo, useState } from "react";
5
+ import { match } from "ts-pattern";
6
+ import {
7
+ buildPlanLimitChanges,
8
+ buildPlanLimitsModel,
9
+ type PlanLimitChange,
10
+ type PlanLimitLock,
11
+ type PlanLimitRow,
12
+ type PlanLimitRule,
13
+ type PlanLimitRuleModel,
14
+ planLimitControlLabel,
15
+ planLimitsCanSave,
16
+ planLimitSentences,
17
+ sliderRangeFor,
18
+ } from "./plan-limits-model";
19
+ import { messageOf, type PlanLimitsSaveResult } from "./plan-limits-save";
20
+ import { Banner } from "#components/banner/index";
21
+ import { Button } from "#components/button/index";
22
+ import { Input, InputDate } from "#components/input/index";
23
+ import { Loader } from "#components/loader/index";
24
+ import {
25
+ Dialog,
26
+ DialogBody,
27
+ DialogClose,
28
+ DialogContent,
29
+ DialogDescription,
30
+ DialogFooter,
31
+ DialogHeader,
32
+ DialogTitle,
33
+ } from "#components/modal/index";
34
+ import { Slider } from "#components/slider/index";
35
+ import { RuleNarrativeSegments } from "#ldo-ui";
36
+ import { ruleValueInputDescriptors } from "#routes/rules/components/rule-value-input";
37
+ import { getRuleDisplayName } from "#routes/rules/components/rules.utils";
38
+
39
+ export type PlanLimitsDialogProps = {
40
+ open: boolean;
41
+ onOpenChange: (open: boolean) => void;
42
+ rules: readonly PlanLimitRule[];
43
+ onSave: (changes: readonly PlanLimitChange[]) => Promise<PlanLimitsSaveResult>;
44
+ isLoading?: boolean;
45
+ isSaving?: boolean;
46
+ error?: string | null;
47
+ /** Rules the dialog does not show, when the plan has more than the page read. */
48
+ omittedRules?: number;
49
+ };
50
+
51
+ export const planLimitsDialogTitle = "This plan's limits";
52
+ export const planLimitsDialogDescription =
53
+ "The numbers and dates this plan's rules use. Saving updates the recommended changes now; Manta acts on them at the plan's next run.";
54
+ export const planLimitsEmptyText = "This plan's rules carry no value to edit.";
55
+ export const planLimitsNothingEditableText = "None of these rules can be edited here. Each one says why.";
56
+ export const planLimitLockNotes: Record<PlanLimitLock, string> = {
57
+ manta: "Manta maintains this rule, so it can't be edited here.",
58
+ staged: "This rule has a change staged on its rule page. Commit or clear it there first.",
59
+ };
60
+
61
+ const numberFormat = new Intl.NumberFormat("en-US", { maximumFractionDigits: 4 });
62
+ /** A rule's date literal is a plain ISO day. */
63
+ const ruleDateFormat = "yyyy-MM-dd";
64
+
65
+ function dateOf(value: string): Date | undefined {
66
+ const date = parse(value, ruleDateFormat, new Date());
67
+ return isValid(date) ? date : undefined;
68
+ }
69
+
70
+ export function PlanLimitsDialog(props: PlanLimitsDialogProps) {
71
+ const { open, onOpenChange, rules, onSave, isLoading = false, isSaving = false, error, omittedRules = 0 } = props;
72
+ const [values, setValues] = useState<Record<string, string>>({});
73
+ const [saveError, setSaveError] = useState<string>();
74
+ const [submitting, setSubmitting] = useState(false);
75
+
76
+ const model = useMemo(() => buildPlanLimitsModel(rules), [rules]);
77
+ const build = useMemo(() => buildPlanLimitChanges(model, values), [model, values]);
78
+
79
+ useEffect(() => {
80
+ setValues({});
81
+ setSaveError(undefined);
82
+ }, [open]);
83
+
84
+ const hasEditableRows = isPresent(model.editableRows);
85
+ const notShown = omittedRules + model.unparsable.length;
86
+ const busy = isSaving || submitting;
87
+ const canSave = planLimitsCanSave(build) && !busy;
88
+ const changedRuleIris = new Set(build.changes.map((change) => change.ruleIri));
89
+ const changedValues = model.editableRows.filter(
90
+ (row) => changedRuleIris.has(row.ruleIri) && values[row.id] !== undefined && values[row.id] !== row.edit.value,
91
+ ).length;
92
+
93
+ async function handleSave() {
94
+ if (!canSave) return;
95
+ setSaveError(undefined);
96
+ setSubmitting(true);
97
+ try {
98
+ const result = await onSave(build.changes);
99
+ if (result.ok) onOpenChange(false);
100
+ else setSaveError(result.error);
101
+ } catch (err: unknown) {
102
+ setSaveError(messageOf(err, "The limits could not be saved"));
103
+ } finally {
104
+ setSubmitting(false);
105
+ }
106
+ }
107
+
108
+ return (
109
+ <Dialog open={open} onOpenChange={onOpenChange}>
110
+ <DialogContent size="lg" fullScreenOnMobile>
111
+ <DialogHeader>
112
+ <DialogTitle text={planLimitsDialogTitle} />
113
+ <DialogDescription>{planLimitsDialogDescription}</DialogDescription>
114
+ </DialogHeader>
115
+ <DialogBody className="flex flex-col gap-7">
116
+ {isLoading && (
117
+ <div className="flex items-center gap-2 typography-small text-muted-foreground">
118
+ <Loader className="size-4" />
119
+ Loading the plan's rules...
120
+ </div>
121
+ )}
122
+ {!isLoading && isPresent(error) && <Banner label={error} />}
123
+ {!isLoading && !isPresent(error) && !isPresent(model.rows) && (
124
+ <p className="typography-small text-muted-foreground">{planLimitsEmptyText}</p>
125
+ )}
126
+ {!isLoading && isPresent(model.rows) && !hasEditableRows && (
127
+ <p className="typography-small text-muted-foreground">{planLimitsNothingEditableText}</p>
128
+ )}
129
+ {model.rules.map((rule) => (
130
+ <PlanLimitRuleView
131
+ key={rule.ruleIri}
132
+ rule={rule}
133
+ values={values}
134
+ fieldErrors={build.fieldErrors}
135
+ ruleError={build.ruleErrors[rule.ruleIri]}
136
+ disabled={busy}
137
+ onChange={(row, value) => setValues((current) => ({ ...current, [row.id]: value }))}
138
+ />
139
+ ))}
140
+ {(hasEditableRows || notShown > 0) && (
141
+ <dl className="grid grid-cols-[1fr_auto] gap-x-6 gap-y-2 rounded-lg-v4 bg-muted/40 px-4 py-3 typography-small">
142
+ {hasEditableRows && (
143
+ <>
144
+ <dt className="text-muted-foreground">Values changed</dt>
145
+ <dd className="text-right text-default-foreground">{changedValues}</dd>
146
+ <dt className="text-muted-foreground">Rules updated on save</dt>
147
+ <dd className="text-right text-default-foreground">{build.changes.length}</dd>
148
+ <dt className="text-muted-foreground">Recommended changes</dt>
149
+ <dd className="text-right text-default-foreground">update on save</dd>
150
+ <dt className="text-muted-foreground">Manta acts on them</dt>
151
+ <dd className="text-right text-default-foreground">at the plan's next run</dd>
152
+ </>
153
+ )}
154
+ {omittedRules > 0 && (
155
+ <>
156
+ <dt className="text-muted-foreground">Not shown, on the plan's rule pages</dt>
157
+ <dd className="text-right text-default-foreground">{humanCount(omittedRules, "rule")}</dd>
158
+ </>
159
+ )}
160
+ {isPresent(model.unparsable) && (
161
+ <>
162
+ <dt className="text-muted-foreground">Not shown, could not be read</dt>
163
+ <dd className="text-right text-default-foreground">{humanCount(model.unparsable.length, "rule")}</dd>
164
+ </>
165
+ )}
166
+ </dl>
167
+ )}
168
+ {isPresent(saveError) && <Banner label={saveError} />}
169
+ </DialogBody>
170
+ <DialogFooter>
171
+ <DialogClose asChild>
172
+ <Button variant="tertiary" label="Cancel" disabled={busy} />
173
+ </DialogClose>
174
+ <Button label={busy ? "Saving..." : "Save limits"} disabled={!canSave} onClick={() => void handleSave()} />
175
+ </DialogFooter>
176
+ </DialogContent>
177
+ </Dialog>
178
+ );
179
+ }
180
+
181
+ type PlanLimitRuleViewProps = {
182
+ rule: PlanLimitRuleModel;
183
+ values: Readonly<Record<string, string>>;
184
+ fieldErrors: Readonly<Record<string, string>>;
185
+ ruleError: string | undefined;
186
+ disabled: boolean;
187
+ onChange: (row: PlanLimitRow, value: string) => void;
188
+ };
189
+
190
+ /** One rule's limits: each sentence once with its values live, a control per value under it, the rule named once. */
191
+ function PlanLimitRuleView(props: PlanLimitRuleViewProps) {
192
+ const { rule, values, fieldErrors, ruleError, disabled, onChange } = props;
193
+ const editable = !rule.lock;
194
+ const ruleName = getRuleDisplayName(rule.ruleIri);
195
+ const valueOf = (row: PlanLimitRow) => values[row.id] ?? row.edit.value;
196
+ const figureOf = (row: PlanLimitRow) => {
197
+ const value = valueOf(row);
198
+ const numeric = Number(value);
199
+ return row.edit.kind === "number" && Number.isFinite(numeric) ? numberFormat.format(numeric) : value;
200
+ };
201
+
202
+ return (
203
+ <section aria-label={ruleName} className="flex flex-col gap-3">
204
+ {planLimitSentences(rule.rows).map((sentence) => {
205
+ const live = sentence.segments.map((segment) => {
206
+ const row = sentence.rows.find(
207
+ (candidate) => segment.kind === "value" && segment.edit?.id === candidate.edit.id,
208
+ );
209
+ return row ? { ...segment, text: figureOf(row) } : segment;
210
+ });
211
+ return (
212
+ <div key={sentence.rows[0]?.id} className="flex flex-col gap-3">
213
+ <p className="typography-small-medium leading-6 text-default-foreground">
214
+ <RuleNarrativeSegments variant="narrative" segments={live} />
215
+ </p>
216
+ {editable &&
217
+ sentence.rows.map((row) => (
218
+ <PlanLimitControl
219
+ key={row.id}
220
+ row={row}
221
+ label={planLimitControlLabel(row)}
222
+ value={valueOf(row)}
223
+ fieldError={fieldErrors[row.id]}
224
+ disabled={disabled}
225
+ onChange={(value) => onChange(row, value)}
226
+ />
227
+ ))}
228
+ </div>
229
+ );
230
+ })}
231
+ <p className="typography-caption text-muted-foreground">
232
+ From the rule {ruleName}.{rule.lock && ` ${planLimitLockNotes[rule.lock]}`}
233
+ </p>
234
+ {isPresent(ruleError) && <p className="typography-caption text-error-foreground">{ruleError}</p>}
235
+ </section>
236
+ );
237
+ }
238
+
239
+ type PlanLimitControlProps = {
240
+ row: PlanLimitRow;
241
+ label: string;
242
+ value: string;
243
+ fieldError: string | undefined;
244
+ disabled: boolean;
245
+ onChange: (value: string) => void;
246
+ };
247
+
248
+ /** The control for one value: a slider with a field for a number, a date field for a date. */
249
+ function PlanLimitControl(props: PlanLimitControlProps) {
250
+ const { row, label, value, fieldError, disabled, onChange } = props;
251
+ const inputId = useId();
252
+ const descriptor = ruleValueInputDescriptors[row.edit.kind];
253
+ const [typed, setTyped] = useState(row.edit.value);
254
+ const range = sliderRangeFor(row.edit.value, typed);
255
+ const numeric = Number(value);
256
+
257
+ const fallbackInput = (
258
+ <Input
259
+ id={inputId}
260
+ containerClassName="w-56"
261
+ className="w-full"
262
+ type={descriptor.type}
263
+ step={descriptor.step}
264
+ inputMode={descriptor.inputMode}
265
+ value={descriptor.toInputValue(value)}
266
+ error={fieldError}
267
+ helperText={descriptor.helperText}
268
+ disabled={disabled}
269
+ onChange={(event) => onChange(descriptor.fromInputValue(event.target.value))}
270
+ />
271
+ );
272
+
273
+ return (
274
+ <div className="grid items-center gap-3 md:grid-cols-[7rem_minmax(0,1fr)]">
275
+ <label htmlFor={inputId} className="typography-small text-muted-foreground">
276
+ {label}
277
+ </label>
278
+ {match(row.edit.kind)
279
+ .with("number", () =>
280
+ range ? (
281
+ <div className="flex items-center gap-4">
282
+ <Slider
283
+ className="min-w-0 flex-1"
284
+ min={range.min}
285
+ max={range.max}
286
+ step={range.step}
287
+ value={[Number.isFinite(numeric) ? numeric : range.min]}
288
+ disabled={disabled}
289
+ onValueChange={([next]) => onChange(String(next))}
290
+ thumbProps={[{ "aria-label": label }]}
291
+ />
292
+ <Input
293
+ id={inputId}
294
+ containerClassName="w-28 shrink-0"
295
+ className="w-full"
296
+ type="number"
297
+ step="any"
298
+ inputMode="decimal"
299
+ value={value}
300
+ error={fieldError}
301
+ disabled={disabled}
302
+ onChange={(event) => {
303
+ setTyped(event.target.value);
304
+ onChange(event.target.value);
305
+ }}
306
+ />
307
+ </div>
308
+ ) : (
309
+ fallbackInput
310
+ ),
311
+ )
312
+ .with("date", () => (
313
+ <div className="flex flex-col gap-1">
314
+ <InputDate
315
+ id={inputId}
316
+ className="w-44"
317
+ aria-invalid={fieldError ? true : undefined}
318
+ selected={dateOf(value)}
319
+ allowPast
320
+ closeOnSelect
321
+ disabled={disabled}
322
+ onChange={(date) => onChange(format(date, ruleDateFormat))}
323
+ />
324
+ {isPresent(fieldError) && <p className="typography-caption text-error-foreground">{fieldError}</p>}
325
+ </div>
326
+ ))
327
+ .with("dateTime", () => fallbackInput)
328
+ .exhaustive()}
329
+ </div>
330
+ );
331
+ }
@@ -0,0 +1,3 @@
1
+ export type { PlanLimitChange, PlanLimitLock, PlanLimitRule } from "./plan-limits-model";
2
+ export type { PlanLimitsSaveResult, PlanLimitsSaveStep } from "./plan-limits-save";
3
+ export { PlanLimitsDialog, type PlanLimitsDialogProps } from "./PlanLimitsDialog";
@@ -0,0 +1,71 @@
1
+ import {
2
+ type GQLActionPlanRulesQuery,
3
+ type GQLClearStagedRulesMutation,
4
+ type GQLClearStagedRulesMutationVariables,
5
+ type GQLCommitStagedRulesMutation,
6
+ type GQLCommitStagedRulesMutationVariables,
7
+ GQLRuleOperation,
8
+ GQLRuleOwner,
9
+ type GQLStageRuleOperationMutation,
10
+ type GQLStageRuleOperationMutationVariables,
11
+ type GQLValidateStagedRulesMutation,
12
+ type GQLValidateStagedRulesMutationVariables,
13
+ } from "@manta-eu/client";
14
+ import { extractPlanName } from "@manta-eu/client/shared/agent-mode";
15
+ import type { PlanLimitRule } from "./plan-limits-model";
16
+ import type { PlanLimitsSaveClient } from "./plan-limits-save";
17
+
18
+ export type PlanRuleRow = GQLActionPlanRulesQuery["rules"]["rules"][number];
19
+
20
+ /** A rule with no owner is not Manta's, so it can be edited like a user's. */
21
+ export function planLimitRuleOf(rule: PlanRuleRow): PlanLimitRule {
22
+ return {
23
+ ruleIri: rule.ruleIri,
24
+ ruleText: rule.committedRule ?? rule.stagedRule ?? "",
25
+ ownedByManta: rule.ownedBy?.type === GQLRuleOwner.Manta,
26
+ hasStagedChange: rule.isStaged,
27
+ };
28
+ }
29
+
30
+ export type PlanLimitsMutations = {
31
+ stage: (variables: GQLStageRuleOperationMutationVariables) => Promise<GQLStageRuleOperationMutation>;
32
+ validate: (variables: GQLValidateStagedRulesMutationVariables) => Promise<GQLValidateStagedRulesMutation>;
33
+ commit: (variables: GQLCommitStagedRulesMutationVariables) => Promise<GQLCommitStagedRulesMutation>;
34
+ clear: (variables: GQLClearStagedRulesMutationVariables) => Promise<GQLClearStagedRulesMutation>;
35
+ };
36
+
37
+ /** Reads the rule mutations' answers into what the save chain needs. */
38
+ export function planLimitsSaveClient(
39
+ mutations: PlanLimitsMutations,
40
+ planGraphIri: string | undefined,
41
+ ): PlanLimitsSaveClient {
42
+ return {
43
+ stage: async (change) => {
44
+ const response = await mutations.stage({
45
+ input: {
46
+ humanIntent: `Edit the limits of ${planGraphIri ? extractPlanName(planGraphIri) : "the plan"}`,
47
+ operation: GQLRuleOperation.Change,
48
+ ruleIri: change.ruleIri,
49
+ newRule: change.ruleText,
50
+ },
51
+ });
52
+ return { success: response.stageRuleOperation.success, error: response.stageRuleOperation.error };
53
+ },
54
+ validate: async (ruleIris) => {
55
+ const response = await mutations.validate({ ruleIris });
56
+ const validation = response.validateStagedRules;
57
+ const errors = [
58
+ ...(validation.syntaxErrors ?? []),
59
+ ...(validation.isStratifiable ? [] : ["The changed rules cannot be stratified."]),
60
+ ...(validation.error ? [validation.error] : []),
61
+ ];
62
+ return { isValid: validation.isValid && validation.isStratifiable, errors };
63
+ },
64
+ commit: async (ruleIris) => {
65
+ const response = await mutations.commit({ dryRun: false, ruleIris });
66
+ const commit = response.commitStagedRules;
67
+ return { success: commit.success, rulesUpdated: commit.rulesUpdated, error: commit.error };
68
+ },
69
+ clear: (ruleIris) => mutations.clear({ ruleIris }),
70
+ };
71
+ }
@@ -0,0 +1,180 @@
1
+ import { isPresent } from "@manta-eu/lib/present";
2
+ import {
3
+ buildRuleSetupModel,
4
+ type EditableRuleValue,
5
+ type NarrativeSegment,
6
+ parseDatalogRuleCached,
7
+ type RuleSetupModel,
8
+ } from "#ldo-ui";
9
+ import { buildUpdatedRuleText } from "#routes/rules/components/rule-value-edit";
10
+
11
+ export type PlanLimitRule = {
12
+ ruleIri: string;
13
+ ruleText: string;
14
+ /** A rule Manta maintains; editing it would make it the user's and stop Manta's updates, so it stays read-only. */
15
+ ownedByManta: boolean;
16
+ /** A rule with an uncommitted change staged elsewhere; saving here would commit that change too. */
17
+ hasStagedChange: boolean;
18
+ };
19
+
20
+ export type PlanLimitLock = "manta" | "staged";
21
+
22
+ export function planLimitLock(rule: PlanLimitRule): PlanLimitLock | null {
23
+ if (rule.hasStagedChange) return "staged";
24
+ if (rule.ownedByManta) return "manta";
25
+ return null;
26
+ }
27
+
28
+ export type PlanLimitRow = {
29
+ /** Unique across the plan: a rule's edit ids repeat between rules. */
30
+ id: string;
31
+ ruleIri: string;
32
+ edit: EditableRuleValue;
33
+ segments: readonly NarrativeSegment[];
34
+ };
35
+
36
+ export type PlanLimitRuleModel = PlanLimitRule & {
37
+ lock: PlanLimitLock | null;
38
+ model: RuleSetupModel;
39
+ rows: PlanLimitRow[];
40
+ };
41
+
42
+ export type PlanLimitsModel = {
43
+ rules: PlanLimitRuleModel[];
44
+ rows: PlanLimitRow[];
45
+ editableRows: PlanLimitRow[];
46
+ unparsable: { ruleIri: string; error: string }[];
47
+ };
48
+
49
+ export type PlanLimitChange = { ruleIri: string; ruleText: string };
50
+
51
+ export type PlanLimitsBuild = {
52
+ changed: boolean;
53
+ changes: PlanLimitChange[];
54
+ fieldErrors: Readonly<Record<string, string>>;
55
+ ruleErrors: Readonly<Record<string, string>>;
56
+ };
57
+
58
+ export function planLimitRowId(ruleIri: string, editId: string): string {
59
+ return `${ruleIri}#${editId}`;
60
+ }
61
+
62
+ export function buildPlanLimitsModel(rules: readonly PlanLimitRule[]): PlanLimitsModel {
63
+ const unparsable: PlanLimitsModel["unparsable"] = [];
64
+ const ruleModels = rules.flatMap((rule): PlanLimitRuleModel[] => {
65
+ if (!isPresent(rule.ruleText)) return [];
66
+ const { ast, error } = parseDatalogRuleCached(rule.ruleText);
67
+ if (!ast) {
68
+ unparsable.push({ ruleIri: rule.ruleIri, error: error ?? "Could not parse rule" });
69
+ return [];
70
+ }
71
+ const model = buildRuleSetupModel(ast);
72
+ const rows = model.editableValues.map(({ edit, segments }) => ({
73
+ id: planLimitRowId(rule.ruleIri, edit.id),
74
+ ruleIri: rule.ruleIri,
75
+ edit,
76
+ segments,
77
+ }));
78
+ return isPresent(rows) ? [{ ...rule, lock: planLimitLock(rule), model, rows }] : [];
79
+ });
80
+ return {
81
+ rules: ruleModels,
82
+ rows: ruleModels.flatMap((rule) => rule.rows),
83
+ editableRows: ruleModels.flatMap((rule) => (rule.lock ? [] : rule.rows)),
84
+ unparsable,
85
+ };
86
+ }
87
+
88
+ export function buildPlanLimitChanges(
89
+ model: PlanLimitsModel,
90
+ values: Readonly<Record<string, string>>,
91
+ ): PlanLimitsBuild {
92
+ const changes: PlanLimitChange[] = [];
93
+ const fieldErrors: Record<string, string> = {};
94
+ const ruleErrors: Record<string, string> = {};
95
+
96
+ for (const rule of model.rules) {
97
+ if (rule.lock) continue;
98
+ const ruleValues: Record<string, string> = {};
99
+ for (const row of rule.rows) {
100
+ const value = values[row.id];
101
+ if (value !== undefined) ruleValues[row.edit.id] = value;
102
+ }
103
+ const result = buildUpdatedRuleText(rule.model, ruleValues);
104
+ for (const [editId, message] of Object.entries(result.fieldErrors)) {
105
+ fieldErrors[planLimitRowId(rule.ruleIri, editId)] = message;
106
+ }
107
+ if (result.error) ruleErrors[rule.ruleIri] = result.error;
108
+ if (result.changed && !result.error && !isPresent(Object.keys(result.fieldErrors))) {
109
+ changes.push({ ruleIri: rule.ruleIri, ruleText: result.ruleText });
110
+ }
111
+ }
112
+
113
+ return { changed: isPresent(changes), changes, fieldErrors, ruleErrors };
114
+ }
115
+
116
+ /** A build can be saved only when something changed and no value and no rule carries an error. */
117
+ export function planLimitsCanSave(build: PlanLimitsBuild): boolean {
118
+ return build.changed && !isPresent(Object.keys(build.fieldErrors)) && !isPresent(Object.keys(build.ruleErrors));
119
+ }
120
+
121
+ export type SliderRange = { min: number; max: number; step: number };
122
+
123
+ /** Rounds up to 1, 2 or 5 times a power of ten, so a slider ends on a round figure. */
124
+ export function niceCeiling(value: number): number {
125
+ if (value <= 0) return 0;
126
+ const magnitude = 10 ** Math.floor(Math.log10(value));
127
+ const leading = value / magnitude;
128
+ const nice = leading <= 1 ? 1 : leading <= 2 ? 2 : leading <= 5 ? 5 : 10;
129
+ return nice * magnitude;
130
+ }
131
+
132
+ /** A slider's bounds around a rule's number: 0 to a round figure past twice the rule's or the typed value. */
133
+ export function sliderRangeFor(ruleValue: string, currentValue: string = ruleValue): SliderRange | null {
134
+ const original = Number(ruleValue);
135
+ const current = Number(currentValue);
136
+ if (!Number.isFinite(original)) return null;
137
+ const decimals = Math.min(4, (ruleValue.split(".")[1] ?? "").length);
138
+ const step = decimals === 0 ? 1 : 10 ** -decimals;
139
+ const base = original === 0 ? 10 : niceCeiling(Math.abs(original) * 2);
140
+ const typed = Number.isFinite(current) ? Math.abs(current) : 0;
141
+ const max = typed > base ? niceCeiling(typed * 2) : base;
142
+ const min = original < 0 || current < 0 ? -max : 0;
143
+ return { min, max, step };
144
+ }
145
+
146
+ export type PlanLimitSentence = {
147
+ /** The narrative row's segments, shared by every value it holds. */
148
+ segments: readonly NarrativeSegment[];
149
+ rows: PlanLimitRow[];
150
+ };
151
+
152
+ /** A rule's values grouped by sentence: `buildRuleSetupModel` gives every value of a row one `editContext` array. */
153
+ export function planLimitSentences(rows: readonly PlanLimitRow[]): PlanLimitSentence[] {
154
+ const sentences: PlanLimitSentence[] = [];
155
+ for (const row of rows) {
156
+ const sentence = sentences.find((candidate) => candidate.segments === row.segments);
157
+ if (sentence) sentence.rows.push(row);
158
+ else sentences.push({ segments: row.segments, rows: [row] });
159
+ }
160
+ return sentences;
161
+ }
162
+
163
+ /** The words right before a value in its sentence ("at least", "at most"), to name its control. */
164
+ export function planLimitControlLabel(row: PlanLimitRow): string {
165
+ const index = row.segments.findIndex((segment) => segment.kind === "value" && segment.edit?.id === row.edit.id);
166
+ const words: string[] = [];
167
+ for (let cursor = index - 1; cursor >= 0; cursor--) {
168
+ const segment = row.segments[cursor];
169
+ if (segment?.kind !== "text") break;
170
+ words.unshift(segment.text);
171
+ }
172
+ const label = words
173
+ .join("")
174
+ .trim()
175
+ .replace(/^(and|or|,)\s+/i, "")
176
+ .replace(/^is\s+/i, "")
177
+ .replace(/[,:]$/, "")
178
+ .trim();
179
+ return label || "Value";
180
+ }
@@ -0,0 +1,68 @@
1
+ import { parseError } from "@manta-eu/client/shared/error-utils";
2
+ import { humanList } from "@manta-eu/lib/humanize";
3
+ import { isPresent } from "@manta-eu/lib/present";
4
+ import type { PlanLimitChange } from "./plan-limits-model";
5
+
6
+ export type PlanLimitsSaveStep = "stage" | "validate" | "commit";
7
+
8
+ export type PlanLimitsSaveClient = {
9
+ stage: (change: PlanLimitChange) => Promise<{ success: boolean; error?: string | null }>;
10
+ validate: (ruleIris: string[]) => Promise<{ isValid: boolean; errors: string[] }>;
11
+ commit: (ruleIris: string[]) => Promise<{ success: boolean; rulesUpdated: number; error?: string | null }>;
12
+ clear: (ruleIris: string[]) => Promise<unknown>;
13
+ };
14
+
15
+ export type PlanLimitsSaveResult =
16
+ | { ok: true; rulesUpdated: number }
17
+ | { ok: false; step: PlanLimitsSaveStep; error: string };
18
+
19
+ /** Stages every change, validates and commits them together; a failure clears what was staged, or says it could not. */
20
+ export async function savePlanLimits(
21
+ client: PlanLimitsSaveClient,
22
+ changes: readonly PlanLimitChange[],
23
+ ): Promise<PlanLimitsSaveResult> {
24
+ const ruleIris = changes.map((change) => change.ruleIri);
25
+ const staged: string[] = [];
26
+
27
+ const rollback = async (step: PlanLimitsSaveStep, error: string): Promise<PlanLimitsSaveResult> => {
28
+ if (!isPresent(staged)) return { ok: false, step, error };
29
+ const cleared = await client.clear(staged).then(
30
+ () => null,
31
+ (err: unknown) => messageOf(err),
32
+ );
33
+ if (cleared === null) return { ok: false, step, error };
34
+ return {
35
+ ok: false,
36
+ step,
37
+ error: `${error.replace(/\.$/, "")}. The staged changes could not be cleared (${cleared}); clear them on the rule pages.`,
38
+ };
39
+ };
40
+
41
+ for (const change of changes) {
42
+ const result = await client.stage(change).catch((err: unknown) => ({ success: false, error: messageOf(err) }));
43
+ if (!result.success) return rollback("stage", result.error ?? `Could not stage ${change.ruleIri}`);
44
+ staged.push(change.ruleIri);
45
+ }
46
+
47
+ const validation = await client
48
+ .validate(ruleIris)
49
+ .catch((err: unknown) => ({ isValid: false, errors: [messageOf(err)] }));
50
+ if (!validation.isValid)
51
+ return rollback(
52
+ "validate",
53
+ isPresent(validation.errors) ? humanList(validation.errors) : "The rules did not validate",
54
+ );
55
+
56
+ const commit = await client
57
+ .commit(ruleIris)
58
+ .catch((err: unknown) => ({ success: false, rulesUpdated: 0, error: messageOf(err) }));
59
+ if (!commit.success) return rollback("commit", commit.error ?? "Could not commit the rules");
60
+
61
+ return { ok: true, rulesUpdated: commit.rulesUpdated };
62
+ }
63
+
64
+ /** The text to show for a thrown error: its description when it has one, else its message. */
65
+ export function messageOf(err: unknown, fallback = "Something went wrong"): string {
66
+ const info = parseError(err, fallback);
67
+ return info.description ?? info.message;
68
+ }