@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-section.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 {\n type ConsolePluginPageProps,\n CRM_COLLECTIONS,\n type CrmViewFilterClause,\n findOrgMember,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { ListTable } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { useCrmSavedView } from '../hooks/use-crm-saved-view'\nimport { useCrmScope } from '../hooks/use-crm-scope'\nimport { useCrmViewGrid } from '../hooks/use-crm-view-grid'\nimport { CRM_LIST_SLOTS, CrmColumnOrderProvider } from './crm-column-menu'\nimport CrmViewsControl from './crm-views-control'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Button,\n Checkbox,\n Stack,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport { deleteField, doc, serverTimestamp, updateDoc } from 'firebase/firestore'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useCrmRecordNames } from '../hooks/use-crm-record-names'\nimport { type CrmTaskRow, useCrmTaskList, useNowMs } from '../hooks/use-crm-tasks'\nimport { useOrgMemberDirectory } from '../hooks/use-org-member-directory'\nimport { downloadTextFile } from '../model/contacts-csv'\nimport { crmRoutes } from '../model/crm-routes'\nimport { refreshCrmNextActivity } from '../model/next-activity-api'\nimport { completeCrmTask } from '../model/task-api'\nimport { crmTaskCallScope } from '../model/task-routes'\nimport { type TaskCsvOptions, tasksCsv } from '../model/tasks-csv'\nimport {\n CRM_TASK_KIND_LABELS,\n CRM_TASK_KINDS,\n CRM_TASK_PRIORITIES,\n CRM_TASK_PRIORITY_LABELS,\n CRM_TASK_VIEWS,\n type CrmTaskView,\n TASK_LIST_QUERY_FIELDS,\n} from '../model/task-views'\nimport type { ListFilterField } from '@aglyn/shared-ui-jsx/const/list-filter'\nimport { listFilterGridColumns } from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport { TABLE_PAGE_SIZE_DEFAULT } from '@aglyn/shared-ui-jsx/const/table-pagination'\nimport ListQueryNotices, {\n listQueryRefusals,\n} from '@aglyn/shared-ui-jsx/components/list-query-notices.component'\nimport { useListGridFilter } from '@aglyn/shared-ui-jsx/hooks/use-list-grid-filter'\nimport ListFilterChips from '@aglyn/shared-ui-jsx/components/list-filter-chips.component'\nimport { CrmListActions, CrmListToolbar } from './crm-list-toolbar'\nimport {\n TaskDueText,\n TaskKindCell,\n TaskPriorityChip,\n TaskRecordLink,\n} from './task-cells'\nimport TaskEditDrawer from './task-edit-drawer'\nimport TasksCalendar from './tasks-calendar'\nimport { TaskImportButton } from './task-import-drawer'\nimport TaskSnoozeMenu from './task-snooze-menu'\nimport TasksBulkBar from './tasks-bulk-bar'\n\n/** What an empty view is headed, by view — \"nothing overdue\" is good news. */\n/*\n * What the tasks grid's panel offers (AGL-3313). `view` is the task view\n * the query's base answers — a hidden column, since it is no field of a\n * task — and Kind, Priority and Assignee are predicates on the same query\n * (AGL-3321).\n */\nconst TASK_FILTER_FIELDS: readonly ListFilterField[] = [\n { column: 'view', kind: 'exact', path: 'view', operators: ['equals'] },\n ...TASK_LIST_QUERY_FIELDS,\n]\nconst TASK_FILTER_HEADERS: Readonly<Record<string, string>> = {\n view: 'Show',\n kind: 'Kind',\n priority: 'Priority',\n assigneeUid: 'Assignee',\n}\n/** The filter-only `view` column never shows. */\nconst TASK_HIDDEN_COLUMNS: Readonly<Record<string, boolean>> = { view: false }\n/** How many tasks the month view reads: one page, sized for a month of work. */\nconst CALENDAR_PAGE_SIZE = 200\n/** No `view` clause is \"My tasks\", which the section opened on before views existed. */\nconst TASK_VIEW_DEFAULT: CrmViewFilterClause = { field: 'view', op: 'equals', value: 'mine' }\nconst EMPTY_LABEL: Record<CrmTaskView, string> = {\n mine: 'Nothing is assigned to you',\n overdue: 'Nothing is overdue',\n today: 'Nothing is due today',\n upcoming: 'Nothing is scheduled beyond today',\n open: 'No open tasks',\n done: 'No completed tasks yet',\n}\n\n/** The one sentence under it, by view. */\nconst EMPTY_COPY: Record<CrmTaskView, string> = {\n mine: 'Tasks you create are yours unless you hand them to someone.',\n overdue: 'Every dated task is on or ahead of schedule.',\n today: 'Nothing on your calendar day is owed to anyone in the CRM.',\n upcoming: 'A task with a due date past today would be listed here.',\n open: 'A task is a call, an email, a meeting or a to-do owed to a contact, a company or a deal.',\n done: 'Tasks ticked off on their record, or here, are kept for the history.',\n}\n\n/**\n * `/crm/tasks` — what the team owes the people in the CRM (AGL-2599).\n *\n * Six views over `orgs/{orgId}/crmTasks`, each a bounded listener on one of\n * the collection's indexes, chosen by a segmented control. A task hangs off\n * a contact, a company or a deal, but it is listed HERE because \"what is due\n * today\" is a question about the team's day and not about any one record;\n * the record pages carry their own `RecordTasksCard` for the other\n * direction.\n *\n * Completing goes through `crm/task-complete`, because completing fires the\n * `taskCompleted` host event and only the server can run a workflow.\n * Reopening is client-direct: undoing a tick has no side effect beyond the\n * document, and the rules gate it like any other CRM write.\n *\n * The rows are selectable, and a selection raises `TasksBulkBar` over the\n * list — Complete and Assign through their routes, the due date and the\n * delete as batched writes (AGL-2621). Export CSV beside the view control\n * writes the view through `tasksCsv()`, naming the assignee and the linked\n * records; the bar writes the same file over the selection.\n */\nexport function TasksSection(props: ConsolePluginPageProps) {\n const { hostId, org, basePath = '' } = props\n const orgRecord = org as Record<string, unknown> | undefined\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const nowMs = useNowMs()\n const routes = useMemo(() => crmRoutes(basePath), [basePath])\n // The viewing group a linked contact is named through, or `null` at the\n // organization level, where each is named through its own holder.\n const { consentGroup } = useCrmScope({ hostId, org: orgRecord })\n const groupId = consentGroup?.groupId ?? null\n\n /*\n * Which of the six task views is open is the saved VIEW'S (AGL-2617): a\n * saved view of tasks holds the task view beside the columns and the\n * sort, and the toggle below writes into it. Unset reads as \"My tasks\",\n * which is what the section opened on before views existed.\n */\n const views = useCrmSavedView({ section: 'tasks', hostId, org: orgRecord, basePath })\n const view: CrmTaskView = useMemo(() => {\n const value = views.state.filters.find((clause) => clause.field === 'view')?.value\n return CRM_TASK_VIEWS.some((option) => option.id === value)\n ? (value as CrmTaskView)\n : 'mine'\n }, [views.state.filters])\n /*\n * The grid's own Filters panel and quick search edit the view's clauses\n * (AGL-3313). \"Show\" is the task view the query's base answers — the\n * hidden `view` column, as the toggle stored it, with none meaning \"My\n * tasks\" — and Kind, Priority, Assignee and the search word are on the\n * same query (AGL-3321).\n */\n const clauses = useMemo(\n () =>\n views.state.filters.some((clause) => clause.field === 'view')\n ? views.state.filters\n : [TASK_VIEW_DEFAULT, ...views.state.filters],\n [views.state.filters],\n )\n const setClauses = useCallback(\n (next: CrmViewFilterClause[]) =>\n views.setFilters(\n next.filter(\n (clause) => !(clause.field === 'view' && clause.value === TASK_VIEW_DEFAULT.value),\n ),\n ),\n [views.setFilters],\n )\n const gridFilter = useListGridFilter({\n clauses,\n onChange: setClauses,\n selectFields: ['view', 'kind', 'priority', 'assigneeUid'],\n })\n const queryClauses = useMemo(\n () => clauses.filter((clause) => clause.field !== 'view'),\n [clauses],\n )\n const list = useCrmTaskList({\n hostId,\n org: orgRecord,\n view,\n uid: user?.uid,\n nowMs,\n clauses: queryClauses,\n search: gridFilter.searchWords,\n })\n const { tasks, status, fromCache, scope, orgId, readTokens } = list\n const directory = useOrgMemberDirectory(orgId)\n const filterOptions = useMemo(\n () => ({\n view: CRM_TASK_VIEWS.map((option) => ({ value: option.id, label: option.label })),\n kind: CRM_TASK_KINDS.map((kind) => ({ value: kind, label: CRM_TASK_KIND_LABELS[kind] })),\n priority: CRM_TASK_PRIORITIES.map((priority) => ({\n value: priority,\n label: CRM_TASK_PRIORITY_LABELS[priority],\n })),\n assigneeUid: directory.members.map((member) => ({\n value: member.uid,\n label: member.label,\n })),\n }),\n [directory.members],\n )\n // What the query could not hold, said above the list rather than matched in memory.\n const refused = useMemo(\n () =>\n listQueryRefusals(list.plan.refused, {\n fields: TASK_FILTER_FIELDS,\n headers: TASK_FILTER_HEADERS,\n options: filterOptions,\n }),\n [list.plan.refused, filterOptions],\n )\n const filtered = queryClauses.length > 0 || gridFilter.searchWords.some((word) => word.trim())\n\n /*\n * Every record a task names, not only the one its \"For\" cell shows: the\n * export writes the contact, the company and the deal each by name, and\n * a task that names two would otherwise carry an id in one column.\n */\n const linked = useMemo(\n () =>\n tasks.flatMap((task) => [\n ...(task.contactId ? [{ kind: 'contact' as const, id: task.contactId }] : []),\n ...(task.companyId ? [{ kind: 'company' as const, id: task.companyId }] : []),\n ...(task.dealId ? [{ kind: 'deal' as const, id: task.dealId }] : []),\n ]),\n [tasks],\n )\n const nameOf = useCrmRecordNames({ orgId, groupId, org: orgRecord, records: linked })\n\n const [selectedIds, setSelectedIds] = useState<string[]>([])\n // A view, a filter or a page is a different set of rows; a selection made\n // on the last one would be a count over rows no longer on screen.\n useEffect(() => setSelectedIds([]), [view, list.plan, list.page])\n const csvOptions: TaskCsvOptions = useMemo(\n () => ({\n assigneeEmail: (uid) => {\n const member = findOrgMember(directory.members, uid)\n return member?.email || member?.label || uid\n },\n recordName: nameOf,\n }),\n [directory.members, nameOf],\n )\n const handleExport = useCallback(() => {\n downloadTextFile('tasks.csv', 'text/csv', tasksCsv(tasks, csvOptions))\n }, [tasks, csvOptions])\n\n /*\n * List or month (AGL-2662). A layout choice over the SAME rows and the\n * same view — switching does not narrow anything and costs no read, so\n * it is a toggle rather than another saved view.\n */\n const [layout, setLayout] = useState<'list' | 'calendar'>('list')\n /*\n * The month draws one query page, so it asks for a month's worth: the\n * calendar's page is {@link CALENDAR_PAGE_SIZE} tasks of the same view and\n * filters, and it says when the view holds more. The list's own page size\n * comes back with the list.\n */\n const { setPage: setListPage, setPageSize: setListPageSize } = list\n useEffect(() => {\n setListPage(0)\n setListPageSize(layout === 'calendar' ? CALENDAR_PAGE_SIZE : TABLE_PAGE_SIZE_DEFAULT)\n }, [layout, setListPage, setListPageSize])\n const [drawer, setDrawer] = useState<{ open: boolean; task: CrmTaskRow | null }>({\n open: false,\n task: null,\n })\n const [busyId, setBusyId] = useState<string | null>(null)\n\n /*\n * Tick or untick. The two directions are two different writes on purpose\n * — see the module comment — and the row is disabled while either is in\n * flight so a double-click cannot complete a task and reopen it in the\n * same breath.\n */\n const toggleDone = useCallback(\n async (task: CrmTaskRow) => {\n if (!scope || busyId) return\n setBusyId(task.$id)\n try {\n if (task.status === 'done') {\n await updateDoc(\n doc(firestore, scope[0], scope[1], CRM_COLLECTIONS.tasks, task.$id),\n {\n status: 'open',\n completedAtMs: null,\n completedByUid: deleteField(),\n updatedAt: serverTimestamp(),\n },\n )\n enqueueSnackbar('Task reopened', { variant: 'success' })\n // A client-direct write: the records it names are told (AGL-2661).\n await refreshCrmNextActivity(user, crmTaskCallScope(hostId, orgId), [task])\n } else {\n // The route runs as the mounted site, which hears the event, or\n // at the organization level as the org — the org variant, which\n // emits on the task's own site, or nowhere for an org task.\n const callScope = crmTaskCallScope(hostId, orgId)\n if (!callScope) return\n await completeCrmTask(user, { ...callScope, taskId: task.$id })\n enqueueSnackbar('Task completed', { variant: 'success' })\n }\n } catch (cause) {\n enqueueSnackbar(\n cause instanceof Error ? cause.message : 'The task could not be updated.',\n { variant: 'warning' },\n )\n } finally {\n setBusyId(null)\n }\n },\n [scope, busyId, firestore, user, hostId, orgId, enqueueSnackbar],\n )\n\n const columns: GridColDef[] = useMemo(\n () => [\n {\n field: 'status',\n headerName: '',\n width: 56,\n sortable: false,\n filterable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <Checkbox\n size=\"small\"\n checked={row.status === 'done'}\n disabled={busyId === row.$id}\n onClick={(event) => {\n event.stopPropagation()\n void toggleDone(row)\n }}\n slotProps={{\n input: {\n 'aria-label':\n row.status === 'done'\n ? `Reopen \"${row.title}\"`\n : `Complete \"${row.title}\"`,\n },\n }}\n />\n ),\n },\n {\n field: 'title',\n headerName: 'Task',\n flex: 2,\n minWidth: 220,\n sortable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <Stack sx={{ justifyContent: 'center', height: '100%', minWidth: 0 }}>\n <Typography\n variant=\"body2\"\n noWrap\n sx={{\n textDecoration: row.status === 'done' ? 'line-through' : undefined,\n color: row.status === 'done' ? 'text.secondary' : undefined,\n }}\n >\n {row.title}\n </Typography>\n {row.notes ? (\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {row.notes}\n </Typography>\n ) : null}\n </Stack>\n ),\n },\n {\n field: 'kind',\n headerName: 'Kind',\n width: 120,\n sortable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => <TaskKindCell kind={row.kind} />,\n },\n {\n field: 'priority',\n headerName: 'Priority',\n width: 110,\n sortable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <TaskPriorityChip priority={row.priority} />\n ),\n },\n {\n field: 'dueAtMs',\n headerName: 'Due',\n width: 260,\n sortable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center', height: '100%' }}>\n <TaskDueText task={row} nowMs={nowMs} />\n {row.status === 'done' || !scope ? null : (\n <TaskSnoozeMenu\n dueAtMs={row.dueAtMs}\n remindAtMs={row.remindAtMs}\n target={{\n write: {\n scope,\n taskId: row.$id,\n call: crmTaskCallScope(hostId, orgId),\n links: row,\n },\n }}\n disabled={busyId === row.$id}\n />\n )}\n </Stack>\n ),\n },\n {\n field: 'assigneeUid',\n headerName: 'Assignee',\n flex: 1,\n minWidth: 140,\n sortable: false,\n valueGetter: (_value: unknown, row: CrmTaskRow) =>\n directory.nameOf(row.assigneeUid),\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <Typography variant=\"body2\" color={row.assigneeUid ? undefined : 'text.secondary'}>\n {row.assigneeUid ? directory.nameOf(row.assigneeUid) : 'Unassigned'}\n </Typography>\n ),\n },\n {\n field: 'record',\n headerName: 'For',\n flex: 1,\n minWidth: 160,\n sortable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <TaskRecordLink task={row} routes={routes} nameOf={nameOf} />\n ),\n },\n ],\n [busyId, toggleDone, nowMs, directory, routes, nameOf, scope],\n )\n /* The column and sort models are the view's (AGL-2617). */\n const filterColumns = useMemo(\n () => listFilterGridColumns(columns, TASK_FILTER_FIELDS, filterOptions, TASK_FILTER_HEADERS),\n [columns, filterOptions],\n )\n const grid = useCrmViewGrid(views, filterColumns, TASK_HIDDEN_COLUMNS)\n\n return (\n <>\n <CardDisplay\n header={'Tasks'}\n help={pluginDocsHelp('crmTasks', {\n anchor: '#the-tasks-page',\n excerpt:\n 'Calls, emails, meetings and to-dos, each linked to the contact, ' +\n 'company or deal it is for. Overdue and today are read off the ' +\n 'due date as you look.',\n })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n // The record actions, top right and never clipped (AGL-3311).\n action: (\n <CrmListActions>\n <TaskImportButton hostId={hostId} />\n <Button size=\"small\" onClick={handleExport} disabled={!tasks.length}>\n {'Export CSV'}\n </Button>\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n onClick={() => setDrawer({ open: true, task: null })}\n >\n {'New task'}\n </Button>\n </CrmListActions>\n ),\n }}\n >\n <Stack spacing={2}>\n {/*\n The saved view, and the clauses narrowing it as chips — \"Show\"\n among them — set in the grid's own Filters panel (AGL-3313).\n */}\n <CrmListToolbar label=\"Task filters\">\n <CrmViewsControl controller={views} allLabel=\"All tasks\" />\n <ListFilterChips\n fields={TASK_FILTER_FIELDS}\n headers={TASK_FILTER_HEADERS}\n clauses={clauses}\n onChange={setClauses}\n options={filterOptions}\n marksServed={false}\n />\n <ToggleButtonGroup\n exclusive\n size=\"small\"\n color=\"primary\"\n value={layout}\n onChange={(_event, next) => {\n if (next) setLayout(next as 'list' | 'calendar')\n }}\n aria-label=\"Task layout\"\n >\n <ToggleButton value=\"list\">{'List'}</ToggleButton>\n <ToggleButton value=\"calendar\">{'Calendar'}</ToggleButton>\n </ToggleButtonGroup>\n </CrmListToolbar>\n <ListQueryNotices refused={refused} notices={list.plan.notices} />\n {status === 'error' ? (\n <Typography variant=\"body2\" color=\"error\">\n {'The tasks could not be loaded. Reload to try again.'}\n </Typography>\n ) : (\n <>\n {/*\n The calendar draws the same rows, so there is no bulk bar\n over it: a selection is a list gesture, and a month grid\n offers nowhere to make one.\n */}\n {layout === 'calendar' ? (\n <TasksCalendar\n tasks={tasks}\n truncated={list.hasMore}\n onOpen={(task) => setDrawer({ open: true, task })}\n />\n ) : (\n <>\n <TasksBulkBar\n hostId={hostId}\n scope={scope}\n rows={tasks}\n selected={selectedIds}\n onSelectedChange={setSelectedIds}\n directory={directory}\n csv={csvOptions}\n />\n <CrmColumnOrderProvider value={grid.columnOrder}>\n <ListTable\n rows={tasks}\n columns={grid.columns}\n slots={CRM_LIST_SLOTS}\n selectable={{ selected: selectedIds, onChange: setSelectedIds }}\n loading={status === 'loading'}\n onOpen={(id) => {\n const found = tasks.find((row) => row.$id === id)\n if (found) setDrawer({ open: true, task: found })\n }}\n /*\n * The panel and the search are the grid's; the section\n * answers them, the view through the query (AGL-3313). An\n * empty view is said inside the grid rather than instead of\n * it, so its toolbar stays to choose another view.\n */\n noRowsLabel={filtered ? 'No tasks match these filters' : EMPTY_LABEL[view]}\n noRowsDescription={filtered ? undefined : EMPTY_COPY[view]}\n noRowsAction={\n filtered ? undefined : (\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n onClick={() => setDrawer({ open: true, task: null })}\n >\n {'New task'}\n </Button>\n )\n }\n filterMode=\"server\"\n filterModel={gridFilter.filterModel}\n onFilterModelChange={gridFilter.onFilterModelChange}\n quickFilter\n // The view orders the query (due soonest, or Done most\n // recently due), so the grid sorts nothing itself: a\n // sort over one page would reorder ten rows.\n sortingMode=\"server\"\n disableColumnSorting\n // Columns are the view's, controlled (AGL-2617).\n columnVisibilityModel={grid.columnVisibilityModel}\n onColumnVisibilityModelChange={grid.onColumnVisibilityModelChange}\n // Paged by the footer below, so the grid must not also slice.\n hideFooter\n />\n </CrmColumnOrderProvider>\n <ListPagination\n page={list.page}\n pageSize={list.pageSize}\n rowCount={tasks.length}\n hasMore={list.hasMore}\n onPageChange={list.setPage}\n onPageSizeChange={list.setPageSize}\n />\n </>\n )}\n </>\n )}\n </Stack>\n </CardDisplay>\n <TaskEditDrawer\n open={drawer.open}\n onClose={() => setDrawer((prev) => ({ ...prev, open: false }))}\n hostId={hostId}\n org={orgRecord}\n orgId={orgId}\n scope={scope}\n readTokens={readTokens}\n task={drawer.task}\n seed={{ fromCache, unreadable: status === 'error' }}\n />\n </>\n )\n}\nTasksSection.displayName = 'TasksSection'\n\nexport default TasksSection\n"],"names":["CRM_COLLECTIONS","findOrgMember","pluginDocsHelp","CardDisplay","ListTable","useCrmSavedView","useCrmScope","useCrmViewGrid","CRM_LIST_SLOTS","CrmColumnOrderProvider","CrmViewsControl","useSnackbar","useFirestore","useUser","Button","Checkbox","Stack","ToggleButton","ToggleButtonGroup","Typography","deleteField","doc","serverTimestamp","updateDoc","useCallback","useEffect","useMemo","useState","useCrmRecordNames","useCrmTaskList","useNowMs","useOrgMemberDirectory","downloadTextFile","crmRoutes","refreshCrmNextActivity","completeCrmTask","crmTaskCallScope","tasksCsv","CRM_TASK_KIND_LABELS","CRM_TASK_KINDS","CRM_TASK_PRIORITIES","CRM_TASK_PRIORITY_LABELS","CRM_TASK_VIEWS","TASK_LIST_QUERY_FIELDS","listFilterGridColumns","ListPagination","TABLE_PAGE_SIZE_DEFAULT","ListQueryNotices","listQueryRefusals","useListGridFilter","ListFilterChips","CrmListActions","CrmListToolbar","TaskDueText","TaskKindCell","TaskPriorityChip","TaskRecordLink","TaskEditDrawer","TasksCalendar","TaskImportButton","TaskSnoozeMenu","TasksBulkBar","TASK_FILTER_FIELDS","column","kind","path","operators","TASK_FILTER_HEADERS","view","priority","assigneeUid","TASK_HIDDEN_COLUMNS","CALENDAR_PAGE_SIZE","TASK_VIEW_DEFAULT","field","op","value","EMPTY_LABEL","mine","overdue","today","upcoming","open","done","EMPTY_COPY","TasksSection","props","hostId","org","basePath","orgRecord","firestore","data","user","enqueueSnackbar","nowMs","routes","consentGroup","groupId","views","section","state","filters","find","clause","some","option","id","clauses","setClauses","next","setFilters","filter","gridFilter","onChange","selectFields","queryClauses","list","uid","search","searchWords","tasks","status","fromCache","scope","orgId","readTokens","directory","filterOptions","map","label","members","member","refused","plan","fields","headers","options","filtered","length","word","trim","linked","flatMap","task","contactId","companyId","dealId","nameOf","records","selectedIds","setSelectedIds","page","csvOptions","assigneeEmail","email","recordName","handleExport","layout","setLayout","setPage","setListPage","setPageSize","setListPageSize","drawer","setDrawer","busyId","setBusyId","toggleDone","$id","completedAtMs","completedByUid","updatedAt","variant","callScope","taskId","cause","Error","message","columns","headerName","width","sortable","filterable","renderCell","row","size","checked","disabled","onClick","event","stopPropagation","slotProps","input","title","flex","minWidth","sx","justifyContent","height","noWrap","textDecoration","undefined","color","notes","direction","spacing","alignItems","dueAtMs","remindAtMs","target","write","call","links","valueGetter","_value","filterColumns","grid","header","help","anchor","excerpt","contentGutterX","contentGutterY","HeaderProps","action","controller","allLabel","marksServed","exclusive","_event","aria-label","notices","truncated","hasMore","onOpen","rows","selected","onSelectedChange","csv","columnOrder","slots","selectable","loading","found","noRowsLabel","noRowsDescription","noRowsAction","filterMode","filterModel","onFilterModelChange","quickFilter","sortingMode","disableColumnSorting","columnVisibilityModel","onColumnVisibilityModelChange","hideFooter","pageSize","rowCount","onPageChange","onPageSizeChange","onClose","prev","seed","unreadable","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/tasks-section.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 {\n type ConsolePluginPageProps,\n CRM_COLLECTIONS,\n crmPicklistShownLabel,\n crmTaskPicklistLabels,\n crmTaskStatusWrite,\n type CrmViewFilterClause,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { ListTable } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { useCrmSavedView } from '../hooks/use-crm-saved-view'\nimport { useCrmScope } from '../hooks/use-crm-scope'\nimport { useCrmViewGrid } from '../hooks/use-crm-view-grid'\nimport { CRM_LIST_SLOTS, CrmColumnOrderProvider } from './crm-column-menu'\nimport CrmViewsControl from './crm-views-control'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Button,\n Checkbox,\n Stack,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport { deleteField, doc, serverTimestamp, updateDoc } from 'firebase/firestore'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useCrmRecordNames } from '../hooks/use-crm-record-names'\nimport { type CrmTaskRow, useCrmTaskList, useNowMs } from '../hooks/use-crm-tasks'\nimport { useOrgMemberDirectory } from '../hooks/use-org-member-directory'\nimport { useCrmTaskPicklists } from '../hooks/use-crm-task-picklists'\nimport { crmRoutes } from '../model/crm-routes'\nimport { refreshCrmNextActivity } from '../model/next-activity-api'\nimport { completeCrmTask } from '../model/task-api'\nimport { crmTaskCallScope } from '../model/task-routes'\nimport {\n CRM_TASK_KINDS,\n CRM_TASK_PRIORITIES,\n CRM_TASK_VIEWS,\n type CrmTaskView,\n TASK_LIST_QUERY_FIELDS,\n} from '../model/task-views'\nimport type { ListFilterField } from '@aglyn/shared-ui-jsx/const/list-filter'\nimport { listFilterGridColumns } from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport { TABLE_PAGE_SIZE_DEFAULT } from '@aglyn/shared-ui-jsx/const/table-pagination'\nimport ListQueryNotices, {\n listQueryRefusals,\n} from '@aglyn/shared-ui-jsx/components/list-query-notices.component'\nimport { useListGridFilter } from '@aglyn/shared-ui-jsx/hooks/use-list-grid-filter'\nimport ListFilterChips from '@aglyn/shared-ui-jsx/components/list-filter-chips.component'\nimport { CrmListActions, CrmListToolbar } from './crm-list-toolbar'\nimport {\n TaskDueText,\n TaskKindCell,\n TaskPriorityChip,\n TaskRecordLink,\n} from './task-cells'\nimport TaskEditDrawer from './task-edit-drawer'\nimport TasksCalendar from './tasks-calendar'\nimport { CrmExportButton, CrmImportButton } from './crm-transfer-buttons'\nimport { CRM_TASKS_RESOURCE } from '../transfer/fields'\nimport TaskSnoozeMenu from './task-snooze-menu'\nimport TasksBulkBar from './tasks-bulk-bar'\n\n/** What an empty view is headed, by view — \"nothing overdue\" is good news. */\n/*\n * What the tasks grid's panel offers (AGL-3313). `view` is the task view\n * the query's base answers — a hidden column, since it is no field of a\n * task — and Kind, Priority and Assignee are predicates on the same query\n * (AGL-3321).\n */\nconst TASK_FILTER_FIELDS: readonly ListFilterField[] = [\n { column: 'view', kind: 'exact', path: 'view', operators: ['equals'] },\n ...TASK_LIST_QUERY_FIELDS,\n]\nconst TASK_FILTER_HEADERS: Readonly<Record<string, string>> = {\n view: 'Show',\n kind: 'Type',\n priority: 'Priority',\n assigneeUid: 'Assignee',\n}\n/** The filter-only `view` column never shows. */\nconst TASK_HIDDEN_COLUMNS: Readonly<Record<string, boolean>> = { view: false }\n/** How many tasks the month view reads: one page, sized for a month of work. */\nconst CALENDAR_PAGE_SIZE = 200\n/** No `view` clause is \"My tasks\", which the section opened on before views existed. */\nconst TASK_VIEW_DEFAULT: CrmViewFilterClause = { field: 'view', op: 'equals', value: 'mine' }\nconst EMPTY_LABEL: Record<CrmTaskView, string> = {\n mine: 'Nothing is assigned to you',\n overdue: 'Nothing is overdue',\n today: 'Nothing is due today',\n upcoming: 'Nothing is scheduled beyond today',\n open: 'No open tasks',\n done: 'No completed tasks yet',\n}\n\n/** The one sentence under it, by view. */\nconst EMPTY_COPY: Record<CrmTaskView, string> = {\n mine: 'Tasks you create are yours unless you hand them to someone.',\n overdue: 'Every dated task is on or ahead of schedule.',\n today: 'Nothing on your calendar day is owed to anyone in the CRM.',\n upcoming: 'A task with a due date past today would be listed here.',\n open: 'A task is a call, an email, a meeting or a to-do owed to a contact, a company or a deal.',\n done: 'Tasks ticked off on their record, or here, are kept for the history.',\n}\n\n/**\n * `/crm/tasks` — what the team owes the people in the CRM (AGL-2599).\n *\n * Six views over `orgs/{orgId}/crmTasks`, each a bounded listener on one of\n * the collection's indexes, chosen by a segmented control. A task hangs off\n * a contact, a company or a deal, but it is listed HERE because \"what is due\n * today\" is a question about the team's day and not about any one record;\n * the record pages carry their own `RecordTasksCard` for the other\n * direction.\n *\n * Completing goes through `crm/task-complete`, because completing fires the\n * `taskCompleted` host event and only the server can run a workflow.\n * Reopening is client-direct: undoing a tick has no side effect beyond the\n * document, and the rules gate it like any other CRM write.\n *\n * The rows are selectable, and a selection raises `TasksBulkBar` over the\n * list — Complete and Assign through their routes, the due date and the\n * delete as batched writes (AGL-2621). Import and Export open the console's\n * wizard and dialog on `crm.tasks` (AGL-3528); the export reads the view's\n * own query, and the bar opens it on the selection.\n */\nexport function TasksSection(props: ConsolePluginPageProps) {\n const { hostId, org, basePath = '' } = props\n const orgRecord = org as Record<string, unknown> | undefined\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const nowMs = useNowMs()\n const routes = useMemo(() => crmRoutes(basePath), [basePath])\n // The viewing group a linked contact is named through, or `null` at the\n // organization level, where each is named through its own holder.\n const { consentGroup } = useCrmScope({ hostId, org: orgRecord })\n const groupId = consentGroup?.groupId ?? null\n\n /*\n * Which of the six task views is open is the saved VIEW'S (AGL-2617): a\n * saved view of tasks holds the task view beside the columns and the\n * sort, and the toggle below writes into it. Unset reads as \"My tasks\",\n * which is what the section opened on before views existed.\n */\n const views = useCrmSavedView({ section: 'tasks', hostId, org: orgRecord, basePath })\n const view: CrmTaskView = useMemo(() => {\n const value = views.state.filters.find((clause) => clause.field === 'view')?.value\n return CRM_TASK_VIEWS.some((option) => option.id === value)\n ? (value as CrmTaskView)\n : 'mine'\n }, [views.state.filters])\n /*\n * The grid's own Filters panel and quick search edit the view's clauses\n * (AGL-3313). \"Show\" is the task view the query's base answers — the\n * hidden `view` column, as the toggle stored it, with none meaning \"My\n * tasks\" — and Kind, Priority, Assignee and the search word are on the\n * same query (AGL-3321).\n */\n const clauses = useMemo(\n () =>\n views.state.filters.some((clause) => clause.field === 'view')\n ? views.state.filters\n : [TASK_VIEW_DEFAULT, ...views.state.filters],\n [views.state.filters],\n )\n const setClauses = useCallback(\n (next: CrmViewFilterClause[]) =>\n views.setFilters(\n next.filter(\n (clause) => !(clause.field === 'view' && clause.value === TASK_VIEW_DEFAULT.value),\n ),\n ),\n [views.setFilters],\n )\n const gridFilter = useListGridFilter({\n clauses,\n onChange: setClauses,\n selectFields: ['view', 'kind', 'priority', 'assigneeUid'],\n })\n const queryClauses = useMemo(\n () => clauses.filter((clause) => clause.field !== 'view'),\n [clauses],\n )\n const list = useCrmTaskList({\n hostId,\n org: orgRecord,\n view,\n uid: user?.uid,\n nowMs,\n clauses: queryClauses,\n search: gridFilter.searchWords,\n })\n const { tasks, status, fromCache, scope, orgId, readTokens } = list\n const directory = useOrgMemberDirectory(orgId)\n const picklists = useCrmTaskPicklists(orgId)\n /*\n * Type and Priority filter on the MEANING the query holds (AGL-3517), so\n * each option is a meaning, named by the org's label for it.\n */\n const filterOptions = useMemo(\n () => ({\n view: CRM_TASK_VIEWS.map((option) => ({ value: option.id, label: option.label })),\n kind: CRM_TASK_KINDS.map((kind) => ({\n value: kind,\n label: crmPicklistShownLabel(picklists.type, kind, null),\n })),\n priority: CRM_TASK_PRIORITIES.map((priority) => ({\n value: priority,\n label: crmPicklistShownLabel(picklists.priority, priority, null),\n })),\n assigneeUid: directory.members.map((member) => ({\n value: member.uid,\n label: member.label,\n })),\n }),\n [directory.members, picklists.type, picklists.priority],\n )\n // What the query could not hold, said above the list rather than matched in memory.\n const refused = useMemo(\n () =>\n listQueryRefusals(list.plan.refused, {\n fields: TASK_FILTER_FIELDS,\n headers: TASK_FILTER_HEADERS,\n options: filterOptions,\n }),\n [list.plan.refused, filterOptions],\n )\n const filtered = queryClauses.length > 0 || gridFilter.searchWords.some((word) => word.trim())\n\n /*\n * Every record a task names, not only the one its \"For\" cell shows: the\n * export writes the contact, the company and the deal each by name, and\n * a task that names two would otherwise carry an id in one column.\n */\n const linked = useMemo(\n () =>\n tasks.flatMap((task) => [\n ...(task.contactId ? [{ kind: 'contact' as const, id: task.contactId }] : []),\n ...(task.companyId ? [{ kind: 'company' as const, id: task.companyId }] : []),\n ...(task.dealId ? [{ kind: 'deal' as const, id: task.dealId }] : []),\n ]),\n [tasks],\n )\n const nameOf = useCrmRecordNames({ orgId, groupId, org: orgRecord, records: linked })\n\n const [selectedIds, setSelectedIds] = useState<string[]>([])\n // A view, a filter or a page is a different set of rows; a selection made\n // on the last one would be a count over rows no longer on screen.\n useEffect(() => setSelectedIds([]), [view, list.plan, list.page])\n // The view and its filters, for the export to read the same tasks the list does (AGL-3528).\n const exportFilter = useMemo(() => ({ label: 'what the list shows', plan: list.plan }), [list.plan])\n\n /*\n * List or month (AGL-2662). A layout choice over the SAME rows and the\n * same view — switching does not narrow anything and costs no read, so\n * it is a toggle rather than another saved view.\n */\n const [layout, setLayout] = useState<'list' | 'calendar'>('list')\n /*\n * The month draws one query page, so it asks for a month's worth: the\n * calendar's page is {@link CALENDAR_PAGE_SIZE} tasks of the same view and\n * filters, and it says when the view holds more. The list's own page size\n * comes back with the list.\n */\n const { setPage: setListPage, setPageSize: setListPageSize } = list\n useEffect(() => {\n setListPage(0)\n setListPageSize(layout === 'calendar' ? CALENDAR_PAGE_SIZE : TABLE_PAGE_SIZE_DEFAULT)\n }, [layout, setListPage, setListPageSize])\n const [drawer, setDrawer] = useState<{ open: boolean; task: CrmTaskRow | null }>({\n open: false,\n task: null,\n })\n const [busyId, setBusyId] = useState<string | null>(null)\n\n /*\n * Tick or untick. The two directions are two different writes on purpose\n * — see the module comment — and the row is disabled while either is in\n * flight so a double-click cannot complete a task and reopen it in the\n * same breath.\n */\n const toggleDone = useCallback(\n async (task: CrmTaskRow) => {\n if (!scope || busyId) return\n setBusyId(task.$id)\n try {\n if (task.status === 'done') {\n await updateDoc(\n doc(firestore, scope[0], scope[1], CRM_COLLECTIONS.tasks, task.$id),\n {\n // Open again, with the label a new task starts with (AGL-3517).\n ...crmTaskStatusWrite(picklists.status, false),\n completedAtMs: null,\n completedByUid: deleteField(),\n updatedAt: serverTimestamp(),\n },\n )\n enqueueSnackbar('Task reopened', { variant: 'success' })\n // A client-direct write: the records it names are told (AGL-2661).\n await refreshCrmNextActivity(user, crmTaskCallScope(hostId, orgId), [task])\n } else {\n // The route runs as the mounted site, which hears the event, or\n // at the organization level as the org — the org variant, which\n // emits on the task's own site, or nowhere for an org task.\n const callScope = crmTaskCallScope(hostId, orgId)\n if (!callScope) return\n await completeCrmTask(user, { ...callScope, taskId: task.$id })\n enqueueSnackbar('Task completed', { variant: 'success' })\n }\n } catch (cause) {\n enqueueSnackbar(\n cause instanceof Error ? cause.message : 'The task could not be updated.',\n { variant: 'warning' },\n )\n } finally {\n setBusyId(null)\n }\n },\n [scope, busyId, firestore, user, hostId, orgId, enqueueSnackbar, picklists.status],\n )\n\n const columns: GridColDef[] = useMemo(\n () => [\n {\n field: 'status',\n headerName: '',\n width: 56,\n sortable: false,\n filterable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <Checkbox\n size=\"small\"\n checked={row.status === 'done'}\n disabled={busyId === row.$id}\n onClick={(event) => {\n event.stopPropagation()\n void toggleDone(row)\n }}\n slotProps={{\n input: {\n 'aria-label':\n row.status === 'done'\n ? `Reopen \"${row.title}\"`\n : `Complete \"${row.title}\"`,\n },\n }}\n />\n ),\n },\n {\n field: 'title',\n headerName: 'Task',\n flex: 2,\n minWidth: 220,\n sortable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <Stack sx={{ justifyContent: 'center', height: '100%', minWidth: 0 }}>\n <Typography\n variant=\"body2\"\n noWrap\n sx={{\n textDecoration: row.status === 'done' ? 'line-through' : undefined,\n color: row.status === 'done' ? 'text.secondary' : undefined,\n }}\n >\n {row.title}\n </Typography>\n {row.notes ? (\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {row.notes}\n </Typography>\n ) : null}\n </Stack>\n ),\n },\n {\n field: 'kind',\n headerName: 'Type',\n width: 120,\n sortable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <TaskKindCell kind={row.kind} label={crmTaskPicklistLabels(row, picklists).type} />\n ),\n },\n {\n field: 'priority',\n headerName: 'Priority',\n width: 110,\n sortable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <TaskPriorityChip\n priority={row.priority}\n label={crmTaskPicklistLabels(row, picklists).priority}\n />\n ),\n },\n {\n // The org's status label (AGL-3517); the checkbox is the open/done half.\n field: 'statusLabel',\n headerName: 'Status',\n width: 150,\n sortable: false,\n valueGetter: (_value: unknown, row: CrmTaskRow) =>\n crmTaskPicklistLabels(row, picklists).status,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <Typography\n variant=\"body2\"\n color={row.status === 'done' ? 'text.secondary' : undefined}\n noWrap\n >\n {crmTaskPicklistLabels(row, picklists).status}\n </Typography>\n ),\n },\n {\n field: 'dueAtMs',\n headerName: 'Due',\n width: 260,\n sortable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center', height: '100%' }}>\n <TaskDueText task={row} nowMs={nowMs} />\n {row.status === 'done' || !scope ? null : (\n <TaskSnoozeMenu\n dueAtMs={row.dueAtMs}\n remindAtMs={row.remindAtMs}\n target={{\n write: {\n scope,\n taskId: row.$id,\n call: crmTaskCallScope(hostId, orgId),\n links: row,\n },\n }}\n disabled={busyId === row.$id}\n />\n )}\n </Stack>\n ),\n },\n {\n field: 'assigneeUid',\n headerName: 'Assignee',\n flex: 1,\n minWidth: 140,\n sortable: false,\n valueGetter: (_value: unknown, row: CrmTaskRow) =>\n directory.nameOf(row.assigneeUid),\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <Typography variant=\"body2\" color={row.assigneeUid ? undefined : 'text.secondary'}>\n {row.assigneeUid ? directory.nameOf(row.assigneeUid) : 'Unassigned'}\n </Typography>\n ),\n },\n {\n field: 'record',\n headerName: 'For',\n flex: 1,\n minWidth: 160,\n sortable: false,\n renderCell: ({ row }: { row: CrmTaskRow }) => (\n <TaskRecordLink task={row} routes={routes} nameOf={nameOf} />\n ),\n },\n ],\n [busyId, toggleDone, nowMs, directory, routes, nameOf, scope, picklists],\n )\n /* The column and sort models are the view's (AGL-2617). */\n const filterColumns = useMemo(\n () => listFilterGridColumns(columns, TASK_FILTER_FIELDS, filterOptions, TASK_FILTER_HEADERS),\n [columns, filterOptions],\n )\n const grid = useCrmViewGrid(views, filterColumns, TASK_HIDDEN_COLUMNS)\n\n return (\n <>\n <CardDisplay\n header={'Tasks'}\n help={pluginDocsHelp('crmTasks', {\n anchor: '#the-tasks-page',\n excerpt:\n 'Calls, emails, meetings and to-dos, each linked to the contact, ' +\n 'company or deal it is for. Overdue and today are read off the ' +\n 'due date as you look.',\n })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n // The record actions, top right and never clipped (AGL-3311).\n action: (\n <CrmListActions>\n <CrmImportButton resource={CRM_TASKS_RESOURCE} noun=\"tasks\" hostId={hostId} />\n <CrmExportButton resource={CRM_TASKS_RESOURCE} hostId={hostId} filter={exportFilter} />\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n onClick={() => setDrawer({ open: true, task: null })}\n >\n {'New task'}\n </Button>\n </CrmListActions>\n ),\n }}\n >\n <Stack spacing={2}>\n {/*\n The saved view, and the clauses narrowing it as chips — \"Show\"\n among them — set in the grid's own Filters panel (AGL-3313).\n */}\n <CrmListToolbar label=\"Task filters\">\n <CrmViewsControl controller={views} allLabel=\"All tasks\" />\n <ListFilterChips\n fields={TASK_FILTER_FIELDS}\n headers={TASK_FILTER_HEADERS}\n clauses={clauses}\n onChange={setClauses}\n options={filterOptions}\n marksServed={false}\n />\n <ToggleButtonGroup\n exclusive\n size=\"small\"\n color=\"primary\"\n value={layout}\n onChange={(_event, next) => {\n if (next) setLayout(next as 'list' | 'calendar')\n }}\n aria-label=\"Task layout\"\n >\n <ToggleButton value=\"list\">{'List'}</ToggleButton>\n <ToggleButton value=\"calendar\">{'Calendar'}</ToggleButton>\n </ToggleButtonGroup>\n </CrmListToolbar>\n <ListQueryNotices refused={refused} notices={list.plan.notices} />\n {status === 'error' ? (\n <Typography variant=\"body2\" color=\"error\">\n {'The tasks could not be loaded. Reload to try again.'}\n </Typography>\n ) : (\n <>\n {/*\n The calendar draws the same rows, so there is no bulk bar\n over it: a selection is a list gesture, and a month grid\n offers nowhere to make one.\n */}\n {layout === 'calendar' ? (\n <TasksCalendar\n tasks={tasks}\n picklists={picklists}\n truncated={list.hasMore}\n onOpen={(task) => setDrawer({ open: true, task })}\n />\n ) : (\n <>\n <TasksBulkBar\n hostId={hostId}\n scope={scope}\n rows={tasks}\n selected={selectedIds}\n onSelectedChange={setSelectedIds}\n directory={directory}\n />\n <CrmColumnOrderProvider value={grid.columnOrder}>\n <ListTable\n rows={tasks}\n columns={grid.columns}\n slots={CRM_LIST_SLOTS}\n selectable={{ selected: selectedIds, onChange: setSelectedIds }}\n loading={status === 'loading'}\n onOpen={(id) => {\n const found = tasks.find((row) => row.$id === id)\n if (found) setDrawer({ open: true, task: found })\n }}\n /*\n * The panel and the search are the grid's; the section\n * answers them, the view through the query (AGL-3313). An\n * empty view is said inside the grid rather than instead of\n * it, so its toolbar stays to choose another view.\n */\n noRowsLabel={filtered ? 'No tasks match these filters' : EMPTY_LABEL[view]}\n noRowsDescription={filtered ? undefined : EMPTY_COPY[view]}\n noRowsAction={\n filtered ? undefined : (\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n onClick={() => setDrawer({ open: true, task: null })}\n >\n {'New task'}\n </Button>\n )\n }\n filterMode=\"server\"\n filterModel={gridFilter.filterModel}\n onFilterModelChange={gridFilter.onFilterModelChange}\n quickFilter\n // The view orders the query (due soonest, or Done most\n // recently due), so the grid sorts nothing itself: a\n // sort over one page would reorder ten rows.\n sortingMode=\"server\"\n disableColumnSorting\n // Columns are the view's, controlled (AGL-2617).\n columnVisibilityModel={grid.columnVisibilityModel}\n onColumnVisibilityModelChange={grid.onColumnVisibilityModelChange}\n // Paged by the footer below, so the grid must not also slice.\n hideFooter\n />\n </CrmColumnOrderProvider>\n <ListPagination\n page={list.page}\n pageSize={list.pageSize}\n rowCount={tasks.length}\n hasMore={list.hasMore}\n onPageChange={list.setPage}\n onPageSizeChange={list.setPageSize}\n />\n </>\n )}\n </>\n )}\n </Stack>\n </CardDisplay>\n <TaskEditDrawer\n open={drawer.open}\n onClose={() => setDrawer((prev) => ({ ...prev, open: false }))}\n hostId={hostId}\n org={orgRecord}\n orgId={orgId}\n scope={scope}\n readTokens={readTokens}\n task={drawer.task}\n seed={{ fromCache, unreadable: status === 'error' }}\n />\n </>\n )\n}\nTasksSection.displayName = 'TasksSection'\n\nexport default TasksSection\n"],"names":["CRM_COLLECTIONS","crmPicklistShownLabel","crmTaskPicklistLabels","crmTaskStatusWrite","pluginDocsHelp","CardDisplay","ListTable","useCrmSavedView","useCrmScope","useCrmViewGrid","CRM_LIST_SLOTS","CrmColumnOrderProvider","CrmViewsControl","useSnackbar","useFirestore","useUser","Button","Checkbox","Stack","ToggleButton","ToggleButtonGroup","Typography","deleteField","doc","serverTimestamp","updateDoc","useCallback","useEffect","useMemo","useState","useCrmRecordNames","useCrmTaskList","useNowMs","useOrgMemberDirectory","useCrmTaskPicklists","crmRoutes","refreshCrmNextActivity","completeCrmTask","crmTaskCallScope","CRM_TASK_KINDS","CRM_TASK_PRIORITIES","CRM_TASK_VIEWS","TASK_LIST_QUERY_FIELDS","listFilterGridColumns","ListPagination","TABLE_PAGE_SIZE_DEFAULT","ListQueryNotices","listQueryRefusals","useListGridFilter","ListFilterChips","CrmListActions","CrmListToolbar","TaskDueText","TaskKindCell","TaskPriorityChip","TaskRecordLink","TaskEditDrawer","TasksCalendar","CrmExportButton","CrmImportButton","CRM_TASKS_RESOURCE","TaskSnoozeMenu","TasksBulkBar","TASK_FILTER_FIELDS","column","kind","path","operators","TASK_FILTER_HEADERS","view","priority","assigneeUid","TASK_HIDDEN_COLUMNS","CALENDAR_PAGE_SIZE","TASK_VIEW_DEFAULT","field","op","value","EMPTY_LABEL","mine","overdue","today","upcoming","open","done","EMPTY_COPY","TasksSection","props","hostId","org","basePath","orgRecord","firestore","data","user","enqueueSnackbar","nowMs","routes","consentGroup","groupId","views","section","state","filters","find","clause","some","option","id","clauses","setClauses","next","setFilters","filter","gridFilter","onChange","selectFields","queryClauses","list","uid","search","searchWords","tasks","status","fromCache","scope","orgId","readTokens","directory","picklists","filterOptions","map","label","type","members","member","refused","plan","fields","headers","options","filtered","length","word","trim","linked","flatMap","task","contactId","companyId","dealId","nameOf","records","selectedIds","setSelectedIds","page","exportFilter","layout","setLayout","setPage","setListPage","setPageSize","setListPageSize","drawer","setDrawer","busyId","setBusyId","toggleDone","$id","completedAtMs","completedByUid","updatedAt","variant","callScope","taskId","cause","Error","message","columns","headerName","width","sortable","filterable","renderCell","row","size","checked","disabled","onClick","event","stopPropagation","slotProps","input","title","flex","minWidth","sx","justifyContent","height","noWrap","textDecoration","undefined","color","notes","valueGetter","_value","direction","spacing","alignItems","dueAtMs","remindAtMs","target","write","call","links","filterColumns","grid","header","help","anchor","excerpt","contentGutterX","contentGutterY","HeaderProps","action","resource","noun","controller","allLabel","marksServed","exclusive","_event","aria-label","notices","truncated","hasMore","onOpen","rows","selected","onSelectedChange","columnOrder","slots","selectable","loading","found","noRowsLabel","noRowsDescription","noRowsAction","filterMode","filterModel","onFilterModelChange","quickFilter","sortingMode","disableColumnSorting","columnVisibilityModel","onColumnVisibilityModelChange","hideFooter","pageSize","rowCount","onPageChange","onPageSizeChange","onClose","prev","seed","unreadable","displayName"],"mappings":"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"}
@@ -14,7 +14,7 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
- import type { CrmActionRecipeId } from '@aglyn/aglyn';
17
+ import type { CrmActionRecipeId } from '../model/crm-recipes';
18
18
  /**
19
19
  * The CRM plugin's console API routes, as the dispatcher keys them.
20
20
  *
@@ -88,13 +88,6 @@ export declare const CRM_API_ROUTES: {
88
88
  * `server/inbound-route.ts`.
89
89
  */
90
90
  readonly inbound: "crm/inbound";
91
- /**
92
- * `GET` — one of the organization's CRM collections, or a site's leads,
93
- * as a CSV streamed over every row (AGL-2662); the contacts and leads
94
- * files are every workspace's (a portability route), see
95
- * `server/export-route.ts`.
96
- */
97
- readonly export: "crm/export";
98
91
  };
