@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,80 @@
|
|
|
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 { useCallback, useMemo } from "react";
|
|
19
|
+
import { useCrmApi } from "../components/use-crm-api.js";
|
|
20
|
+
/**
|
|
21
|
+
* THE CONSOLE'S DOOR TO `crm/contact-update` (AGL-2804).
|
|
22
|
+
*
|
|
23
|
+
* Every surface that edits a contact's facet saves through here rather than
|
|
24
|
+
* writing the document — the record page's profile, custom fields, files and
|
|
25
|
+
* campaign filing, the company page's link, and the contacts bar — because
|
|
26
|
+
* the rules leave a client nothing in a facet but letting a holder go.
|
|
27
|
+
*
|
|
28
|
+
* Built on `useCrmApi`, so beneath the organization hub's mount the request
|
|
29
|
+
* names the org and the route writes each contact through its own primary
|
|
30
|
+
* holder, and under a site it writes the site's.
|
|
31
|
+
*
|
|
32
|
+
* A request refused WHOLE — no session, no permission, a plan without the CRM
|
|
33
|
+
* — throws with the route's sentence.
|
|
34
|
+
* `updateMany` hands a per-contact answer back in the bulk runners' shape;
|
|
35
|
+
* `updateOne` throws that one contact's refusal, which is what a single
|
|
36
|
+
* record's Save shows.
|
|
37
|
+
*/ export function useContactUpdate(hostId) {
|
|
38
|
+
const callCrm = useCrmApi(hostId);
|
|
39
|
+
const updateMany = useCallback(async (contactIds, set)=>{
|
|
40
|
+
const { response, payload } = await callCrm('contact-update', {
|
|
41
|
+
contactIds: [
|
|
42
|
+
...contactIds
|
|
43
|
+
],
|
|
44
|
+
set
|
|
45
|
+
});
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
const error = payload['error'];
|
|
48
|
+
throw new Error(typeof error === 'string' && error ? error : `The contact could not be saved (${response.status}).`);
|
|
49
|
+
}
|
|
50
|
+
const results = Array.isArray(payload['results']) ? payload['results'] : [];
|
|
51
|
+
return results.map((outcome)=>_extends({
|
|
52
|
+
id: outcome.contactId,
|
|
53
|
+
ok: outcome.ok
|
|
54
|
+
}, 'error' in outcome ? {
|
|
55
|
+
error: outcome.error
|
|
56
|
+
} : {}));
|
|
57
|
+
}, [
|
|
58
|
+
callCrm
|
|
59
|
+
]);
|
|
60
|
+
const updateOne = useCallback(async (contactId, set)=>{
|
|
61
|
+
const [answer] = await updateMany([
|
|
62
|
+
contactId
|
|
63
|
+
], set);
|
|
64
|
+
if (!(answer == null ? void 0 : answer.ok)) {
|
|
65
|
+
throw new Error((answer == null ? void 0 : answer.error) || 'The contact could not be saved.');
|
|
66
|
+
}
|
|
67
|
+
}, [
|
|
68
|
+
updateMany
|
|
69
|
+
]);
|
|
70
|
+
return useMemo(()=>({
|
|
71
|
+
updateMany,
|
|
72
|
+
updateOne
|
|
73
|
+
}), [
|
|
74
|
+
updateMany,
|
|
75
|
+
updateOne
|
|
76
|
+
]);
|
|
77
|
+
}
|
|
78
|
+
export default useContactUpdate;
|
|
79
|
+
|
|
80
|
+
//# sourceMappingURL=use-contact-update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-contact-update.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { useCallback, useMemo } from 'react'\nimport { useCrmApi } from '../components/use-crm-api'\nimport type { ContactUpdateFields, ContactUpdateOutcome } from '../model/contact-update'\nimport type { CrmBulkAnswer } from '../model/crm-bulk-writes'\n\n/**\n * THE CONSOLE'S DOOR TO `crm/contact-update` (AGL-2804).\n *\n * Every surface that edits a contact's facet saves through here rather than\n * writing the document — the record page's profile, custom fields, files and\n * campaign filing, the company page's link, and the contacts bar — because\n * the rules leave a client nothing in a facet but letting a holder go.\n *\n * Built on `useCrmApi`, so beneath the organization hub's mount the request\n * names the org and the route writes each contact through its own primary\n * holder, and under a site it writes the site's.\n *\n * A request refused WHOLE — no session, no permission, a plan without the CRM\n * — throws with the route's sentence.\n * `updateMany` hands a per-contact answer back in the bulk runners' shape;\n * `updateOne` throws that one contact's refusal, which is what a single\n * record's Save shows.\n */\nexport function useContactUpdate(hostId: string | null) {\n const callCrm = useCrmApi(hostId)\n\n const updateMany = useCallback(\n async (\n contactIds: readonly string[],\n set: ContactUpdateFields,\n ): Promise<CrmBulkAnswer[]> => {\n const { response, payload } = await callCrm('contact-update', {\n contactIds: [...contactIds],\n set,\n })\n if (!response.ok) {\n const error = payload['error']\n throw new Error(\n typeof error === 'string' && error\n ? error\n : `The contact could not be saved (${response.status}).`,\n )\n }\n const results: ContactUpdateOutcome[] = Array.isArray(payload['results'])\n ? payload['results']\n : []\n return results.map((outcome) => ({\n id: outcome.contactId,\n ok: outcome.ok,\n ...('error' in outcome ? { error: outcome.error } : {}),\n }))\n },\n [callCrm],\n )\n\n const updateOne = useCallback(\n async (contactId: string, set: ContactUpdateFields): Promise<void> => {\n const [answer] = await updateMany([contactId], set)\n if (!answer?.ok) {\n throw new Error(answer?.error || 'The contact could not be saved.')\n }\n },\n [updateMany],\n )\n\n return useMemo(() => ({ updateMany, updateOne }), [updateMany, updateOne])\n}\n\nexport default useContactUpdate\n"],"names":["useCallback","useMemo","useCrmApi","useContactUpdate","hostId","callCrm","updateMany","contactIds","set","response","payload","ok","error","Error","status","results","Array","isArray","map","outcome","id","contactId","updateOne","answer"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA,SAASA,WAAW,EAAEC,OAAO,QAAQ,QAAO;AAC5C,SAASC,SAAS,QAAQ,+BAA2B;AAIrD;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,SAASC,iBAAiBC,MAAqB;IACpD,MAAMC,UAAUH,UAAUE;IAE1B,MAAME,aAAaN,YACjB,OACEO,YACAC;QAEA,MAAM,EAAEC,QAAQ,EAAEC,OAAO,EAAE,GAAG,MAAML,QAAQ,kBAAkB;YAC5DE,YAAY;mBAAIA;aAAW;YAC3BC;QACF;QACA,IAAI,CAACC,SAASE,EAAE,EAAE;YAChB,MAAMC,QAAQF,OAAO,CAAC,QAAQ;YAC9B,MAAM,IAAIG,MACR,OAAOD,UAAU,YAAYA,QACzBA,QACA,CAAC,gCAAgC,EAAEH,SAASK,MAAM,CAAC,EAAE,CAAC;QAE9D;QACA,MAAMC,UAAkCC,MAAMC,OAAO,CAACP,OAAO,CAAC,UAAU,IACpEA,OAAO,CAAC,UAAU,GAClB,EAAE;QACN,OAAOK,QAAQG,GAAG,CAAC,CAACC,UAAa;gBAC/BC,IAAID,QAAQE,SAAS;gBACrBV,IAAIQ,QAAQR,EAAE;eACV,WAAWQ,UAAU;gBAAEP,OAAOO,QAAQP,KAAK;YAAC,IAAI,CAAC;IAEzD,GACA;QAACP;KAAQ;IAGX,MAAMiB,YAAYtB,YAChB,OAAOqB,WAAmBb;QACxB,MAAM,CAACe,OAAO,GAAG,MAAMjB,WAAW;YAACe;SAAU,EAAEb;QAC/C,IAAI,EAACe,0BAAAA,OAAQZ,EAAE,GAAE;YACf,MAAM,IAAIE,MAAMU,CAAAA,0BAAAA,OAAQX,KAAK,KAAI;QACnC;IACF,GACA;QAACN;KAAW;IAGd,OAAOL,QAAQ,IAAO,CAAA;YAAEK;YAAYgB;QAAU,CAAA,GAAI;QAAChB;QAAYgB;KAAU;AAC3E;AAEA,eAAenB,iBAAgB"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type HostActivityTarget } from '@aglyn/tenant-feature-instance';
|
|
2
|
+
import type { CrmOrgActivityKind } from '../constants/api-routes';
|
|
3
|
+
/**
|
|
4
|
+
* A record kind BOTH feeds accept.
|
|
5
|
+
*
|
|
6
|
+
* The org feed also files tasks and the host feed also files screens, and a
|
|
7
|
+
* line that can land in either has to name something both presenters can
|
|
8
|
+
* render as a link. Spelled as the intersection rather than a third hand-
|
|
9
|
+
* written union so a kind added to one side alone cannot silently become a
|
|
10
|
+
* line the other side draws as unknown.
|
|
11
|
+
*/
|
|
12
|
+
export type CrmActivityKind = Extract<CrmOrgActivityKind, HostActivityTarget['type']>;
|
|
13
|
+
/** What a CRM activity line points at. */
|
|
14
|
+
export interface CrmActivityTarget {
|
|
15
|
+
type: CrmActivityKind;
|
|
16
|
+
id?: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* ONE LINE FOR ONE RECORD, IN THE FEED THE ACT BELONGS TO (AGL-2738).
|
|
21
|
+
*
|
|
22
|
+
* A CRM record is org data whichever hub it is edited from, but the feed
|
|
23
|
+
* that holds "who deleted it" is not: under a SITE the line goes into that
|
|
24
|
+
* site's `hosts/{hostId}/activity` client-direct, and at the ORGANIZATION
|
|
25
|
+
* level it goes into `orgs/{orgId}/activity` through `crm/org-activity`,
|
|
26
|
+
* because the org feed is closed to every client by rule.
|
|
27
|
+
*
|
|
28
|
+
* ## The two gates are on different axes, and that is the bug this closes
|
|
29
|
+
*
|
|
30
|
+
* The record write asks `canWriteOrgData()` — an org role of owner, admin
|
|
31
|
+
* or editor, plus the scope tokens. The line asks `canWriteHostContent()`,
|
|
32
|
+
* which resolves a role out of `hosts/{hostId}.memberRoles[uid]` and knows
|
|
33
|
+
* nothing about the org roster. At the org hub the two come apart for
|
|
34
|
+
* members who are genuinely admitted to the hub:
|
|
35
|
+
*
|
|
36
|
+
* - a pre-`allHosts` member doc reads as org-wide (`isOrgWideMember`) and
|
|
37
|
+
* projects to NO host role at all (`hostRoleFor` returns null without
|
|
38
|
+
* `allHosts`), so an editor holding `data.manage` org-wide appears in no
|
|
39
|
+
* site's `memberRoles`;
|
|
40
|
+
* - an org editor carrying an explicit `hostAccess` entry of `viewer` on
|
|
41
|
+
* one site writes the record and cannot write that site's feed;
|
|
42
|
+
* - a site whose projection never ran, and a SUSPENDED site, refuse the
|
|
43
|
+
* append while the org-level record write goes through untouched.
|
|
44
|
+
*
|
|
45
|
+
* Each of those used to spend its audit line on a rejected client write
|
|
46
|
+
* that `useHostActivityLogger` swallowed. Widening the rule is not the
|
|
47
|
+
* answer — `cloud/rules-tests/firestore-rules.test.mjs` pins that a viewer
|
|
48
|
+
* cannot forge a line, and adding `activity` to the create exclusion list
|
|
49
|
+
* ends host logging rather than moving it. Routing the org-level line
|
|
50
|
+
* through the org's own door is: `crm/org-activity` authorizes the caller
|
|
51
|
+
* on the ORG, which is the axis the record write was authorized on, and
|
|
52
|
+
* appends with the Admin SDK.
|
|
53
|
+
*
|
|
54
|
+
* ## Which door, decided by the MOUNTED site and not by the record's
|
|
55
|
+
*
|
|
56
|
+
* `hostId` here is the site the surface is mounted under, never the site
|
|
57
|
+
* the record was captured by. A record page at the org hub is handed
|
|
58
|
+
* `null` and posts to the org feed; the lead page, which the hub mounts
|
|
59
|
+
* UNDER a site by address (AGL-2630), is handed that site and keeps
|
|
60
|
+
* writing client-direct exactly as it does on the site's own hub. Falling
|
|
61
|
+
* back to the record's own site is what put an org-level act in front of a
|
|
62
|
+
* site-level gate in the first place.
|
|
63
|
+
*
|
|
64
|
+
* This is the same split `useCrmBulkApply` makes for the bulk bars and the
|
|
65
|
+
* email and stage routes make on the server: the level the act was
|
|
66
|
+
* performed at decides the feed.
|
|
67
|
+
*
|
|
68
|
+
* @param hostId the site the surface is MOUNTED under — `props.hostId`,
|
|
69
|
+
* which is `null` at the organization hub. Never the record's own
|
|
70
|
+
* `hostId`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function useCrmActivityLogger(hostId: string | null | undefined): (action: string, target: CrmActivityTarget) => void;
|
|
73
|
+
export default useCrmActivityLogger;
|
|
@@ -0,0 +1,101 @@
|
|
|
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 { useHostActivityLogger } from "@aglyn/tenant-feature-instance";
|
|
18
|
+
import { useCallback } from "react";
|
|
19
|
+
import { useCrmApi } from "../components/use-crm-api.js";
|
|
20
|
+
import { orgActivityRefusal, reportDroppedActivityLine } from "../model/crm-activity-report.js";
|
|
21
|
+
import { useCrmOrgMount } from "./use-crm-org-mount.js";
|
|
22
|
+
/**
|
|
23
|
+
* ONE LINE FOR ONE RECORD, IN THE FEED THE ACT BELONGS TO (AGL-2738).
|
|
24
|
+
*
|
|
25
|
+
* A CRM record is org data whichever hub it is edited from, but the feed
|
|
26
|
+
* that holds "who deleted it" is not: under a SITE the line goes into that
|
|
27
|
+
* site's `hosts/{hostId}/activity` client-direct, and at the ORGANIZATION
|
|
28
|
+
* level it goes into `orgs/{orgId}/activity` through `crm/org-activity`,
|
|
29
|
+
* because the org feed is closed to every client by rule.
|
|
30
|
+
*
|
|
31
|
+
* ## The two gates are on different axes, and that is the bug this closes
|
|
32
|
+
*
|
|
33
|
+
* The record write asks `canWriteOrgData()` — an org role of owner, admin
|
|
34
|
+
* or editor, plus the scope tokens. The line asks `canWriteHostContent()`,
|
|
35
|
+
* which resolves a role out of `hosts/{hostId}.memberRoles[uid]` and knows
|
|
36
|
+
* nothing about the org roster. At the org hub the two come apart for
|
|
37
|
+
* members who are genuinely admitted to the hub:
|
|
38
|
+
*
|
|
39
|
+
* - a pre-`allHosts` member doc reads as org-wide (`isOrgWideMember`) and
|
|
40
|
+
* projects to NO host role at all (`hostRoleFor` returns null without
|
|
41
|
+
* `allHosts`), so an editor holding `data.manage` org-wide appears in no
|
|
42
|
+
* site's `memberRoles`;
|
|
43
|
+
* - an org editor carrying an explicit `hostAccess` entry of `viewer` on
|
|
44
|
+
* one site writes the record and cannot write that site's feed;
|
|
45
|
+
* - a site whose projection never ran, and a SUSPENDED site, refuse the
|
|
46
|
+
* append while the org-level record write goes through untouched.
|
|
47
|
+
*
|
|
48
|
+
* Each of those used to spend its audit line on a rejected client write
|
|
49
|
+
* that `useHostActivityLogger` swallowed. Widening the rule is not the
|
|
50
|
+
* answer — `cloud/rules-tests/firestore-rules.test.mjs` pins that a viewer
|
|
51
|
+
* cannot forge a line, and adding `activity` to the create exclusion list
|
|
52
|
+
* ends host logging rather than moving it. Routing the org-level line
|
|
53
|
+
* through the org's own door is: `crm/org-activity` authorizes the caller
|
|
54
|
+
* on the ORG, which is the axis the record write was authorized on, and
|
|
55
|
+
* appends with the Admin SDK.
|
|
56
|
+
*
|
|
57
|
+
* ## Which door, decided by the MOUNTED site and not by the record's
|
|
58
|
+
*
|
|
59
|
+
* `hostId` here is the site the surface is mounted under, never the site
|
|
60
|
+
* the record was captured by. A record page at the org hub is handed
|
|
61
|
+
* `null` and posts to the org feed; the lead page, which the hub mounts
|
|
62
|
+
* UNDER a site by address (AGL-2630), is handed that site and keeps
|
|
63
|
+
* writing client-direct exactly as it does on the site's own hub. Falling
|
|
64
|
+
* back to the record's own site is what put an org-level act in front of a
|
|
65
|
+
* site-level gate in the first place.
|
|
66
|
+
*
|
|
67
|
+
* This is the same split `useCrmBulkApply` makes for the bulk bars and the
|
|
68
|
+
* email and stage routes make on the server: the level the act was
|
|
69
|
+
* performed at decides the feed.
|
|
70
|
+
*
|
|
71
|
+
* @param hostId the site the surface is MOUNTED under — `props.hostId`,
|
|
72
|
+
* which is `null` at the organization hub. Never the record's own
|
|
73
|
+
* `hostId`.
|
|
74
|
+
*/ export function useCrmActivityLogger(hostId) {
|
|
75
|
+
const mount = useCrmOrgMount();
|
|
76
|
+
const logHostActivity = useHostActivityLogger(hostId != null ? hostId : undefined);
|
|
77
|
+
// `null`, because the line is about the org and not about a site: the
|
|
78
|
+
// hook stamps the mount's `orgId` into the body, which is what makes the
|
|
79
|
+
// call the route's org variant.
|
|
80
|
+
const callCrm = useCrmApi(null);
|
|
81
|
+
return useCallback((action, target)=>{
|
|
82
|
+
if (hostId || !mount) {
|
|
83
|
+
logHostActivity(action, target);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
void callCrm('org-activity', {
|
|
87
|
+
action,
|
|
88
|
+
target
|
|
89
|
+
}).then(({ response, payload })=>{
|
|
90
|
+
if (!response.ok) throw orgActivityRefusal(response.status, payload);
|
|
91
|
+
}).catch(reportDroppedActivityLine);
|
|
92
|
+
}, [
|
|
93
|
+
hostId,
|
|
94
|
+
mount,
|
|
95
|
+
logHostActivity,
|
|
96
|
+
callCrm
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
99
|
+
export default useCrmActivityLogger;
|
|
100
|
+
|
|
101
|
+
//# sourceMappingURL=use-crm-activity-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-crm-activity-logger.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type HostActivityTarget,\n useHostActivityLogger,\n} from '@aglyn/tenant-feature-instance'\nimport { useCallback } from 'react'\nimport { useCrmApi } from '../components/use-crm-api'\nimport type { CrmOrgActivityKind } from '../constants/api-routes'\nimport {\n orgActivityRefusal,\n reportDroppedActivityLine,\n} from '../model/crm-activity-report'\nimport { useCrmOrgMount } from './use-crm-org-mount'\n\n/**\n * A record kind BOTH feeds accept.\n *\n * The org feed also files tasks and the host feed also files screens, and a\n * line that can land in either has to name something both presenters can\n * render as a link. Spelled as the intersection rather than a third hand-\n * written union so a kind added to one side alone cannot silently become a\n * line the other side draws as unknown.\n */\nexport type CrmActivityKind = Extract<\n CrmOrgActivityKind,\n HostActivityTarget['type']\n>\n\n/** What a CRM activity line points at. */\nexport interface CrmActivityTarget {\n type: CrmActivityKind\n id?: string\n name?: string\n}\n\n/**\n * ONE LINE FOR ONE RECORD, IN THE FEED THE ACT BELONGS TO (AGL-2738).\n *\n * A CRM record is org data whichever hub it is edited from, but the feed\n * that holds \"who deleted it\" is not: under a SITE the line goes into that\n * site's `hosts/{hostId}/activity` client-direct, and at the ORGANIZATION\n * level it goes into `orgs/{orgId}/activity` through `crm/org-activity`,\n * because the org feed is closed to every client by rule.\n *\n * ## The two gates are on different axes, and that is the bug this closes\n *\n * The record write asks `canWriteOrgData()` — an org role of owner, admin\n * or editor, plus the scope tokens. The line asks `canWriteHostContent()`,\n * which resolves a role out of `hosts/{hostId}.memberRoles[uid]` and knows\n * nothing about the org roster. At the org hub the two come apart for\n * members who are genuinely admitted to the hub:\n *\n * - a pre-`allHosts` member doc reads as org-wide (`isOrgWideMember`) and\n * projects to NO host role at all (`hostRoleFor` returns null without\n * `allHosts`), so an editor holding `data.manage` org-wide appears in no\n * site's `memberRoles`;\n * - an org editor carrying an explicit `hostAccess` entry of `viewer` on\n * one site writes the record and cannot write that site's feed;\n * - a site whose projection never ran, and a SUSPENDED site, refuse the\n * append while the org-level record write goes through untouched.\n *\n * Each of those used to spend its audit line on a rejected client write\n * that `useHostActivityLogger` swallowed. Widening the rule is not the\n * answer — `cloud/rules-tests/firestore-rules.test.mjs` pins that a viewer\n * cannot forge a line, and adding `activity` to the create exclusion list\n * ends host logging rather than moving it. Routing the org-level line\n * through the org's own door is: `crm/org-activity` authorizes the caller\n * on the ORG, which is the axis the record write was authorized on, and\n * appends with the Admin SDK.\n *\n * ## Which door, decided by the MOUNTED site and not by the record's\n *\n * `hostId` here is the site the surface is mounted under, never the site\n * the record was captured by. A record page at the org hub is handed\n * `null` and posts to the org feed; the lead page, which the hub mounts\n * UNDER a site by address (AGL-2630), is handed that site and keeps\n * writing client-direct exactly as it does on the site's own hub. Falling\n * back to the record's own site is what put an org-level act in front of a\n * site-level gate in the first place.\n *\n * This is the same split `useCrmBulkApply` makes for the bulk bars and the\n * email and stage routes make on the server: the level the act was\n * performed at decides the feed.\n *\n * @param hostId the site the surface is MOUNTED under — `props.hostId`,\n * which is `null` at the organization hub. Never the record's own\n * `hostId`.\n */\nexport function useCrmActivityLogger(hostId: string | null | undefined) {\n const mount = useCrmOrgMount()\n const logHostActivity = useHostActivityLogger(hostId ?? undefined)\n // `null`, because the line is about the org and not about a site: the\n // hook stamps the mount's `orgId` into the body, which is what makes the\n // call the route's org variant.\n const callCrm = useCrmApi(null)\n return useCallback(\n (action: string, target: CrmActivityTarget) => {\n if (hostId || !mount) {\n logHostActivity(action, target)\n return\n }\n void callCrm('org-activity', { action, target })\n .then(({ response, payload }) => {\n if (!response.ok) throw orgActivityRefusal(response.status, payload)\n })\n .catch(reportDroppedActivityLine)\n },\n [hostId, mount, logHostActivity, callCrm],\n )\n}\n\nexport default useCrmActivityLogger\n"],"names":["useHostActivityLogger","useCallback","useCrmApi","orgActivityRefusal","reportDroppedActivityLine","useCrmOrgMount","useCrmActivityLogger","hostId","mount","logHostActivity","undefined","callCrm","action","target","then","response","payload","ok","status","catch"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SAEEA,qBAAqB,QAChB,iCAAgC;AACvC,SAASC,WAAW,QAAQ,QAAO;AACnC,SAASC,SAAS,QAAQ,+BAA2B;AAErD,SACEC,kBAAkB,EAClBC,yBAAyB,QACpB,kCAA8B;AACrC,SAASC,cAAc,QAAQ,yBAAqB;AAuBpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDC,GACD,OAAO,SAASC,qBAAqBC,MAAiC;IACpE,MAAMC,QAAQH;IACd,MAAMI,kBAAkBT,sBAAsBO,iBAAAA,SAAUG;IACxD,sEAAsE;IACtE,yEAAyE;IACzE,gCAAgC;IAChC,MAAMC,UAAUT,UAAU;IAC1B,OAAOD,YACL,CAACW,QAAgBC;QACf,IAAIN,UAAU,CAACC,OAAO;YACpBC,gBAAgBG,QAAQC;YACxB;QACF;QACA,KAAKF,QAAQ,gBAAgB;YAAEC;YAAQC;QAAO,GAC3CC,IAAI,CAAC,CAAC,EAAEC,QAAQ,EAAEC,OAAO,EAAE;YAC1B,IAAI,CAACD,SAASE,EAAE,EAAE,MAAMd,mBAAmBY,SAASG,MAAM,EAAEF;QAC9D,GACCG,KAAK,CAACf;IACX,GACA;QAACG;QAAQC;QAAOC;QAAiBE;KAAQ;AAE7C;AAEA,eAAeL,qBAAoB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { CrmOrgActivityKind } from '../constants/api-routes';
|
|
2
|
+
import { type CrmBulkOutcome, type CrmBulkSkip } from '../model/crm-bulk-writes';
|
|
3
|
+
export interface CrmBulkApplyOptions {
|
|
4
|
+
/**
|
|
5
|
+
* What the bar's rows are — the record kind the ORGANIZATION's feed files
|
|
6
|
+
* the bar's one line under (AGL-2634). A bar that names none writes no
|
|
7
|
+
* org line.
|
|
8
|
+
*/
|
|
9
|
+
recordKind?: CrmOrgActivityKind;
|
|
10
|
+
}
|
|
11
|
+
export interface CrmBulkApplyRun {
|
|
12
|
+
attempted: number;
|
|
13
|
+
skipped: readonly CrmBulkSkip[];
|
|
14
|
+
job: () => Promise<CrmBulkOutcome>;
|
|
15
|
+
done: (count: number) => string;
|
|
16
|
+
/**
|
|
17
|
+
* The job goes through a route that writes its own line per record —
|
|
18
|
+
* a stage move, a loss — so the bar's summary would say it twice.
|
|
19
|
+
*/
|
|
20
|
+
loggedByRoute?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* What a bulk bar does AROUND an action (AGL-2621): mark itself busy, run
|
|
24
|
+
* the job, put the sentence in the snackbar, and hold the refused rows by
|
|
25
|
+
* name until the reader dismisses them. Every bar says the same things in
|
|
26
|
+
* the same places — "Owner set on 3 deals", "Nothing was changed", the
|
|
27
|
+
* warning alert — so the saying lives here once.
|
|
28
|
+
*
|
|
29
|
+
* `job` is whatever applies the plan: the batched runner for a document
|
|
30
|
+
* write, the sequential caller for a route. `attempted` is how many rows
|
|
31
|
+
* the plan wanted to reach, which is what tells "nothing was changed"
|
|
32
|
+
* (it tried and the store refused) from "nothing to change" (every row
|
|
33
|
+
* already said what was asked).
|
|
34
|
+
*
|
|
35
|
+
* ## The organization's line (AGL-2634)
|
|
36
|
+
*
|
|
37
|
+
* Under a site a bar logs what it must into the site's feed itself, one
|
|
38
|
+
* line per record, client-direct. At the ORGANIZATION level there is no
|
|
39
|
+
* site's feed and the org's is closed to clients, so the one thing every
|
|
40
|
+
* bar has in common — the sentence it just put in the snackbar — is posted
|
|
41
|
+
* once, through `crm/org-activity`, as the org feed's line for the action:
|
|
42
|
+
* "Owner set on 3 deals", filed under the bar's record kind. Nothing is
|
|
43
|
+
* posted for an action that changed nothing, and nothing for a job whose
|
|
44
|
+
* route already wrote a line per record.
|
|
45
|
+
*/
|
|
46
|
+
export declare function useCrmBulkApply(options?: CrmBulkApplyOptions): {
|
|
47
|
+
busy: boolean;
|
|
48
|
+
report: CrmBulkSkip[];
|
|
49
|
+
apply: (run: CrmBulkApplyRun) => Promise<CrmBulkOutcome>;
|
|
50
|
+
dismissReport: () => void;
|
|
51
|
+
};
|
|
52
|
+
export default useCrmBulkApply;
|
|
@@ -0,0 +1,112 @@
|
|
|
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 { useSnackbar } from "@aglyn/shared-ui-snackstack";
|
|
18
|
+
import { useCallback, useState } from "react";
|
|
19
|
+
import { useCrmApi } from "../components/use-crm-api.js";
|
|
20
|
+
import { orgActivityRefusal, reportDroppedActivityLine } from "../model/crm-activity-report.js";
|
|
21
|
+
import { bulkReport } from "../model/crm-bulk-writes.js";
|
|
22
|
+
import { useCrmOrgMount } from "./use-crm-org-mount.js";
|
|
23
|
+
/**
|
|
24
|
+
* What a bulk bar does AROUND an action (AGL-2621): mark itself busy, run
|
|
25
|
+
* the job, put the sentence in the snackbar, and hold the refused rows by
|
|
26
|
+
* name until the reader dismisses them. Every bar says the same things in
|
|
27
|
+
* the same places — "Owner set on 3 deals", "Nothing was changed", the
|
|
28
|
+
* warning alert — so the saying lives here once.
|
|
29
|
+
*
|
|
30
|
+
* `job` is whatever applies the plan: the batched runner for a document
|
|
31
|
+
* write, the sequential caller for a route. `attempted` is how many rows
|
|
32
|
+
* the plan wanted to reach, which is what tells "nothing was changed"
|
|
33
|
+
* (it tried and the store refused) from "nothing to change" (every row
|
|
34
|
+
* already said what was asked).
|
|
35
|
+
*
|
|
36
|
+
* ## The organization's line (AGL-2634)
|
|
37
|
+
*
|
|
38
|
+
* Under a site a bar logs what it must into the site's feed itself, one
|
|
39
|
+
* line per record, client-direct. At the ORGANIZATION level there is no
|
|
40
|
+
* site's feed and the org's is closed to clients, so the one thing every
|
|
41
|
+
* bar has in common — the sentence it just put in the snackbar — is posted
|
|
42
|
+
* once, through `crm/org-activity`, as the org feed's line for the action:
|
|
43
|
+
* "Owner set on 3 deals", filed under the bar's record kind. Nothing is
|
|
44
|
+
* posted for an action that changed nothing, and nothing for a job whose
|
|
45
|
+
* route already wrote a line per record.
|
|
46
|
+
*/ export function useCrmBulkApply(options = {}) {
|
|
47
|
+
const { recordKind } = options;
|
|
48
|
+
const { enqueueSnackbar } = useSnackbar();
|
|
49
|
+
const mount = useCrmOrgMount();
|
|
50
|
+
const callCrm = useCrmApi(null);
|
|
51
|
+
const [busy, setBusy] = useState(false);
|
|
52
|
+
const [report, setReport] = useState(null);
|
|
53
|
+
const apply = useCallback(async (run)=>{
|
|
54
|
+
const { attempted, skipped, job, done, loggedByRoute } = run;
|
|
55
|
+
setBusy(true);
|
|
56
|
+
let outcome = {
|
|
57
|
+
done: 0,
|
|
58
|
+
refused: []
|
|
59
|
+
};
|
|
60
|
+
try {
|
|
61
|
+
outcome = await job();
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error(error);
|
|
64
|
+
enqueueSnackbar('An error has occurred', {
|
|
65
|
+
variant: 'error',
|
|
66
|
+
allowDuplicate: true
|
|
67
|
+
});
|
|
68
|
+
setBusy(false);
|
|
69
|
+
return outcome;
|
|
70
|
+
}
|
|
71
|
+
const left = bulkReport({
|
|
72
|
+
skipped: [
|
|
73
|
+
...skipped
|
|
74
|
+
]
|
|
75
|
+
}, outcome);
|
|
76
|
+
setReport(left);
|
|
77
|
+
const sentence = outcome.done ? done(outcome.done) : attempted ? 'Nothing was changed' : 'Nothing to change';
|
|
78
|
+
enqueueSnackbar(sentence, {
|
|
79
|
+
variant: outcome.done && !left ? 'success' : 'warning',
|
|
80
|
+
persist: false
|
|
81
|
+
});
|
|
82
|
+
if (mount && recordKind && outcome.done && !loggedByRoute) {
|
|
83
|
+
// Fire-and-forget, as the site logger is: an audit miss must not
|
|
84
|
+
// turn a finished action into a failed one.
|
|
85
|
+
void callCrm('org-activity', {
|
|
86
|
+
action: sentence,
|
|
87
|
+
target: {
|
|
88
|
+
type: recordKind
|
|
89
|
+
}
|
|
90
|
+
}).then(({ response, payload })=>{
|
|
91
|
+
if (!response.ok) throw orgActivityRefusal(response.status, payload);
|
|
92
|
+
}).catch(reportDroppedActivityLine);
|
|
93
|
+
}
|
|
94
|
+
setBusy(false);
|
|
95
|
+
return outcome;
|
|
96
|
+
}, [
|
|
97
|
+
enqueueSnackbar,
|
|
98
|
+
mount,
|
|
99
|
+
recordKind,
|
|
100
|
+
callCrm
|
|
101
|
+
]);
|
|
102
|
+
const dismissReport = useCallback(()=>setReport(null), []);
|
|
103
|
+
return {
|
|
104
|
+
busy,
|
|
105
|
+
report,
|
|
106
|
+
apply,
|
|
107
|
+
dismissReport
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
export default useCrmBulkApply;
|
|
111
|
+
|
|
112
|
+
//# sourceMappingURL=use-crm-bulk-apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-crm-bulk-apply.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useCallback, useState } from 'react'\nimport { useCrmApi } from '../components/use-crm-api'\nimport type { CrmOrgActivityKind } from '../constants/api-routes'\nimport {\n orgActivityRefusal,\n reportDroppedActivityLine,\n} from '../model/crm-activity-report'\nimport {\n bulkReport,\n type CrmBulkOutcome,\n type CrmBulkSkip,\n} from '../model/crm-bulk-writes'\nimport { useCrmOrgMount } from './use-crm-org-mount'\n\nexport interface CrmBulkApplyOptions {\n /**\n * What the bar's rows are — the record kind the ORGANIZATION's feed files\n * the bar's one line under (AGL-2634). A bar that names none writes no\n * org line.\n */\n recordKind?: CrmOrgActivityKind\n}\n\nexport interface CrmBulkApplyRun {\n attempted: number\n skipped: readonly CrmBulkSkip[]\n job: () => Promise<CrmBulkOutcome>\n done: (count: number) => string\n /**\n * The job goes through a route that writes its own line per record —\n * a stage move, a loss — so the bar's summary would say it twice.\n */\n loggedByRoute?: boolean\n}\n\n/**\n * What a bulk bar does AROUND an action (AGL-2621): mark itself busy, run\n * the job, put the sentence in the snackbar, and hold the refused rows by\n * name until the reader dismisses them. Every bar says the same things in\n * the same places — \"Owner set on 3 deals\", \"Nothing was changed\", the\n * warning alert — so the saying lives here once.\n *\n * `job` is whatever applies the plan: the batched runner for a document\n * write, the sequential caller for a route. `attempted` is how many rows\n * the plan wanted to reach, which is what tells \"nothing was changed\"\n * (it tried and the store refused) from \"nothing to change\" (every row\n * already said what was asked).\n *\n * ## The organization's line (AGL-2634)\n *\n * Under a site a bar logs what it must into the site's feed itself, one\n * line per record, client-direct. At the ORGANIZATION level there is no\n * site's feed and the org's is closed to clients, so the one thing every\n * bar has in common — the sentence it just put in the snackbar — is posted\n * once, through `crm/org-activity`, as the org feed's line for the action:\n * \"Owner set on 3 deals\", filed under the bar's record kind. Nothing is\n * posted for an action that changed nothing, and nothing for a job whose\n * route already wrote a line per record.\n */\nexport function useCrmBulkApply(options: CrmBulkApplyOptions = {}) {\n const { recordKind } = options\n const { enqueueSnackbar } = useSnackbar()\n const mount = useCrmOrgMount()\n const callCrm = useCrmApi(null)\n const [busy, setBusy] = useState(false)\n const [report, setReport] = useState<CrmBulkSkip[] | null>(null)\n\n const apply = useCallback(\n async (run: CrmBulkApplyRun): Promise<CrmBulkOutcome> => {\n const { attempted, skipped, job, done, loggedByRoute } = run\n setBusy(true)\n let outcome: CrmBulkOutcome = { done: 0, refused: [] }\n try {\n outcome = await job()\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n setBusy(false)\n return outcome\n }\n const left = bulkReport({ skipped: [...skipped] }, outcome)\n setReport(left)\n const sentence = outcome.done\n ? done(outcome.done)\n : attempted\n ? 'Nothing was changed'\n : 'Nothing to change'\n enqueueSnackbar(sentence, {\n variant: outcome.done && !left ? 'success' : 'warning',\n persist: false,\n })\n if (mount && recordKind && outcome.done && !loggedByRoute) {\n // Fire-and-forget, as the site logger is: an audit miss must not\n // turn a finished action into a failed one.\n void callCrm('org-activity', {\n action: sentence,\n target: { type: recordKind },\n })\n .then(({ response, payload }) => {\n if (!response.ok) throw orgActivityRefusal(response.status, payload)\n })\n .catch(reportDroppedActivityLine)\n }\n setBusy(false)\n return outcome\n },\n [enqueueSnackbar, mount, recordKind, callCrm],\n )\n\n const dismissReport = useCallback(() => setReport(null), [])\n\n return { busy, report, apply, dismissReport }\n}\n\nexport default useCrmBulkApply\n"],"names":["useSnackbar","useCallback","useState","useCrmApi","orgActivityRefusal","reportDroppedActivityLine","bulkReport","useCrmOrgMount","useCrmBulkApply","options","recordKind","enqueueSnackbar","mount","callCrm","busy","setBusy","report","setReport","apply","run","attempted","skipped","job","done","loggedByRoute","outcome","refused","error","console","variant","allowDuplicate","left","sentence","persist","action","target","type","then","response","payload","ok","status","catch","dismissReport"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SAASA,WAAW,QAAQ,8BAA6B;AACzD,SAASC,WAAW,EAAEC,QAAQ,QAAQ,QAAO;AAC7C,SAASC,SAAS,QAAQ,+BAA2B;AAErD,SACEC,kBAAkB,EAClBC,yBAAyB,QACpB,kCAA8B;AACrC,SACEC,UAAU,QAGL,8BAA0B;AACjC,SAASC,cAAc,QAAQ,yBAAqB;AAuBpD;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GACD,OAAO,SAASC,gBAAgBC,UAA+B,CAAC,CAAC;IAC/D,MAAM,EAAEC,UAAU,EAAE,GAAGD;IACvB,MAAM,EAAEE,eAAe,EAAE,GAAGX;IAC5B,MAAMY,QAAQL;IACd,MAAMM,UAAUV,UAAU;IAC1B,MAAM,CAACW,MAAMC,QAAQ,GAAGb,SAAS;IACjC,MAAM,CAACc,QAAQC,UAAU,GAAGf,SAA+B;IAE3D,MAAMgB,QAAQjB,YACZ,OAAOkB;QACL,MAAM,EAAEC,SAAS,EAAEC,OAAO,EAAEC,GAAG,EAAEC,IAAI,EAAEC,aAAa,EAAE,GAAGL;QACzDJ,QAAQ;QACR,IAAIU,UAA0B;YAAEF,MAAM;YAAGG,SAAS,EAAE;QAAC;QACrD,IAAI;YACFD,UAAU,MAAMH;QAClB,EAAE,OAAOK,OAAO;YACdC,QAAQD,KAAK,CAACA;YACdhB,gBAAgB,yBAAyB;gBACvCkB,SAAS;gBACTC,gBAAgB;YAClB;YACAf,QAAQ;YACR,OAAOU;QACT;QACA,MAAMM,OAAOzB,WAAW;YAAEe,SAAS;mBAAIA;aAAQ;QAAC,GAAGI;QACnDR,UAAUc;QACV,MAAMC,WAAWP,QAAQF,IAAI,GACzBA,KAAKE,QAAQF,IAAI,IACjBH,YACE,wBACA;QACNT,gBAAgBqB,UAAU;YACxBH,SAASJ,QAAQF,IAAI,IAAI,CAACQ,OAAO,YAAY;YAC7CE,SAAS;QACX;QACA,IAAIrB,SAASF,cAAce,QAAQF,IAAI,IAAI,CAACC,eAAe;YACzD,iEAAiE;YACjE,4CAA4C;YAC5C,KAAKX,QAAQ,gBAAgB;gBAC3BqB,QAAQF;gBACRG,QAAQ;oBAAEC,MAAM1B;gBAAW;YAC7B,GACG2B,IAAI,CAAC,CAAC,EAAEC,QAAQ,EAAEC,OAAO,EAAE;gBAC1B,IAAI,CAACD,SAASE,EAAE,EAAE,MAAMpC,mBAAmBkC,SAASG,MAAM,EAAEF;YAC9D,GACCG,KAAK,CAACrC;QACX;QACAU,QAAQ;QACR,OAAOU;IACT,GACA;QAACd;QAAiBC;QAAOF;QAAYG;KAAQ;IAG/C,MAAM8B,gBAAgB1C,YAAY,IAAMgB,UAAU,OAAO,EAAE;IAE3D,OAAO;QAAEH;QAAME;QAAQE;QAAOyB;IAAc;AAC9C;AAEA,eAAenC,gBAAe"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type CrmViewSection } from '@aglyn/aglyn';
|
|
2
|
+
/**
|
|
3
|
+
* The view a section opens on for THIS reader (AGL-2617).
|
|
4
|
+
*
|
|
5
|
+
* Read from and written to the reader's own profile document, beside the
|
|
6
|
+
* notification mutes that live there, because it is the same kind of fact:
|
|
7
|
+
* one person's preference for their own console, which the rules let them
|
|
8
|
+
* and nobody else write. A merged write keeps the other organizations' and
|
|
9
|
+
* sections' defaults on the same document, and the mutes beside them.
|
|
10
|
+
*
|
|
11
|
+
* One document read per reader per session — the profile listener the
|
|
12
|
+
* avatar and name hooks already hold — rather than a field on the view,
|
|
13
|
+
* where "default" would have to mean everybody's.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useCrmDefaultView(options: {
|
|
16
|
+
uid: string | null | undefined;
|
|
17
|
+
orgId: string | null;
|
|
18
|
+
section: CrmViewSection;
|
|
19
|
+
}): {
|
|
20
|
+
defaultViewId: string | null;
|
|
21
|
+
ready: boolean;
|
|
22
|
+
setDefault: (viewId: string | null) => Promise<void>;
|
|
23
|
+
};
|
|
24
|
+
export default useCrmDefaultView;
|
|
@@ -0,0 +1,64 @@
|
|
|
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 { crmDefaultViewId, crmDefaultViewPatch } from "@aglyn/aglyn";
|
|
18
|
+
import { useFirestore, useFirestoreDoc } from "@aglyn/tenant-feature-instance";
|
|
19
|
+
import { doc, setDoc } from "firebase/firestore";
|
|
20
|
+
import { useCallback, useMemo } from "react";
|
|
21
|
+
/**
|
|
22
|
+
* The view a section opens on for THIS reader (AGL-2617).
|
|
23
|
+
*
|
|
24
|
+
* Read from and written to the reader's own profile document, beside the
|
|
25
|
+
* notification mutes that live there, because it is the same kind of fact:
|
|
26
|
+
* one person's preference for their own console, which the rules let them
|
|
27
|
+
* and nobody else write. A merged write keeps the other organizations' and
|
|
28
|
+
* sections' defaults on the same document, and the mutes beside them.
|
|
29
|
+
*
|
|
30
|
+
* One document read per reader per session — the profile listener the
|
|
31
|
+
* avatar and name hooks already hold — rather than a field on the view,
|
|
32
|
+
* where "default" would have to mean everybody's.
|
|
33
|
+
*/ export function useCrmDefaultView(options) {
|
|
34
|
+
const { uid, orgId, section } = options;
|
|
35
|
+
const firestore = useFirestore();
|
|
36
|
+
const { data: profile, status } = useFirestoreDoc(()=>uid ? doc(firestore, 'users', uid) : null, [
|
|
37
|
+
firestore,
|
|
38
|
+
uid
|
|
39
|
+
]);
|
|
40
|
+
const defaultViewId = useMemo(()=>crmDefaultViewId(profile != null ? profile : null, orgId, section), [
|
|
41
|
+
profile,
|
|
42
|
+
orgId,
|
|
43
|
+
section
|
|
44
|
+
]);
|
|
45
|
+
const setDefault = useCallback(async (viewId)=>{
|
|
46
|
+
if (!uid || !orgId) return;
|
|
47
|
+
await setDoc(doc(firestore, 'users', uid), crmDefaultViewPatch(orgId, section, viewId), {
|
|
48
|
+
merge: true
|
|
49
|
+
});
|
|
50
|
+
}, [
|
|
51
|
+
firestore,
|
|
52
|
+
uid,
|
|
53
|
+
orgId,
|
|
54
|
+
section
|
|
55
|
+
]);
|
|
56
|
+
return {
|
|
57
|
+
defaultViewId,
|
|
58
|
+
ready: !uid || status !== 'loading',
|
|
59
|
+
setDefault
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export default useCrmDefaultView;
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=use-crm-default-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-crm-default-view.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type CrmViewSection,\n crmDefaultViewId,\n crmDefaultViewPatch,\n} from '@aglyn/aglyn'\nimport { useFirestore, useFirestoreDoc } from '@aglyn/tenant-feature-instance'\nimport { doc, setDoc } from 'firebase/firestore'\nimport { useCallback, useMemo } from 'react'\n\n/**\n * The view a section opens on for THIS reader (AGL-2617).\n *\n * Read from and written to the reader's own profile document, beside the\n * notification mutes that live there, because it is the same kind of fact:\n * one person's preference for their own console, which the rules let them\n * and nobody else write. A merged write keeps the other organizations' and\n * sections' defaults on the same document, and the mutes beside them.\n *\n * One document read per reader per session — the profile listener the\n * avatar and name hooks already hold — rather than a field on the view,\n * where \"default\" would have to mean everybody's.\n */\nexport function useCrmDefaultView(options: {\n uid: string | null | undefined\n orgId: string | null\n section: CrmViewSection\n}): {\n defaultViewId: string | null\n ready: boolean\n setDefault: (viewId: string | null) => Promise<void>\n} {\n const { uid, orgId, section } = options\n const firestore = useFirestore()\n const { data: profile, status } = useFirestoreDoc<Record<string, unknown>>(\n () => (uid ? doc(firestore, 'users', uid) : null),\n [firestore, uid],\n )\n const defaultViewId = useMemo(\n () => crmDefaultViewId(profile ?? null, orgId, section),\n [profile, orgId, section],\n )\n const setDefault = useCallback(\n async (viewId: string | null) => {\n if (!uid || !orgId) return\n await setDoc(\n doc(firestore, 'users', uid),\n crmDefaultViewPatch(orgId, section, viewId),\n { merge: true },\n )\n },\n [firestore, uid, orgId, section],\n )\n return {\n defaultViewId,\n ready: !uid || status !== 'loading',\n setDefault,\n }\n}\n\nexport default useCrmDefaultView\n"],"names":["crmDefaultViewId","crmDefaultViewPatch","useFirestore","useFirestoreDoc","doc","setDoc","useCallback","useMemo","useCrmDefaultView","options","uid","orgId","section","firestore","data","profile","status","defaultViewId","setDefault","viewId","merge","ready"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SAEEA,gBAAgB,EAChBC,mBAAmB,QACd,eAAc;AACrB,SAASC,YAAY,EAAEC,eAAe,QAAQ,iCAAgC;AAC9E,SAASC,GAAG,EAAEC,MAAM,QAAQ,qBAAoB;AAChD,SAASC,WAAW,EAAEC,OAAO,QAAQ,QAAO;AAE5C;;;;;;;;;;;;CAYC,GACD,OAAO,SAASC,kBAAkBC,OAIjC;IAKC,MAAM,EAAEC,GAAG,EAAEC,KAAK,EAAEC,OAAO,EAAE,GAAGH;IAChC,MAAMI,YAAYX;IAClB,MAAM,EAAEY,MAAMC,OAAO,EAAEC,MAAM,EAAE,GAAGb,gBAChC,IAAOO,MAAMN,IAAIS,WAAW,SAASH,OAAO,MAC5C;QAACG;QAAWH;KAAI;IAElB,MAAMO,gBAAgBV,QACpB,IAAMP,iBAAiBe,kBAAAA,UAAW,MAAMJ,OAAOC,UAC/C;QAACG;QAASJ;QAAOC;KAAQ;IAE3B,MAAMM,aAAaZ,YACjB,OAAOa;QACL,IAAI,CAACT,OAAO,CAACC,OAAO;QACpB,MAAMN,OACJD,IAAIS,WAAW,SAASH,MACxBT,oBAAoBU,OAAOC,SAASO,SACpC;YAAEC,OAAO;QAAK;IAElB,GACA;QAACP;QAAWH;QAAKC;QAAOC;KAAQ;IAElC,OAAO;QACLK;QACAI,OAAO,CAACX,OAAOM,WAAW;QAC1BE;IACF;AACF;AAEA,eAAeV,kBAAiB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type CrmEmailTemplateRow, type ScopeToken } from '@aglyn/aglyn';
|
|
2
|
+
import { type CrmOrgDoc } from './use-crm-scope';
|
|
3
|
+
export interface CrmEmailTemplateScope {
|
|
4
|
+
/** The org data root, or `null` until the org lookup settles or when there is none. */
|
|
5
|
+
scope: readonly ['orgs', string] | null;
|
|
6
|
+
orgId: string | null;
|
|
7
|
+
ready: boolean;
|
|
8
|
+
/** The listener's clause under a site; `null` at the organization level. */
|
|
9
|
+
visibleTo: readonly ScopeToken[] | null;
|
|
10
|
+
/**
|
|
11
|
+
* The site a template written here is filed under, or `null` for the
|
|
12
|
+
* organization's own — see {@link useCrmEmailTemplateScope}.
|
|
13
|
+
*/
|
|
14
|
+
createHostId: string | null;
|
|
15
|
+
/** What a template written here is stamped with; empty while no site is known. */
|
|
16
|
+
createTokens: readonly ScopeToken[];
|
|
17
|
+
/** The holder group whose facet the merge fields read a contact by. */
|
|
18
|
+
groupId: string | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Where an email template lives, for the surface writing or listing it
|
|
22
|
+
* (AGL-2658).
|
|
23
|
+
*
|
|
24
|
+
* Under a site it is the site's, as a task is: stamped with the site's
|
|
25
|
+
* tokens and `hostId`. From the ORGANIZATION's own hub it is the
|
|
26
|
+
* organization's — `hostId: null`, the org token alone — the way an
|
|
27
|
+
* organization task is (AGL-2637): a letter the whole workspace keeps is
|
|
28
|
+
* not one brand's, and the org-level reader is an org-wide member who may
|
|
29
|
+
* stamp it so. Every site's hub lists it beside its own, because a site's
|
|
30
|
+
* read tokens carry the org token.
|
|
31
|
+
*/
|
|
32
|
+
export declare function useCrmEmailTemplateScope(props: {
|
|
33
|
+
hostId: string | null | undefined;
|
|
34
|
+
org?: CrmOrgDoc;
|
|
35
|
+
}): CrmEmailTemplateScope;
|
|
36
|
+
/**
|
|
37
|
+
* The templates and snippets this member may pick from (AGL-2658): every
|
|
38
|
+
* shared one the reader's scope reaches, and the personal ones they own.
|
|
39
|
+
*
|
|
40
|
+
* ONE bounded listener, filtered on the reader's tokens like every CRM read
|
|
41
|
+
* and ordered by name — the `(visibleTo, name)` index under a site, the
|
|
42
|
+
* automatic single-field one at the organization level. A colleague's
|
|
43
|
+
* personal template is readable under the rules and hidden here by
|
|
44
|
+
* `crmEmailTemplateIsListed`, for the reason a private saved view is
|
|
45
|
+
* (AGL-2617). Rows past the window are not listed; the console's create
|
|
46
|
+
* stops at the window, so a workspace cannot write what its menu cannot
|
|
47
|
+
* show.
|
|
48
|
+
*/
|
|
49
|
+
export declare function useCrmEmailTemplates(options: {
|
|
50
|
+
scope: readonly ['orgs', string] | null;
|
|
51
|
+
/** The reader's tokens, or `null` at the organization level — no clause. */
|
|
52
|
+
visibleTo: readonly string[] | null;
|
|
53
|
+
uid: string | null | undefined;
|
|
54
|
+
}): {
|
|
55
|
+
templates: CrmEmailTemplateRow[];
|
|
56
|
+
ready: boolean;
|
|
57
|
+
fromCache: boolean;
|
|
58
|
+
};
|
|
59
|
+
export default useCrmEmailTemplates;
|