@aglyn/plugins-crm 1.0.0-beta.143
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/LICENSE +201 -0
- package/README.md +7 -0
- package/package.json +57 -0
- package/src/index.d.ts +21 -0
- package/src/index.js +29 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/activity-list.d.ts +98 -0
- package/src/lib/components/activity-list.js +321 -0
- package/src/lib/components/activity-list.js.map +1 -0
- package/src/lib/components/activity-queries.d.ts +117 -0
- package/src/lib/components/activity-queries.js +198 -0
- package/src/lib/components/activity-queries.js.map +1 -0
- package/src/lib/components/add-to-list-button.d.ts +25 -0
- package/src/lib/components/add-to-list-button.js +64 -0
- package/src/lib/components/add-to-list-button.js.map +1 -0
- package/src/lib/components/add-to-list-dialog.d.ts +24 -0
- package/src/lib/components/add-to-list-dialog.js +327 -0
- package/src/lib/components/add-to-list-dialog.js.map +1 -0
- package/src/lib/components/assignment-rule-drawer.d.ts +43 -0
- package/src/lib/components/assignment-rule-drawer.js +293 -0
- package/src/lib/components/assignment-rule-drawer.js.map +1 -0
- package/src/lib/components/companies-bulk-bar.d.ts +29 -0
- package/src/lib/components/companies-bulk-bar.js +274 -0
- package/src/lib/components/companies-bulk-bar.js.map +1 -0
- package/src/lib/components/companies-section.d.ts +54 -0
- package/src/lib/components/companies-section.js +522 -0
- package/src/lib/components/companies-section.js.map +1 -0
- package/src/lib/components/company-contacts-card.d.ts +49 -0
- package/src/lib/components/company-contacts-card.js +435 -0
- package/src/lib/components/company-contacts-card.js.map +1 -0
- package/src/lib/components/company-deals-card.d.ts +20 -0
- package/src/lib/components/company-deals-card.js +38 -0
- package/src/lib/components/company-deals-card.js.map +1 -0
- package/src/lib/components/company-detail-page.d.ts +20 -0
- package/src/lib/components/company-detail-page.js +165 -0
- package/src/lib/components/company-detail-page.js.map +1 -0
- package/src/lib/components/company-edit-drawer.d.ts +65 -0
- package/src/lib/components/company-edit-drawer.js +433 -0
- package/src/lib/components/company-edit-drawer.js.map +1 -0
- package/src/lib/components/company-import-drawer.d.ts +42 -0
- package/src/lib/components/company-import-drawer.js +99 -0
- package/src/lib/components/company-import-drawer.js.map +1 -0
- package/src/lib/components/company-picker.d.ts +127 -0
- package/src/lib/components/company-picker.js +323 -0
- package/src/lib/components/company-picker.js.map +1 -0
- package/src/lib/components/company-properties-card.d.ts +47 -0
- package/src/lib/components/company-properties-card.js +289 -0
- package/src/lib/components/company-properties-card.js.map +1 -0
- package/src/lib/components/contact-address-fields.d.ts +29 -0
- package/src/lib/components/contact-address-fields.js +149 -0
- package/src/lib/components/contact-address-fields.js.map +1 -0
- package/src/lib/components/contact-associations-card.d.ts +72 -0
- package/src/lib/components/contact-associations-card.js +296 -0
- package/src/lib/components/contact-associations-card.js.map +1 -0
- package/src/lib/components/contact-custom-columns.d.ts +38 -0
- package/src/lib/components/contact-custom-columns.js +102 -0
- package/src/lib/components/contact-custom-columns.js.map +1 -0
- package/src/lib/components/contact-custom-fields-card.d.ts +39 -0
- package/src/lib/components/contact-custom-fields-card.js +204 -0
- package/src/lib/components/contact-custom-fields-card.js.map +1 -0
- package/src/lib/components/contact-deals-card.d.ts +20 -0
- package/src/lib/components/contact-deals-card.js +38 -0
- package/src/lib/components/contact-deals-card.js.map +1 -0
- package/src/lib/components/contact-detail-page.d.ts +46 -0
- package/src/lib/components/contact-detail-page.js +535 -0
- package/src/lib/components/contact-detail-page.js.map +1 -0
- package/src/lib/components/contact-duplicates-card.d.ts +42 -0
- package/src/lib/components/contact-duplicates-card.js +167 -0
- package/src/lib/components/contact-duplicates-card.js.map +1 -0
- package/src/lib/components/contact-field-drawer.d.ts +64 -0
- package/src/lib/components/contact-field-drawer.js +251 -0
- package/src/lib/components/contact-field-drawer.js.map +1 -0
- package/src/lib/components/contact-import-drawer.d.ts +46 -0
- package/src/lib/components/contact-import-drawer.js +149 -0
- package/src/lib/components/contact-import-drawer.js.map +1 -0
- package/src/lib/components/contact-known-by-card.d.ts +39 -0
- package/src/lib/components/contact-known-by-card.js +142 -0
- package/src/lib/components/contact-known-by-card.js.map +1 -0
- package/src/lib/components/contact-list-columns.d.ts +53 -0
- package/src/lib/components/contact-list-columns.js +288 -0
- package/src/lib/components/contact-list-columns.js.map +1 -0
- package/src/lib/components/contact-merge-dialog.d.ts +79 -0
- package/src/lib/components/contact-merge-dialog.js +405 -0
- package/src/lib/components/contact-merge-dialog.js.map +1 -0
- package/src/lib/components/contact-properties-card.d.ts +89 -0
- package/src/lib/components/contact-properties-card.js +492 -0
- package/src/lib/components/contact-properties-card.js.map +1 -0
- package/src/lib/components/contact-timeline-card.d.ts +68 -0
- package/src/lib/components/contact-timeline-card.js +435 -0
- package/src/lib/components/contact-timeline-card.js.map +1 -0
- package/src/lib/components/contacts-bulk-bar.d.ts +91 -0
- package/src/lib/components/contacts-bulk-bar.js +493 -0
- package/src/lib/components/contacts-bulk-bar.js.map +1 -0
- package/src/lib/components/contacts-section.d.ts +26 -0
- package/src/lib/components/contacts-section.js +1025 -0
- package/src/lib/components/contacts-section.js.map +1 -0
- package/src/lib/components/copy-capture-address-button.d.ts +33 -0
- package/src/lib/components/copy-capture-address-button.js +60 -0
- package/src/lib/components/copy-capture-address-button.js.map +1 -0
- package/src/lib/components/crm-attribution-zone.d.ts +38 -0
- package/src/lib/components/crm-attribution-zone.js +36 -0
- package/src/lib/components/crm-attribution-zone.js.map +1 -0
- package/src/lib/components/crm-booking-zone.d.ts +61 -0
- package/src/lib/components/crm-booking-zone.js +50 -0
- package/src/lib/components/crm-booking-zone.js.map +1 -0
- package/src/lib/components/crm-bulk-bar-frame.d.ts +47 -0
- package/src/lib/components/crm-bulk-bar-frame.js +137 -0
- package/src/lib/components/crm-bulk-bar-frame.js.map +1 -0
- package/src/lib/components/crm-call-actions.d.ts +65 -0
- package/src/lib/components/crm-call-actions.js +110 -0
- package/src/lib/components/crm-call-actions.js.map +1 -0
- package/src/lib/components/crm-column-menu.d.ts +21 -0
- package/src/lib/components/crm-column-menu.js +103 -0
- package/src/lib/components/crm-column-menu.js.map +1 -0
- package/src/lib/components/crm-console-page.d.ts +19 -0
- package/src/lib/components/crm-console-page.js +151 -0
- package/src/lib/components/crm-console-page.js.map +1 -0
- package/src/lib/components/crm-console-sections.d.ts +52 -0
- package/src/lib/components/crm-console-sections.js +83 -0
- package/src/lib/components/crm-console-sections.js.map +1 -0
- package/src/lib/components/crm-custom-field-control.d.ts +26 -0
- package/src/lib/components/crm-custom-field-control.js +131 -0
- package/src/lib/components/crm-custom-field-control.js.map +1 -0
- package/src/lib/components/crm-email-template-tools.d.ts +69 -0
- package/src/lib/components/crm-email-template-tools.js +240 -0
- package/src/lib/components/crm-email-template-tools.js.map +1 -0
- package/src/lib/components/crm-export-all-button.d.ts +39 -0
- package/src/lib/components/crm-export-all-button.js +98 -0
- package/src/lib/components/crm-export-all-button.js.map +1 -0
- package/src/lib/components/crm-filter-bar.d.ts +53 -0
- package/src/lib/components/crm-filter-bar.js +294 -0
- package/src/lib/components/crm-filter-bar.js.map +1 -0
- package/src/lib/components/crm-glance-card.d.ts +54 -0
- package/src/lib/components/crm-glance-card.js +219 -0
- package/src/lib/components/crm-glance-card.js.map +1 -0
- package/src/lib/components/crm-next-activity-column.d.ts +35 -0
- package/src/lib/components/crm-next-activity-column.js +100 -0
- package/src/lib/components/crm-next-activity-column.js.map +1 -0
- package/src/lib/components/crm-record-header.d.ts +97 -0
- package/src/lib/components/crm-record-header.js +160 -0
- package/src/lib/components/crm-record-header.js.map +1 -0
- package/src/lib/components/crm-record-insights-zone.d.ts +50 -0
- package/src/lib/components/crm-record-insights-zone.js +169 -0
- package/src/lib/components/crm-record-insights-zone.js.map +1 -0
- package/src/lib/components/crm-record-picker.d.ts +42 -0
- package/src/lib/components/crm-record-picker.js +104 -0
- package/src/lib/components/crm-record-picker.js.map +1 -0
- package/src/lib/components/crm-send-email-button.d.ts +39 -0
- package/src/lib/components/crm-send-email-button.js +81 -0
- package/src/lib/components/crm-send-email-button.js.map +1 -0
- package/src/lib/components/crm-send-email-dialog.d.ts +61 -0
- package/src/lib/components/crm-send-email-dialog.js +851 -0
- package/src/lib/components/crm-send-email-dialog.js.map +1 -0
- package/src/lib/components/crm-site-picker.d.ts +61 -0
- package/src/lib/components/crm-site-picker.js +99 -0
- package/src/lib/components/crm-site-picker.js.map +1 -0
- package/src/lib/components/crm-suite-lock.d.ts +29 -0
- package/src/lib/components/crm-suite-lock.js +114 -0
- package/src/lib/components/crm-suite-lock.js.map +1 -0
- package/src/lib/components/crm-tasks-due-card.d.ts +42 -0
- package/src/lib/components/crm-tasks-due-card.js +225 -0
- package/src/lib/components/crm-tasks-due-card.js.map +1 -0
- package/src/lib/components/crm-views-control.d.ts +65 -0
- package/src/lib/components/crm-views-control.js +518 -0
- package/src/lib/components/crm-views-control.js.map +1 -0
- package/src/lib/components/csv-import-drawer.d.ts +132 -0
- package/src/lib/components/csv-import-drawer.js +746 -0
- package/src/lib/components/csv-import-drawer.js.map +1 -0
- package/src/lib/components/deal-board.d.ts +70 -0
- package/src/lib/components/deal-board.js +478 -0
- package/src/lib/components/deal-board.js.map +1 -0
- package/src/lib/components/deal-detail-page.d.ts +18 -0
- package/src/lib/components/deal-detail-page.js +323 -0
- package/src/lib/components/deal-detail-page.js.map +1 -0
- package/src/lib/components/deal-edit-drawer.d.ts +59 -0
- package/src/lib/components/deal-edit-drawer.js +640 -0
- package/src/lib/components/deal-edit-drawer.js.map +1 -0
- package/src/lib/components/deal-import-drawer.d.ts +24 -0
- package/src/lib/components/deal-import-drawer.js +83 -0
- package/src/lib/components/deal-import-drawer.js.map +1 -0
- package/src/lib/components/deal-products-card.d.ts +48 -0
- package/src/lib/components/deal-products-card.js +614 -0
- package/src/lib/components/deal-products-card.js.map +1 -0
- package/src/lib/components/deal-properties-card.d.ts +29 -0
- package/src/lib/components/deal-properties-card.js +144 -0
- package/src/lib/components/deal-properties-card.js.map +1 -0
- package/src/lib/components/deal-stage-card.d.ts +24 -0
- package/src/lib/components/deal-stage-card.js +199 -0
- package/src/lib/components/deal-stage-card.js.map +1 -0
- package/src/lib/components/deals-bulk-bar.d.ts +31 -0
- package/src/lib/components/deals-bulk-bar.js +340 -0
- package/src/lib/components/deals-bulk-bar.js.map +1 -0
- package/src/lib/components/deals-section.d.ts +49 -0
- package/src/lib/components/deals-section.js +767 -0
- package/src/lib/components/deals-section.js.map +1 -0
- package/src/lib/components/email-capture-card.d.ts +42 -0
- package/src/lib/components/email-capture-card.js +134 -0
- package/src/lib/components/email-capture-card.js.map +1 -0
- package/src/lib/components/email-template-drawer.d.ts +33 -0
- package/src/lib/components/email-template-drawer.js +209 -0
- package/src/lib/components/email-template-drawer.js.map +1 -0
- package/src/lib/components/email-templates-card.d.ts +33 -0
- package/src/lib/components/email-templates-card.js +370 -0
- package/src/lib/components/email-templates-card.js.map +1 -0
- package/src/lib/components/erase-person-action.d.ts +92 -0
- package/src/lib/components/erase-person-action.js +261 -0
- package/src/lib/components/erase-person-action.js.map +1 -0
- package/src/lib/components/fields-section.d.ts +37 -0
- package/src/lib/components/fields-section.js +641 -0
- package/src/lib/components/fields-section.js.map +1 -0
- package/src/lib/components/form-contact-fields-card.d.ts +46 -0
- package/src/lib/components/form-contact-fields-card.js +253 -0
- package/src/lib/components/form-contact-fields-card.js.map +1 -0
- package/src/lib/components/insert-link-at-caret.d.ts +28 -0
- package/src/lib/components/insert-link-at-caret.js +37 -0
- package/src/lib/components/insert-link-at-caret.js.map +1 -0
- package/src/lib/components/lead-convert-dialog.d.ts +32 -0
- package/src/lib/components/lead-convert-dialog.js +493 -0
- package/src/lib/components/lead-convert-dialog.js.map +1 -0
- package/src/lib/components/lead-detail-page.d.ts +16 -0
- package/src/lib/components/lead-detail-page.js +163 -0
- package/src/lib/components/lead-detail-page.js.map +1 -0
- package/src/lib/components/lead-history-card.d.ts +32 -0
- package/src/lib/components/lead-history-card.js +165 -0
- package/src/lib/components/lead-history-card.js.map +1 -0
- package/src/lib/components/lead-import-drawer.d.ts +24 -0
- package/src/lib/components/lead-import-drawer.js +95 -0
- package/src/lib/components/lead-import-drawer.js.map +1 -0
- package/src/lib/components/lead-owner-select.d.ts +35 -0
- package/src/lib/components/lead-owner-select.js +91 -0
- package/src/lib/components/lead-owner-select.js.map +1 -0
- package/src/lib/components/lead-properties-card.d.ts +61 -0
- package/src/lib/components/lead-properties-card.js +395 -0
- package/src/lib/components/lead-properties-card.js.map +1 -0
- package/src/lib/components/lead-status-chip.d.ts +12 -0
- package/src/lib/components/lead-status-chip.js +43 -0
- package/src/lib/components/lead-status-chip.js.map +1 -0
- package/src/lib/components/lead-surfaces-note.d.ts +126 -0
- package/src/lib/components/lead-surfaces-note.js +262 -0
- package/src/lib/components/lead-surfaces-note.js.map +1 -0
- package/src/lib/components/lead-unqualify-dialog.d.ts +24 -0
- package/src/lib/components/lead-unqualify-dialog.js +125 -0
- package/src/lib/components/lead-unqualify-dialog.js.map +1 -0
- package/src/lib/components/leads-bulk-bar.d.ts +58 -0
- package/src/lib/components/leads-bulk-bar.js +307 -0
- package/src/lib/components/leads-bulk-bar.js.map +1 -0
- package/src/lib/components/leads-section.d.ts +23 -0
- package/src/lib/components/leads-section.js +664 -0
- package/src/lib/components/leads-section.js.map +1 -0
- package/src/lib/components/linked-deals-card.d.ts +32 -0
- package/src/lib/components/linked-deals-card.js +163 -0
- package/src/lib/components/linked-deals-card.js.map +1 -0
- package/src/lib/components/log-activity-dialog.d.ts +60 -0
- package/src/lib/components/log-activity-dialog.js +368 -0
- package/src/lib/components/log-activity-dialog.js.map +1 -0
- package/src/lib/components/lost-reason-dialog.d.ts +26 -0
- package/src/lib/components/lost-reason-dialog.js +95 -0
- package/src/lib/components/lost-reason-dialog.js.map +1 -0
- package/src/lib/components/new-contact-drawer.d.ts +78 -0
- package/src/lib/components/new-contact-drawer.js +343 -0
- package/src/lib/components/new-contact-drawer.js.map +1 -0
- package/src/lib/components/org-lead-surfaces-note.d.ts +57 -0
- package/src/lib/components/org-lead-surfaces-note.js +172 -0
- package/src/lib/components/org-lead-surfaces-note.js.map +1 -0
- package/src/lib/components/owner-avatar.d.ts +18 -0
- package/src/lib/components/owner-avatar.js +61 -0
- package/src/lib/components/owner-avatar.js.map +1 -0
- package/src/lib/components/pipeline-stages-dialog.d.ts +43 -0
- package/src/lib/components/pipeline-stages-dialog.js +339 -0
- package/src/lib/components/pipeline-stages-dialog.js.map +1 -0
- package/src/lib/components/pipelines-dialog.d.ts +55 -0
- package/src/lib/components/pipelines-dialog.js +517 -0
- package/src/lib/components/pipelines-dialog.js.map +1 -0
- package/src/lib/components/recent-activity-feed.d.ts +39 -0
- package/src/lib/components/recent-activity-feed.js +103 -0
- package/src/lib/components/recent-activity-feed.js.map +1 -0
- package/src/lib/components/recipes-card.d.ts +39 -0
- package/src/lib/components/recipes-card.js +485 -0
- package/src/lib/components/recipes-card.js.map +1 -0
- package/src/lib/components/record-activity-card.d.ts +26 -0
- package/src/lib/components/record-activity-card.js +121 -0
- package/src/lib/components/record-activity-card.js.map +1 -0
- package/src/lib/components/record-files-card.d.ts +67 -0
- package/src/lib/components/record-files-card.js +290 -0
- package/src/lib/components/record-files-card.js.map +1 -0
- package/src/lib/components/record-tasks-card.d.ts +32 -0
- package/src/lib/components/record-tasks-card.js +306 -0
- package/src/lib/components/record-tasks-card.js.map +1 -0
- package/src/lib/components/reports/activity-card.d.ts +57 -0
- package/src/lib/components/reports/activity-card.js +281 -0
- package/src/lib/components/reports/activity-card.js.map +1 -0
- package/src/lib/components/reports/closed-deals-card.d.ts +20 -0
- package/src/lib/components/reports/closed-deals-card.js +194 -0
- package/src/lib/components/reports/closed-deals-card.js.map +1 -0
- package/src/lib/components/reports/contacts-mix-card.d.ts +27 -0
- package/src/lib/components/reports/contacts-mix-card.js +161 -0
- package/src/lib/components/reports/contacts-mix-card.js.map +1 -0
- package/src/lib/components/reports/contacts-trend-card.d.ts +31 -0
- package/src/lib/components/reports/contacts-trend-card.js +144 -0
- package/src/lib/components/reports/contacts-trend-card.js.map +1 -0
- package/src/lib/components/reports/forecast-card.d.ts +22 -0
- package/src/lib/components/reports/forecast-card.js +251 -0
- package/src/lib/components/reports/forecast-card.js.map +1 -0
- package/src/lib/components/reports/lead-counts.d.ts +32 -0
- package/src/lib/components/reports/lead-counts.js +44 -0
- package/src/lib/components/reports/lead-counts.js.map +1 -0
- package/src/lib/components/reports/lead-funnel-card.d.ts +38 -0
- package/src/lib/components/reports/lead-funnel-card.js +375 -0
- package/src/lib/components/reports/lead-funnel-card.js.map +1 -0
- package/src/lib/components/reports/pipeline-card.d.ts +19 -0
- package/src/lib/components/reports/pipeline-card.js +338 -0
- package/src/lib/components/reports/pipeline-card.js.map +1 -0
- package/src/lib/components/reports/report-bar-chart.d.ts +39 -0
- package/src/lib/components/reports/report-bar-chart.js +133 -0
- package/src/lib/components/reports/report-bar-chart.js.map +1 -0
- package/src/lib/components/reports/report-breakdown.d.ts +32 -0
- package/src/lib/components/reports/report-breakdown.js +105 -0
- package/src/lib/components/reports/report-breakdown.js.map +1 -0
- package/src/lib/components/reports/report-export.d.ts +37 -0
- package/src/lib/components/reports/report-export.js +66 -0
- package/src/lib/components/reports/report-export.js.map +1 -0
- package/src/lib/components/reports/report-format.d.ts +36 -0
- package/src/lib/components/reports/report-format.js +43 -0
- package/src/lib/components/reports/report-format.js.map +1 -0
- package/src/lib/components/reports/report-scope.d.ts +81 -0
- package/src/lib/components/reports/report-scope.js +58 -0
- package/src/lib/components/reports/report-scope.js.map +1 -0
- package/src/lib/components/reports/report-stat-tile.d.ts +47 -0
- package/src/lib/components/reports/report-stat-tile.js +96 -0
- package/src/lib/components/reports/report-stat-tile.js.map +1 -0
- package/src/lib/components/reports/source-conversion-card.d.ts +28 -0
- package/src/lib/components/reports/source-conversion-card.js +205 -0
- package/src/lib/components/reports/source-conversion-card.js.map +1 -0
- package/src/lib/components/reports/tasks-card.d.ts +26 -0
- package/src/lib/components/reports/tasks-card.js +279 -0
- package/src/lib/components/reports/tasks-card.js.map +1 -0
- package/src/lib/components/reports/use-aggregate-read.d.ts +99 -0
- package/src/lib/components/reports/use-aggregate-read.js +195 -0
- package/src/lib/components/reports/use-aggregate-read.js.map +1 -0
- package/src/lib/components/reports/won-lost-by-owner-card.d.ts +30 -0
- package/src/lib/components/reports/won-lost-by-owner-card.js +168 -0
- package/src/lib/components/reports/won-lost-by-owner-card.js.map +1 -0
- package/src/lib/components/reports-section.d.ts +42 -0
- package/src/lib/components/reports-section.js +308 -0
- package/src/lib/components/reports-section.js.map +1 -0
- package/src/lib/components/sending-addresses-card.d.ts +49 -0
- package/src/lib/components/sending-addresses-card.js +262 -0
- package/src/lib/components/sending-addresses-card.js.map +1 -0
- package/src/lib/components/settings-section.d.ts +151 -0
- package/src/lib/components/settings-section.js +783 -0
- package/src/lib/components/settings-section.js.map +1 -0
- package/src/lib/components/task-cells.d.ts +51 -0
- package/src/lib/components/task-cells.js +139 -0
- package/src/lib/components/task-cells.js.map +1 -0
- package/src/lib/components/task-edit-drawer.d.ts +53 -0
- package/src/lib/components/task-edit-drawer.js +483 -0
- package/src/lib/components/task-edit-drawer.js.map +1 -0
- package/src/lib/components/task-import-drawer.d.ts +24 -0
- package/src/lib/components/task-import-drawer.js +82 -0
- package/src/lib/components/task-import-drawer.js.map +1 -0
- package/src/lib/components/task-snooze-menu.d.ts +65 -0
- package/src/lib/components/task-snooze-menu.js +207 -0
- package/src/lib/components/task-snooze-menu.js.map +1 -0
- package/src/lib/components/tasks-bulk-bar.d.ts +25 -0
- package/src/lib/components/tasks-bulk-bar.js +348 -0
- package/src/lib/components/tasks-bulk-bar.js.map +1 -0
- package/src/lib/components/tasks-calendar.d.ts +38 -0
- package/src/lib/components/tasks-calendar.js +228 -0
- package/src/lib/components/tasks-calendar.js.map +1 -0
- package/src/lib/components/tasks-section.d.ts +27 -0
- package/src/lib/components/tasks-section.js +579 -0
- package/src/lib/components/tasks-section.js.map +1 -0
- package/src/lib/components/use-contact-campaign-emails.d.ts +32 -0
- package/src/lib/components/use-contact-campaign-emails.js +83 -0
- package/src/lib/components/use-contact-campaign-emails.js.map +1 -0
- package/src/lib/components/use-crm-api.d.ts +44 -0
- package/src/lib/components/use-crm-api.js +84 -0
- package/src/lib/components/use-crm-api.js.map +1 -0
- package/src/lib/components/use-crm-inbound-address.d.ts +60 -0
- package/src/lib/components/use-crm-inbound-address.js +124 -0
- package/src/lib/components/use-crm-inbound-address.js.map +1 -0
- package/src/lib/components/use-emails-hub-path.d.ts +24 -0
- package/src/lib/components/use-emails-hub-path.js +59 -0
- package/src/lib/components/use-emails-hub-path.js.map +1 -0
- package/src/lib/components/use-member-email-aliases.d.ts +54 -0
- package/src/lib/components/use-member-email-aliases.js +186 -0
- package/src/lib/components/use-member-email-aliases.js.map +1 -0
- package/src/lib/components/use-org-members.d.ts +40 -0
- package/src/lib/components/use-org-members.js +100 -0
- package/src/lib/components/use-org-members.js.map +1 -0
- package/src/lib/constants/api-routes.d.ts +109 -0
- package/src/lib/constants/api-routes.js +74 -0
- package/src/lib/constants/api-routes.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +14 -0
- package/src/lib/constants/bundle-common.js +14 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/constants/company-filters.d.ts +18 -0
- package/src/lib/constants/company-filters.js +51 -0
- package/src/lib/constants/company-filters.js.map +1 -0
- package/src/lib/constants/contact-filters.d.ts +38 -0
- package/src/lib/constants/contact-filters.js +294 -0
- package/src/lib/constants/contact-filters.js.map +1 -0
- package/src/lib/hooks/use-contact-field-definitions.d.ts +48 -0
- package/src/lib/hooks/use-contact-field-definitions.js +72 -0
- package/src/lib/hooks/use-contact-field-definitions.js.map +1 -0
- package/src/lib/hooks/use-contact-update.d.ts +25 -0
- package/src/lib/hooks/use-contact-update.js +80 -0
- package/src/lib/hooks/use-contact-update.js.map +1 -0
- package/src/lib/hooks/use-crm-activity-logger.d.ts +73 -0
- package/src/lib/hooks/use-crm-activity-logger.js +101 -0
- package/src/lib/hooks/use-crm-activity-logger.js.map +1 -0
- package/src/lib/hooks/use-crm-bulk-apply.d.ts +52 -0
- package/src/lib/hooks/use-crm-bulk-apply.js +112 -0
- package/src/lib/hooks/use-crm-bulk-apply.js.map +1 -0
- package/src/lib/hooks/use-crm-default-view.d.ts +24 -0
- package/src/lib/hooks/use-crm-default-view.js +64 -0
- package/src/lib/hooks/use-crm-default-view.js.map +1 -0
- package/src/lib/hooks/use-crm-email-templates.d.ts +59 -0
- package/src/lib/hooks/use-crm-email-templates.js +103 -0
- package/src/lib/hooks/use-crm-email-templates.js.map +1 -0
- package/src/lib/hooks/use-crm-hub-path.d.ts +29 -0
- package/src/lib/hooks/use-crm-hub-path.js +41 -0
- package/src/lib/hooks/use-crm-hub-path.js.map +1 -0
- package/src/lib/hooks/use-crm-org-mount.d.ts +97 -0
- package/src/lib/hooks/use-crm-org-mount.js +215 -0
- package/src/lib/hooks/use-crm-org-mount.js.map +1 -0
- package/src/lib/hooks/use-crm-record-names.d.ts +52 -0
- package/src/lib/hooks/use-crm-record-names.js +126 -0
- package/src/lib/hooks/use-crm-record-names.js.map +1 -0
- package/src/lib/hooks/use-crm-records-quota.d.ts +68 -0
- package/src/lib/hooks/use-crm-records-quota.js +118 -0
- package/src/lib/hooks/use-crm-records-quota.js.map +1 -0
- package/src/lib/hooks/use-crm-saved-view.d.ts +96 -0
- package/src/lib/hooks/use-crm-saved-view.js +329 -0
- package/src/lib/hooks/use-crm-saved-view.js.map +1 -0
- package/src/lib/hooks/use-crm-scope.d.ts +117 -0
- package/src/lib/hooks/use-crm-scope.js +147 -0
- package/src/lib/hooks/use-crm-scope.js.map +1 -0
- package/src/lib/hooks/use-crm-tasks.d.ts +85 -0
- package/src/lib/hooks/use-crm-tasks.js +153 -0
- package/src/lib/hooks/use-crm-tasks.js.map +1 -0
- package/src/lib/hooks/use-crm-view-grid.d.ts +55 -0
- package/src/lib/hooks/use-crm-view-grid.js +170 -0
- package/src/lib/hooks/use-crm-view-grid.js.map +1 -0
- package/src/lib/hooks/use-crm-views.d.ts +42 -0
- package/src/lib/hooks/use-crm-views.js +84 -0
- package/src/lib/hooks/use-crm-views.js.map +1 -0
- package/src/lib/hooks/use-deal-stage-api.d.ts +69 -0
- package/src/lib/hooks/use-deal-stage-api.js +78 -0
- package/src/lib/hooks/use-deal-stage-api.js.map +1 -0
- package/src/lib/hooks/use-deals.d.ts +47 -0
- package/src/lib/hooks/use-deals.js +105 -0
- package/src/lib/hooks/use-deals.js.map +1 -0
- package/src/lib/hooks/use-org-leads.d.ts +53 -0
- package/src/lib/hooks/use-org-leads.js +114 -0
- package/src/lib/hooks/use-org-leads.js.map +1 -0
- package/src/lib/hooks/use-org-member-directory.d.ts +36 -0
- package/src/lib/hooks/use-org-member-directory.js +116 -0
- package/src/lib/hooks/use-org-member-directory.js.map +1 -0
- package/src/lib/hooks/use-org-member-options.d.ts +38 -0
- package/src/lib/hooks/use-org-member-options.js +131 -0
- package/src/lib/hooks/use-org-member-options.js.map +1 -0
- package/src/lib/hooks/use-pipeline.d.ts +71 -0
- package/src/lib/hooks/use-pipeline.js +159 -0
- package/src/lib/hooks/use-pipeline.js.map +1 -0
- package/src/lib/model/companies-bulk-writes.d.ts +40 -0
- package/src/lib/model/companies-bulk-writes.js +103 -0
- package/src/lib/model/companies-bulk-writes.js.map +1 -0
- package/src/lib/model/companies-csv.d.ts +36 -0
- package/src/lib/model/companies-csv.js +38 -0
- package/src/lib/model/companies-csv.js.map +1 -0
- package/src/lib/model/companies.d.ts +99 -0
- package/src/lib/model/companies.js +168 -0
- package/src/lib/model/companies.js.map +1 -0
- package/src/lib/model/company-delete-route.d.ts +43 -0
- package/src/lib/model/company-delete-route.js +31 -0
- package/src/lib/model/company-delete-route.js.map +1 -0
- package/src/lib/model/company-delete.d.ts +42 -0
- package/src/lib/model/company-delete.js +52 -0
- package/src/lib/model/company-delete.js.map +1 -0
- package/src/lib/model/contact-duplicates.d.ts +58 -0
- package/src/lib/model/contact-duplicates.js +67 -0
- package/src/lib/model/contact-duplicates.js.map +1 -0
- package/src/lib/model/contact-record.d.ts +113 -0
- package/src/lib/model/contact-record.js +70 -0
- package/src/lib/model/contact-record.js.map +1 -0
- package/src/lib/model/contact-update.d.ts +93 -0
- package/src/lib/model/contact-update.js +50 -0
- package/src/lib/model/contact-update.js.map +1 -0
- package/src/lib/model/contacts-bulk-writes.d.ts +173 -0
- package/src/lib/model/contacts-bulk-writes.js +196 -0
- package/src/lib/model/contacts-bulk-writes.js.map +1 -0
- package/src/lib/model/contacts-csv.d.ts +54 -0
- package/src/lib/model/contacts-csv.js +67 -0
- package/src/lib/model/contacts-csv.js.map +1 -0
- package/src/lib/model/contacts-list-seed.d.ts +51 -0
- package/src/lib/model/contacts-list-seed.js +63 -0
- package/src/lib/model/contacts-list-seed.js.map +1 -0
- package/src/lib/model/crm-activity-report.d.ts +27 -0
- package/src/lib/model/crm-activity-report.js +56 -0
- package/src/lib/model/crm-activity-report.js.map +1 -0
- package/src/lib/model/crm-api.d.ts +49 -0
- package/src/lib/model/crm-api.js +47 -0
- package/src/lib/model/crm-api.js.map +1 -0
- package/src/lib/model/crm-bulk-writes.d.ts +147 -0
- package/src/lib/model/crm-bulk-writes.js +207 -0
- package/src/lib/model/crm-bulk-writes.js.map +1 -0
- package/src/lib/model/crm-company-import.d.ts +154 -0
- package/src/lib/model/crm-company-import.js +331 -0
- package/src/lib/model/crm-company-import.js.map +1 -0
- package/src/lib/model/crm-custom-draft.d.ts +62 -0
- package/src/lib/model/crm-custom-draft.js +67 -0
- package/src/lib/model/crm-custom-draft.js.map +1 -0
- package/src/lib/model/crm-deal-import.d.ts +112 -0
- package/src/lib/model/crm-deal-import.js +263 -0
- package/src/lib/model/crm-deal-import.js.map +1 -0
- package/src/lib/model/crm-import.d.ts +244 -0
- package/src/lib/model/crm-import.js +466 -0
- package/src/lib/model/crm-import.js.map +1 -0
- package/src/lib/model/crm-lead-import.d.ts +105 -0
- package/src/lib/model/crm-lead-import.js +255 -0
- package/src/lib/model/crm-lead-import.js.map +1 -0
- package/src/lib/model/crm-record-routes.d.ts +21 -0
- package/src/lib/model/crm-record-routes.js +70 -0
- package/src/lib/model/crm-record-routes.js.map +1 -0
- package/src/lib/model/crm-routes.d.ts +101 -0
- package/src/lib/model/crm-routes.js +92 -0
- package/src/lib/model/crm-routes.js.map +1 -0
- package/src/lib/model/crm-task-import.d.ts +94 -0
- package/src/lib/model/crm-task-import.js +275 -0
- package/src/lib/model/crm-task-import.js.map +1 -0
- package/src/lib/model/crm-view-param.d.ts +43 -0
- package/src/lib/model/crm-view-param.js +49 -0
- package/src/lib/model/crm-view-param.js.map +1 -0
- package/src/lib/model/deal-board-model.d.ts +241 -0
- package/src/lib/model/deal-board-model.js +439 -0
- package/src/lib/model/deal-board-model.js.map +1 -0
- package/src/lib/model/deal-form-model.d.ts +114 -0
- package/src/lib/model/deal-form-model.js +218 -0
- package/src/lib/model/deal-form-model.js.map +1 -0
- package/src/lib/model/deals-csv.d.ts +32 -0
- package/src/lib/model/deals-csv.js +37 -0
- package/src/lib/model/deals-csv.js.map +1 -0
- package/src/lib/model/import-column-shapes.d.ts +36 -0
- package/src/lib/model/import-column-shapes.js +76 -0
- package/src/lib/model/import-column-shapes.js.map +1 -0
- package/src/lib/model/lead-company-suggestion.d.ts +61 -0
- package/src/lib/model/lead-company-suggestion.js +65 -0
- package/src/lib/model/lead-company-suggestion.js.map +1 -0
- package/src/lib/model/lead-filters.d.ts +29 -0
- package/src/lib/model/lead-filters.js +39 -0
- package/src/lib/model/lead-filters.js.map +1 -0
- package/src/lib/model/lead-surfaces.d.ts +58 -0
- package/src/lib/model/lead-surfaces.js +67 -0
- package/src/lib/model/lead-surfaces.js.map +1 -0
- package/src/lib/model/leads-csv.d.ts +40 -0
- package/src/lib/model/leads-csv.js +40 -0
- package/src/lib/model/leads-csv.js.map +1 -0
- package/src/lib/model/next-activity-api.d.ts +31 -0
- package/src/lib/model/next-activity-api.js +57 -0
- package/src/lib/model/next-activity-api.js.map +1 -0
- package/src/lib/model/next-activity.d.ts +64 -0
- package/src/lib/model/next-activity.js +47 -0
- package/src/lib/model/next-activity.js.map +1 -0
- package/src/lib/model/person-key-web.d.ts +43 -0
- package/src/lib/model/person-key-web.js +52 -0
- package/src/lib/model/person-key-web.js.map +1 -0
- package/src/lib/model/record-facts.d.ts +282 -0
- package/src/lib/model/record-facts.js +434 -0
- package/src/lib/model/record-facts.js.map +1 -0
- package/src/lib/model/task-api.d.ts +28 -0
- package/src/lib/model/task-api.js +57 -0
- package/src/lib/model/task-api.js.map +1 -0
- package/src/lib/model/task-calendar.d.ts +108 -0
- package/src/lib/model/task-calendar.js +139 -0
- package/src/lib/model/task-calendar.js.map +1 -0
- package/src/lib/model/task-routes.d.ts +177 -0
- package/src/lib/model/task-routes.js +197 -0
- package/src/lib/model/task-routes.js.map +1 -0
- package/src/lib/model/task-scope.d.ts +45 -0
- package/src/lib/model/task-scope.js +51 -0
- package/src/lib/model/task-scope.js.map +1 -0
- package/src/lib/model/task-views.d.ts +149 -0
- package/src/lib/model/task-views.js +286 -0
- package/src/lib/model/task-views.js.map +1 -0
- package/src/lib/model/tasks-csv.d.ts +28 -0
- package/src/lib/model/tasks-csv.js +28 -0
- package/src/lib/model/tasks-csv.js.map +1 -0
- package/src/lib/plugin.d.ts +32 -0
- package/src/lib/plugin.js +208 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/server/companies-import.d.ts +57 -0
- package/src/lib/server/companies-import.js +242 -0
- package/src/lib/server/companies-import.js.map +1 -0
- package/src/lib/server/company-delete.d.ts +59 -0
- package/src/lib/server/company-delete.js +146 -0
- package/src/lib/server/company-delete.js.map +1 -0
- package/src/lib/server/contact-email-history.d.ts +82 -0
- package/src/lib/server/contact-email-history.js +264 -0
- package/src/lib/server/contact-email-history.js.map +1 -0
- package/src/lib/server/contact-profile.d.ts +41 -0
- package/src/lib/server/contact-profile.js +45 -0
- package/src/lib/server/contact-profile.js.map +1 -0
- package/src/lib/server/contact-update.d.ts +92 -0
- package/src/lib/server/contact-update.js +512 -0
- package/src/lib/server/contact-update.js.map +1 -0
- package/src/lib/server/contacts-import.d.ts +73 -0
- package/src/lib/server/contacts-import.js +263 -0
- package/src/lib/server/contacts-import.js.map +1 -0
- package/src/lib/server/contacts-merge.d.ts +86 -0
- package/src/lib/server/contacts-merge.js +206 -0
- package/src/lib/server/contacts-merge.js.map +1 -0
- package/src/lib/server/deals-import.d.ts +76 -0
- package/src/lib/server/deals-import.js +246 -0
- package/src/lib/server/deals-import.js.map +1 -0
- package/src/lib/server/email-send.d.ts +119 -0
- package/src/lib/server/email-send.js +667 -0
- package/src/lib/server/email-send.js.map +1 -0
- package/src/lib/server/email-template-duplicate.d.ts +19 -0
- package/src/lib/server/email-template-duplicate.js +206 -0
- package/src/lib/server/email-template-duplicate.js.map +1 -0
- package/src/lib/server/erase-person.d.ts +108 -0
- package/src/lib/server/erase-person.js +309 -0
- package/src/lib/server/erase-person.js.map +1 -0
- package/src/lib/server/import-context.d.ts +85 -0
- package/src/lib/server/import-context.js +181 -0
- package/src/lib/server/import-context.js.map +1 -0
- package/src/lib/server/inbound-address.d.ts +61 -0
- package/src/lib/server/inbound-address.js +188 -0
- package/src/lib/server/inbound-address.js.map +1 -0
- package/src/lib/server/lead-convert.d.ts +78 -0
- package/src/lib/server/lead-convert.js +250 -0
- package/src/lib/server/lead-convert.js.map +1 -0
- package/src/lib/server/leads-import.d.ts +84 -0
- package/src/lib/server/leads-import.js +261 -0
- package/src/lib/server/leads-import.js.map +1 -0
- package/src/lib/server/next-activity-routes.d.ts +33 -0
- package/src/lib/server/next-activity-routes.js +110 -0
- package/src/lib/server/next-activity-routes.js.map +1 -0
- package/src/lib/server/org-activity.d.ts +61 -0
- package/src/lib/server/org-activity.js +120 -0
- package/src/lib/server/org-activity.js.map +1 -0
- package/src/lib/server/org-caller.d.ts +110 -0
- package/src/lib/server/org-caller.js +154 -0
- package/src/lib/server/org-caller.js.map +1 -0
- package/src/lib/server/recipe-routes.d.ts +75 -0
- package/src/lib/server/recipe-routes.js +442 -0
- package/src/lib/server/recipe-routes.js.map +1 -0
- package/src/lib/server/record-facts.d.ts +65 -0
- package/src/lib/server/record-facts.js +337 -0
- package/src/lib/server/record-facts.js.map +1 -0
- package/src/lib/server/record-timeline.d.ts +51 -0
- package/src/lib/server/record-timeline.js +215 -0
- package/src/lib/server/record-timeline.js.map +1 -0
- package/src/lib/server/suite-gate.d.ts +42 -0
- package/src/lib/server/suite-gate.js +87 -0
- package/src/lib/server/suite-gate.js.map +1 -0
- package/src/lib/server/task-routes.d.ts +132 -0
- package/src/lib/server/task-routes.js +699 -0
- package/src/lib/server/task-routes.js.map +1 -0
- package/src/lib/server/tasks-import.d.ts +54 -0
- package/src/lib/server/tasks-import.js +157 -0
- package/src/lib/server/tasks-import.js.map +1 -0
- package/src/lib/server-deal-stage.d.ts +88 -0
- package/src/lib/server-deal-stage.js +316 -0
- package/src/lib/server-deal-stage.js.map +1 -0
- package/src/lib/server.d.ts +149 -0
- package/src/lib/server.js +615 -0
- package/src/lib/server.js.map +1 -0
|
@@ -0,0 +1,169 @@
|
|
|
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, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
19
|
+
import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot-context";
|
|
20
|
+
import { useConfirmationContext } from "@aglyn/shared-ui-jsx";
|
|
21
|
+
import { useSnackbar } from "@aglyn/shared-ui-snackstack";
|
|
22
|
+
import { useCallback, useMemo, useState } from "react";
|
|
23
|
+
import { useCrmScope } from "../hooks/use-crm-scope.js";
|
|
24
|
+
import { openStages } from "../model/deal-board-model.js";
|
|
25
|
+
import TaskEditDrawer from "./task-edit-drawer.js";
|
|
26
|
+
/** The due time a proposed task opens the form with: the end of the working day, `days` from today. */ export function crmProposedDueAtMs(dueInDays, nowMs = Date.now()) {
|
|
27
|
+
const due = new Date(nowMs);
|
|
28
|
+
due.setDate(due.getDate() + Math.max(0, Math.round(dueInDays)));
|
|
29
|
+
due.setHours(17, 0, 0, 0);
|
|
30
|
+
return due.getTime();
|
|
31
|
+
}
|
|
32
|
+
/** A proposed next step as the task form's fields, linked to the record. */ export function crmProposedTaskFields(task, link, nowMs = Date.now()) {
|
|
33
|
+
return _extends({}, link, {
|
|
34
|
+
title: task.title,
|
|
35
|
+
notes: task.notes,
|
|
36
|
+
kind: task.kind,
|
|
37
|
+
priority: task.priority,
|
|
38
|
+
dueAtMs: crmProposedDueAtMs(task.dueInDays, nowMs)
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The `recordInsights` zone on a CRM record's page (AGL-2917), hosted through
|
|
43
|
+
* the renderer the console shell hands down, as the product editor hosts
|
|
44
|
+
* `seoFields`: outside the shell it renders nothing, and inside it every gate
|
|
45
|
+
* a console page's slot applies applies here.
|
|
46
|
+
*
|
|
47
|
+
* A widget proposes; this page writes. A proposed task opens the CRM's own
|
|
48
|
+
* task form with the proposal filled in, and the form's Save is the write,
|
|
49
|
+
* through `crm/task-save`. A proposed stage is confirmed first and then moved
|
|
50
|
+
* through `crm/deal-stage`, the one writer of a deal's stage, so the move
|
|
51
|
+
* emits the event every automation listens for. Only an open stage is
|
|
52
|
+
* accepted: winning or losing a deal is a decision the stage card takes.
|
|
53
|
+
*/ export function CrmRecordInsightsZone(props) {
|
|
54
|
+
const Slot = useConsoleWidgetSlot();
|
|
55
|
+
// Outside the console shell there is no workspace to gate on, and nothing
|
|
56
|
+
// below is read.
|
|
57
|
+
return Slot ? /*#__PURE__*/ _jsx(HostedRecordInsightsZone, _extends({}, props, {
|
|
58
|
+
Slot: Slot
|
|
59
|
+
})) : null;
|
|
60
|
+
}
|
|
61
|
+
CrmRecordInsightsZone.displayName = 'CrmRecordInsightsZone';
|
|
62
|
+
function HostedRecordInsightsZone(props) {
|
|
63
|
+
var _ref;
|
|
64
|
+
var _props_taskLink, _props_taskLink1, _props_taskLink2;
|
|
65
|
+
const { hostId, org, kind, recordId, name, deal, Slot } = props;
|
|
66
|
+
// By the ids it names, so a page that passes a fresh object each render
|
|
67
|
+
// hands the widget the same callback.
|
|
68
|
+
const contactId = (_props_taskLink = props.taskLink) == null ? void 0 : _props_taskLink.contactId;
|
|
69
|
+
const companyId = (_props_taskLink1 = props.taskLink) == null ? void 0 : _props_taskLink1.companyId;
|
|
70
|
+
const dealId = (_props_taskLink2 = props.taskLink) == null ? void 0 : _props_taskLink2.dealId;
|
|
71
|
+
const linked = Boolean(props.taskLink);
|
|
72
|
+
const taskLink = useMemo(()=>linked ? _extends({}, contactId ? {
|
|
73
|
+
contactId
|
|
74
|
+
} : {}, companyId ? {
|
|
75
|
+
companyId
|
|
76
|
+
} : {}, dealId ? {
|
|
77
|
+
dealId
|
|
78
|
+
} : {}) : undefined, [
|
|
79
|
+
linked,
|
|
80
|
+
contactId,
|
|
81
|
+
companyId,
|
|
82
|
+
dealId
|
|
83
|
+
]);
|
|
84
|
+
const { scope, orgId, visibleTo } = useCrmScope({
|
|
85
|
+
hostId,
|
|
86
|
+
org
|
|
87
|
+
});
|
|
88
|
+
const { confirm } = useConfirmationContext();
|
|
89
|
+
const { enqueueSnackbar } = useSnackbar();
|
|
90
|
+
const [proposed, setProposed] = useState(null);
|
|
91
|
+
const proposeTask = useCallback((task, key)=>{
|
|
92
|
+
if (!taskLink) return;
|
|
93
|
+
setProposed({
|
|
94
|
+
key,
|
|
95
|
+
fields: crmProposedTaskFields(task, taskLink)
|
|
96
|
+
});
|
|
97
|
+
}, [
|
|
98
|
+
taskLink
|
|
99
|
+
]);
|
|
100
|
+
const stages = useMemo(()=>deal ? openStages(deal.pipeline).map((stage)=>({
|
|
101
|
+
id: stage.id,
|
|
102
|
+
name: stage.name
|
|
103
|
+
})) : undefined, [
|
|
104
|
+
deal
|
|
105
|
+
]);
|
|
106
|
+
const proposeStage = useCallback(async (stageId)=>{
|
|
107
|
+
if (!deal || deal.status !== 'open') return;
|
|
108
|
+
const stage = stages == null ? void 0 : stages.find((entry)=>entry.id === stageId);
|
|
109
|
+
if (!stage || stage.id === deal.stageId) return;
|
|
110
|
+
const agreed = await confirm({
|
|
111
|
+
title: `Move this deal to ${stage.name}?`,
|
|
112
|
+
description: 'The deal moves as it would from its stage card, and any automation that listens for a stage change runs.',
|
|
113
|
+
confirmationText: `Move to ${stage.name}`
|
|
114
|
+
}).then(()=>true).catch(()=>false);
|
|
115
|
+
if (!agreed) return;
|
|
116
|
+
try {
|
|
117
|
+
await deal.api.moveToStage(deal.ref, stage.id);
|
|
118
|
+
enqueueSnackbar(`Moved to ${stage.name}`, {
|
|
119
|
+
variant: 'success',
|
|
120
|
+
persist: false
|
|
121
|
+
});
|
|
122
|
+
} catch (error) {
|
|
123
|
+
enqueueSnackbar(error instanceof Error ? error.message : 'The deal could not be moved.', {
|
|
124
|
+
variant: 'warning'
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}, [
|
|
128
|
+
deal,
|
|
129
|
+
stages,
|
|
130
|
+
confirm,
|
|
131
|
+
enqueueSnackbar
|
|
132
|
+
]);
|
|
133
|
+
const zone = _extends({
|
|
134
|
+
hostId,
|
|
135
|
+
orgId: orgId != null ? orgId : undefined,
|
|
136
|
+
record: {
|
|
137
|
+
kind,
|
|
138
|
+
id: recordId,
|
|
139
|
+
name
|
|
140
|
+
}
|
|
141
|
+
}, taskLink ? {
|
|
142
|
+
proposeTask
|
|
143
|
+
} : {}, deal && stages ? {
|
|
144
|
+
stages,
|
|
145
|
+
stageId: deal.stageId,
|
|
146
|
+
proposeStage: (stageId)=>void proposeStage(stageId)
|
|
147
|
+
} : {});
|
|
148
|
+
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
149
|
+
children: [
|
|
150
|
+
/*#__PURE__*/ _jsx(Slot, _extends({
|
|
151
|
+
slot: "recordInsights"
|
|
152
|
+
}, zone)),
|
|
153
|
+
taskLink ? /*#__PURE__*/ _jsx(TaskEditDrawer, {
|
|
154
|
+
open: Boolean(proposed),
|
|
155
|
+
onClose: ()=>setProposed(null),
|
|
156
|
+
hostId: hostId,
|
|
157
|
+
org: org,
|
|
158
|
+
orgId: orgId,
|
|
159
|
+
scope: scope,
|
|
160
|
+
readTokens: visibleTo,
|
|
161
|
+
prefill: proposed == null ? void 0 : proposed.fields,
|
|
162
|
+
onSaved: ()=>setProposed(null)
|
|
163
|
+
}, (_ref = proposed == null ? void 0 : proposed.key) != null ? _ref : 'none') : null
|
|
164
|
+
]
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
export default CrmRecordInsightsZone;
|
|
168
|
+
|
|
169
|
+
//# sourceMappingURL=crm-record-insights-zone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/crm-record-insights-zone.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type ConsoleWidgetSlotRenderer,\n useConsoleWidgetSlot,\n} from '@aglyn/aglyn/app-utils/console-widget-slot-context'\nimport type { ConsoleRecordInsightsZoneProps } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport type { ConsoleProposedTask } from '@aglyn/aglyn/plugin-manager/record-zone-props'\nimport { useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useCrmScope } from '../hooks/use-crm-scope'\nimport type { DealStageApi, DealStageRef } from '../hooks/use-deal-stage-api'\nimport { openStages, type PipelineDoc } from '../model/deal-board-model'\nimport type { CrmTaskFields } from '../model/task-routes'\nimport TaskEditDrawer from './task-edit-drawer'\n\n/** The record links a task proposed on a record's page is filed under. */\nexport type CrmRecordTaskLink = Pick<Partial<CrmTaskFields>, 'contactId' | 'companyId' | 'dealId'>\n\nexport interface CrmRecordInsightsZoneProps {\n /** The site the page is under, or `null` at the organization level; a lead's own site on a lead's page. */\n hostId: string | null\n org?: Record<string, unknown> | null\n kind: 'contact' | 'company' | 'deal' | 'lead'\n recordId: string\n /** The record's name as the page shows it. */\n name: string\n /**\n * The links a proposed next step is filed under. Absent for a lead, which a\n * task cannot name, so the zone offers no task there.\n */\n taskLink?: CrmRecordTaskLink\n /** A deal's stage controls: its pipeline, the deal as the stage route names it, and the route. */\n deal?: { pipeline: PipelineDoc | null; ref: DealStageRef; stageId: string; status: string; api: DealStageApi }\n}\n\n/** The due time a proposed task opens the form with: the end of the working day, `days` from today. */\nexport function crmProposedDueAtMs(dueInDays: number, nowMs: number = Date.now()): number {\n const due = new Date(nowMs)\n due.setDate(due.getDate() + Math.max(0, Math.round(dueInDays)))\n due.setHours(17, 0, 0, 0)\n return due.getTime()\n}\n\n/** A proposed next step as the task form's fields, linked to the record. */\nexport function crmProposedTaskFields(\n task: ConsoleProposedTask,\n link: CrmRecordTaskLink,\n nowMs: number = Date.now(),\n): Partial<CrmTaskFields> {\n return {\n ...link,\n title: task.title,\n notes: task.notes,\n kind: task.kind,\n priority: task.priority,\n dueAtMs: crmProposedDueAtMs(task.dueInDays, nowMs),\n }\n}\n\n/**\n * The `recordInsights` zone on a CRM record's page (AGL-2917), hosted through\n * the renderer the console shell hands down, as the product editor hosts\n * `seoFields`: outside the shell it renders nothing, and inside it every gate\n * a console page's slot applies applies here.\n *\n * A widget proposes; this page writes. A proposed task opens the CRM's own\n * task form with the proposal filled in, and the form's Save is the write,\n * through `crm/task-save`. A proposed stage is confirmed first and then moved\n * through `crm/deal-stage`, the one writer of a deal's stage, so the move\n * emits the event every automation listens for. Only an open stage is\n * accepted: winning or losing a deal is a decision the stage card takes.\n */\nexport function CrmRecordInsightsZone(props: CrmRecordInsightsZoneProps) {\n const Slot = useConsoleWidgetSlot()\n // Outside the console shell there is no workspace to gate on, and nothing\n // below is read.\n return Slot ? <HostedRecordInsightsZone {...props} Slot={Slot} /> : null\n}\nCrmRecordInsightsZone.displayName = 'CrmRecordInsightsZone'\n\nfunction HostedRecordInsightsZone(props: CrmRecordInsightsZoneProps & { Slot: ConsoleWidgetSlotRenderer }) {\n const { hostId, org, kind, recordId, name, deal, Slot } = props\n // By the ids it names, so a page that passes a fresh object each render\n // hands the widget the same callback.\n const contactId = props.taskLink?.contactId\n const companyId = props.taskLink?.companyId\n const dealId = props.taskLink?.dealId\n const linked = Boolean(props.taskLink)\n const taskLink = useMemo<CrmRecordTaskLink | undefined>(\n () =>\n linked\n ? { ...(contactId ? { contactId } : {}), ...(companyId ? { companyId } : {}), ...(dealId ? { dealId } : {}) }\n : undefined,\n [linked, contactId, companyId, dealId],\n )\n const { scope, orgId, visibleTo } = useCrmScope({ hostId, org })\n const { confirm } = useConfirmationContext()\n const { enqueueSnackbar } = useSnackbar()\n const [proposed, setProposed] = useState<{ key: string; fields: Partial<CrmTaskFields> } | null>(null)\n\n const proposeTask = useCallback(\n (task: ConsoleProposedTask, key: string) => {\n if (!taskLink) return\n setProposed({ key, fields: crmProposedTaskFields(task, taskLink) })\n },\n [taskLink],\n )\n\n const stages = useMemo(\n () => (deal ? openStages(deal.pipeline).map((stage) => ({ id: stage.id, name: stage.name })) : undefined),\n [deal],\n )\n\n const proposeStage = useCallback(\n async (stageId: string) => {\n if (!deal || deal.status !== 'open') return\n const stage = stages?.find((entry) => entry.id === stageId)\n if (!stage || stage.id === deal.stageId) return\n const agreed = await confirm({\n title: `Move this deal to ${stage.name}?`,\n description: 'The deal moves as it would from its stage card, and any automation that listens for a stage change runs.',\n confirmationText: `Move to ${stage.name}`,\n })\n .then(() => true)\n .catch(() => false)\n if (!agreed) return\n try {\n await deal.api.moveToStage(deal.ref, stage.id)\n enqueueSnackbar(`Moved to ${stage.name}`, { variant: 'success', persist: false })\n } catch (error) {\n enqueueSnackbar(error instanceof Error ? error.message : 'The deal could not be moved.', { variant: 'warning' })\n }\n },\n [deal, stages, confirm, enqueueSnackbar],\n )\n\n const zone: ConsoleRecordInsightsZoneProps = {\n hostId,\n orgId: orgId ?? undefined,\n record: { kind, id: recordId, name },\n ...(taskLink ? { proposeTask } : {}),\n ...(deal && stages ? { stages, stageId: deal.stageId, proposeStage: (stageId: string) => void proposeStage(stageId) } : {}),\n }\n return (\n <>\n <Slot slot=\"recordInsights\" {...zone} />\n {taskLink ? (\n <TaskEditDrawer\n key={proposed?.key ?? 'none'}\n open={Boolean(proposed)}\n onClose={() => setProposed(null)}\n hostId={hostId}\n org={org}\n orgId={orgId}\n scope={scope}\n readTokens={visibleTo}\n prefill={proposed?.fields}\n onSaved={() => setProposed(null)}\n />\n ) : null}\n </>\n )\n}\n\nexport default CrmRecordInsightsZone\n"],"names":["useConsoleWidgetSlot","useConfirmationContext","useSnackbar","useCallback","useMemo","useState","useCrmScope","openStages","TaskEditDrawer","crmProposedDueAtMs","dueInDays","nowMs","Date","now","due","setDate","getDate","Math","max","round","setHours","getTime","crmProposedTaskFields","task","link","title","notes","kind","priority","dueAtMs","CrmRecordInsightsZone","props","Slot","HostedRecordInsightsZone","displayName","hostId","org","recordId","name","deal","contactId","taskLink","companyId","dealId","linked","Boolean","undefined","scope","orgId","visibleTo","confirm","enqueueSnackbar","proposed","setProposed","proposeTask","key","fields","stages","pipeline","map","stage","id","proposeStage","stageId","status","find","entry","agreed","description","confirmationText","then","catch","api","moveToStage","ref","variant","persist","error","Error","message","zone","record","slot","open","onClose","readTokens","prefill","onSaved"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,SAEEA,oBAAoB,QACf,qDAAoD;AAG3D,SAASC,sBAAsB,QAAQ,uBAAsB;AAC7D,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,WAAW,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AACtD,SAASC,WAAW,QAAQ,4BAAwB;AAEpD,SAASC,UAAU,QAA0B,+BAA2B;AAExE,OAAOC,oBAAoB,wBAAoB;AAsB/C,qGAAqG,GACrG,OAAO,SAASC,mBAAmBC,SAAiB,EAAEC,QAAgBC,KAAKC,GAAG,EAAE;IAC9E,MAAMC,MAAM,IAAIF,KAAKD;IACrBG,IAAIC,OAAO,CAACD,IAAIE,OAAO,KAAKC,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAACT;IACnDI,IAAIM,QAAQ,CAAC,IAAI,GAAG,GAAG;IACvB,OAAON,IAAIO,OAAO;AACpB;AAEA,0EAA0E,GAC1E,OAAO,SAASC,sBACdC,IAAyB,EACzBC,IAAuB,EACvBb,QAAgBC,KAAKC,GAAG,EAAE;IAE1B,OAAO,aACFW;QACHC,OAAOF,KAAKE,KAAK;QACjBC,OAAOH,KAAKG,KAAK;QACjBC,MAAMJ,KAAKI,IAAI;QACfC,UAAUL,KAAKK,QAAQ;QACvBC,SAASpB,mBAAmBc,KAAKb,SAAS,EAAEC;;AAEhD;AAEA;;;;;;;;;;;;CAYC,GACD,OAAO,SAASmB,sBAAsBC,KAAiC;IACrE,MAAMC,OAAOhC;IACb,0EAA0E;IAC1E,iBAAiB;IACjB,OAAOgC,qBAAO,KAACC,uCAA6BF;QAAOC,MAAMA;UAAW;AACtE;AACAF,sBAAsBI,WAAW,GAAG;AAEpC,SAASD,yBAAyBF,KAAuE;;QAIrFA,iBACAA,kBACHA;IALf,MAAM,EAAEI,MAAM,EAAEC,GAAG,EAAET,IAAI,EAAEU,QAAQ,EAAEC,IAAI,EAAEC,IAAI,EAAEP,IAAI,EAAE,GAAGD;IAC1D,wEAAwE;IACxE,sCAAsC;IACtC,MAAMS,aAAYT,kBAAAA,MAAMU,QAAQ,qBAAdV,gBAAgBS,SAAS;IAC3C,MAAME,aAAYX,mBAAAA,MAAMU,QAAQ,qBAAdV,iBAAgBW,SAAS;IAC3C,MAAMC,UAASZ,mBAAAA,MAAMU,QAAQ,qBAAdV,iBAAgBY,MAAM;IACrC,MAAMC,SAASC,QAAQd,MAAMU,QAAQ;IACrC,MAAMA,WAAWrC,QACf,IACEwC,SACI,aAAMJ,YAAY;YAAEA;QAAU,IAAI,CAAC,GAAQE,YAAY;YAAEA;QAAU,IAAI,CAAC,GAAQC,SAAS;YAAEA;QAAO,IAAI,CAAC,KACvGG,WACN;QAACF;QAAQJ;QAAWE;QAAWC;KAAO;IAExC,MAAM,EAAEI,KAAK,EAAEC,KAAK,EAAEC,SAAS,EAAE,GAAG3C,YAAY;QAAE6B;QAAQC;IAAI;IAC9D,MAAM,EAAEc,OAAO,EAAE,GAAGjD;IACpB,MAAM,EAAEkD,eAAe,EAAE,GAAGjD;IAC5B,MAAM,CAACkD,UAAUC,YAAY,GAAGhD,SAAiE;IAEjG,MAAMiD,cAAcnD,YAClB,CAACoB,MAA2BgC;QAC1B,IAAI,CAACd,UAAU;QACfY,YAAY;YAAEE;YAAKC,QAAQlC,sBAAsBC,MAAMkB;QAAU;IACnE,GACA;QAACA;KAAS;IAGZ,MAAMgB,SAASrD,QACb,IAAOmC,OAAOhC,WAAWgC,KAAKmB,QAAQ,EAAEC,GAAG,CAAC,CAACC,QAAW,CAAA;gBAAEC,IAAID,MAAMC,EAAE;gBAAEvB,MAAMsB,MAAMtB,IAAI;YAAC,CAAA,KAAMQ,WAC/F;QAACP;KAAK;IAGR,MAAMuB,eAAe3D,YACnB,OAAO4D;QACL,IAAI,CAACxB,QAAQA,KAAKyB,MAAM,KAAK,QAAQ;QACrC,MAAMJ,QAAQH,0BAAAA,OAAQQ,IAAI,CAAC,CAACC,QAAUA,MAAML,EAAE,KAAKE;QACnD,IAAI,CAACH,SAASA,MAAMC,EAAE,KAAKtB,KAAKwB,OAAO,EAAE;QACzC,MAAMI,SAAS,MAAMjB,QAAQ;YAC3BzB,OAAO,CAAC,kBAAkB,EAAEmC,MAAMtB,IAAI,CAAC,CAAC,CAAC;YACzC8B,aAAa;YACbC,kBAAkB,CAAC,QAAQ,EAAET,MAAMtB,IAAI,EAAE;QAC3C,GACGgC,IAAI,CAAC,IAAM,MACXC,KAAK,CAAC,IAAM;QACf,IAAI,CAACJ,QAAQ;QACb,IAAI;YACF,MAAM5B,KAAKiC,GAAG,CAACC,WAAW,CAAClC,KAAKmC,GAAG,EAAEd,MAAMC,EAAE;YAC7CV,gBAAgB,CAAC,SAAS,EAAES,MAAMtB,IAAI,EAAE,EAAE;gBAAEqC,SAAS;gBAAWC,SAAS;YAAM;QACjF,EAAE,OAAOC,OAAO;YACd1B,gBAAgB0B,iBAAiBC,QAAQD,MAAME,OAAO,GAAG,gCAAgC;gBAAEJ,SAAS;YAAU;QAChH;IACF,GACA;QAACpC;QAAMkB;QAAQP;QAASC;KAAgB;IAG1C,MAAM6B,OAAuC;QAC3C7C;QACAa,KAAK,EAAEA,gBAAAA,QAASF;QAChBmC,QAAQ;YAAEtD;YAAMkC,IAAIxB;YAAUC;QAAK;OAC/BG,WAAW;QAAEa;IAAY,IAAI,CAAC,GAC9Bf,QAAQkB,SAAS;QAAEA;QAAQM,SAASxB,KAAKwB,OAAO;QAAED,cAAc,CAACC,UAAoB,KAAKD,aAAaC;IAAS,IAAI,CAAC;IAE3H,qBACE;;0BACE,KAAC/B;gBAAKkD,MAAK;eAAqBF;YAC/BvC,yBACC,KAACjC;gBAEC2E,MAAMtC,QAAQO;gBACdgC,SAAS,IAAM/B,YAAY;gBAC3BlB,QAAQA;gBACRC,KAAKA;gBACLY,OAAOA;gBACPD,OAAOA;gBACPsC,YAAYpC;gBACZqC,OAAO,EAAElC,4BAAAA,SAAUI,MAAM;gBACzB+B,SAAS,IAAMlC,YAAY;uBATtBD,4BAAAA,SAAUG,GAAG,mBAAI,UAWtB;;;AAGV;AAEA,eAAezB,sBAAqB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type CrmRecordKind } from '../hooks/use-crm-record-names';
|
|
2
|
+
/**
|
|
3
|
+
* How many records a picker offers. The window is the hundred most recently
|
|
4
|
+
* touched, which is the hundred a person is most likely to be making a task
|
|
5
|
+
* about; the field says so, and the record pages' own "New task" buttons
|
|
6
|
+
* arrive with the record already linked, which is how a task about an older
|
|
7
|
+
* one gets made.
|
|
8
|
+
*/
|
|
9
|
+
export declare const CRM_RECORD_PICKER_LIMIT = 100;
|
|
10
|
+
export interface CrmRecordPickerProps {
|
|
11
|
+
kind: CrmRecordKind;
|
|
12
|
+
scope: readonly [string, string] | null;
|
|
13
|
+
/** The reader's tokens, or `null` at the organization level — no clause (AGL-2630). */
|
|
14
|
+
readTokens: readonly string[] | null;
|
|
15
|
+
/**
|
|
16
|
+
* The viewing group, for a contact's facet name — or `null` at the
|
|
17
|
+
* organization level, where each contact is named through its own
|
|
18
|
+
* primary holder (`contactPrimaryGroup`), resolved from {@link org}.
|
|
19
|
+
*/
|
|
20
|
+
groupId: string | null;
|
|
21
|
+
/** The org document, for the per-contact holder when {@link groupId} is null. */
|
|
22
|
+
org?: Record<string, unknown> | null;
|
|
23
|
+
value: string | null;
|
|
24
|
+
onChange: (id: string | null) => void;
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Link a task to a contact, company or deal by name (AGL-2599).
|
|
29
|
+
*
|
|
30
|
+
* One query shape for all three kinds — the most recently updated hundred
|
|
31
|
+
* visible to this site, filtered as the person types — because that is the
|
|
32
|
+
* one shape every CRM collection has an index for (`visibleTo, updatedAt`).
|
|
33
|
+
* A prefix search on the stored name would need `(visibleTo, nameLower)`,
|
|
34
|
+
* which companies have and contacts do not, and a picker that searched two
|
|
35
|
+
* kinds properly and one kind not at all would be worse to explain than a
|
|
36
|
+
* window. The listener opens with the drawer and closes with it.
|
|
37
|
+
*/
|
|
38
|
+
export declare function CrmRecordPicker(props: CrmRecordPickerProps): import("react").JSX.Element;
|
|
39
|
+
export declare namespace CrmRecordPicker {
|
|
40
|
+
var displayName: string;
|
|
41
|
+
}
|
|
42
|
+
export default CrmRecordPicker;
|
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
import { useFirestore, useFirestoreCollection } from "@aglyn/tenant-feature-instance";
|
|
20
|
+
import { Autocomplete, TextField } from "@mui/material";
|
|
21
|
+
import { collection, limit, orderBy, query } from "firebase/firestore";
|
|
22
|
+
import { useMemo } from "react";
|
|
23
|
+
import { CRM_RECORD_COLLECTIONS, crmRecordName } from "../hooks/use-crm-record-names.js";
|
|
24
|
+
import { crmVisibleToClause } from "../hooks/use-crm-scope.js";
|
|
25
|
+
import { contactPrimaryGroup } from "../model/contact-record.js";
|
|
26
|
+
/**
|
|
27
|
+
* How many records a picker offers. The window is the hundred most recently
|
|
28
|
+
* touched, which is the hundred a person is most likely to be making a task
|
|
29
|
+
* about; the field says so, and the record pages' own "New task" buttons
|
|
30
|
+
* arrive with the record already linked, which is how a task about an older
|
|
31
|
+
* one gets made.
|
|
32
|
+
*/ export const CRM_RECORD_PICKER_LIMIT = 100;
|
|
33
|
+
const PICKER_LABELS = {
|
|
34
|
+
contact: 'Contact',
|
|
35
|
+
company: 'Company',
|
|
36
|
+
deal: 'Deal'
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Link a task to a contact, company or deal by name (AGL-2599).
|
|
40
|
+
*
|
|
41
|
+
* One query shape for all three kinds — the most recently updated hundred
|
|
42
|
+
* visible to this site, filtered as the person types — because that is the
|
|
43
|
+
* one shape every CRM collection has an index for (`visibleTo, updatedAt`).
|
|
44
|
+
* A prefix search on the stored name would need `(visibleTo, nameLower)`,
|
|
45
|
+
* which companies have and contacts do not, and a picker that searched two
|
|
46
|
+
* kinds properly and one kind not at all would be worse to explain than a
|
|
47
|
+
* window. The listener opens with the drawer and closes with it.
|
|
48
|
+
*/ export function CrmRecordPicker(props) {
|
|
49
|
+
const { kind, scope, readTokens, groupId, org, value, onChange, disabled } = props;
|
|
50
|
+
const firestore = useFirestore();
|
|
51
|
+
const { data, status } = useFirestoreCollection(()=>scope ? query(collection(firestore, scope[0], scope[1], CRM_RECORD_COLLECTIONS[kind]), ...crmVisibleToClause(readTokens), orderBy('updatedAt', 'desc'), limit(CRM_RECORD_PICKER_LIMIT)) : null, [
|
|
52
|
+
firestore,
|
|
53
|
+
scope,
|
|
54
|
+
readTokens,
|
|
55
|
+
kind
|
|
56
|
+
], {
|
|
57
|
+
idField: '$id'
|
|
58
|
+
});
|
|
59
|
+
const options = useMemo(()=>(data != null ? data : []).map((row)=>({
|
|
60
|
+
id: row.$id,
|
|
61
|
+
label: crmRecordName(kind, row, groupId != null ? groupId : contactPrimaryGroup(row, org).groupId) || row.$id
|
|
62
|
+
})).sort((a, b)=>a.label.localeCompare(b.label)), [
|
|
63
|
+
data,
|
|
64
|
+
kind,
|
|
65
|
+
groupId,
|
|
66
|
+
org
|
|
67
|
+
]);
|
|
68
|
+
/*
|
|
69
|
+
* The linked record may sit outside the window — an old contact a record
|
|
70
|
+
* page's button linked — so the value is a placeholder carrying its id
|
|
71
|
+
* until (unless) the window turns out to hold it.
|
|
72
|
+
*/ const selected = useMemo(()=>{
|
|
73
|
+
var _options_find;
|
|
74
|
+
if (!value) return null;
|
|
75
|
+
return (_options_find = options.find((option)=>option.id === value)) != null ? _options_find : {
|
|
76
|
+
id: value,
|
|
77
|
+
label: value
|
|
78
|
+
};
|
|
79
|
+
}, [
|
|
80
|
+
options,
|
|
81
|
+
value
|
|
82
|
+
]);
|
|
83
|
+
return /*#__PURE__*/ _jsx(Autocomplete, {
|
|
84
|
+
options: options,
|
|
85
|
+
value: selected,
|
|
86
|
+
onChange: (_event, next)=>{
|
|
87
|
+
var _ref;
|
|
88
|
+
return onChange((_ref = next == null ? void 0 : next.id) != null ? _ref : null);
|
|
89
|
+
},
|
|
90
|
+
getOptionLabel: (option)=>option.label,
|
|
91
|
+
isOptionEqualToValue: (option, current)=>option.id === current.id,
|
|
92
|
+
loading: status === 'loading',
|
|
93
|
+
disabled: disabled,
|
|
94
|
+
size: "small",
|
|
95
|
+
renderInput: (params)=>/*#__PURE__*/ _jsx(TextField, _extends({}, params, {
|
|
96
|
+
label: PICKER_LABELS[kind],
|
|
97
|
+
helperText: options.length >= CRM_RECORD_PICKER_LIMIT ? `The ${CRM_RECORD_PICKER_LIMIT} most recently updated — type to narrow.` : undefined
|
|
98
|
+
}))
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
CrmRecordPicker.displayName = 'CrmRecordPicker';
|
|
102
|
+
export default CrmRecordPicker;
|
|
103
|
+
|
|
104
|
+
//# sourceMappingURL=crm-record-picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/crm-record-picker.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 useFirestore,\n useFirestoreCollection,\n} from '@aglyn/tenant-feature-instance'\nimport { Autocomplete, TextField } from '@mui/material'\nimport { collection, limit, orderBy, query } from 'firebase/firestore'\nimport { useMemo } from 'react'\nimport {\n CRM_RECORD_COLLECTIONS,\n type CrmRecordKind,\n crmRecordName,\n} from '../hooks/use-crm-record-names'\nimport { crmVisibleToClause } from '../hooks/use-crm-scope'\nimport { contactPrimaryGroup } from '../model/contact-record'\n\n/**\n * How many records a picker offers. The window is the hundred most recently\n * touched, which is the hundred a person is most likely to be making a task\n * about; the field says so, and the record pages' own \"New task\" buttons\n * arrive with the record already linked, which is how a task about an older\n * one gets made.\n */\nexport const CRM_RECORD_PICKER_LIMIT = 100\n\nconst PICKER_LABELS: Record<CrmRecordKind, string> = {\n contact: 'Contact',\n company: 'Company',\n deal: 'Deal',\n}\n\nexport interface CrmRecordPickerProps {\n kind: CrmRecordKind\n scope: readonly [string, string] | null\n /** The reader's tokens, or `null` at the organization level — no clause (AGL-2630). */\n readTokens: readonly string[] | null\n /**\n * The viewing group, for a contact's facet name — or `null` at the\n * organization level, where each contact is named through its own\n * primary holder (`contactPrimaryGroup`), resolved from {@link org}.\n */\n groupId: string | null\n /** The org document, for the per-contact holder when {@link groupId} is null. */\n org?: Record<string, unknown> | null\n value: string | null\n onChange: (id: string | null) => void\n disabled?: boolean\n}\n\n/**\n * Link a task to a contact, company or deal by name (AGL-2599).\n *\n * One query shape for all three kinds — the most recently updated hundred\n * visible to this site, filtered as the person types — because that is the\n * one shape every CRM collection has an index for (`visibleTo, updatedAt`).\n * A prefix search on the stored name would need `(visibleTo, nameLower)`,\n * which companies have and contacts do not, and a picker that searched two\n * kinds properly and one kind not at all would be worse to explain than a\n * window. The listener opens with the drawer and closes with it.\n */\nexport function CrmRecordPicker(props: CrmRecordPickerProps) {\n const { kind, scope, readTokens, groupId, org, value, onChange, disabled } = props\n const firestore = useFirestore()\n const { data, status } = useFirestoreCollection<Record<string, unknown> & { $id: string }>(\n () =>\n scope\n ? query(\n collection(firestore, scope[0], scope[1], CRM_RECORD_COLLECTIONS[kind]),\n ...crmVisibleToClause(readTokens),\n orderBy('updatedAt', 'desc'),\n limit(CRM_RECORD_PICKER_LIMIT),\n )\n : null,\n [firestore, scope, readTokens, kind],\n { idField: '$id' },\n )\n const options = useMemo(\n () =>\n (data ?? [])\n .map((row) => ({\n id: row.$id,\n label:\n crmRecordName(\n kind,\n row,\n groupId ?? contactPrimaryGroup(row, org).groupId,\n ) || row.$id,\n }))\n .sort((a, b) => a.label.localeCompare(b.label)),\n [data, kind, groupId, org],\n )\n /*\n * The linked record may sit outside the window — an old contact a record\n * page's button linked — so the value is a placeholder carrying its id\n * until (unless) the window turns out to hold it.\n */\n const selected = useMemo(() => {\n if (!value) return null\n return options.find((option) => option.id === value) ?? { id: value, label: value }\n }, [options, value])\n\n return (\n <Autocomplete\n options={options}\n value={selected}\n onChange={(_event, next) => onChange(next?.id ?? null)}\n getOptionLabel={(option) => option.label}\n isOptionEqualToValue={(option, current) => option.id === current.id}\n loading={status === 'loading'}\n disabled={disabled}\n size=\"small\"\n renderInput={(params) => (\n <TextField\n {...params}\n label={PICKER_LABELS[kind]}\n helperText={\n options.length >= CRM_RECORD_PICKER_LIMIT\n ? `The ${CRM_RECORD_PICKER_LIMIT} most recently updated — type to narrow.`\n : undefined\n }\n />\n )}\n />\n )\n}\nCrmRecordPicker.displayName = 'CrmRecordPicker'\n\nexport default CrmRecordPicker\n"],"names":["useFirestore","useFirestoreCollection","Autocomplete","TextField","collection","limit","orderBy","query","useMemo","CRM_RECORD_COLLECTIONS","crmRecordName","crmVisibleToClause","contactPrimaryGroup","CRM_RECORD_PICKER_LIMIT","PICKER_LABELS","contact","company","deal","CrmRecordPicker","props","kind","scope","readTokens","groupId","org","value","onChange","disabled","firestore","data","status","idField","options","map","row","id","$id","label","sort","a","b","localeCompare","selected","find","option","_event","next","getOptionLabel","isOptionEqualToValue","current","loading","size","renderInput","params","helperText","length","undefined","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,SACEA,YAAY,EACZC,sBAAsB,QACjB,iCAAgC;AACvC,SAASC,YAAY,EAAEC,SAAS,QAAQ,gBAAe;AACvD,SAASC,UAAU,EAAEC,KAAK,EAAEC,OAAO,EAAEC,KAAK,QAAQ,qBAAoB;AACtE,SAASC,OAAO,QAAQ,QAAO;AAC/B,SACEC,sBAAsB,EAEtBC,aAAa,QACR,mCAA+B;AACtC,SAASC,kBAAkB,QAAQ,4BAAwB;AAC3D,SAASC,mBAAmB,QAAQ,6BAAyB;AAE7D;;;;;;CAMC,GACD,OAAO,MAAMC,0BAA0B,IAAG;AAE1C,MAAMC,gBAA+C;IACnDC,SAAS;IACTC,SAAS;IACTC,MAAM;AACR;AAoBA;;;;;;;;;;CAUC,GACD,OAAO,SAASC,gBAAgBC,KAA2B;IACzD,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAEC,UAAU,EAAEC,OAAO,EAAEC,GAAG,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,GAAGR;IAC7E,MAAMS,YAAY5B;IAClB,MAAM,EAAE6B,IAAI,EAAEC,MAAM,EAAE,GAAG7B,uBACvB,IACEoB,QACId,MACEH,WAAWwB,WAAWP,KAAK,CAAC,EAAE,EAAEA,KAAK,CAAC,EAAE,EAAEZ,sBAAsB,CAACW,KAAK,MACnET,mBAAmBW,aACtBhB,QAAQ,aAAa,SACrBD,MAAMQ,4BAER,MACN;QAACe;QAAWP;QAAOC;QAAYF;KAAK,EACpC;QAAEW,SAAS;IAAM;IAEnB,MAAMC,UAAUxB,QACd,IACE,CAACqB,eAAAA,OAAQ,EAAE,EACRI,GAAG,CAAC,CAACC,MAAS,CAAA;gBACbC,IAAID,IAAIE,GAAG;gBACXC,OACE3B,cACEU,MACAc,KACAX,kBAAAA,UAAWX,oBAAoBsB,KAAKV,KAAKD,OAAO,KAC7CW,IAAIE,GAAG;YAChB,CAAA,GACCE,IAAI,CAAC,CAACC,GAAGC,IAAMD,EAAEF,KAAK,CAACI,aAAa,CAACD,EAAEH,KAAK,IACjD;QAACR;QAAMT;QAAMG;QAASC;KAAI;IAE5B;;;;GAIC,GACD,MAAMkB,WAAWlC,QAAQ;YAEhBwB;QADP,IAAI,CAACP,OAAO,OAAO;QACnB,QAAOO,gBAAAA,QAAQW,IAAI,CAAC,CAACC,SAAWA,OAAOT,EAAE,KAAKV,kBAAvCO,gBAAiD;YAAEG,IAAIV;YAAOY,OAAOZ;QAAM;IACpF,GAAG;QAACO;QAASP;KAAM;IAEnB,qBACE,KAACvB;QACC8B,SAASA;QACTP,OAAOiB;QACPhB,UAAU,CAACmB,QAAQC;;mBAASpB,iBAASoB,wBAAAA,KAAMX,EAAE,mBAAI;;QACjDY,gBAAgB,CAACH,SAAWA,OAAOP,KAAK;QACxCW,sBAAsB,CAACJ,QAAQK,UAAYL,OAAOT,EAAE,KAAKc,QAAQd,EAAE;QACnEe,SAASpB,WAAW;QACpBH,UAAUA;QACVwB,MAAK;QACLC,aAAa,CAACC,uBACZ,KAAClD,wBACKkD;gBACJhB,OAAOvB,aAAa,CAACM,KAAK;gBAC1BkC,YACEtB,QAAQuB,MAAM,IAAI1C,0BACd,CAAC,IAAI,EAAEA,wBAAwB,wCAAwC,CAAC,GACxE2C;;;AAMhB;AACAtC,gBAAgBuC,WAAW,GAAG;AAE9B,eAAevC,gBAAe"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AglynOrgBilling } from '@aglyn/aglyn';
|
|
2
|
+
export interface CrmSendEmailButtonProps {
|
|
3
|
+
/**
|
|
4
|
+
* The site the message leaves from — passed in, never read off the URL.
|
|
5
|
+
* At the organization level the record's own capturing site (AGL-2630),
|
|
6
|
+
* or `null` for a record no site has captured: beneath the org hub's
|
|
7
|
+
* mount the dialog offers the org's sites to send from (AGL-2634), and
|
|
8
|
+
* only a surface mounted nowhere holds the button.
|
|
9
|
+
*/
|
|
10
|
+
hostId: string | null;
|
|
11
|
+
org?: Partial<AglynOrgBilling> | null;
|
|
12
|
+
contactId?: string;
|
|
13
|
+
leadId?: string;
|
|
14
|
+
dealId?: string;
|
|
15
|
+
/** The record's address, when the page holds it. */
|
|
16
|
+
email?: string | null;
|
|
17
|
+
name?: string | null;
|
|
18
|
+
/**
|
|
19
|
+
* The org's plan lacks the CRM, whose act one-to-one email is
|
|
20
|
+
* (AGL-2788): the button stands locked where it would be, and no dialog
|
|
21
|
+
* opens.
|
|
22
|
+
*/
|
|
23
|
+
suiteLocked?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The **Send email** action a record page carries (AGL-2615): one button,
|
|
27
|
+
* and the dialog it opens, mounted only while open.
|
|
28
|
+
*
|
|
29
|
+
* One component file so a record page adds the action with one import and
|
|
30
|
+
* one line, whichever header the page draws its actions in. Disabled, with
|
|
31
|
+
* the reason, for a record that names nobody to write to — a deal with no
|
|
32
|
+
* contact, a contact with no address — rather than opening a dialog whose
|
|
33
|
+
* To field is blank.
|
|
34
|
+
*/
|
|
35
|
+
export declare function CrmSendEmailButton(props: CrmSendEmailButtonProps): import("react").JSX.Element;
|
|
36
|
+
export declare namespace CrmSendEmailButton {
|
|
37
|
+
var displayName: string;
|
|
38
|
+
}
|
|
39
|
+
export default CrmSendEmailButton;
|
|
@@ -0,0 +1,81 @@
|
|
|
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, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
18
|
+
import { Button, Tooltip } from "@mui/material";
|
|
19
|
+
import { useState } from "react";
|
|
20
|
+
import { useCrmOrgMount } from "../hooks/use-crm-org-mount.js";
|
|
21
|
+
import CrmSendEmailDialog from "./crm-send-email-dialog.js";
|
|
22
|
+
import { CrmSuiteLockedButton } from "./crm-suite-lock.js";
|
|
23
|
+
/**
|
|
24
|
+
* The **Send email** action a record page carries (AGL-2615): one button,
|
|
25
|
+
* and the dialog it opens, mounted only while open.
|
|
26
|
+
*
|
|
27
|
+
* One component file so a record page adds the action with one import and
|
|
28
|
+
* one line, whichever header the page draws its actions in. Disabled, with
|
|
29
|
+
* the reason, for a record that names nobody to write to — a deal with no
|
|
30
|
+
* contact, a contact with no address — rather than opening a dialog whose
|
|
31
|
+
* To field is blank.
|
|
32
|
+
*/ export function CrmSendEmailButton(props) {
|
|
33
|
+
const { hostId, org, contactId, leadId, dealId, email, name, suiteLocked = false } = props;
|
|
34
|
+
const [open, setOpen] = useState(false);
|
|
35
|
+
const address = String(email != null ? email : '').trim();
|
|
36
|
+
const orgMount = useCrmOrgMount();
|
|
37
|
+
if (suiteLocked) {
|
|
38
|
+
return /*#__PURE__*/ _jsx(CrmSuiteLockedButton, {
|
|
39
|
+
variant: "outlined",
|
|
40
|
+
children: 'Send email'
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// A site to send from, or an org whose sites the dialog can offer.
|
|
44
|
+
const canSend = Boolean(hostId) || Boolean(orgMount);
|
|
45
|
+
// A contact can be read for its address on open; a deal names one or
|
|
46
|
+
// nothing; a lead carries its own.
|
|
47
|
+
const reachable = canSend && (Boolean(address) || Boolean(contactId));
|
|
48
|
+
const reason = !reachable ? !canSend ? 'No site has captured this record to send from' : dealId && !contactId ? 'This deal names no contact to email' : 'This record has no email address' : '';
|
|
49
|
+
const button = /*#__PURE__*/ _jsx(Button, {
|
|
50
|
+
size: "small",
|
|
51
|
+
variant: "outlined",
|
|
52
|
+
disabled: !reachable,
|
|
53
|
+
onClick: ()=>setOpen(true),
|
|
54
|
+
children: 'Send email'
|
|
55
|
+
});
|
|
56
|
+
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
57
|
+
children: [
|
|
58
|
+
reason ? /*#__PURE__*/ _jsx(Tooltip, {
|
|
59
|
+
title: reason,
|
|
60
|
+
children: /*#__PURE__*/ _jsx("span", {
|
|
61
|
+
children: button
|
|
62
|
+
})
|
|
63
|
+
}) : button,
|
|
64
|
+
open ? /*#__PURE__*/ _jsx(CrmSendEmailDialog, {
|
|
65
|
+
open: true,
|
|
66
|
+
onClose: ()=>setOpen(false),
|
|
67
|
+
hostId: hostId,
|
|
68
|
+
org: org,
|
|
69
|
+
contactId: contactId,
|
|
70
|
+
leadId: leadId,
|
|
71
|
+
dealId: dealId,
|
|
72
|
+
email: address || null,
|
|
73
|
+
name: name
|
|
74
|
+
}) : null
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
CrmSendEmailButton.displayName = 'CrmSendEmailButton';
|
|
79
|
+
export default CrmSendEmailButton;
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=crm-send-email-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/crm-send-email-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 type { AglynOrgBilling } from '@aglyn/aglyn'\nimport { Button, Tooltip } from '@mui/material'\nimport { useState } from 'react'\nimport { useCrmOrgMount } from '../hooks/use-crm-org-mount'\nimport CrmSendEmailDialog from './crm-send-email-dialog'\nimport { CrmSuiteLockedButton } from './crm-suite-lock'\n\nexport interface CrmSendEmailButtonProps {\n /**\n * The site the message leaves from — passed in, never read off the URL.\n * At the organization level the record's own capturing site (AGL-2630),\n * or `null` for a record no site has captured: beneath the org hub's\n * mount the dialog offers the org's sites to send from (AGL-2634), and\n * only a surface mounted nowhere holds the button.\n */\n hostId: string | null\n org?: Partial<AglynOrgBilling> | null\n contactId?: string\n leadId?: string\n dealId?: string\n /** The record's address, when the page holds it. */\n email?: string | null\n name?: string | null\n /**\n * The org's plan lacks the CRM, whose act one-to-one email is\n * (AGL-2788): the button stands locked where it would be, and no dialog\n * opens.\n */\n suiteLocked?: boolean\n}\n\n/**\n * The **Send email** action a record page carries (AGL-2615): one button,\n * and the dialog it opens, mounted only while open.\n *\n * One component file so a record page adds the action with one import and\n * one line, whichever header the page draws its actions in. Disabled, with\n * the reason, for a record that names nobody to write to — a deal with no\n * contact, a contact with no address — rather than opening a dialog whose\n * To field is blank.\n */\nexport function CrmSendEmailButton(props: CrmSendEmailButtonProps) {\n const { hostId, org, contactId, leadId, dealId, email, name, suiteLocked = false } = props\n const [open, setOpen] = useState(false)\n const address = String(email ?? '').trim()\n const orgMount = useCrmOrgMount()\n if (suiteLocked) {\n return <CrmSuiteLockedButton variant=\"outlined\">{'Send email'}</CrmSuiteLockedButton>\n }\n // A site to send from, or an org whose sites the dialog can offer.\n const canSend = Boolean(hostId) || Boolean(orgMount)\n // A contact can be read for its address on open; a deal names one or\n // nothing; a lead carries its own.\n const reachable = canSend && (Boolean(address) || Boolean(contactId))\n const reason = !reachable\n ? !canSend\n ? 'No site has captured this record to send from'\n : dealId && !contactId\n ? 'This deal names no contact to email'\n : 'This record has no email address'\n : ''\n const button = (\n <Button\n size=\"small\"\n variant=\"outlined\"\n disabled={!reachable}\n onClick={() => setOpen(true)}\n >\n {'Send email'}\n </Button>\n )\n return (\n <>\n {reason ? (\n <Tooltip title={reason}>\n <span>{button}</span>\n </Tooltip>\n ) : (\n button\n )}\n {open ? (\n <CrmSendEmailDialog\n open\n onClose={() => setOpen(false)}\n hostId={hostId}\n org={org}\n contactId={contactId}\n leadId={leadId}\n dealId={dealId}\n email={address || null}\n name={name}\n />\n ) : null}\n </>\n )\n}\nCrmSendEmailButton.displayName = 'CrmSendEmailButton'\n\nexport default CrmSendEmailButton\n"],"names":["Button","Tooltip","useState","useCrmOrgMount","CrmSendEmailDialog","CrmSuiteLockedButton","CrmSendEmailButton","props","hostId","org","contactId","leadId","dealId","email","name","suiteLocked","open","setOpen","address","String","trim","orgMount","variant","canSend","Boolean","reachable","reason","button","size","disabled","onClick","title","span","onClose","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAGA,SAASA,MAAM,EAAEC,OAAO,QAAQ,gBAAe;AAC/C,SAASC,QAAQ,QAAQ,QAAO;AAChC,SAASC,cAAc,QAAQ,gCAA4B;AAC3D,OAAOC,wBAAwB,6BAAyB;AACxD,SAASC,oBAAoB,QAAQ,sBAAkB;AA0BvD;;;;;;;;;CASC,GACD,OAAO,SAASC,mBAAmBC,KAA8B;IAC/D,MAAM,EAAEC,MAAM,EAAEC,GAAG,EAAEC,SAAS,EAAEC,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAEC,cAAc,KAAK,EAAE,GAAGR;IACrF,MAAM,CAACS,MAAMC,QAAQ,GAAGf,SAAS;IACjC,MAAMgB,UAAUC,OAAON,gBAAAA,QAAS,IAAIO,IAAI;IACxC,MAAMC,WAAWlB;IACjB,IAAIY,aAAa;QACf,qBAAO,KAACV;YAAqBiB,SAAQ;sBAAY;;IACnD;IACA,mEAAmE;IACnE,MAAMC,UAAUC,QAAQhB,WAAWgB,QAAQH;IAC3C,qEAAqE;IACrE,mCAAmC;IACnC,MAAMI,YAAYF,WAAYC,CAAAA,QAAQN,YAAYM,QAAQd,UAAS;IACnE,MAAMgB,SAAS,CAACD,YACZ,CAACF,UACC,kDACAX,UAAU,CAACF,YACT,wCACA,qCACJ;IACJ,MAAMiB,uBACJ,KAAC3B;QACC4B,MAAK;QACLN,SAAQ;QACRO,UAAU,CAACJ;QACXK,SAAS,IAAMb,QAAQ;kBAEtB;;IAGL,qBACE;;YACGS,uBACC,KAACzB;gBAAQ8B,OAAOL;0BACd,cAAA,KAACM;8BAAML;;iBAGTA;YAEDX,qBACC,KAACZ;gBACCY,IAAI;gBACJiB,SAAS,IAAMhB,QAAQ;gBACvBT,QAAQA;gBACRC,KAAKA;gBACLC,WAAWA;gBACXC,QAAQA;gBACRC,QAAQA;gBACRC,OAAOK,WAAW;gBAClBJ,MAAMA;iBAEN;;;AAGV;AACAR,mBAAmB4B,WAAW,GAAG;AAEjC,eAAe5B,mBAAkB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type AglynOrgBilling } from '@aglyn/aglyn';
|
|
2
|
+
export interface CrmSendEmailDialogProps {
|
|
3
|
+
open: boolean;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
/**
|
|
6
|
+
* The site the message leaves from — passed in, never assumed from the
|
|
7
|
+
* URL. At the organization level the record's own capturing site, or
|
|
8
|
+
* `null` for a record no site has captured (AGL-2634): the dialog then
|
|
9
|
+
* offers the org's sites to send from, defaulting to the reader's pick.
|
|
10
|
+
*/
|
|
11
|
+
hostId: string | null;
|
|
12
|
+
/** The org the shell passed; lets a deal's contact be read without a lookup. */
|
|
13
|
+
org?: Partial<AglynOrgBilling> | null;
|
|
14
|
+
contactId?: string;
|
|
15
|
+
leadId?: string;
|
|
16
|
+
dealId?: string;
|
|
17
|
+
/**
|
|
18
|
+
* The recipient as the record shows it. A deal's page holds no address,
|
|
19
|
+
* so a caller with only a `contactId` may leave this out and the dialog
|
|
20
|
+
* reads it off the contact when it opens.
|
|
21
|
+
*/
|
|
22
|
+
email?: string | null;
|
|
23
|
+
/** What the dialog says it is writing to, beside the address. */
|
|
24
|
+
name?: string | null;
|
|
25
|
+
/** Told once the route has accepted the message. */
|
|
26
|
+
onSent?: (result: {
|
|
27
|
+
activityId: string;
|
|
28
|
+
}) => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* One email to one person, from their record (AGL-2615).
|
|
32
|
+
*
|
|
33
|
+
* ## What the reader sees, and what they cannot change
|
|
34
|
+
*
|
|
35
|
+
* To is the record's address and is read-only: the route resolves the
|
|
36
|
+
* recipient off the record again, so an editable field here would be a
|
|
37
|
+
* promise the server does not keep. From is the site's sending identity as
|
|
38
|
+
* the sending-identity route reports it — the same answer the campaign
|
|
39
|
+
* composer prints — and when that route refuses, the dialog says why and
|
|
40
|
+
* points at **Emails › Sending** rather than offering a Send button that
|
|
41
|
+
* 409s. Reply-to is the signed-in user's own address, because a reply to a
|
|
42
|
+
* relationship email belongs in the inbox of the person who wrote it, not
|
|
43
|
+
* the site's shared mailbox. Subject and Body are the whole of what a
|
|
44
|
+
* person writes; the body is plain paragraphs, and the email design system
|
|
45
|
+
* is deliberately not here — this is a letter, not a campaign.
|
|
46
|
+
*
|
|
47
|
+
* ## A refusal stays on screen
|
|
48
|
+
*
|
|
49
|
+
* The route's refusals — the daily cap, a suppressed address, a stated
|
|
50
|
+
* refusal, the ceiling — are answers the rep should read, so they render
|
|
51
|
+
* inside the dialog with the draft intact rather than as a toast over a
|
|
52
|
+
* closed one. Only a send the provider accepted closes it.
|
|
53
|
+
*
|
|
54
|
+
* Mounted on open by its button, so the identity request and the contact
|
|
55
|
+
* read happen when somebody asks and not on every record page paint.
|
|
56
|
+
*/
|
|
57
|
+
export declare function CrmSendEmailDialog(props: CrmSendEmailDialogProps): import("react").JSX.Element;
|
|
58
|
+
export declare namespace CrmSendEmailDialog {
|
|
59
|
+
var displayName: string;
|
|
60
|
+
}
|
|
61
|
+
export default CrmSendEmailDialog;
|