99
92
  /**
100
93
  * One site's answer to `crm/recipe-status` (AGL-2639).
@@ -115,7 +108,7 @@ export interface CrmRecipeInstallRequest {
115
108
  hostId: string;
116
109
  orgId?: string;
117
110
  recipeId: CrmActionRecipeId;
118
- /** The site's form a recipe that `needs: 'form'` is keyed on. */
111
+ /** The site's form a recipe that picks one (`picks: 'form'`) is keyed on. */
119
112
  formId?: string;
120
113
  }
121
114
  /** What a successful `crm/recipe-install` answers with. */
@@ -72,13 +72,7 @@
72
72
  * `POST` — the mail provider's signed notice of a message received at a
73
73
  * capture address (AGL-2657); a machine's route, see
74
74
  * `server/inbound-route.ts`.
75
- */ inbound: 'crm/inbound',
76
- /**
77
- * `GET` — one of the organization's CRM collections, or a site's leads,
78
- * as a CSV streamed over every row (AGL-2662); the contacts and leads
79
- * files are every workspace's (a portability route), see
80
- * `server/export-route.ts`.
81
- */ export: 'crm/export'
75
+ */ inbound: 'crm/inbound'
82
76
  };
83
77
  /**
84
78
  * What an organization-level activity line may point at: the CRM's record
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/constants/api-routes.ts"],"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\nimport type { CrmActionRecipeId } from '@aglyn/aglyn'\n\n/**\n * The CRM plugin's console API routes, as the dispatcher keys them.\n *\n * One file both halves import, because the server registers the path and\n * the client fetches it, and a route spelled twice is a route that 404s\n * the day one spelling changes. Client-safe: constants only.\n */\nexport const CRM_API_ROUTES = {\n ping: 'crm/ping',\n /**\n * `POST` — moves one contact to a lifecycle stage, or clears it; see\n * `server.ts`.\n */\n contactStage: 'crm/contact-stage',\n /**\n * `POST` — one holder's profile fields on one or more contacts (AGL-2804):\n * every facet write the console makes; see `server/contact-update.ts`.\n */\n contactUpdate: 'crm/contact-update',\n /**\n * `POST` — lets one or more contacts go from a site, or deletes them once\n * nobody else holds them, keeping every marketing refusal they held\n * (AGL-3338); see `server/contact-remove.ts`.\n */\n contactRemove: 'crm/contact-remove',\n /**\n * `POST` — unlinks the contacts that name a company, then deletes it\n * (AGL-2804); see `server/company-delete.ts`.\n */\n companyDelete: 'crm/company-delete',\n /** `POST` — one email to one person from a record; see `server/email-send.ts`. */\n emailSend: 'crm/email-send',\n /**\n * `POST` — one line in the ORGANIZATION's activity feed for an act the\n * org-level hub performed client-direct (AGL-2634); see\n * `server/org-activity.ts`.\n */\n orgActivity: 'crm/org-activity',\n /**\n * `POST` — installs one recipe's action on one site (AGL-2639): the\n * server builds it, stamps it and writes it into the site's actions;\n * see `server/recipe-routes.ts`.\n */\n recipeInstall: 'crm/recipe-install',\n /**\n * `POST` — which recipes each of the organization's sites carries\n * (AGL-2639), read off the stamps; see `server/recipe-routes.ts`.\n */\n recipeStatus: 'crm/recipe-status',\n /**\n * `POST` — the workspace's email capture address (AGL-2657), minted on\n * the first ask and replaced with `rotate: true`; see\n * `server/inbound-address.ts`.\n */\n inboundAddress: 'crm/inbound-address',\n /**\n * `POST` (a run) or `GET` (the plan) — the daily digest, posted by the\n * scheduler with the cron secret (AGL-2619); a machine's route, see\n * `server/daily-digest-route.ts`.\n */\n dailyDigest: 'crm/daily-digest',\n /**\n * `POST` (a run) or `GET` (the plan) — the hourly task reminders, posted\n * by the scheduler with the cron secret (AGL-2659); a machine's route, see\n * `server/task-reminders-route.ts`.\n */\n taskReminders: 'crm/task-reminders',\n /**\n * `POST` — the mail provider's signed notice of a message received at a\n * capture address (AGL-2657); a machine's route, see\n * `server/inbound-route.ts`.\n */\n inbound: 'crm/inbound',\n /**\n * `GET` — one of the organization's CRM collections, or a site's leads,\n * as a CSV streamed over every row (AGL-2662); the contacts and leads\n * files are every workspace's (a portability route), see\n * `server/export-route.ts`.\n */\n export: 'crm/export',\n} as const\n\n/**\n * One site's answer to `crm/recipe-status` (AGL-2639).\n *\n * `installed` names the recipes a live action on the site is stamped with.\n * `unstamped` counts the live actions that carry NO stamp — every action\n * saved before the stamp existed — and a site with any is one the reader\n * cannot call free of a recipe: the card names it as \"may already have\n * it\" rather than offering the install as if to a blank site.\n */\nexport interface CrmRecipeSiteStatus {\n hostId: string\n installed: CrmActionRecipeId[]\n unstamped: number\n}\n\n/** The body `crm/recipe-install` reads, beside the route scope. */\nexport interface CrmRecipeInstallRequest {\n hostId: string\n orgId?: string\n recipeId: CrmActionRecipeId\n /** The site's form a recipe that `needs: 'form'` is keyed on. */\n formId?: string\n}\n\n/** What a successful `crm/recipe-install` answers with. */\nexport interface CrmRecipeInstallResult {\n ok: true\n actionId: string\n /** The installed action's name, as the site's Actions list will show it. */\n name: string\n recipeId: CrmActionRecipeId\n}\n\n/**\n * What an organization-level activity line may point at: the CRM's record\n * kinds, and nothing the org feed holds for its own reasons (a member, a\n * subscription). The route refuses any other type, so a bulk bar cannot\n * write a line the feed's presenter would render as a workspace event.\n */\nexport const CRM_ORG_ACTIVITY_KINDS = [\n 'contact',\n 'company',\n 'deal',\n 'lead',\n 'task',\n] as const\n\nexport type CrmOrgActivityKind = (typeof CRM_ORG_ACTIVITY_KINDS)[number]\n\n/** The most an activity line may say — a sentence, not a report. */\nexport const CRM_ORG_ACTIVITY_ACTION_MAX = 160\n\n/** The browser-side URL for a route key. */\nexport function crmApiUrl(route: keyof typeof CRM_API_ROUTES): string {\n return `/api/${CRM_API_ROUTES[route]}`\n}\n"],"names":["CRM_API_ROUTES","ping","contactStage","contactUpdate","contactRemove","companyDelete","emailSend","orgActivity","recipeInstall","recipeStatus","inboundAddress","dailyDigest","taskReminders","inbound","export","CRM_ORG_ACTIVITY_KINDS","CRM_ORG_ACTIVITY_ACTION_MAX","crmApiUrl","route"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAID;;;;;;CAMC,GACD,OAAO,MAAMA,iBAAiB;IAC5BC,MAAM;IACN;;;GAGC,GACDC,cAAc;IACd;;;GAGC,GACDC,eAAe;IACf;;;;GAIC,GACDC,eAAe;IACf;;;GAGC,GACDC,eAAe;IACf,gFAAgF,GAChFC,WAAW;IACX;;;;GAIC,GACDC,aAAa;IACb;;;;GAIC,GACDC,eAAe;IACf;;;GAGC,GACDC,cAAc;IACd;;;;GAIC,GACDC,gBAAgB;IAChB;;;;GAIC,GACDC,aAAa;IACb;;;;GAIC,GACDC,eAAe;IACf;;;;GAIC,GACDC,SAAS;IACT;;;;;GAKC,GACDC,QAAQ;AACV,EAAU;AAmCV;;;;;CAKC,GACD,OAAO,MAAMC,yBAAyB;IACpC;IACA;IACA;IACA;IACA;CACD,CAAS;AAIV,kEAAkE,GAClE,OAAO,MAAMC,8BAA8B,IAAG;AAE9C,0CAA0C,GAC1C,OAAO,SAASC,UAAUC,KAAkC;IAC1D,OAAO,CAAC,KAAK,EAAElB,cAAc,CAACkB,MAAM,EAAE;AACxC"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/constants/api-routes.ts"],"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\nimport type { CrmActionRecipeId } from '../model/crm-recipes'\n\n/**\n * The CRM plugin's console API routes, as the dispatcher keys them.\n *\n * One file both halves import, because the server registers the path and\n * the client fetches it, and a route spelled twice is a route that 404s\n * the day one spelling changes. Client-safe: constants only.\n */\nexport const CRM_API_ROUTES = {\n ping: 'crm/ping',\n /**\n * `POST` — moves one contact to a lifecycle stage, or clears it; see\n * `server.ts`.\n */\n contactStage: 'crm/contact-stage',\n /**\n * `POST` — one holder's profile fields on one or more contacts (AGL-2804):\n * every facet write the console makes; see `server/contact-update.ts`.\n */\n contactUpdate: 'crm/contact-update',\n /**\n * `POST` — lets one or more contacts go from a site, or deletes them once\n * nobody else holds them, keeping every marketing refusal they held\n * (AGL-3338); see `server/contact-remove.ts`.\n */\n contactRemove: 'crm/contact-remove',\n /**\n * `POST` — unlinks the contacts that name a company, then deletes it\n * (AGL-2804); see `server/company-delete.ts`.\n */\n companyDelete: 'crm/company-delete',\n /** `POST` — one email to one person from a record; see `server/email-send.ts`. */\n emailSend: 'crm/email-send',\n /**\n * `POST` — one line in the ORGANIZATION's activity feed for an act the\n * org-level hub performed client-direct (AGL-2634); see\n * `server/org-activity.ts`.\n */\n orgActivity: 'crm/org-activity',\n /**\n * `POST` — installs one recipe's action on one site (AGL-2639): the\n * server builds it, stamps it and writes it into the site's actions;\n * see `server/recipe-routes.ts`.\n */\n recipeInstall: 'crm/recipe-install',\n /**\n * `POST` — which recipes each of the organization's sites carries\n * (AGL-2639), read off the stamps; see `server/recipe-routes.ts`.\n */\n recipeStatus: 'crm/recipe-status',\n /**\n * `POST` — the workspace's email capture address (AGL-2657), minted on\n * the first ask and replaced with `rotate: true`; see\n * `server/inbound-address.ts`.\n */\n inboundAddress: 'crm/inbound-address',\n /**\n * `POST` (a run) or `GET` (the plan) — the daily digest, posted by the\n * scheduler with the cron secret (AGL-2619); a machine's route, see\n * `server/daily-digest-route.ts`.\n */\n dailyDigest: 'crm/daily-digest',\n /**\n * `POST` (a run) or `GET` (the plan) — the hourly task reminders, posted\n * by the scheduler with the cron secret (AGL-2659); a machine's route, see\n * `server/task-reminders-route.ts`.\n */\n taskReminders: 'crm/task-reminders',\n /**\n * `POST` — the mail provider's signed notice of a message received at a\n * capture address (AGL-2657); a machine's route, see\n * `server/inbound-route.ts`.\n */\n inbound: 'crm/inbound',\n} as const\n\n/**\n * One site's answer to `crm/recipe-status` (AGL-2639).\n *\n * `installed` names the recipes a live action on the site is stamped with.\n * `unstamped` counts the live actions that carry NO stamp — every action\n * saved before the stamp existed — and a site with any is one the reader\n * cannot call free of a recipe: the card names it as \"may already have\n * it\" rather than offering the install as if to a blank site.\n */\nexport interface CrmRecipeSiteStatus {\n hostId: string\n installed: CrmActionRecipeId[]\n unstamped: number\n}\n\n/** The body `crm/recipe-install` reads, beside the route scope. */\nexport interface CrmRecipeInstallRequest {\n hostId: string\n orgId?: string\n recipeId: CrmActionRecipeId\n /** The site's form a recipe that picks one (`picks: 'form'`) is keyed on. */\n formId?: string\n}\n\n/** What a successful `crm/recipe-install` answers with. */\nexport interface CrmRecipeInstallResult {\n ok: true\n actionId: string\n /** The installed action's name, as the site's Actions list will show it. */\n name: string\n recipeId: CrmActionRecipeId\n}\n\n/**\n * What an organization-level activity line may point at: the CRM's record\n * kinds, and nothing the org feed holds for its own reasons (a member, a\n * subscription). The route refuses any other type, so a bulk bar cannot\n * write a line the feed's presenter would render as a workspace event.\n */\nexport const CRM_ORG_ACTIVITY_KINDS = [\n 'contact',\n 'company',\n 'deal',\n 'lead',\n 'task',\n] as const\n\nexport type CrmOrgActivityKind = (typeof CRM_ORG_ACTIVITY_KINDS)[number]\n\n/** The most an activity line may say — a sentence, not a report. */\nexport const CRM_ORG_ACTIVITY_ACTION_MAX = 160\n\n/** The browser-side URL for a route key. */\nexport function crmApiUrl(route: keyof typeof CRM_API_ROUTES): string {\n return `/api/${CRM_API_ROUTES[route]}`\n}\n"],"names":["CRM_API_ROUTES","ping","contactStage","contactUpdate","contactRemove","companyDelete","emailSend","orgActivity","recipeInstall","recipeStatus","inboundAddress","dailyDigest","taskReminders","inbound","CRM_ORG_ACTIVITY_KINDS","CRM_ORG_ACTIVITY_ACTION_MAX","crmApiUrl","route"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAID;;;;;;CAMC,GACD,OAAO,MAAMA,iBAAiB;IAC5BC,MAAM;IACN;;;GAGC,GACDC,cAAc;IACd;;;GAGC,GACDC,eAAe;IACf;;;;GAIC,GACDC,eAAe;IACf;;;GAGC,GACDC,eAAe;IACf,gFAAgF,GAChFC,WAAW;IACX;;;;GAIC,GACDC,aAAa;IACb;;;;GAIC,GACDC,eAAe;IACf;;;GAGC,GACDC,cAAc;IACd;;;;GAIC,GACDC,gBAAgB;IAChB;;;;GAIC,GACDC,aAAa;IACb;;;;GAIC,GACDC,eAAe;IACf;;;;GAIC,GACDC,SAAS;AACX,EAAU;AAmCV;;;;;CAKC,GACD,OAAO,MAAMC,yBAAyB;IACpC;IACA;IACA;IACA;IACA;CACD,CAAS;AAIV,kEAAkE,GAClE,OAAO,MAAMC,8BAA8B,IAAG;AAE9C,0CAA0C,GAC1C,OAAO,SAASC,UAAUC,KAAkC;IAC1D,OAAO,CAAC,KAAK,EAAEjB,cAAc,CAACiB,MAAM,EAAE;AACxC"}
@@ -14,3 +14,9 @@
14
14
  export declare const BUNDLE_ID = "crm";
