@aglyn/plugins-crm 1.0.0-beta.221 → 1.0.0-beta.223

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 (541) hide show
  1. package/README.md +2 -1
  2. package/package.json +13 -13
  3. package/src/lib/components/activity-list.js +12 -5
  4. package/src/lib/components/activity-list.js.map +1 -1
  5. package/src/lib/components/companies-bulk-bar.d.ts +1 -4
  6. package/src/lib/components/companies-bulk-bar.js +7 -20
  7. package/src/lib/components/companies-bulk-bar.js.map +1 -1
  8. package/src/lib/components/companies-section.d.ts +3 -3
  9. package/src/lib/components/companies-section.js +149 -46
  10. package/src/lib/components/companies-section.js.map +1 -1
  11. package/src/lib/components/company-edit-drawer.js +281 -20
  12. package/src/lib/components/company-edit-drawer.js.map +1 -1
  13. package/src/lib/components/company-properties-card.js +99 -8
  14. package/src/lib/components/company-properties-card.js.map +1 -1
  15. package/src/lib/components/contact-detail-page.js +3 -1
  16. package/src/lib/components/contact-detail-page.js.map +1 -1
  17. package/src/lib/components/contact-merge-dialog.js +33 -10
  18. package/src/lib/components/contact-merge-dialog.js.map +1 -1
  19. package/src/lib/components/contact-properties-card.d.ts +0 -69
  20. package/src/lib/components/contact-properties-card.js +350 -60
  21. package/src/lib/components/contact-properties-card.js.map +1 -1
  22. package/src/lib/components/contact-reports-to-field.d.ts +46 -0
  23. package/src/lib/components/contact-reports-to-field.js +67 -0
  24. package/src/lib/components/contact-reports-to-field.js.map +1 -0
  25. package/src/lib/components/contacts-bulk-bar.d.ts +1 -8
  26. package/src/lib/components/contacts-bulk-bar.js +7 -19
  27. package/src/lib/components/contacts-bulk-bar.js.map +1 -1
  28. package/src/lib/components/contacts-section.js +46 -33
  29. package/src/lib/components/contacts-section.js.map +1 -1
  30. package/src/lib/components/crm-call-actions.d.ts +10 -0
  31. package/src/lib/components/crm-call-actions.js +26 -9
  32. package/src/lib/components/crm-call-actions.js.map +1 -1
  33. package/src/lib/components/crm-next-activity-column.js +1 -1
  34. package/src/lib/components/crm-next-activity-column.js.map +1 -1
  35. package/src/lib/components/crm-record-picker.d.ts +15 -0
  36. package/src/lib/components/crm-record-picker.js +16 -10
  37. package/src/lib/components/crm-record-picker.js.map +1 -1
  38. package/src/lib/components/crm-transfer-buttons.d.ts +54 -0
  39. package/src/lib/components/crm-transfer-buttons.js +167 -0
  40. package/src/lib/components/crm-transfer-buttons.js.map +1 -0
  41. package/src/lib/components/deal-contact-roles-card.d.ts +46 -0
  42. package/src/lib/components/deal-contact-roles-card.js +368 -0
  43. package/src/lib/components/deal-contact-roles-card.js.map +1 -0
  44. package/src/lib/components/deal-detail-page.d.ts +3 -2
  45. package/src/lib/components/deal-detail-page.js +25 -6
  46. package/src/lib/components/deal-detail-page.js.map +1 -1
  47. package/src/lib/components/deal-edit-drawer.d.ts +10 -0
  48. package/src/lib/components/deal-edit-drawer.js +219 -10
  49. package/src/lib/components/deal-edit-drawer.js.map +1 -1
  50. package/src/lib/components/deal-properties-card.d.ts +7 -0
  51. package/src/lib/components/deal-properties-card.js +34 -3
  52. package/src/lib/components/deal-properties-card.js.map +1 -1
  53. package/src/lib/components/deal-stage-card.d.ts +4 -0
  54. package/src/lib/components/deal-stage-card.js +10 -2
  55. package/src/lib/components/deal-stage-card.js.map +1 -1
  56. package/src/lib/components/deals-bulk-bar.d.ts +0 -3
  57. package/src/lib/components/deals-bulk-bar.js +7 -20
  58. package/src/lib/components/deals-bulk-bar.js.map +1 -1
  59. package/src/lib/components/deals-section.d.ts +3 -3
  60. package/src/lib/components/deals-section.js +123 -63
  61. package/src/lib/components/deals-section.js.map +1 -1
  62. package/src/lib/components/fields-section.js +31 -17
  63. package/src/lib/components/fields-section.js.map +1 -1
  64. package/src/lib/components/lead-convert-dialog.d.ts +4 -0
  65. package/src/lib/components/lead-convert-dialog.js +23 -1
  66. package/src/lib/components/lead-convert-dialog.js.map +1 -1
  67. package/src/lib/components/lead-detail-page.js +8 -2
  68. package/src/lib/components/lead-detail-page.js.map +1 -1
  69. package/src/lib/components/lead-profile-fields.d.ts +71 -0
  70. package/src/lib/components/lead-profile-fields.js +386 -0
  71. package/src/lib/components/lead-profile-fields.js.map +1 -0
  72. package/src/lib/components/lead-properties-card.d.ts +2 -1
  73. package/src/lib/components/lead-properties-card.js +85 -176
  74. package/src/lib/components/lead-properties-card.js.map +1 -1
  75. package/src/lib/components/lead-source-select.d.ts +4 -23
  76. package/src/lib/components/lead-source-select.js +9 -73
  77. package/src/lib/components/lead-source-select.js.map +1 -1
  78. package/src/lib/components/lead-status-chip.d.ts +9 -3
  79. package/src/lib/components/lead-status-chip.js +8 -4
  80. package/src/lib/components/lead-status-chip.js.map +1 -1
  81. package/src/lib/components/lead-status-options.d.ts +20 -0
  82. package/src/lib/components/lead-status-options.js +51 -0
  83. package/src/lib/components/lead-status-options.js.map +1 -0
  84. package/src/lib/components/lead-unqualify-dialog.d.ts +5 -0
  85. package/src/lib/components/lead-unqualify-dialog.js +50 -18
  86. package/src/lib/components/lead-unqualify-dialog.js.map +1 -1
  87. package/src/lib/components/leads-bulk-bar.d.ts +0 -3
  88. package/src/lib/components/leads-bulk-bar.js +29 -29
  89. package/src/lib/components/leads-bulk-bar.js.map +1 -1
  90. package/src/lib/components/leads-section.js +120 -68
  91. package/src/lib/components/leads-section.js.map +1 -1
  92. package/src/lib/components/linked-deals-card.d.ts +4 -0
  93. package/src/lib/components/linked-deals-card.js +47 -3
  94. package/src/lib/components/linked-deals-card.js.map +1 -1
  95. package/src/lib/components/log-activity-dialog.js +43 -3
  96. package/src/lib/components/log-activity-dialog.js.map +1 -1
  97. package/src/lib/components/new-contact-drawer.d.ts +8 -0
  98. package/src/lib/components/new-contact-drawer.js +108 -6
  99. package/src/lib/components/new-contact-drawer.js.map +1 -1
  100. package/src/lib/components/new-lead-drawer.d.ts +9 -2
  101. package/src/lib/components/new-lead-drawer.js +88 -121
  102. package/src/lib/components/new-lead-drawer.js.map +1 -1
  103. package/src/lib/components/picklist-select.d.ts +36 -0
  104. package/src/lib/components/picklist-select.js +114 -0
  105. package/src/lib/components/picklist-select.js.map +1 -0
  106. package/src/lib/components/picklist-values-card.d.ts +34 -0
  107. package/src/lib/components/{lead-source-values-card.js → picklist-values-card.js} +241 -58
  108. package/src/lib/components/picklist-values-card.js.map +1 -0
  109. package/src/lib/components/pipeline-stages-dialog.d.ts +7 -0
  110. package/src/lib/components/pipeline-stages-dialog.js +26 -4
  111. package/src/lib/components/pipeline-stages-dialog.js.map +1 -1
  112. package/src/lib/components/pipelines-dialog.js +15 -6
  113. package/src/lib/components/pipelines-dialog.js.map +1 -1
  114. package/src/lib/components/recent-activity-feed.js +20 -5
  115. package/src/lib/components/recent-activity-feed.js.map +1 -1
  116. package/src/lib/components/recipes-card.js +4 -2
  117. package/src/lib/components/recipes-card.js.map +1 -1
  118. package/src/lib/components/record-tasks-card.js +15 -8
  119. package/src/lib/components/record-tasks-card.js.map +1 -1
  120. package/src/lib/components/reports/forecast-card.d.ts +6 -0
  121. package/src/lib/components/reports/forecast-card.js +101 -3
  122. package/src/lib/components/reports/forecast-card.js.map +1 -1
  123. package/src/lib/components/reports/lead-funnel-card.d.ts +12 -0
  124. package/src/lib/components/reports/lead-funnel-card.js +9 -5
  125. package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
  126. package/src/lib/components/reports/lead-source-card.d.ts +23 -0
  127. package/src/lib/components/reports/lead-source-card.js +318 -0
  128. package/src/lib/components/reports/lead-source-card.js.map +1 -0
  129. package/src/lib/components/reports/pipeline-card.js +2 -1
  130. package/src/lib/components/reports/pipeline-card.js.map +1 -1
  131. package/src/lib/components/reports/report-export.js +1 -1
  132. package/src/lib/components/reports/report-export.js.map +1 -1
  133. package/src/lib/components/reports-section.js +8 -0
  134. package/src/lib/components/reports-section.js.map +1 -1
  135. package/src/lib/components/sharing-rule-drawer.d.ts +5 -0
  136. package/src/lib/components/sharing-rule-drawer.js +108 -19
  137. package/src/lib/components/sharing-rule-drawer.js.map +1 -1
  138. package/src/lib/components/sharing-rules-card.js +11 -3
  139. package/src/lib/components/sharing-rules-card.js.map +1 -1
  140. package/src/lib/components/task-cells.d.ts +9 -1
  141. package/src/lib/components/task-cells.js +9 -4
  142. package/src/lib/components/task-cells.js.map +1 -1
  143. package/src/lib/components/task-edit-drawer.js +111 -43
  144. package/src/lib/components/task-edit-drawer.js.map +1 -1
  145. package/src/lib/components/tasks-bulk-bar.d.ts +0 -3
  146. package/src/lib/components/tasks-bulk-bar.js +7 -20
  147. package/src/lib/components/tasks-bulk-bar.js.map +1 -1
  148. package/src/lib/components/tasks-calendar.d.ts +3 -0
  149. package/src/lib/components/tasks-calendar.js +8 -1
  150. package/src/lib/components/tasks-calendar.js.map +1 -1
  151. package/src/lib/components/tasks-section.d.ts +3 -3
  152. package/src/lib/components/tasks-section.js +58 -43
  153. package/src/lib/components/tasks-section.js.map +1 -1
  154. package/src/lib/constants/api-routes.d.ts +2 -9
  155. package/src/lib/constants/api-routes.js +1 -7
  156. package/src/lib/constants/api-routes.js.map +1 -1
  157. package/src/lib/constants/bundle-common.d.ts +6 -0
  158. package/src/lib/constants/bundle-common.js +11 -0
  159. package/src/lib/constants/bundle-common.js.map +1 -1
  160. package/src/lib/constants/company-filters.d.ts +14 -0
  161. package/src/lib/constants/company-filters.js +51 -1
  162. package/src/lib/constants/company-filters.js.map +1 -1
  163. package/src/lib/constants/contact-filters.d.ts +2 -0
  164. package/src/lib/constants/contact-filters.js +18 -1
  165. package/src/lib/constants/contact-filters.js.map +1 -1
  166. package/src/lib/constants/deal-filters.d.ts +22 -1
  167. package/src/lib/constants/deal-filters.js +67 -4
  168. package/src/lib/constants/deal-filters.js.map +1 -1
  169. package/src/lib/declarations.console-server.d.ts +3 -0
  170. package/src/lib/declarations.console-server.js +35 -0
  171. package/src/lib/declarations.console-server.js.map +1 -1
  172. package/src/lib/declarations.d.ts +26 -0
  173. package/src/lib/declarations.js +35 -0
  174. package/src/lib/declarations.js.map +1 -0
  175. package/src/lib/declarations.server.d.ts +11 -0
  176. package/src/lib/declarations.server.js +97 -1
  177. package/src/lib/declarations.server.js.map +1 -1
  178. package/src/lib/hooks/use-company-picklists.d.ts +15 -0
  179. package/src/lib/hooks/use-company-picklists.js +55 -0
  180. package/src/lib/hooks/use-company-picklists.js.map +1 -0
  181. package/src/lib/hooks/use-crm-picklist.d.ts +25 -0
  182. package/src/lib/hooks/use-crm-picklist.js +53 -0
  183. package/src/lib/hooks/use-crm-picklist.js.map +1 -0
  184. package/src/lib/hooks/use-crm-record-names.d.ts +16 -0
  185. package/src/lib/hooks/use-crm-record-names.js +45 -19
  186. package/src/lib/hooks/use-crm-record-names.js.map +1 -1
  187. package/src/lib/hooks/use-crm-task-picklists.d.ts +11 -0
  188. package/src/lib/hooks/use-crm-task-picklists.js +45 -0
  189. package/src/lib/hooks/use-crm-task-picklists.js.map +1 -0
  190. package/src/lib/hooks/use-deals.d.ts +14 -0
  191. package/src/lib/hooks/use-deals.js +29 -0
  192. package/src/lib/hooks/use-deals.js.map +1 -1
  193. package/src/lib/hooks/use-lead-picklists.d.ts +14 -0
  194. package/src/lib/hooks/use-lead-picklists.js +46 -0
  195. package/src/lib/hooks/use-lead-picklists.js.map +1 -0
  196. package/src/lib/hooks/use-lead-source-picklist.d.ts +5 -19
  197. package/src/lib/hooks/use-lead-source-picklist.js +12 -22
  198. package/src/lib/hooks/use-lead-source-picklist.js.map +1 -1
  199. package/src/lib/hooks/use-lead-status-picklist.d.ts +9 -0
  200. package/src/lib/hooks/use-lead-status-picklist.js +40 -0
  201. package/src/lib/hooks/use-lead-status-picklist.js.map +1 -0
  202. package/src/lib/model/companies.d.ts +32 -3
  203. package/src/lib/model/companies.js +133 -16
  204. package/src/lib/model/companies.js.map +1 -1
  205. package/src/lib/model/contact-merge.d.ts +27 -3
  206. package/src/lib/model/contact-merge.js +81 -7
  207. package/src/lib/model/contact-merge.js.map +1 -1
  208. package/src/lib/model/contact-record.d.ts +17 -0
  209. package/src/lib/model/contact-record.js +17 -2
  210. package/src/lib/model/contact-record.js.map +1 -1
  211. package/src/lib/model/contact-update.d.ts +31 -2
  212. package/src/lib/model/contact-update.js +14 -0
  213. package/src/lib/model/contact-update.js.map +1 -1
  214. package/src/lib/model/crm-list-query.d.ts +5 -0
  215. package/src/lib/model/crm-list-query.js +8 -0
  216. package/src/lib/model/crm-list-query.js.map +1 -1
  217. package/src/lib/model/crm-next-activity.d.ts +107 -0
  218. package/src/lib/model/crm-next-activity.js +140 -0
  219. package/src/lib/model/crm-next-activity.js.map +1 -0
  220. package/src/lib/model/crm-recipes.d.ts +40 -0
  221. package/src/lib/model/crm-recipes.js +259 -0
  222. package/src/lib/model/crm-recipes.js.map +1 -0
  223. package/src/lib/model/crm-record-counts.d.ts +36 -0
  224. package/src/lib/model/crm-record-counts.js +54 -0
  225. package/src/lib/model/crm-record-counts.js.map +1 -0
  226. package/src/lib/model/crm-record-lists.d.ts +23 -0
  227. package/src/lib/model/crm-record-lists.js +161 -0
  228. package/src/lib/model/crm-record-lists.js.map +1 -0
  229. package/src/lib/model/crm-reports.d.ts +73 -3
  230. package/src/lib/model/crm-reports.js +120 -1
  231. package/src/lib/model/crm-reports.js.map +1 -1
  232. package/src/lib/model/crm-sharing.d.ts +21 -3
  233. package/src/lib/model/crm-sharing.js +27 -6
  234. package/src/lib/model/crm-sharing.js.map +1 -1
  235. package/src/lib/model/crm-task-reminders.d.ts +152 -0
  236. package/src/lib/model/crm-task-reminders.js +161 -0
  237. package/src/lib/model/crm-task-reminders.js.map +1 -0
  238. package/src/lib/model/deal-board-model.d.ts +8 -2
  239. package/src/lib/model/deal-board-model.js +15 -2
  240. package/src/lib/model/deal-board-model.js.map +1 -1
  241. package/src/lib/model/deal-contact-roles.d.ts +45 -0
  242. package/src/lib/model/deal-contact-roles.js +73 -0
  243. package/src/lib/model/deal-contact-roles.js.map +1 -0
  244. package/src/lib/model/deal-form-model.d.ts +56 -0
  245. package/src/lib/model/deal-form-model.js +79 -7
  246. package/src/lib/model/deal-form-model.js.map +1 -1
  247. package/src/lib/model/download-text-file.d.ts +23 -0
  248. package/src/lib/model/download-text-file.js +34 -0
  249. package/src/lib/model/download-text-file.js.map +1 -0
  250. package/src/lib/model/lead-filters.d.ts +36 -2
  251. package/src/lib/model/lead-filters.js +123 -2
  252. package/src/lib/model/lead-filters.js.map +1 -1
  253. package/src/lib/model/lead-source-direction.d.ts +38 -0
  254. package/src/lib/model/lead-source-direction.js +52 -0
  255. package/src/lib/model/lead-source-direction.js.map +1 -0
  256. package/src/lib/model/next-activity.d.ts +1 -1
  257. package/src/lib/model/next-activity.js.map +1 -1
  258. package/src/lib/model/picklist-values.d.ts +119 -0
  259. package/src/lib/model/picklist-values.js +256 -0
  260. package/src/lib/model/picklist-values.js.map +1 -0
  261. package/src/lib/model/record-facts-disclosed.d.ts +81 -0
  262. package/src/lib/model/record-facts-disclosed.js +281 -0
  263. package/src/lib/model/record-facts-disclosed.js.map +1 -0
  264. package/src/lib/model/record-facts.d.ts +215 -34
  265. package/src/lib/model/record-facts.js +307 -128
  266. package/src/lib/model/record-facts.js.map +1 -1
  267. package/src/lib/model/task-picklists.d.ts +52 -0
  268. package/src/lib/model/task-picklists.js +83 -0
  269. package/src/lib/model/task-picklists.js.map +1 -0
  270. package/src/lib/model/task-routes.d.ts +13 -0
  271. package/src/lib/model/task-routes.js +23 -4
  272. package/src/lib/model/task-routes.js.map +1 -1
  273. package/src/lib/plan-entitlements.js +6 -4
  274. package/src/lib/plan-entitlements.js.map +1 -1
  275. package/src/lib/plugin.js +17 -0
  276. package/src/lib/plugin.js.map +1 -1
  277. package/src/lib/server/api-v1/contacts.js +220 -14
  278. package/src/lib/server/api-v1/contacts.js.map +1 -1
  279. package/src/lib/server/api-v1/crm-activities.js +14 -1
  280. package/src/lib/server/api-v1/crm-activities.js.map +1 -1
  281. package/src/lib/server/api-v1/crm-companies.js +123 -14
  282. package/src/lib/server/api-v1/crm-companies.js.map +1 -1
  283. package/src/lib/server/api-v1/crm-deals.js +291 -26
  284. package/src/lib/server/api-v1/crm-deals.js.map +1 -1
  285. package/src/lib/server/api-v1/crm-leads.js +144 -38
  286. package/src/lib/server/api-v1/crm-leads.js.map +1 -1
  287. package/src/lib/server/api-v1/crm-pipelines.d.ts +6 -0
  288. package/src/lib/server/api-v1/crm-pipelines.js +8 -2
  289. package/src/lib/server/api-v1/crm-pipelines.js.map +1 -1
  290. package/src/lib/server/api-v1/crm-tasks.js +78 -34
  291. package/src/lib/server/api-v1/crm-tasks.js.map +1 -1
  292. package/src/lib/server/api-v1/openapi.d.ts +0 -11
  293. package/src/lib/server/api-v1/openapi.js +171 -16
  294. package/src/lib/server/api-v1/openapi.js.map +1 -1
  295. package/src/lib/server/assign-contact-owner.d.ts +188 -0
  296. package/src/lib/server/assign-contact-owner.js +446 -0
  297. package/src/lib/server/assign-contact-owner.js.map +1 -0
  298. package/src/lib/server/associate-company-by-domain.d.ts +70 -0
  299. package/src/lib/server/associate-company-by-domain.js +153 -0
  300. package/src/lib/server/associate-company-by-domain.js.map +1 -0
  301. package/src/lib/server/automation-steps.d.ts +140 -0
  302. package/src/lib/server/automation-steps.js +669 -0
  303. package/src/lib/server/automation-steps.js.map +1 -0
  304. package/src/lib/server/capture-contact.d.ts +17 -0
  305. package/src/lib/server/capture-contact.js +95 -26
  306. package/src/lib/server/capture-contact.js.map +1 -1
  307. package/src/lib/server/capture-host-contact.d.ts +104 -0
  308. package/src/lib/server/capture-host-contact.js +151 -0
  309. package/src/lib/server/capture-host-contact.js.map +1 -0
  310. package/src/lib/server/company-children.d.ts +25 -0
  311. package/src/lib/server/company-children.js +42 -0
  312. package/src/lib/server/company-children.js.map +1 -0
  313. package/src/lib/server/company-delete.d.ts +18 -0
  314. package/src/lib/server/company-delete.js +44 -21
  315. package/src/lib/server/company-delete.js.map +1 -1
  316. package/src/lib/server/contact-email-history.js +21 -19
  317. package/src/lib/server/contact-email-history.js.map +1 -1
  318. package/src/lib/server/contact-remove.js +27 -2
  319. package/src/lib/server/contact-remove.js.map +1 -1
  320. package/src/lib/server/contact-reports-to.d.ts +61 -0
  321. package/src/lib/server/contact-reports-to.js +114 -0
  322. package/src/lib/server/contact-reports-to.js.map +1 -0
  323. package/src/lib/server/contact-update.d.ts +42 -1
  324. package/src/lib/server/contact-update.js +204 -23
  325. package/src/lib/server/contact-update.js.map +1 -1
  326. package/src/lib/server/convert-host-lead.d.ts +46 -1
  327. package/src/lib/server/convert-host-lead.js +173 -15
  328. package/src/lib/server/convert-host-lead.js.map +1 -1
  329. package/src/lib/server/convert-open-lead.js +12 -5
  330. package/src/lib/server/convert-open-lead.js.map +1 -1
  331. package/src/lib/server/crm-email-activity.d.ts +118 -0
  332. package/src/lib/server/crm-email-activity.js +148 -0
  333. package/src/lib/server/crm-email-activity.js.map +1 -0
  334. package/src/lib/server/crm-inbound-email.js +1 -1
  335. package/src/lib/server/crm-inbound-email.js.map +1 -1
  336. package/src/lib/server/crm-next-activity.d.ts +74 -0
  337. package/src/lib/server/crm-next-activity.js +194 -0
  338. package/src/lib/server/crm-next-activity.js.map +1 -0
  339. package/src/lib/server/crm-record-indexes.d.ts +45 -0
  340. package/src/lib/server/crm-record-indexes.js +78 -0
  341. package/src/lib/server/crm-record-indexes.js.map +1 -0
  342. package/src/lib/server/crm-sharing.d.ts +9 -1
  343. package/src/lib/server/crm-sharing.js +23 -3
  344. package/src/lib/server/crm-sharing.js.map +1 -1
  345. package/src/lib/server/deal-contact-roles.d.ts +27 -0
  346. package/src/lib/server/deal-contact-roles.js +89 -0
  347. package/src/lib/server/deal-contact-roles.js.map +1 -0
  348. package/src/lib/server/email-send.js +2 -1
  349. package/src/lib/server/email-send.js.map +1 -1
  350. package/src/lib/server/lead-convert.d.ts +5 -0
  351. package/src/lib/server/lead-convert.js +19 -3
  352. package/src/lib/server/lead-convert.js.map +1 -1
  353. package/src/lib/server/lead-create.d.ts +17 -2
  354. package/src/lib/server/lead-create.js +46 -14
  355. package/src/lib/server/lead-create.js.map +1 -1
  356. package/src/lib/server/lead-nurturing.d.ts +6 -0
  357. package/src/lib/server/lead-nurturing.js +57 -20
  358. package/src/lib/server/lead-nurturing.js.map +1 -1
  359. package/src/lib/server/lead-picklists.d.ts +35 -0
  360. package/src/lib/server/lead-picklists.js +52 -0
  361. package/src/lib/server/lead-picklists.js.map +1 -0
  362. package/src/lib/server/lead-source-picklist.d.ts +1 -13
  363. package/src/lib/server/lead-source-picklist.js +6 -33
  364. package/src/lib/server/lead-source-picklist.js.map +1 -1
  365. package/src/lib/server/merge-contacts.js +23 -5
  366. package/src/lib/server/merge-contacts.js.map +1 -1
  367. package/src/lib/server/next-activity-routes.js +2 -1
  368. package/src/lib/server/next-activity-routes.js.map +1 -1
  369. package/src/lib/server/person-eraser.d.ts +53 -0
  370. package/src/lib/server/person-eraser.js +149 -0
  371. package/src/lib/server/person-eraser.js.map +1 -0
  372. package/src/lib/server/person-records.d.ts +69 -0
  373. package/src/lib/server/person-records.js +317 -0
  374. package/src/lib/server/person-records.js.map +1 -0
  375. package/src/lib/server/person-refund.d.ts +97 -0
  376. package/src/lib/server/person-refund.js +221 -0
  377. package/src/lib/server/person-refund.js.map +1 -0
  378. package/src/lib/server/picklist-values.d.ts +21 -0
  379. package/src/lib/server/picklist-values.js +308 -0
  380. package/src/lib/server/picklist-values.js.map +1 -0
  381. package/src/lib/server/read-picklist.d.ts +44 -0
  382. package/src/lib/server/read-picklist.js +65 -0
  383. package/src/lib/server/read-picklist.js.map +1 -0
  384. package/src/lib/server/recipe-routes.js +22 -8
  385. package/src/lib/server/recipe-routes.js.map +1 -1
  386. package/src/lib/server/record-email-state.js +7 -1
  387. package/src/lib/server/record-email-state.js.map +1 -1
  388. package/src/lib/server/record-facts.d.ts +3 -0
  389. package/src/lib/server/record-facts.js +233 -31
  390. package/src/lib/server/record-facts.js.map +1 -1
  391. package/src/lib/server/record-origin.d.ts +27 -0
  392. package/src/lib/server/record-origin.js +104 -0
  393. package/src/lib/server/record-origin.js.map +1 -0
  394. package/src/lib/server/record-timeline.js +40 -3
  395. package/src/lib/server/record-timeline.js.map +1 -1
  396. package/src/lib/server/suite-gate.js +4 -3
  397. package/src/lib/server/suite-gate.js.map +1 -1
  398. package/src/lib/server/task-reminders-route.js +2 -1
  399. package/src/lib/server/task-reminders-route.js.map +1 -1
  400. package/src/lib/server/task-routes.js +33 -17
  401. package/src/lib/server/task-routes.js.map +1 -1
  402. package/src/lib/server-deal-stage.d.ts +5 -1
  403. package/src/lib/server-deal-stage.js +10 -5
  404. package/src/lib/server-deal-stage.js.map +1 -1
  405. package/src/lib/server.d.ts +8 -3
  406. package/src/lib/server.js +47 -43
  407. package/src/lib/server.js.map +1 -1
  408. package/src/lib/testing/memory-firestore.d.ts +55 -0
  409. package/src/lib/testing/memory-firestore.js +335 -0
  410. package/src/lib/testing/memory-firestore.js.map +1 -0
  411. package/src/lib/testing/stand-in-email-send-index.d.ts +25 -0
  412. package/src/lib/testing/stand-in-email-send-index.js +49 -0
  413. package/src/lib/testing/stand-in-email-send-index.js.map +1 -0
  414. package/src/lib/transfer/activities.d.ts +30 -0
  415. package/src/lib/transfer/activities.js +132 -0
  416. package/src/lib/transfer/activities.js.map +1 -0
  417. package/src/lib/transfer/aliases.d.ts +22 -0
  418. package/src/lib/transfer/aliases.js +1342 -0
  419. package/src/lib/transfer/aliases.js.map +1 -0
  420. package/src/lib/transfer/common.d.ts +222 -0
  421. package/src/lib/transfer/common.js +832 -0
  422. package/src/lib/transfer/common.js.map +1 -0
  423. package/src/lib/transfer/companies.d.ts +43 -0
  424. package/src/lib/transfer/companies.js +549 -0
  425. package/src/lib/transfer/companies.js.map +1 -0
  426. package/src/lib/transfer/contacts.d.ts +31 -0
  427. package/src/lib/transfer/contacts.js +727 -0
  428. package/src/lib/transfer/contacts.js.map +1 -0
  429. package/src/lib/transfer/deals.d.ts +66 -0
  430. package/src/lib/transfer/deals.js +698 -0
  431. package/src/lib/transfer/deals.js.map +1 -0
  432. package/src/lib/transfer/email-templates-package.d.ts +40 -0
  433. package/src/lib/transfer/email-templates-package.js +76 -0
  434. package/src/lib/transfer/email-templates-package.js.map +1 -0
  435. package/src/lib/transfer/email-templates-package.server.d.ts +32 -0
  436. package/src/lib/transfer/email-templates-package.server.js +176 -0
  437. package/src/lib/transfer/email-templates-package.server.js.map +1 -0
  438. package/src/lib/transfer/fields.d.ts +102 -0
  439. package/src/lib/transfer/fields.js +1755 -0
  440. package/src/lib/transfer/fields.js.map +1 -0
  441. package/src/lib/transfer/leads.d.ts +30 -0
  442. package/src/lib/transfer/leads.js +582 -0
  443. package/src/lib/transfer/leads.js.map +1 -0
  444. package/src/lib/transfer/pipelines.d.ts +21 -0
  445. package/src/lib/transfer/pipelines.js +172 -0
  446. package/src/lib/transfer/pipelines.js.map +1 -0
  447. package/src/lib/transfer/register.d.ts +47 -0
  448. package/src/lib/transfer/register.js +277 -0
  449. package/src/lib/transfer/register.js.map +1 -0
  450. package/src/lib/transfer/tasks.d.ts +30 -0
  451. package/src/lib/transfer/tasks.js +418 -0
  452. package/src/lib/transfer/tasks.js.map +1 -0
  453. package/src/lib/transfer/ui.d.ts +20 -0
  454. package/src/lib/transfer/ui.js +42 -0
  455. package/src/lib/transfer/ui.js.map +1 -0
  456. package/src/lib/components/company-import-drawer.d.ts +0 -42
  457. package/src/lib/components/company-import-drawer.js +0 -99
  458. package/src/lib/components/company-import-drawer.js.map +0 -1
  459. package/src/lib/components/contact-import-drawer.d.ts +0 -46
  460. package/src/lib/components/contact-import-drawer.js +0 -149
  461. package/src/lib/components/contact-import-drawer.js.map +0 -1
  462. package/src/lib/components/crm-export-all-button.d.ts +0 -39
  463. package/src/lib/components/crm-export-all-button.js +0 -98
  464. package/src/lib/components/crm-export-all-button.js.map +0 -1
  465. package/src/lib/components/csv-import-drawer.d.ts +0 -139
  466. package/src/lib/components/csv-import-drawer.js +0 -757
  467. package/src/lib/components/csv-import-drawer.js.map +0 -1
  468. package/src/lib/components/deal-import-drawer.d.ts +0 -24
  469. package/src/lib/components/deal-import-drawer.js +0 -83
  470. package/src/lib/components/deal-import-drawer.js.map +0 -1
  471. package/src/lib/components/lead-import-drawer.d.ts +0 -27
  472. package/src/lib/components/lead-import-drawer.js +0 -118
  473. package/src/lib/components/lead-import-drawer.js.map +0 -1
  474. package/src/lib/components/lead-source-values-card.d.ts +0 -27
  475. package/src/lib/components/lead-source-values-card.js.map +0 -1
  476. package/src/lib/components/task-import-drawer.d.ts +0 -24
  477. package/src/lib/components/task-import-drawer.js +0 -82
  478. package/src/lib/components/task-import-drawer.js.map +0 -1
  479. package/src/lib/model/companies-csv.d.ts +0 -36
  480. package/src/lib/model/companies-csv.js +0 -38
  481. package/src/lib/model/companies-csv.js.map +0 -1
  482. package/src/lib/model/contacts-csv.d.ts +0 -54
  483. package/src/lib/model/contacts-csv.js +0 -67
  484. package/src/lib/model/contacts-csv.js.map +0 -1
  485. package/src/lib/model/crm-company-import.d.ts +0 -154
  486. package/src/lib/model/crm-company-import.js +0 -331
  487. package/src/lib/model/crm-company-import.js.map +0 -1
  488. package/src/lib/model/crm-csv.d.ts +0 -239
  489. package/src/lib/model/crm-csv.js +0 -467
  490. package/src/lib/model/crm-csv.js.map +0 -1
  491. package/src/lib/model/crm-deal-import.d.ts +0 -112
  492. package/src/lib/model/crm-deal-import.js +0 -263
  493. package/src/lib/model/crm-deal-import.js.map +0 -1
  494. package/src/lib/model/crm-import.d.ts +0 -250
  495. package/src/lib/model/crm-import.js +0 -467
  496. package/src/lib/model/crm-import.js.map +0 -1
  497. package/src/lib/model/crm-lead-import.d.ts +0 -138
  498. package/src/lib/model/crm-lead-import.js +0 -446
  499. package/src/lib/model/crm-lead-import.js.map +0 -1
  500. package/src/lib/model/crm-task-import.d.ts +0 -94
  501. package/src/lib/model/crm-task-import.js +0 -275
  502. package/src/lib/model/crm-task-import.js.map +0 -1
  503. package/src/lib/model/deals-csv.d.ts +0 -32
  504. package/src/lib/model/deals-csv.js +0 -36
  505. package/src/lib/model/deals-csv.js.map +0 -1
  506. package/src/lib/model/import-column-shapes.d.ts +0 -36
  507. package/src/lib/model/import-column-shapes.js +0 -76
  508. package/src/lib/model/import-column-shapes.js.map +0 -1
  509. package/src/lib/model/lead-source-values.d.ts +0 -82
  510. package/src/lib/model/lead-source-values.js +0 -149
  511. package/src/lib/model/lead-source-values.js.map +0 -1
  512. package/src/lib/model/leads-csv.d.ts +0 -40
  513. package/src/lib/model/leads-csv.js +0 -40
  514. package/src/lib/model/leads-csv.js.map +0 -1
  515. package/src/lib/model/tasks-csv.d.ts +0 -28
  516. package/src/lib/model/tasks-csv.js +0 -28
  517. package/src/lib/model/tasks-csv.js.map +0 -1
  518. package/src/lib/server/companies-import.d.ts +0 -57
  519. package/src/lib/server/companies-import.js +0 -242
  520. package/src/lib/server/companies-import.js.map +0 -1
  521. package/src/lib/server/contacts-import.d.ts +0 -109
  522. package/src/lib/server/contacts-import.js +0 -393
  523. package/src/lib/server/contacts-import.js.map +0 -1
  524. package/src/lib/server/deals-import.d.ts +0 -76
  525. package/src/lib/server/deals-import.js +0 -248
  526. package/src/lib/server/deals-import.js.map +0 -1
  527. package/src/lib/server/export-route.d.ts +0 -60
  528. package/src/lib/server/export-route.js +0 -447
  529. package/src/lib/server/export-route.js.map +0 -1
  530. package/src/lib/server/import-context.d.ts +0 -87
  531. package/src/lib/server/import-context.js +0 -182
  532. package/src/lib/server/import-context.js.map +0 -1
  533. package/src/lib/server/lead-source-values.d.ts +0 -50
  534. package/src/lib/server/lead-source-values.js +0 -191
  535. package/src/lib/server/lead-source-values.js.map +0 -1
  536. package/src/lib/server/leads-import.d.ts +0 -84
  537. package/src/lib/server/leads-import.js +0 -367
  538. package/src/lib/server/leads-import.js.map +0 -1
  539. package/src/lib/server/tasks-import.d.ts +0 -54
  540. package/src/lib/server/tasks-import.js +0 -160
  541. package/src/lib/server/tasks-import.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/tasks-bulk-bar.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\n/**\n * The bar over the tasks list, for whatever rows are ticked (AGL-2621).\n *\n * Complete them, hand them to somebody, move their due date, take them\n * into a spreadsheet, or delete them. Two of these have a side effect\n * outside the document and go through their ROUTE: completing fires\n * `taskCompleted`, which only the server emits, and assigning tells the\n * assignee, which only the server may write into somebody's inbox — so\n * Complete goes through `crm/task-complete` and Assign through\n * `crm/task-save`, exactly as the checkbox and the drawer do for one task.\n * Under a site that is one request per task, each authorized against the\n * site; beneath the organization hub it is ONE request per action, the\n * routes' org-level batch form (AGL-2637), authorized once by the org and\n * answered per task. The due date and the delete have no effect beyond\n * the document, so they are batched client-direct writes under the rules,\n * as reopening is.\n */\n\nimport { CRM_COLLECTIONS, crmMemberPickerLabel } from '@aglyn/aglyn'\nimport { useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport { Button, MenuItem, TextField } from '@mui/material'\nimport { doc, serverTimestamp } from 'firebase/firestore'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useCrmBulkApply } from '../hooks/use-crm-bulk-apply'\nimport type { CrmTaskRow } from '../hooks/use-crm-tasks'\nimport type { OrgMemberDirectory } from '../hooks/use-org-member-directory'\nimport { downloadTextFile } from '../model/contacts-csv'\nimport { refreshCrmNextActivity } from '../model/next-activity-api'\nimport {\n type CrmBulkPlan,\n type CrmBulkWrite,\n crmBulkWriters,\n runCrmBulkBatch,\n runCrmBulkCalls,\n runCrmBulkWrites,\n} from '../model/crm-bulk-writes'\nimport {\n completeCrmTask,\n completeCrmTasks,\n saveCrmTask,\n saveCrmTasks,\n} from '../model/task-api'\nimport { crmTaskCallScope, crmTaskFieldsOf } from '../model/task-routes'\nimport { dueAtToLocalInput, localInputToDueAt } from '../model/task-views'\nimport { type TaskCsvOptions, tasksCsv } from '../model/tasks-csv'\nimport {\n type CrmBulkNoun,\n CrmBulkBarFrame,\n CrmBulkValueDialog,\n countNoun,\n} from './crm-bulk-bar-frame'\nimport CrmExportAllButton from './crm-export-all-button'\n\nexport interface TasksBulkBarProps {\n /**\n * The site the task routes run as, or `null` at the organization level\n * (AGL-2630), where the routes run as the org — their batch form, one\n * request per action (AGL-2637).\n */\n hostId: string | null\n /** `['orgs', orgId]`, or `null` while the org is unresolved. */\n scope: readonly [string, string] | null\n rows: readonly CrmTaskRow[]\n selected: readonly string[]\n onSelectedChange: (ids: string[]) => void\n /** The section's roster — already read for the Assignee column. */\n directory: OrgMemberDirectory\n /** How the export names the assignee and the linked records — the list's own. */\n csv?: TaskCsvOptions\n}\n\nconst NOUN: CrmBulkNoun = { singular: 'task', plural: 'tasks' }\n\ntype PendingAction = 'assign' | 'due'\n\nconst ACTION_TITLES: Record<PendingAction, string> = {\n assign: 'Assign to',\n due: 'Set the due date',\n}\n\nconst labelOf = (task: CrmTaskRow): string => task.title || task.$id\n\nexport function TasksBulkBar(props: TasksBulkBarProps) {\n if (!props.selected.length) return null\n return <TasksBulkBarBody {...props} />\n}\nTasksBulkBar.displayName = 'TasksBulkBar'\n\nfunction TasksBulkBarBody(props: TasksBulkBarProps) {\n const { hostId, scope, rows, selected, onSelectedChange, directory, csv } = props\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { confirm } = useConfirmationContext()\n const { busy, report, apply, dismissReport } = useCrmBulkApply({ recordKind: 'task' })\n\n const selectedRows = useMemo(() => {\n const chosen = new Set(selected)\n return rows.filter((row) => chosen.has(row.$id))\n }, [rows, selected])\n\n const [pending, setPending] = useState<PendingAction | null>(null)\n const [value, setValue] = useState('')\n\n const writers = useMemo(\n () =>\n crmBulkWriters(firestore, (id) =>\n doc(firestore, scope?.[0] ?? 'orgs', scope?.[1] ?? '', CRM_COLLECTIONS.tasks, id),\n ),\n [firestore, scope],\n )\n\n const openAction = (action: PendingAction) => {\n setValue('')\n setPending(action)\n }\n\n // The org the batch form names — the scope's, which is the org's root.\n const orgId = scope?.[1] ?? null\n\n const runPlan = useCallback(\n async (plan: CrmBulkPlan, done: (count: number) => string) => {\n const outcome = await apply({\n attempted: plan.writes.length,\n skipped: plan.skipped,\n job: () => runCrmBulkWrites(writers, plan.writes, (write) => write.label),\n done,\n })\n // Client-direct writes: the records the selection names are told\n // (AGL-2661), once each however many tasks named them.\n const written = new Set(plan.writes.map((write) => write.id))\n await refreshCrmNextActivity(\n user,\n crmTaskCallScope(hostId, orgId),\n selectedRows.filter((task) => written.has(task.$id)),\n )\n return outcome\n },\n [apply, writers, user, hostId, orgId, selectedRows],\n )\n\n /**\n * The routes over the rows: under a site one request per task, in\n * order, named by title; beneath the org hub one request for them all,\n * tallied off its per-task answers.\n */\n const runCalls = useCallback(\n (\n tasks: readonly CrmTaskRow[],\n call: {\n each: (task: CrmTaskRow) => Promise<unknown>\n batch: (tasks: readonly CrmTaskRow[]) => Promise<ReadonlyArray<{ taskId: string; ok: boolean; error?: string }>>\n },\n done: (count: number) => string,\n ) =>\n apply({\n attempted: tasks.length,\n skipped: [],\n job: () =>\n hostId\n ? runCrmBulkCalls(tasks, labelOf, call.each)\n : runCrmBulkBatch(\n tasks,\n (task) => task.$id,\n labelOf,\n async (rows) =>\n (await call.batch(rows)).map(({ taskId, ...rest }) => ({ id: taskId, ...rest })),\n ),\n done,\n }),\n [apply, hostId],\n )\n\n /*\n * A task already done is left alone rather than sent: the route would\n * answer `alreadyDone` and write nothing, and a request that can only\n * answer nothing is not worth its round trip.\n */\n const handleComplete = useCallback(async () => {\n if (!orgId) return\n const open = selectedRows.filter((task) => task.status !== 'done')\n await runCalls(\n open,\n {\n each: (task) => completeCrmTask(user, { hostId: hostId as string, taskId: task.$id }),\n batch: async (tasks) =>\n (await completeCrmTasks(user, { orgId, taskIds: tasks.map((task) => task.$id) }))\n .results,\n },\n (count) => `Completed ${countNoun(count, NOUN)}`,\n )\n }, [selectedRows, runCalls, user, hostId, orgId])\n\n const handleApply = useCallback(async () => {\n if (!pending || !scope) return\n const action = pending\n setPending(null)\n if (action === 'assign') {\n const assigneeUid = value || null\n const who = assigneeUid ? directory.nameOf(assigneeUid) : 'nobody'\n const reassigned = (task: CrmTaskRow) => ({\n taskId: task.$id,\n task: { ...crmTaskFieldsOf(task), assigneeUid },\n })\n await runCalls(\n selectedRows,\n {\n each: (task) => saveCrmTask(user, { hostId: hostId as string, ...reassigned(task) }),\n batch: async (tasks) =>\n (await saveCrmTasks(user, { orgId: scope[1], tasks: tasks.map(reassigned) })).results,\n },\n (count) => `Assigned ${countNoun(count, NOUN)} to ${who}`,\n )\n return\n }\n const dueAtMs = localInputToDueAt(value)\n const writes: CrmBulkWrite[] = selectedRows.map((task) => ({\n id: task.$id,\n label: labelOf(task),\n kind: 'update',\n // `null` rather than a deleted field: every view orders by `dueAtMs`,\n // and a document missing it drops out of the `orderBy` entirely.\n data: { dueAtMs, updatedAt: serverTimestamp() },\n }))\n await runPlan(\n { writes, skipped: [] },\n (count) =>\n dueAtMs === null\n ? `Due date cleared on ${countNoun(count, NOUN)}`\n : `Due date set on ${countNoun(count, NOUN)}`,\n )\n }, [pending, scope, value, directory, selectedRows, runCalls, user, hostId, runPlan])\n\n const handleExport = useCallback(() => {\n downloadTextFile('tasks-selected.csv', 'text/csv', tasksCsv(selectedRows, csv))\n }, [selectedRows, csv])\n\n const handleDelete = useCallback(async () => {\n if (!scope || !selectedRows.length) return\n const count = selectedRows.length\n const confirmed = await confirm({\n title: count === 1 ? 'Delete this task?' : `Delete ${count} tasks?`,\n description:\n `${count === 1 ? 'It is' : 'They are'} removed for everyone who can ` +\n 'see them. A finished task is better ticked done, which keeps it in ' +\n 'the Done view.',\n confirmationText: count === 1 ? 'Delete task' : 'Delete tasks',\n confirmationButtonProps: { color: 'error' },\n })\n // `confirm` resolves with no value and REJECTS on cancel.\n .then(() => true)\n .catch(() => false)\n if (!confirmed) return\n const writes: CrmBulkWrite[] = selectedRows.map((task) => ({\n id: task.$id,\n label: labelOf(task),\n kind: 'delete',\n }))\n const outcome = await runPlan(\n { writes, skipped: [] },\n (done) => `Deleted ${countNoun(done, NOUN)}`,\n )\n const refused = new Set(outcome.refused.map((row) => row.label))\n onSelectedChange(\n selectedRows.filter((task) => refused.has(labelOf(task))).map((task) => task.$id),\n )\n }, [scope, selectedRows, confirm, runPlan, onSelectedChange])\n\n return (\n <CrmBulkBarFrame\n count={selected.length}\n noun={NOUN}\n busy={busy}\n onClear={() => onSelectedChange([])}\n report={report}\n onDismissReport={dismissReport}\n extras={\n <CrmBulkValueDialog\n open={pending !== null}\n title={pending ? ACTION_TITLES[pending] : ''}\n count={selected.length}\n noun={NOUN}\n busy={busy}\n canApply\n onClose={() => setPending(null)}\n onApply={() => void handleApply()}\n >\n {pending === 'assign' ? (\n <TextField\n select\n size=\"small\"\n label=\"Assignee\"\n value={value}\n onChange={(event) => setValue(event.target.value)}\n disabled={directory.loading}\n error={Boolean(directory.error)}\n helperText={\n directory.error ??\n (directory.loading\n ? 'Loading the team…'\n : 'Somebody other than you is told, as the drawer tells them')\n }\n >\n <MenuItem value=\"\">{'Nobody — clear the assignee'}</MenuItem>\n {directory.members.map((member) => (\n <MenuItem key={member.uid} value={member.uid}>\n {crmMemberPickerLabel(member)}\n </MenuItem>\n ))}\n </TextField>\n ) : pending === 'due' ? (\n <TextField\n size=\"small\"\n type=\"datetime-local\"\n label=\"Due\"\n value={value}\n onChange={(event) => setValue(event.target.value)}\n helperText=\"Leave it empty to clear the due date\"\n slotProps={{ inputLabel: { shrink: true } }}\n />\n ) : null}\n </CrmBulkValueDialog>\n }\n >\n <Button size=\"small\" disabled={busy || !scope} onClick={() => void handleComplete()}>\n {'Complete'}\n </Button>\n <Button size=\"small\" disabled={busy || !scope} onClick={() => openAction('assign')}>\n {'Assign'}\n </Button>\n <Button\n size=\"small\"\n disabled={busy || !scope}\n onClick={() => {\n openAction('due')\n // Start from the first task's own date, so a nudge is an edit\n // rather than a retype.\n setValue(dueAtToLocalInput(selectedRows[0]?.dueAtMs))\n }}\n >\n {'Set due'}\n </Button>\n <Button size=\"small\" disabled={busy} onClick={handleExport}>\n {'Export CSV'}\n </Button>\n {/*\n The selection's file is the rows on screen; this one is the whole\n collection, streamed by the server (AGL-2662).\n */}\n <CrmExportAllButton\n resource=\"tasks\"\n orgId={scope?.[1] ?? null}\n hostId={hostId}\n disabled={busy}\n />\n <Button\n size=\"small\"\n color=\"error\"\n disabled={busy || !scope}\n onClick={() => void handleDelete()}\n >\n {'Delete'}\n </Button>\n </CrmBulkBarFrame>\n )\n}\nTasksBulkBarBody.displayName = 'TasksBulkBarBody'\n\nexport default TasksBulkBar\n"],"names":["CRM_COLLECTIONS","crmMemberPickerLabel","useConfirmationContext","useFirestore","useUser","Button","MenuItem","TextField","doc","serverTimestamp","useCallback","useMemo","useState","useCrmBulkApply","downloadTextFile","refreshCrmNextActivity","crmBulkWriters","runCrmBulkBatch","runCrmBulkCalls","runCrmBulkWrites","completeCrmTask","completeCrmTasks","saveCrmTask","saveCrmTasks","crmTaskCallScope","crmTaskFieldsOf","dueAtToLocalInput","localInputToDueAt","tasksCsv","CrmBulkBarFrame","CrmBulkValueDialog","countNoun","CrmExportAllButton","NOUN","singular","plural","ACTION_TITLES","assign","due","labelOf","task","title","$id","TasksBulkBar","props","selected","length","TasksBulkBarBody","displayName","directory","hostId","scope","rows","onSelectedChange","csv","firestore","data","user","confirm","busy","report","apply","dismissReport","recordKind","selectedRows","chosen","Set","filter","row","has","pending","setPending","value","setValue","writers","id","tasks","openAction","action","orgId","runPlan","plan","done","outcome","attempted","writes","skipped","job","write","label","written","map","runCalls","call","each","batch","taskId","rest","handleComplete","open","status","taskIds","results","count","handleApply","assigneeUid","who","nameOf","reassigned","dueAtMs","kind","updatedAt","handleExport","handleDelete","confirmed","description","confirmationText","confirmationButtonProps","color","then","catch","refused","noun","onClear","onDismissReport","extras","canApply","onClose","onApply","select","size","onChange","event","target","disabled","loading","error","Boolean","helperText","members","member","uid","type","slotProps","inputLabel","shrink","onClick","resource"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/tasks-bulk-bar.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\n/**\n * The bar over the tasks list, for whatever rows are ticked (AGL-2621).\n *\n * Complete them, hand them to somebody, move their due date, take them\n * into a spreadsheet, or delete them. Two of these have a side effect\n * outside the document and go through their ROUTE: completing fires\n * `taskCompleted`, which only the server emits, and assigning tells the\n * assignee, which only the server may write into somebody's inbox — so\n * Complete goes through `crm/task-complete` and Assign through\n * `crm/task-save`, exactly as the checkbox and the drawer do for one task.\n * Under a site that is one request per task, each authorized against the\n * site; beneath the organization hub it is ONE request per action, the\n * routes' org-level batch form (AGL-2637), authorized once by the org and\n * answered per task. The due date and the delete have no effect beyond\n * the document, so they are batched client-direct writes under the rules,\n * as reopening is.\n */\n\nimport { CRM_COLLECTIONS, crmMemberPickerLabel } from '@aglyn/aglyn'\nimport { useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport { Button, MenuItem, TextField } from '@mui/material'\nimport { doc, serverTimestamp } from 'firebase/firestore'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useCrmBulkApply } from '../hooks/use-crm-bulk-apply'\nimport type { CrmTaskRow } from '../hooks/use-crm-tasks'\nimport type { OrgMemberDirectory } from '../hooks/use-org-member-directory'\nimport { refreshCrmNextActivity } from '../model/next-activity-api'\nimport {\n type CrmBulkPlan,\n type CrmBulkWrite,\n crmBulkWriters,\n runCrmBulkBatch,\n runCrmBulkCalls,\n runCrmBulkWrites,\n} from '../model/crm-bulk-writes'\nimport {\n completeCrmTask,\n completeCrmTasks,\n saveCrmTask,\n saveCrmTasks,\n} from '../model/task-api'\nimport { crmTaskCallScope, crmTaskFieldsOf } from '../model/task-routes'\nimport { dueAtToLocalInput, localInputToDueAt } from '../model/task-views'\nimport {\n type CrmBulkNoun,\n CrmBulkBarFrame,\n CrmBulkValueDialog,\n countNoun,\n} from './crm-bulk-bar-frame'\nimport { CrmExportButton } from './crm-transfer-buttons'\nimport { CRM_TASKS_RESOURCE } from '../transfer/fields'\n\nexport interface TasksBulkBarProps {\n /**\n * The site the task routes run as, or `null` at the organization level\n * (AGL-2630), where the routes run as the org — their batch form, one\n * request per action (AGL-2637).\n */\n hostId: string | null\n /** `['orgs', orgId]`, or `null` while the org is unresolved. */\n scope: readonly [string, string] | null\n rows: readonly CrmTaskRow[]\n selected: readonly string[]\n onSelectedChange: (ids: string[]) => void\n /** The section's roster — already read for the Assignee column. */\n directory: OrgMemberDirectory\n}\n\nconst NOUN: CrmBulkNoun = { singular: 'task', plural: 'tasks' }\n\ntype PendingAction = 'assign' | 'due'\n\nconst ACTION_TITLES: Record<PendingAction, string> = {\n assign: 'Assign to',\n due: 'Set the due date',\n}\n\nconst labelOf = (task: CrmTaskRow): string => task.title || task.$id\n\nexport function TasksBulkBar(props: TasksBulkBarProps) {\n if (!props.selected.length) return null\n return <TasksBulkBarBody {...props} />\n}\nTasksBulkBar.displayName = 'TasksBulkBar'\n\nfunction TasksBulkBarBody(props: TasksBulkBarProps) {\n const { hostId, scope, rows, selected, onSelectedChange, directory } = props\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { confirm } = useConfirmationContext()\n const { busy, report, apply, dismissReport } = useCrmBulkApply({ recordKind: 'task' })\n\n const selectedRows = useMemo(() => {\n const chosen = new Set(selected)\n return rows.filter((row) => chosen.has(row.$id))\n }, [rows, selected])\n\n const [pending, setPending] = useState<PendingAction | null>(null)\n const [value, setValue] = useState('')\n\n const writers = useMemo(\n () =>\n crmBulkWriters(firestore, (id) =>\n doc(firestore, scope?.[0] ?? 'orgs', scope?.[1] ?? '', CRM_COLLECTIONS.tasks, id),\n ),\n [firestore, scope],\n )\n\n const openAction = (action: PendingAction) => {\n setValue('')\n setPending(action)\n }\n\n // The org the batch form names — the scope's, which is the org's root.\n const orgId = scope?.[1] ?? null\n\n const runPlan = useCallback(\n async (plan: CrmBulkPlan, done: (count: number) => string) => {\n const outcome = await apply({\n attempted: plan.writes.length,\n skipped: plan.skipped,\n job: () => runCrmBulkWrites(writers, plan.writes, (write) => write.label),\n done,\n })\n // Client-direct writes: the records the selection names are told\n // (AGL-2661), once each however many tasks named them.\n const written = new Set(plan.writes.map((write) => write.id))\n await refreshCrmNextActivity(\n user,\n crmTaskCallScope(hostId, orgId),\n selectedRows.filter((task) => written.has(task.$id)),\n )\n return outcome\n },\n [apply, writers, user, hostId, orgId, selectedRows],\n )\n\n /**\n * The routes over the rows: under a site one request per task, in\n * order, named by title; beneath the org hub one request for them all,\n * tallied off its per-task answers.\n */\n const runCalls = useCallback(\n (\n tasks: readonly CrmTaskRow[],\n call: {\n each: (task: CrmTaskRow) => Promise<unknown>\n batch: (tasks: readonly CrmTaskRow[]) => Promise<ReadonlyArray<{ taskId: string; ok: boolean; error?: string }>>\n },\n done: (count: number) => string,\n ) =>\n apply({\n attempted: tasks.length,\n skipped: [],\n job: () =>\n hostId\n ? runCrmBulkCalls(tasks, labelOf, call.each)\n : runCrmBulkBatch(\n tasks,\n (task) => task.$id,\n labelOf,\n async (rows) =>\n (await call.batch(rows)).map(({ taskId, ...rest }) => ({ id: taskId, ...rest })),\n ),\n done,\n }),\n [apply, hostId],\n )\n\n /*\n * A task already done is left alone rather than sent: the route would\n * answer `alreadyDone` and write nothing, and a request that can only\n * answer nothing is not worth its round trip.\n */\n const handleComplete = useCallback(async () => {\n if (!orgId) return\n const open = selectedRows.filter((task) => task.status !== 'done')\n await runCalls(\n open,\n {\n each: (task) => completeCrmTask(user, { hostId: hostId as string, taskId: task.$id }),\n batch: async (tasks) =>\n (await completeCrmTasks(user, { orgId, taskIds: tasks.map((task) => task.$id) }))\n .results,\n },\n (count) => `Completed ${countNoun(count, NOUN)}`,\n )\n }, [selectedRows, runCalls, user, hostId, orgId])\n\n const handleApply = useCallback(async () => {\n if (!pending || !scope) return\n const action = pending\n setPending(null)\n if (action === 'assign') {\n const assigneeUid = value || null\n const who = assigneeUid ? directory.nameOf(assigneeUid) : 'nobody'\n const reassigned = (task: CrmTaskRow) => ({\n taskId: task.$id,\n task: { ...crmTaskFieldsOf(task), assigneeUid },\n })\n await runCalls(\n selectedRows,\n {\n each: (task) => saveCrmTask(user, { hostId: hostId as string, ...reassigned(task) }),\n batch: async (tasks) =>\n (await saveCrmTasks(user, { orgId: scope[1], tasks: tasks.map(reassigned) })).results,\n },\n (count) => `Assigned ${countNoun(count, NOUN)} to ${who}`,\n )\n return\n }\n const dueAtMs = localInputToDueAt(value)\n const writes: CrmBulkWrite[] = selectedRows.map((task) => ({\n id: task.$id,\n label: labelOf(task),\n kind: 'update',\n // `null` rather than a deleted field: every view orders by `dueAtMs`,\n // and a document missing it drops out of the `orderBy` entirely.\n data: { dueAtMs, updatedAt: serverTimestamp() },\n }))\n await runPlan(\n { writes, skipped: [] },\n (count) =>\n dueAtMs === null\n ? `Due date cleared on ${countNoun(count, NOUN)}`\n : `Due date set on ${countNoun(count, NOUN)}`,\n )\n }, [pending, scope, value, directory, selectedRows, runCalls, user, hostId, runPlan])\n\n const handleDelete = useCallback(async () => {\n if (!scope || !selectedRows.length) return\n const count = selectedRows.length\n const confirmed = await confirm({\n title: count === 1 ? 'Delete this task?' : `Delete ${count} tasks?`,\n description:\n `${count === 1 ? 'It is' : 'They are'} removed for everyone who can ` +\n 'see them. A finished task is better ticked done, which keeps it in ' +\n 'the Done view.',\n confirmationText: count === 1 ? 'Delete task' : 'Delete tasks',\n confirmationButtonProps: { color: 'error' },\n })\n // `confirm` resolves with no value and REJECTS on cancel.\n .then(() => true)\n .catch(() => false)\n if (!confirmed) return\n const writes: CrmBulkWrite[] = selectedRows.map((task) => ({\n id: task.$id,\n label: labelOf(task),\n kind: 'delete',\n }))\n const outcome = await runPlan(\n { writes, skipped: [] },\n (done) => `Deleted ${countNoun(done, NOUN)}`,\n )\n const refused = new Set(outcome.refused.map((row) => row.label))\n onSelectedChange(\n selectedRows.filter((task) => refused.has(labelOf(task))).map((task) => task.$id),\n )\n }, [scope, selectedRows, confirm, runPlan, onSelectedChange])\n\n return (\n <CrmBulkBarFrame\n count={selected.length}\n noun={NOUN}\n busy={busy}\n onClear={() => onSelectedChange([])}\n report={report}\n onDismissReport={dismissReport}\n extras={\n <CrmBulkValueDialog\n open={pending !== null}\n title={pending ? ACTION_TITLES[pending] : ''}\n count={selected.length}\n noun={NOUN}\n busy={busy}\n canApply\n onClose={() => setPending(null)}\n onApply={() => void handleApply()}\n >\n {pending === 'assign' ? (\n <TextField\n select\n size=\"small\"\n label=\"Assignee\"\n value={value}\n onChange={(event) => setValue(event.target.value)}\n disabled={directory.loading}\n error={Boolean(directory.error)}\n helperText={\n directory.error ??\n (directory.loading\n ? 'Loading the team…'\n : 'Somebody other than you is told, as the drawer tells them')\n }\n >\n <MenuItem value=\"\">{'Nobody — clear the assignee'}</MenuItem>\n {directory.members.map((member) => (\n <MenuItem key={member.uid} value={member.uid}>\n {crmMemberPickerLabel(member)}\n </MenuItem>\n ))}\n </TextField>\n ) : pending === 'due' ? (\n <TextField\n size=\"small\"\n type=\"datetime-local\"\n label=\"Due\"\n value={value}\n onChange={(event) => setValue(event.target.value)}\n helperText=\"Leave it empty to clear the due date\"\n slotProps={{ inputLabel: { shrink: true } }}\n />\n ) : null}\n </CrmBulkValueDialog>\n }\n >\n <Button size=\"small\" disabled={busy || !scope} onClick={() => void handleComplete()}>\n {'Complete'}\n </Button>\n <Button size=\"small\" disabled={busy || !scope} onClick={() => openAction('assign')}>\n {'Assign'}\n </Button>\n <Button\n size=\"small\"\n disabled={busy || !scope}\n onClick={() => {\n openAction('due')\n // Start from the first task's own date, so a nudge is an edit\n // rather than a retype.\n setValue(dueAtToLocalInput(selectedRows[0]?.dueAtMs))\n }}\n >\n {'Set due'}\n </Button>\n {/* The selection through the export dialog: every field, chosen (AGL-3528). */}\n <CrmExportButton\n resource={CRM_TASKS_RESOURCE}\n hostId={hostId}\n selection={selectedRows.map((row) => row.$id)}\n disabled={busy}\n />\n <Button\n size=\"small\"\n color=\"error\"\n disabled={busy || !scope}\n onClick={() => void handleDelete()}\n >\n {'Delete'}\n </Button>\n </CrmBulkBarFrame>\n )\n}\nTasksBulkBarBody.displayName = 'TasksBulkBarBody'\n\nexport default TasksBulkBar\n"],"names":["CRM_COLLECTIONS","crmMemberPickerLabel","useConfirmationContext","useFirestore","useUser","Button","MenuItem","TextField","doc","serverTimestamp","useCallback","useMemo","useState","useCrmBulkApply","refreshCrmNextActivity","crmBulkWriters","runCrmBulkBatch","runCrmBulkCalls","runCrmBulkWrites","completeCrmTask","completeCrmTasks","saveCrmTask","saveCrmTasks","crmTaskCallScope","crmTaskFieldsOf","dueAtToLocalInput","localInputToDueAt","CrmBulkBarFrame","CrmBulkValueDialog","countNoun","CrmExportButton","CRM_TASKS_RESOURCE","NOUN","singular","plural","ACTION_TITLES","assign","due","labelOf","task","title","$id","TasksBulkBar","props","selected","length","TasksBulkBarBody","displayName","directory","hostId","scope","rows","onSelectedChange","firestore","data","user","confirm","busy","report","apply","dismissReport","recordKind","selectedRows","chosen","Set","filter","row","has","pending","setPending","value","setValue","writers","id","tasks","openAction","action","orgId","runPlan","plan","done","outcome","attempted","writes","skipped","job","write","label","written","map","runCalls","call","each","batch","taskId","rest","handleComplete","open","status","taskIds","results","count","handleApply","assigneeUid","who","nameOf","reassigned","dueAtMs","kind","updatedAt","handleDelete","confirmed","description","confirmationText","confirmationButtonProps","color","then","catch","refused","noun","onClear","onDismissReport","extras","canApply","onClose","onApply","select","size","onChange","event","target","disabled","loading","error","Boolean","helperText","members","member","uid","type","slotProps","inputLabel","shrink","onClick","resource","selection"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;;AAEA;;;;;;;;;;;;;;;;CAgBC,GAED,SAASA,eAAe,EAAEC,oBAAoB,QAAQ,eAAc;AACpE,SAASC,sBAAsB,QAAQ,uBAAsB;AAC7D,SAASC,YAAY,EAAEC,OAAO,QAAQ,iCAAgC;AACtE,SAASC,MAAM,EAAEC,QAAQ,EAAEC,SAAS,QAAQ,gBAAe;AAC3D,SAASC,GAAG,EAAEC,eAAe,QAAQ,qBAAoB;AACzD,SAASC,WAAW,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AACtD,SAASC,eAAe,QAAQ,iCAA6B;AAG7D,SAASC,sBAAsB,QAAQ,gCAA4B;AACnE,SAGEC,cAAc,EACdC,eAAe,EACfC,eAAe,EACfC,gBAAgB,QACX,8BAA0B;AACjC,SACEC,eAAe,EACfC,gBAAgB,EAChBC,WAAW,EACXC,YAAY,QACP,uBAAmB;AAC1B,SAASC,gBAAgB,EAAEC,eAAe,QAAQ,0BAAsB;AACxE,SAASC,iBAAiB,EAAEC,iBAAiB,QAAQ,yBAAqB;AAC1E,SAEEC,eAAe,EACfC,kBAAkB,EAClBC,SAAS,QACJ,0BAAsB;AAC7B,SAASC,eAAe,QAAQ,4BAAwB;AACxD,SAASC,kBAAkB,QAAQ,wBAAoB;AAkBvD,MAAMC,OAAoB;IAAEC,UAAU;IAAQC,QAAQ;AAAQ;AAI9D,MAAMC,gBAA+C;IACnDC,QAAQ;IACRC,KAAK;AACP;AAEA,MAAMC,UAAU,CAACC,OAA6BA,KAAKC,KAAK,IAAID,KAAKE,GAAG;AAEpE,OAAO,SAASC,aAAaC,KAAwB;IACnD,IAAI,CAACA,MAAMC,QAAQ,CAACC,MAAM,EAAE,OAAO;IACnC,qBAAO,KAACC,+BAAqBH;AAC/B;AACAD,aAAaK,WAAW,GAAG;AAE3B,SAASD,iBAAiBH,KAAwB;cA4MlCK;IA3Md,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAEP,QAAQ,EAAEQ,gBAAgB,EAAEJ,SAAS,EAAE,GAAGL;IACvE,MAAMU,YAAYlD;IAClB,MAAM,EAAEmD,MAAMC,IAAI,EAAE,GAAGnD;IACvB,MAAM,EAAEoD,OAAO,EAAE,GAAGtD;IACpB,MAAM,EAAEuD,IAAI,EAAEC,MAAM,EAAEC,KAAK,EAAEC,aAAa,EAAE,GAAG/C,gBAAgB;QAAEgD,YAAY;IAAO;IAEpF,MAAMC,eAAenD,QAAQ;QAC3B,MAAMoD,SAAS,IAAIC,IAAIpB;QACvB,OAAOO,KAAKc,MAAM,CAAC,CAACC,MAAQH,OAAOI,GAAG,CAACD,IAAIzB,GAAG;IAChD,GAAG;QAACU;QAAMP;KAAS;IAEnB,MAAM,CAACwB,SAASC,WAAW,GAAGzD,SAA+B;IAC7D,MAAM,CAAC0D,OAAOC,SAAS,GAAG3D,SAAS;IAEnC,MAAM4D,UAAU7D,QACd,IACEI,eAAesC,WAAW,CAACoB;;mBACzBjE,IAAI6C,mBAAWH,yBAAAA,KAAO,CAAC,EAAE,mBAAI,iBAAQA,yBAAAA,KAAO,CAAC,EAAE,oBAAI,IAAIlD,gBAAgB0E,KAAK,EAAED;YAElF;QAACpB;QAAWH;KAAM;IAGpB,MAAMyB,aAAa,CAACC;QAClBL,SAAS;QACTF,WAAWO;IACb;IAEA,uEAAuE;IACvE,MAAMC,gBAAQ3B,yBAAAA,KAAO,CAAC,EAAE,mBAAI;IAE5B,MAAM4B,UAAUpE,YACd,OAAOqE,MAAmBC;QACxB,MAAMC,UAAU,MAAMtB,MAAM;YAC1BuB,WAAWH,KAAKI,MAAM,CAACtC,MAAM;YAC7BuC,SAASL,KAAKK,OAAO;YACrBC,KAAK,IAAMnE,iBAAiBsD,SAASO,KAAKI,MAAM,EAAE,CAACG,QAAUA,MAAMC,KAAK;YACxEP;QACF;QACA,iEAAiE;QACjE,uDAAuD;QACvD,MAAMQ,UAAU,IAAIxB,IAAIe,KAAKI,MAAM,CAACM,GAAG,CAAC,CAACH,QAAUA,MAAMb,EAAE;QAC3D,MAAM3D,uBACJyC,MACAhC,iBAAiB0B,QAAQ4B,QACzBf,aAAaG,MAAM,CAAC,CAAC1B,OAASiD,QAAQrB,GAAG,CAAC5B,KAAKE,GAAG;QAEpD,OAAOwC;IACT,GACA;QAACtB;QAAOa;QAASjB;QAAMN;QAAQ4B;QAAOf;KAAa;IAGrD;;;;GAIC,GACD,MAAM4B,WAAWhF,YACf,CACEgE,OACAiB,MAIAX,OAEArB,MAAM;YACJuB,WAAWR,MAAM7B,MAAM;YACvBuC,SAAS,EAAE;YACXC,KAAK,IACHpC,SACIhC,gBAAgByD,OAAOpC,SAASqD,KAAKC,IAAI,IACzC5E,gBACE0D,OACA,CAACnC,OAASA,KAAKE,GAAG,EAClBH,SACA,OAAOa,OACL,AAAC,CAAA,MAAMwC,KAAKE,KAAK,CAAC1C,KAAI,EAAGsC,GAAG,CAAC;4BAAC,EAAEK,MAAM,EAAW,OAANC;;;+BAAY;4BAAEtB,IAAIqB;2BAAWC;;YAElFf;QACF,IACF;QAACrB;QAAOV;KAAO;IAGjB;;;;GAIC,GACD,MAAM+C,iBAAiBtF,YAAY;QACjC,IAAI,CAACmE,OAAO;QACZ,MAAMoB,OAAOnC,aAAaG,MAAM,CAAC,CAAC1B,OAASA,KAAK2D,MAAM,KAAK;QAC3D,MAAMR,SACJO,MACA;YACEL,MAAM,CAACrD,OAASpB,gBAAgBoC,MAAM;oBAAEN,QAAQA;oBAAkB6C,QAAQvD,KAAKE,GAAG;gBAAC;YACnFoD,OAAO,OAAOnB,QACZ,AAAC,CAAA,MAAMtD,iBAAiBmC,MAAM;oBAAEsB;oBAAOsB,SAASzB,MAAMe,GAAG,CAAC,CAAClD,OAASA,KAAKE,GAAG;gBAAE,EAAC,EAC5E2D,OAAO;QACd,GACA,CAACC,QAAU,CAAC,UAAU,EAAExE,UAAUwE,OAAOrE,OAAO;IAEpD,GAAG;QAAC8B;QAAc4B;QAAUnC;QAAMN;QAAQ4B;KAAM;IAEhD,MAAMyB,cAAc5F,YAAY;QAC9B,IAAI,CAAC0D,WAAW,CAAClB,OAAO;QACxB,MAAM0B,SAASR;QACfC,WAAW;QACX,IAAIO,WAAW,UAAU;YACvB,MAAM2B,cAAcjC,SAAS;YAC7B,MAAMkC,MAAMD,cAAcvD,UAAUyD,MAAM,CAACF,eAAe;YAC1D,MAAMG,aAAa,CAACnE,OAAsB,CAAA;oBACxCuD,QAAQvD,KAAKE,GAAG;oBAChBF,MAAM,aAAKf,gBAAgBe;wBAAOgE;;gBACpC,CAAA;YACA,MAAMb,SACJ5B,cACA;gBACE8B,MAAM,CAACrD,OAASlB,YAAYkC,MAAM;wBAAEN,QAAQA;uBAAqByD,WAAWnE;gBAC5EsD,OAAO,OAAOnB,QACZ,AAAC,CAAA,MAAMpD,aAAaiC,MAAM;wBAAEsB,OAAO3B,KAAK,CAAC,EAAE;wBAAEwB,OAAOA,MAAMe,GAAG,CAACiB;oBAAY,EAAC,EAAGN,OAAO;YACzF,GACA,CAACC,QAAU,CAAC,SAAS,EAAExE,UAAUwE,OAAOrE,MAAM,IAAI,EAAEwE,KAAK;YAE3D;QACF;QACA,MAAMG,UAAUjF,kBAAkB4C;QAClC,MAAMa,SAAyBrB,aAAa2B,GAAG,CAAC,CAAClD,OAAU,CAAA;gBACzDkC,IAAIlC,KAAKE,GAAG;gBACZ8C,OAAOjD,QAAQC;gBACfqE,MAAM;gBACN,sEAAsE;gBACtE,iEAAiE;gBACjEtD,MAAM;oBAAEqD;oBAASE,WAAWpG;gBAAkB;YAChD,CAAA;QACA,MAAMqE,QACJ;YAAEK;YAAQC,SAAS,EAAE;QAAC,GACtB,CAACiB,QACCM,YAAY,OACR,CAAC,oBAAoB,EAAE9E,UAAUwE,OAAOrE,OAAO,GAC/C,CAAC,gBAAgB,EAAEH,UAAUwE,OAAOrE,OAAO;IAErD,GAAG;QAACoC;QAASlB;QAAOoB;QAAOtB;QAAWc;QAAc4B;QAAUnC;QAAMN;QAAQ6B;KAAQ;IAEpF,MAAMgC,eAAepG,YAAY;QAC/B,IAAI,CAACwC,SAAS,CAACY,aAAajB,MAAM,EAAE;QACpC,MAAMwD,QAAQvC,aAAajB,MAAM;QACjC,MAAMkE,YAAY,MAAMvD,QAAQ;YAC9BhB,OAAO6D,UAAU,IAAI,sBAAsB,CAAC,OAAO,EAAEA,MAAM,OAAO,CAAC;YACnEW,aACE,GAAGX,UAAU,IAAI,UAAU,WAAW,8BAA8B,CAAC,GACrE,wEACA;YACFY,kBAAkBZ,UAAU,IAAI,gBAAgB;YAChDa,yBAAyB;gBAAEC,OAAO;YAAQ;QAC5C,EACE,0DAA0D;SACzDC,IAAI,CAAC,IAAM,MACXC,KAAK,CAAC,IAAM;QACf,IAAI,CAACN,WAAW;QAChB,MAAM5B,SAAyBrB,aAAa2B,GAAG,CAAC,CAAClD,OAAU,CAAA;gBACzDkC,IAAIlC,KAAKE,GAAG;gBACZ8C,OAAOjD,QAAQC;gBACfqE,MAAM;YACR,CAAA;QACA,MAAM3B,UAAU,MAAMH,QACpB;YAAEK;YAAQC,SAAS,EAAE;QAAC,GACtB,CAACJ,OAAS,CAAC,QAAQ,EAAEnD,UAAUmD,MAAMhD,OAAO;QAE9C,MAAMsF,UAAU,IAAItD,IAAIiB,QAAQqC,OAAO,CAAC7B,GAAG,CAAC,CAACvB,MAAQA,IAAIqB,KAAK;QAC9DnC,iBACEU,aAAaG,MAAM,CAAC,CAAC1B,OAAS+E,QAAQnD,GAAG,CAAC7B,QAAQC,QAAQkD,GAAG,CAAC,CAAClD,OAASA,KAAKE,GAAG;IAEpF,GAAG;QAACS;QAAOY;QAAcN;QAASsB;QAAS1B;KAAiB;IAE5D,qBACE,MAACzB;QACC0E,OAAOzD,SAASC,MAAM;QACtB0E,MAAMvF;QACNyB,MAAMA;QACN+D,SAAS,IAAMpE,iBAAiB,EAAE;QAClCM,QAAQA;QACR+D,iBAAiB7D;QACjB8D,sBACE,KAAC9F;YACCqE,MAAM7B,YAAY;YAClB5B,OAAO4B,UAAUjC,aAAa,CAACiC,QAAQ,GAAG;YAC1CiC,OAAOzD,SAASC,MAAM;YACtB0E,MAAMvF;YACNyB,MAAMA;YACNkE,QAAQ;YACRC,SAAS,IAAMvD,WAAW;YAC1BwD,SAAS,IAAM,KAAKvB;sBAEnBlC,YAAY,yBACX,MAAC7D;gBACCuH,MAAM;gBACNC,MAAK;gBACLxC,OAAM;gBACNjB,OAAOA;gBACP0D,UAAU,CAACC,QAAU1D,SAAS0D,MAAMC,MAAM,CAAC5D,KAAK;gBAChD6D,UAAUnF,UAAUoF,OAAO;gBAC3BC,OAAOC,QAAQtF,UAAUqF,KAAK;gBAC9BE,UAAU,GACRvF,mBAAAA,UAAUqF,KAAK,YAAfrF,mBACCA,UAAUoF,OAAO,GACd,sBACA;;kCAGN,KAAC9H;wBAASgE,OAAM;kCAAI;;oBACnBtB,UAAUwF,OAAO,CAAC/C,GAAG,CAAC,CAACgD,uBACtB,KAACnI;4BAA0BgE,OAAOmE,OAAOC,GAAG;sCACzCzI,qBAAqBwI;2BADTA,OAAOC,GAAG;;iBAK3BtE,YAAY,sBACd,KAAC7D;gBACCwH,MAAK;gBACLY,MAAK;gBACLpD,OAAM;gBACNjB,OAAOA;gBACP0D,UAAU,CAACC,QAAU1D,SAAS0D,MAAMC,MAAM,CAAC5D,KAAK;gBAChDiE,YAAW;gBACXK,WAAW;oBAAEC,YAAY;wBAAEC,QAAQ;oBAAK;gBAAE;iBAE1C;;;0BAIR,KAACzI;gBAAO0H,MAAK;gBAAQI,UAAU1E,QAAQ,CAACP;gBAAO6F,SAAS,IAAM,KAAK/C;0BAChE;;0BAEH,KAAC3F;gBAAO0H,MAAK;gBAAQI,UAAU1E,QAAQ,CAACP;gBAAO6F,SAAS,IAAMpE,WAAW;0BACtE;;0BAEH,KAACtE;gBACC0H,MAAK;gBACLI,UAAU1E,QAAQ,CAACP;gBACnB6F,SAAS;wBAIoBjF;oBAH3Ba,WAAW;oBACX,8DAA8D;oBAC9D,wBAAwB;oBACxBJ,SAAS9C,mBAAkBqC,iBAAAA,YAAY,CAAC,EAAE,qBAAfA,eAAiB6C,OAAO;gBACrD;0BAEC;;0BAGH,KAAC7E;gBACCkH,UAAUjH;gBACVkB,QAAQA;gBACRgG,WAAWnF,aAAa2B,GAAG,CAAC,CAACvB,MAAQA,IAAIzB,GAAG;gBAC5C0F,UAAU1E;;0BAEZ,KAACpD;gBACC0H,MAAK;gBACLZ,OAAM;gBACNgB,UAAU1E,QAAQ,CAACP;gBACnB6F,SAAS,IAAM,KAAKjC;0BAEnB;;;;AAIT;AACAhE,iBAAiBC,WAAW,GAAG;AAE/B,eAAeL,aAAY"}
@@ -1,3 +1,4 @@
1
+ import { type CrmTaskPicklists } from '@aglyn/aglyn';
1
2
  import type { CrmTaskRow } from '../hooks/use-crm-tasks';
2
3
  export interface TasksCalendarProps {
3
4
  /** The window the list is holding — the calendar reads no more than it. */
@@ -6,6 +7,8 @@ export interface TasksCalendarProps {
6
7
  onOpen: (task: CrmTaskRow) => void;
7
8
  /** The list's window filled, so neither surface is showing everything. */
8
9
  truncated?: boolean;
10
+ /** The org's task lists, which name each entry's type and status on hover (AGL-3517). */
11
+ picklists?: CrmTaskPicklists;
9
12
  }
10
13
  /**
11
14
  * A MONTH OF TASKS, BY DUE DATE (AGL-2662).
@@ -15,6 +15,7 @@
15
15
  * limitations under the License.
16
16
  */ 'use client';
17
17
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
+ import { crmTaskPicklistLabels } from "@aglyn/aglyn";
18
19
  import { mdiChevronLeft, mdiChevronRight } from "@aglyn/shared-data-mdi";
19
20
  import { MdiIcon } from "@aglyn/shared-ui-jsx";
20
21
  import { Box, Button, ButtonBase, IconButton, Stack, Typography } from "@mui/material";
@@ -45,7 +46,12 @@ import { bucketTasksByCalendarDay, CALENDAR_DAY_LABELS, CALENDAR_WEEK_DAYS, shif
45
46
  * scheduling library for one surface is a dependency the whole console
46
47
  * would carry.
47
48
  */ export function TasksCalendar(props) {
48
- const { tasks, onOpen, truncated } = props;
49
+ const { tasks, onOpen, truncated, picklists } = props;
50
+ /** "Call Ada · Call · In Progress" — the entry's type and status on hover. */ const hoverText = (task)=>{
51
+ if (!picklists) return task.title;
52
+ const labels = crmTaskPicklistLabels(task, picklists);
53
+ return `${task.title} · ${labels.type} · ${labels.status}`;
54
+ };
49
55
  /*
50
56
  * The clock is read ONCE, at mount. A component that read `Date.now()`
51
57
  * per render would move the today square under a reader who left the tab
@@ -173,6 +179,7 @@ import { bucketTasksByCalendarDay, CALENDAR_DAY_LABELS, CALENDAR_WEEK_DAYS, shif
173
179
  children: [
174
180
  shown.map((task)=>/*#__PURE__*/ _jsx(ButtonBase, {
175
181
  onClick: ()=>onOpen(task),
182
+ title: hoverText(task),
176
183
  sx: {
177
184
  justifyContent: 'flex-start',
178
185
  width: '100%',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/tasks-calendar.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { mdiChevronLeft, mdiChevronRight } from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { Box, Button, ButtonBase, IconButton, Stack, Typography } from '@mui/material'\nimport { useMemo, useState } from 'react'\nimport type { CrmTaskRow } from '../hooks/use-crm-tasks'\nimport {\n bucketTasksByCalendarDay,\n CALENDAR_DAY_LABELS,\n CALENDAR_WEEK_DAYS,\n shiftCalendarMonth,\n taskCalendarMonth,\n} from '../model/task-calendar'\n\n/** How many tasks a square lists before folding the rest into a count. */\nconst TASKS_PER_DAY = 3\n\nexport interface TasksCalendarProps {\n /** The window the list is holding — the calendar reads no more than it. */\n tasks: readonly CrmTaskRow[]\n /** Open one task's drawer, the same drawer a row opens. */\n onOpen: (task: CrmTaskRow) => void\n /** The list's window filled, so neither surface is showing everything. */\n truncated?: boolean\n}\n\n/**\n * A MONTH OF TASKS, BY DUE DATE (AGL-2662).\n *\n * The Tasks list answers \"what is on my plate\"; this answers \"what does\n * next week look like\", which a list ordered by due date can only imply.\n *\n * ## Drawn over the list's own window, and never over a second read\n *\n * The rows are the ones the section already holds. A calendar that fetched\n * its own month would be a second listener over the same collection, would\n * disagree with the list whenever the two windows differed, and would put\n * a read behind every page of the arrows. What it costs instead is honesty:\n * the grid can only place what the window carries, so the tasks due in\n * other months are counted under it rather than implied to be absent.\n *\n * ## Hand-built rather than a calendar dependency\n *\n * Seven columns of MUI boxes and the local-day arithmetic in\n * `task-calendar.ts`. The one calendar package already installed\n * (`@mui/x-date-pickers`) draws a date PICKER — a grid whose squares are\n * choices, not content — so it answers a different question, and a\n * scheduling library for one surface is a dependency the whole console\n * would carry.\n */\nexport function TasksCalendar(props: TasksCalendarProps) {\n const { tasks, onOpen, truncated } = props\n /*\n * The clock is read ONCE, at mount. A component that read `Date.now()`\n * per render would move the today square under a reader who left the tab\n * open across midnight, without any state having changed — and the grid\n * is a pure function of this, so what is drawn can be pinned.\n */\n const [nowMs] = useState(() => Date.now())\n const [anchorMs, setAnchorMs] = useState(() => nowMs)\n\n const month = useMemo(\n () => taskCalendarMonth(anchorMs, nowMs),\n [anchorMs, nowMs],\n )\n const buckets = useMemo(\n () => bucketTasksByCalendarDay(tasks, (task) => task.dueAtMs, month),\n [tasks, month],\n )\n const label = useMemo(\n () =>\n month.monthDate.toLocaleDateString(undefined, {\n month: 'long',\n year: 'numeric',\n }),\n [month],\n )\n\n return (\n <Stack spacing={1.5}>\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}\n >\n <IconButton\n size=\"small\"\n aria-label=\"Previous month\"\n onClick={() => setAnchorMs((current) => shiftCalendarMonth(current, -1))}\n >\n <MdiIcon path={mdiChevronLeft.path} size={0.9} />\n </IconButton>\n <Typography variant=\"subtitle1\" sx={{ minWidth: 160, textAlign: 'center' }}>\n {label}\n </Typography>\n <IconButton\n size=\"small\"\n aria-label=\"Next month\"\n onClick={() => setAnchorMs((current) => shiftCalendarMonth(current, 1))}\n >\n <MdiIcon path={mdiChevronRight.path} size={0.9} />\n </IconButton>\n <Button size=\"small\" onClick={() => setAnchorMs(nowMs)}>\n {'Today'}\n </Button>\n </Stack>\n\n <Box sx={{ overflowX: 'auto' }}>\n <Box sx={{ minWidth: 640 }}>\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: `repeat(${CALENDAR_WEEK_DAYS}, 1fr)`,\n gap: 0.5,\n mb: 0.5,\n }}\n >\n {CALENDAR_DAY_LABELS.map((day) => (\n <Typography\n key={day}\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ textAlign: 'center' }}\n >\n {day}\n </Typography>\n ))}\n </Box>\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: `repeat(${CALENDAR_WEEK_DAYS}, 1fr)`,\n gap: 0.5,\n }}\n >\n {month.weeks.flat().map((day) => {\n const held = buckets.byDay.get(day.startMs) ?? []\n const shown = held.slice(0, TASKS_PER_DAY)\n const folded = held.length - shown.length\n return (\n <Box\n key={day.startMs}\n sx={{\n minHeight: 96,\n p: 0.75,\n borderRadius: 1,\n border: 1,\n borderColor: day.isToday ? 'primary.main' : 'divider',\n bgcolor: day.inMonth ? 'background.paper' : 'action.hover',\n }}\n >\n <Typography\n variant=\"caption\"\n sx={{\n display: 'block',\n mb: 0.5,\n fontWeight: day.isToday ? 'fontWeightBold' : undefined,\n color: day.inMonth ? 'text.primary' : 'text.disabled',\n }}\n >\n {day.date}\n </Typography>\n <Stack spacing={0.25}>\n {shown.map((task) => (\n <ButtonBase\n key={task.$id}\n onClick={() => onOpen(task)}\n sx={{\n justifyContent: 'flex-start',\n width: '100%',\n px: 0.5,\n py: 0.25,\n borderRadius: 0.5,\n bgcolor: 'action.selected',\n '&:hover': { bgcolor: 'action.focus' },\n }}\n >\n <Typography\n variant=\"caption\"\n noWrap\n sx={{\n width: '100%',\n textAlign: 'left',\n textDecoration:\n task.status === 'done' ? 'line-through' : undefined,\n color:\n task.status === 'done'\n ? 'text.secondary'\n : day.endMs <= nowMs\n ? 'error.main'\n : 'text.primary',\n }}\n >\n {task.title}\n </Typography>\n </ButtonBase>\n ))}\n {folded > 0 ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`+${folded} more`}\n </Typography>\n ) : null}\n </Stack>\n </Box>\n )\n })}\n </Box>\n </Box>\n </Box>\n\n {/*\n What the grid could not place. Said plainly, because a month with\n nothing on it reads as \"nothing is due\" and the honest reading here\n is often \"the window's tasks are somewhere else\".\n */}\n {buckets.undated.length || buckets.elsewhere.length || truncated ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {[\n buckets.elsewhere.length\n ? `${buckets.elsewhere.length} due outside this month`\n : '',\n buckets.undated.length\n ? `${buckets.undated.length} with no due date`\n : '',\n truncated ? 'and the view is showing only its first page' : '',\n ]\n .filter(Boolean)\n .join(' · ')}\n </Typography>\n ) : null}\n </Stack>\n )\n}\nTasksCalendar.displayName = 'TasksCalendar'\n\nexport default TasksCalendar\n"],"names":["mdiChevronLeft","mdiChevronRight","MdiIcon","Box","Button","ButtonBase","IconButton","Stack","Typography","useMemo","useState","bucketTasksByCalendarDay","CALENDAR_DAY_LABELS","CALENDAR_WEEK_DAYS","shiftCalendarMonth","taskCalendarMonth","TASKS_PER_DAY","TasksCalendar","props","tasks","onOpen","truncated","nowMs","Date","now","anchorMs","setAnchorMs","month","buckets","task","dueAtMs","label","monthDate","toLocaleDateString","undefined","year","spacing","direction","sx","alignItems","flexWrap","rowGap","size","aria-label","onClick","current","path","variant","minWidth","textAlign","overflowX","display","gridTemplateColumns","gap","mb","map","day","color","weeks","flat","held","byDay","get","startMs","shown","slice","folded","length","minHeight","p","borderRadius","border","borderColor","isToday","bgcolor","inMonth","fontWeight","date","justifyContent","width","px","py","noWrap","textDecoration","status","endMs","title","$id","undated","elsewhere","filter","Boolean","join","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/tasks-calendar.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { type CrmTaskPicklists, crmTaskPicklistLabels } from '@aglyn/aglyn'\nimport { mdiChevronLeft, mdiChevronRight } from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { Box, Button, ButtonBase, IconButton, Stack, Typography } from '@mui/material'\nimport { useMemo, useState } from 'react'\nimport type { CrmTaskRow } from '../hooks/use-crm-tasks'\nimport {\n bucketTasksByCalendarDay,\n CALENDAR_DAY_LABELS,\n CALENDAR_WEEK_DAYS,\n shiftCalendarMonth,\n taskCalendarMonth,\n} from '../model/task-calendar'\n\n/** How many tasks a square lists before folding the rest into a count. */\nconst TASKS_PER_DAY = 3\n\nexport interface TasksCalendarProps {\n /** The window the list is holding — the calendar reads no more than it. */\n tasks: readonly CrmTaskRow[]\n /** Open one task's drawer, the same drawer a row opens. */\n onOpen: (task: CrmTaskRow) => void\n /** The list's window filled, so neither surface is showing everything. */\n truncated?: boolean\n /** The org's task lists, which name each entry's type and status on hover (AGL-3517). */\n picklists?: CrmTaskPicklists\n}\n\n/**\n * A MONTH OF TASKS, BY DUE DATE (AGL-2662).\n *\n * The Tasks list answers \"what is on my plate\"; this answers \"what does\n * next week look like\", which a list ordered by due date can only imply.\n *\n * ## Drawn over the list's own window, and never over a second read\n *\n * The rows are the ones the section already holds. A calendar that fetched\n * its own month would be a second listener over the same collection, would\n * disagree with the list whenever the two windows differed, and would put\n * a read behind every page of the arrows. What it costs instead is honesty:\n * the grid can only place what the window carries, so the tasks due in\n * other months are counted under it rather than implied to be absent.\n *\n * ## Hand-built rather than a calendar dependency\n *\n * Seven columns of MUI boxes and the local-day arithmetic in\n * `task-calendar.ts`. The one calendar package already installed\n * (`@mui/x-date-pickers`) draws a date PICKER — a grid whose squares are\n * choices, not content — so it answers a different question, and a\n * scheduling library for one surface is a dependency the whole console\n * would carry.\n */\nexport function TasksCalendar(props: TasksCalendarProps) {\n const { tasks, onOpen, truncated, picklists } = props\n /** \"Call Ada · Call · In Progress\" — the entry's type and status on hover. */\n const hoverText = (task: CrmTaskRow) => {\n if (!picklists) return task.title\n const labels = crmTaskPicklistLabels(task, picklists)\n return `${task.title} · ${labels.type} · ${labels.status}`\n }\n /*\n * The clock is read ONCE, at mount. A component that read `Date.now()`\n * per render would move the today square under a reader who left the tab\n * open across midnight, without any state having changed — and the grid\n * is a pure function of this, so what is drawn can be pinned.\n */\n const [nowMs] = useState(() => Date.now())\n const [anchorMs, setAnchorMs] = useState(() => nowMs)\n\n const month = useMemo(\n () => taskCalendarMonth(anchorMs, nowMs),\n [anchorMs, nowMs],\n )\n const buckets = useMemo(\n () => bucketTasksByCalendarDay(tasks, (task) => task.dueAtMs, month),\n [tasks, month],\n )\n const label = useMemo(\n () =>\n month.monthDate.toLocaleDateString(undefined, {\n month: 'long',\n year: 'numeric',\n }),\n [month],\n )\n\n return (\n <Stack spacing={1.5}>\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}\n >\n <IconButton\n size=\"small\"\n aria-label=\"Previous month\"\n onClick={() => setAnchorMs((current) => shiftCalendarMonth(current, -1))}\n >\n <MdiIcon path={mdiChevronLeft.path} size={0.9} />\n </IconButton>\n <Typography variant=\"subtitle1\" sx={{ minWidth: 160, textAlign: 'center' }}>\n {label}\n </Typography>\n <IconButton\n size=\"small\"\n aria-label=\"Next month\"\n onClick={() => setAnchorMs((current) => shiftCalendarMonth(current, 1))}\n >\n <MdiIcon path={mdiChevronRight.path} size={0.9} />\n </IconButton>\n <Button size=\"small\" onClick={() => setAnchorMs(nowMs)}>\n {'Today'}\n </Button>\n </Stack>\n\n <Box sx={{ overflowX: 'auto' }}>\n <Box sx={{ minWidth: 640 }}>\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: `repeat(${CALENDAR_WEEK_DAYS}, 1fr)`,\n gap: 0.5,\n mb: 0.5,\n }}\n >\n {CALENDAR_DAY_LABELS.map((day) => (\n <Typography\n key={day}\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ textAlign: 'center' }}\n >\n {day}\n </Typography>\n ))}\n </Box>\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: `repeat(${CALENDAR_WEEK_DAYS}, 1fr)`,\n gap: 0.5,\n }}\n >\n {month.weeks.flat().map((day) => {\n const held = buckets.byDay.get(day.startMs) ?? []\n const shown = held.slice(0, TASKS_PER_DAY)\n const folded = held.length - shown.length\n return (\n <Box\n key={day.startMs}\n sx={{\n minHeight: 96,\n p: 0.75,\n borderRadius: 1,\n border: 1,\n borderColor: day.isToday ? 'primary.main' : 'divider',\n bgcolor: day.inMonth ? 'background.paper' : 'action.hover',\n }}\n >\n <Typography\n variant=\"caption\"\n sx={{\n display: 'block',\n mb: 0.5,\n fontWeight: day.isToday ? 'fontWeightBold' : undefined,\n color: day.inMonth ? 'text.primary' : 'text.disabled',\n }}\n >\n {day.date}\n </Typography>\n <Stack spacing={0.25}>\n {shown.map((task) => (\n <ButtonBase\n key={task.$id}\n onClick={() => onOpen(task)}\n title={hoverText(task)}\n sx={{\n justifyContent: 'flex-start',\n width: '100%',\n px: 0.5,\n py: 0.25,\n borderRadius: 0.5,\n bgcolor: 'action.selected',\n '&:hover': { bgcolor: 'action.focus' },\n }}\n >\n <Typography\n variant=\"caption\"\n noWrap\n sx={{\n width: '100%',\n textAlign: 'left',\n textDecoration:\n task.status === 'done' ? 'line-through' : undefined,\n color:\n task.status === 'done'\n ? 'text.secondary'\n : day.endMs <= nowMs\n ? 'error.main'\n : 'text.primary',\n }}\n >\n {task.title}\n </Typography>\n </ButtonBase>\n ))}\n {folded > 0 ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`+${folded} more`}\n </Typography>\n ) : null}\n </Stack>\n </Box>\n )\n })}\n </Box>\n </Box>\n </Box>\n\n {/*\n What the grid could not place. Said plainly, because a month with\n nothing on it reads as \"nothing is due\" and the honest reading here\n is often \"the window's tasks are somewhere else\".\n */}\n {buckets.undated.length || buckets.elsewhere.length || truncated ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {[\n buckets.elsewhere.length\n ? `${buckets.elsewhere.length} due outside this month`\n : '',\n buckets.undated.length\n ? `${buckets.undated.length} with no due date`\n : '',\n truncated ? 'and the view is showing only its first page' : '',\n ]\n .filter(Boolean)\n .join(' · ')}\n </Typography>\n ) : null}\n </Stack>\n )\n}\nTasksCalendar.displayName = 'TasksCalendar'\n\nexport default TasksCalendar\n"],"names":["crmTaskPicklistLabels","mdiChevronLeft","mdiChevronRight","MdiIcon","Box","Button","ButtonBase","IconButton","Stack","Typography","useMemo","useState","bucketTasksByCalendarDay","CALENDAR_DAY_LABELS","CALENDAR_WEEK_DAYS","shiftCalendarMonth","taskCalendarMonth","TASKS_PER_DAY","TasksCalendar","props","tasks","onOpen","truncated","picklists","hoverText","task","title","labels","type","status","nowMs","Date","now","anchorMs","setAnchorMs","month","buckets","dueAtMs","label","monthDate","toLocaleDateString","undefined","year","spacing","direction","sx","alignItems","flexWrap","rowGap","size","aria-label","onClick","current","path","variant","minWidth","textAlign","overflowX","display","gridTemplateColumns","gap","mb","map","day","color","weeks","flat","held","byDay","get","startMs","shown","slice","folded","length","minHeight","p","borderRadius","border","borderColor","isToday","bgcolor","inMonth","fontWeight","date","justifyContent","width","px","py","noWrap","textDecoration","endMs","$id","undated","elsewhere","filter","Boolean","join","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA,SAAgCA,qBAAqB,QAAQ,eAAc;AAC3E,SAASC,cAAc,EAAEC,eAAe,QAAQ,yBAAwB;AACxE,SAASC,OAAO,QAAQ,uBAAsB;AAC9C,SAASC,GAAG,EAAEC,MAAM,EAAEC,UAAU,EAAEC,UAAU,EAAEC,KAAK,EAAEC,UAAU,QAAQ,gBAAe;AACtF,SAASC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AAEzC,SACEC,wBAAwB,EACxBC,mBAAmB,EACnBC,kBAAkB,EAClBC,kBAAkB,EAClBC,iBAAiB,QACZ,4BAAwB;AAE/B,wEAAwE,GACxE,MAAMC,gBAAgB;AAatB;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GACD,OAAO,SAASC,cAAcC,KAAyB;IACrD,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAE,GAAGJ;IAChD,4EAA4E,GAC5E,MAAMK,YAAY,CAACC;QACjB,IAAI,CAACF,WAAW,OAAOE,KAAKC,KAAK;QACjC,MAAMC,SAAS3B,sBAAsByB,MAAMF;QAC3C,OAAO,GAAGE,KAAKC,KAAK,CAAC,GAAG,EAAEC,OAAOC,IAAI,CAAC,GAAG,EAAED,OAAOE,MAAM,EAAE;IAC5D;IACA;;;;;GAKC,GACD,MAAM,CAACC,MAAM,GAAGnB,SAAS,IAAMoB,KAAKC,GAAG;IACvC,MAAM,CAACC,UAAUC,YAAY,GAAGvB,SAAS,IAAMmB;IAE/C,MAAMK,QAAQzB,QACZ,IAAMM,kBAAkBiB,UAAUH,QAClC;QAACG;QAAUH;KAAM;IAEnB,MAAMM,UAAU1B,QACd,IAAME,yBAAyBQ,OAAO,CAACK,OAASA,KAAKY,OAAO,EAAEF,QAC9D;QAACf;QAAOe;KAAM;IAEhB,MAAMG,QAAQ5B,QACZ,IACEyB,MAAMI,SAAS,CAACC,kBAAkB,CAACC,WAAW;YAC5CN,OAAO;YACPO,MAAM;QACR,IACF;QAACP;KAAM;IAGT,qBACE,MAAC3B;QAAMmC,SAAS;;0BACd,MAACnC;gBACCoC,WAAU;gBACVD,SAAS;gBACTE,IAAI;oBAAEC,YAAY;oBAAUC,UAAU;oBAAQC,QAAQ;gBAAE;;kCAExD,KAACzC;wBACC0C,MAAK;wBACLC,cAAW;wBACXC,SAAS,IAAMjB,YAAY,CAACkB,UAAYrC,mBAAmBqC,SAAS,CAAC;kCAErE,cAAA,KAACjD;4BAAQkD,MAAMpD,eAAeoD,IAAI;4BAAEJ,MAAM;;;kCAE5C,KAACxC;wBAAW6C,SAAQ;wBAAYT,IAAI;4BAAEU,UAAU;4BAAKC,WAAW;wBAAS;kCACtElB;;kCAEH,KAAC/B;wBACC0C,MAAK;wBACLC,cAAW;wBACXC,SAAS,IAAMjB,YAAY,CAACkB,UAAYrC,mBAAmBqC,SAAS;kCAEpE,cAAA,KAACjD;4BAAQkD,MAAMnD,gBAAgBmD,IAAI;4BAAEJ,MAAM;;;kCAE7C,KAAC5C;wBAAO4C,MAAK;wBAAQE,SAAS,IAAMjB,YAAYJ;kCAC7C;;;;0BAIL,KAAC1B;gBAAIyC,IAAI;oBAAEY,WAAW;gBAAO;0BAC3B,cAAA,MAACrD;oBAAIyC,IAAI;wBAAEU,UAAU;oBAAI;;sCACvB,KAACnD;4BACCyC,IAAI;gCACFa,SAAS;gCACTC,qBAAqB,CAAC,OAAO,EAAE7C,mBAAmB,MAAM,CAAC;gCACzD8C,KAAK;gCACLC,IAAI;4BACN;sCAEChD,oBAAoBiD,GAAG,CAAC,CAACC,oBACxB,KAACtD;oCAEC6C,SAAQ;oCACRU,OAAM;oCACNnB,IAAI;wCAAEW,WAAW;oCAAS;8CAEzBO;mCALIA;;sCASX,KAAC3D;4BACCyC,IAAI;gCACFa,SAAS;gCACTC,qBAAqB,CAAC,OAAO,EAAE7C,mBAAmB,MAAM,CAAC;gCACzD8C,KAAK;4BACP;sCAECzB,MAAM8B,KAAK,CAACC,IAAI,GAAGJ,GAAG,CAAC,CAACC;oCACV3B;gCAAb,MAAM+B,QAAO/B,qBAAAA,QAAQgC,KAAK,CAACC,GAAG,CAACN,IAAIO,OAAO,aAA7BlC,qBAAkC,EAAE;gCACjD,MAAMmC,QAAQJ,KAAKK,KAAK,CAAC,GAAGvD;gCAC5B,MAAMwD,SAASN,KAAKO,MAAM,GAAGH,MAAMG,MAAM;gCACzC,qBACE,MAACtE;oCAECyC,IAAI;wCACF8B,WAAW;wCACXC,GAAG;wCACHC,cAAc;wCACdC,QAAQ;wCACRC,aAAahB,IAAIiB,OAAO,GAAG,iBAAiB;wCAC5CC,SAASlB,IAAImB,OAAO,GAAG,qBAAqB;oCAC9C;;sDAEA,KAACzE;4CACC6C,SAAQ;4CACRT,IAAI;gDACFa,SAAS;gDACTG,IAAI;gDACJsB,YAAYpB,IAAIiB,OAAO,GAAG,mBAAmBvC;gDAC7CuB,OAAOD,IAAImB,OAAO,GAAG,iBAAiB;4CACxC;sDAECnB,IAAIqB,IAAI;;sDAEX,MAAC5E;4CAAMmC,SAAS;;gDACb4B,MAAMT,GAAG,CAAC,CAACrC,qBACV,KAACnB;wDAEC6C,SAAS,IAAM9B,OAAOI;wDACtBC,OAAOF,UAAUC;wDACjBoB,IAAI;4DACFwC,gBAAgB;4DAChBC,OAAO;4DACPC,IAAI;4DACJC,IAAI;4DACJX,cAAc;4DACdI,SAAS;4DACT,WAAW;gEAAEA,SAAS;4DAAe;wDACvC;kEAEA,cAAA,KAACxE;4DACC6C,SAAQ;4DACRmC,MAAM;4DACN5C,IAAI;gEACFyC,OAAO;gEACP9B,WAAW;gEACXkC,gBACEjE,KAAKI,MAAM,KAAK,SAAS,iBAAiBY;gEAC5CuB,OACEvC,KAAKI,MAAM,KAAK,SACZ,mBACAkC,IAAI4B,KAAK,IAAI7D,QACX,eACA;4DACV;sEAECL,KAAKC,KAAK;;uDA7BRD,KAAKmE,GAAG;gDAiChBnB,SAAS,kBACR,KAAChE;oDAAW6C,SAAQ;oDAAUU,OAAM;8DACjC,CAAC,CAAC,EAAES,OAAO,KAAK,CAAC;qDAElB;;;;mCA7DDV,IAAIO,OAAO;4BAiEtB;;;;;YAULlC,QAAQyD,OAAO,CAACnB,MAAM,IAAItC,QAAQ0D,SAAS,CAACpB,MAAM,IAAIpD,0BACrD,KAACb;gBAAW6C,SAAQ;gBAAUU,OAAM;0BACjC;oBACC5B,QAAQ0D,SAAS,CAACpB,MAAM,GACpB,GAAGtC,QAAQ0D,SAAS,CAACpB,MAAM,CAAC,uBAAuB,CAAC,GACpD;oBACJtC,QAAQyD,OAAO,CAACnB,MAAM,GAClB,GAAGtC,QAAQyD,OAAO,CAACnB,MAAM,CAAC,iBAAiB,CAAC,GAC5C;oBACJpD,YAAY,gDAAgD;iBAC7D,CACEyE,MAAM,CAACC,SACPC,IAAI,CAAC;iBAER;;;AAGV;AACA/E,cAAcgF,WAAW,GAAG;AAE5B,eAAehF,cAAa"}
@@ -16,9 +16,9 @@ import { type ConsolePluginPageProps } from '@aglyn/aglyn';
16
16
  *
17
17
  * The rows are selectable, and a selection raises `TasksBulkBar` over the
18
18
  * list — Complete and Assign through their routes, the due date and the
19
- * delete as batched writes (AGL-2621). Export CSV beside the view control
20
- * writes the view through `tasksCsv()`, naming the assignee and the linked
21
- * records; the bar writes the same file over the selection.
19
+ * delete as batched writes (AGL-2621). Import and Export open the console's
20
+ * wizard and dialog on `crm.tasks` (AGL-3528); the export reads the view's
21
+ * own query, and the bar opens it on the selection.
22
22
  */
23
23
  export declare function TasksSection(props: ConsolePluginPageProps): import("react").JSX.Element;
24
24
  export declare namespace TasksSection {
@@ -16,7 +16,7 @@
16
16
  */ 'use client';
17
17
  import { _ as _extends } from "@swc/helpers/_/_extends";
18
18
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
19
- import { CRM_COLLECTIONS, findOrgMember, pluginDocsHelp } from "@aglyn/aglyn";
19
+ import { CRM_COLLECTIONS, crmPicklistShownLabel, crmTaskPicklistLabels, crmTaskStatusWrite, pluginDocsHelp } from "@aglyn/aglyn";
20
20
  import { CardDisplay } from "@aglyn/shared-ui-jsx";
21
21
  import { ListTable } from "@aglyn/shared-ui-jsx/components/list-table.component";
22
22
  import { useCrmSavedView } from "../hooks/use-crm-saved-view.js";
@@ -32,13 +32,12 @@ import { useCallback, useEffect, useMemo, useState } from "react";
32
32
  import { useCrmRecordNames } from "../hooks/use-crm-record-names.js";
33
33
  import { useCrmTaskList, useNowMs } from "../hooks/use-crm-tasks.js";
34
34
  import { useOrgMemberDirectory } from "../hooks/use-org-member-directory.js";
35
- import { downloadTextFile } from "../model/contacts-csv.js";
35
+ import { useCrmTaskPicklists } from "../hooks/use-crm-task-picklists.js";
36
36
  import { crmRoutes } from "../model/crm-routes.js";
37
37
  import { refreshCrmNextActivity } from "../model/next-activity-api.js";
38
38
  import { completeCrmTask } from "../model/task-api.js";
39
39
  import { crmTaskCallScope } from "../model/task-routes.js";
40
- import { tasksCsv } from "../model/tasks-csv.js";
41
- import { CRM_TASK_KIND_LABELS, CRM_TASK_KINDS, CRM_TASK_PRIORITIES, CRM_TASK_PRIORITY_LABELS, CRM_TASK_VIEWS, TASK_LIST_QUERY_FIELDS } from "../model/task-views.js";
40
+ import { CRM_TASK_KINDS, CRM_TASK_PRIORITIES, CRM_TASK_VIEWS, TASK_LIST_QUERY_FIELDS } from "../model/task-views.js";
42
41
  import { listFilterGridColumns } from "@aglyn/shared-ui-jsx/const/list-grid-filter";
43
42
  import { ListPagination } from "@aglyn/shared-ui-jsx/components/list-pagination.component";
44
43
  import { TABLE_PAGE_SIZE_DEFAULT } from "@aglyn/shared-ui-jsx/const/table-pagination";
@@ -49,7 +48,8 @@ import { CrmListActions, CrmListToolbar } from "./crm-list-toolbar.js";
49
48
  import { TaskDueText, TaskKindCell, TaskPriorityChip, TaskRecordLink } from "./task-cells.js";
50
49
  import TaskEditDrawer from "./task-edit-drawer.js";
51
50
  import TasksCalendar from "./tasks-calendar.js";
52
- import { TaskImportButton } from "./task-import-drawer.js";
51
+ import { CrmExportButton, CrmImportButton } from "./crm-transfer-buttons.js";
52
+ import { CRM_TASKS_RESOURCE } from "../transfer/fields.js";
53
53
  import TaskSnoozeMenu from "./task-snooze-menu.js";
54
54
  import TasksBulkBar from "./tasks-bulk-bar.js";
55
55
  /** What an empty view is headed, by view — "nothing overdue" is good news. */ /*
@@ -70,7 +70,7 @@ import TasksBulkBar from "./tasks-bulk-bar.js";
70
70
  ];
71
71
  const TASK_FILTER_HEADERS = {
72
72
  view: 'Show',
73
- kind: 'Kind',
73
+ kind: 'Type',
74
74
  priority: 'Priority',
75
75
  assigneeUid: 'Assignee'
76
76
  };
@@ -116,9 +116,9 @@ const EMPTY_LABEL = {
116
116
  *
117
117
  * The rows are selectable, and a selection raises `TasksBulkBar` over the
118
118
  * list — Complete and Assign through their routes, the due date and the
119
- * delete as batched writes (AGL-2621). Export CSV beside the view control
120
- * writes the view through `tasksCsv()`, naming the assignee and the linked
121
- * records; the bar writes the same file over the selection.
119
+ * delete as batched writes (AGL-2621). Import and Export open the console's
120
+ * wizard and dialog on `crm.tasks` (AGL-3528); the export reads the view's
121
+ * own query, and the bar opens it on the selection.
122
122
  */ export function TasksSection(props) {
123
123
  var _ref;
124
124
  const { hostId, org, basePath = '' } = props;
@@ -194,25 +194,31 @@ const EMPTY_LABEL = {
194
194
  });
195
195
  const { tasks, status, fromCache, scope, orgId, readTokens } = list;
196
196
  const directory = useOrgMemberDirectory(orgId);
197
- const filterOptions = useMemo(()=>({
197
+ const picklists = useCrmTaskPicklists(orgId);
198
+ /*
199
+ * Type and Priority filter on the MEANING the query holds (AGL-3517), so
200
+ * each option is a meaning, named by the org's label for it.
201
+ */ const filterOptions = useMemo(()=>({
198
202
  view: CRM_TASK_VIEWS.map((option)=>({
199
203
  value: option.id,
200
204
  label: option.label
201
205
  })),
202
206
  kind: CRM_TASK_KINDS.map((kind)=>({
203
207
  value: kind,
204
- label: CRM_TASK_KIND_LABELS[kind]
208
+ label: crmPicklistShownLabel(picklists.type, kind, null)
205
209
  })),
206
210
  priority: CRM_TASK_PRIORITIES.map((priority)=>({
207
211
  value: priority,
208
- label: CRM_TASK_PRIORITY_LABELS[priority]
212
+ label: crmPicklistShownLabel(picklists.priority, priority, null)
209
213
  })),
210
214
  assigneeUid: directory.members.map((member)=>({
211
215
  value: member.uid,
212
216
  label: member.label
213
217
  }))
214
218
  }), [
215
- directory.members
219
+ directory.members,
220
+ picklists.type,
221
+ picklists.priority
216
222
  ]);
217
223
  // What the query could not hold, said above the list rather than matched in memory.
218
224
  const refused = useMemo(()=>listQueryRefusals(list.plan.refused, {
@@ -264,21 +270,12 @@ const EMPTY_LABEL = {
264
270
  list.plan,
265
271
  list.page
266
272
  ]);
267
- const csvOptions = useMemo(()=>({
268
- assigneeEmail: (uid)=>{
269
- const member = findOrgMember(directory.members, uid);
270
- return (member == null ? void 0 : member.email) || (member == null ? void 0 : member.label) || uid;
271
- },
272
- recordName: nameOf
273
+ // The view and its filters, for the export to read the same tasks the list does (AGL-3528).
274
+ const exportFilter = useMemo(()=>({
275
+ label: 'what the list shows',
276
+ plan: list.plan
273
277
  }), [
274
- directory.members,
275
- nameOf
276
- ]);
277
- const handleExport = useCallback(()=>{
278
- downloadTextFile('tasks.csv', 'text/csv', tasksCsv(tasks, csvOptions));
279
- }, [
280
- tasks,
281
- csvOptions
278
+ list.plan
282
279
  ]);
283
280
  /*
284
281
  * List or month (AGL-2662). A layout choice over the SAME rows and the
@@ -314,12 +311,11 @@ const EMPTY_LABEL = {
314
311
  setBusyId(task.$id);
315
312
  try {
316
313
  if (task.status === 'done') {
317
- await updateDoc(doc(firestore, scope[0], scope[1], CRM_COLLECTIONS.tasks, task.$id), {
318
- status: 'open',
314
+ await updateDoc(doc(firestore, scope[0], scope[1], CRM_COLLECTIONS.tasks, task.$id), _extends({}, crmTaskStatusWrite(picklists.status, false), {
319
315
  completedAtMs: null,
320
316
  completedByUid: deleteField(),
321
317
  updatedAt: serverTimestamp()
322
- });
318
+ }));
323
319
  enqueueSnackbar('Task reopened', {
324
320
  variant: 'success'
325
321
  });
@@ -354,7 +350,8 @@ const EMPTY_LABEL = {
354
350
  user,
355
351
  hostId,
356
352
  orgId,
357
- enqueueSnackbar
353
+ enqueueSnackbar,
354
+ picklists.status
358
355
  ]);
359
356
  const columns = useMemo(()=>[
360
357
  {
@@ -411,11 +408,12 @@ const EMPTY_LABEL = {
411
408
  },
412
409
  {
413
410
  field: 'kind',
414
- headerName: 'Kind',
411
+ headerName: 'Type',
415
412
  width: 120,
416
413
  sortable: false,
417
414
  renderCell: ({ row })=>/*#__PURE__*/ _jsx(TaskKindCell, {
418
- kind: row.kind
415
+ kind: row.kind,
416
+ label: crmTaskPicklistLabels(row, picklists).type
419
417
  })
420
418
  },
421
419
  {
@@ -424,7 +422,22 @@ const EMPTY_LABEL = {
424
422
  width: 110,
425
423
  sortable: false,
426
424
  renderCell: ({ row })=>/*#__PURE__*/ _jsx(TaskPriorityChip, {
427
- priority: row.priority
425
+ priority: row.priority,
426
+ label: crmTaskPicklistLabels(row, picklists).priority
427
+ })
428
+ },
429
+ {
430
+ // The org's status label (AGL-3517); the checkbox is the open/done half.
431
+ field: 'statusLabel',
432
+ headerName: 'Status',
433
+ width: 150,
434
+ sortable: false,
435
+ valueGetter: (_value, row)=>crmTaskPicklistLabels(row, picklists).status,
436
+ renderCell: ({ row })=>/*#__PURE__*/ _jsx(Typography, {
437
+ variant: "body2",
438
+ color: row.status === 'done' ? 'text.secondary' : undefined,
439
+ noWrap: true,
440
+ children: crmTaskPicklistLabels(row, picklists).status
428
441
  })
429
442
  },
430
443
  {
@@ -492,7 +505,8 @@ const EMPTY_LABEL = {
492
505
  directory,
493
506
  routes,
494
507
  nameOf,
495
- scope
508
+ scope,
509
+ picklists
496
510
  ]);
497
511
  /* The column and sort models are the view's (AGL-2617). */ const filterColumns = useMemo(()=>listFilterGridColumns(columns, TASK_FILTER_FIELDS, filterOptions, TASK_FILTER_HEADERS), [
498
512
  columns,
@@ -513,14 +527,15 @@ const EMPTY_LABEL = {
513
527
  // The record actions, top right and never clipped (AGL-3311).
514
528
  action: /*#__PURE__*/ _jsxs(CrmListActions, {
515
529
  children: [
516
- /*#__PURE__*/ _jsx(TaskImportButton, {
530
+ /*#__PURE__*/ _jsx(CrmImportButton, {
531
+ resource: CRM_TASKS_RESOURCE,
532
+ noun: "tasks",
517
533
  hostId: hostId
518
534
  }),
519
- /*#__PURE__*/ _jsx(Button, {
520
- size: "small",
521
- onClick: handleExport,
522
- disabled: !tasks.length,
523
- children: 'Export CSV'
535
+ /*#__PURE__*/ _jsx(CrmExportButton, {
536
+ resource: CRM_TASKS_RESOURCE,
537
+ hostId: hostId,
538
+ filter: exportFilter
524
539
  }),
525
540
  /*#__PURE__*/ _jsx(Button, {
526
541
  size: "small",
@@ -586,6 +601,7 @@ const EMPTY_LABEL = {
586
601
  }) : /*#__PURE__*/ _jsx(_Fragment, {
587
602
  children: layout === 'calendar' ? /*#__PURE__*/ _jsx(TasksCalendar, {
588
603
  tasks: tasks,
604
+ picklists: picklists,
589
605
  truncated: list.hasMore,
590
606
  onOpen: (task)=>setDrawer({
591
607
  open: true,
@@ -599,8 +615,7 @@ const EMPTY_LABEL = {
599
615
  rows: tasks,
600
616
  selected: selectedIds,
601
617
  onSelectedChange: setSelectedIds,
602
- directory: directory,
603
- csv: csvOptions
618
+ directory: directory
604
619
  }),
605
620
  /*#__PURE__*/ _jsx(CrmColumnOrderProvider, {
606
621
  value: grid.columnOrder,