@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,348 @@
|
|
|
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 { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
19
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
20
|
+
/**
|
|
21
|
+
* The bar over the tasks list, for whatever rows are ticked (AGL-2621).
|
|
22
|
+
*
|
|
23
|
+
* Complete them, hand them to somebody, move their due date, take them
|
|
24
|
+
* into a spreadsheet, or delete them. Two of these have a side effect
|
|
25
|
+
* outside the document and go through their ROUTE: completing fires
|
|
26
|
+
* `taskCompleted`, which only the server emits, and assigning tells the
|
|
27
|
+
* assignee, which only the server may write into somebody's inbox — so
|
|
28
|
+
* Complete goes through `crm/task-complete` and Assign through
|
|
29
|
+
* `crm/task-save`, exactly as the checkbox and the drawer do for one task.
|
|
30
|
+
* Under a site that is one request per task, each authorized against the
|
|
31
|
+
* site; beneath the organization hub it is ONE request per action, the
|
|
32
|
+
* routes' org-level batch form (AGL-2637), authorized once by the org and
|
|
33
|
+
* answered per task. The due date and the delete have no effect beyond
|
|
34
|
+
* the document, so they are batched client-direct writes under the rules,
|
|
35
|
+
* as reopening is.
|
|
36
|
+
*/ import { CRM_COLLECTIONS } from "@aglyn/aglyn";
|
|
37
|
+
import { useConfirmationContext } from "@aglyn/shared-ui-jsx";
|
|
38
|
+
import { useFirestore, useUser } from "@aglyn/tenant-feature-instance";
|
|
39
|
+
import { Button, MenuItem, TextField } from "@mui/material";
|
|
40
|
+
import { doc, serverTimestamp } from "firebase/firestore";
|
|
41
|
+
import { useCallback, useMemo, useState } from "react";
|
|
42
|
+
import { useCrmBulkApply } from "../hooks/use-crm-bulk-apply.js";
|
|
43
|
+
import { downloadTextFile } from "../model/contacts-csv.js";
|
|
44
|
+
import { refreshCrmNextActivity } from "../model/next-activity-api.js";
|
|
45
|
+
import { crmBulkWriters, runCrmBulkBatch, runCrmBulkCalls, runCrmBulkWrites } from "../model/crm-bulk-writes.js";
|
|
46
|
+
import { completeCrmTask, completeCrmTasks, saveCrmTask, saveCrmTasks } from "../model/task-api.js";
|
|
47
|
+
import { crmTaskCallScope, crmTaskFieldsOf } from "../model/task-routes.js";
|
|
48
|
+
import { dueAtToLocalInput, localInputToDueAt } from "../model/task-views.js";
|
|
49
|
+
import { tasksCsv } from "../model/tasks-csv.js";
|
|
50
|
+
import { CrmBulkBarFrame, CrmBulkValueDialog, countNoun } from "./crm-bulk-bar-frame.js";
|
|
51
|
+
import CrmExportAllButton from "./crm-export-all-button.js";
|
|
52
|
+
const NOUN = {
|
|
53
|
+
singular: 'task',
|
|
54
|
+
plural: 'tasks'
|
|
55
|
+
};
|
|
56
|
+
const ACTION_TITLES = {
|
|
57
|
+
assign: 'Assign to',
|
|
58
|
+
due: 'Set the due date'
|
|
59
|
+
};
|
|
60
|
+
const labelOf = (task)=>task.title || task.$id;
|
|
61
|
+
export function TasksBulkBar(props) {
|
|
62
|
+
if (!props.selected.length) return null;
|
|
63
|
+
return /*#__PURE__*/ _jsx(TasksBulkBarBody, _extends({}, props));
|
|
64
|
+
}
|
|
65
|
+
TasksBulkBar.displayName = 'TasksBulkBar';
|
|
66
|
+
function TasksBulkBarBody(props) {
|
|
67
|
+
var _ref, _directory_error, _ref1;
|
|
68
|
+
const { hostId, scope, rows, selected, onSelectedChange, directory, csv } = props;
|
|
69
|
+
const firestore = useFirestore();
|
|
70
|
+
const { data: user } = useUser();
|
|
71
|
+
const { confirm } = useConfirmationContext();
|
|
72
|
+
const { busy, report, apply, dismissReport } = useCrmBulkApply({
|
|
73
|
+
recordKind: 'task'
|
|
74
|
+
});
|
|
75
|
+
const selectedRows = useMemo(()=>{
|
|
76
|
+
const chosen = new Set(selected);
|
|
77
|
+
return rows.filter((row)=>chosen.has(row.$id));
|
|
78
|
+
}, [
|
|
79
|
+
rows,
|
|
80
|
+
selected
|
|
81
|
+
]);
|
|
82
|
+
const [pending, setPending] = useState(null);
|
|
83
|
+
const [value, setValue] = useState('');
|
|
84
|
+
const writers = useMemo(()=>crmBulkWriters(firestore, (id)=>{
|
|
85
|
+
var _ref, _ref1;
|
|
86
|
+
return doc(firestore, (_ref = scope == null ? void 0 : scope[0]) != null ? _ref : 'orgs', (_ref1 = scope == null ? void 0 : scope[1]) != null ? _ref1 : '', CRM_COLLECTIONS.tasks, id);
|
|
87
|
+
}), [
|
|
88
|
+
firestore,
|
|
89
|
+
scope
|
|
90
|
+
]);
|
|
91
|
+
const openAction = (action)=>{
|
|
92
|
+
setValue('');
|
|
93
|
+
setPending(action);
|
|
94
|
+
};
|
|
95
|
+
// The org the batch form names — the scope's, which is the org's root.
|
|
96
|
+
const orgId = (_ref = scope == null ? void 0 : scope[1]) != null ? _ref : null;
|
|
97
|
+
const runPlan = useCallback(async (plan, done)=>{
|
|
98
|
+
const outcome = await apply({
|
|
99
|
+
attempted: plan.writes.length,
|
|
100
|
+
skipped: plan.skipped,
|
|
101
|
+
job: ()=>runCrmBulkWrites(writers, plan.writes, (write)=>write.label),
|
|
102
|
+
done
|
|
103
|
+
});
|
|
104
|
+
// Client-direct writes: the records the selection names are told
|
|
105
|
+
// (AGL-2661), once each however many tasks named them.
|
|
106
|
+
const written = new Set(plan.writes.map((write)=>write.id));
|
|
107
|
+
await refreshCrmNextActivity(user, crmTaskCallScope(hostId, orgId), selectedRows.filter((task)=>written.has(task.$id)));
|
|
108
|
+
return outcome;
|
|
109
|
+
}, [
|
|
110
|
+
apply,
|
|
111
|
+
writers,
|
|
112
|
+
user,
|
|
113
|
+
hostId,
|
|
114
|
+
orgId,
|
|
115
|
+
selectedRows
|
|
116
|
+
]);
|
|
117
|
+
/**
|
|
118
|
+
* The routes over the rows: under a site one request per task, in
|
|
119
|
+
* order, named by title; beneath the org hub one request for them all,
|
|
120
|
+
* tallied off its per-task answers.
|
|
121
|
+
*/ const runCalls = useCallback((tasks, call, done)=>apply({
|
|
122
|
+
attempted: tasks.length,
|
|
123
|
+
skipped: [],
|
|
124
|
+
job: ()=>hostId ? runCrmBulkCalls(tasks, labelOf, call.each) : runCrmBulkBatch(tasks, (task)=>task.$id, labelOf, async (rows)=>(await call.batch(rows)).map((_0)=>{
|
|
125
|
+
let { taskId } = _0, rest = _object_without_properties_loose(_0, [
|
|
126
|
+
"taskId"
|
|
127
|
+
]);
|
|
128
|
+
return _extends({
|
|
129
|
+
id: taskId
|
|
130
|
+
}, rest);
|
|
131
|
+
})),
|
|
132
|
+
done
|
|
133
|
+
}), [
|
|
134
|
+
apply,
|
|
135
|
+
hostId
|
|
136
|
+
]);
|
|
137
|
+
/*
|
|
138
|
+
* A task already done is left alone rather than sent: the route would
|
|
139
|
+
* answer `alreadyDone` and write nothing, and a request that can only
|
|
140
|
+
* answer nothing is not worth its round trip.
|
|
141
|
+
*/ const handleComplete = useCallback(async ()=>{
|
|
142
|
+
if (!orgId) return;
|
|
143
|
+
const open = selectedRows.filter((task)=>task.status !== 'done');
|
|
144
|
+
await runCalls(open, {
|
|
145
|
+
each: (task)=>completeCrmTask(user, {
|
|
146
|
+
hostId: hostId,
|
|
147
|
+
taskId: task.$id
|
|
148
|
+
}),
|
|
149
|
+
batch: async (tasks)=>(await completeCrmTasks(user, {
|
|
150
|
+
orgId,
|
|
151
|
+
taskIds: tasks.map((task)=>task.$id)
|
|
152
|
+
})).results
|
|
153
|
+
}, (count)=>`Completed ${countNoun(count, NOUN)}`);
|
|
154
|
+
}, [
|
|
155
|
+
selectedRows,
|
|
156
|
+
runCalls,
|
|
157
|
+
user,
|
|
158
|
+
hostId,
|
|
159
|
+
orgId
|
|
160
|
+
]);
|
|
161
|
+
const handleApply = useCallback(async ()=>{
|
|
162
|
+
if (!pending || !scope) return;
|
|
163
|
+
const action = pending;
|
|
164
|
+
setPending(null);
|
|
165
|
+
if (action === 'assign') {
|
|
166
|
+
const assigneeUid = value || null;
|
|
167
|
+
const who = assigneeUid ? directory.nameOf(assigneeUid) : 'nobody';
|
|
168
|
+
const reassigned = (task)=>({
|
|
169
|
+
taskId: task.$id,
|
|
170
|
+
task: _extends({}, crmTaskFieldsOf(task), {
|
|
171
|
+
assigneeUid
|
|
172
|
+
})
|
|
173
|
+
});
|
|
174
|
+
await runCalls(selectedRows, {
|
|
175
|
+
each: (task)=>saveCrmTask(user, _extends({
|
|
176
|
+
hostId: hostId
|
|
177
|
+
}, reassigned(task))),
|
|
178
|
+
batch: async (tasks)=>(await saveCrmTasks(user, {
|
|
179
|
+
orgId: scope[1],
|
|
180
|
+
tasks: tasks.map(reassigned)
|
|
181
|
+
})).results
|
|
182
|
+
}, (count)=>`Assigned ${countNoun(count, NOUN)} to ${who}`);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const dueAtMs = localInputToDueAt(value);
|
|
186
|
+
const writes = selectedRows.map((task)=>({
|
|
187
|
+
id: task.$id,
|
|
188
|
+
label: labelOf(task),
|
|
189
|
+
kind: 'update',
|
|
190
|
+
// `null` rather than a deleted field: every view orders by `dueAtMs`,
|
|
191
|
+
// and a document missing it drops out of the `orderBy` entirely.
|
|
192
|
+
data: {
|
|
193
|
+
dueAtMs,
|
|
194
|
+
updatedAt: serverTimestamp()
|
|
195
|
+
}
|
|
196
|
+
}));
|
|
197
|
+
await runPlan({
|
|
198
|
+
writes,
|
|
199
|
+
skipped: []
|
|
200
|
+
}, (count)=>dueAtMs === null ? `Due date cleared on ${countNoun(count, NOUN)}` : `Due date set on ${countNoun(count, NOUN)}`);
|
|
201
|
+
}, [
|
|
202
|
+
pending,
|
|
203
|
+
scope,
|
|
204
|
+
value,
|
|
205
|
+
directory,
|
|
206
|
+
selectedRows,
|
|
207
|
+
runCalls,
|
|
208
|
+
user,
|
|
209
|
+
hostId,
|
|
210
|
+
runPlan
|
|
211
|
+
]);
|
|
212
|
+
const handleExport = useCallback(()=>{
|
|
213
|
+
downloadTextFile('tasks-selected.csv', 'text/csv', tasksCsv(selectedRows, csv));
|
|
214
|
+
}, [
|
|
215
|
+
selectedRows,
|
|
216
|
+
csv
|
|
217
|
+
]);
|
|
218
|
+
const handleDelete = useCallback(async ()=>{
|
|
219
|
+
if (!scope || !selectedRows.length) return;
|
|
220
|
+
const count = selectedRows.length;
|
|
221
|
+
const confirmed = await confirm({
|
|
222
|
+
title: count === 1 ? 'Delete this task?' : `Delete ${count} tasks?`,
|
|
223
|
+
description: `${count === 1 ? 'It is' : 'They are'} removed for everyone who can ` + 'see them. A finished task is better ticked done, which keeps it in ' + 'the Done view.',
|
|
224
|
+
confirmationText: count === 1 ? 'Delete task' : 'Delete tasks',
|
|
225
|
+
confirmationButtonProps: {
|
|
226
|
+
color: 'error'
|
|
227
|
+
}
|
|
228
|
+
})// `confirm` resolves with no value and REJECTS on cancel.
|
|
229
|
+
.then(()=>true).catch(()=>false);
|
|
230
|
+
if (!confirmed) return;
|
|
231
|
+
const writes = selectedRows.map((task)=>({
|
|
232
|
+
id: task.$id,
|
|
233
|
+
label: labelOf(task),
|
|
234
|
+
kind: 'delete'
|
|
235
|
+
}));
|
|
236
|
+
const outcome = await runPlan({
|
|
237
|
+
writes,
|
|
238
|
+
skipped: []
|
|
239
|
+
}, (done)=>`Deleted ${countNoun(done, NOUN)}`);
|
|
240
|
+
const refused = new Set(outcome.refused.map((row)=>row.label));
|
|
241
|
+
onSelectedChange(selectedRows.filter((task)=>refused.has(labelOf(task))).map((task)=>task.$id));
|
|
242
|
+
}, [
|
|
243
|
+
scope,
|
|
244
|
+
selectedRows,
|
|
245
|
+
confirm,
|
|
246
|
+
runPlan,
|
|
247
|
+
onSelectedChange
|
|
248
|
+
]);
|
|
249
|
+
return /*#__PURE__*/ _jsxs(CrmBulkBarFrame, {
|
|
250
|
+
count: selected.length,
|
|
251
|
+
noun: NOUN,
|
|
252
|
+
busy: busy,
|
|
253
|
+
onClear: ()=>onSelectedChange([]),
|
|
254
|
+
report: report,
|
|
255
|
+
onDismissReport: dismissReport,
|
|
256
|
+
extras: /*#__PURE__*/ _jsx(CrmBulkValueDialog, {
|
|
257
|
+
open: pending !== null,
|
|
258
|
+
title: pending ? ACTION_TITLES[pending] : '',
|
|
259
|
+
count: selected.length,
|
|
260
|
+
noun: NOUN,
|
|
261
|
+
busy: busy,
|
|
262
|
+
canApply: true,
|
|
263
|
+
onClose: ()=>setPending(null),
|
|
264
|
+
onApply: ()=>void handleApply(),
|
|
265
|
+
children: pending === 'assign' ? /*#__PURE__*/ _jsxs(TextField, {
|
|
266
|
+
select: true,
|
|
267
|
+
size: "small",
|
|
268
|
+
label: "Assignee",
|
|
269
|
+
value: value,
|
|
270
|
+
onChange: (event)=>setValue(event.target.value),
|
|
271
|
+
disabled: directory.loading,
|
|
272
|
+
error: Boolean(directory.error),
|
|
273
|
+
helperText: (_directory_error = directory.error) != null ? _directory_error : directory.loading ? 'Loading the team…' : 'Somebody other than you is told, as the drawer tells them',
|
|
274
|
+
children: [
|
|
275
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
276
|
+
value: "",
|
|
277
|
+
children: 'Nobody — clear the assignee'
|
|
278
|
+
}),
|
|
279
|
+
directory.members.map((member)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
280
|
+
value: member.uid,
|
|
281
|
+
children: member.label
|
|
282
|
+
}, member.uid))
|
|
283
|
+
]
|
|
284
|
+
}) : pending === 'due' ? /*#__PURE__*/ _jsx(TextField, {
|
|
285
|
+
size: "small",
|
|
286
|
+
type: "datetime-local",
|
|
287
|
+
label: "Due",
|
|
288
|
+
value: value,
|
|
289
|
+
onChange: (event)=>setValue(event.target.value),
|
|
290
|
+
helperText: "Leave it empty to clear the due date",
|
|
291
|
+
slotProps: {
|
|
292
|
+
inputLabel: {
|
|
293
|
+
shrink: true
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}) : null
|
|
297
|
+
}),
|
|
298
|
+
children: [
|
|
299
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
300
|
+
size: "small",
|
|
301
|
+
disabled: busy || !scope,
|
|
302
|
+
onClick: ()=>void handleComplete(),
|
|
303
|
+
children: 'Complete'
|
|
304
|
+
}),
|
|
305
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
306
|
+
size: "small",
|
|
307
|
+
disabled: busy || !scope,
|
|
308
|
+
onClick: ()=>openAction('assign'),
|
|
309
|
+
children: 'Assign'
|
|
310
|
+
}),
|
|
311
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
312
|
+
size: "small",
|
|
313
|
+
disabled: busy || !scope,
|
|
314
|
+
onClick: ()=>{
|
|
315
|
+
var _selectedRows_;
|
|
316
|
+
openAction('due');
|
|
317
|
+
// Start from the first task's own date, so a nudge is an edit
|
|
318
|
+
// rather than a retype.
|
|
319
|
+
setValue(dueAtToLocalInput((_selectedRows_ = selectedRows[0]) == null ? void 0 : _selectedRows_.dueAtMs));
|
|
320
|
+
},
|
|
321
|
+
children: 'Set due'
|
|
322
|
+
}),
|
|
323
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
324
|
+
size: "small",
|
|
325
|
+
disabled: busy,
|
|
326
|
+
onClick: handleExport,
|
|
327
|
+
children: 'Export CSV'
|
|
328
|
+
}),
|
|
329
|
+
/*#__PURE__*/ _jsx(CrmExportAllButton, {
|
|
330
|
+
resource: "tasks",
|
|
331
|
+
orgId: (_ref1 = scope == null ? void 0 : scope[1]) != null ? _ref1 : null,
|
|
332
|
+
hostId: hostId,
|
|
333
|
+
disabled: busy
|
|
334
|
+
}),
|
|
335
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
336
|
+
size: "small",
|
|
337
|
+
color: "error",
|
|
338
|
+
disabled: busy || !scope,
|
|
339
|
+
onClick: ()=>void handleDelete(),
|
|
340
|
+
children: 'Delete'
|
|
341
|
+
})
|
|
342
|
+
]
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
TasksBulkBarBody.displayName = 'TasksBulkBarBody';
|
|
346
|
+
export default TasksBulkBar;
|
|
347
|
+
|
|
348
|
+
//# sourceMappingURL=tasks-bulk-bar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/tasks-bulk-bar.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\n/**\n * The bar over the tasks list, for whatever rows are ticked (AGL-2621).\n *\n * Complete them, hand them to somebody, move their due date, take them\n * into a spreadsheet, or delete them. Two of these have a side effect\n * outside the document and go through their ROUTE: completing fires\n * `taskCompleted`, which only the server emits, and assigning tells the\n * assignee, which only the server may write into somebody's inbox — so\n * Complete goes through `crm/task-complete` and Assign through\n * `crm/task-save`, exactly as the checkbox and the drawer do for one task.\n * Under a site that is one request per task, each authorized against the\n * site; beneath the organization hub it is ONE request per action, the\n * routes' org-level batch form (AGL-2637), authorized once by the org and\n * answered per task. The due date and the delete have no effect beyond\n * the document, so they are batched client-direct writes under the rules,\n * as reopening is.\n */\n\nimport { CRM_COLLECTIONS } from '@aglyn/aglyn'\nimport { useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport { Button, MenuItem, TextField } from '@mui/material'\nimport { doc, serverTimestamp } from 'firebase/firestore'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useCrmBulkApply } from '../hooks/use-crm-bulk-apply'\nimport type { CrmTaskRow } from '../hooks/use-crm-tasks'\nimport type { OrgMemberDirectory } from '../hooks/use-org-member-directory'\nimport { downloadTextFile } from '../model/contacts-csv'\nimport { refreshCrmNextActivity } from '../model/next-activity-api'\nimport {\n type CrmBulkPlan,\n type CrmBulkWrite,\n crmBulkWriters,\n runCrmBulkBatch,\n runCrmBulkCalls,\n runCrmBulkWrites,\n} from '../model/crm-bulk-writes'\nimport {\n completeCrmTask,\n completeCrmTasks,\n saveCrmTask,\n saveCrmTasks,\n} from '../model/task-api'\nimport { crmTaskCallScope, crmTaskFieldsOf } from '../model/task-routes'\nimport { dueAtToLocalInput, localInputToDueAt } from '../model/task-views'\nimport { type TaskCsvOptions, tasksCsv } from '../model/tasks-csv'\nimport {\n type CrmBulkNoun,\n CrmBulkBarFrame,\n CrmBulkValueDialog,\n countNoun,\n} from './crm-bulk-bar-frame'\nimport CrmExportAllButton from './crm-export-all-button'\n\nexport interface TasksBulkBarProps {\n /**\n * The site the task routes run as, or `null` at the organization level\n * (AGL-2630), where the routes run as the org — their batch form, one\n * request per action (AGL-2637).\n */\n hostId: string | null\n /** `['orgs', orgId]`, or `null` while the org is unresolved. */\n scope: readonly [string, string] | null\n rows: readonly CrmTaskRow[]\n selected: readonly string[]\n onSelectedChange: (ids: string[]) => void\n /** The section's roster — already read for the Assignee column. */\n directory: OrgMemberDirectory\n /** How the export names the assignee and the linked records — the list's own. */\n csv?: TaskCsvOptions\n}\n\nconst NOUN: CrmBulkNoun = { singular: 'task', plural: 'tasks' }\n\ntype PendingAction = 'assign' | 'due'\n\nconst ACTION_TITLES: Record<PendingAction, string> = {\n assign: 'Assign to',\n due: 'Set the due date',\n}\n\nconst labelOf = (task: CrmTaskRow): string => task.title || task.$id\n\nexport function TasksBulkBar(props: TasksBulkBarProps) {\n if (!props.selected.length) return null\n return <TasksBulkBarBody {...props} />\n}\nTasksBulkBar.displayName = 'TasksBulkBar'\n\nfunction TasksBulkBarBody(props: TasksBulkBarProps) {\n const { hostId, scope, rows, selected, onSelectedChange, directory, csv } = props\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { confirm } = useConfirmationContext()\n const { busy, report, apply, dismissReport } = useCrmBulkApply({ recordKind: 'task' })\n\n const selectedRows = useMemo(() => {\n const chosen = new Set(selected)\n return rows.filter((row) => chosen.has(row.$id))\n }, [rows, selected])\n\n const [pending, setPending] = useState<PendingAction | null>(null)\n const [value, setValue] = useState('')\n\n const writers = useMemo(\n () =>\n crmBulkWriters(firestore, (id) =>\n doc(firestore, scope?.[0] ?? 'orgs', scope?.[1] ?? '', CRM_COLLECTIONS.tasks, id),\n ),\n [firestore, scope],\n )\n\n const openAction = (action: PendingAction) => {\n setValue('')\n setPending(action)\n }\n\n // The org the batch form names — the scope's, which is the org's root.\n const orgId = scope?.[1] ?? null\n\n const runPlan = useCallback(\n async (plan: CrmBulkPlan, done: (count: number) => string) => {\n const outcome = await apply({\n attempted: plan.writes.length,\n skipped: plan.skipped,\n job: () => runCrmBulkWrites(writers, plan.writes, (write) => write.label),\n done,\n })\n // Client-direct writes: the records the selection names are told\n // (AGL-2661), once each however many tasks named them.\n const written = new Set(plan.writes.map((write) => write.id))\n await refreshCrmNextActivity(\n user,\n crmTaskCallScope(hostId, orgId),\n selectedRows.filter((task) => written.has(task.$id)),\n )\n return outcome\n },\n [apply, writers, user, hostId, orgId, selectedRows],\n )\n\n /**\n * The routes over the rows: under a site one request per task, in\n * order, named by title; beneath the org hub one request for them all,\n * tallied off its per-task answers.\n */\n const runCalls = useCallback(\n (\n tasks: readonly CrmTaskRow[],\n call: {\n each: (task: CrmTaskRow) => Promise<unknown>\n batch: (tasks: readonly CrmTaskRow[]) => Promise<ReadonlyArray<{ taskId: string; ok: boolean; error?: string }>>\n },\n done: (count: number) => string,\n ) =>\n apply({\n attempted: tasks.length,\n skipped: [],\n job: () =>\n hostId\n ? runCrmBulkCalls(tasks, labelOf, call.each)\n : runCrmBulkBatch(\n tasks,\n (task) => task.$id,\n labelOf,\n async (rows) =>\n (await call.batch(rows)).map(({ taskId, ...rest }) => ({ id: taskId, ...rest })),\n ),\n done,\n }),\n [apply, hostId],\n )\n\n /*\n * A task already done is left alone rather than sent: the route would\n * answer `alreadyDone` and write nothing, and a request that can only\n * answer nothing is not worth its round trip.\n */\n const handleComplete = useCallback(async () => {\n if (!orgId) return\n const open = selectedRows.filter((task) => task.status !== 'done')\n await runCalls(\n open,\n {\n each: (task) => completeCrmTask(user, { hostId: hostId as string, taskId: task.$id }),\n batch: async (tasks) =>\n (await completeCrmTasks(user, { orgId, taskIds: tasks.map((task) => task.$id) }))\n .results,\n },\n (count) => `Completed ${countNoun(count, NOUN)}`,\n )\n }, [selectedRows, runCalls, user, hostId, orgId])\n\n const handleApply = useCallback(async () => {\n if (!pending || !scope) return\n const action = pending\n setPending(null)\n if (action === 'assign') {\n const assigneeUid = value || null\n const who = assigneeUid ? directory.nameOf(assigneeUid) : 'nobody'\n const reassigned = (task: CrmTaskRow) => ({\n taskId: task.$id,\n task: { ...crmTaskFieldsOf(task), assigneeUid },\n })\n await runCalls(\n selectedRows,\n {\n each: (task) => saveCrmTask(user, { hostId: hostId as string, ...reassigned(task) }),\n batch: async (tasks) =>\n (await saveCrmTasks(user, { orgId: scope[1], tasks: tasks.map(reassigned) })).results,\n },\n (count) => `Assigned ${countNoun(count, NOUN)} to ${who}`,\n )\n return\n }\n const dueAtMs = localInputToDueAt(value)\n const writes: CrmBulkWrite[] = selectedRows.map((task) => ({\n id: task.$id,\n label: labelOf(task),\n kind: 'update',\n // `null` rather than a deleted field: every view orders by `dueAtMs`,\n // and a document missing it drops out of the `orderBy` entirely.\n data: { dueAtMs, updatedAt: serverTimestamp() },\n }))\n await runPlan(\n { writes, skipped: [] },\n (count) =>\n dueAtMs === null\n ? `Due date cleared on ${countNoun(count, NOUN)}`\n : `Due date set on ${countNoun(count, NOUN)}`,\n )\n }, [pending, scope, value, directory, selectedRows, runCalls, user, hostId, runPlan])\n\n const handleExport = useCallback(() => {\n downloadTextFile('tasks-selected.csv', 'text/csv', tasksCsv(selectedRows, csv))\n }, [selectedRows, csv])\n\n const handleDelete = useCallback(async () => {\n if (!scope || !selectedRows.length) return\n const count = selectedRows.length\n const confirmed = await confirm({\n title: count === 1 ? 'Delete this task?' : `Delete ${count} tasks?`,\n description:\n `${count === 1 ? 'It is' : 'They are'} removed for everyone who can ` +\n 'see them. A finished task is better ticked done, which keeps it in ' +\n 'the Done view.',\n confirmationText: count === 1 ? 'Delete task' : 'Delete tasks',\n confirmationButtonProps: { color: 'error' },\n })\n // `confirm` resolves with no value and REJECTS on cancel.\n .then(() => true)\n .catch(() => false)\n if (!confirmed) return\n const writes: CrmBulkWrite[] = selectedRows.map((task) => ({\n id: task.$id,\n label: labelOf(task),\n kind: 'delete',\n }))\n const outcome = await runPlan(\n { writes, skipped: [] },\n (done) => `Deleted ${countNoun(done, NOUN)}`,\n )\n const refused = new Set(outcome.refused.map((row) => row.label))\n onSelectedChange(\n selectedRows.filter((task) => refused.has(labelOf(task))).map((task) => task.$id),\n )\n }, [scope, selectedRows, confirm, runPlan, onSelectedChange])\n\n return (\n <CrmBulkBarFrame\n count={selected.length}\n noun={NOUN}\n busy={busy}\n onClear={() => onSelectedChange([])}\n report={report}\n onDismissReport={dismissReport}\n extras={\n <CrmBulkValueDialog\n open={pending !== null}\n title={pending ? ACTION_TITLES[pending] : ''}\n count={selected.length}\n noun={NOUN}\n busy={busy}\n canApply\n onClose={() => setPending(null)}\n onApply={() => void handleApply()}\n >\n {pending === 'assign' ? (\n <TextField\n select\n size=\"small\"\n label=\"Assignee\"\n value={value}\n onChange={(event) => setValue(event.target.value)}\n disabled={directory.loading}\n error={Boolean(directory.error)}\n helperText={\n directory.error ??\n (directory.loading\n ? 'Loading the team…'\n : 'Somebody other than you is told, as the drawer tells them')\n }\n >\n <MenuItem value=\"\">{'Nobody — clear the assignee'}</MenuItem>\n {directory.members.map((member) => (\n <MenuItem key={member.uid} value={member.uid}>\n {member.label}\n </MenuItem>\n ))}\n </TextField>\n ) : pending === 'due' ? (\n <TextField\n size=\"small\"\n type=\"datetime-local\"\n label=\"Due\"\n value={value}\n onChange={(event) => setValue(event.target.value)}\n helperText=\"Leave it empty to clear the due date\"\n slotProps={{ inputLabel: { shrink: true } }}\n />\n ) : null}\n </CrmBulkValueDialog>\n }\n >\n <Button size=\"small\" disabled={busy || !scope} onClick={() => void handleComplete()}>\n {'Complete'}\n </Button>\n <Button size=\"small\" disabled={busy || !scope} onClick={() => openAction('assign')}>\n {'Assign'}\n </Button>\n <Button\n size=\"small\"\n disabled={busy || !scope}\n onClick={() => {\n openAction('due')\n // Start from the first task's own date, so a nudge is an edit\n // rather than a retype.\n setValue(dueAtToLocalInput(selectedRows[0]?.dueAtMs))\n }}\n >\n {'Set due'}\n </Button>\n <Button size=\"small\" disabled={busy} onClick={handleExport}>\n {'Export CSV'}\n </Button>\n {/*\n The selection's file is the rows on screen; this one is the whole\n collection, streamed by the server (AGL-2662).\n */}\n <CrmExportAllButton\n resource=\"tasks\"\n orgId={scope?.[1] ?? null}\n hostId={hostId}\n disabled={busy}\n />\n <Button\n size=\"small\"\n color=\"error\"\n disabled={busy || !scope}\n onClick={() => void handleDelete()}\n >\n {'Delete'}\n </Button>\n </CrmBulkBarFrame>\n )\n}\nTasksBulkBarBody.displayName = 'TasksBulkBarBody'\n\nexport default TasksBulkBar\n"],"names":["CRM_COLLECTIONS","useConfirmationContext","useFirestore","useUser","Button","MenuItem","TextField","doc","serverTimestamp","useCallback","useMemo","useState","useCrmBulkApply","downloadTextFile","refreshCrmNextActivity","crmBulkWriters","runCrmBulkBatch","runCrmBulkCalls","runCrmBulkWrites","completeCrmTask","completeCrmTasks","saveCrmTask","saveCrmTasks","crmTaskCallScope","crmTaskFieldsOf","dueAtToLocalInput","localInputToDueAt","tasksCsv","CrmBulkBarFrame","CrmBulkValueDialog","countNoun","CrmExportAllButton","NOUN","singular","plural","ACTION_TITLES","assign","due","labelOf","task","title","$id","TasksBulkBar","props","selected","length","TasksBulkBarBody","displayName","directory","hostId","scope","rows","onSelectedChange","csv","firestore","data","user","confirm","busy","report","apply","dismissReport","recordKind","selectedRows","chosen","Set","filter","row","has","pending","setPending","value","setValue","writers","id","tasks","openAction","action","orgId","runPlan","plan","done","outcome","attempted","writes","skipped","job","write","label","written","map","runCalls","call","each","batch","taskId","rest","handleComplete","open","status","taskIds","results","count","handleApply","assigneeUid","who","nameOf","reassigned","dueAtMs","kind","updatedAt","handleExport","handleDelete","confirmed","description","confirmationText","confirmationButtonProps","color","then","catch","refused","noun","onClear","onDismissReport","extras","canApply","onClose","onApply","select","size","onChange","event","target","disabled","loading","error","Boolean","helperText","members","member","uid","type","slotProps","inputLabel","shrink","onClick","resource"],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { CrmTaskRow } from '../hooks/use-crm-tasks';
|
|
2
|
+
export interface TasksCalendarProps {
|
|
3
|
+
/** The window the list is holding — the calendar reads no more than it. */
|
|
4
|
+
tasks: readonly CrmTaskRow[];
|
|
5
|
+
/** Open one task's drawer, the same drawer a row opens. */
|
|
6
|
+
onOpen: (task: CrmTaskRow) => void;
|
|
7
|
+
/** The list's window filled, so neither surface is showing everything. */
|
|
8
|
+
truncated?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A MONTH OF TASKS, BY DUE DATE (AGL-2662).
|
|
12
|
+
*
|
|
13
|
+
* The Tasks list answers "what is on my plate"; this answers "what does
|
|
14
|
+
* next week look like", which a list ordered by due date can only imply.
|
|
15
|
+
*
|
|
16
|
+
* ## Drawn over the list's own window, and never over a second read
|
|
17
|
+
*
|
|
18
|
+
* The rows are the ones the section already holds. A calendar that fetched
|
|
19
|
+
* its own month would be a second listener over the same collection, would
|
|
20
|
+
* disagree with the list whenever the two windows differed, and would put
|
|
21
|
+
* a read behind every page of the arrows. What it costs instead is honesty:
|
|
22
|
+
* the grid can only place what the window carries, so the tasks due in
|
|
23
|
+
* other months are counted under it rather than implied to be absent.
|
|
24
|
+
*
|
|
25
|
+
* ## Hand-built rather than a calendar dependency
|
|
26
|
+
*
|
|
27
|
+
* Seven columns of MUI boxes and the local-day arithmetic in
|
|
28
|
+
* `task-calendar.ts`. The one calendar package already installed
|
|
29
|
+
* (`@mui/x-date-pickers`) draws a date PICKER — a grid whose squares are
|
|
30
|
+
* choices, not content — so it answers a different question, and a
|
|
31
|
+
* scheduling library for one surface is a dependency the whole console
|
|
32
|
+
* would carry.
|
|
33
|
+
*/
|
|
34
|
+
export declare function TasksCalendar(props: TasksCalendarProps): import("react").JSX.Element;
|
|
35
|
+
export declare namespace TasksCalendar {
|
|
36
|
+
var displayName: string;
|
|
37
|
+
}
|
|
38
|
+
export default TasksCalendar;
|
|
@@ -0,0 +1,228 @@
|
|
|
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 } from "react/jsx-runtime";
|
|
18
|
+
import { mdiChevronLeft, mdiChevronRight } from "@aglyn/shared-data-mdi";
|
|
19
|
+
import { MdiIcon } from "@aglyn/shared-ui-jsx";
|
|
20
|
+
import { Box, Button, ButtonBase, IconButton, Stack, Typography } from "@mui/material";
|
|
21
|
+
import { useMemo, useState } from "react";
|
|
22
|
+
import { bucketTasksByCalendarDay, CALENDAR_DAY_LABELS, CALENDAR_WEEK_DAYS, shiftCalendarMonth, taskCalendarMonth } from "../model/task-calendar.js";
|
|
23
|
+
/** How many tasks a square lists before folding the rest into a count. */ const TASKS_PER_DAY = 3;
|
|
24
|
+
/**
|
|
25
|
+
* A MONTH OF TASKS, BY DUE DATE (AGL-2662).
|
|
26
|
+
*
|
|
27
|
+
* The Tasks list answers "what is on my plate"; this answers "what does
|
|
28
|
+
* next week look like", which a list ordered by due date can only imply.
|
|
29
|
+
*
|
|
30
|
+
* ## Drawn over the list's own window, and never over a second read
|
|
31
|
+
*
|
|
32
|
+
* The rows are the ones the section already holds. A calendar that fetched
|
|
33
|
+
* its own month would be a second listener over the same collection, would
|
|
34
|
+
* disagree with the list whenever the two windows differed, and would put
|
|
35
|
+
* a read behind every page of the arrows. What it costs instead is honesty:
|
|
36
|
+
* the grid can only place what the window carries, so the tasks due in
|
|
37
|
+
* other months are counted under it rather than implied to be absent.
|
|
38
|
+
*
|
|
39
|
+
* ## Hand-built rather than a calendar dependency
|
|
40
|
+
*
|
|
41
|
+
* Seven columns of MUI boxes and the local-day arithmetic in
|
|
42
|
+
* `task-calendar.ts`. The one calendar package already installed
|
|
43
|
+
* (`@mui/x-date-pickers`) draws a date PICKER — a grid whose squares are
|
|
44
|
+
* choices, not content — so it answers a different question, and a
|
|
45
|
+
* scheduling library for one surface is a dependency the whole console
|
|
46
|
+
* would carry.
|
|
47
|
+
*/ export function TasksCalendar(props) {
|
|
48
|
+
const { tasks, onOpen, truncated } = props;
|
|
49
|
+
/*
|
|
50
|
+
* The clock is read ONCE, at mount. A component that read `Date.now()`
|
|
51
|
+
* per render would move the today square under a reader who left the tab
|
|
52
|
+
* open across midnight, without any state having changed — and the grid
|
|
53
|
+
* is a pure function of this, so what is drawn can be pinned.
|
|
54
|
+
*/ const [nowMs] = useState(()=>Date.now());
|
|
55
|
+
const [anchorMs, setAnchorMs] = useState(()=>nowMs);
|
|
56
|
+
const month = useMemo(()=>taskCalendarMonth(anchorMs, nowMs), [
|
|
57
|
+
anchorMs,
|
|
58
|
+
nowMs
|
|
59
|
+
]);
|
|
60
|
+
const buckets = useMemo(()=>bucketTasksByCalendarDay(tasks, (task)=>task.dueAtMs, month), [
|
|
61
|
+
tasks,
|
|
62
|
+
month
|
|
63
|
+
]);
|
|
64
|
+
const label = useMemo(()=>month.monthDate.toLocaleDateString(undefined, {
|
|
65
|
+
month: 'long',
|
|
66
|
+
year: 'numeric'
|
|
67
|
+
}), [
|
|
68
|
+
month
|
|
69
|
+
]);
|
|
70
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
71
|
+
spacing: 1.5,
|
|
72
|
+
children: [
|
|
73
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
74
|
+
direction: "row",
|
|
75
|
+
spacing: 1,
|
|
76
|
+
sx: {
|
|
77
|
+
alignItems: 'center',
|
|
78
|
+
flexWrap: 'wrap',
|
|
79
|
+
rowGap: 1
|
|
80
|
+
},
|
|
81
|
+
children: [
|
|
82
|
+
/*#__PURE__*/ _jsx(IconButton, {
|
|
83
|
+
size: "small",
|
|
84
|
+
"aria-label": "Previous month",
|
|
85
|
+
onClick: ()=>setAnchorMs((current)=>shiftCalendarMonth(current, -1)),
|
|
86
|
+
children: /*#__PURE__*/ _jsx(MdiIcon, {
|
|
87
|
+
path: mdiChevronLeft.path,
|
|
88
|
+
size: 0.9
|
|
89
|
+
})
|
|
90
|
+
}),
|
|
91
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
92
|
+
variant: "subtitle1",
|
|
93
|
+
sx: {
|
|
94
|
+
minWidth: 160,
|
|
95
|
+
textAlign: 'center'
|
|
96
|
+
},
|
|
97
|
+
children: label
|
|
98
|
+
}),
|
|
99
|
+
/*#__PURE__*/ _jsx(IconButton, {
|
|
100
|
+
size: "small",
|
|
101
|
+
"aria-label": "Next month",
|
|
102
|
+
onClick: ()=>setAnchorMs((current)=>shiftCalendarMonth(current, 1)),
|
|
103
|
+
children: /*#__PURE__*/ _jsx(MdiIcon, {
|
|
104
|
+
path: mdiChevronRight.path,
|
|
105
|
+
size: 0.9
|
|
106
|
+
})
|
|
107
|
+
}),
|
|
108
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
109
|
+
size: "small",
|
|
110
|
+
onClick: ()=>setAnchorMs(nowMs),
|
|
111
|
+
children: 'Today'
|
|
112
|
+
})
|
|
113
|
+
]
|
|
114
|
+
}),
|
|
115
|
+
/*#__PURE__*/ _jsx(Box, {
|
|
116
|
+
sx: {
|
|
117
|
+
overflowX: 'auto'
|
|
118
|
+
},
|
|
119
|
+
children: /*#__PURE__*/ _jsxs(Box, {
|
|
120
|
+
sx: {
|
|
121
|
+
minWidth: 640
|
|
122
|
+
},
|
|
123
|
+
children: [
|
|
124
|
+
/*#__PURE__*/ _jsx(Box, {
|
|
125
|
+
sx: {
|
|
126
|
+
display: 'grid',
|
|
127
|
+
gridTemplateColumns: `repeat(${CALENDAR_WEEK_DAYS}, 1fr)`,
|
|
128
|
+
gap: 0.5,
|
|
129
|
+
mb: 0.5
|
|
130
|
+
},
|
|
131
|
+
children: CALENDAR_DAY_LABELS.map((day)=>/*#__PURE__*/ _jsx(Typography, {
|
|
132
|
+
variant: "caption",
|
|
133
|
+
color: "text.secondary",
|
|
134
|
+
sx: {
|
|
135
|
+
textAlign: 'center'
|
|
136
|
+
},
|
|
137
|
+
children: day
|
|
138
|
+
}, day))
|
|
139
|
+
}),
|
|
140
|
+
/*#__PURE__*/ _jsx(Box, {
|
|
141
|
+
sx: {
|
|
142
|
+
display: 'grid',
|
|
143
|
+
gridTemplateColumns: `repeat(${CALENDAR_WEEK_DAYS}, 1fr)`,
|
|
144
|
+
gap: 0.5
|
|
145
|
+
},
|
|
146
|
+
children: month.weeks.flat().map((day)=>{
|
|
147
|
+
var _buckets_byDay_get;
|
|
148
|
+
const held = (_buckets_byDay_get = buckets.byDay.get(day.startMs)) != null ? _buckets_byDay_get : [];
|
|
149
|
+
const shown = held.slice(0, TASKS_PER_DAY);
|
|
150
|
+
const folded = held.length - shown.length;
|
|
151
|
+
return /*#__PURE__*/ _jsxs(Box, {
|
|
152
|
+
sx: {
|
|
153
|
+
minHeight: 96,
|
|
154
|
+
p: 0.75,
|
|
155
|
+
borderRadius: 1,
|
|
156
|
+
border: 1,
|
|
157
|
+
borderColor: day.isToday ? 'primary.main' : 'divider',
|
|
158
|
+
bgcolor: day.inMonth ? 'background.paper' : 'action.hover'
|
|
159
|
+
},
|
|
160
|
+
children: [
|
|
161
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
162
|
+
variant: "caption",
|
|
163
|
+
sx: {
|
|
164
|
+
display: 'block',
|
|
165
|
+
mb: 0.5,
|
|
166
|
+
fontWeight: day.isToday ? 'fontWeightBold' : undefined,
|
|
167
|
+
color: day.inMonth ? 'text.primary' : 'text.disabled'
|
|
168
|
+
},
|
|
169
|
+
children: day.date
|
|
170
|
+
}),
|
|
171
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
172
|
+
spacing: 0.25,
|
|
173
|
+
children: [
|
|
174
|
+
shown.map((task)=>/*#__PURE__*/ _jsx(ButtonBase, {
|
|
175
|
+
onClick: ()=>onOpen(task),
|
|
176
|
+
sx: {
|
|
177
|
+
justifyContent: 'flex-start',
|
|
178
|
+
width: '100%',
|
|
179
|
+
px: 0.5,
|
|
180
|
+
py: 0.25,
|
|
181
|
+
borderRadius: 0.5,
|
|
182
|
+
bgcolor: 'action.selected',
|
|
183
|
+
'&:hover': {
|
|
184
|
+
bgcolor: 'action.focus'
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
children: /*#__PURE__*/ _jsx(Typography, {
|
|
188
|
+
variant: "caption",
|
|
189
|
+
noWrap: true,
|
|
190
|
+
sx: {
|
|
191
|
+
width: '100%',
|
|
192
|
+
textAlign: 'left',
|
|
193
|
+
textDecoration: task.status === 'done' ? 'line-through' : undefined,
|
|
194
|
+
color: task.status === 'done' ? 'text.secondary' : day.endMs <= nowMs ? 'error.main' : 'text.primary'
|
|
195
|
+
},
|
|
196
|
+
children: task.title
|
|
197
|
+
})
|
|
198
|
+
}, task.$id)),
|
|
199
|
+
folded > 0 ? /*#__PURE__*/ _jsx(Typography, {
|
|
200
|
+
variant: "caption",
|
|
201
|
+
color: "text.secondary",
|
|
202
|
+
children: `+${folded} more`
|
|
203
|
+
}) : null
|
|
204
|
+
]
|
|
205
|
+
})
|
|
206
|
+
]
|
|
207
|
+
}, day.startMs);
|
|
208
|
+
})
|
|
209
|
+
})
|
|
210
|
+
]
|
|
211
|
+
})
|
|
212
|
+
}),
|
|
213
|
+
buckets.undated.length || buckets.elsewhere.length || truncated ? /*#__PURE__*/ _jsx(Typography, {
|
|
214
|
+
variant: "caption",
|
|
215
|
+
color: "text.secondary",
|
|
216
|
+
children: [
|
|
217
|
+
buckets.elsewhere.length ? `${buckets.elsewhere.length} due outside this month` : '',
|
|
218
|
+
buckets.undated.length ? `${buckets.undated.length} with no due date` : '',
|
|
219
|
+
truncated ? 'and the view is showing only its first page' : ''
|
|
220
|
+
].filter(Boolean).join(' · ')
|
|
221
|
+
}) : null
|
|
222
|
+
]
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
TasksCalendar.displayName = 'TasksCalendar';
|
|
226
|
+
export default TasksCalendar;
|
|
227
|
+
|
|
228
|
+
//# sourceMappingURL=tasks-calendar.js.map
|