15
15
  /** The records band's meter in the monthly usage sweep (`server/crm-records-meter.ts`). */
16
16
  export declare const CRM_RECORDS_METER_ID = "records";
17
+ /**
18
+ * The automation steps this plugin runs for the workflows engine
19
+ * (`server/automation-steps.ts`), as `plugins.config.json` declares them
20
+ * under `serverSteps`.
21
+ */
22
+ export declare const CRM_STEP_TYPES: readonly ["setContactStage", "addContactTag", "assignContactOwner", "createCrmTask", "logCrmActivity"];
@@ -11,5 +11,16 @@
11
11
  * (AGL-2614), so `contacts` now reads as an unknown id like any other.
12
12
  */ export const BUNDLE_ID = 'crm';
13
13
  /** The records band's meter in the monthly usage sweep (`server/crm-records-meter.ts`). */ export const CRM_RECORDS_METER_ID = 'records';
14
+ /**
15
+ * The automation steps this plugin runs for the workflows engine
16
+ * (`server/automation-steps.ts`), as `plugins.config.json` declares them
17
+ * under `serverSteps`.
18
+ */ export const CRM_STEP_TYPES = [
19
+ 'setContactStage',
20
+ 'addContactTag',
21
+ 'assignContactOwner',
22
+ 'createCrmTask',
23
+ 'logCrmActivity'
24
+ ];
14
25
 
