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

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 (514) 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-record-picker.d.ts +15 -0
  34. package/src/lib/components/crm-record-picker.js +16 -10
  35. package/src/lib/components/crm-record-picker.js.map +1 -1
  36. package/src/lib/components/crm-transfer-buttons.d.ts +54 -0
  37. package/src/lib/components/crm-transfer-buttons.js +167 -0
  38. package/src/lib/components/crm-transfer-buttons.js.map +1 -0
  39. package/src/lib/components/deal-contact-roles-card.d.ts +46 -0
  40. package/src/lib/components/deal-contact-roles-card.js +368 -0
  41. package/src/lib/components/deal-contact-roles-card.js.map +1 -0
  42. package/src/lib/components/deal-detail-page.d.ts +3 -2
  43. package/src/lib/components/deal-detail-page.js +25 -6
  44. package/src/lib/components/deal-detail-page.js.map +1 -1
  45. package/src/lib/components/deal-edit-drawer.d.ts +10 -0
  46. package/src/lib/components/deal-edit-drawer.js +219 -10
  47. package/src/lib/components/deal-edit-drawer.js.map +1 -1
  48. package/src/lib/components/deal-properties-card.d.ts +7 -0
  49. package/src/lib/components/deal-properties-card.js +34 -3
  50. package/src/lib/components/deal-properties-card.js.map +1 -1
  51. package/src/lib/components/deal-stage-card.d.ts +4 -0
  52. package/src/lib/components/deal-stage-card.js +10 -2
  53. package/src/lib/components/deal-stage-card.js.map +1 -1
  54. package/src/lib/components/deals-bulk-bar.d.ts +0 -3
  55. package/src/lib/components/deals-bulk-bar.js +7 -20
  56. package/src/lib/components/deals-bulk-bar.js.map +1 -1
  57. package/src/lib/components/deals-section.d.ts +3 -3
  58. package/src/lib/components/deals-section.js +123 -63
  59. package/src/lib/components/deals-section.js.map +1 -1
  60. package/src/lib/components/fields-section.js +31 -17
  61. package/src/lib/components/fields-section.js.map +1 -1
  62. package/src/lib/components/lead-convert-dialog.d.ts +4 -0
  63. package/src/lib/components/lead-convert-dialog.js +23 -1
  64. package/src/lib/components/lead-convert-dialog.js.map +1 -1
  65. package/src/lib/components/lead-detail-page.js +8 -2
  66. package/src/lib/components/lead-detail-page.js.map +1 -1
  67. package/src/lib/components/lead-profile-fields.d.ts +71 -0
  68. package/src/lib/components/lead-profile-fields.js +386 -0
  69. package/src/lib/components/lead-profile-fields.js.map +1 -0
  70. package/src/lib/components/lead-properties-card.d.ts +2 -1
  71. package/src/lib/components/lead-properties-card.js +85 -176
  72. package/src/lib/components/lead-properties-card.js.map +1 -1
  73. package/src/lib/components/lead-source-select.d.ts +4 -23
  74. package/src/lib/components/lead-source-select.js +9 -73
  75. package/src/lib/components/lead-source-select.js.map +1 -1
  76. package/src/lib/components/lead-status-chip.d.ts +9 -3
  77. package/src/lib/components/lead-status-chip.js +8 -4
  78. package/src/lib/components/lead-status-chip.js.map +1 -1
  79. package/src/lib/components/lead-status-options.d.ts +20 -0
  80. package/src/lib/components/lead-status-options.js +51 -0
  81. package/src/lib/components/lead-status-options.js.map +1 -0
  82. package/src/lib/components/lead-unqualify-dialog.d.ts +5 -0
  83. package/src/lib/components/lead-unqualify-dialog.js +50 -18
  84. package/src/lib/components/lead-unqualify-dialog.js.map +1 -1
  85. package/src/lib/components/leads-bulk-bar.d.ts +0 -3
  86. package/src/lib/components/leads-bulk-bar.js +29 -29
  87. package/src/lib/components/leads-bulk-bar.js.map +1 -1
  88. package/src/lib/components/leads-section.js +120 -68
  89. package/src/lib/components/leads-section.js.map +1 -1
  90. package/src/lib/components/linked-deals-card.d.ts +4 -0
  91. package/src/lib/components/linked-deals-card.js +47 -3
  92. package/src/lib/components/linked-deals-card.js.map +1 -1
  93. package/src/lib/components/log-activity-dialog.js +43 -3
  94. package/src/lib/components/log-activity-dialog.js.map +1 -1
  95. package/src/lib/components/new-contact-drawer.d.ts +8 -0
  96. package/src/lib/components/new-contact-drawer.js +108 -6
  97. package/src/lib/components/new-contact-drawer.js.map +1 -1
  98. package/src/lib/components/new-lead-drawer.d.ts +9 -2
  99. package/src/lib/components/new-lead-drawer.js +88 -121
  100. package/src/lib/components/new-lead-drawer.js.map +1 -1
  101. package/src/lib/components/picklist-select.d.ts +36 -0
  102. package/src/lib/components/picklist-select.js +114 -0
  103. package/src/lib/components/picklist-select.js.map +1 -0
  104. package/src/lib/components/picklist-values-card.d.ts +34 -0
  105. package/src/lib/components/{lead-source-values-card.js → picklist-values-card.js} +241 -58
  106. package/src/lib/components/picklist-values-card.js.map +1 -0
  107. package/src/lib/components/pipeline-stages-dialog.d.ts +7 -0
  108. package/src/lib/components/pipeline-stages-dialog.js +26 -4
  109. package/src/lib/components/pipeline-stages-dialog.js.map +1 -1
  110. package/src/lib/components/pipelines-dialog.js +15 -6
  111. package/src/lib/components/pipelines-dialog.js.map +1 -1
  112. package/src/lib/components/recent-activity-feed.js +20 -5
  113. package/src/lib/components/recent-activity-feed.js.map +1 -1
  114. package/src/lib/components/recipes-card.js +4 -2
  115. package/src/lib/components/recipes-card.js.map +1 -1
  116. package/src/lib/components/record-tasks-card.js +15 -8
  117. package/src/lib/components/record-tasks-card.js.map +1 -1
  118. package/src/lib/components/reports/forecast-card.d.ts +6 -0
  119. package/src/lib/components/reports/forecast-card.js +101 -3
  120. package/src/lib/components/reports/forecast-card.js.map +1 -1
  121. package/src/lib/components/reports/lead-funnel-card.d.ts +12 -0
  122. package/src/lib/components/reports/lead-funnel-card.js +9 -5
  123. package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
  124. package/src/lib/components/reports/lead-source-card.d.ts +23 -0
  125. package/src/lib/components/reports/lead-source-card.js +318 -0
  126. package/src/lib/components/reports/lead-source-card.js.map +1 -0
  127. package/src/lib/components/reports/report-export.js +1 -1
  128. package/src/lib/components/reports/report-export.js.map +1 -1
  129. package/src/lib/components/reports-section.js +8 -0
  130. package/src/lib/components/reports-section.js.map +1 -1
  131. package/src/lib/components/sharing-rule-drawer.d.ts +5 -0
  132. package/src/lib/components/sharing-rule-drawer.js +108 -19
  133. package/src/lib/components/sharing-rule-drawer.js.map +1 -1
  134. package/src/lib/components/sharing-rules-card.js +11 -3
  135. package/src/lib/components/sharing-rules-card.js.map +1 -1
  136. package/src/lib/components/task-cells.d.ts +9 -1
  137. package/src/lib/components/task-cells.js +9 -4
  138. package/src/lib/components/task-cells.js.map +1 -1
  139. package/src/lib/components/task-edit-drawer.js +111 -43
  140. package/src/lib/components/task-edit-drawer.js.map +1 -1
  141. package/src/lib/components/tasks-bulk-bar.d.ts +0 -3
  142. package/src/lib/components/tasks-bulk-bar.js +7 -20
  143. package/src/lib/components/tasks-bulk-bar.js.map +1 -1
  144. package/src/lib/components/tasks-calendar.d.ts +3 -0
  145. package/src/lib/components/tasks-calendar.js +8 -1
  146. package/src/lib/components/tasks-calendar.js.map +1 -1
  147. package/src/lib/components/tasks-section.d.ts +3 -3
  148. package/src/lib/components/tasks-section.js +58 -43
  149. package/src/lib/components/tasks-section.js.map +1 -1
  150. package/src/lib/constants/api-routes.d.ts +2 -9
  151. package/src/lib/constants/api-routes.js +1 -7
  152. package/src/lib/constants/api-routes.js.map +1 -1
  153. package/src/lib/constants/bundle-common.d.ts +6 -0
  154. package/src/lib/constants/bundle-common.js +11 -0
  155. package/src/lib/constants/bundle-common.js.map +1 -1
  156. package/src/lib/constants/company-filters.d.ts +14 -0
  157. package/src/lib/constants/company-filters.js +51 -1
  158. package/src/lib/constants/company-filters.js.map +1 -1
  159. package/src/lib/constants/contact-filters.d.ts +2 -0
  160. package/src/lib/constants/contact-filters.js +18 -1
  161. package/src/lib/constants/contact-filters.js.map +1 -1
  162. package/src/lib/constants/deal-filters.d.ts +22 -1
  163. package/src/lib/constants/deal-filters.js +67 -4
  164. package/src/lib/constants/deal-filters.js.map +1 -1
  165. package/src/lib/declarations.console-server.d.ts +3 -0
  166. package/src/lib/declarations.console-server.js +35 -0
  167. package/src/lib/declarations.console-server.js.map +1 -1
  168. package/src/lib/declarations.d.ts +26 -0
  169. package/src/lib/declarations.js +35 -0
  170. package/src/lib/declarations.js.map +1 -0
  171. package/src/lib/declarations.server.d.ts +11 -0
  172. package/src/lib/declarations.server.js +92 -1
  173. package/src/lib/declarations.server.js.map +1 -1
  174. package/src/lib/hooks/use-company-picklists.d.ts +15 -0
  175. package/src/lib/hooks/use-company-picklists.js +55 -0
  176. package/src/lib/hooks/use-company-picklists.js.map +1 -0
  177. package/src/lib/hooks/use-crm-picklist.d.ts +25 -0
  178. package/src/lib/hooks/use-crm-picklist.js +53 -0
  179. package/src/lib/hooks/use-crm-picklist.js.map +1 -0
  180. package/src/lib/hooks/use-crm-record-names.d.ts +16 -0
  181. package/src/lib/hooks/use-crm-record-names.js +45 -19
  182. package/src/lib/hooks/use-crm-record-names.js.map +1 -1
  183. package/src/lib/hooks/use-crm-task-picklists.d.ts +11 -0
  184. package/src/lib/hooks/use-crm-task-picklists.js +45 -0
  185. package/src/lib/hooks/use-crm-task-picklists.js.map +1 -0
  186. package/src/lib/hooks/use-deals.d.ts +14 -0
  187. package/src/lib/hooks/use-deals.js +29 -0
  188. package/src/lib/hooks/use-deals.js.map +1 -1
  189. package/src/lib/hooks/use-lead-picklists.d.ts +14 -0
  190. package/src/lib/hooks/use-lead-picklists.js +46 -0
  191. package/src/lib/hooks/use-lead-picklists.js.map +1 -0
  192. package/src/lib/hooks/use-lead-source-picklist.d.ts +5 -19
  193. package/src/lib/hooks/use-lead-source-picklist.js +12 -22
  194. package/src/lib/hooks/use-lead-source-picklist.js.map +1 -1
  195. package/src/lib/hooks/use-lead-status-picklist.d.ts +9 -0
  196. package/src/lib/hooks/use-lead-status-picklist.js +40 -0
  197. package/src/lib/hooks/use-lead-status-picklist.js.map +1 -0
  198. package/src/lib/model/companies.d.ts +32 -3
  199. package/src/lib/model/companies.js +133 -16
  200. package/src/lib/model/companies.js.map +1 -1
  201. package/src/lib/model/contact-merge.d.ts +27 -3
  202. package/src/lib/model/contact-merge.js +81 -7
  203. package/src/lib/model/contact-merge.js.map +1 -1
  204. package/src/lib/model/contact-record.d.ts +17 -0
  205. package/src/lib/model/contact-record.js +15 -1
  206. package/src/lib/model/contact-record.js.map +1 -1
  207. package/src/lib/model/contact-update.d.ts +31 -2
  208. package/src/lib/model/contact-update.js +14 -0
  209. package/src/lib/model/contact-update.js.map +1 -1
  210. package/src/lib/model/crm-list-query.d.ts +5 -0
  211. package/src/lib/model/crm-list-query.js +8 -0
  212. package/src/lib/model/crm-list-query.js.map +1 -1
  213. package/src/lib/model/crm-recipes.d.ts +40 -0
  214. package/src/lib/model/crm-recipes.js +244 -0
  215. package/src/lib/model/crm-recipes.js.map +1 -0
  216. package/src/lib/model/crm-record-counts.d.ts +36 -0
  217. package/src/lib/model/crm-record-counts.js +54 -0
  218. package/src/lib/model/crm-record-counts.js.map +1 -0
  219. package/src/lib/model/crm-record-lists.d.ts +23 -0
  220. package/src/lib/model/crm-record-lists.js +161 -0
  221. package/src/lib/model/crm-record-lists.js.map +1 -0
  222. package/src/lib/model/crm-reports.d.ts +73 -3
  223. package/src/lib/model/crm-reports.js +120 -1
  224. package/src/lib/model/crm-reports.js.map +1 -1
  225. package/src/lib/model/crm-sharing.d.ts +21 -3
  226. package/src/lib/model/crm-sharing.js +27 -6
  227. package/src/lib/model/crm-sharing.js.map +1 -1
  228. package/src/lib/model/deal-board-model.d.ts +8 -2
  229. package/src/lib/model/deal-board-model.js +15 -2
  230. package/src/lib/model/deal-board-model.js.map +1 -1
  231. package/src/lib/model/deal-contact-roles.d.ts +45 -0
  232. package/src/lib/model/deal-contact-roles.js +73 -0
  233. package/src/lib/model/deal-contact-roles.js.map +1 -0
  234. package/src/lib/model/deal-form-model.d.ts +56 -0
  235. package/src/lib/model/deal-form-model.js +79 -7
  236. package/src/lib/model/deal-form-model.js.map +1 -1
  237. package/src/lib/model/download-text-file.d.ts +23 -0
  238. package/src/lib/model/download-text-file.js +34 -0
  239. package/src/lib/model/download-text-file.js.map +1 -0
  240. package/src/lib/model/lead-filters.d.ts +36 -2
  241. package/src/lib/model/lead-filters.js +123 -2
  242. package/src/lib/model/lead-filters.js.map +1 -1
  243. package/src/lib/model/lead-source-direction.d.ts +38 -0
  244. package/src/lib/model/lead-source-direction.js +52 -0
  245. package/src/lib/model/lead-source-direction.js.map +1 -0
  246. package/src/lib/model/picklist-values.d.ts +119 -0
  247. package/src/lib/model/picklist-values.js +256 -0
  248. package/src/lib/model/picklist-values.js.map +1 -0
  249. package/src/lib/model/record-facts-disclosed.d.ts +81 -0
  250. package/src/lib/model/record-facts-disclosed.js +281 -0
  251. package/src/lib/model/record-facts-disclosed.js.map +1 -0
  252. package/src/lib/model/record-facts.d.ts +215 -34
  253. package/src/lib/model/record-facts.js +307 -128
  254. package/src/lib/model/record-facts.js.map +1 -1
  255. package/src/lib/model/task-picklists.d.ts +52 -0
  256. package/src/lib/model/task-picklists.js +83 -0
  257. package/src/lib/model/task-picklists.js.map +1 -0
  258. package/src/lib/model/task-routes.d.ts +13 -0
  259. package/src/lib/model/task-routes.js +23 -4
  260. package/src/lib/model/task-routes.js.map +1 -1
  261. package/src/lib/plan-entitlements.js +6 -4
  262. package/src/lib/plan-entitlements.js.map +1 -1
  263. package/src/lib/plugin.js +17 -0
  264. package/src/lib/plugin.js.map +1 -1
  265. package/src/lib/server/api-v1/contacts.js +220 -14
  266. package/src/lib/server/api-v1/contacts.js.map +1 -1
  267. package/src/lib/server/api-v1/crm-activities.js +14 -1
  268. package/src/lib/server/api-v1/crm-activities.js.map +1 -1
  269. package/src/lib/server/api-v1/crm-companies.js +123 -14
  270. package/src/lib/server/api-v1/crm-companies.js.map +1 -1
  271. package/src/lib/server/api-v1/crm-deals.js +291 -26
  272. package/src/lib/server/api-v1/crm-deals.js.map +1 -1
  273. package/src/lib/server/api-v1/crm-leads.js +144 -38
  274. package/src/lib/server/api-v1/crm-leads.js.map +1 -1
  275. package/src/lib/server/api-v1/crm-pipelines.d.ts +6 -0
  276. package/src/lib/server/api-v1/crm-pipelines.js +8 -2
  277. package/src/lib/server/api-v1/crm-pipelines.js.map +1 -1
  278. package/src/lib/server/api-v1/crm-tasks.js +75 -33
  279. package/src/lib/server/api-v1/crm-tasks.js.map +1 -1
  280. package/src/lib/server/api-v1/openapi.d.ts +0 -11
  281. package/src/lib/server/api-v1/openapi.js +171 -16
  282. package/src/lib/server/api-v1/openapi.js.map +1 -1
  283. package/src/lib/server/assign-contact-owner.d.ts +162 -0
  284. package/src/lib/server/assign-contact-owner.js +340 -0
  285. package/src/lib/server/assign-contact-owner.js.map +1 -0
  286. package/src/lib/server/associate-company-by-domain.d.ts +70 -0
  287. package/src/lib/server/associate-company-by-domain.js +153 -0
  288. package/src/lib/server/associate-company-by-domain.js.map +1 -0
  289. package/src/lib/server/automation-steps.d.ts +139 -0
  290. package/src/lib/server/automation-steps.js +472 -0
  291. package/src/lib/server/automation-steps.js.map +1 -0
  292. package/src/lib/server/capture-contact.js +65 -21
  293. package/src/lib/server/capture-contact.js.map +1 -1
  294. package/src/lib/server/capture-host-contact.d.ts +104 -0
  295. package/src/lib/server/capture-host-contact.js +151 -0
  296. package/src/lib/server/capture-host-contact.js.map +1 -0
  297. package/src/lib/server/company-children.d.ts +25 -0
  298. package/src/lib/server/company-children.js +42 -0
  299. package/src/lib/server/company-children.js.map +1 -0
  300. package/src/lib/server/company-delete.d.ts +18 -0
  301. package/src/lib/server/company-delete.js +44 -21
  302. package/src/lib/server/company-delete.js.map +1 -1
  303. package/src/lib/server/contact-email-history.js +21 -19
  304. package/src/lib/server/contact-email-history.js.map +1 -1
  305. package/src/lib/server/contact-remove.js +27 -2
  306. package/src/lib/server/contact-remove.js.map +1 -1
  307. package/src/lib/server/contact-reports-to.d.ts +61 -0
  308. package/src/lib/server/contact-reports-to.js +114 -0
  309. package/src/lib/server/contact-reports-to.js.map +1 -0
  310. package/src/lib/server/contact-update.d.ts +42 -1
  311. package/src/lib/server/contact-update.js +204 -23
  312. package/src/lib/server/contact-update.js.map +1 -1
  313. package/src/lib/server/convert-host-lead.d.ts +46 -1
  314. package/src/lib/server/convert-host-lead.js +173 -15
  315. package/src/lib/server/convert-host-lead.js.map +1 -1
  316. package/src/lib/server/convert-open-lead.js +12 -5
  317. package/src/lib/server/convert-open-lead.js.map +1 -1
  318. package/src/lib/server/crm-record-indexes.d.ts +45 -0
  319. package/src/lib/server/crm-record-indexes.js +78 -0
  320. package/src/lib/server/crm-record-indexes.js.map +1 -0
  321. package/src/lib/server/crm-sharing.d.ts +9 -1
  322. package/src/lib/server/crm-sharing.js +23 -3
  323. package/src/lib/server/crm-sharing.js.map +1 -1
  324. package/src/lib/server/deal-contact-roles.d.ts +27 -0
  325. package/src/lib/server/deal-contact-roles.js +89 -0
  326. package/src/lib/server/deal-contact-roles.js.map +1 -0
  327. package/src/lib/server/lead-convert.d.ts +5 -0
  328. package/src/lib/server/lead-convert.js +19 -3
  329. package/src/lib/server/lead-convert.js.map +1 -1
  330. package/src/lib/server/lead-create.d.ts +17 -2
  331. package/src/lib/server/lead-create.js +46 -14
  332. package/src/lib/server/lead-create.js.map +1 -1
  333. package/src/lib/server/lead-nurturing.d.ts +6 -0
  334. package/src/lib/server/lead-nurturing.js +57 -20
  335. package/src/lib/server/lead-nurturing.js.map +1 -1
  336. package/src/lib/server/lead-picklists.d.ts +35 -0
  337. package/src/lib/server/lead-picklists.js +52 -0
  338. package/src/lib/server/lead-picklists.js.map +1 -0
  339. package/src/lib/server/lead-source-picklist.d.ts +1 -13
  340. package/src/lib/server/lead-source-picklist.js +6 -33
  341. package/src/lib/server/lead-source-picklist.js.map +1 -1
  342. package/src/lib/server/merge-contacts.js +22 -4
  343. package/src/lib/server/merge-contacts.js.map +1 -1
  344. package/src/lib/server/person-eraser.d.ts +53 -0
  345. package/src/lib/server/person-eraser.js +149 -0
  346. package/src/lib/server/person-eraser.js.map +1 -0
  347. package/src/lib/server/person-records.d.ts +69 -0
  348. package/src/lib/server/person-records.js +317 -0
  349. package/src/lib/server/person-records.js.map +1 -0
  350. package/src/lib/server/person-refund.d.ts +97 -0
  351. package/src/lib/server/person-refund.js +221 -0
  352. package/src/lib/server/person-refund.js.map +1 -0
  353. package/src/lib/server/picklist-values.d.ts +21 -0
  354. package/src/lib/server/picklist-values.js +308 -0
  355. package/src/lib/server/picklist-values.js.map +1 -0
  356. package/src/lib/server/read-picklist.d.ts +44 -0
  357. package/src/lib/server/read-picklist.js +65 -0
  358. package/src/lib/server/read-picklist.js.map +1 -0
  359. package/src/lib/server/recipe-routes.js +15 -7
  360. package/src/lib/server/recipe-routes.js.map +1 -1
  361. package/src/lib/server/record-email-state.js +7 -1
  362. package/src/lib/server/record-email-state.js.map +1 -1
  363. package/src/lib/server/record-facts.d.ts +3 -0
  364. package/src/lib/server/record-facts.js +233 -31
  365. package/src/lib/server/record-facts.js.map +1 -1
  366. package/src/lib/server/record-origin.d.ts +27 -0
  367. package/src/lib/server/record-origin.js +104 -0
  368. package/src/lib/server/record-origin.js.map +1 -0
  369. package/src/lib/server/record-timeline.js +15 -2
  370. package/src/lib/server/record-timeline.js.map +1 -1
  371. package/src/lib/server/suite-gate.js +4 -3
  372. package/src/lib/server/suite-gate.js.map +1 -1
  373. package/src/lib/server/task-routes.js +30 -16
  374. package/src/lib/server/task-routes.js.map +1 -1
  375. package/src/lib/server-deal-stage.d.ts +5 -1
  376. package/src/lib/server-deal-stage.js +10 -5
  377. package/src/lib/server-deal-stage.js.map +1 -1
  378. package/src/lib/server.d.ts +8 -3
  379. package/src/lib/server.js +47 -43
  380. package/src/lib/server.js.map +1 -1
  381. package/src/lib/testing/memory-firestore.d.ts +55 -0
  382. package/src/lib/testing/memory-firestore.js +335 -0
  383. package/src/lib/testing/memory-firestore.js.map +1 -0
  384. package/src/lib/testing/stand-in-email-send-index.d.ts +25 -0
  385. package/src/lib/testing/stand-in-email-send-index.js +49 -0
  386. package/src/lib/testing/stand-in-email-send-index.js.map +1 -0
  387. package/src/lib/transfer/activities.d.ts +30 -0
  388. package/src/lib/transfer/activities.js +132 -0
  389. package/src/lib/transfer/activities.js.map +1 -0
  390. package/src/lib/transfer/aliases.d.ts +22 -0
  391. package/src/lib/transfer/aliases.js +1342 -0
  392. package/src/lib/transfer/aliases.js.map +1 -0
  393. package/src/lib/transfer/common.d.ts +222 -0
  394. package/src/lib/transfer/common.js +832 -0
  395. package/src/lib/transfer/common.js.map +1 -0
  396. package/src/lib/transfer/companies.d.ts +43 -0
  397. package/src/lib/transfer/companies.js +549 -0
  398. package/src/lib/transfer/companies.js.map +1 -0
  399. package/src/lib/transfer/contacts.d.ts +31 -0
  400. package/src/lib/transfer/contacts.js +727 -0
  401. package/src/lib/transfer/contacts.js.map +1 -0
  402. package/src/lib/transfer/deals.d.ts +66 -0
  403. package/src/lib/transfer/deals.js +698 -0
  404. package/src/lib/transfer/deals.js.map +1 -0
  405. package/src/lib/transfer/email-templates-package.d.ts +40 -0
  406. package/src/lib/transfer/email-templates-package.js +76 -0
  407. package/src/lib/transfer/email-templates-package.js.map +1 -0
  408. package/src/lib/transfer/email-templates-package.server.d.ts +32 -0
  409. package/src/lib/transfer/email-templates-package.server.js +176 -0
  410. package/src/lib/transfer/email-templates-package.server.js.map +1 -0
  411. package/src/lib/transfer/fields.d.ts +102 -0
  412. package/src/lib/transfer/fields.js +1755 -0
  413. package/src/lib/transfer/fields.js.map +1 -0
  414. package/src/lib/transfer/leads.d.ts +30 -0
  415. package/src/lib/transfer/leads.js +582 -0
  416. package/src/lib/transfer/leads.js.map +1 -0
  417. package/src/lib/transfer/pipelines.d.ts +21 -0
  418. package/src/lib/transfer/pipelines.js +172 -0
  419. package/src/lib/transfer/pipelines.js.map +1 -0
  420. package/src/lib/transfer/register.d.ts +47 -0
  421. package/src/lib/transfer/register.js +277 -0
  422. package/src/lib/transfer/register.js.map +1 -0
  423. package/src/lib/transfer/tasks.d.ts +30 -0
  424. package/src/lib/transfer/tasks.js +418 -0
  425. package/src/lib/transfer/tasks.js.map +1 -0
  426. package/src/lib/transfer/ui.d.ts +20 -0
  427. package/src/lib/transfer/ui.js +42 -0
  428. package/src/lib/transfer/ui.js.map +1 -0
  429. package/src/lib/components/company-import-drawer.d.ts +0 -42
  430. package/src/lib/components/company-import-drawer.js +0 -99
  431. package/src/lib/components/company-import-drawer.js.map +0 -1
  432. package/src/lib/components/contact-import-drawer.d.ts +0 -46
  433. package/src/lib/components/contact-import-drawer.js +0 -149
  434. package/src/lib/components/contact-import-drawer.js.map +0 -1
  435. package/src/lib/components/crm-export-all-button.d.ts +0 -39
  436. package/src/lib/components/crm-export-all-button.js +0 -98
  437. package/src/lib/components/crm-export-all-button.js.map +0 -1
  438. package/src/lib/components/csv-import-drawer.d.ts +0 -139
  439. package/src/lib/components/csv-import-drawer.js +0 -757
  440. package/src/lib/components/csv-import-drawer.js.map +0 -1
  441. package/src/lib/components/deal-import-drawer.d.ts +0 -24
  442. package/src/lib/components/deal-import-drawer.js +0 -83
  443. package/src/lib/components/deal-import-drawer.js.map +0 -1
  444. package/src/lib/components/lead-import-drawer.d.ts +0 -27
  445. package/src/lib/components/lead-import-drawer.js +0 -118
  446. package/src/lib/components/lead-import-drawer.js.map +0 -1
  447. package/src/lib/components/lead-source-values-card.d.ts +0 -27
  448. package/src/lib/components/lead-source-values-card.js.map +0 -1
  449. package/src/lib/components/task-import-drawer.d.ts +0 -24
  450. package/src/lib/components/task-import-drawer.js +0 -82
  451. package/src/lib/components/task-import-drawer.js.map +0 -1
  452. package/src/lib/model/companies-csv.d.ts +0 -36
  453. package/src/lib/model/companies-csv.js +0 -38
  454. package/src/lib/model/companies-csv.js.map +0 -1
  455. package/src/lib/model/contacts-csv.d.ts +0 -54
  456. package/src/lib/model/contacts-csv.js +0 -67
  457. package/src/lib/model/contacts-csv.js.map +0 -1
  458. package/src/lib/model/crm-company-import.d.ts +0 -154
  459. package/src/lib/model/crm-company-import.js +0 -331
  460. package/src/lib/model/crm-company-import.js.map +0 -1
  461. package/src/lib/model/crm-csv.d.ts +0 -239
  462. package/src/lib/model/crm-csv.js +0 -467
  463. package/src/lib/model/crm-csv.js.map +0 -1
  464. package/src/lib/model/crm-deal-import.d.ts +0 -112
  465. package/src/lib/model/crm-deal-import.js +0 -263
  466. package/src/lib/model/crm-deal-import.js.map +0 -1
  467. package/src/lib/model/crm-import.d.ts +0 -250
  468. package/src/lib/model/crm-import.js +0 -467
  469. package/src/lib/model/crm-import.js.map +0 -1
  470. package/src/lib/model/crm-lead-import.d.ts +0 -138
  471. package/src/lib/model/crm-lead-import.js +0 -446
  472. package/src/lib/model/crm-lead-import.js.map +0 -1
  473. package/src/lib/model/crm-task-import.d.ts +0 -94
  474. package/src/lib/model/crm-task-import.js +0 -275
  475. package/src/lib/model/crm-task-import.js.map +0 -1
  476. package/src/lib/model/deals-csv.d.ts +0 -32
  477. package/src/lib/model/deals-csv.js +0 -36
  478. package/src/lib/model/deals-csv.js.map +0 -1
  479. package/src/lib/model/import-column-shapes.d.ts +0 -36
  480. package/src/lib/model/import-column-shapes.js +0 -76
  481. package/src/lib/model/import-column-shapes.js.map +0 -1
  482. package/src/lib/model/lead-source-values.d.ts +0 -82
  483. package/src/lib/model/lead-source-values.js +0 -149
  484. package/src/lib/model/lead-source-values.js.map +0 -1
  485. package/src/lib/model/leads-csv.d.ts +0 -40
  486. package/src/lib/model/leads-csv.js +0 -40
  487. package/src/lib/model/leads-csv.js.map +0 -1
  488. package/src/lib/model/tasks-csv.d.ts +0 -28
  489. package/src/lib/model/tasks-csv.js +0 -28
  490. package/src/lib/model/tasks-csv.js.map +0 -1
  491. package/src/lib/server/companies-import.d.ts +0 -57
  492. package/src/lib/server/companies-import.js +0 -242
  493. package/src/lib/server/companies-import.js.map +0 -1
  494. package/src/lib/server/contacts-import.d.ts +0 -109
  495. package/src/lib/server/contacts-import.js +0 -393
  496. package/src/lib/server/contacts-import.js.map +0 -1
  497. package/src/lib/server/deals-import.d.ts +0 -76
  498. package/src/lib/server/deals-import.js +0 -248
  499. package/src/lib/server/deals-import.js.map +0 -1
  500. package/src/lib/server/export-route.d.ts +0 -60
  501. package/src/lib/server/export-route.js +0 -447
  502. package/src/lib/server/export-route.js.map +0 -1
  503. package/src/lib/server/import-context.d.ts +0 -87
  504. package/src/lib/server/import-context.js +0 -182
  505. package/src/lib/server/import-context.js.map +0 -1
  506. package/src/lib/server/lead-source-values.d.ts +0 -50
  507. package/src/lib/server/lead-source-values.js +0 -191
  508. package/src/lib/server/lead-source-values.js.map +0 -1
  509. package/src/lib/server/leads-import.d.ts +0 -84
  510. package/src/lib/server/leads-import.js +0 -367
  511. package/src/lib/server/leads-import.js.map +0 -1
  512. package/src/lib/server/tasks-import.d.ts +0 -54
  513. package/src/lib/server/tasks-import.js +0 -160
  514. package/src/lib/server/tasks-import.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/csv-import-drawer.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\n/**\n * IMPORTING A CSV INTO A CRM COLLECTION — the screen, for whichever\n * collection (AGL-2602, shared since AGL-2621).\n *\n * The contact import settled the walk from a file on disk to a result the\n * operator can act on: choose the file, read what is in it, match its\n * columns to fields with the first row beside each, preview the ten rows\n * the mapping produces, run it in bounded requests with a progress bar,\n * and report what was added, updated and skipped with the skipped rows as\n * a file to fix. A companies file walks the same path with a different\n * vocabulary, so the walk lives here once and each collection hands in a\n * {@link CsvImportVocabulary}: its fields and their labels, the one field\n * every row needs, its route, its tally, its template.\n *\n * ## The file is read in the browser, and judged on the server\n *\n * `parseCsv` — the same parser the list import and the dataset import run\n * — turns the file into cells here, so the operator can map and preview\n * without a round trip and without uploading a file they may still decide\n * not to import. Nothing is VALIDATED here beyond counting the rows whose\n * required cell is unusable, and that count is a courtesy: every row is\n * judged by the route, through the normalizers every other door uses, and\n * the numbers on the result panel are the server's.\n *\n * ## Bounded requests, and closing stops them\n *\n * A chunk per request, as many requests as the file needs, and a progress\n * bar between them. Closing the drawer mid-run stops the loop after the\n * request in flight; the rows already written stay written and the result\n * panel says how far it got. There is no durable job to resume — an import\n * is idempotent by construction (the door dedupes on the address, or the\n * domain and the name), so running the same file again finishes what a\n * closed drawer left, reporting the earlier rows as merged.\n */\n\nimport {\n customImportTarget,\n customImportTargetKey,\n type ImportChunkResult,\n type ImportSkippedRow,\n importNoMailServerSentence,\n CSV_UPLOAD_MAX_CHARACTERS,\n parseCsv,\n} from '@aglyn/aglyn'\nimport { ICON_VARIANT_CLOSE } from '@aglyn/shared-data-enums'\nimport { Container, HelpTip, MdiIcon, SrOnly } from '@aglyn/shared-ui-jsx'\nimport { NavigationDrawerComponent } from '@aglyn/shared-ui-jsx/components/navigation-drawer.component'\nimport { ScrollTable } from '@aglyn/shared-ui-jsx/components/scroll-table.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useOrgDataScope, useUser } from '@aglyn/tenant-feature-instance'\nimport { useConsoleWidgetSlot } from '@aglyn/aglyn/app-utils/console-widget-slot-context'\nimport {\n Alert,\n AlertTitle,\n Box,\n Button,\n Chip,\n IconButton,\n LinearProgress,\n MenuItem,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material'\nimport {\n type ComponentProps,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { useCrmOrgMount } from '../hooks/use-crm-org-mount'\nimport { downloadTextFile } from '../model/contacts-csv'\nimport { importColumns } from '../model/import-column-shapes'\nimport { CrmSitePicker } from './crm-site-picker'\n\n/** A column's target: a standard field, or a custom one as `custom:<key>`. */\nexport type CsvImportTarget<F extends string> = F | `custom:${string}`\n\n/** Column index → target. A column absent from the map is not imported. */\nexport type CsvImportMapping<F extends string> = Record<number, CsvImportTarget<F>>\n\n/** A custom field a column may be mapped to, when the collection has any. */\nexport interface CsvImportCustomField {\n key: string\n label: string\n}\n\n/**\n * Everything one collection's import says for itself. Pure values and pure\n * functions, so a vocabulary is built once outside React and handed in.\n */\nexport interface CsvImportVocabulary<\n F extends string,\n R extends Record<string, unknown>,\n S extends ImportSkippedRow<string>,\n> {\n /** The drawer's title — \"Import contacts from CSV\". */\n title: string\n /**\n * What the import is called where the `importMapping` zone names it —\n * `contacts`, `companies`, `deals`, `leads` (AGL-2917). Absent, the drawer\n * hosts no zone.\n */\n collection?: string\n help: ComponentProps<typeof HelpTip>\n /**\n * What the site picker's answer decides, said under it at the\n * organization level (AGL-2630). Absent, the picker's own sentence.\n */\n sitePickerHelperText?: string\n /** The paragraph under the title. */\n intro: string\n /** The standard targets, in the order the mapping menu lists them. */\n fields: readonly F[]\n fieldLabels: Record<F, string>\n /** Custom targets, offered after the standard ones; none for most collections. */\n customFields?: readonly CsvImportCustomField[]\n /** The one field every row needs, and what the drawer says when it is unmapped. */\n requiredField: F\n requiredWarning: string\n /**\n * Whether a required cell is one the server would refuse — the courtesy\n * count the preview shows. Absent, only a blank cell counts.\n */\n unusable?: (cell: string) => boolean\n /** The preview's sentence about them. */\n unusableNotice: (count: number, total: number) => string\n guessMapping: (columns: readonly string[]) => CsvImportMapping<F>\n mapRow: (cells: readonly string[], mapping: CsvImportMapping<F>) => R\n /** The browser-side URL of the route one chunk is posted to. */\n route: string\n maxRows: number\n chunkSize: number\n previewRows: number\n emptyResult: () => ImportChunkResult<S>\n mergeResults: (\n total: ImportChunkResult<S>,\n chunk: ImportChunkResult<S>,\n offset: number,\n ) => ImportChunkResult<S>\n skipLabels: Record<S['reason'], string>\n skippedCsv: (\n columns: readonly string[],\n entries: readonly { cells: readonly string[]; reason: S['reason'] }[],\n ) => string\n skippedFileName: string\n /** The export's header over no rows. */\n templateCsv: () => string\n templateFileName: string\n /** The result panel's collection-specific lines, when there are any. */\n resultExtras?: (result: ImportChunkResult<S>) => ReactNode\n /**\n * A collection-specific warning about the mapped file, shown above the\n * preview before anything is sent — a value the server will refuse that\n * the operator can fix first. Given every row as `mapRow` reads it;\n * answers nothing when the file is fine.\n */\n rowsNotice?: (rows: readonly R[]) => ReactNode\n}\n\nexport interface CsvImportDrawerProps<\n F extends string,\n R extends Record<string, unknown>,\n S extends ImportSkippedRow<string>,\n> {\n open: boolean\n onClose: () => void\n /**\n * The site the file is imported INTO — what the route files every row\n * under — or `null` at the organization level (AGL-2630), where the\n * drawer asks which site with a picker and holds the import until one is\n * named.\n */\n hostId: string | null\n vocabulary: CsvImportVocabulary<F, R, S>\n}\n\n/** The value the mapping select shows for a column that is not imported. */\nconst SKIP_TARGET = ''\n\n/** What a target is called — a standard field's label, or the custom field's. */\nfunction targetLabel<F extends string>(\n target: string,\n vocabulary: Pick<CsvImportVocabulary<F, never, never>, 'fieldLabels' | 'customFields'>,\n): string {\n const customKey = customImportTargetKey(target)\n if (customKey) {\n return vocabulary.customFields?.find((field) => field.key === customKey)?.label ?? customKey\n }\n return vocabulary.fieldLabels[target as F] ?? target\n}\n\n/** What a dropped-value field is called in the result panel — the label without its hint. */\nfunction droppedFieldLabel<F extends string>(\n field: string,\n vocabulary: Pick<CsvImportVocabulary<F, never, never>, 'fieldLabels' | 'customFields'>,\n): string {\n return targetLabel(field, vocabulary).replace(/ \\(.*\\)$/, '')\n}\n\nexport function CsvImportDrawer<\n F extends string,\n R extends Record<string, unknown>,\n S extends ImportSkippedRow<string>,\n>(props: CsvImportDrawerProps<F, R, S>) {\n const { open, onClose, hostId, vocabulary } = props\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n // The site every row is captured under: the mounted one, or at the\n // organization level the one the picker named — `null` until it has.\n const mount = useCrmOrgMount()\n const createHostId = hostId ?? mount?.createHostId ?? null\n\n const [fileName, setFileName] = useState('')\n const [columns, setColumns] = useState<string[]>([])\n const [rows, setRows] = useState<string[][]>([])\n /** How many rows the file had past the ceiling, so the drawer can say so. */\n const [overCeiling, setOverCeiling] = useState(0)\n const [mapping, setMapping] = useState<CsvImportMapping<F>>({})\n const [result, setResult] = useState<ImportChunkResult<S> | null>(null)\n const [progress, setProgress] = useState<{ sent: number; total: number } | null>(\n null,\n )\n const [busy, setBusy] = useState(false)\n /**\n * Set when the drawer closes mid-run, read by the loop.\n *\n * A ref and not state, for the reason the list import gives: the loop is\n * an `async` function that captured its closure when it started, and a\n * state value it read would be the one from that render.\n */\n const abandoned = useRef(false)\n\n useEffect(() => {\n if (open) abandoned.current = false\n }, [open])\n\n const reset = useCallback(() => {\n setFileName('')\n setColumns([])\n setRows([])\n setOverCeiling(0)\n setMapping({})\n setResult(null)\n setProgress(null)\n }, [])\n\n const handleClose = useCallback(() => {\n abandoned.current = true\n onClose()\n }, [onClose])\n\n const handleFile = useCallback(\n async (file: File | null | undefined) => {\n if (!file) return\n const contents = await file.text().catch(() => '')\n if (contents.length > CSV_UPLOAD_MAX_CHARACTERS) {\n return void enqueueSnackbar(\n 'That file is too large to read in one go. Split it and import the ' +\n 'pieces.',\n { variant: 'warning', allowDuplicate: true },\n )\n }\n const table = parseCsv(contents).filter((cells) =>\n cells.some((cell) => String(cell ?? '').trim()),\n )\n if (table.length < 2) {\n return void enqueueSnackbar(\n 'That file needs a header row and at least one row under it.',\n { variant: 'warning', allowDuplicate: true },\n )\n }\n const header = table[0].map((cell) => String(cell ?? '').trim())\n const body = table.slice(1)\n setFileName(file.name)\n setColumns(header)\n setRows(body.slice(0, vocabulary.maxRows))\n setOverCeiling(Math.max(0, body.length - vocabulary.maxRows))\n setMapping(vocabulary.guessMapping(header))\n setResult(null)\n setProgress(null)\n },\n [enqueueSnackbar, vocabulary],\n )\n\n const requiredMapped = Object.values(mapping).includes(vocabulary.requiredField)\n /** Rows whose required cell the server would refuse. */\n const unusableRows = useMemo(() => {\n const at = Number(\n Object.entries(mapping).find(\n ([, target]) => target === vocabulary.requiredField,\n )?.[0] ?? -1,\n )\n if (at < 0) return rows.length\n const unusable = vocabulary.unusable ?? ((cell: string) => !cell.trim())\n return rows.filter((cells) => unusable(String(cells[at] ?? ''))).length\n }, [mapping, rows, vocabulary])\n\n const preview = useMemo(\n () =>\n rows\n .slice(0, vocabulary.previewRows)\n .map((cells) => vocabulary.mapRow(cells, mapping)),\n [rows, mapping, vocabulary],\n )\n // The collection's own warning over the whole mapped file, when it has one.\n const rowsNotice = useMemo(\n () =>\n vocabulary.rowsNotice && rows.length\n ? vocabulary.rowsNotice(rows.map((cells) => vocabulary.mapRow(cells, mapping)))\n : null,\n [rows, mapping, vocabulary],\n )\n const mappedTargets = useMemo(\n () =>\n Object.entries(mapping)\n .sort(([a], [b]) => Number(a) - Number(b))\n .map(([, target]) => target),\n [mapping],\n )\n\n /*\n * The `importMapping` zone (AGL-2917), hosted through the shell's renderer:\n * a widget there reads each column's header and shape, never a cell, and\n * proposes a matching, which replaces the table's above for the preview to\n * show. A target this import does not offer, or one a column before it\n * already took, is dropped, as the table itself would refuse it.\n */\n const MappingSlot = useConsoleWidgetSlot()\n const { orgId } = useOrgDataScope({ hostId: hostId ?? undefined, orgId: mount?.orgId })\n const shapedColumns = useMemo(() => importColumns(columns, rows), [columns, rows])\n const offeredTargets = useMemo(\n () =>\n new Set<string>([\n ...vocabulary.fields,\n ...(vocabulary.customFields ?? []).map((field) => customImportTarget(field.key)),\n ]),\n [vocabulary],\n )\n const proposeMapping = useCallback(\n (proposed: Readonly<Record<number, string>>) => {\n const taken = new Set<string>()\n const next: CsvImportMapping<F> = {}\n for (const [column, target] of Object.entries(proposed).sort(([a], [b]) => Number(a) - Number(b))) {\n const index = Number(column)\n if (!Number.isInteger(index) || index < 0 || index >= columns.length) continue\n if (!offeredTargets.has(target) || taken.has(target)) continue\n taken.add(target)\n next[index] = target as CsvImportTarget<F>\n }\n setMapping(next)\n },\n [offeredTargets, columns.length],\n )\n\n const handleMap = useCallback((index: number, target: string) => {\n setMapping((previous) => {\n const next: CsvImportMapping<F> = {}\n for (const [column, existing] of Object.entries(previous)) {\n // One column per target: choosing a target already taken moves it\n // here rather than importing one field from two columns.\n if (Number(column) !== index && existing !== target) {\n next[Number(column)] = existing\n }\n }\n if (target !== SKIP_TARGET) next[index] = target as CsvImportTarget<F>\n return next\n })\n }, [])\n\n /**\n * Runs the file, one bounded request at a time.\n *\n * Every chunk's result is folded into the running total as it arrives,\n * so a file that stops halfway — a lost connection, a closed drawer —\n * still reports what it did rather than nothing.\n */\n const handleImport = useCallback(async () => {\n if (busy || !rows.length || !requiredMapped || !createHostId) return\n setBusy(true)\n let total = vocabulary.emptyResult()\n setResult(total)\n setProgress({ sent: 0, total: rows.length })\n try {\n for (let offset = 0; offset < rows.length; offset += vocabulary.chunkSize) {\n if (abandoned.current) return\n const chunk = rows\n .slice(offset, offset + vocabulary.chunkSize)\n .map((cells) => vocabulary.mapRow(cells, mapping))\n const response = await authorizedFetch(user, vocabulary.route, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hostId: createHostId, rows: chunk }),\n })\n const payload = await response.json().catch(() => ({}))\n if (!response.ok) {\n return void enqueueSnackbar(\n payload?.error ?? 'The import could not continue.',\n { variant: 'warning', allowDuplicate: true },\n )\n }\n total = vocabulary.mergeResults(total, payload as ImportChunkResult<S>, offset)\n setResult(total)\n setProgress({ sent: Math.min(offset + chunk.length, rows.length), total: rows.length })\n }\n enqueueSnackbar('Import finished', { variant: 'success', persist: false })\n } catch {\n enqueueSnackbar('The import could not continue.', {\n variant: 'warning',\n allowDuplicate: true,\n })\n } finally {\n setBusy(false)\n }\n }, [busy, rows, requiredMapped, mapping, user, createHostId, enqueueSnackbar, vocabulary])\n\n const handleDownloadSkipped = useCallback(() => {\n if (!result?.skipped.length) return\n downloadTextFile(\n vocabulary.skippedFileName,\n 'text/csv',\n vocabulary.skippedCsv(\n columns,\n result.skipped.map((entry) => ({\n cells: rows[entry.index] ?? [],\n reason: entry.reason as S['reason'],\n })),\n ),\n )\n }, [result, columns, rows, vocabulary])\n\n const finished = !!result && !busy\n\n return (\n <NavigationDrawerComponent\n open={open}\n anchor=\"right\"\n variant=\"temporary\"\n onClose={handleClose}\n AppBarProps={{ color: 'surface' }}\n appBarLeft={\n <>\n <IconButton\n color=\"inherit\"\n edge=\"start\"\n onClick={handleClose}\n sx={{ mr: 2 }}\n >\n <MdiIcon path={ICON_VARIANT_CLOSE.path} />\n <SrOnly>{'close drawer'}</SrOnly>\n </IconButton>\n <Typography variant=\"h6\" component=\"div\">\n {vocabulary.title}\n </Typography>\n <HelpTip {...vocabulary.help} />\n </>\n }\n appBarRight={\n <Button variant=\"outlined\" color=\"inherit\" onClick={handleClose}>\n {finished ? 'Done' : 'Cancel'}\n </Button>\n }\n >\n <Container gutterY>\n <Stack spacing={2}>\n {result ? (\n <ImportResultPanel\n result={result}\n progress={progress}\n busy={busy}\n vocabulary={vocabulary}\n onDownloadSkipped={handleDownloadSkipped}\n onAnother={reset}\n />\n ) : (\n <>\n {/*\n First, because every row is filed under the answer: the site\n the file is imported into. Nothing under a site (AGL-2630).\n */}\n <CrmSitePicker\n hostId={hostId}\n disabled={busy}\n helperText={vocabulary.sitePickerHelperText}\n />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {vocabulary.intro}\n </Typography>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}>\n <Button variant=\"outlined\" component=\"label\" disabled={busy}>\n {'Choose file'}\n <input\n type=\"file\"\n accept=\".csv,text/csv\"\n hidden\n onChange={(event) => {\n void handleFile(event.target.files?.[0])\n event.target.value = ''\n }}\n />\n </Button>\n {/* The export's own header over no rows, so a sheet filled in\n against it maps itself. */}\n <Button\n size=\"small\"\n disabled={busy}\n onClick={() =>\n downloadTextFile(\n vocabulary.templateFileName,\n 'text/csv',\n vocabulary.templateCsv(),\n )\n }\n >\n {'Download template'}\n </Button>\n {fileName ? (\n <Chip size=\"small\" variant=\"outlined\" label={fileName} />\n ) : null}\n {rows.length ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`${rows.length.toLocaleString()} rows`}\n </Typography>\n ) : null}\n </Stack>\n {overCeiling > 0 ? (\n <Alert severity=\"warning\">\n {`This file has ${(rows.length + overCeiling).toLocaleString()} ` +\n `rows. Only the first ${vocabulary.maxRows.toLocaleString()} ` +\n 'are imported — split the file and import the rest ' +\n 'separately.'}\n </Alert>\n ) : null}\n {columns.length ? (\n <ImportMappingTable\n columns={columns}\n sample={rows[0] ?? []}\n mapping={mapping}\n vocabulary={vocabulary}\n onMap={handleMap}\n />\n ) : null}\n {columns.length && MappingSlot && vocabulary.collection ? (\n <MappingSlot\n slot=\"importMapping\"\n hostId={hostId}\n orgId={orgId ?? undefined}\n collection={vocabulary.collection}\n columns={shapedColumns}\n mapping={mapping}\n proposeMapping={(proposed: Readonly<Record<number, string>>) => proposeMapping(proposed)}\n />\n ) : null}\n {columns.length > 0 && !requiredMapped ? (\n <Alert severity=\"warning\">{vocabulary.requiredWarning}</Alert>\n ) : null}\n {columns.length > 0 && requiredMapped ? rowsNotice : null}\n {columns.length > 0 && requiredMapped ? (\n <ImportPreviewTable\n targets={mappedTargets}\n preview={preview}\n total={rows.length}\n unusable={unusableRows}\n vocabulary={vocabulary}\n />\n ) : null}\n <Stack direction=\"row\" spacing={1} sx={{ justifyContent: 'flex-end' }}>\n <Button\n variant=\"contained\"\n // Held until the capturing site is known.\n disabled={busy || !rows.length || !requiredMapped || !createHostId}\n onClick={() => void handleImport()}\n >\n {rows.length\n ? `Import ${rows.length.toLocaleString()} rows`\n : 'Import'}\n </Button>\n </Stack>\n </>\n )}\n </Stack>\n </Container>\n </NavigationDrawerComponent>\n )\n}\nCsvImportDrawer.displayName = 'CsvImportDrawer'\n\n/**\n * WHICH COLUMN IS WHICH.\n *\n * One row per column in the file: its header, the first row's value under\n * it so the operator can tell \"Title\" the job from \"Title\" the honorific,\n * and a select naming where it goes. The proposal came from the alias\n * table; every row of this table is the operator's to overrule.\n */\nfunction ImportMappingTable<F extends string>(props: {\n columns: readonly string[]\n sample: readonly string[]\n mapping: CsvImportMapping<F>\n vocabulary: Pick<CsvImportVocabulary<F, never, never>, 'fields' | 'fieldLabels' | 'customFields'>\n onMap: (index: number, target: string) => void\n}) {\n const { columns, sample, mapping, vocabulary, onMap } = props\n return (\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">{'Columns'}</Typography>\n <ScrollTable size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>{'Column'}</TableCell>\n <TableCell>{'First row'}</TableCell>\n <TableCell>{'Imports as'}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {columns.map((column, index) => (\n <TableRow key={`${column}-${index}`}>\n <TableCell>{column || `Column ${index + 1}`}</TableCell>\n <TableCell>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>\n {String(sample[index] ?? '')}\n </Typography>\n </TableCell>\n <TableCell>\n <TextField\n select\n size=\"small\"\n value={mapping[index] ?? SKIP_TARGET}\n onChange={(event) => onMap(index, event.target.value)}\n sx={{ minWidth: 220 }}\n >\n <MenuItem value={SKIP_TARGET}>{'Do not import'}</MenuItem>\n {vocabulary.fields.map((field) => (\n <MenuItem key={field} value={field}>\n {vocabulary.fieldLabels[field]}\n </MenuItem>\n ))}\n {(vocabulary.customFields ?? []).map((field) => (\n <MenuItem key={field.key} value={customImportTarget(field.key)}>\n {`${field.label} (custom)`}\n </MenuItem>\n ))}\n </TextField>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </ScrollTable>\n </Stack>\n )\n}\n\n/**\n * The first rows, as the mapping reads them.\n *\n * Verbatim cell values under the fields they were mapped to — not the\n * normalized ones, because normalization is the server's and a preview that\n * showed a cleaned phone number would be promising a result the route may\n * refuse. What it does say is how many rows have no usable required cell,\n * since that is the one refusal the operator can fix before sending.\n */\nfunction ImportPreviewTable<F extends string>(props: {\n targets: readonly string[]\n preview: readonly Record<string, unknown>[]\n total: number\n unusable: number\n vocabulary: Pick<\n CsvImportVocabulary<F, never, never>,\n 'fieldLabels' | 'customFields' | 'previewRows' | 'unusableNotice'\n >\n}) {\n const { targets, preview, total, unusable, vocabulary } = props\n const cell = (row: Record<string, unknown>, target: string) => {\n const customKey = customImportTargetKey(target)\n if (customKey) {\n return String((row['custom'] as Record<string, string> | undefined)?.[customKey] ?? '')\n }\n return String(row[target] ?? '')\n }\n return (\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">\n {`Preview — first ${Math.min(preview.length, vocabulary.previewRows)} of ${total.toLocaleString()}`}\n </Typography>\n {unusable > 0 ? (\n <Alert severity=\"info\">{vocabulary.unusableNotice(unusable, total)}</Alert>\n ) : null}\n <Box>\n <ScrollTable size=\"small\">\n <TableHead>\n <TableRow>\n {targets.map((target) => (\n <TableCell key={target}>{targetLabel(target, vocabulary)}</TableCell>\n ))}\n </TableRow>\n </TableHead>\n <TableBody>\n {preview.map((row, index) => (\n <TableRow key={index}>\n {targets.map((target) => (\n <TableCell key={target}>\n <Typography variant=\"body2\" noWrap sx={{ maxWidth: 240 }}>\n {cell(row, target)}\n </Typography>\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </ScrollTable>\n </Box>\n </Stack>\n )\n}\n\n/** How far the run has got, and what it did. */\nfunction ImportResultPanel<F extends string, S extends ImportSkippedRow<string>>(props: {\n result: ImportChunkResult<S>\n progress: { sent: number; total: number } | null\n busy: boolean\n vocabulary: Pick<\n CsvImportVocabulary<F, never, S>,\n 'fieldLabels' | 'customFields' | 'skipLabels' | 'resultExtras'\n >\n onDownloadSkipped: () => void\n onAnother: () => void\n}) {\n const { result, progress, busy, vocabulary, onDownloadSkipped, onAnother } = props\n const percent = progress?.total\n ? Math.min((progress.sent / progress.total) * 100, 100)\n : 0\n const skippedByReason = useMemo(() => {\n const counts: Partial<Record<string, number>> = {}\n for (const entry of result.skipped) {\n counts[entry.reason] = (counts[entry.reason] ?? 0) + 1\n }\n return Object.entries(counts) as [S['reason'], number][]\n }, [result.skipped])\n const droppedFields = Object.entries(result.dropped).filter(([, count]) => count > 0)\n return (\n <Stack spacing={2}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {busy\n ? `${(progress?.sent ?? 0).toLocaleString()} of ${(progress?.total ?? 0).toLocaleString()} rows sent.`\n : `Finished. ${result.created.toLocaleString()} added, ` +\n `${result.merged.toLocaleString()} updated, ` +\n `${result.skipped.length.toLocaleString()} skipped.`}\n </Typography>\n <LinearProgress\n variant=\"determinate\"\n value={percent}\n sx={{ borderRadius: 1 }}\n />\n {skippedByReason.length ? (\n <ScrollTable size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>{'Skipped'}</TableCell>\n <TableCell align=\"right\">{'Rows'}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {skippedByReason.map(([reason, count]) => (\n <TableRow key={reason}>\n <TableCell>{vocabulary.skipLabels[reason] ?? reason}</TableCell>\n <TableCell align=\"right\">{count}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </ScrollTable>\n ) : null}\n {droppedFields.length ? (\n <Alert severity=\"info\">\n <AlertTitle>{'Some values could not be read'}</AlertTitle>\n {'The rows were imported without them: ' +\n droppedFields\n .map(([field, count]) => `${droppedFieldLabel(field, vocabulary)} (${count})`)\n .join(', ') +\n '.'}\n </Alert>\n ) : null}\n {result.ownersUnresolved.length ? (\n <Alert severity=\"info\">\n {'No team member has these owner addresses, so those rows ' +\n `have no owner: ${result.ownersUnresolved.slice(0, 5).join(', ')}` +\n (result.ownersUnresolved.length > 5\n ? ` and ${result.ownersUnresolved.length - 5} more.`\n : '.')}\n </Alert>\n ) : null}\n {importNoMailServerSentence(result.noMailServer) ? (\n <Alert severity=\"warning\">{importNoMailServerSentence(result.noMailServer)}</Alert>\n ) : null}\n {vocabulary.resultExtras?.(result)}\n <Stack direction=\"row\" spacing={1} sx={{ justifyContent: 'flex-end' }}>\n {result.skipped.length ? (\n <Button variant=\"outlined\" onClick={onDownloadSkipped}>\n {'Download skipped rows'}\n </Button>\n ) : null}\n {!busy ? (\n <Button variant=\"outlined\" onClick={onAnother}>\n {'Import another file'}\n </Button>\n ) : null}\n </Stack>\n </Stack>\n )\n}\n\n/**\n * An \"Import CSV\" button that mounts its drawer only once it has been\n * opened, so the list pays nothing — no hooks, no listeners — for a\n * feature the operator has not reached for.\n */\nexport function CsvImportButton(props: {\n label?: string\n children: (open: boolean, onClose: () => void) => ReactNode\n}) {\n const { label = 'Import CSV', children } = props\n const [open, setOpen] = useState(false)\n const [mounted, setMounted] = useState(false)\n const handleOpen = useCallback(() => {\n setMounted(true)\n setOpen(true)\n }, [])\n const handleClose = useCallback(() => setOpen(false), [])\n return (\n <>\n <Button size=\"small\" onClick={handleOpen}>\n {label}\n </Button>\n {mounted ? children(open, handleClose) : null}\n </>\n )\n}\nCsvImportButton.displayName = 'CsvImportButton'\n\nexport default CsvImportDrawer\n"],"names":["customImportTarget","customImportTargetKey","importNoMailServerSentence","CSV_UPLOAD_MAX_CHARACTERS","parseCsv","ICON_VARIANT_CLOSE","Container","HelpTip","MdiIcon","SrOnly","NavigationDrawerComponent","ScrollTable","useSnackbar","authorizedFetch","useOrgDataScope","useUser","useConsoleWidgetSlot","Alert","AlertTitle","Box","Button","Chip","IconButton","LinearProgress","MenuItem","Stack","TableBody","TableCell","TableHead","TableRow","TextField","Typography","useCallback","useEffect","useMemo","useRef","useState","useCrmOrgMount","downloadTextFile","importColumns","CrmSitePicker","SKIP_TARGET","targetLabel","target","vocabulary","customKey","customFields","find","field","key","label","fieldLabels","droppedFieldLabel","replace","CsvImportDrawer","props","hostId","rows","open","onClose","data","user","enqueueSnackbar","mount","createHostId","fileName","setFileName","columns","setColumns","setRows","overCeiling","setOverCeiling","mapping","setMapping","result","setResult","progress","setProgress","busy","setBusy","abandoned","current","reset","handleClose","handleFile","file","contents","text","catch","length","variant","allowDuplicate","table","filter","cells","some","cell","String","trim","header","map","body","slice","name","maxRows","Math","max","guessMapping","requiredMapped","Object","values","includes","requiredField","unusableRows","at","Number","entries","unusable","preview","previewRows","mapRow","rowsNotice","mappedTargets","sort","a","b","MappingSlot","orgId","undefined","shapedColumns","offeredTargets","Set","fields","proposeMapping","proposed","taken","next","column","index","isInteger","has","add","handleMap","previous","existing","handleImport","total","emptyResult","sent","offset","chunkSize","chunk","response","route","method","headers","JSON","stringify","payload","json","ok","error","mergeResults","min","persist","handleDownloadSkipped","skipped","skippedFileName","skippedCsv","entry","reason","finished","anchor","AppBarProps","color","appBarLeft","edge","onClick","sx","mr","path","component","title","help","appBarRight","gutterY","spacing","ImportResultPanel","onDownloadSkipped","onAnother","disabled","helperText","sitePickerHelperText","intro","direction","alignItems","flexWrap","rowGap","input","type","accept","hidden","onChange","event","files","value","size","templateFileName","templateCsv","toLocaleString","severity","ImportMappingTable","sample","onMap","collection","slot","requiredWarning","ImportPreviewTable","targets","justifyContent","displayName","noWrap","select","minWidth","row","unusableNotice","maxWidth","percent","skippedByReason","counts","droppedFields","dropped","count","created","merged","borderRadius","align","skipLabels","join","ownersUnresolved","noMailServer","resultExtras","CsvImportButton","children","setOpen","mounted","setMounted","handleOpen"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCC,GAED,SACEA,kBAAkB,EAClBC,qBAAqB,EAGrBC,0BAA0B,EAC1BC,yBAAyB,EACzBC,QAAQ,QACH,eAAc;AACrB,SAASC,kBAAkB,QAAQ,2BAA0B;AAC7D,SAASC,SAAS,EAAEC,OAAO,EAAEC,OAAO,EAAEC,MAAM,QAAQ,uBAAsB;AAC1E,SAASC,yBAAyB,QAAQ,8DAA6D;AACvG,SAASC,WAAW,QAAQ,yDAAwD;AACpF,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,eAAe,QAAQ,2CAA0C;AAC1E,SAASC,eAAe,EAAEC,OAAO,QAAQ,iCAAgC;AACzE,SAASC,oBAAoB,QAAQ,qDAAoD;AACzF,SACEC,KAAK,EACLC,UAAU,EACVC,GAAG,EACHC,MAAM,EACNC,IAAI,EACJC,UAAU,EACVC,cAAc,EACdC,QAAQ,EACRC,KAAK,EACLC,SAAS,EACTC,SAAS,EACTC,SAAS,EACTC,QAAQ,EACRC,SAAS,EACTC,UAAU,QACL,gBAAe;AACtB,SAGEC,WAAW,EACXC,SAAS,EACTC,OAAO,EACPC,MAAM,EACNC,QAAQ,QACH,QAAO;AACd,SAASC,cAAc,QAAQ,gCAA4B;AAC3D,SAASC,gBAAgB,QAAQ,2BAAuB;AACxD,SAASC,aAAa,QAAQ,mCAA+B;AAC7D,SAASC,aAAa,QAAQ,uBAAmB;AAwGjD,0EAA0E,GAC1E,MAAMC,cAAc;AAEpB,+EAA+E,GAC/E,SAASC,YACPC,MAAc,EACdC,UAAsF;QAM/EA;IAJP,MAAMC,YAAY5C,sBAAsB0C;IACxC,IAAIE,WAAW;;YACND,+BAAAA;QAAP,gBAAOA,2BAAAA,WAAWE,YAAY,sBAAvBF,gCAAAA,yBAAyBG,IAAI,CAAC,CAACC,QAAUA,MAAMC,GAAG,KAAKJ,+BAAvDD,8BAAmEM,KAAK,mBAAIL;IACrF;IACA,QAAOD,iCAAAA,WAAWO,WAAW,CAACR,OAAY,YAAnCC,iCAAuCD;AAChD;AAEA,2FAA2F,GAC3F,SAASS,kBACPJ,KAAa,EACbJ,UAAsF;IAEtF,OAAOF,YAAYM,OAAOJ,YAAYS,OAAO,CAAC,YAAY;AAC5D;AAEA,OAAO,SAASC,gBAIdC,KAAoC;QAOfC,MAqUGC;IA3UxB,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEH,MAAM,EAAEZ,UAAU,EAAE,GAAGW;IAC9C,MAAM,EAAEK,MAAMC,IAAI,EAAE,GAAG9C;IACvB,MAAM,EAAE+C,eAAe,EAAE,GAAGlD;IAC5B,mEAAmE;IACnE,qEAAqE;IACrE,MAAMmD,QAAQ1B;IACd,MAAM2B,gBAAeR,OAAAA,iBAAAA,SAAUO,yBAAAA,MAAOC,YAAY,YAA7BR,OAAiC;IAEtD,MAAM,CAACS,UAAUC,YAAY,GAAG9B,SAAS;IACzC,MAAM,CAAC+B,SAASC,WAAW,GAAGhC,SAAmB,EAAE;IACnD,MAAM,CAACqB,MAAMY,QAAQ,GAAGjC,SAAqB,EAAE;IAC/C,2EAA2E,GAC3E,MAAM,CAACkC,aAAaC,eAAe,GAAGnC,SAAS;IAC/C,MAAM,CAACoC,SAASC,WAAW,GAAGrC,SAA8B,CAAC;IAC7D,MAAM,CAACsC,QAAQC,UAAU,GAAGvC,SAAsC;IAClE,MAAM,CAACwC,UAAUC,YAAY,GAAGzC,SAC9B;IAEF,MAAM,CAAC0C,MAAMC,QAAQ,GAAG3C,SAAS;IACjC;;;;;;GAMC,GACD,MAAM4C,YAAY7C,OAAO;IAEzBF,UAAU;QACR,IAAIyB,MAAMsB,UAAUC,OAAO,GAAG;IAChC,GAAG;QAACvB;KAAK;IAET,MAAMwB,QAAQlD,YAAY;QACxBkC,YAAY;QACZE,WAAW,EAAE;QACbC,QAAQ,EAAE;QACVE,eAAe;QACfE,WAAW,CAAC;QACZE,UAAU;QACVE,YAAY;IACd,GAAG,EAAE;IAEL,MAAMM,cAAcnD,YAAY;QAC9BgD,UAAUC,OAAO,GAAG;QACpBtB;IACF,GAAG;QAACA;KAAQ;IAEZ,MAAMyB,aAAapD,YACjB,OAAOqD;QACL,IAAI,CAACA,MAAM;QACX,MAAMC,WAAW,MAAMD,KAAKE,IAAI,GAAGC,KAAK,CAAC,IAAM;QAC/C,IAAIF,SAASG,MAAM,GAAGtF,2BAA2B;YAC/C,OAAO,KAAK2D,gBACV,uEACE,WACF;gBAAE4B,SAAS;gBAAWC,gBAAgB;YAAK;QAE/C;QACA,MAAMC,QAAQxF,SAASkF,UAAUO,MAAM,CAAC,CAACC,QACvCA,MAAMC,IAAI,CAAC,CAACC,OAASC,OAAOD,eAAAA,OAAQ,IAAIE,IAAI;QAE9C,IAAIN,MAAMH,MAAM,GAAG,GAAG;YACpB,OAAO,KAAK3B,gBACV,+DACA;gBAAE4B,SAAS;gBAAWC,gBAAgB;YAAK;QAE/C;QACA,MAAMQ,SAASP,KAAK,CAAC,EAAE,CAACQ,GAAG,CAAC,CAACJ,OAASC,OAAOD,eAAAA,OAAQ,IAAIE,IAAI;QAC7D,MAAMG,OAAOT,MAAMU,KAAK,CAAC;QACzBpC,YAAYmB,KAAKkB,IAAI;QACrBnC,WAAW+B;QACX9B,QAAQgC,KAAKC,KAAK,CAAC,GAAG1D,WAAW4D,OAAO;QACxCjC,eAAekC,KAAKC,GAAG,CAAC,GAAGL,KAAKZ,MAAM,GAAG7C,WAAW4D,OAAO;QAC3D/B,WAAW7B,WAAW+D,YAAY,CAACR;QACnCxB,UAAU;QACVE,YAAY;IACd,GACA;QAACf;QAAiBlB;KAAW;IAG/B,MAAMgE,iBAAiBC,OAAOC,MAAM,CAACtC,SAASuC,QAAQ,CAACnE,WAAWoE,aAAa;IAC/E,sDAAsD,GACtD,MAAMC,eAAe/E,QAAQ;kBAOVU;YALfiE;QADF,MAAMK,KAAKC,gBACTN,uBAAAA,OAAOO,OAAO,CAAC5C,SAASzB,IAAI,CAC1B,CAAC,GAAGJ,OAAO,GAAKA,WAAWC,WAAWoE,aAAa,sBADrDH,oBAEG,CAAC,EAAE,mBAAI,CAAC;QAEb,IAAIK,KAAK,GAAG,OAAOzD,KAAKgC,MAAM;QAC9B,MAAM4B,YAAWzE,uBAAAA,WAAWyE,QAAQ,YAAnBzE,uBAAwB,CAACoD,OAAiB,CAACA,KAAKE,IAAI;QACrE,OAAOzC,KAAKoC,MAAM,CAAC,CAACC;gBAA0BA;mBAAhBuB,SAASpB,QAAOH,YAAAA,KAAK,CAACoB,GAAG,YAATpB,YAAa;WAAML,MAAM;IACzE,GAAG;QAACjB;QAASf;QAAMb;KAAW;IAE9B,MAAM0E,UAAUpF,QACd,IACEuB,KACG6C,KAAK,CAAC,GAAG1D,WAAW2E,WAAW,EAC/BnB,GAAG,CAAC,CAACN,QAAUlD,WAAW4E,MAAM,CAAC1B,OAAOtB,WAC7C;QAACf;QAAMe;QAAS5B;KAAW;IAE7B,4EAA4E;IAC5E,MAAM6E,aAAavF,QACjB,IACEU,WAAW6E,UAAU,IAAIhE,KAAKgC,MAAM,GAChC7C,WAAW6E,UAAU,CAAChE,KAAK2C,GAAG,CAAC,CAACN,QAAUlD,WAAW4E,MAAM,CAAC1B,OAAOtB,aACnE,MACN;QAACf;QAAMe;QAAS5B;KAAW;IAE7B,MAAM8E,gBAAgBxF,QACpB,IACE2E,OAAOO,OAAO,CAAC5C,SACZmD,IAAI,CAAC,CAAC,CAACC,EAAE,EAAE,CAACC,EAAE,GAAKV,OAAOS,KAAKT,OAAOU,IACtCzB,GAAG,CAAC,CAAC,GAAGzD,OAAO,GAAKA,SACzB;QAAC6B;KAAQ;IAGX;;;;;;GAMC,GACD,MAAMsD,cAAc9G;IACpB,MAAM,EAAE+G,KAAK,EAAE,GAAGjH,gBAAgB;QAAE0C,MAAM,EAAEA,iBAAAA,SAAUwE;QAAWD,KAAK,EAAEhE,yBAAAA,MAAOgE,KAAK;IAAC;IACrF,MAAME,gBAAgB/F,QAAQ,IAAMK,cAAc4B,SAASV,OAAO;QAACU;QAASV;KAAK;IACjF,MAAMyE,iBAAiBhG,QACrB;YAGQU;eAFN,IAAIuF,IAAY;eACXvF,WAAWwF,MAAM;eACjB,EAACxF,2BAAAA,WAAWE,YAAY,YAAvBF,2BAA2B,EAAE,EAAEwD,GAAG,CAAC,CAACpD,QAAUhD,mBAAmBgD,MAAMC,GAAG;SAC/E;OACH;QAACL;KAAW;IAEd,MAAMyF,iBAAiBrG,YACrB,CAACsG;QACC,MAAMC,QAAQ,IAAIJ;QAClB,MAAMK,OAA4B,CAAC;QACnC,KAAK,MAAM,CAACC,QAAQ9F,OAAO,IAAIkE,OAAOO,OAAO,CAACkB,UAAUX,IAAI,CAAC,CAAC,CAACC,EAAE,EAAE,CAACC,EAAE,GAAKV,OAAOS,KAAKT,OAAOU,IAAK;YACjG,MAAMa,QAAQvB,OAAOsB;YACrB,IAAI,CAACtB,OAAOwB,SAAS,CAACD,UAAUA,QAAQ,KAAKA,SAASvE,QAAQsB,MAAM,EAAE;YACtE,IAAI,CAACyC,eAAeU,GAAG,CAACjG,WAAW4F,MAAMK,GAAG,CAACjG,SAAS;YACtD4F,MAAMM,GAAG,CAAClG;YACV6F,IAAI,CAACE,MAAM,GAAG/F;QAChB;QACA8B,WAAW+D;IACb,GACA;QAACN;QAAgB/D,QAAQsB,MAAM;KAAC;IAGlC,MAAMqD,YAAY9G,YAAY,CAAC0G,OAAe/F;QAC5C8B,WAAW,CAACsE;YACV,MAAMP,OAA4B,CAAC;YACnC,KAAK,MAAM,CAACC,QAAQO,SAAS,IAAInC,OAAOO,OAAO,CAAC2B,UAAW;gBACzD,kEAAkE;gBAClE,yDAAyD;gBACzD,IAAI5B,OAAOsB,YAAYC,SAASM,aAAarG,QAAQ;oBACnD6F,IAAI,CAACrB,OAAOsB,QAAQ,GAAGO;gBACzB;YACF;YACA,IAAIrG,WAAWF,aAAa+F,IAAI,CAACE,MAAM,GAAG/F;YAC1C,OAAO6F;QACT;IACF,GAAG,EAAE;IAEL;;;;;;GAMC,GACD,MAAMS,eAAejH,YAAY;QAC/B,IAAI8C,QAAQ,CAACrB,KAAKgC,MAAM,IAAI,CAACmB,kBAAkB,CAAC5C,cAAc;QAC9De,QAAQ;QACR,IAAImE,QAAQtG,WAAWuG,WAAW;QAClCxE,UAAUuE;QACVrE,YAAY;YAAEuE,MAAM;YAAGF,OAAOzF,KAAKgC,MAAM;QAAC;QAC1C,IAAI;YACF,IAAK,IAAI4D,SAAS,GAAGA,SAAS5F,KAAKgC,MAAM,EAAE4D,UAAUzG,WAAW0G,SAAS,CAAE;gBACzE,IAAItE,UAAUC,OAAO,EAAE;gBACvB,MAAMsE,QAAQ9F,KACX6C,KAAK,CAAC+C,QAAQA,SAASzG,WAAW0G,SAAS,EAC3ClD,GAAG,CAAC,CAACN,QAAUlD,WAAW4E,MAAM,CAAC1B,OAAOtB;gBAC3C,MAAMgF,WAAW,MAAM3I,gBAAgBgD,MAAMjB,WAAW6G,KAAK,EAAE;oBAC7DC,QAAQ;oBACRC,SAAS;wBAAE,gBAAgB;oBAAmB;oBAC9CtD,MAAMuD,KAAKC,SAAS,CAAC;wBAAErG,QAAQQ;wBAAcP,MAAM8F;oBAAM;gBAC3D;gBACA,MAAMO,UAAU,MAAMN,SAASO,IAAI,GAAGvE,KAAK,CAAC,IAAO,CAAA,CAAC,CAAA;gBACpD,IAAI,CAACgE,SAASQ,EAAE,EAAE;;oBAChB,OAAO,KAAKlG,wBACVgG,2BAAAA,QAASG,KAAK,mBAAI,kCAClB;wBAAEvE,SAAS;wBAAWC,gBAAgB;oBAAK;gBAE/C;gBACAuD,QAAQtG,WAAWsH,YAAY,CAAChB,OAAOY,SAAiCT;gBACxE1E,UAAUuE;gBACVrE,YAAY;oBAAEuE,MAAM3C,KAAK0D,GAAG,CAACd,SAASE,MAAM9D,MAAM,EAAEhC,KAAKgC,MAAM;oBAAGyD,OAAOzF,KAAKgC,MAAM;gBAAC;YACvF;YACA3B,gBAAgB,mBAAmB;gBAAE4B,SAAS;gBAAW0E,SAAS;YAAM;QAC1E,EAAE,eAAM;YACNtG,gBAAgB,kCAAkC;gBAChD4B,SAAS;gBACTC,gBAAgB;YAClB;QACF,SAAU;YACRZ,QAAQ;QACV;IACF,GAAG;QAACD;QAAMrB;QAAMmD;QAAgBpC;QAASX;QAAMG;QAAcF;QAAiBlB;KAAW;IAEzF,MAAMyH,wBAAwBrI,YAAY;QACxC,IAAI,EAAC0C,0BAAAA,OAAQ4F,OAAO,CAAC7E,MAAM,GAAE;QAC7BnD,iBACEM,WAAW2H,eAAe,EAC1B,YACA3H,WAAW4H,UAAU,CACnBrG,SACAO,OAAO4F,OAAO,CAAClE,GAAG,CAAC,CAACqE;gBACXhH;mBADsB;gBAC7BqC,KAAK,GAAErC,oBAAAA,IAAI,CAACgH,MAAM/B,KAAK,CAAC,YAAjBjF,oBAAqB,EAAE;gBAC9BiH,QAAQD,MAAMC,MAAM;YACtB;;IAGN,GAAG;QAAChG;QAAQP;QAASV;QAAMb;KAAW;IAEtC,MAAM+H,WAAW,CAAC,CAACjG,UAAU,CAACI;IAE9B,qBACE,KAACpE;QACCgD,MAAMA;QACNkH,QAAO;QACPlF,SAAQ;QACR/B,SAASwB;QACT0F,aAAa;YAAEC,OAAO;QAAU;QAChCC,0BACE;;8BACE,MAACzJ;oBACCwJ,OAAM;oBACNE,MAAK;oBACLC,SAAS9F;oBACT+F,IAAI;wBAAEC,IAAI;oBAAE;;sCAEZ,KAAC3K;4BAAQ4K,MAAM/K,mBAAmB+K,IAAI;;sCACtC,KAAC3K;sCAAQ;;;;8BAEX,KAACsB;oBAAW2D,SAAQ;oBAAK2F,WAAU;8BAChCzI,WAAW0I,KAAK;;8BAEnB,KAAC/K,sBAAYqC,WAAW2I,IAAI;;;QAGhCC,2BACE,KAACpK;YAAOsE,SAAQ;YAAWoF,OAAM;YAAUG,SAAS9F;sBACjDwF,WAAW,SAAS;;kBAIzB,cAAA,KAACrK;YAAUmL,OAAO;sBAChB,cAAA,KAAChK;gBAAMiK,SAAS;0BACbhH,uBACC,KAACiH;oBACCjH,QAAQA;oBACRE,UAAUA;oBACVE,MAAMA;oBACNlC,YAAYA;oBACZgJ,mBAAmBvB;oBACnBwB,WAAW3G;mCAGb;;sCAKE,KAAC1C;4BACCgB,QAAQA;4BACRsI,UAAUhH;4BACViH,YAAYnJ,WAAWoJ,oBAAoB;;sCAE7C,KAACjK;4BAAW2D,SAAQ;4BAAQoF,OAAM;sCAC/BlI,WAAWqJ,KAAK;;sCAEnB,MAACxK;4BAAMyK,WAAU;4BAAMR,SAAS;4BAAGR,IAAI;gCAAEiB,YAAY;gCAAUC,UAAU;gCAAQC,QAAQ;4BAAE;;8CACzF,MAACjL;oCAAOsE,SAAQ;oCAAW2F,WAAU;oCAAQS,UAAUhH;;wCACpD;sDACD,KAACwH;4CACCC,MAAK;4CACLC,QAAO;4CACPC,MAAM;4CACNC,UAAU,CAACC;oDACOA;gDAAhB,KAAKvH,YAAWuH,sBAAAA,MAAMhK,MAAM,CAACiK,KAAK,qBAAlBD,mBAAoB,CAAC,EAAE;gDACvCA,MAAMhK,MAAM,CAACkK,KAAK,GAAG;4CACvB;;;;8CAKJ,KAACzL;oCACC0L,MAAK;oCACLhB,UAAUhH;oCACVmG,SAAS,IACP3I,iBACEM,WAAWmK,gBAAgB,EAC3B,YACAnK,WAAWoK,WAAW;8CAIzB;;gCAEF/I,yBACC,KAAC5C;oCAAKyL,MAAK;oCAAQpH,SAAQ;oCAAWxC,OAAOe;qCAC3C;gCACHR,KAAKgC,MAAM,iBACV,KAAC1D;oCAAW2D,SAAQ;oCAAQoF,OAAM;8CAC/B,GAAGrH,KAAKgC,MAAM,CAACwH,cAAc,GAAG,KAAK,CAAC;qCAEvC;;;wBAEL3I,cAAc,kBACb,KAACrD;4BAAMiM,UAAS;sCACb,CAAC,cAAc,EAAE,AAACzJ,CAAAA,KAAKgC,MAAM,GAAGnB,WAAU,EAAG2I,cAAc,GAAG,CAAC,CAAC,GAC/D,CAAC,qBAAqB,EAAErK,WAAW4D,OAAO,CAACyG,cAAc,GAAG,CAAC,CAAC,GAC9D,uDACA;6BAEF;wBACH9I,QAAQsB,MAAM,iBACb,KAAC0H;4BACChJ,SAASA;4BACTiJ,MAAM,GAAE3J,SAAAA,IAAI,CAAC,EAAE,YAAPA,SAAW,EAAE;4BACrBe,SAASA;4BACT5B,YAAYA;4BACZyK,OAAOvE;6BAEP;wBACH3E,QAAQsB,MAAM,IAAIqC,eAAelF,WAAW0K,UAAU,iBACrD,KAACxF;4BACCyF,MAAK;4BACL/J,QAAQA;4BACRuE,KAAK,EAAEA,gBAAAA,QAASC;4BAChBsF,YAAY1K,WAAW0K,UAAU;4BACjCnJ,SAAS8D;4BACTzD,SAASA;4BACT6D,gBAAgB,CAACC,WAA+CD,eAAeC;6BAE/E;wBACHnE,QAAQsB,MAAM,GAAG,KAAK,CAACmB,+BACtB,KAAC3F;4BAAMiM,UAAS;sCAAWtK,WAAW4K,eAAe;6BACnD;wBACHrJ,QAAQsB,MAAM,GAAG,KAAKmB,iBAAiBa,aAAa;wBACpDtD,QAAQsB,MAAM,GAAG,KAAKmB,+BACrB,KAAC6G;4BACCC,SAAShG;4BACTJ,SAASA;4BACT4B,OAAOzF,KAAKgC,MAAM;4BAClB4B,UAAUJ;4BACVrE,YAAYA;6BAEZ;sCACJ,KAACnB;4BAAMyK,WAAU;4BAAMR,SAAS;4BAAGR,IAAI;gCAAEyC,gBAAgB;4BAAW;sCAClE,cAAA,KAACvM;gCACCsE,SAAQ;gCACR,0CAA0C;gCAC1CoG,UAAUhH,QAAQ,CAACrB,KAAKgC,MAAM,IAAI,CAACmB,kBAAkB,CAAC5C;gCACtDiH,SAAS,IAAM,KAAKhC;0CAEnBxF,KAAKgC,MAAM,GACR,CAAC,OAAO,EAAEhC,KAAKgC,MAAM,CAACwH,cAAc,GAAG,KAAK,CAAC,GAC7C;;;;;;;;AAStB;AACA3J,gBAAgBsK,WAAW,GAAG;AAE9B;;;;;;;CAOC,GACD,SAAST,mBAAqC5J,KAM7C;IACC,MAAM,EAAEY,OAAO,EAAEiJ,MAAM,EAAE5I,OAAO,EAAE5B,UAAU,EAAEyK,KAAK,EAAE,GAAG9J;IACxD,qBACE,MAAC9B;QAAMiK,SAAS;;0BACd,KAAC3J;gBAAW2D,SAAQ;0BAAa;;0BACjC,MAAC/E;gBAAYmM,MAAK;;kCAChB,KAAClL;kCACC,cAAA,MAACC;;8CACC,KAACF;8CAAW;;8CACZ,KAACA;8CAAW;;8CACZ,KAACA;8CAAW;;;;;kCAGhB,KAACD;kCACEyC,QAAQiC,GAAG,CAAC,CAACqC,QAAQC;gCAKN0E,eAOD5I,gBAUL5B;iDArBR,MAACf;;kDACC,KAACF;kDAAW8G,UAAU,CAAC,OAAO,EAAEC,QAAQ,GAAG;;kDAC3C,KAAC/G;kDACC,cAAA,KAACI;4CAAW2D,SAAQ;4CAAQoF,OAAM;4CAAiB+C,MAAM;sDACtD5H,QAAOmH,gBAAAA,MAAM,CAAC1E,MAAM,YAAb0E,gBAAiB;;;kDAG7B,KAACzL;kDACC,cAAA,MAACG;4CACCgM,MAAM;4CACNhB,MAAK;4CACLD,KAAK,GAAErI,iBAAAA,OAAO,CAACkE,MAAM,YAAdlE,iBAAkB/B;4CACzBiK,UAAU,CAACC,QAAUU,MAAM3E,OAAOiE,MAAMhK,MAAM,CAACkK,KAAK;4CACpD3B,IAAI;gDAAE6C,UAAU;4CAAI;;8DAEpB,KAACvM;oDAASqL,OAAOpK;8DAAc;;gDAC9BG,WAAWwF,MAAM,CAAChC,GAAG,CAAC,CAACpD,sBACtB,KAACxB;wDAAqBqL,OAAO7J;kEAC1BJ,WAAWO,WAAW,CAACH,MAAM;uDADjBA;gDAIhB,EAACJ,2BAAAA,WAAWE,YAAY,YAAvBF,2BAA2B,EAAE,EAAEwD,GAAG,CAAC,CAACpD,sBACpC,KAACxB;wDAAyBqL,OAAO7M,mBAAmBgD,MAAMC,GAAG;kEAC1D,GAAGD,MAAME,KAAK,CAAC,SAAS,CAAC;uDADbF,MAAMC,GAAG;;;;;+BAtBjB,GAAGwF,OAAO,CAAC,EAAEC,OAAO;;;;;;;AAkC/C;AAEA;;;;;;;;CAQC,GACD,SAAS+E,mBAAqClK,KAS7C;IACC,MAAM,EAAEmK,OAAO,EAAEpG,OAAO,EAAE4B,KAAK,EAAE7B,QAAQ,EAAEzE,UAAU,EAAE,GAAGW;IAC1D,MAAMyC,OAAO,CAACgI,KAA8BrL;YAK5BqL;QAJd,MAAMnL,YAAY5C,sBAAsB0C;QACxC,IAAIE,WAAW;;gBACEmL;YAAf,OAAO/H,gBAAQ+H,cAAAA,GAAG,CAAC,SAAS,qBAAd,AAACA,WAAsD,CAACnL,UAAU,mBAAI;QACtF;QACA,OAAOoD,QAAO+H,cAAAA,GAAG,CAACrL,OAAO,YAAXqL,cAAe;IAC/B;IACA,qBACE,MAACvM;QAAMiK,SAAS;;0BACd,KAAC3J;gBAAW2D,SAAQ;0BACjB,CAAC,gBAAgB,EAAEe,KAAK0D,GAAG,CAAC7C,QAAQ7B,MAAM,EAAE7C,WAAW2E,WAAW,EAAE,IAAI,EAAE2B,MAAM+D,cAAc,IAAI;;YAEpG5F,WAAW,kBACV,KAACpG;gBAAMiM,UAAS;0BAAQtK,WAAWqL,cAAc,CAAC5G,UAAU6B;iBAC1D;0BACJ,KAAC/H;0BACC,cAAA,MAACR;oBAAYmM,MAAK;;sCAChB,KAAClL;sCACC,cAAA,KAACC;0CACE6L,QAAQtH,GAAG,CAAC,CAACzD,uBACZ,KAAChB;kDAAwBe,YAAYC,QAAQC;uCAA7BD;;;sCAItB,KAACjB;sCACE4F,QAAQlB,GAAG,CAAC,CAAC4H,KAAKtF,sBACjB,KAAC7G;8CACE6L,QAAQtH,GAAG,CAAC,CAACzD,uBACZ,KAAChB;sDACC,cAAA,KAACI;gDAAW2D,SAAQ;gDAAQmI,MAAM;gDAAC3C,IAAI;oDAAEgD,UAAU;gDAAI;0DACpDlI,KAAKgI,KAAKrL;;2CAFCA;mCAFL+F;;;;;;;AAe7B;AAEA,8CAA8C,GAC9C,SAASiD,kBAAwEpI,KAUhF;;IACC,MAAM,EAAEmB,MAAM,EAAEE,QAAQ,EAAEE,IAAI,EAAElC,UAAU,EAAEgJ,iBAAiB,EAAEC,SAAS,EAAE,GAAGtI;IAC7E,MAAM4K,UAAUvJ,CAAAA,4BAAAA,SAAUsE,KAAK,IAC3BzC,KAAK0D,GAAG,CAAC,AAACvF,SAASwE,IAAI,GAAGxE,SAASsE,KAAK,GAAI,KAAK,OACjD;IACJ,MAAMkF,kBAAkBlM,QAAQ;QAC9B,MAAMmM,SAA0C,CAAC;QACjD,KAAK,MAAM5D,SAAS/F,OAAO4F,OAAO,CAAE;gBACV+D;YAAxBA,MAAM,CAAC5D,MAAMC,MAAM,CAAC,GAAG,EAAC2D,uBAAAA,MAAM,CAAC5D,MAAMC,MAAM,CAAC,YAApB2D,uBAAwB,KAAK;QACvD;QACA,OAAOxH,OAAOO,OAAO,CAACiH;IACxB,GAAG;QAAC3J,OAAO4F,OAAO;KAAC;IACnB,MAAMgE,gBAAgBzH,OAAOO,OAAO,CAAC1C,OAAO6J,OAAO,EAAE1I,MAAM,CAAC,CAAC,GAAG2I,MAAM,GAAKA,QAAQ;IACnF,qBACE,MAAC/M;QAAMiK,SAAS;;0BACd,KAAC3J;gBAAW2D,SAAQ;gBAAQoF,OAAM;0BAC/BhG,OACG,GAAG,SAACF,4BAAAA,SAAUwE,IAAI,mBAAI,GAAG6D,cAAc,GAAG,IAAI,EAAE,UAACrI,4BAAAA,SAAUsE,KAAK,oBAAI,GAAG+D,cAAc,GAAG,WAAW,CAAC,GACpG,CAAC,UAAU,EAAEvI,OAAO+J,OAAO,CAACxB,cAAc,GAAG,QAAQ,CAAC,GACtD,GAAGvI,OAAOgK,MAAM,CAACzB,cAAc,GAAG,UAAU,CAAC,GAC7C,GAAGvI,OAAO4F,OAAO,CAAC7E,MAAM,CAACwH,cAAc,GAAG,SAAS,CAAC;;0BAE1D,KAAC1L;gBACCmE,SAAQ;gBACRmH,OAAOsB;gBACPjD,IAAI;oBAAEyD,cAAc;gBAAE;;YAEvBP,gBAAgB3I,MAAM,iBACrB,MAAC9E;gBAAYmM,MAAK;;kCAChB,KAAClL;kCACC,cAAA,MAACC;;8CACC,KAACF;8CAAW;;8CACZ,KAACA;oCAAUiN,OAAM;8CAAS;;;;;kCAG9B,KAAClN;kCACE0M,gBAAgBhI,GAAG,CAAC,CAAC,CAACsE,QAAQ8D,MAAM;gCAErB5L;iDADd,MAACf;;kDACC,KAACF;mDAAWiB,gCAAAA,WAAWiM,UAAU,CAACnE,OAAO,YAA7B9H,gCAAiC8H;;kDAC7C,KAAC/I;wCAAUiN,OAAM;kDAASJ;;;+BAFb9D;;;;iBAOnB;YACH4D,cAAc7I,MAAM,iBACnB,MAACxE;gBAAMiM,UAAS;;kCACd,KAAChM;kCAAY;;oBACZ,0CACCoN,cACGlI,GAAG,CAAC,CAAC,CAACpD,OAAOwL,MAAM,GAAK,GAAGpL,kBAAkBJ,OAAOJ,YAAY,EAAE,EAAE4L,MAAM,CAAC,CAAC,EAC5EM,IAAI,CAAC,QACR;;iBAEF;YACHpK,OAAOqK,gBAAgB,CAACtJ,MAAM,iBAC7B,KAACxE;gBAAMiM,UAAS;0BACb,6DACC,CAAC,eAAe,EAAExI,OAAOqK,gBAAgB,CAACzI,KAAK,CAAC,GAAG,GAAGwI,IAAI,CAAC,OAAO,GACjEpK,CAAAA,OAAOqK,gBAAgB,CAACtJ,MAAM,GAAG,IAC9B,CAAC,KAAK,EAAEf,OAAOqK,gBAAgB,CAACtJ,MAAM,GAAG,EAAE,MAAM,CAAC,GAClD,GAAE;iBAER;YACHvF,2BAA2BwE,OAAOsK,YAAY,kBAC7C,KAAC/N;gBAAMiM,UAAS;0BAAWhN,2BAA2BwE,OAAOsK,YAAY;iBACvE;YACHpM,WAAWqM,YAAY,oBAAvBrM,WAAWqM,YAAY,MAAvBrM,YAA0B8B;0BAC3B,MAACjD;gBAAMyK,WAAU;gBAAMR,SAAS;gBAAGR,IAAI;oBAAEyC,gBAAgB;gBAAW;;oBACjEjJ,OAAO4F,OAAO,CAAC7E,MAAM,iBACpB,KAACrE;wBAAOsE,SAAQ;wBAAWuF,SAASW;kCACjC;yBAED;oBACH,CAAC9G,qBACA,KAAC1D;wBAAOsE,SAAQ;wBAAWuF,SAASY;kCACjC;yBAED;;;;;AAIZ;AAEA;;;;CAIC,GACD,OAAO,SAASqD,gBAAgB3L,KAG/B;IACC,MAAM,EAAEL,QAAQ,YAAY,EAAEiM,QAAQ,EAAE,GAAG5L;IAC3C,MAAM,CAACG,MAAM0L,QAAQ,GAAGhN,SAAS;IACjC,MAAM,CAACiN,SAASC,WAAW,GAAGlN,SAAS;IACvC,MAAMmN,aAAavN,YAAY;QAC7BsN,WAAW;QACXF,QAAQ;IACV,GAAG,EAAE;IACL,MAAMjK,cAAcnD,YAAY,IAAMoN,QAAQ,QAAQ,EAAE;IACxD,qBACE;;0BACE,KAAChO;gBAAO0L,MAAK;gBAAQ7B,SAASsE;0BAC3BrM;;YAEFmM,UAAUF,SAASzL,MAAMyB,eAAe;;;AAG/C;AACA+J,gBAAgBtB,WAAW,GAAG;AAE9B,eAAetK,gBAAe"}
@@ -1,24 +0,0 @@
1
- import { type DealImportField, type DealImportRawRow, type DealImportSkippedRow } from '../model/crm-deal-import';
2
- import { type CsvImportVocabulary } from './csv-import-drawer';
3
- /** The browser-side address of the route one chunk is posted to. */
4
- export declare const DEALS_IMPORT_URL = "/api/crm/deals-import";
5
- /** Built once: nothing in it depends on a render. */
6
- export declare const DEAL_IMPORT_VOCABULARY: CsvImportVocabulary<DealImportField, DealImportRawRow & Record<string, unknown>, DealImportSkippedRow>;
7
- export interface DealImportDrawerProps {
8
- open: boolean;
9
- onClose: () => void;
10
- /** The site the file is filed under, or `null` at the organization level. */
11
- hostId: string | null;
12
- }
13
- export declare function DealImportDrawer(props: DealImportDrawerProps): import("react").JSX.Element;
14
- export declare namespace DealImportDrawer {
15
- var displayName: string;
16
- }
17
- /** The "Import CSV" action on the deals table, with the drawer it opens. */
18
- export declare function DealImportButton(props: {
19
- hostId: string | null;
20
- }): import("react").JSX.Element;
21
- export declare namespace DealImportButton {
22
- var displayName: string;
23
- }
24
- export default DealImportDrawer;
@@ -1,83 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Aglyn LLC
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */ 'use client';
17
- import { jsx as _jsx } from "react/jsx-runtime";
18
- /**
19
- * IMPORTING A DEALS FILE — the deal vocabulary over the shared drawer
20
- * (AGL-2662).
21
- *
22
- * The server half is `server/deals-import.ts`. What is particular to
23
- * deals: the title is the one cell every row needs, the pipeline and the
24
- * stage travel as NAMES the server resolves (and refuses, by name, when
25
- * the org has no such pipeline or stage), and nothing is merged — a deal
26
- * has no key, so every row is a new deal.
27
- */ import { pluginDocsHelp } from "@aglyn/aglyn";
28
- import { DEAL_IMPORT_CHUNK_SIZE, DEAL_IMPORT_FIELD_LABELS, DEAL_IMPORT_FIELDS, DEAL_IMPORT_MAX_ROWS, DEAL_IMPORT_PREVIEW_ROWS, DEAL_IMPORT_SKIP_LABELS, dealImportSkippedCsv, emptyDealImportResult, guessDealImportMapping, mapDealImportRow, mergeDealImportResults } from "../model/crm-deal-import.js";
29
- import { dealsCsv } from "../model/deals-csv.js";
30
- import { CsvImportButton, CsvImportDrawer } from "./csv-import-drawer.js";
31
- /** The browser-side address of the route one chunk is posted to. */ export const DEALS_IMPORT_URL = '/api/crm/deals-import';
32
- /** Built once: nothing in it depends on a render. */ export const DEAL_IMPORT_VOCABULARY = {
33
- title: 'Import deals from CSV',
34
- collection: 'deals',
35
- help: pluginDocsHelp('deals', {
36
- anchor: '#import-from-csv'
37
- }),
38
- sitePickerHelperText: 'The site these deals are filed under — it decides which of your sites ' + 'may see them.',
39
- intro: 'A CSV with a header row. Match its columns to deal fields below, check ' + 'the preview, then import. Name the pipeline and the stage as they ' + 'appear in your settings; a row naming neither lands in the default ' + 'pipeline’s first stage. Every row becomes a new deal — importing a ' + `file twice files it twice. Up to ${DEAL_IMPORT_MAX_ROWS.toLocaleString()} ` + 'rows per file — split a larger one.',
40
- fields: DEAL_IMPORT_FIELDS,
41
- fieldLabels: DEAL_IMPORT_FIELD_LABELS,
42
- requiredField: 'title',
43
- requiredWarning: 'Choose which column holds the deal title. It is the one field every ' + 'row needs.',
44
- unusableNotice: (count, total)=>`${count.toLocaleString()} of ${total.toLocaleString()} rows have no ` + 'title and will be skipped. You can download them after the import.',
45
- guessMapping: guessDealImportMapping,
46
- mapRow: (cells, mapping)=>mapDealImportRow(cells, mapping),
47
- route: DEALS_IMPORT_URL,
48
- maxRows: DEAL_IMPORT_MAX_ROWS,
49
- chunkSize: DEAL_IMPORT_CHUNK_SIZE,
50
- previewRows: DEAL_IMPORT_PREVIEW_ROWS,
51
- emptyResult: emptyDealImportResult,
52
- mergeResults: mergeDealImportResults,
53
- skipLabels: DEAL_IMPORT_SKIP_LABELS,
54
- skippedCsv: dealImportSkippedCsv,
55
- skippedFileName: 'skipped-deals.csv',
56
- // The export's own header over no rows, so an export re-imports as is.
57
- templateCsv: ()=>dealsCsv([]),
58
- templateFileName: 'deals-template.csv'
59
- };
60
- export function DealImportDrawer(props) {
61
- const { open, onClose, hostId } = props;
62
- return /*#__PURE__*/ _jsx(CsvImportDrawer, {
63
- open: open,
64
- onClose: onClose,
65
- hostId: hostId,
66
- vocabulary: DEAL_IMPORT_VOCABULARY
67
- });
68
- }
69
- DealImportDrawer.displayName = 'DealImportDrawer';
70
- /** The "Import CSV" action on the deals table, with the drawer it opens. */ export function DealImportButton(props) {
71
- const { hostId } = props;
72
- return /*#__PURE__*/ _jsx(CsvImportButton, {
73
- children: (open, onClose)=>/*#__PURE__*/ _jsx(DealImportDrawer, {
74
- open: open,
75
- onClose: onClose,
76
- hostId: hostId
77
- })
78
- });
79
- }
80
- DealImportButton.displayName = 'DealImportButton';
81
- export default DealImportDrawer;
82
-
83
- //# sourceMappingURL=deal-import-drawer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/deal-import-drawer.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\n/**\n * IMPORTING A DEALS FILE — the deal vocabulary over the shared drawer\n * (AGL-2662).\n *\n * The server half is `server/deals-import.ts`. What is particular to\n * deals: the title is the one cell every row needs, the pipeline and the\n * stage travel as NAMES the server resolves (and refuses, by name, when\n * the org has no such pipeline or stage), and nothing is merged — a deal\n * has no key, so every row is a new deal.\n */\n\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport {\n DEAL_IMPORT_CHUNK_SIZE,\n DEAL_IMPORT_FIELD_LABELS,\n DEAL_IMPORT_FIELDS,\n DEAL_IMPORT_MAX_ROWS,\n DEAL_IMPORT_PREVIEW_ROWS,\n DEAL_IMPORT_SKIP_LABELS,\n type DealImportField,\n type DealImportRawRow,\n type DealImportSkippedRow,\n dealImportSkippedCsv,\n emptyDealImportResult,\n guessDealImportMapping,\n mapDealImportRow,\n mergeDealImportResults,\n} from '../model/crm-deal-import'\nimport { dealsCsv } from '../model/deals-csv'\nimport {\n CsvImportButton,\n CsvImportDrawer,\n type CsvImportVocabulary,\n} from './csv-import-drawer'\n\n/** The browser-side address of the route one chunk is posted to. */\nexport const DEALS_IMPORT_URL = '/api/crm/deals-import'\n\n/** Built once: nothing in it depends on a render. */\nexport const DEAL_IMPORT_VOCABULARY: CsvImportVocabulary<\n DealImportField,\n DealImportRawRow & Record<string, unknown>,\n DealImportSkippedRow\n> = {\n title: 'Import deals from CSV',\n collection: 'deals',\n help: pluginDocsHelp('deals', { anchor: '#import-from-csv' }),\n sitePickerHelperText:\n 'The site these deals are filed under — it decides which of your sites ' +\n 'may see them.',\n intro:\n 'A CSV with a header row. Match its columns to deal fields below, check ' +\n 'the preview, then import. Name the pipeline and the stage as they ' +\n 'appear in your settings; a row naming neither lands in the default ' +\n 'pipeline’s first stage. Every row becomes a new deal — importing a ' +\n `file twice files it twice. Up to ${DEAL_IMPORT_MAX_ROWS.toLocaleString()} ` +\n 'rows per file — split a larger one.',\n fields: DEAL_IMPORT_FIELDS,\n fieldLabels: DEAL_IMPORT_FIELD_LABELS,\n requiredField: 'title',\n requiredWarning:\n 'Choose which column holds the deal title. It is the one field every ' +\n 'row needs.',\n unusableNotice: (count, total) =>\n `${count.toLocaleString()} of ${total.toLocaleString()} rows have no ` +\n 'title and will be skipped. You can download them after the import.',\n guessMapping: guessDealImportMapping,\n mapRow: (cells, mapping) =>\n mapDealImportRow(cells, mapping) as DealImportRawRow & Record<string, unknown>,\n route: DEALS_IMPORT_URL,\n maxRows: DEAL_IMPORT_MAX_ROWS,\n chunkSize: DEAL_IMPORT_CHUNK_SIZE,\n previewRows: DEAL_IMPORT_PREVIEW_ROWS,\n emptyResult: emptyDealImportResult,\n mergeResults: mergeDealImportResults,\n skipLabels: DEAL_IMPORT_SKIP_LABELS,\n skippedCsv: dealImportSkippedCsv,\n skippedFileName: 'skipped-deals.csv',\n // The export's own header over no rows, so an export re-imports as is.\n templateCsv: () => dealsCsv([]),\n templateFileName: 'deals-template.csv',\n}\n\nexport interface DealImportDrawerProps {\n open: boolean\n onClose: () => void\n /** The site the file is filed under, or `null` at the organization level. */\n hostId: string | null\n}\n\nexport function DealImportDrawer(props: DealImportDrawerProps) {\n const { open, onClose, hostId } = props\n return (\n <CsvImportDrawer\n open={open}\n onClose={onClose}\n hostId={hostId}\n vocabulary={DEAL_IMPORT_VOCABULARY}\n />\n )\n}\nDealImportDrawer.displayName = 'DealImportDrawer'\n\n/** The \"Import CSV\" action on the deals table, with the drawer it opens. */\nexport function DealImportButton(props: { hostId: string | null }) {\n const { hostId } = props\n return (\n <CsvImportButton>\n {(open, onClose) => <DealImportDrawer open={open} onClose={onClose} hostId={hostId} />}\n </CsvImportButton>\n )\n}\nDealImportButton.displayName = 'DealImportButton'\n\nexport default DealImportDrawer\n"],"names":["pluginDocsHelp","DEAL_IMPORT_CHUNK_SIZE","DEAL_IMPORT_FIELD_LABELS","DEAL_IMPORT_FIELDS","DEAL_IMPORT_MAX_ROWS","DEAL_IMPORT_PREVIEW_ROWS","DEAL_IMPORT_SKIP_LABELS","dealImportSkippedCsv","emptyDealImportResult","guessDealImportMapping","mapDealImportRow","mergeDealImportResults","dealsCsv","CsvImportButton","CsvImportDrawer","DEALS_IMPORT_URL","DEAL_IMPORT_VOCABULARY","title","collection","help","anchor","sitePickerHelperText","intro","toLocaleString","fields","fieldLabels","requiredField","requiredWarning","unusableNotice","count","total","guessMapping","mapRow","cells","mapping","route","maxRows","chunkSize","previewRows","emptyResult","mergeResults","skipLabels","skippedCsv","skippedFileName","templateCsv","templateFileName","DealImportDrawer","props","open","onClose","hostId","vocabulary","displayName","DealImportButton"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA;;;;;;;;;CASC,GAED,SAASA,cAAc,QAAQ,eAAc;AAC7C,SACEC,sBAAsB,EACtBC,wBAAwB,EACxBC,kBAAkB,EAClBC,oBAAoB,EACpBC,wBAAwB,EACxBC,uBAAuB,EAIvBC,oBAAoB,EACpBC,qBAAqB,EACrBC,sBAAsB,EACtBC,gBAAgB,EAChBC,sBAAsB,QACjB,8BAA0B;AACjC,SAASC,QAAQ,QAAQ,wBAAoB;AAC7C,SACEC,eAAe,EACfC,eAAe,QAEV,yBAAqB;AAE5B,kEAAkE,GAClE,OAAO,MAAMC,mBAAmB,wBAAuB;AAEvD,mDAAmD,GACnD,OAAO,MAAMC,yBAIT;IACFC,OAAO;IACPC,YAAY;IACZC,MAAMnB,eAAe,SAAS;QAAEoB,QAAQ;IAAmB;IAC3DC,sBACE,2EACA;IACFC,OACE,4EACA,uEACA,wEACA,wEACA,CAAC,iCAAiC,EAAElB,qBAAqBmB,cAAc,GAAG,CAAC,CAAC,GAC5E;IACFC,QAAQrB;IACRsB,aAAavB;IACbwB,eAAe;IACfC,iBACE,yEACA;IACFC,gBAAgB,CAACC,OAAOC,QACtB,GAAGD,MAAMN,cAAc,GAAG,IAAI,EAAEO,MAAMP,cAAc,GAAG,cAAc,CAAC,GACtE;IACFQ,cAActB;IACduB,QAAQ,CAACC,OAAOC,UACdxB,iBAAiBuB,OAAOC;IAC1BC,OAAOpB;IACPqB,SAAShC;IACTiC,WAAWpC;IACXqC,aAAajC;IACbkC,aAAa/B;IACbgC,cAAc7B;IACd8B,YAAYnC;IACZoC,YAAYnC;IACZoC,iBAAiB;IACjB,uEAAuE;IACvEC,aAAa,IAAMhC,SAAS,EAAE;IAC9BiC,kBAAkB;AACpB,EAAC;AASD,OAAO,SAASC,iBAAiBC,KAA4B;IAC3D,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEC,MAAM,EAAE,GAAGH;IAClC,qBACE,KAACjC;QACCkC,MAAMA;QACNC,SAASA;QACTC,QAAQA;QACRC,YAAYnC;;AAGlB;AACA8B,iBAAiBM,WAAW,GAAG;AAE/B,0EAA0E,GAC1E,OAAO,SAASC,iBAAiBN,KAAgC;IAC/D,MAAM,EAAEG,MAAM,EAAE,GAAGH;IACnB,qBACE,KAAClC;kBACE,CAACmC,MAAMC,wBAAY,KAACH;gBAAiBE,MAAMA;gBAAMC,SAASA;gBAASC,QAAQA;;;AAGlF;AACAG,iBAAiBD,WAAW,GAAG;AAE/B,eAAeN,iBAAgB"}
@@ -1,27 +0,0 @@
1
- import { type LeadImportField, type LeadImportRawRow, type LeadImportSkippedRow } from '../model/crm-lead-import';
2
- import { type CsvImportVocabulary } from './csv-import-drawer';
3
- /** The browser-side address of the route one chunk is posted to. */
4
- export declare const LEADS_IMPORT_URL = "/api/crm/leads-import";
5
- /** Built once: nothing in it depends on a render. */
6
- export declare const LEAD_IMPORT_VOCABULARY: CsvImportVocabulary<LeadImportField, LeadImportRawRow & Record<string, unknown>, LeadImportSkippedRow>;
7
- export interface LeadImportDrawerProps {
8
- open: boolean;
9
- onClose: () => void;
10
- /** The site the file is filed under, or `null` at the organization level. */
11
- hostId: string | null;
12
- /** The org the lead source list is read from (AGL-3298); `null` while it settles. */
13
- orgId?: string | null;
14
- }
15
- export declare function LeadImportDrawer(props: LeadImportDrawerProps): import("react").JSX.Element;
16
- export declare namespace LeadImportDrawer {
17
- var displayName: string;
18
- }
19
- /** The "Import CSV" action on the leads list, with the drawer it opens. */
20
- export declare function LeadImportButton(props: {
21
- hostId: string | null;
22
- orgId?: string | null;
23
- }): import("react").JSX.Element;
24
- export declare namespace LeadImportButton {
25
- var displayName: string;
26
- }
27
- export default LeadImportDrawer;
@@ -1,118 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Aglyn LLC
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */ 'use client';
17
- import { _ as _extends } from "@swc/helpers/_/_extends";
18
- import { jsx as _jsx } from "react/jsx-runtime";
19
- /**
20
- * IMPORTING A LEADS FILE — the lead vocabulary over the shared drawer
21
- * (AGL-2701).
22
- *
23
- * The server half is `server/leads-import.ts`. What is particular to
24
- * leads: the address is the one cell every row needs AND the document's
25
- * id, so a row is merged onto the person the site already holds rather
26
- * than filed twice; the file may set only the team's working state, since
27
- * the capture history is the capture door's; and there is no consent
28
- * column, because a spreadsheet is not a checkbox somebody ticked.
29
- *
30
- * ## The site is the whole scope, so the picker is the whole question
31
- *
32
- * A lead lives under `hosts/{hostId}/leads` and is private to that site by
33
- * path. At the organization level there is therefore no site to fall back
34
- * on and no scope token that could stand in for one, so the shared
35
- * drawer's site picker is not a convenience here — it is the only thing
36
- * that says where the file lands, and the import stays held until it is
37
- * answered.
38
- */ import { crmLeadSourceRefusal, normalizeContactEmail, pluginDocsHelp } from "@aglyn/aglyn";
39
- import { Alert } from "@mui/material";
40
- import { useMemo } from "react";
41
- import { useLeadSourcePicklist } from "../hooks/use-lead-source-picklist.js";
42
- import { LEAD_IMPORT_CHUNK_SIZE, LEAD_IMPORT_FIELD_LABELS, LEAD_IMPORT_FIELDS, LEAD_IMPORT_MAX_ROWS, LEAD_IMPORT_PREVIEW_ROWS, LEAD_IMPORT_SKIP_LABELS, emptyLeadImportResult, guessLeadImportMapping, leadImportSkippedCsv, leadImportUnknownLeadSources, mapLeadImportRow, mergeLeadImportResults } from "../model/crm-lead-import.js";
43
- import { leadsCsv } from "../model/leads-csv.js";
44
- import { CsvImportButton, CsvImportDrawer } from "./csv-import-drawer.js";
45
- /** The browser-side address of the route one chunk is posted to. */ export const LEADS_IMPORT_URL = '/api/crm/leads-import';
46
- /** Built once: nothing in it depends on a render. */ export const LEAD_IMPORT_VOCABULARY = {
47
- title: 'Import leads from CSV',
48
- collection: 'leads',
49
- help: pluginDocsHelp('crmLeads', {
50
- anchor: '#import-from-csv'
51
- }),
52
- sitePickerHelperText: 'The site these leads are filed under — a lead is private to one site, ' + 'and this is the site that will hold them.',
53
- intro: 'A CSV with a header row. Match its columns to lead fields below, check ' + 'the preview, then import. A person this site has already met is ' + 'updated rather than added twice. Nobody is emailed, and no marketing ' + 'consent is recorded — a file is not a checkbox somebody ticked, so an ' + 'imported lead can be mailed only if this site already holds a consent ' + `for them. Up to ${LEAD_IMPORT_MAX_ROWS.toLocaleString()} rows per file ` + '— split a larger one.',
54
- fields: LEAD_IMPORT_FIELDS,
55
- fieldLabels: LEAD_IMPORT_FIELD_LABELS,
56
- requiredField: 'email',
57
- requiredWarning: 'Choose which column holds the email address. It is the one field every ' + 'row needs, and it is what tells one lead from another.',
58
- unusable: (cell)=>!normalizeContactEmail(cell),
59
- unusableNotice: (count, total)=>`${count.toLocaleString()} of ${total.toLocaleString()} rows have no ` + 'usable email address and will be skipped. You can download them after ' + 'the import.',
60
- guessMapping: guessLeadImportMapping,
61
- mapRow: (cells, mapping)=>mapLeadImportRow(cells, mapping),
62
- route: LEADS_IMPORT_URL,
63
- maxRows: LEAD_IMPORT_MAX_ROWS,
64
- chunkSize: LEAD_IMPORT_CHUNK_SIZE,
65
- previewRows: LEAD_IMPORT_PREVIEW_ROWS,
66
- emptyResult: emptyLeadImportResult,
67
- mergeResults: mergeLeadImportResults,
68
- skipLabels: LEAD_IMPORT_SKIP_LABELS,
69
- skippedCsv: leadImportSkippedCsv,
70
- skippedFileName: 'skipped-leads.csv',
71
- // The export's own header over no rows, so an export re-imports as is —
72
- // the columns a file cannot set land on "Do not import".
73
- templateCsv: ()=>leadsCsv([]),
74
- templateFileName: 'leads-template.csv'
75
- };
76
- export function LeadImportDrawer(props) {
77
- const { open, onClose, hostId, orgId = null } = props;
78
- /*
79
- * THE ORG'S LEAD SOURCES (AGL-3298). The server refuses a row naming a
80
- * value outside the list; the notice says so before the file is sent,
81
- * naming the values it holds that the list does not and the ones it
82
- * allows, so the operator can fix the file or add the value first.
83
- */ const { picklist } = useLeadSourcePicklist(orgId);
84
- const vocabulary = useMemo(()=>_extends({}, LEAD_IMPORT_VOCABULARY, {
85
- rowsNotice: (rows)=>{
86
- const unknown = leadImportUnknownLeadSources(rows, picklist);
87
- if (!unknown.length) return null;
88
- return /*#__PURE__*/ _jsx(Alert, {
89
- severity: "warning",
90
- children: `${unknown.length === 1 ? 'A lead source' : `${unknown.length} lead sources`} in this ` + `file ${unknown.length === 1 ? 'is' : 'are'} not in your list: ` + `${unknown.slice(0, 10).join(', ')}${unknown.length > 10 ? ', …' : ''}. ` + 'Those rows will be skipped. ' + crmLeadSourceRefusal(picklist) + ' Add a value under CRM › Fields › Leads to import it.'
91
- });
92
- }
93
- }), [
94
- picklist
95
- ]);
96
- return /*#__PURE__*/ _jsx(CsvImportDrawer, {
97
- open: open,
98
- onClose: onClose,
99
- hostId: hostId,
100
- vocabulary: vocabulary
101
- });
102
- }
103
- LeadImportDrawer.displayName = 'LeadImportDrawer';
104
- /** The "Import CSV" action on the leads list, with the drawer it opens. */ export function LeadImportButton(props) {
105
- const { hostId, orgId = null } = props;
106
- return /*#__PURE__*/ _jsx(CsvImportButton, {
107
- children: (open, onClose)=>/*#__PURE__*/ _jsx(LeadImportDrawer, {
108
- open: open,
109
- onClose: onClose,
110
- hostId: hostId,
111
- orgId: orgId
112
- })
113
- });
114
- }
115
- LeadImportButton.displayName = 'LeadImportButton';
116
- export default LeadImportDrawer;
117
-
118
- //# sourceMappingURL=lead-import-drawer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/lead-import-drawer.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\n/**\n * IMPORTING A LEADS FILE — the lead vocabulary over the shared drawer\n * (AGL-2701).\n *\n * The server half is `server/leads-import.ts`. What is particular to\n * leads: the address is the one cell every row needs AND the document's\n * id, so a row is merged onto the person the site already holds rather\n * than filed twice; the file may set only the team's working state, since\n * the capture history is the capture door's; and there is no consent\n * column, because a spreadsheet is not a checkbox somebody ticked.\n *\n * ## The site is the whole scope, so the picker is the whole question\n *\n * A lead lives under `hosts/{hostId}/leads` and is private to that site by\n * path. At the organization level there is therefore no site to fall back\n * on and no scope token that could stand in for one, so the shared\n * drawer's site picker is not a convenience here — it is the only thing\n * that says where the file lands, and the import stays held until it is\n * answered.\n */\n\nimport { crmLeadSourceRefusal, normalizeContactEmail, pluginDocsHelp } from '@aglyn/aglyn'\nimport { Alert } from '@mui/material'\nimport { useMemo } from 'react'\nimport { useLeadSourcePicklist } from '../hooks/use-lead-source-picklist'\nimport {\n LEAD_IMPORT_CHUNK_SIZE,\n LEAD_IMPORT_FIELD_LABELS,\n LEAD_IMPORT_FIELDS,\n LEAD_IMPORT_MAX_ROWS,\n LEAD_IMPORT_PREVIEW_ROWS,\n LEAD_IMPORT_SKIP_LABELS,\n type LeadImportField,\n type LeadImportRawRow,\n type LeadImportSkippedRow,\n emptyLeadImportResult,\n guessLeadImportMapping,\n leadImportSkippedCsv,\n leadImportUnknownLeadSources,\n mapLeadImportRow,\n mergeLeadImportResults,\n} from '../model/crm-lead-import'\nimport { leadsCsv } from '../model/leads-csv'\nimport {\n CsvImportButton,\n CsvImportDrawer,\n type CsvImportVocabulary,\n} from './csv-import-drawer'\n\n/** The browser-side address of the route one chunk is posted to. */\nexport const LEADS_IMPORT_URL = '/api/crm/leads-import'\n\n/** Built once: nothing in it depends on a render. */\nexport const LEAD_IMPORT_VOCABULARY: CsvImportVocabulary<\n LeadImportField,\n LeadImportRawRow & Record<string, unknown>,\n LeadImportSkippedRow\n> = {\n title: 'Import leads from CSV',\n collection: 'leads',\n help: pluginDocsHelp('crmLeads', { anchor: '#import-from-csv' }),\n sitePickerHelperText:\n 'The site these leads are filed under — a lead is private to one site, ' +\n 'and this is the site that will hold them.',\n intro:\n 'A CSV with a header row. Match its columns to lead fields below, check ' +\n 'the preview, then import. A person this site has already met is ' +\n 'updated rather than added twice. Nobody is emailed, and no marketing ' +\n 'consent is recorded — a file is not a checkbox somebody ticked, so an ' +\n 'imported lead can be mailed only if this site already holds a consent ' +\n `for them. Up to ${LEAD_IMPORT_MAX_ROWS.toLocaleString()} rows per file ` +\n '— split a larger one.',\n fields: LEAD_IMPORT_FIELDS,\n fieldLabels: LEAD_IMPORT_FIELD_LABELS,\n requiredField: 'email',\n requiredWarning:\n 'Choose which column holds the email address. It is the one field every ' +\n 'row needs, and it is what tells one lead from another.',\n unusable: (cell) => !normalizeContactEmail(cell),\n unusableNotice: (count, total) =>\n `${count.toLocaleString()} of ${total.toLocaleString()} rows have no ` +\n 'usable email address and will be skipped. You can download them after ' +\n 'the import.',\n guessMapping: guessLeadImportMapping,\n mapRow: (cells, mapping) =>\n mapLeadImportRow(cells, mapping) as LeadImportRawRow & Record<string, unknown>,\n route: LEADS_IMPORT_URL,\n maxRows: LEAD_IMPORT_MAX_ROWS,\n chunkSize: LEAD_IMPORT_CHUNK_SIZE,\n previewRows: LEAD_IMPORT_PREVIEW_ROWS,\n emptyResult: emptyLeadImportResult,\n mergeResults: mergeLeadImportResults,\n skipLabels: LEAD_IMPORT_SKIP_LABELS,\n skippedCsv: leadImportSkippedCsv,\n skippedFileName: 'skipped-leads.csv',\n // The export's own header over no rows, so an export re-imports as is —\n // the columns a file cannot set land on \"Do not import\".\n templateCsv: () => leadsCsv([]),\n templateFileName: 'leads-template.csv',\n}\n\nexport interface LeadImportDrawerProps {\n open: boolean\n onClose: () => void\n /** The site the file is filed under, or `null` at the organization level. */\n hostId: string | null\n /** The org the lead source list is read from (AGL-3298); `null` while it settles. */\n orgId?: string | null\n}\n\nexport function LeadImportDrawer(props: LeadImportDrawerProps) {\n const { open, onClose, hostId, orgId = null } = props\n /*\n * THE ORG'S LEAD SOURCES (AGL-3298). The server refuses a row naming a\n * value outside the list; the notice says so before the file is sent,\n * naming the values it holds that the list does not and the ones it\n * allows, so the operator can fix the file or add the value first.\n */\n const { picklist } = useLeadSourcePicklist(orgId)\n const vocabulary = useMemo(\n () => ({\n ...LEAD_IMPORT_VOCABULARY,\n rowsNotice: (rows: readonly (LeadImportRawRow & Record<string, unknown>)[]) => {\n const unknown = leadImportUnknownLeadSources(rows, picklist)\n if (!unknown.length) return null\n return (\n <Alert severity=\"warning\">\n {`${unknown.length === 1 ? 'A lead source' : `${unknown.length} lead sources`} in this ` +\n `file ${unknown.length === 1 ? 'is' : 'are'} not in your list: ` +\n `${unknown.slice(0, 10).join(', ')}${unknown.length > 10 ? ', …' : ''}. ` +\n 'Those rows will be skipped. ' +\n crmLeadSourceRefusal(picklist) +\n ' Add a value under CRM › Fields › Leads to import it.'}\n </Alert>\n )\n },\n }),\n [picklist],\n )\n return (\n <CsvImportDrawer open={open} onClose={onClose} hostId={hostId} vocabulary={vocabulary} />\n )\n}\nLeadImportDrawer.displayName = 'LeadImportDrawer'\n\n/** The \"Import CSV\" action on the leads list, with the drawer it opens. */\nexport function LeadImportButton(props: { hostId: string | null; orgId?: string | null }) {\n const { hostId, orgId = null } = props\n return (\n <CsvImportButton>\n {(open, onClose) => (\n <LeadImportDrawer open={open} onClose={onClose} hostId={hostId} orgId={orgId} />\n )}\n </CsvImportButton>\n )\n}\nLeadImportButton.displayName = 'LeadImportButton'\n\nexport default LeadImportDrawer\n"],"names":["crmLeadSourceRefusal","normalizeContactEmail","pluginDocsHelp","Alert","useMemo","useLeadSourcePicklist","LEAD_IMPORT_CHUNK_SIZE","LEAD_IMPORT_FIELD_LABELS","LEAD_IMPORT_FIELDS","LEAD_IMPORT_MAX_ROWS","LEAD_IMPORT_PREVIEW_ROWS","LEAD_IMPORT_SKIP_LABELS","emptyLeadImportResult","guessLeadImportMapping","leadImportSkippedCsv","leadImportUnknownLeadSources","mapLeadImportRow","mergeLeadImportResults","leadsCsv","CsvImportButton","CsvImportDrawer","LEADS_IMPORT_URL","LEAD_IMPORT_VOCABULARY","title","collection","help","anchor","sitePickerHelperText","intro","toLocaleString","fields","fieldLabels","requiredField","requiredWarning","unusable","cell","unusableNotice","count","total","guessMapping","mapRow","cells","mapping","route","maxRows","chunkSize","previewRows","emptyResult","mergeResults","skipLabels","skippedCsv","skippedFileName","templateCsv","templateFileName","LeadImportDrawer","props","open","onClose","hostId","orgId","picklist","vocabulary","rowsNotice","rows","unknown","length","severity","slice","join","displayName","LeadImportButton"],"mappings":"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"}
@@ -1,27 +0,0 @@
1
- export interface LeadSourceValuesCardProps {
2
- /** The mounted site, or `null` at the organization level. */
3
- hostId: string | null;
4
- /** The org whose list this is; `null` while it settles. */
5
- orgId: string | null;
6
- /** The site a newly written list records as its definer — the Fields page's own. */
7
- createHostId: string | null;
8
- }
9
- /**
10
- * THE LEAD SOURCE VALUES (AGL-3298) — Salesforce's Lead Source picklist,
11
- * managed where the org's lead fields are.
12
- *
13
- * Every move that touches only the LIST — add, reorder by drag or arrows,
14
- * sort A–Z, activate, deactivate, default — is one client write of the
15
- * whole document, guarded against a cached read like every seeded save on
16
- * the Fields page. The two that change RECORDS — rename, and delete with a
17
- * replacement — go to `crm/lead-source-values`, which rewrites the list and
18
- * every lead and contact holding the old label together; see that route.
19
- *
20
- * An org that has never edited its list reads the starter set, and the
21
- * first move here writes it down as the org's own.
22
- */
23
- export declare function LeadSourceValuesCard(props: LeadSourceValuesCardProps): import("react").JSX.Element;
24
- export declare namespace LeadSourceValuesCard {
25
- var displayName: string;
26
- }
27
- export default LeadSourceValuesCard;
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/lead-source-values-card.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 CRM_COLLECTIONS,\n CRM_LEAD_SOURCE_PICKLIST,\n CRM_LEAD_TEXT_MAX,\n type CrmPicklist,\n type CrmPicklistValue,\n crmPicklistActiveValues,\n newResourceScopeFields,\n ORG_SCOPE_TOKEN,\n} from '@aglyn/aglyn'\nimport {\n mdiArrowDown,\n mdiArrowUp,\n mdiDeleteOutline,\n mdiDragVertical,\n mdiEyeOffOutline,\n mdiEyeOutline,\n mdiPencilOutline,\n mdiStarOutline,\n} from '@aglyn/shared-data-mdi'\nimport { MdiIcon, SrOnly } from '@aglyn/shared-ui-jsx'\nimport RowActionsMenu, {\n type RowActionsMenuItem,\n} from '@aglyn/shared-ui-jsx/components/row-actions-menu.component'\nimport { ScrollTable } from '@aglyn/shared-ui-jsx/components/scroll-table.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport {\n useFirestore,\n useUser,\n writeGuardedBySeed,\n} from '@aglyn/tenant-feature-instance'\nimport {\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n IconButton,\n MenuItem,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material'\nimport { doc, serverTimestamp, setDoc } from 'firebase/firestore'\nimport { useCallback, useState } from 'react'\nimport { useLeadSourcePicklist } from '../hooks/use-lead-source-picklist'\nimport {\n addPicklistValue,\n crmLeadSourceValuesRouteUrl,\n type LeadSourceValuesRequest,\n type LeadSourceValuesResponse,\n movePicklistValue,\n setPicklistDefault,\n setPicklistValueActive,\n sortPicklistValues,\n} from '../model/lead-source-values'\nimport { crmTaskCallScope } from '../model/task-routes'\n\nexport interface LeadSourceValuesCardProps {\n /** The mounted site, or `null` at the organization level. */\n hostId: string | null\n /** The org whose list this is; `null` while it settles. */\n orgId: string | null\n /** The site a newly written list records as its definer — the Fields page's own. */\n createHostId: string | null\n}\n\n/** The add and rename dialog's state: which value, if any, is being renamed. */\ntype NameDialog = { mode: 'add' } | { mode: 'rename'; value: CrmPicklistValue } | null\n\n/**\n * THE LEAD SOURCE VALUES (AGL-3298) — Salesforce's Lead Source picklist,\n * managed where the org's lead fields are.\n *\n * Every move that touches only the LIST — add, reorder by drag or arrows,\n * sort A–Z, activate, deactivate, default — is one client write of the\n * whole document, guarded against a cached read like every seeded save on\n * the Fields page. The two that change RECORDS — rename, and delete with a\n * replacement — go to `crm/lead-source-values`, which rewrites the list and\n * every lead and contact holding the old label together; see that route.\n *\n * An org that has never edited its list reads the starter set, and the\n * first move here writes it down as the org's own.\n */\nexport function LeadSourceValuesCard(props: LeadSourceValuesCardProps) {\n const { hostId, orgId, createHostId } = props\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const { picklist, stored, ready, fromCache } = useLeadSourcePicklist(orgId)\n const [busy, setBusy] = useState(false)\n const [nameDialog, setNameDialog] = useState<NameDialog>(null)\n const [draftName, setDraftName] = useState('')\n const [nameError, setNameError] = useState('')\n const [deleting, setDeleting] = useState<CrmPicklistValue | null>(null)\n const [replaceWith, setReplaceWith] = useState('')\n const [dragFrom, setDragFrom] = useState<number | null>(null)\n\n /** Write the whole list — the list-only moves above. */\n const save = useCallback(\n async (next: CrmPicklist, done: string) => {\n if (!orgId || busy) return\n setBusy(true)\n try {\n const verdict = await writeGuardedBySeed({ subject: 'lead source list', fromCache }, () =>\n setDoc(\n doc(firestore, 'orgs', orgId, CRM_COLLECTIONS.picklists, CRM_LEAD_SOURCE_PICKLIST),\n {\n values: next.values,\n defaultValueId: next.defaultValueId,\n updatedAt: serverTimestamp(),\n // The org-wide stamp the rules require of a new CRM document,\n // the same one a field definition carries.\n ...(stored\n ? {}\n : {\n hostId: createHostId,\n createdAt: serverTimestamp(),\n ...newResourceScopeFields([ORG_SCOPE_TOKEN]),\n }),\n },\n { merge: true },\n ),\n )\n if (!verdict.ok) {\n enqueueSnackbar(verdict.message, { variant: 'warning', persist: false })\n return\n }\n enqueueSnackbar(done, { variant: 'success', persist: false })\n } catch (error) {\n console.error(error)\n enqueueSnackbar('The lead sources could not be saved.', { variant: 'error', allowDuplicate: true })\n } finally {\n setBusy(false)\n }\n },\n [orgId, busy, fromCache, firestore, stored, createHostId, enqueueSnackbar],\n )\n\n /** A rename or a delete — the moves that change records too. */\n const post = useCallback(\n async (request: LeadSourceValuesRequest): Promise<LeadSourceValuesResponse | null> => {\n const scope = crmTaskCallScope(hostId, orgId)\n if (!scope || busy) return null\n setBusy(true)\n try {\n const response = await authorizedFetch(user, crmLeadSourceValuesRouteUrl(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ ...request, ...scope }),\n })\n const payload = (await response.json().catch(() => ({}))) as { error?: string }\n if (!response.ok) {\n enqueueSnackbar(payload.error || 'The lead sources could not be saved.', {\n variant: 'warning',\n persist: false,\n })\n return null\n }\n return payload as LeadSourceValuesResponse\n } catch (error) {\n console.error(error)\n enqueueSnackbar('The lead sources could not be saved.', { variant: 'error', allowDuplicate: true })\n return null\n } finally {\n setBusy(false)\n }\n },\n [hostId, orgId, busy, user, enqueueSnackbar],\n )\n\n const moved = (result: LeadSourceValuesResponse) => {\n const records = result.leads + result.contacts\n return records\n ? ` — ${result.leads.toLocaleString()} lead${result.leads === 1 ? '' : 's'} and ` +\n `${result.contacts.toLocaleString()} contact${result.contacts === 1 ? '' : 's'} updated`\n : ''\n }\n\n const openAdd = () => {\n setDraftName('')\n setNameError('')\n setNameDialog({ mode: 'add' })\n }\n const openRename = (value: CrmPicklistValue) => {\n setDraftName(value.label)\n setNameError('')\n setNameDialog({ mode: 'rename', value })\n }\n\n const submitName = async () => {\n if (!nameDialog) return\n if (nameDialog.mode === 'add') {\n const move = addPicklistValue(picklist, draftName)\n if (move.ok === false) return void setNameError(move.error)\n setNameDialog(null)\n await save(move.picklist, `“${draftName.trim()}” added`)\n return\n }\n const result = await post({ action: 'rename', valueId: nameDialog.value.id, label: draftName })\n if (!result) return\n setNameDialog(null)\n enqueueSnackbar(`Renamed${moved(result)}`, { variant: 'success', persist: false })\n }\n\n const openDelete = (value: CrmPicklistValue) => {\n setReplaceWith('')\n setDeleting(value)\n }\n const submitDelete = async () => {\n if (!deleting) return\n const result = await post({\n action: 'delete',\n valueId: deleting.id,\n replaceWith: replaceWith || null,\n })\n if (!result) return\n setDeleting(null)\n enqueueSnackbar(`“${deleting.label}” deleted${moved(result)}`, {\n variant: 'success',\n persist: false,\n })\n }\n\n const move = (from: number, to: number) =>\n void save(movePicklistValue(picklist, from, to), 'Order saved')\n\n const rowActions = (value: CrmPicklistValue): RowActionsMenuItem[] => {\n const isDefault = picklist.defaultValueId === value.id\n return [\n {\n key: 'rename',\n label: 'Rename',\n icon: <MdiIcon path={mdiPencilOutline.path} size={0.8} />,\n disabled: busy,\n onClick: () => openRename(value),\n },\n {\n key: 'default',\n label: isDefault ? 'Clear default' : 'Make default',\n icon: <MdiIcon path={mdiStarOutline.path} size={0.8} />,\n disabled: busy || (!isDefault && !value.active),\n disabledReason: !value.active ? 'An inactive value cannot be the default' : undefined,\n onClick: () =>\n void save(\n setPicklistDefault(picklist, isDefault ? null : value.id),\n isDefault ? 'Default cleared' : `New leads start as “${value.label}”`,\n ),\n },\n {\n key: 'active',\n label: value.active ? 'Deactivate' : 'Activate',\n icon: (\n <MdiIcon path={value.active ? mdiEyeOffOutline.path : mdiEyeOutline.path} size={0.8} />\n ),\n disabled: busy,\n onClick: () =>\n void save(\n setPicklistValueActive(picklist, value.id, !value.active),\n value.active ? `“${value.label}” deactivated` : `“${value.label}” activated`,\n ),\n },\n {\n key: 'delete',\n label: 'Delete…',\n icon: <MdiIcon path={mdiDeleteOutline.path} size={0.8} />,\n destructive: true,\n disabled: busy,\n onClick: () => openDelete(value),\n },\n ]\n }\n\n const replacements = crmPicklistActiveValues(picklist).filter(\n (value) => value.id !== deleting?.id,\n )\n\n return (\n <Stack spacing={1.5}>\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n spacing={1}\n sx={{ justifyContent: 'space-between', alignItems: { sm: 'center' } }}\n >\n <Stack spacing={0.25}>\n <Typography variant=\"subtitle1\">{'Lead source values'}</Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'The choices in every lead’s Lead source select, in this order. ' +\n 'An import or an API write naming anything else is refused. ' +\n 'A deactivated value stays on the records that hold it.'}\n </Typography>\n </Stack>\n {orgId ? (\n <Stack direction=\"row\" spacing={1} sx={{ flexShrink: 0 }}>\n <Button\n size=\"small\"\n disabled={busy || picklist.values.length < 2}\n onClick={() => void save(sortPicklistValues(picklist), 'Sorted A–Z')}\n >\n {'Sort A–Z'}\n </Button>\n <Button size=\"small\" variant=\"outlined\" disabled={busy} onClick={openAdd}>\n {'Add value'}\n </Button>\n </Stack>\n ) : null}\n </Stack>\n {!ready ? null : (\n <ScrollTable size=\"small\" aria-label=\"Lead source values\">\n <TableHead>\n <TableRow>\n <TableCell sx={{ width: 120 }}>{'Order'}</TableCell>\n <TableCell>{'Value'}</TableCell>\n <TableCell>{'Status'}</TableCell>\n <TableCell align=\"right\" />\n </TableRow>\n </TableHead>\n <TableBody>\n {picklist.values.length === 0 ? (\n <TableRow>\n <TableCell colSpan={4}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No values yet. Add one, and every lead can be given it.'}\n </Typography>\n </TableCell>\n </TableRow>\n ) : null}\n {picklist.values.map((value, index) => (\n <TableRow\n key={value.id}\n hover\n // Native drag and drop for a pointer; the arrows beside the\n // handle are the same move for a keyboard or a touch screen.\n draggable={!busy}\n onDragStart={(event) => {\n setDragFrom(index)\n event.dataTransfer.effectAllowed = 'move'\n }}\n onDragOver={(event) => {\n if (dragFrom === null) return\n event.preventDefault()\n event.dataTransfer.dropEffect = 'move'\n }}\n onDrop={(event) => {\n event.preventDefault()\n if (dragFrom !== null && dragFrom !== index) move(dragFrom, index)\n setDragFrom(null)\n }}\n onDragEnd={() => setDragFrom(null)}\n sx={{\n ...(value.active ? {} : { opacity: 0.6 }),\n ...(dragFrom === index ? { outline: 1, outlineColor: 'primary.main' } : {}),\n }}\n >\n <TableCell>\n <Stack direction=\"row\" spacing={0} sx={{ alignItems: 'center' }}>\n <MdiIcon\n path={mdiDragVertical.path}\n size={0.8}\n style={{ cursor: busy ? 'default' : 'grab' }}\n aria-hidden\n />\n <IconButton\n size=\"small\"\n disabled={index === 0 || busy}\n onClick={() => move(index, index - 1)}\n >\n <MdiIcon path={mdiArrowUp.path} size={0.7} />\n <SrOnly>{`Move ${value.label} up`}</SrOnly>\n </IconButton>\n <IconButton\n size=\"small\"\n disabled={index === picklist.values.length - 1 || busy}\n onClick={() => move(index, index + 1)}\n >\n <MdiIcon path={mdiArrowDown.path} size={0.7} />\n <SrOnly>{`Move ${value.label} down`}</SrOnly>\n </IconButton>\n </Stack>\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\">{value.label}</Typography>\n </TableCell>\n <TableCell>\n <Stack direction=\"row\" spacing={1} sx={{ flexWrap: 'wrap', alignItems: 'center' }}>\n {value.active ? null : (\n <Chip size=\"small\" variant=\"outlined\" color=\"warning\" label=\"Inactive\" />\n )}\n {picklist.defaultValueId === value.id ? (\n <Chip size=\"small\" variant=\"outlined\" color=\"primary\" label=\"Default\" />\n ) : null}\n {value.active && picklist.defaultValueId !== value.id ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Active'}\n </Typography>\n ) : null}\n </Stack>\n </TableCell>\n <TableCell align=\"right\" sx={{ width: 56 }}>\n <RowActionsMenu label={value.label} items={rowActions(value)} />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </ScrollTable>\n )}\n {ready && !stored ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'This is the starter list. Your first change here makes it your organization’s own.'}\n </Typography>\n ) : null}\n\n <Dialog open={nameDialog !== null} onClose={() => setNameDialog(null)} fullWidth maxWidth=\"xs\">\n <DialogTitle>\n {nameDialog?.mode === 'rename' ? `Rename “${nameDialog.value.label}”` : 'Add a lead source'}\n </DialogTitle>\n <DialogContent>\n <Stack spacing={1.5} sx={{ pt: 1 }}>\n {nameDialog?.mode === 'rename' ? (\n <DialogContentText variant=\"body2\">\n {'Every lead and contact holding this value is updated to the new name.'}\n </DialogContentText>\n ) : null}\n <TextField\n size=\"small\"\n label=\"Value\"\n value={draftName}\n onChange={(event) => {\n setDraftName(event.target.value)\n setNameError('')\n }}\n onKeyDown={(event) => {\n if (event.key === 'Enter') void submitName()\n }}\n error={Boolean(nameError)}\n helperText={nameError || ' '}\n slotProps={{ htmlInput: { maxLength: CRM_LEAD_TEXT_MAX } }}\n autoFocus\n fullWidth\n />\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setNameDialog(null)}>{'Cancel'}</Button>\n <Button\n variant=\"contained\"\n disabled={busy || !draftName.trim()}\n onClick={() => void submitName()}\n >\n {nameDialog?.mode === 'rename' ? 'Rename' : 'Add'}\n </Button>\n </DialogActions>\n </Dialog>\n\n <Dialog open={deleting !== null} onClose={() => setDeleting(null)} fullWidth maxWidth=\"xs\">\n <DialogTitle>{`Delete “${deleting?.label ?? ''}”?`}</DialogTitle>\n <DialogContent>\n <Stack spacing={1.5} sx={{ pt: 1 }}>\n <DialogContentText variant=\"body2\">\n {'The value leaves the list for good. Leads and contacts that hold it ' +\n 'are moved to the value you pick here, or cleared. To keep it on ' +\n 'those records instead, deactivate it.'}\n </DialogContentText>\n <TextField\n select\n size=\"small\"\n label=\"Replace it on existing records with\"\n value={replaceWith}\n onChange={(event) => setReplaceWith(String(event.target.value))}\n fullWidth\n slotProps={{ select: { displayEmpty: true }, inputLabel: { shrink: true } }}\n >\n <MenuItem value=\"\">{'None — clear it'}</MenuItem>\n {replacements.map((value) => (\n <MenuItem key={value.id} value={value.label}>\n {value.label}\n </MenuItem>\n ))}\n </TextField>\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setDeleting(null)}>{'Cancel'}</Button>\n <Button\n variant=\"contained\"\n color=\"error\"\n disabled={busy}\n onClick={() => void submitDelete()}\n >\n {'Delete value'}\n </Button>\n </DialogActions>\n </Dialog>\n </Stack>\n )\n}\nLeadSourceValuesCard.displayName = 'LeadSourceValuesCard'\n\nexport default LeadSourceValuesCard\n"],"names":["CRM_COLLECTIONS","CRM_LEAD_SOURCE_PICKLIST","CRM_LEAD_TEXT_MAX","crmPicklistActiveValues","newResourceScopeFields","ORG_SCOPE_TOKEN","mdiArrowDown","mdiArrowUp","mdiDeleteOutline","mdiDragVertical","mdiEyeOffOutline","mdiEyeOutline","mdiPencilOutline","mdiStarOutline","MdiIcon","SrOnly","RowActionsMenu","ScrollTable","useSnackbar","authorizedFetch","useFirestore","useUser","writeGuardedBySeed","Button","Chip","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","IconButton","MenuItem","Stack","TableBody","TableCell","TableHead","TableRow","TextField","Typography","doc","serverTimestamp","setDoc","useCallback","useState","useLeadSourcePicklist","addPicklistValue","crmLeadSourceValuesRouteUrl","movePicklistValue","setPicklistDefault","setPicklistValueActive","sortPicklistValues","crmTaskCallScope","LeadSourceValuesCard","props","hostId","orgId","createHostId","firestore","data","user","enqueueSnackbar","picklist","stored","ready","fromCache","busy","setBusy","nameDialog","setNameDialog","draftName","setDraftName","nameError","setNameError","deleting","setDeleting","replaceWith","setReplaceWith","dragFrom","setDragFrom","save","next","done","verdict","subject","picklists","values","defaultValueId","updatedAt","createdAt","merge","ok","message","variant","persist","error","console","allowDuplicate","post","request","scope","response","method","headers","body","JSON","stringify","payload","json","catch","moved","result","records","leads","contacts","toLocaleString","openAdd","mode","openRename","value","label","submitName","move","trim","action","valueId","id","openDelete","submitDelete","from","to","rowActions","isDefault","key","icon","path","size","disabled","onClick","active","disabledReason","undefined","destructive","replacements","filter","spacing","direction","xs","sm","sx","justifyContent","alignItems","color","flexShrink","length","aria-label","width","align","colSpan","map","index","hover","draggable","onDragStart","event","dataTransfer","effectAllowed","onDragOver","preventDefault","dropEffect","onDrop","onDragEnd","opacity","outline","outlineColor","style","cursor","aria-hidden","flexWrap","items","open","onClose","fullWidth","maxWidth","pt","onChange","target","onKeyDown","Boolean","helperText","slotProps","htmlInput","maxLength","autoFocus","select","String","displayEmpty","inputLabel","shrink","displayName"],"mappings":"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"}
@@ -1,24 +0,0 @@
1
- import { type TaskImportField, type TaskImportRawRow, type TaskImportSkippedRow } from '../model/crm-task-import';
2
- import { type CsvImportVocabulary } from './csv-import-drawer';
3
- /** The browser-side address of the route one chunk is posted to. */
4
- export declare const TASKS_IMPORT_URL = "/api/crm/tasks-import";
5
- /** Built once: nothing in it depends on a render. */
6
- export declare const TASK_IMPORT_VOCABULARY: CsvImportVocabulary<TaskImportField, TaskImportRawRow & Record<string, unknown>, TaskImportSkippedRow>;
7
- export interface TaskImportDrawerProps {
8
- open: boolean;
9
- onClose: () => void;
10
- /** The site the file is filed from, or `null` at the organization level. */
11
- hostId: string | null;
12
- }
13
- export declare function TaskImportDrawer(props: TaskImportDrawerProps): import("react").JSX.Element;
14
- export declare namespace TaskImportDrawer {
15
- var displayName: string;
16
- }
17
- /** The "Import CSV" action on the tasks list, with the drawer it opens. */
18
- export declare function TaskImportButton(props: {
19
- hostId: string | null;
20
- }): import("react").JSX.Element;
21
- export declare namespace TaskImportButton {
22
- var displayName: string;
23
- }
24
- export default TaskImportDrawer;