@aglyn/plugins-crm 1.0.0-beta.221 → 1.0.0-beta.223
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/package.json +13 -13
- package/src/lib/components/activity-list.js +12 -5
- package/src/lib/components/activity-list.js.map +1 -1
- package/src/lib/components/companies-bulk-bar.d.ts +1 -4
- package/src/lib/components/companies-bulk-bar.js +7 -20
- package/src/lib/components/companies-bulk-bar.js.map +1 -1
- package/src/lib/components/companies-section.d.ts +3 -3
- package/src/lib/components/companies-section.js +149 -46
- package/src/lib/components/companies-section.js.map +1 -1
- package/src/lib/components/company-edit-drawer.js +281 -20
- package/src/lib/components/company-edit-drawer.js.map +1 -1
- package/src/lib/components/company-properties-card.js +99 -8
- package/src/lib/components/company-properties-card.js.map +1 -1
- package/src/lib/components/contact-detail-page.js +3 -1
- package/src/lib/components/contact-detail-page.js.map +1 -1
- package/src/lib/components/contact-merge-dialog.js +33 -10
- package/src/lib/components/contact-merge-dialog.js.map +1 -1
- package/src/lib/components/contact-properties-card.d.ts +0 -69
- package/src/lib/components/contact-properties-card.js +350 -60
- package/src/lib/components/contact-properties-card.js.map +1 -1
- package/src/lib/components/contact-reports-to-field.d.ts +46 -0
- package/src/lib/components/contact-reports-to-field.js +67 -0
- package/src/lib/components/contact-reports-to-field.js.map +1 -0
- package/src/lib/components/contacts-bulk-bar.d.ts +1 -8
- package/src/lib/components/contacts-bulk-bar.js +7 -19
- package/src/lib/components/contacts-bulk-bar.js.map +1 -1
- package/src/lib/components/contacts-section.js +46 -33
- package/src/lib/components/contacts-section.js.map +1 -1
- package/src/lib/components/crm-call-actions.d.ts +10 -0
- package/src/lib/components/crm-call-actions.js +26 -9
- package/src/lib/components/crm-call-actions.js.map +1 -1
- package/src/lib/components/crm-next-activity-column.js +1 -1
- package/src/lib/components/crm-next-activity-column.js.map +1 -1
- package/src/lib/components/crm-record-picker.d.ts +15 -0
- package/src/lib/components/crm-record-picker.js +16 -10
- package/src/lib/components/crm-record-picker.js.map +1 -1
- package/src/lib/components/crm-transfer-buttons.d.ts +54 -0
- package/src/lib/components/crm-transfer-buttons.js +167 -0
- package/src/lib/components/crm-transfer-buttons.js.map +1 -0
- package/src/lib/components/deal-contact-roles-card.d.ts +46 -0
- package/src/lib/components/deal-contact-roles-card.js +368 -0
- package/src/lib/components/deal-contact-roles-card.js.map +1 -0
- package/src/lib/components/deal-detail-page.d.ts +3 -2
- package/src/lib/components/deal-detail-page.js +25 -6
- package/src/lib/components/deal-detail-page.js.map +1 -1
- package/src/lib/components/deal-edit-drawer.d.ts +10 -0
- package/src/lib/components/deal-edit-drawer.js +219 -10
- package/src/lib/components/deal-edit-drawer.js.map +1 -1
- package/src/lib/components/deal-properties-card.d.ts +7 -0
- package/src/lib/components/deal-properties-card.js +34 -3
- package/src/lib/components/deal-properties-card.js.map +1 -1
- package/src/lib/components/deal-stage-card.d.ts +4 -0
- package/src/lib/components/deal-stage-card.js +10 -2
- package/src/lib/components/deal-stage-card.js.map +1 -1
- package/src/lib/components/deals-bulk-bar.d.ts +0 -3
- package/src/lib/components/deals-bulk-bar.js +7 -20
- package/src/lib/components/deals-bulk-bar.js.map +1 -1
- package/src/lib/components/deals-section.d.ts +3 -3
- package/src/lib/components/deals-section.js +123 -63
- package/src/lib/components/deals-section.js.map +1 -1
- package/src/lib/components/fields-section.js +31 -17
- package/src/lib/components/fields-section.js.map +1 -1
- package/src/lib/components/lead-convert-dialog.d.ts +4 -0
- package/src/lib/components/lead-convert-dialog.js +23 -1
- package/src/lib/components/lead-convert-dialog.js.map +1 -1
- package/src/lib/components/lead-detail-page.js +8 -2
- package/src/lib/components/lead-detail-page.js.map +1 -1
- package/src/lib/components/lead-profile-fields.d.ts +71 -0
- package/src/lib/components/lead-profile-fields.js +386 -0
- package/src/lib/components/lead-profile-fields.js.map +1 -0
- package/src/lib/components/lead-properties-card.d.ts +2 -1
- package/src/lib/components/lead-properties-card.js +85 -176
- package/src/lib/components/lead-properties-card.js.map +1 -1
- package/src/lib/components/lead-source-select.d.ts +4 -23
- package/src/lib/components/lead-source-select.js +9 -73
- package/src/lib/components/lead-source-select.js.map +1 -1
- package/src/lib/components/lead-status-chip.d.ts +9 -3
- package/src/lib/components/lead-status-chip.js +8 -4
- package/src/lib/components/lead-status-chip.js.map +1 -1
- package/src/lib/components/lead-status-options.d.ts +20 -0
- package/src/lib/components/lead-status-options.js +51 -0
- package/src/lib/components/lead-status-options.js.map +1 -0
- package/src/lib/components/lead-unqualify-dialog.d.ts +5 -0
- package/src/lib/components/lead-unqualify-dialog.js +50 -18
- package/src/lib/components/lead-unqualify-dialog.js.map +1 -1
- package/src/lib/components/leads-bulk-bar.d.ts +0 -3
- package/src/lib/components/leads-bulk-bar.js +29 -29
- package/src/lib/components/leads-bulk-bar.js.map +1 -1
- package/src/lib/components/leads-section.js +120 -68
- package/src/lib/components/leads-section.js.map +1 -1
- package/src/lib/components/linked-deals-card.d.ts +4 -0
- package/src/lib/components/linked-deals-card.js +47 -3
- package/src/lib/components/linked-deals-card.js.map +1 -1
- package/src/lib/components/log-activity-dialog.js +43 -3
- package/src/lib/components/log-activity-dialog.js.map +1 -1
- package/src/lib/components/new-contact-drawer.d.ts +8 -0
- package/src/lib/components/new-contact-drawer.js +108 -6
- package/src/lib/components/new-contact-drawer.js.map +1 -1
- package/src/lib/components/new-lead-drawer.d.ts +9 -2
- package/src/lib/components/new-lead-drawer.js +88 -121
- package/src/lib/components/new-lead-drawer.js.map +1 -1
- package/src/lib/components/picklist-select.d.ts +36 -0
- package/src/lib/components/picklist-select.js +114 -0
- package/src/lib/components/picklist-select.js.map +1 -0
- package/src/lib/components/picklist-values-card.d.ts +34 -0
- package/src/lib/components/{lead-source-values-card.js → picklist-values-card.js} +241 -58
- package/src/lib/components/picklist-values-card.js.map +1 -0
- package/src/lib/components/pipeline-stages-dialog.d.ts +7 -0
- package/src/lib/components/pipeline-stages-dialog.js +26 -4
- package/src/lib/components/pipeline-stages-dialog.js.map +1 -1
- package/src/lib/components/pipelines-dialog.js +15 -6
- package/src/lib/components/pipelines-dialog.js.map +1 -1
- package/src/lib/components/recent-activity-feed.js +20 -5
- package/src/lib/components/recent-activity-feed.js.map +1 -1
- package/src/lib/components/recipes-card.js +4 -2
- package/src/lib/components/recipes-card.js.map +1 -1
- package/src/lib/components/record-tasks-card.js +15 -8
- package/src/lib/components/record-tasks-card.js.map +1 -1
- package/src/lib/components/reports/forecast-card.d.ts +6 -0
- package/src/lib/components/reports/forecast-card.js +101 -3
- package/src/lib/components/reports/forecast-card.js.map +1 -1
- package/src/lib/components/reports/lead-funnel-card.d.ts +12 -0
- package/src/lib/components/reports/lead-funnel-card.js +9 -5
- package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
- package/src/lib/components/reports/lead-source-card.d.ts +23 -0
- package/src/lib/components/reports/lead-source-card.js +318 -0
- package/src/lib/components/reports/lead-source-card.js.map +1 -0
- package/src/lib/components/reports/pipeline-card.js +2 -1
- package/src/lib/components/reports/pipeline-card.js.map +1 -1
- package/src/lib/components/reports/report-export.js +1 -1
- package/src/lib/components/reports/report-export.js.map +1 -1
- package/src/lib/components/reports-section.js +8 -0
- package/src/lib/components/reports-section.js.map +1 -1
- package/src/lib/components/sharing-rule-drawer.d.ts +5 -0
- package/src/lib/components/sharing-rule-drawer.js +108 -19
- package/src/lib/components/sharing-rule-drawer.js.map +1 -1
- package/src/lib/components/sharing-rules-card.js +11 -3
- package/src/lib/components/sharing-rules-card.js.map +1 -1
- package/src/lib/components/task-cells.d.ts +9 -1
- package/src/lib/components/task-cells.js +9 -4
- package/src/lib/components/task-cells.js.map +1 -1
- package/src/lib/components/task-edit-drawer.js +111 -43
- package/src/lib/components/task-edit-drawer.js.map +1 -1
- package/src/lib/components/tasks-bulk-bar.d.ts +0 -3
- package/src/lib/components/tasks-bulk-bar.js +7 -20
- package/src/lib/components/tasks-bulk-bar.js.map +1 -1
- package/src/lib/components/tasks-calendar.d.ts +3 -0
- package/src/lib/components/tasks-calendar.js +8 -1
- package/src/lib/components/tasks-calendar.js.map +1 -1
- package/src/lib/components/tasks-section.d.ts +3 -3
- package/src/lib/components/tasks-section.js +58 -43
- package/src/lib/components/tasks-section.js.map +1 -1
- package/src/lib/constants/api-routes.d.ts +2 -9
- package/src/lib/constants/api-routes.js +1 -7
- package/src/lib/constants/api-routes.js.map +1 -1
- package/src/lib/constants/bundle-common.d.ts +6 -0
- package/src/lib/constants/bundle-common.js +11 -0
- package/src/lib/constants/bundle-common.js.map +1 -1
- package/src/lib/constants/company-filters.d.ts +14 -0
- package/src/lib/constants/company-filters.js +51 -1
- package/src/lib/constants/company-filters.js.map +1 -1
- package/src/lib/constants/contact-filters.d.ts +2 -0
- package/src/lib/constants/contact-filters.js +18 -1
- package/src/lib/constants/contact-filters.js.map +1 -1
- package/src/lib/constants/deal-filters.d.ts +22 -1
- package/src/lib/constants/deal-filters.js +67 -4
- package/src/lib/constants/deal-filters.js.map +1 -1
- package/src/lib/declarations.console-server.d.ts +3 -0
- package/src/lib/declarations.console-server.js +35 -0
- package/src/lib/declarations.console-server.js.map +1 -1
- package/src/lib/declarations.d.ts +26 -0
- package/src/lib/declarations.js +35 -0
- package/src/lib/declarations.js.map +1 -0
- package/src/lib/declarations.server.d.ts +11 -0
- package/src/lib/declarations.server.js +97 -1
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/hooks/use-company-picklists.d.ts +15 -0
- package/src/lib/hooks/use-company-picklists.js +55 -0
- package/src/lib/hooks/use-company-picklists.js.map +1 -0
- package/src/lib/hooks/use-crm-picklist.d.ts +25 -0
- package/src/lib/hooks/use-crm-picklist.js +53 -0
- package/src/lib/hooks/use-crm-picklist.js.map +1 -0
- package/src/lib/hooks/use-crm-record-names.d.ts +16 -0
- package/src/lib/hooks/use-crm-record-names.js +45 -19
- package/src/lib/hooks/use-crm-record-names.js.map +1 -1
- package/src/lib/hooks/use-crm-task-picklists.d.ts +11 -0
- package/src/lib/hooks/use-crm-task-picklists.js +45 -0
- package/src/lib/hooks/use-crm-task-picklists.js.map +1 -0
- package/src/lib/hooks/use-deals.d.ts +14 -0
- package/src/lib/hooks/use-deals.js +29 -0
- package/src/lib/hooks/use-deals.js.map +1 -1
- package/src/lib/hooks/use-lead-picklists.d.ts +14 -0
- package/src/lib/hooks/use-lead-picklists.js +46 -0
- package/src/lib/hooks/use-lead-picklists.js.map +1 -0
- package/src/lib/hooks/use-lead-source-picklist.d.ts +5 -19
- package/src/lib/hooks/use-lead-source-picklist.js +12 -22
- package/src/lib/hooks/use-lead-source-picklist.js.map +1 -1
- package/src/lib/hooks/use-lead-status-picklist.d.ts +9 -0
- package/src/lib/hooks/use-lead-status-picklist.js +40 -0
- package/src/lib/hooks/use-lead-status-picklist.js.map +1 -0
- package/src/lib/model/companies.d.ts +32 -3
- package/src/lib/model/companies.js +133 -16
- package/src/lib/model/companies.js.map +1 -1
- package/src/lib/model/contact-merge.d.ts +27 -3
- package/src/lib/model/contact-merge.js +81 -7
- package/src/lib/model/contact-merge.js.map +1 -1
- package/src/lib/model/contact-record.d.ts +17 -0
- package/src/lib/model/contact-record.js +17 -2
- package/src/lib/model/contact-record.js.map +1 -1
- package/src/lib/model/contact-update.d.ts +31 -2
- package/src/lib/model/contact-update.js +14 -0
- package/src/lib/model/contact-update.js.map +1 -1
- package/src/lib/model/crm-list-query.d.ts +5 -0
- package/src/lib/model/crm-list-query.js +8 -0
- package/src/lib/model/crm-list-query.js.map +1 -1
- package/src/lib/model/crm-next-activity.d.ts +107 -0
- package/src/lib/model/crm-next-activity.js +140 -0
- package/src/lib/model/crm-next-activity.js.map +1 -0
- package/src/lib/model/crm-recipes.d.ts +40 -0
- package/src/lib/model/crm-recipes.js +259 -0
- package/src/lib/model/crm-recipes.js.map +1 -0
- package/src/lib/model/crm-record-counts.d.ts +36 -0
- package/src/lib/model/crm-record-counts.js +54 -0
- package/src/lib/model/crm-record-counts.js.map +1 -0
- package/src/lib/model/crm-record-lists.d.ts +23 -0
- package/src/lib/model/crm-record-lists.js +161 -0
- package/src/lib/model/crm-record-lists.js.map +1 -0
- package/src/lib/model/crm-reports.d.ts +73 -3
- package/src/lib/model/crm-reports.js +120 -1
- package/src/lib/model/crm-reports.js.map +1 -1
- package/src/lib/model/crm-sharing.d.ts +21 -3
- package/src/lib/model/crm-sharing.js +27 -6
- package/src/lib/model/crm-sharing.js.map +1 -1
- package/src/lib/model/crm-task-reminders.d.ts +152 -0
- package/src/lib/model/crm-task-reminders.js +161 -0
- package/src/lib/model/crm-task-reminders.js.map +1 -0
- package/src/lib/model/deal-board-model.d.ts +8 -2
- package/src/lib/model/deal-board-model.js +15 -2
- package/src/lib/model/deal-board-model.js.map +1 -1
- package/src/lib/model/deal-contact-roles.d.ts +45 -0
- package/src/lib/model/deal-contact-roles.js +73 -0
- package/src/lib/model/deal-contact-roles.js.map +1 -0
- package/src/lib/model/deal-form-model.d.ts +56 -0
- package/src/lib/model/deal-form-model.js +79 -7
- package/src/lib/model/deal-form-model.js.map +1 -1
- package/src/lib/model/download-text-file.d.ts +23 -0
- package/src/lib/model/download-text-file.js +34 -0
- package/src/lib/model/download-text-file.js.map +1 -0
- package/src/lib/model/lead-filters.d.ts +36 -2
- package/src/lib/model/lead-filters.js +123 -2
- package/src/lib/model/lead-filters.js.map +1 -1
- package/src/lib/model/lead-source-direction.d.ts +38 -0
- package/src/lib/model/lead-source-direction.js +52 -0
- package/src/lib/model/lead-source-direction.js.map +1 -0
- package/src/lib/model/next-activity.d.ts +1 -1
- package/src/lib/model/next-activity.js.map +1 -1
- package/src/lib/model/picklist-values.d.ts +119 -0
- package/src/lib/model/picklist-values.js +256 -0
- package/src/lib/model/picklist-values.js.map +1 -0
- package/src/lib/model/record-facts-disclosed.d.ts +81 -0
- package/src/lib/model/record-facts-disclosed.js +281 -0
- package/src/lib/model/record-facts-disclosed.js.map +1 -0
- package/src/lib/model/record-facts.d.ts +215 -34
- package/src/lib/model/record-facts.js +307 -128
- package/src/lib/model/record-facts.js.map +1 -1
- package/src/lib/model/task-picklists.d.ts +52 -0
- package/src/lib/model/task-picklists.js +83 -0
- package/src/lib/model/task-picklists.js.map +1 -0
- package/src/lib/model/task-routes.d.ts +13 -0
- package/src/lib/model/task-routes.js +23 -4
- package/src/lib/model/task-routes.js.map +1 -1
- package/src/lib/plan-entitlements.js +6 -4
- package/src/lib/plan-entitlements.js.map +1 -1
- package/src/lib/plugin.js +17 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/api-v1/contacts.js +220 -14
- package/src/lib/server/api-v1/contacts.js.map +1 -1
- package/src/lib/server/api-v1/crm-activities.js +14 -1
- package/src/lib/server/api-v1/crm-activities.js.map +1 -1
- package/src/lib/server/api-v1/crm-companies.js +123 -14
- package/src/lib/server/api-v1/crm-companies.js.map +1 -1
- package/src/lib/server/api-v1/crm-deals.js +291 -26
- package/src/lib/server/api-v1/crm-deals.js.map +1 -1
- package/src/lib/server/api-v1/crm-leads.js +144 -38
- package/src/lib/server/api-v1/crm-leads.js.map +1 -1
- package/src/lib/server/api-v1/crm-pipelines.d.ts +6 -0
- package/src/lib/server/api-v1/crm-pipelines.js +8 -2
- package/src/lib/server/api-v1/crm-pipelines.js.map +1 -1
- package/src/lib/server/api-v1/crm-tasks.js +78 -34
- package/src/lib/server/api-v1/crm-tasks.js.map +1 -1
- package/src/lib/server/api-v1/openapi.d.ts +0 -11
- package/src/lib/server/api-v1/openapi.js +171 -16
- package/src/lib/server/api-v1/openapi.js.map +1 -1
- package/src/lib/server/assign-contact-owner.d.ts +188 -0
- package/src/lib/server/assign-contact-owner.js +446 -0
- package/src/lib/server/assign-contact-owner.js.map +1 -0
- package/src/lib/server/associate-company-by-domain.d.ts +70 -0
- package/src/lib/server/associate-company-by-domain.js +153 -0
- package/src/lib/server/associate-company-by-domain.js.map +1 -0
- package/src/lib/server/automation-steps.d.ts +140 -0
- package/src/lib/server/automation-steps.js +669 -0
- package/src/lib/server/automation-steps.js.map +1 -0
- package/src/lib/server/capture-contact.d.ts +17 -0
- package/src/lib/server/capture-contact.js +95 -26
- package/src/lib/server/capture-contact.js.map +1 -1
- package/src/lib/server/capture-host-contact.d.ts +104 -0
- package/src/lib/server/capture-host-contact.js +151 -0
- package/src/lib/server/capture-host-contact.js.map +1 -0
- package/src/lib/server/company-children.d.ts +25 -0
- package/src/lib/server/company-children.js +42 -0
- package/src/lib/server/company-children.js.map +1 -0
- package/src/lib/server/company-delete.d.ts +18 -0
- package/src/lib/server/company-delete.js +44 -21
- package/src/lib/server/company-delete.js.map +1 -1
- package/src/lib/server/contact-email-history.js +21 -19
- package/src/lib/server/contact-email-history.js.map +1 -1
- package/src/lib/server/contact-remove.js +27 -2
- package/src/lib/server/contact-remove.js.map +1 -1
- package/src/lib/server/contact-reports-to.d.ts +61 -0
- package/src/lib/server/contact-reports-to.js +114 -0
- package/src/lib/server/contact-reports-to.js.map +1 -0
- package/src/lib/server/contact-update.d.ts +42 -1
- package/src/lib/server/contact-update.js +204 -23
- package/src/lib/server/contact-update.js.map +1 -1
- package/src/lib/server/convert-host-lead.d.ts +46 -1
- package/src/lib/server/convert-host-lead.js +173 -15
- package/src/lib/server/convert-host-lead.js.map +1 -1
- package/src/lib/server/convert-open-lead.js +12 -5
- package/src/lib/server/convert-open-lead.js.map +1 -1
- package/src/lib/server/crm-email-activity.d.ts +118 -0
- package/src/lib/server/crm-email-activity.js +148 -0
- package/src/lib/server/crm-email-activity.js.map +1 -0
- package/src/lib/server/crm-inbound-email.js +1 -1
- package/src/lib/server/crm-inbound-email.js.map +1 -1
- package/src/lib/server/crm-next-activity.d.ts +74 -0
- package/src/lib/server/crm-next-activity.js +194 -0
- package/src/lib/server/crm-next-activity.js.map +1 -0
- package/src/lib/server/crm-record-indexes.d.ts +45 -0
- package/src/lib/server/crm-record-indexes.js +78 -0
- package/src/lib/server/crm-record-indexes.js.map +1 -0
- package/src/lib/server/crm-sharing.d.ts +9 -1
- package/src/lib/server/crm-sharing.js +23 -3
- package/src/lib/server/crm-sharing.js.map +1 -1
- package/src/lib/server/deal-contact-roles.d.ts +27 -0
- package/src/lib/server/deal-contact-roles.js +89 -0
- package/src/lib/server/deal-contact-roles.js.map +1 -0
- package/src/lib/server/email-send.js +2 -1
- package/src/lib/server/email-send.js.map +1 -1
- package/src/lib/server/lead-convert.d.ts +5 -0
- package/src/lib/server/lead-convert.js +19 -3
- package/src/lib/server/lead-convert.js.map +1 -1
- package/src/lib/server/lead-create.d.ts +17 -2
- package/src/lib/server/lead-create.js +46 -14
- package/src/lib/server/lead-create.js.map +1 -1
- package/src/lib/server/lead-nurturing.d.ts +6 -0
- package/src/lib/server/lead-nurturing.js +57 -20
- package/src/lib/server/lead-nurturing.js.map +1 -1
- package/src/lib/server/lead-picklists.d.ts +35 -0
- package/src/lib/server/lead-picklists.js +52 -0
- package/src/lib/server/lead-picklists.js.map +1 -0
- package/src/lib/server/lead-source-picklist.d.ts +1 -13
- package/src/lib/server/lead-source-picklist.js +6 -33
- package/src/lib/server/lead-source-picklist.js.map +1 -1
- package/src/lib/server/merge-contacts.js +23 -5
- package/src/lib/server/merge-contacts.js.map +1 -1
- package/src/lib/server/next-activity-routes.js +2 -1
- package/src/lib/server/next-activity-routes.js.map +1 -1
- package/src/lib/server/person-eraser.d.ts +53 -0
- package/src/lib/server/person-eraser.js +149 -0
- package/src/lib/server/person-eraser.js.map +1 -0
- package/src/lib/server/person-records.d.ts +69 -0
- package/src/lib/server/person-records.js +317 -0
- package/src/lib/server/person-records.js.map +1 -0
- package/src/lib/server/person-refund.d.ts +97 -0
- package/src/lib/server/person-refund.js +221 -0
- package/src/lib/server/person-refund.js.map +1 -0
- package/src/lib/server/picklist-values.d.ts +21 -0
- package/src/lib/server/picklist-values.js +308 -0
- package/src/lib/server/picklist-values.js.map +1 -0
- package/src/lib/server/read-picklist.d.ts +44 -0
- package/src/lib/server/read-picklist.js +65 -0
- package/src/lib/server/read-picklist.js.map +1 -0
- package/src/lib/server/recipe-routes.js +22 -8
- package/src/lib/server/recipe-routes.js.map +1 -1
- package/src/lib/server/record-email-state.js +7 -1
- package/src/lib/server/record-email-state.js.map +1 -1
- package/src/lib/server/record-facts.d.ts +3 -0
- package/src/lib/server/record-facts.js +233 -31
- package/src/lib/server/record-facts.js.map +1 -1
- package/src/lib/server/record-origin.d.ts +27 -0
- package/src/lib/server/record-origin.js +104 -0
- package/src/lib/server/record-origin.js.map +1 -0
- package/src/lib/server/record-timeline.js +40 -3
- package/src/lib/server/record-timeline.js.map +1 -1
- package/src/lib/server/suite-gate.js +4 -3
- package/src/lib/server/suite-gate.js.map +1 -1
- package/src/lib/server/task-reminders-route.js +2 -1
- package/src/lib/server/task-reminders-route.js.map +1 -1
- package/src/lib/server/task-routes.js +33 -17
- package/src/lib/server/task-routes.js.map +1 -1
- package/src/lib/server-deal-stage.d.ts +5 -1
- package/src/lib/server-deal-stage.js +10 -5
- package/src/lib/server-deal-stage.js.map +1 -1
- package/src/lib/server.d.ts +8 -3
- package/src/lib/server.js +47 -43
- package/src/lib/server.js.map +1 -1
- package/src/lib/testing/memory-firestore.d.ts +55 -0
- package/src/lib/testing/memory-firestore.js +335 -0
- package/src/lib/testing/memory-firestore.js.map +1 -0
- package/src/lib/testing/stand-in-email-send-index.d.ts +25 -0
- package/src/lib/testing/stand-in-email-send-index.js +49 -0
- package/src/lib/testing/stand-in-email-send-index.js.map +1 -0
- package/src/lib/transfer/activities.d.ts +30 -0
- package/src/lib/transfer/activities.js +132 -0
- package/src/lib/transfer/activities.js.map +1 -0
- package/src/lib/transfer/aliases.d.ts +22 -0
- package/src/lib/transfer/aliases.js +1342 -0
- package/src/lib/transfer/aliases.js.map +1 -0
- package/src/lib/transfer/common.d.ts +222 -0
- package/src/lib/transfer/common.js +832 -0
- package/src/lib/transfer/common.js.map +1 -0
- package/src/lib/transfer/companies.d.ts +43 -0
- package/src/lib/transfer/companies.js +549 -0
- package/src/lib/transfer/companies.js.map +1 -0
- package/src/lib/transfer/contacts.d.ts +31 -0
- package/src/lib/transfer/contacts.js +727 -0
- package/src/lib/transfer/contacts.js.map +1 -0
- package/src/lib/transfer/deals.d.ts +66 -0
- package/src/lib/transfer/deals.js +698 -0
- package/src/lib/transfer/deals.js.map +1 -0
- package/src/lib/transfer/email-templates-package.d.ts +40 -0
- package/src/lib/transfer/email-templates-package.js +76 -0
- package/src/lib/transfer/email-templates-package.js.map +1 -0
- package/src/lib/transfer/email-templates-package.server.d.ts +32 -0
- package/src/lib/transfer/email-templates-package.server.js +176 -0
- package/src/lib/transfer/email-templates-package.server.js.map +1 -0
- package/src/lib/transfer/fields.d.ts +102 -0
- package/src/lib/transfer/fields.js +1755 -0
- package/src/lib/transfer/fields.js.map +1 -0
- package/src/lib/transfer/leads.d.ts +30 -0
- package/src/lib/transfer/leads.js +582 -0
- package/src/lib/transfer/leads.js.map +1 -0
- package/src/lib/transfer/pipelines.d.ts +21 -0
- package/src/lib/transfer/pipelines.js +172 -0
- package/src/lib/transfer/pipelines.js.map +1 -0
- package/src/lib/transfer/register.d.ts +47 -0
- package/src/lib/transfer/register.js +277 -0
- package/src/lib/transfer/register.js.map +1 -0
- package/src/lib/transfer/tasks.d.ts +30 -0
- package/src/lib/transfer/tasks.js +418 -0
- package/src/lib/transfer/tasks.js.map +1 -0
- package/src/lib/transfer/ui.d.ts +20 -0
- package/src/lib/transfer/ui.js +42 -0
- package/src/lib/transfer/ui.js.map +1 -0
- package/src/lib/components/company-import-drawer.d.ts +0 -42
- package/src/lib/components/company-import-drawer.js +0 -99
- package/src/lib/components/company-import-drawer.js.map +0 -1
- package/src/lib/components/contact-import-drawer.d.ts +0 -46
- package/src/lib/components/contact-import-drawer.js +0 -149
- package/src/lib/components/contact-import-drawer.js.map +0 -1
- package/src/lib/components/crm-export-all-button.d.ts +0 -39
- package/src/lib/components/crm-export-all-button.js +0 -98
- package/src/lib/components/crm-export-all-button.js.map +0 -1
- package/src/lib/components/csv-import-drawer.d.ts +0 -139
- package/src/lib/components/csv-import-drawer.js +0 -757
- package/src/lib/components/csv-import-drawer.js.map +0 -1
- package/src/lib/components/deal-import-drawer.d.ts +0 -24
- package/src/lib/components/deal-import-drawer.js +0 -83
- package/src/lib/components/deal-import-drawer.js.map +0 -1
- package/src/lib/components/lead-import-drawer.d.ts +0 -27
- package/src/lib/components/lead-import-drawer.js +0 -118
- package/src/lib/components/lead-import-drawer.js.map +0 -1
- package/src/lib/components/lead-source-values-card.d.ts +0 -27
- package/src/lib/components/lead-source-values-card.js.map +0 -1
- package/src/lib/components/task-import-drawer.d.ts +0 -24
- package/src/lib/components/task-import-drawer.js +0 -82
- package/src/lib/components/task-import-drawer.js.map +0 -1
- package/src/lib/model/companies-csv.d.ts +0 -36
- package/src/lib/model/companies-csv.js +0 -38
- package/src/lib/model/companies-csv.js.map +0 -1
- package/src/lib/model/contacts-csv.d.ts +0 -54
- package/src/lib/model/contacts-csv.js +0 -67
- package/src/lib/model/contacts-csv.js.map +0 -1
- package/src/lib/model/crm-company-import.d.ts +0 -154
- package/src/lib/model/crm-company-import.js +0 -331
- package/src/lib/model/crm-company-import.js.map +0 -1
- package/src/lib/model/crm-csv.d.ts +0 -239
- package/src/lib/model/crm-csv.js +0 -467
- package/src/lib/model/crm-csv.js.map +0 -1
- package/src/lib/model/crm-deal-import.d.ts +0 -112
- package/src/lib/model/crm-deal-import.js +0 -263
- package/src/lib/model/crm-deal-import.js.map +0 -1
- package/src/lib/model/crm-import.d.ts +0 -250
- package/src/lib/model/crm-import.js +0 -467
- package/src/lib/model/crm-import.js.map +0 -1
- package/src/lib/model/crm-lead-import.d.ts +0 -138
- package/src/lib/model/crm-lead-import.js +0 -446
- package/src/lib/model/crm-lead-import.js.map +0 -1
- package/src/lib/model/crm-task-import.d.ts +0 -94
- package/src/lib/model/crm-task-import.js +0 -275
- package/src/lib/model/crm-task-import.js.map +0 -1
- package/src/lib/model/deals-csv.d.ts +0 -32
- package/src/lib/model/deals-csv.js +0 -36
- package/src/lib/model/deals-csv.js.map +0 -1
- package/src/lib/model/import-column-shapes.d.ts +0 -36
- package/src/lib/model/import-column-shapes.js +0 -76
- package/src/lib/model/import-column-shapes.js.map +0 -1
- package/src/lib/model/lead-source-values.d.ts +0 -82
- package/src/lib/model/lead-source-values.js +0 -149
- package/src/lib/model/lead-source-values.js.map +0 -1
- package/src/lib/model/leads-csv.d.ts +0 -40
- package/src/lib/model/leads-csv.js +0 -40
- package/src/lib/model/leads-csv.js.map +0 -1
- package/src/lib/model/tasks-csv.d.ts +0 -28
- package/src/lib/model/tasks-csv.js +0 -28
- package/src/lib/model/tasks-csv.js.map +0 -1
- package/src/lib/server/companies-import.d.ts +0 -57
- package/src/lib/server/companies-import.js +0 -242
- package/src/lib/server/companies-import.js.map +0 -1
- package/src/lib/server/contacts-import.d.ts +0 -109
- package/src/lib/server/contacts-import.js +0 -393
- package/src/lib/server/contacts-import.js.map +0 -1
- package/src/lib/server/deals-import.d.ts +0 -76
- package/src/lib/server/deals-import.js +0 -248
- package/src/lib/server/deals-import.js.map +0 -1
- package/src/lib/server/export-route.d.ts +0 -60
- package/src/lib/server/export-route.js +0 -447
- package/src/lib/server/export-route.js.map +0 -1
- package/src/lib/server/import-context.d.ts +0 -87
- package/src/lib/server/import-context.js +0 -182
- package/src/lib/server/import-context.js.map +0 -1
- package/src/lib/server/lead-source-values.d.ts +0 -50
- package/src/lib/server/lead-source-values.js +0 -191
- package/src/lib/server/lead-source-values.js.map +0 -1
- package/src/lib/server/leads-import.d.ts +0 -84
- package/src/lib/server/leads-import.js +0 -367
- package/src/lib/server/leads-import.js.map +0 -1
- package/src/lib/server/tasks-import.d.ts +0 -54
- package/src/lib/server/tasks-import.js +0 -160
- package/src/lib/server/tasks-import.js.map +0 -1
|
@@ -1,99 +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 COMPANIES FILE — the company vocabulary over the shared
|
|
20
|
-
* drawer (AGL-2621).
|
|
21
|
-
*
|
|
22
|
-
* The server half is `server/companies-import.ts`. What is particular to
|
|
23
|
-
* companies: the name is the one cell every row needs (a domain is a key,
|
|
24
|
-
* a name is the caption the list cannot do without), the custom fields
|
|
25
|
-
* are the org's COMPANY definitions (AGL-2661), and a row is matched to a
|
|
26
|
-
* company already filed by its domain first and its name second.
|
|
27
|
-
*/ import { pluginDocsHelp } from "@aglyn/aglyn";
|
|
28
|
-
import { COMPANY_IMPORT_CHUNK_SIZE, COMPANY_IMPORT_FIELD_LABELS, COMPANY_IMPORT_FIELDS, COMPANY_IMPORT_MAX_ROWS, COMPANY_IMPORT_PREVIEW_ROWS, COMPANY_IMPORT_SKIP_LABELS, companyImportSkippedCsv, emptyCompanyImportResult, guessCompanyImportMapping, mapCompanyImportRow, mergeCompanyImportResults } from "../model/crm-company-import.js";
|
|
29
|
-
import { useMemo } from "react";
|
|
30
|
-
import { useContactFieldDefinitions } from "../hooks/use-contact-field-definitions.js";
|
|
31
|
-
import { useCrmScope } from "../hooks/use-crm-scope.js";
|
|
32
|
-
import { companyImportTemplateCsv } from "../model/companies-csv.js";
|
|
33
|
-
import { CsvImportButton, CsvImportDrawer } from "./csv-import-drawer.js";
|
|
34
|
-
/** The browser-side address of the route one chunk is posted to. */ export const COMPANIES_IMPORT_URL = '/api/crm/companies-import';
|
|
35
|
-
/** The company vocabulary, over the org's company custom fields (AGL-2661). */ export function companyImportVocabulary(fields) {
|
|
36
|
-
return {
|
|
37
|
-
title: 'Import companies from CSV',
|
|
38
|
-
collection: 'companies',
|
|
39
|
-
help: pluginDocsHelp('companies', {
|
|
40
|
-
anchor: '#import-from-csv'
|
|
41
|
-
}),
|
|
42
|
-
sitePickerHelperText: 'The site these companies are filed under — it decides which of your ' + 'sites may see them.',
|
|
43
|
-
intro: 'A CSV with a header row. Match its columns to company fields below, ' + 'check the preview, then import. A company already in your list — by ' + 'domain, or failing that by name — is updated rather than added twice. ' + `Up to ${COMPANY_IMPORT_MAX_ROWS.toLocaleString()} rows per file — split ` + 'a larger one.',
|
|
44
|
-
fields: COMPANY_IMPORT_FIELDS,
|
|
45
|
-
fieldLabels: COMPANY_IMPORT_FIELD_LABELS,
|
|
46
|
-
customFields: fields,
|
|
47
|
-
requiredField: 'name',
|
|
48
|
-
requiredWarning: 'Choose which column holds the company name. It is the one field every ' + 'row needs.',
|
|
49
|
-
unusableNotice: (count, total)=>`${count.toLocaleString()} of ${total.toLocaleString()} rows have no ` + 'company name and will be skipped. You can download them after the ' + 'import.',
|
|
50
|
-
guessMapping: (columns)=>guessCompanyImportMapping(columns, fields),
|
|
51
|
-
mapRow: (cells, mapping)=>mapCompanyImportRow(cells, mapping),
|
|
52
|
-
route: COMPANIES_IMPORT_URL,
|
|
53
|
-
maxRows: COMPANY_IMPORT_MAX_ROWS,
|
|
54
|
-
chunkSize: COMPANY_IMPORT_CHUNK_SIZE,
|
|
55
|
-
previewRows: COMPANY_IMPORT_PREVIEW_ROWS,
|
|
56
|
-
emptyResult: emptyCompanyImportResult,
|
|
57
|
-
mergeResults: mergeCompanyImportResults,
|
|
58
|
-
skipLabels: COMPANY_IMPORT_SKIP_LABELS,
|
|
59
|
-
skippedCsv: companyImportSkippedCsv,
|
|
60
|
-
skippedFileName: 'skipped-companies.csv',
|
|
61
|
-
templateCsv: companyImportTemplateCsv,
|
|
62
|
-
templateFileName: 'companies-template.csv'
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
/** The vocabulary with no custom fields — what a surface without an org resolves to. */ export const COMPANY_IMPORT_VOCABULARY = companyImportVocabulary([]);
|
|
66
|
-
export function CompanyImportDrawer(props) {
|
|
67
|
-
const { open, onClose, hostId, org } = props;
|
|
68
|
-
// The org's company fields, read only while the drawer is open.
|
|
69
|
-
const { orgId } = useCrmScope({
|
|
70
|
-
hostId,
|
|
71
|
-
org
|
|
72
|
-
});
|
|
73
|
-
const { active } = useContactFieldDefinitions(open ? orgId : null, 'company');
|
|
74
|
-
const vocabulary = useMemo(()=>companyImportVocabulary(active), [
|
|
75
|
-
active
|
|
76
|
-
]);
|
|
77
|
-
return /*#__PURE__*/ _jsx(CsvImportDrawer, {
|
|
78
|
-
open: open,
|
|
79
|
-
onClose: onClose,
|
|
80
|
-
hostId: hostId,
|
|
81
|
-
vocabulary: vocabulary
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
CompanyImportDrawer.displayName = 'CompanyImportDrawer';
|
|
85
|
-
/** The "Import CSV" action on the companies list, with the drawer it opens. */ export function CompanyImportButton(props) {
|
|
86
|
-
const { hostId, org } = props;
|
|
87
|
-
return /*#__PURE__*/ _jsx(CsvImportButton, {
|
|
88
|
-
children: (open, onClose)=>/*#__PURE__*/ _jsx(CompanyImportDrawer, {
|
|
89
|
-
open: open,
|
|
90
|
-
onClose: onClose,
|
|
91
|
-
hostId: hostId,
|
|
92
|
-
org: org
|
|
93
|
-
})
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
CompanyImportButton.displayName = 'CompanyImportButton';
|
|
97
|
-
export default CompanyImportDrawer;
|
|
98
|
-
|
|
99
|
-
//# sourceMappingURL=company-import-drawer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/company-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 COMPANIES FILE — the company vocabulary over the shared\n * drawer (AGL-2621).\n *\n * The server half is `server/companies-import.ts`. What is particular to\n * companies: the name is the one cell every row needs (a domain is a key,\n * a name is the caption the list cannot do without), the custom fields\n * are the org's COMPANY definitions (AGL-2661), and a row is matched to a\n * company already filed by its domain first and its name second.\n */\n\nimport {\n type ConsolePluginPageProps,\n type ContactFieldDefinition,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport {\n COMPANY_IMPORT_CHUNK_SIZE,\n COMPANY_IMPORT_FIELD_LABELS,\n COMPANY_IMPORT_FIELDS,\n COMPANY_IMPORT_MAX_ROWS,\n COMPANY_IMPORT_PREVIEW_ROWS,\n COMPANY_IMPORT_SKIP_LABELS,\n type CompanyImportField,\n type CompanyImportRawRow,\n type CompanyImportSkippedRow,\n companyImportSkippedCsv,\n emptyCompanyImportResult,\n guessCompanyImportMapping,\n mapCompanyImportRow,\n mergeCompanyImportResults,\n} from '../model/crm-company-import'\nimport { useMemo } from 'react'\nimport { useContactFieldDefinitions } from '../hooks/use-contact-field-definitions'\nimport { useCrmScope } from '../hooks/use-crm-scope'\nimport { companyImportTemplateCsv } from '../model/companies-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 COMPANIES_IMPORT_URL = '/api/crm/companies-import'\n\n/** The company vocabulary, over the org's company custom fields (AGL-2661). */\nexport function companyImportVocabulary(\n fields: readonly ContactFieldDefinition[],\n): CsvImportVocabulary<\n CompanyImportField,\n CompanyImportRawRow & Record<string, unknown>,\n CompanyImportSkippedRow\n> {\n return {\n title: 'Import companies from CSV',\n collection: 'companies',\n help: pluginDocsHelp('companies', { anchor: '#import-from-csv' }),\n sitePickerHelperText:\n 'The site these companies are filed under — it decides which of your ' +\n 'sites may see them.',\n intro:\n 'A CSV with a header row. Match its columns to company fields below, ' +\n 'check the preview, then import. A company already in your list — by ' +\n 'domain, or failing that by name — is updated rather than added twice. ' +\n `Up to ${COMPANY_IMPORT_MAX_ROWS.toLocaleString()} rows per file — split ` +\n 'a larger one.',\n fields: COMPANY_IMPORT_FIELDS,\n fieldLabels: COMPANY_IMPORT_FIELD_LABELS,\n customFields: fields,\n requiredField: 'name',\n requiredWarning:\n 'Choose which column holds the company name. It is the one field every ' +\n 'row needs.',\n unusableNotice: (count, total) =>\n `${count.toLocaleString()} of ${total.toLocaleString()} rows have no ` +\n 'company name and will be skipped. You can download them after the ' +\n 'import.',\n guessMapping: (columns) => guessCompanyImportMapping(columns, fields),\n mapRow: (cells, mapping) =>\n mapCompanyImportRow(cells, mapping) as CompanyImportRawRow & Record<string, unknown>,\n route: COMPANIES_IMPORT_URL,\n maxRows: COMPANY_IMPORT_MAX_ROWS,\n chunkSize: COMPANY_IMPORT_CHUNK_SIZE,\n previewRows: COMPANY_IMPORT_PREVIEW_ROWS,\n emptyResult: emptyCompanyImportResult,\n mergeResults: mergeCompanyImportResults,\n skipLabels: COMPANY_IMPORT_SKIP_LABELS,\n skippedCsv: companyImportSkippedCsv,\n skippedFileName: 'skipped-companies.csv',\n templateCsv: companyImportTemplateCsv,\n templateFileName: 'companies-template.csv',\n }\n}\n\n/** The vocabulary with no custom fields — what a surface without an org resolves to. */\nexport const COMPANY_IMPORT_VOCABULARY = companyImportVocabulary([])\n\nexport interface CompanyImportDrawerProps {\n open: boolean\n onClose: () => void\n /** The site the file is filed under, or `null` at the organization level (AGL-2630). */\n hostId: string | null\n /** The org, for the company field definitions the mapping offers (AGL-2661). */\n org?: ConsolePluginPageProps['org']\n}\n\nexport function CompanyImportDrawer(props: CompanyImportDrawerProps) {\n const { open, onClose, hostId, org } = props\n // The org's company fields, read only while the drawer is open.\n const { orgId } = useCrmScope({ hostId, org })\n const { active } = useContactFieldDefinitions(open ? orgId : null, 'company')\n const vocabulary = useMemo(() => companyImportVocabulary(active), [active])\n return (\n <CsvImportDrawer\n open={open}\n onClose={onClose}\n hostId={hostId}\n vocabulary={vocabulary}\n />\n )\n}\nCompanyImportDrawer.displayName = 'CompanyImportDrawer'\n\n/** The \"Import CSV\" action on the companies list, with the drawer it opens. */\nexport function CompanyImportButton(props: {\n hostId: string | null\n org?: ConsolePluginPageProps['org']\n}) {\n const { hostId, org } = props\n return (\n <CsvImportButton>\n {(open, onClose) => (\n <CompanyImportDrawer open={open} onClose={onClose} hostId={hostId} org={org} />\n )}\n </CsvImportButton>\n )\n}\nCompanyImportButton.displayName = 'CompanyImportButton'\n\nexport default CompanyImportDrawer\n"],"names":["pluginDocsHelp","COMPANY_IMPORT_CHUNK_SIZE","COMPANY_IMPORT_FIELD_LABELS","COMPANY_IMPORT_FIELDS","COMPANY_IMPORT_MAX_ROWS","COMPANY_IMPORT_PREVIEW_ROWS","COMPANY_IMPORT_SKIP_LABELS","companyImportSkippedCsv","emptyCompanyImportResult","guessCompanyImportMapping","mapCompanyImportRow","mergeCompanyImportResults","useMemo","useContactFieldDefinitions","useCrmScope","companyImportTemplateCsv","CsvImportButton","CsvImportDrawer","COMPANIES_IMPORT_URL","companyImportVocabulary","fields","title","collection","help","anchor","sitePickerHelperText","intro","toLocaleString","fieldLabels","customFields","requiredField","requiredWarning","unusableNotice","count","total","guessMapping","columns","mapRow","cells","mapping","route","maxRows","chunkSize","previewRows","emptyResult","mergeResults","skipLabels","skippedCsv","skippedFileName","templateCsv","templateFileName","COMPANY_IMPORT_VOCABULARY","CompanyImportDrawer","props","open","onClose","hostId","org","orgId","active","vocabulary","displayName","CompanyImportButton"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA;;;;;;;;;CASC,GAED,SAGEA,cAAc,QACT,eAAc;AACrB,SACEC,yBAAyB,EACzBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,uBAAuB,EACvBC,2BAA2B,EAC3BC,0BAA0B,EAI1BC,uBAAuB,EACvBC,wBAAwB,EACxBC,yBAAyB,EACzBC,mBAAmB,EACnBC,yBAAyB,QACpB,iCAA6B;AACpC,SAASC,OAAO,QAAQ,QAAO;AAC/B,SAASC,0BAA0B,QAAQ,4CAAwC;AACnF,SAASC,WAAW,QAAQ,4BAAwB;AACpD,SAASC,wBAAwB,QAAQ,4BAAwB;AACjE,SACEC,eAAe,EACfC,eAAe,QAEV,yBAAqB;AAE5B,kEAAkE,GAClE,OAAO,MAAMC,uBAAuB,4BAA2B;AAE/D,6EAA6E,GAC7E,OAAO,SAASC,wBACdC,MAAyC;IAMzC,OAAO;QACLC,OAAO;QACPC,YAAY;QACZC,MAAMvB,eAAe,aAAa;YAAEwB,QAAQ;QAAmB;QAC/DC,sBACE,yEACA;QACFC,OACE,yEACA,yEACA,2EACA,CAAC,MAAM,EAAEtB,wBAAwBuB,cAAc,GAAG,uBAAuB,CAAC,GAC1E;QACFP,QAAQjB;QACRyB,aAAa1B;QACb2B,cAAcT;QACdU,eAAe;QACfC,iBACE,2EACA;QACFC,gBAAgB,CAACC,OAAOC,QACtB,GAAGD,MAAMN,cAAc,GAAG,IAAI,EAAEO,MAAMP,cAAc,GAAG,cAAc,CAAC,GACtE,uEACA;QACFQ,cAAc,CAACC,UAAY3B,0BAA0B2B,SAAShB;QAC9DiB,QAAQ,CAACC,OAAOC,UACd7B,oBAAoB4B,OAAOC;QAC7BC,OAAOtB;QACPuB,SAASrC;QACTsC,WAAWzC;QACX0C,aAAatC;QACbuC,aAAapC;QACbqC,cAAclC;QACdmC,YAAYxC;QACZyC,YAAYxC;QACZyC,iBAAiB;QACjBC,aAAalC;QACbmC,kBAAkB;IACpB;AACF;AAEA,sFAAsF,GACtF,OAAO,MAAMC,4BAA4BhC,wBAAwB,EAAE,EAAC;AAWpE,OAAO,SAASiC,oBAAoBC,KAA+B;IACjE,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEC,MAAM,EAAEC,GAAG,EAAE,GAAGJ;IACvC,gEAAgE;IAChE,MAAM,EAAEK,KAAK,EAAE,GAAG5C,YAAY;QAAE0C;QAAQC;IAAI;IAC5C,MAAM,EAAEE,MAAM,EAAE,GAAG9C,2BAA2ByC,OAAOI,QAAQ,MAAM;IACnE,MAAME,aAAahD,QAAQ,IAAMO,wBAAwBwC,SAAS;QAACA;KAAO;IAC1E,qBACE,KAAC1C;QACCqC,MAAMA;QACNC,SAASA;QACTC,QAAQA;QACRI,YAAYA;;AAGlB;AACAR,oBAAoBS,WAAW,GAAG;AAElC,6EAA6E,GAC7E,OAAO,SAASC,oBAAoBT,KAGnC;IACC,MAAM,EAAEG,MAAM,EAAEC,GAAG,EAAE,GAAGJ;IACxB,qBACE,KAACrC;kBACE,CAACsC,MAAMC,wBACN,KAACH;gBAAoBE,MAAMA;gBAAMC,SAASA;gBAASC,QAAQA;gBAAQC,KAAKA;;;AAIhF;AACAK,oBAAoBD,WAAW,GAAG;AAElC,eAAeT,oBAAmB"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IMPORTING A CONTACT FILE — the contact vocabulary over the shared drawer
|
|
3
|
-
* (AGL-2602; the drawer itself is `csv-import-drawer.tsx` since AGL-2621).
|
|
4
|
-
*
|
|
5
|
-
* The server half is `server/contacts-import.ts`. What this file adds to
|
|
6
|
-
* the walk the shared drawer makes is what is particular to people: the
|
|
7
|
-
* contact fields and their aliases, the holder's custom fields as further
|
|
8
|
-
* targets, the email as the one cell every row needs — judged here by the
|
|
9
|
-
* same normalizer the route runs, as a courtesy count — and the line in
|
|
10
|
-
* the result that says how many companies the file's company column made.
|
|
11
|
-
*/
|
|
12
|
-
import { type ConsolePluginPageProps } from '@aglyn/aglyn';
|
|
13
|
-
export interface ContactImportDrawerProps {
|
|
14
|
-
open: boolean;
|
|
15
|
-
onClose: () => void;
|
|
16
|
-
/**
|
|
17
|
-
* The site the file is imported INTO — what the route captures every row
|
|
18
|
-
* under — or `null` at the organization level (AGL-2630), where the
|
|
19
|
-
* drawer asks which site with a picker and holds the import until one is
|
|
20
|
-
* named.
|
|
21
|
-
*/
|
|
22
|
-
hostId: string | null;
|
|
23
|
-
/**
|
|
24
|
-
* The org document the shell passed, for the consent group's scope
|
|
25
|
-
* tokens. Typed as the page prop it is forwarded from, so the contacts
|
|
26
|
-
* list mounts the button with the value it already holds and no cast.
|
|
27
|
-
*/
|
|
28
|
-
org?: ConsolePluginPageProps['org'];
|
|
29
|
-
}
|
|
30
|
-
export declare function ContactImportDrawer(props: ContactImportDrawerProps): import("react").JSX.Element;
|
|
31
|
-
export declare namespace ContactImportDrawer {
|
|
32
|
-
var displayName: string;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* The "Import CSV" action on the contacts list, with the drawer it opens —
|
|
36
|
-
* mounted only once opened, so the list pays nothing for it until then.
|
|
37
|
-
*/
|
|
38
|
-
export declare function ContactImportButton(props: {
|
|
39
|
-
/** The site the list is read under, or `null` at the organization level. */
|
|
40
|
-
hostId: string | null;
|
|
41
|
-
org?: ConsolePluginPageProps['org'];
|
|
42
|
-
}): import("react").JSX.Element;
|
|
43
|
-
export declare namespace ContactImportButton {
|
|
44
|
-
var displayName: string;
|
|
45
|
-
}
|
|
46
|
-
export default ContactImportDrawer;
|
|
@@ -1,149 +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 CONTACT FILE — the contact vocabulary over the shared drawer
|
|
20
|
-
* (AGL-2602; the drawer itself is `csv-import-drawer.tsx` since AGL-2621).
|
|
21
|
-
*
|
|
22
|
-
* The server half is `server/contacts-import.ts`. What this file adds to
|
|
23
|
-
* the walk the shared drawer makes is what is particular to people: the
|
|
24
|
-
* contact fields and their aliases, the holder's custom fields as further
|
|
25
|
-
* targets, the email as the one cell every row needs — judged here by the
|
|
26
|
-
* same normalizer the route runs, as a courtesy count — and the line in
|
|
27
|
-
* the result that says how many companies the file's company column made.
|
|
28
|
-
*/ import { CRM_COLLECTIONS, normalizeContactEmail, pluginDocsHelp } from "@aglyn/aglyn";
|
|
29
|
-
import { CONTACT_IMPORT_CHUNK_SIZE, CONTACT_IMPORT_FIELD_LABELS, CONTACT_IMPORT_FIELDS, CONTACT_IMPORT_MAX_ROWS, CONTACT_IMPORT_PREVIEW_ROWS, CONTACT_IMPORT_SKIP_LABELS, contactImportSkippedCsv, emptyContactImportResult, guessContactImportMapping, mapContactImportRow, mergeContactImportResults } from "../model/crm-import.js";
|
|
30
|
-
import { useFirestore, useFirestoreCollection } from "@aglyn/tenant-feature-instance";
|
|
31
|
-
import { Typography } from "@mui/material";
|
|
32
|
-
import { collection, limit, query } from "firebase/firestore";
|
|
33
|
-
import { useMemo } from "react";
|
|
34
|
-
import { crmVisibleToClause, useCrmScope } from "../hooks/use-crm-scope.js";
|
|
35
|
-
import { contactImportTemplateCsv } from "../model/contacts-csv.js";
|
|
36
|
-
import { CsvImportButton, CsvImportDrawer } from "./csv-import-drawer.js";
|
|
37
|
-
/**
|
|
38
|
-
* The holder's live custom-field definitions, read only while the drawer
|
|
39
|
-
* is open.
|
|
40
|
-
*
|
|
41
|
-
* A local hook rather than a shared one because the Fields section that
|
|
42
|
-
* will own these definitions is landing beside this drawer; when it ships a
|
|
43
|
-
* `useContactFieldDefinitions`, this is the read to replace with it. Scoped
|
|
44
|
-
* by `visibleTo` the way the contacts listener is, because the rules prove
|
|
45
|
-
* a scoped member's query per document and refuse an unfiltered one.
|
|
46
|
-
*
|
|
47
|
-
* Ordered in memory rather than by the query: `array-contains-any` with an
|
|
48
|
-
* `orderBy` on another field needs a composite index the collection does
|
|
49
|
-
* not have, and a holder's field list fits in one page.
|
|
50
|
-
*/ function useImportFieldDefinitions(options) {
|
|
51
|
-
const { orgId, visibleToTokens, enabled } = options;
|
|
52
|
-
const firestore = useFirestore();
|
|
53
|
-
const { data } = useFirestoreCollection(()=>enabled && orgId ? query(collection(firestore, 'orgs', orgId, CRM_COLLECTIONS.contactFields), ...crmVisibleToClause(visibleToTokens), limit(100)) : null, [
|
|
54
|
-
firestore,
|
|
55
|
-
orgId,
|
|
56
|
-
visibleToTokens,
|
|
57
|
-
enabled
|
|
58
|
-
], {
|
|
59
|
-
idField: '$id'
|
|
60
|
-
});
|
|
61
|
-
return useMemo(()=>(data != null ? data : []).filter((field)=>!!field.key && !field.retiredAt).sort((a, b)=>{
|
|
62
|
-
var _a_order, _b_order;
|
|
63
|
-
return Number((_a_order = a.order) != null ? _a_order : 0) - Number((_b_order = b.order) != null ? _b_order : 0);
|
|
64
|
-
}), [
|
|
65
|
-
data
|
|
66
|
-
]);
|
|
67
|
-
}
|
|
68
|
-
/** The contact vocabulary, over the holder's custom fields. */ function contactImportVocabulary(fields) {
|
|
69
|
-
return {
|
|
70
|
-
title: 'Import contacts from CSV',
|
|
71
|
-
collection: 'contacts',
|
|
72
|
-
help: pluginDocsHelp('contacts', {
|
|
73
|
-
anchor: '#import-from-csv'
|
|
74
|
-
}),
|
|
75
|
-
sitePickerHelperText: 'The site these people are imported into — it decides which of your ' + "sites may see them and whose marketing consent the file's consent " + 'column records.',
|
|
76
|
-
intro: 'A CSV with a header row. Match its columns to contact fields ' + 'below, check the preview, then import. A person already in your ' + 'contacts is updated rather than added twice. Up to ' + `${CONTACT_IMPORT_MAX_ROWS.toLocaleString()} rows per file — split a ` + 'larger one.',
|
|
77
|
-
fields: CONTACT_IMPORT_FIELDS,
|
|
78
|
-
fieldLabels: CONTACT_IMPORT_FIELD_LABELS,
|
|
79
|
-
customFields: fields,
|
|
80
|
-
requiredField: 'email',
|
|
81
|
-
requiredWarning: 'Choose which column holds the email address. It is the one field ' + 'every row needs.',
|
|
82
|
-
unusable: (cell)=>!normalizeContactEmail(cell),
|
|
83
|
-
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.',
|
|
84
|
-
guessMapping: (columns)=>guessContactImportMapping(columns, fields),
|
|
85
|
-
mapRow: (cells, mapping)=>mapContactImportRow(cells, mapping),
|
|
86
|
-
route: '/api/crm/contacts-import',
|
|
87
|
-
maxRows: CONTACT_IMPORT_MAX_ROWS,
|
|
88
|
-
chunkSize: CONTACT_IMPORT_CHUNK_SIZE,
|
|
89
|
-
previewRows: CONTACT_IMPORT_PREVIEW_ROWS,
|
|
90
|
-
emptyResult: emptyContactImportResult,
|
|
91
|
-
mergeResults: (total, chunk, offset)=>mergeContactImportResults(total, chunk, offset),
|
|
92
|
-
skipLabels: CONTACT_IMPORT_SKIP_LABELS,
|
|
93
|
-
skippedCsv: contactImportSkippedCsv,
|
|
94
|
-
skippedFileName: 'skipped-contacts.csv',
|
|
95
|
-
templateCsv: ()=>contactImportTemplateCsv(fields),
|
|
96
|
-
templateFileName: 'contacts-template.csv',
|
|
97
|
-
resultExtras: (result)=>{
|
|
98
|
-
const created = result.companiesCreated;
|
|
99
|
-
return created ? /*#__PURE__*/ _jsx(Typography, {
|
|
100
|
-
variant: "body2",
|
|
101
|
-
color: "text.secondary",
|
|
102
|
-
children: `${created.toLocaleString()} new ${created === 1 ? 'company' : 'companies'} created from the company column.`
|
|
103
|
-
}) : null;
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
export function ContactImportDrawer(props) {
|
|
108
|
-
const { open, onClose, hostId, org } = props;
|
|
109
|
-
// The org root and the reader's tokens from the one scope hook (AGL-2614);
|
|
110
|
-
// at the organization level no clause, and the site every row is captured
|
|
111
|
-
// under is the one the drawer's picker names (AGL-2630).
|
|
112
|
-
const { orgId, visibleTo: visibleToTokens } = useCrmScope({
|
|
113
|
-
hostId,
|
|
114
|
-
org
|
|
115
|
-
});
|
|
116
|
-
const fields = useImportFieldDefinitions({
|
|
117
|
-
orgId,
|
|
118
|
-
visibleToTokens,
|
|
119
|
-
enabled: open
|
|
120
|
-
});
|
|
121
|
-
const vocabulary = useMemo(()=>contactImportVocabulary(fields), [
|
|
122
|
-
fields
|
|
123
|
-
]);
|
|
124
|
-
return /*#__PURE__*/ _jsx(CsvImportDrawer, {
|
|
125
|
-
open: open,
|
|
126
|
-
onClose: onClose,
|
|
127
|
-
hostId: hostId,
|
|
128
|
-
vocabulary: vocabulary
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
ContactImportDrawer.displayName = 'ContactImportDrawer';
|
|
132
|
-
/**
|
|
133
|
-
* The "Import CSV" action on the contacts list, with the drawer it opens —
|
|
134
|
-
* mounted only once opened, so the list pays nothing for it until then.
|
|
135
|
-
*/ export function ContactImportButton(props) {
|
|
136
|
-
const { hostId, org } = props;
|
|
137
|
-
return /*#__PURE__*/ _jsx(CsvImportButton, {
|
|
138
|
-
children: (open, onClose)=>/*#__PURE__*/ _jsx(ContactImportDrawer, {
|
|
139
|
-
open: open,
|
|
140
|
-
onClose: onClose,
|
|
141
|
-
hostId: hostId,
|
|
142
|
-
org: org
|
|
143
|
-
})
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
ContactImportButton.displayName = 'ContactImportButton';
|
|
147
|
-
export default ContactImportDrawer;
|
|
148
|
-
|
|
149
|
-
//# sourceMappingURL=contact-import-drawer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/contact-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 CONTACT FILE — the contact vocabulary over the shared drawer\n * (AGL-2602; the drawer itself is `csv-import-drawer.tsx` since AGL-2621).\n *\n * The server half is `server/contacts-import.ts`. What this file adds to\n * the walk the shared drawer makes is what is particular to people: the\n * contact fields and their aliases, the holder's custom fields as further\n * targets, the email as the one cell every row needs — judged here by the\n * same normalizer the route runs, as a courtesy count — and the line in\n * the result that says how many companies the file's company column made.\n */\n\nimport {\n type ConsolePluginPageProps,\n type ContactFieldDefinition,\n CRM_COLLECTIONS,\n normalizeContactEmail,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport {\n CONTACT_IMPORT_CHUNK_SIZE,\n CONTACT_IMPORT_FIELD_LABELS,\n CONTACT_IMPORT_FIELDS,\n CONTACT_IMPORT_MAX_ROWS,\n CONTACT_IMPORT_PREVIEW_ROWS,\n CONTACT_IMPORT_SKIP_LABELS,\n type ContactImportChunkResult,\n type ContactImportField,\n type ContactImportRawRow,\n type ContactImportSkippedRow,\n contactImportSkippedCsv,\n emptyContactImportResult,\n guessContactImportMapping,\n mapContactImportRow,\n mergeContactImportResults,\n} from '../model/crm-import'\nimport { useFirestore, useFirestoreCollection } from '@aglyn/tenant-feature-instance'\nimport { Typography } from '@mui/material'\nimport { collection, limit, query } from 'firebase/firestore'\nimport { useMemo } from 'react'\nimport { crmVisibleToClause, useCrmScope } from '../hooks/use-crm-scope'\nimport { contactImportTemplateCsv } from '../model/contacts-csv'\nimport {\n CsvImportButton,\n CsvImportDrawer,\n type CsvImportVocabulary,\n} from './csv-import-drawer'\n\nexport interface ContactImportDrawerProps {\n open: boolean\n onClose: () => void\n /**\n * The site the file is imported INTO — what the route captures 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 /**\n * The org document the shell passed, for the consent group's scope\n * tokens. Typed as the page prop it is forwarded from, so the contacts\n * list mounts the button with the value it already holds and no cast.\n */\n org?: ConsolePluginPageProps['org']\n}\n\n/**\n * The holder's live custom-field definitions, read only while the drawer\n * is open.\n *\n * A local hook rather than a shared one because the Fields section that\n * will own these definitions is landing beside this drawer; when it ships a\n * `useContactFieldDefinitions`, this is the read to replace with it. Scoped\n * by `visibleTo` the way the contacts listener is, because the rules prove\n * a scoped member's query per document and refuse an unfiltered one.\n *\n * Ordered in memory rather than by the query: `array-contains-any` with an\n * `orderBy` on another field needs a composite index the collection does\n * not have, and a holder's field list fits in one page.\n */\nfunction useImportFieldDefinitions(options: {\n orgId: string | null | undefined\n /** The reader's tokens, or `null` at the organization level — no clause. */\n visibleToTokens: readonly string[] | null\n enabled: boolean\n}): ContactFieldDefinition[] {\n const { orgId, visibleToTokens, enabled } = options\n const firestore = useFirestore()\n const { data } = useFirestoreCollection<ContactFieldDefinition & { $id: string }>(\n () =>\n enabled && orgId\n ? query(\n collection(firestore, 'orgs', orgId, CRM_COLLECTIONS.contactFields),\n ...crmVisibleToClause(visibleToTokens),\n limit(100),\n )\n : null,\n [firestore, orgId, visibleToTokens, enabled],\n { idField: '$id' },\n )\n return useMemo(\n () =>\n (data ?? [])\n .filter((field) => !!field.key && !field.retiredAt)\n .sort((a, b) => Number(a.order ?? 0) - Number(b.order ?? 0)),\n [data],\n )\n}\n\n/** The contact vocabulary, over the holder's custom fields. */\nfunction contactImportVocabulary(\n fields: readonly ContactFieldDefinition[],\n): CsvImportVocabulary<\n ContactImportField,\n ContactImportRawRow & Record<string, unknown>,\n ContactImportSkippedRow\n> {\n return {\n title: 'Import contacts from CSV',\n collection: 'contacts',\n help: pluginDocsHelp('contacts', { anchor: '#import-from-csv' }),\n sitePickerHelperText:\n 'The site these people are imported into — it decides which of your ' +\n \"sites may see them and whose marketing consent the file's consent \" +\n 'column records.',\n intro:\n 'A CSV with a header row. Match its columns to contact fields ' +\n 'below, check the preview, then import. A person already in your ' +\n 'contacts is updated rather than added twice. Up to ' +\n `${CONTACT_IMPORT_MAX_ROWS.toLocaleString()} rows per file — split a ` +\n 'larger one.',\n fields: CONTACT_IMPORT_FIELDS,\n fieldLabels: CONTACT_IMPORT_FIELD_LABELS,\n customFields: fields,\n requiredField: 'email',\n requiredWarning:\n 'Choose which column holds the email address. It is the one field ' +\n 'every row needs.',\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 ' +\n 'after the import.',\n guessMapping: (columns) => guessContactImportMapping(columns, fields),\n mapRow: (cells, mapping) =>\n mapContactImportRow(cells, mapping) as ContactImportRawRow & Record<string, unknown>,\n route: '/api/crm/contacts-import',\n maxRows: CONTACT_IMPORT_MAX_ROWS,\n chunkSize: CONTACT_IMPORT_CHUNK_SIZE,\n previewRows: CONTACT_IMPORT_PREVIEW_ROWS,\n emptyResult: emptyContactImportResult,\n mergeResults: (total, chunk, offset) =>\n mergeContactImportResults(\n total as ContactImportChunkResult,\n chunk as ContactImportChunkResult,\n offset,\n ),\n skipLabels: CONTACT_IMPORT_SKIP_LABELS,\n skippedCsv: contactImportSkippedCsv,\n skippedFileName: 'skipped-contacts.csv',\n templateCsv: () => contactImportTemplateCsv(fields),\n templateFileName: 'contacts-template.csv',\n resultExtras: (result) => {\n const created = (result as ContactImportChunkResult).companiesCreated\n return created ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`${created.toLocaleString()} new ${\n created === 1 ? 'company' : 'companies'\n } created from the company column.`}\n </Typography>\n ) : null\n },\n }\n}\n\nexport function ContactImportDrawer(props: ContactImportDrawerProps) {\n const { open, onClose, hostId, org } = props\n // The org root and the reader's tokens from the one scope hook (AGL-2614);\n // at the organization level no clause, and the site every row is captured\n // under is the one the drawer's picker names (AGL-2630).\n const { orgId, visibleTo: visibleToTokens } = useCrmScope({ hostId, org })\n const fields = useImportFieldDefinitions({\n orgId,\n visibleToTokens,\n enabled: open,\n })\n const vocabulary = useMemo(() => contactImportVocabulary(fields), [fields])\n return (\n <CsvImportDrawer\n open={open}\n onClose={onClose}\n hostId={hostId}\n vocabulary={vocabulary}\n />\n )\n}\nContactImportDrawer.displayName = 'ContactImportDrawer'\n\n/**\n * The \"Import CSV\" action on the contacts list, with the drawer it opens —\n * mounted only once opened, so the list pays nothing for it until then.\n */\nexport function ContactImportButton(props: {\n /** The site the list is read under, or `null` at the organization level. */\n hostId: string | null\n org?: ConsolePluginPageProps['org']\n}) {\n const { hostId, org } = props\n return (\n <CsvImportButton>\n {(open, onClose) => (\n <ContactImportDrawer open={open} onClose={onClose} hostId={hostId} org={org} />\n )}\n </CsvImportButton>\n )\n}\nContactImportButton.displayName = 'ContactImportButton'\n\nexport default ContactImportDrawer\n"],"names":["CRM_COLLECTIONS","normalizeContactEmail","pluginDocsHelp","CONTACT_IMPORT_CHUNK_SIZE","CONTACT_IMPORT_FIELD_LABELS","CONTACT_IMPORT_FIELDS","CONTACT_IMPORT_MAX_ROWS","CONTACT_IMPORT_PREVIEW_ROWS","CONTACT_IMPORT_SKIP_LABELS","contactImportSkippedCsv","emptyContactImportResult","guessContactImportMapping","mapContactImportRow","mergeContactImportResults","useFirestore","useFirestoreCollection","Typography","collection","limit","query","useMemo","crmVisibleToClause","useCrmScope","contactImportTemplateCsv","CsvImportButton","CsvImportDrawer","useImportFieldDefinitions","options","orgId","visibleToTokens","enabled","firestore","data","contactFields","idField","filter","field","key","retiredAt","sort","a","b","Number","order","contactImportVocabulary","fields","title","help","anchor","sitePickerHelperText","intro","toLocaleString","fieldLabels","customFields","requiredField","requiredWarning","unusable","cell","unusableNotice","count","total","guessMapping","columns","mapRow","cells","mapping","route","maxRows","chunkSize","previewRows","emptyResult","mergeResults","chunk","offset","skipLabels","skippedCsv","skippedFileName","templateCsv","templateFileName","resultExtras","result","created","companiesCreated","variant","color","ContactImportDrawer","props","open","onClose","hostId","org","visibleTo","vocabulary","displayName","ContactImportButton"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA;;;;;;;;;;CAUC,GAED,SAGEA,eAAe,EACfC,qBAAqB,EACrBC,cAAc,QACT,eAAc;AACrB,SACEC,yBAAyB,EACzBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,uBAAuB,EACvBC,2BAA2B,EAC3BC,0BAA0B,EAK1BC,uBAAuB,EACvBC,wBAAwB,EACxBC,yBAAyB,EACzBC,mBAAmB,EACnBC,yBAAyB,QACpB,yBAAqB;AAC5B,SAASC,YAAY,EAAEC,sBAAsB,QAAQ,iCAAgC;AACrF,SAASC,UAAU,QAAQ,gBAAe;AAC1C,SAASC,UAAU,EAAEC,KAAK,EAAEC,KAAK,QAAQ,qBAAoB;AAC7D,SAASC,OAAO,QAAQ,QAAO;AAC/B,SAASC,kBAAkB,EAAEC,WAAW,QAAQ,4BAAwB;AACxE,SAASC,wBAAwB,QAAQ,2BAAuB;AAChE,SACEC,eAAe,EACfC,eAAe,QAEV,yBAAqB;AAoB5B;;;;;;;;;;;;;CAaC,GACD,SAASC,0BAA0BC,OAKlC;IACC,MAAM,EAAEC,KAAK,EAAEC,eAAe,EAAEC,OAAO,EAAE,GAAGH;IAC5C,MAAMI,YAAYjB;IAClB,MAAM,EAAEkB,IAAI,EAAE,GAAGjB,uBACf,IACEe,WAAWF,QACPT,MACEF,WAAWc,WAAW,QAAQH,OAAO5B,gBAAgBiC,aAAa,MAC/DZ,mBAAmBQ,kBACtBX,MAAM,QAER,MACN;QAACa;QAAWH;QAAOC;QAAiBC;KAAQ,EAC5C;QAAEI,SAAS;IAAM;IAEnB,OAAOd,QACL,IACE,CAACY,eAAAA,OAAQ,EAAE,EACRG,MAAM,CAAC,CAACC,QAAU,CAAC,CAACA,MAAMC,GAAG,IAAI,CAACD,MAAME,SAAS,EACjDC,IAAI,CAAC,CAACC,GAAGC;gBAAaD,UAAuBC;mBAA9BC,QAAOF,WAAAA,EAAEG,KAAK,YAAPH,WAAW,KAAKE,QAAOD,WAAAA,EAAEE,KAAK,YAAPF,WAAW;YAC7D;QAACT;KAAK;AAEV;AAEA,6DAA6D,GAC7D,SAASY,wBACPC,MAAyC;IAMzC,OAAO;QACLC,OAAO;QACP7B,YAAY;QACZ8B,MAAM7C,eAAe,YAAY;YAAE8C,QAAQ;QAAmB;QAC9DC,sBACE,wEACA,uEACA;QACFC,OACE,kEACA,qEACA,wDACA,GAAG5C,wBAAwB6C,cAAc,GAAG,yBAAyB,CAAC,GACtE;QACFN,QAAQxC;QACR+C,aAAahD;QACbiD,cAAcR;QACdS,eAAe;QACfC,iBACE,sEACA;QACFC,UAAU,CAACC,OAAS,CAACxD,sBAAsBwD;QAC3CC,gBAAgB,CAACC,OAAOC,QACtB,GAAGD,MAAMR,cAAc,GAAG,IAAI,EAAES,MAAMT,cAAc,GAAG,cAAc,CAAC,GACtE,qEACA;QACFU,cAAc,CAACC,UAAYnD,0BAA0BmD,SAASjB;QAC9DkB,QAAQ,CAACC,OAAOC,UACdrD,oBAAoBoD,OAAOC;QAC7BC,OAAO;QACPC,SAAS7D;QACT8D,WAAWjE;QACXkE,aAAa9D;QACb+D,aAAa5D;QACb6D,cAAc,CAACX,OAAOY,OAAOC,SAC3B5D,0BACE+C,OACAY,OACAC;QAEJC,YAAYlE;QACZmE,YAAYlE;QACZmE,iBAAiB;QACjBC,aAAa,IAAMtD,yBAAyBsB;QAC5CiC,kBAAkB;QAClBC,cAAc,CAACC;YACb,MAAMC,UAAU,AAACD,OAAoCE,gBAAgB;YACrE,OAAOD,wBACL,KAACjE;gBAAWmE,SAAQ;gBAAQC,OAAM;0BAC/B,GAAGH,QAAQ9B,cAAc,GAAG,KAAK,EAChC8B,YAAY,IAAI,YAAY,YAC7B,iCAAiC,CAAC;iBAEnC;QACN;IACF;AACF;AAEA,OAAO,SAASI,oBAAoBC,KAA+B;IACjE,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEC,MAAM,EAAEC,GAAG,EAAE,GAAGJ;IACvC,2EAA2E;IAC3E,0EAA0E;IAC1E,yDAAyD;IACzD,MAAM,EAAE1D,KAAK,EAAE+D,WAAW9D,eAAe,EAAE,GAAGP,YAAY;QAAEmE;QAAQC;IAAI;IACxE,MAAM7C,SAASnB,0BAA0B;QACvCE;QACAC;QACAC,SAASyD;IACX;IACA,MAAMK,aAAaxE,QAAQ,IAAMwB,wBAAwBC,SAAS;QAACA;KAAO;IAC1E,qBACE,KAACpB;QACC8D,MAAMA;QACNC,SAASA;QACTC,QAAQA;QACRG,YAAYA;;AAGlB;AACAP,oBAAoBQ,WAAW,GAAG;AAElC;;;CAGC,GACD,OAAO,SAASC,oBAAoBR,KAInC;IACC,MAAM,EAAEG,MAAM,EAAEC,GAAG,EAAE,GAAGJ;IACxB,qBACE,KAAC9D;kBACE,CAAC+D,MAAMC,wBACN,KAACH;gBAAoBE,MAAMA;gBAAMC,SAASA;gBAASC,QAAQA;gBAAQC,KAAKA;;;AAIhF;AACAI,oBAAoBD,WAAW,GAAG;AAElC,eAAeR,oBAAmB"}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { CrmExportResource } from '../model/crm-csv';
|
|
2
|
-
export interface CrmExportAllButtonProps {
|
|
3
|
-
/** Which table to take a complete copy of. */
|
|
4
|
-
resource: CrmExportResource;
|
|
5
|
-
/** The organization whose records these are; null holds the button. */
|
|
6
|
-
orgId: string | null;
|
|
7
|
-
/**
|
|
8
|
-
* The site being read as.
|
|
9
|
-
*
|
|
10
|
-
* Required for contacts — the file is written through one holder's facet
|
|
11
|
-
* and a facet is per site — and for a scoped reader's leads. Null at the
|
|
12
|
-
* organization level, where an org-wide member takes every site's leads
|
|
13
|
-
* in one file.
|
|
14
|
-
*/
|
|
15
|
-
hostId: string | null;
|
|
16
|
-
disabled?: boolean;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* EXPORT ALL — the whole collection, not the loaded window (AGL-2662).
|
|
20
|
-
*
|
|
21
|
-
* Beside "Export CSV", which writes the rows on screen. The two are
|
|
22
|
-
* deliberately both offered and deliberately named apart: a selection's
|
|
23
|
-
* file is what somebody just picked, and this is the audience.
|
|
24
|
-
*
|
|
25
|
-
* ## The response is checked, not trusted
|
|
26
|
-
*
|
|
27
|
-
* The route reports a `count()` aggregate in `X-Aglyn-Export-Rows`, taken
|
|
28
|
-
* before its first page. A stream that dies halfway produces a perfectly
|
|
29
|
-
* well-formed shorter file, and nothing about the bytes says it is short —
|
|
30
|
-
* which is exactly how the window-sized export stayed invisible for as long
|
|
31
|
-
* as it did. A body with fewer rows than promised is REFUSED rather than
|
|
32
|
-
* saved, because a partial audience saved under a confident name is worse
|
|
33
|
-
* than no file.
|
|
34
|
-
*/
|
|
35
|
-
export declare function CrmExportAllButton(props: CrmExportAllButtonProps): import("react").JSX.Element;
|
|
36
|
-
export declare namespace CrmExportAllButton {
|
|
37
|
-
var displayName: string;
|
|
38
|
-
}
|
|
39
|
-
export default CrmExportAllButton;
|
|
@@ -1,98 +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
|
-
import { countCsvDataRows } from "@aglyn/aglyn";
|
|
19
|
-
import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
|
|
20
|
-
import { useUser } from "@aglyn/tenant-feature-instance";
|
|
21
|
-
import { Button } from "@mui/material";
|
|
22
|
-
import { useSnackbar } from "notistack";
|
|
23
|
-
import { useCallback, useState } from "react";
|
|
24
|
-
import { downloadTextFile } from "../model/contacts-csv.js";
|
|
25
|
-
/** The header the export route promises its row count in. */ const EXPORT_ROWS_HEADER = 'X-Aglyn-Export-Rows';
|
|
26
|
-
/**
|
|
27
|
-
* EXPORT ALL — the whole collection, not the loaded window (AGL-2662).
|
|
28
|
-
*
|
|
29
|
-
* Beside "Export CSV", which writes the rows on screen. The two are
|
|
30
|
-
* deliberately both offered and deliberately named apart: a selection's
|
|
31
|
-
* file is what somebody just picked, and this is the audience.
|
|
32
|
-
*
|
|
33
|
-
* ## The response is checked, not trusted
|
|
34
|
-
*
|
|
35
|
-
* The route reports a `count()` aggregate in `X-Aglyn-Export-Rows`, taken
|
|
36
|
-
* before its first page. A stream that dies halfway produces a perfectly
|
|
37
|
-
* well-formed shorter file, and nothing about the bytes says it is short —
|
|
38
|
-
* which is exactly how the window-sized export stayed invisible for as long
|
|
39
|
-
* as it did. A body with fewer rows than promised is REFUSED rather than
|
|
40
|
-
* saved, because a partial audience saved under a confident name is worse
|
|
41
|
-
* than no file.
|
|
42
|
-
*/ export function CrmExportAllButton(props) {
|
|
43
|
-
const { resource, orgId, hostId, disabled } = props;
|
|
44
|
-
const { data: user } = useUser();
|
|
45
|
-
const { enqueueSnackbar } = useSnackbar();
|
|
46
|
-
const [busy, setBusy] = useState(false);
|
|
47
|
-
const handleExport = useCallback(async ()=>{
|
|
48
|
-
if (!orgId || busy) return;
|
|
49
|
-
setBusy(true);
|
|
50
|
-
try {
|
|
51
|
-
var _response_headers_get;
|
|
52
|
-
const params = new URLSearchParams({
|
|
53
|
-
orgId,
|
|
54
|
-
resource
|
|
55
|
-
});
|
|
56
|
-
if (hostId) params.set('hostId', hostId);
|
|
57
|
-
const response = await authorizedFetch(user, `/api/crm/export?${params.toString()}`);
|
|
58
|
-
if (!response.ok) {
|
|
59
|
-
var _ref;
|
|
60
|
-
const failure = await response.json().catch(()=>({}));
|
|
61
|
-
throw new Error((_ref = failure == null ? void 0 : failure.error) != null ? _ref : 'Export failed');
|
|
62
|
-
}
|
|
63
|
-
const text = await response.text();
|
|
64
|
-
const promised = Number((_response_headers_get = response.headers.get(EXPORT_ROWS_HEADER)) != null ? _response_headers_get : '');
|
|
65
|
-
const received = countCsvDataRows(text);
|
|
66
|
-
if (Number.isFinite(promised) && received < promised) {
|
|
67
|
-
enqueueSnackbar(`Export incomplete — ${received} of ${promised} rows arrived. ` + 'Nothing was saved; try again.', {
|
|
68
|
-
variant: 'error'
|
|
69
|
-
});
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
downloadTextFile(`${resource}.csv`, 'text/csv', text);
|
|
73
|
-
} catch (error) {
|
|
74
|
-
enqueueSnackbar(error instanceof Error ? error.message : 'Export failed', {
|
|
75
|
-
variant: 'error'
|
|
76
|
-
});
|
|
77
|
-
} finally{
|
|
78
|
-
setBusy(false);
|
|
79
|
-
}
|
|
80
|
-
}, [
|
|
81
|
-
orgId,
|
|
82
|
-
hostId,
|
|
83
|
-
resource,
|
|
84
|
-
user,
|
|
85
|
-
busy,
|
|
86
|
-
enqueueSnackbar
|
|
87
|
-
]);
|
|
88
|
-
return /*#__PURE__*/ _jsx(Button, {
|
|
89
|
-
size: "small",
|
|
90
|
-
disabled: disabled || busy || !orgId,
|
|
91
|
-
onClick: ()=>void handleExport(),
|
|
92
|
-
children: busy ? 'Exporting…' : 'Export all…'
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
CrmExportAllButton.displayName = 'CrmExportAllButton';
|
|
96
|
-
export default CrmExportAllButton;
|
|
97
|
-
|
|
98
|
-
//# sourceMappingURL=crm-export-all-button.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/crm-export-all-button.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 countCsvDataRows,\n} from '@aglyn/aglyn'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { Button } from '@mui/material'\nimport { useSnackbar } from 'notistack'\nimport { useCallback, useState } from 'react'\nimport { downloadTextFile } from '../model/contacts-csv'\nimport type { CrmExportResource } from '../model/crm-csv'\n\n/** The header the export route promises its row count in. */\nconst EXPORT_ROWS_HEADER = 'X-Aglyn-Export-Rows'\n\nexport interface CrmExportAllButtonProps {\n /** Which table to take a complete copy of. */\n resource: CrmExportResource\n /** The organization whose records these are; null holds the button. */\n orgId: string | null\n /**\n * The site being read as.\n *\n * Required for contacts — the file is written through one holder's facet\n * and a facet is per site — and for a scoped reader's leads. Null at the\n * organization level, where an org-wide member takes every site's leads\n * in one file.\n */\n hostId: string | null\n disabled?: boolean\n}\n\n/**\n * EXPORT ALL — the whole collection, not the loaded window (AGL-2662).\n *\n * Beside \"Export CSV\", which writes the rows on screen. The two are\n * deliberately both offered and deliberately named apart: a selection's\n * file is what somebody just picked, and this is the audience.\n *\n * ## The response is checked, not trusted\n *\n * The route reports a `count()` aggregate in `X-Aglyn-Export-Rows`, taken\n * before its first page. A stream that dies halfway produces a perfectly\n * well-formed shorter file, and nothing about the bytes says it is short —\n * which is exactly how the window-sized export stayed invisible for as long\n * as it did. A body with fewer rows than promised is REFUSED rather than\n * saved, because a partial audience saved under a confident name is worse\n * than no file.\n */\nexport function CrmExportAllButton(props: CrmExportAllButtonProps) {\n const { resource, orgId, hostId, disabled } = props\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const [busy, setBusy] = useState(false)\n\n const handleExport = useCallback(async () => {\n if (!orgId || busy) return\n setBusy(true)\n try {\n const params = new URLSearchParams({ orgId, resource })\n if (hostId) params.set('hostId', hostId)\n const response = await authorizedFetch(\n user,\n `/api/crm/export?${params.toString()}`,\n )\n if (!response.ok) {\n const failure = await response.json().catch(() => ({}))\n throw new Error(failure?.error ?? 'Export failed')\n }\n const text = await response.text()\n const promised = Number(response.headers.get(EXPORT_ROWS_HEADER) ?? '')\n const received = countCsvDataRows(text)\n if (Number.isFinite(promised) && received < promised) {\n enqueueSnackbar(\n `Export incomplete — ${received} of ${promised} rows arrived. ` +\n 'Nothing was saved; try again.',\n { variant: 'error' },\n )\n return\n }\n downloadTextFile(`${resource}.csv`, 'text/csv', text)\n } catch (error) {\n enqueueSnackbar(\n error instanceof Error ? error.message : 'Export failed',\n { variant: 'error' },\n )\n } finally {\n setBusy(false)\n }\n }, [orgId, hostId, resource, user, busy, enqueueSnackbar])\n\n return (\n <Button\n size=\"small\"\n disabled={disabled || busy || !orgId}\n onClick={() => void handleExport()}\n >\n {busy ? 'Exporting…' : 'Export all…'}\n </Button>\n )\n}\nCrmExportAllButton.displayName = 'CrmExportAllButton'\n\nexport default CrmExportAllButton\n"],"names":["countCsvDataRows","authorizedFetch","useUser","Button","useSnackbar","useCallback","useState","downloadTextFile","EXPORT_ROWS_HEADER","CrmExportAllButton","props","resource","orgId","hostId","disabled","data","user","enqueueSnackbar","busy","setBusy","handleExport","response","params","URLSearchParams","set","toString","ok","failure","json","catch","Error","error","text","promised","Number","headers","get","received","isFinite","variant","message","size","onClick","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA,SACEA,gBAAgB,QACX,eAAc;AACrB,SAASC,eAAe,QAAQ,2CAA0C;AAC1E,SAASC,OAAO,QAAQ,iCAAgC;AACxD,SAASC,MAAM,QAAQ,gBAAe;AACtC,SAASC,WAAW,QAAQ,YAAW;AACvC,SAASC,WAAW,EAAEC,QAAQ,QAAQ,QAAO;AAC7C,SAASC,gBAAgB,QAAQ,2BAAuB;AAGxD,2DAA2D,GAC3D,MAAMC,qBAAqB;AAmB3B;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,SAASC,mBAAmBC,KAA8B;IAC/D,MAAM,EAAEC,QAAQ,EAAEC,KAAK,EAAEC,MAAM,EAAEC,QAAQ,EAAE,GAAGJ;IAC9C,MAAM,EAAEK,MAAMC,IAAI,EAAE,GAAGd;IACvB,MAAM,EAAEe,eAAe,EAAE,GAAGb;IAC5B,MAAM,CAACc,MAAMC,QAAQ,GAAGb,SAAS;IAEjC,MAAMc,eAAef,YAAY;QAC/B,IAAI,CAACO,SAASM,MAAM;QACpBC,QAAQ;QACR,IAAI;gBAYsBE;YAXxB,MAAMC,SAAS,IAAIC,gBAAgB;gBAAEX;gBAAOD;YAAS;YACrD,IAAIE,QAAQS,OAAOE,GAAG,CAAC,UAAUX;YACjC,MAAMQ,WAAW,MAAMpB,gBACrBe,MACA,CAAC,gBAAgB,EAAEM,OAAOG,QAAQ,IAAI;YAExC,IAAI,CAACJ,SAASK,EAAE,EAAE;;gBAChB,MAAMC,UAAU,MAAMN,SAASO,IAAI,GAAGC,KAAK,CAAC,IAAO,CAAA,CAAC,CAAA;gBACpD,MAAM,IAAIC,cAAMH,2BAAAA,QAASI,KAAK,mBAAI;YACpC;YACA,MAAMC,OAAO,MAAMX,SAASW,IAAI;YAChC,MAAMC,WAAWC,QAAOb,wBAAAA,SAASc,OAAO,CAACC,GAAG,CAAC5B,+BAArBa,wBAA4C;YACpE,MAAMgB,WAAWrC,iBAAiBgC;YAClC,IAAIE,OAAOI,QAAQ,CAACL,aAAaI,WAAWJ,UAAU;gBACpDhB,gBACE,CAAC,oBAAoB,EAAEoB,SAAS,IAAI,EAAEJ,SAAS,eAAe,CAAC,GAC7D,iCACF;oBAAEM,SAAS;gBAAQ;gBAErB;YACF;YACAhC,iBAAiB,GAAGI,SAAS,IAAI,CAAC,EAAE,YAAYqB;QAClD,EAAE,OAAOD,OAAO;YACdd,gBACEc,iBAAiBD,QAAQC,MAAMS,OAAO,GAAG,iBACzC;gBAAED,SAAS;YAAQ;QAEvB,SAAU;YACRpB,QAAQ;QACV;IACF,GAAG;QAACP;QAAOC;QAAQF;QAAUK;QAAME;QAAMD;KAAgB;IAEzD,qBACE,KAACd;QACCsC,MAAK;QACL3B,UAAUA,YAAYI,QAAQ,CAACN;QAC/B8B,SAAS,IAAM,KAAKtB;kBAEnBF,OAAO,eAAe;;AAG7B;AACAT,mBAAmBkC,WAAW,GAAG;AAEjC,eAAelC,mBAAkB"}
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IMPORTING A CSV INTO A CRM COLLECTION — the screen, for whichever
|
|
3
|
-
* collection (AGL-2602, shared since AGL-2621).
|
|
4
|
-
*
|
|
5
|
-
* The contact import settled the walk from a file on disk to a result the
|
|
6
|
-
* operator can act on: choose the file, read what is in it, match its
|
|
7
|
-
* columns to fields with the first row beside each, preview the ten rows
|
|
8
|
-
* the mapping produces, run it in bounded requests with a progress bar,
|
|
9
|
-
* and report what was added, updated and skipped with the skipped rows as
|
|
10
|
-
* a file to fix. A companies file walks the same path with a different
|
|
11
|
-
* vocabulary, so the walk lives here once and each collection hands in a
|
|
12
|
-
* {@link CsvImportVocabulary}: its fields and their labels, the one field
|
|
13
|
-
* every row needs, its route, its tally, its template.
|
|
14
|
-
*
|
|
15
|
-
* ## The file is read in the browser, and judged on the server
|
|
16
|
-
*
|
|
17
|
-
* `parseCsv` — the same parser the list import and the dataset import run
|
|
18
|
-
* — turns the file into cells here, so the operator can map and preview
|
|
19
|
-
* without a round trip and without uploading a file they may still decide
|
|
20
|
-
* not to import. Nothing is VALIDATED here beyond counting the rows whose
|
|
21
|
-
* required cell is unusable, and that count is a courtesy: every row is
|
|
22
|
-
* judged by the route, through the normalizers every other door uses, and
|
|
23
|
-
* the numbers on the result panel are the server's.
|
|
24
|
-
*
|
|
25
|
-
* ## Bounded requests, and closing stops them
|
|
26
|
-
*
|
|
27
|
-
* A chunk per request, as many requests as the file needs, and a progress
|
|
28
|
-
* bar between them. Closing the drawer mid-run stops the loop after the
|
|
29
|
-
* request in flight; the rows already written stay written and the result
|
|
30
|
-
* panel says how far it got. There is no durable job to resume — an import
|
|
31
|
-
* is idempotent by construction (the door dedupes on the address, or the
|
|
32
|
-
* domain and the name), so running the same file again finishes what a
|
|
33
|
-
* closed drawer left, reporting the earlier rows as merged.
|
|
34
|
-
*/
|
|
35
|
-
import { type ImportChunkResult, type ImportSkippedRow } from '@aglyn/aglyn';
|
|
36
|
-
import { HelpTip } from '@aglyn/shared-ui-jsx';
|
|
37
|
-
import { type ComponentProps, type ReactNode } from 'react';
|
|
38
|
-
/** A column's target: a standard field, or a custom one as `custom:<key>`. */
|
|
39
|
-
export type CsvImportTarget<F extends string> = F | `custom:${string}`;
|
|
40
|
-
/** Column index → target. A column absent from the map is not imported. */
|
|
41
|
-
export type CsvImportMapping<F extends string> = Record<number, CsvImportTarget<F>>;
|
|
42
|
-
/** A custom field a column may be mapped to, when the collection has any. */
|
|
43
|
-
export interface CsvImportCustomField {
|
|
44
|
-
key: string;
|
|
45
|
-
label: string;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Everything one collection's import says for itself. Pure values and pure
|
|
49
|
-
* functions, so a vocabulary is built once outside React and handed in.
|
|
50
|
-
*/
|
|
51
|
-
export interface CsvImportVocabulary<F extends string, R extends Record<string, unknown>, S extends ImportSkippedRow<string>> {
|
|
52
|
-
/** The drawer's title — "Import contacts from CSV". */
|
|
53
|
-
title: string;
|
|
54
|
-
/**
|
|
55
|
-
* What the import is called where the `importMapping` zone names it —
|
|
56
|
-
* `contacts`, `companies`, `deals`, `leads` (AGL-2917). Absent, the drawer
|
|
57
|
-
* hosts no zone.
|
|
58
|
-
*/
|
|
59
|
-
collection?: string;
|
|
60
|
-
help: ComponentProps<typeof HelpTip>;
|
|
61
|
-
/**
|
|
62
|
-
* What the site picker's answer decides, said under it at the
|
|
63
|
-
* organization level (AGL-2630). Absent, the picker's own sentence.
|
|
64
|
-
*/
|
|
65
|
-
sitePickerHelperText?: string;
|
|
66
|
-
/** The paragraph under the title. */
|
|
67
|
-
intro: string;
|
|
68
|
-
/** The standard targets, in the order the mapping menu lists them. */
|
|
69
|
-
fields: readonly F[];
|
|
70
|
-
fieldLabels: Record<F, string>;
|
|
71
|
-
/** Custom targets, offered after the standard ones; none for most collections. */
|
|
72
|
-
customFields?: readonly CsvImportCustomField[];
|
|
73
|
-
/** The one field every row needs, and what the drawer says when it is unmapped. */
|
|
74
|
-
requiredField: F;
|
|
75
|
-
requiredWarning: string;
|
|
76
|
-
/**
|
|
77
|
-
* Whether a required cell is one the server would refuse — the courtesy
|
|
78
|
-
* count the preview shows. Absent, only a blank cell counts.
|
|
79
|
-
*/
|
|
80
|
-
unusable?: (cell: string) => boolean;
|
|
81
|
-
/** The preview's sentence about them. */
|
|
82
|
-
unusableNotice: (count: number, total: number) => string;
|
|
83
|
-
guessMapping: (columns: readonly string[]) => CsvImportMapping<F>;
|
|
84
|
-
mapRow: (cells: readonly string[], mapping: CsvImportMapping<F>) => R;
|
|
85
|
-
/** The browser-side URL of the route one chunk is posted to. */
|
|
86
|
-
route: string;
|
|
87
|
-
maxRows: number;
|
|
88
|
-
chunkSize: number;
|
|
89
|
-
previewRows: number;
|
|
90
|
-
emptyResult: () => ImportChunkResult<S>;
|
|
91
|
-
mergeResults: (total: ImportChunkResult<S>, chunk: ImportChunkResult<S>, offset: number) => ImportChunkResult<S>;
|
|
92
|
-
skipLabels: Record<S['reason'], string>;
|
|
93
|
-
skippedCsv: (columns: readonly string[], entries: readonly {
|
|
94
|
-
cells: readonly string[];
|
|
95
|
-
reason: S['reason'];
|
|
96
|
-
}[]) => string;
|
|
97
|
-
skippedFileName: string;
|
|
98
|
-
/** The export's header over no rows. */
|
|
99
|
-
templateCsv: () => string;
|
|
100
|
-
templateFileName: string;
|
|
101
|
-
/** The result panel's collection-specific lines, when there are any. */
|
|
102
|
-
resultExtras?: (result: ImportChunkResult<S>) => ReactNode;
|
|
103
|
-
/**
|
|
104
|
-
* A collection-specific warning about the mapped file, shown above the
|
|
105
|
-
* preview before anything is sent — a value the server will refuse that
|
|
106
|
-
* the operator can fix first. Given every row as `mapRow` reads it;
|
|
107
|
-
* answers nothing when the file is fine.
|
|
108
|
-
*/
|
|
109
|
-
rowsNotice?: (rows: readonly R[]) => ReactNode;
|
|
110
|
-
}
|
|
111
|
-
export interface CsvImportDrawerProps<F extends string, R extends Record<string, unknown>, S extends ImportSkippedRow<string>> {
|
|
112
|
-
open: boolean;
|
|
113
|
-
onClose: () => void;
|
|
114
|
-
/**
|
|
115
|
-
* The site the file is imported INTO — what the route files every row
|
|
116
|
-
* under — or `null` at the organization level (AGL-2630), where the
|
|
117
|
-
* drawer asks which site with a picker and holds the import until one is
|
|
118
|
-
* named.
|
|
119
|
-
*/
|
|
120
|
-
hostId: string | null;
|
|
121
|
-
vocabulary: CsvImportVocabulary<F, R, S>;
|
|
122
|
-
}
|
|
123
|
-
export declare function CsvImportDrawer<F extends string, R extends Record<string, unknown>, S extends ImportSkippedRow<string>>(props: CsvImportDrawerProps<F, R, S>): import("react").JSX.Element;
|
|
124
|
-
export declare namespace CsvImportDrawer {
|
|
125
|
-
var displayName: string;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* An "Import CSV" button that mounts its drawer only once it has been
|
|
129
|
-
* opened, so the list pays nothing — no hooks, no listeners — for a
|
|
130
|
-
* feature the operator has not reached for.
|
|
131
|
-
*/
|
|
132
|
-
export declare function CsvImportButton(props: {
|
|
133
|
-
label?: string;
|
|
134
|
-
children: (open: boolean, onClose: () => void) => ReactNode;
|
|
135
|
-
}): import("react").JSX.Element;
|
|
136
|
-
export declare namespace CsvImportButton {
|
|
137
|
-
var displayName: string;
|
|
138
|
-
}
|
|
139
|
-
export default CsvImportDrawer;
|