15
26
  //# sourceMappingURL=bundle-common.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/constants/bundle-common.ts"],"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 */\n\n/**\n * The persisted plugin id (AGL-2595). It was `contacts` while the surface was\n * one list; the stored lists were rewritten and the plugin manager's alias for\n * the old value was retired once that backfill reported nothing left\n * (AGL-2614), so `contacts` now reads as an unknown id like any other.\n */\nexport const BUNDLE_ID = 'crm'\n\n/** The records band's meter in the monthly usage sweep (`server/crm-records-meter.ts`). */\nexport const CRM_RECORDS_METER_ID = 'records'\n"],"names":["BUNDLE_ID","CRM_RECORDS_METER_ID"],"mappings":"AAAA;;;;;;CAMC,GAED;;;;;CAKC,GACD,OAAO,MAAMA,YAAY,MAAK;AAE9B,yFAAyF,GACzF,OAAO,MAAMC,uBAAuB,UAAS"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/constants/bundle-common.ts"],"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 */\n\n/**\n * The persisted plugin id (AGL-2595). It was `contacts` while the surface was\n * one list; the stored lists were rewritten and the plugin manager's alias for\n * the old value was retired once that backfill reported nothing left\n * (AGL-2614), so `contacts` now reads as an unknown id like any other.\n */\nexport const BUNDLE_ID = 'crm'\n\n/** The records band's meter in the monthly usage sweep (`server/crm-records-meter.ts`). */\nexport const CRM_RECORDS_METER_ID = 'records'\n\n/**\n * The automation steps this plugin runs for the workflows engine\n * (`server/automation-steps.ts`), as `plugins.config.json` declares them\n * under `serverSteps`.\n */\nexport const CRM_STEP_TYPES = [\n 'setContactStage',\n 'addContactTag',\n 'assignContactOwner',\n 'createCrmTask',\n 'logCrmActivity',\n] as const\n"],"names":["BUNDLE_ID","CRM_RECORDS_METER_ID","CRM_STEP_TYPES"],"mappings":"AAAA;;;;;;CAMC,GAED;;;;;CAKC,GACD,OAAO,MAAMA,YAAY,MAAK;AAE9B,yFAAyF,GACzF,OAAO,MAAMC,uBAAuB,UAAS;AAE7C;;;;CAIC,GACD,OAAO,MAAMC,iBAAiB;IAC5B;IACA;IACA;IACA;IACA;CACD,CAAS"}
@@ -17,6 +17,20 @@
17
17
  import type { ListFilterField } from '@aglyn/shared-ui-jsx/const/list-filter';
18
18
  import type { ListQueryDeclaration, ListQuerySort } from '@aglyn/shared-ui-jsx/const/list-query-plan';
19
19
  export declare const COMPANY_LIST_FILTER_FIELDS: readonly ListFilterField[];
20
+ /** The picklist columns the list filters by, each with the list its choices come from. */
21
+ export declare const COMPANY_PICKLIST_FILTERS: readonly [{
22
+ readonly column: "type";
23
+ readonly picklistId: "accountType";
24
+ readonly header: "Type";
25
+ }, {
26
+ readonly column: "industry";
27
+ readonly picklistId: "industry";
28
+ readonly header: "Industry";
29
+ }, {
30
+ readonly column: "rating";
31
+ readonly picklistId: "rating";
32
+ readonly header: "Rating";
33
+ }];
20
34
  /**
21
35
  * A collaborator's search (see `prefixSearch` in `useCrmListQuery`): the
22
36
  * start of the name, beside the scope clause — the prefix range the
@@ -31,6 +31,12 @@ import { CRM_LIST_SEARCH } from "../model/crm-list-query.js";
31
31
  * choice from the roster, and "No next activity" asks `nextTaskAtMs ==
32
32
  * null`. Each equality rides one `(field, updatedAt DESC)` composite, and
33
33
  * one `(field, nameLower ASC)` beside it for the prefix.
34
+ *
35
+ * Type, Industry and Rating (AGL-3514) are choices from the org's lists,
36
+ * asked of the KEY each writer stores beside the label (`typeKey`,
37
+ * `industryKey`, `ratingKey` — see `crmCompanyListFields`): a choice's
38
+ * value is the key, its caption the label, so the query compares what
39
+ * the record keyed rather than how the label happens to be cased.
34
40
  */ export const COMPANY_LIST_FILTER_FIELDS = [
35
41
  {
36
42
  column: 'name',
@@ -52,7 +58,51 @@ import { CRM_LIST_SEARCH } from "../model/crm-list-query.js";
52
58
  'isAnyOf'
53
59
  ]
54
60
  },
55
- CRM_NEXT_ACTIVITY_FILTER_FIELD
61
+ CRM_NEXT_ACTIVITY_FILTER_FIELD,
62
+ {
63
+ column: 'type',
64
+ kind: 'exact',
65
+ path: 'typeKey',
66
+ operators: [
67
+ 'equals',
68
+ 'isAnyOf'
69
+ ]
70
+ },
71
+ {
72
+ column: 'industry',
73
+ kind: 'exact',
74
+ path: 'industryKey',
75
+ operators: [
76
+ 'equals',
77
+ 'isAnyOf'
78
+ ]
79
+ },
80
+ {
81
+ column: 'rating',
82
+ kind: 'exact',
83
+ path: 'ratingKey',
84
+ operators: [
85
+ 'equals',
86
+ 'isAnyOf'
87
+ ]
88
+ }
89
+ ];
90
+ /** The picklist columns the list filters by, each with the list its choices come from. */ export const COMPANY_PICKLIST_FILTERS = [
91
+ {
92
+ column: 'type',
93
+ picklistId: 'accountType',
94
+ header: 'Type'
95
+ },
96
+ {
97
+ column: 'industry',
98
+ picklistId: 'industry',
99
+ header: 'Industry'
100
+ },
101
+ {
102
+ column: 'rating',
103
+ picklistId: 'rating',
104
+ header: 'Rating'
105
+ }
56
106
  ];
57
107
  /**
58
108
  * A collaborator's search (see `prefixSearch` in `useCrmListQuery`): the
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/constants/company-filters.ts"],"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\nimport type { ListFilterField } from '@aglyn/shared-ui-jsx/const/list-filter'\n\nimport { CRM_NEXT_ACTIVITY_FILTER_FIELD } from '../components/crm-next-activity-column'\nimport type { ListQueryDeclaration, ListQuerySort } from '@aglyn/shared-ui-jsx/const/list-query-plan'\nimport { CRM_LIST_SEARCH } from '../model/crm-list-query'\n\n/*\n * Companies (`orgs/{orgId}/companies`, read scoped to a host) — every clause\n * and the search word on the list's one query, newest change first\n * (AGL-3321).\n *\n * The search box reads `searchTokens`, the word prefixes of the name and\n * the domain every company writer stamps (`crmCompanyListFields`). Under a\n * site the scope clause (`visibleTo array-contains-any`) is the query's one\n * array clause, and the search folds into it (`scopedSearchTokens`) for a\n * reader who may drop it.\n *\n * The name is also an exact match and a PREFIX range over `nameLower` — the\n * list's one range, which then orders the list by name. The owner is a\n * choice from the roster, and \"No next activity\" asks `nextTaskAtMs ==\n * null`. Each equality rides one `(field, updatedAt DESC)` composite, and\n * one `(field, nameLower ASC)` beside it for the prefix.\n */\nexport const COMPANY_LIST_FILTER_FIELDS: readonly ListFilterField[] = [\n {\n column: 'name',\n kind: 'text',\n path: 'name',\n lowerPath: 'nameLower',\n presence: 'always',\n operators: ['equals', 'startsWith'],\n },\n {\n column: 'ownerUid',\n kind: 'exact',\n path: 'ownerUid',\n operators: ['equals', 'isAnyOf'],\n },\n CRM_NEXT_ACTIVITY_FILTER_FIELD,\n]\n\n/**\n * A collaborator's search (see `prefixSearch` in `useCrmListQuery`): the\n * start of the name, beside the scope clause — the prefix range the\n * `(field, nameLower)` composites already serve.\n */\nexport const COMPANY_PREFIX_SEARCH = {\n field: COMPANY_LIST_FILTER_FIELDS[0],\n notice: 'Search matches the start of a company’s name for access limited to specific sites.',\n}\n\n/** The list's orders: newest change first, and by name under a prefix. */\nexport const COMPANY_LIST_SORTS: readonly ListQuerySort[] = [\n { path: 'updatedAt', direction: 'desc' },\n { path: 'nameLower', direction: 'asc' },\n]\n\nexport const COMPANY_LIST_DECLARATION: ListQueryDeclaration = {\n fields: COMPANY_LIST_FILTER_FIELDS,\n sorts: COMPANY_LIST_SORTS,\n search: CRM_LIST_SEARCH,\n}\n"],"names":["CRM_NEXT_ACTIVITY_FILTER_FIELD","CRM_LIST_SEARCH","COMPANY_LIST_FILTER_FIELDS","column","kind","path","lowerPath","presence","operators","COMPANY_PREFIX_SEARCH","field","notice","COMPANY_LIST_SORTS","direction","COMPANY_LIST_DECLARATION","fields","sorts","search"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAID,SAASA,8BAA8B,QAAQ,4CAAwC;AAEvF,SAASC,eAAe,QAAQ,6BAAyB;AAEzD;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,MAAMC,6BAAyD;IACpE;QACEC,QAAQ;QACRC,MAAM;QACNC,MAAM;QACNC,WAAW;QACXC,UAAU;QACVC,WAAW;YAAC;YAAU;SAAa;IACrC;IACA;QACEL,QAAQ;QACRC,MAAM;QACNC,MAAM;QACNG,WAAW;YAAC;YAAU;SAAU;IAClC;IACAR;CACD,CAAA;AAED;;;;CAIC,GACD,OAAO,MAAMS,wBAAwB;IACnCC,OAAOR,0BAA0B,CAAC,EAAE;IACpCS,QAAQ;AACV,EAAC;AAED,wEAAwE,GACxE,OAAO,MAAMC,qBAA+C;IAC1D;QAAEP,MAAM;QAAaQ,WAAW;IAAO;IACvC;QAAER,MAAM;QAAaQ,WAAW;IAAM;CACvC,CAAA;AAED,OAAO,MAAMC,2BAAiD;IAC5DC,QAAQb;IACRc,OAAOJ;IACPK,QAAQhB;AACV,EAAC"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/constants/company-filters.ts"],"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\nimport type { ListFilterField } from '@aglyn/shared-ui-jsx/const/list-filter'\n\nimport { CRM_NEXT_ACTIVITY_FILTER_FIELD } from '../components/crm-next-activity-column'\nimport type { ListQueryDeclaration, ListQuerySort } from '@aglyn/shared-ui-jsx/const/list-query-plan'\nimport { CRM_LIST_SEARCH } from '../model/crm-list-query'\n\n/*\n * Companies (`orgs/{orgId}/companies`, read scoped to a host) — every clause\n * and the search word on the list's one query, newest change first\n * (AGL-3321).\n *\n * The search box reads `searchTokens`, the word prefixes of the name and\n * the domain every company writer stamps (`crmCompanyListFields`). Under a\n * site the scope clause (`visibleTo array-contains-any`) is the query's one\n * array clause, and the search folds into it (`scopedSearchTokens`) for a\n * reader who may drop it.\n *\n * The name is also an exact match and a PREFIX range over `nameLower` — the\n * list's one range, which then orders the list by name. The owner is a\n * choice from the roster, and \"No next activity\" asks `nextTaskAtMs ==\n * null`. Each equality rides one `(field, updatedAt DESC)` composite, and\n * one `(field, nameLower ASC)` beside it for the prefix.\n *\n * Type, Industry and Rating (AGL-3514) are choices from the org's lists,\n * asked of the KEY each writer stores beside the label (`typeKey`,\n * `industryKey`, `ratingKey` — see `crmCompanyListFields`): a choice's\n * value is the key, its caption the label, so the query compares what\n * the record keyed rather than how the label happens to be cased.\n */\nexport const COMPANY_LIST_FILTER_FIELDS: readonly ListFilterField[] = [\n {\n column: 'name',\n kind: 'text',\n path: 'name',\n lowerPath: 'nameLower',\n presence: 'always',\n operators: ['equals', 'startsWith'],\n },\n {\n column: 'ownerUid',\n kind: 'exact',\n path: 'ownerUid',\n operators: ['equals', 'isAnyOf'],\n },\n CRM_NEXT_ACTIVITY_FILTER_FIELD,\n { column: 'type', kind: 'exact', path: 'typeKey', operators: ['equals', 'isAnyOf'] },\n { column: 'industry', kind: 'exact', path: 'industryKey', operators: ['equals', 'isAnyOf'] },\n { column: 'rating', kind: 'exact', path: 'ratingKey', operators: ['equals', 'isAnyOf'] },\n]\n\n/** The picklist columns the list filters by, each with the list its choices come from. */\nexport const COMPANY_PICKLIST_FILTERS = [\n { column: 'type', picklistId: 'accountType', header: 'Type' },\n { column: 'industry', picklistId: 'industry', header: 'Industry' },\n { column: 'rating', picklistId: 'rating', header: 'Rating' },\n] as const\n\n/**\n * A collaborator's search (see `prefixSearch` in `useCrmListQuery`): the\n * start of the name, beside the scope clause — the prefix range the\n * `(field, nameLower)` composites already serve.\n */\nexport const COMPANY_PREFIX_SEARCH = {\n field: COMPANY_LIST_FILTER_FIELDS[0],\n notice: 'Search matches the start of a company’s name for access limited to specific sites.',\n}\n\n/** The list's orders: newest change first, and by name under a prefix. */\nexport const COMPANY_LIST_SORTS: readonly ListQuerySort[] = [\n { path: 'updatedAt', direction: 'desc' },\n { path: 'nameLower', direction: 'asc' },\n]\n\nexport const COMPANY_LIST_DECLARATION: ListQueryDeclaration = {\n fields: COMPANY_LIST_FILTER_FIELDS,\n sorts: COMPANY_LIST_SORTS,\n search: CRM_LIST_SEARCH,\n}\n"],"names":["CRM_NEXT_ACTIVITY_FILTER_FIELD","CRM_LIST_SEARCH","COMPANY_LIST_FILTER_FIELDS","column","kind","path","lowerPath","presence","operators","COMPANY_PICKLIST_FILTERS","picklistId","header","COMPANY_PREFIX_SEARCH","field","notice","COMPANY_LIST_SORTS","direction","COMPANY_LIST_DECLARATION","fields","sorts","search"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAID,SAASA,8BAA8B,QAAQ,4CAAwC;AAEvF,SAASC,eAAe,QAAQ,6BAAyB;AAEzD;;;;;;;;;;;;;;;;;;;;;;CAsBC,GACD,OAAO,MAAMC,6BAAyD;IACpE;QACEC,QAAQ;QACRC,MAAM;QACNC,MAAM;QACNC,WAAW;QACXC,UAAU;QACVC,WAAW;YAAC;YAAU;SAAa;IACrC;IACA;QACEL,QAAQ;QACRC,MAAM;QACNC,MAAM;QACNG,WAAW;YAAC;YAAU;SAAU;IAClC;IACAR;IACA;QAAEG,QAAQ;QAAQC,MAAM;QAASC,MAAM;QAAWG,WAAW;YAAC;YAAU;SAAU;IAAC;IACnF;QAAEL,QAAQ;QAAYC,MAAM;QAASC,MAAM;QAAeG,WAAW;YAAC;YAAU;SAAU;IAAC;IAC3F;QAAEL,QAAQ;QAAUC,MAAM;QAASC,MAAM;QAAaG,WAAW;YAAC;YAAU;SAAU;IAAC;CACxF,CAAA;AAED,wFAAwF,GACxF,OAAO,MAAMC,2BAA2B;IACtC;QAAEN,QAAQ;QAAQO,YAAY;QAAeC,QAAQ;IAAO;IAC5D;QAAER,QAAQ;QAAYO,YAAY;QAAYC,QAAQ;IAAW;IACjE;QAAER,QAAQ;QAAUO,YAAY;QAAUC,QAAQ;IAAS;CAC5D,CAAS;AAEV;;;;CAIC,GACD,OAAO,MAAMC,wBAAwB;IACnCC,OAAOX,0BAA0B,CAAC,EAAE;IACpCY,QAAQ;AACV,EAAC;AAED,wEAAwE,GACxE,OAAO,MAAMC,qBAA+C;IAC1D;QAAEV,MAAM;QAAaW,WAAW;IAAO;IACvC;QAAEX,MAAM;QAAaW,WAAW;IAAM;CACvC,CAAA;AAED,OAAO,MAAMC,2BAAiD;IAC5DC,QAAQhB;IACRiB,OAAOJ;IACPK,QAAQnB;AACV,EAAC"}
@@ -18,6 +18,8 @@ import { type ContactFieldDefinition } from '@aglyn/aglyn';
18
18
  import type { ListFilterField, ListFilterRequest } from '@aglyn/shared-ui-jsx/const/list-filter';
19
19
  import type { ListQueryDeclaration, ListQuerySort } from '@aglyn/shared-ui-jsx/const/list-query-plan';
20
20
  import { type CrmClauseAsked } from '../model/crm-list-query';
21
+ /** The column a contact's lead source filters as (AGL-3511). */
22
+ export declare const CONTACT_LEAD_SOURCE_COLUMN = "leadSource";
21
23
  /** What the Filters panel offers on a contact, in the grid's grammar. */
22
24
  export declare const CONTACT_LIST_FILTER_FIELDS: readonly ListFilterField[];
23
25
  /**
@@ -111,6 +111,7 @@ import { CRM_LIST_SEARCH, crmAnyOf, crmClauseValues } from "../model/crm-list-qu
111
111
  'contains'
112
112
  ]
113
113
  };
114
+ /** The column a contact's lead source filters as (AGL-3511). */ export const CONTACT_LEAD_SOURCE_COLUMN = 'leadSource';
114
115
  /** What the Filters panel offers on a contact, in the grid's grammar. */ export const CONTACT_LIST_FILTER_FIELDS = [
115
116
  NAME_FIELD,
116
117
  EMAIL_FIELD,
@@ -224,6 +225,20 @@ import { CRM_LIST_SEARCH, crmAnyOf, crmClauseValues } from "../model/crm-list-qu
224
225
  ]
225
226
  },
226
227
  /*
228
+ * A holder's lead source (AGL-3511), picked from the org's Lead source
229
+ * values and asked through its `leadSource` facet key — the label as the
230
+ * picklist compares it.
231
+ */ {
232
+ column: CONTACT_LEAD_SOURCE_COLUMN,
233
+ kind: 'exact',
234
+ path: 'leadSource',
235
+ operators: [
236
+ 'equals',
237
+ 'isAnyOf',
238
+ 'isNotEmpty'
239
+ ]
240
+ },
241
+ /*
227
242
  * The verdict on the address (AGL-3245), asked through `emailStatus` —
228
243
  * `none` for a person nothing has been said about, which is what "is
229
244
  * empty" asks.
@@ -325,6 +340,7 @@ import { CRM_LIST_SEARCH, crmAnyOf, crmClauseValues } from "../model/crm-list-qu
325
340
  [CRM_CONTACT_VIEW_FIELDS.stage]: 'Stage',
326
341
  [CRM_CONTACT_VIEW_FIELDS.source]: 'Source',
327
342
  [CRM_CONTACT_VIEW_FIELDS.company]: 'Company',
343
+ [CONTACT_LEAD_SOURCE_COLUMN]: 'Lead source',
328
344
  emailState: 'Email'
329
345
  };
330
346
  /*------------------------------------------
@@ -428,7 +444,8 @@ export const CONTACT_LIST_DECLARATION = {
428
444
  [CRM_CONTACT_VIEW_FIELDS.company]: 'company',
429
445
  [CRM_CONTACT_VIEW_FIELDS.tags]: 'tag',
430
446
  [CRM_CONTACT_VIEW_FIELDS.orders]: 'orders',
431
- [CRM_CONTACT_VIEW_FIELDS.ltv]: 'ltv'
447
+ [CRM_CONTACT_VIEW_FIELDS.ltv]: 'ltv',
448
+ [CONTACT_LEAD_SOURCE_COLUMN]: 'leadSource'
432
449
  };
433
450
  /** Why a reader whose access is some sites cannot filter by a holder's field. */ const LIMITED_ACCESS = 'your access is limited to specific sites, which this filter cannot be combined with — an organization administrator can use it';
434
451
  /** The facet field a grid column names, or null for one that is not a facet field. */ function facetFieldOf(column) {