@aglyn/plugins-outreach 1.0.0-beta.223 → 1.0.0-beta.225

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +10 -4
  2. package/package.json +14 -14
  3. package/src/lib/components/enrollment-detail.d.ts +8 -0
  4. package/src/lib/components/enrollment-detail.js +17 -5
  5. package/src/lib/components/enrollment-detail.js.map +1 -1
  6. package/src/lib/components/mailbox-card.d.ts +3 -3
  7. package/src/lib/components/mailbox-card.js +11 -5
  8. package/src/lib/components/mailbox-card.js.map +1 -1
  9. package/src/lib/components/mailboxes-section.d.ts +6 -5
  10. package/src/lib/components/mailboxes-section.js +61 -26
  11. package/src/lib/components/mailboxes-section.js.map +1 -1
  12. package/src/lib/components/sequence-detail.js +1 -1
  13. package/src/lib/components/sequence-detail.js.map +1 -1
  14. package/src/lib/components/sequence-editor.js +29 -4
  15. package/src/lib/components/sequence-editor.js.map +1 -1
  16. package/src/lib/components/sequence-mailbox-picker.d.ts +21 -0
  17. package/src/lib/components/sequence-mailbox-picker.js +74 -13
  18. package/src/lib/components/sequence-mailbox-picker.js.map +1 -1
  19. package/src/lib/components/use-outreach-mailbox-api.d.ts +10 -2
  20. package/src/lib/components/use-outreach-mailbox-api.js +7 -2
  21. package/src/lib/components/use-outreach-mailbox-api.js.map +1 -1
  22. package/src/lib/engine/enrollment-state.d.ts +6 -0
  23. package/src/lib/engine/enrollment-state.js +1 -1
  24. package/src/lib/engine/enrollment-state.js.map +1 -1
  25. package/src/lib/engine/index.d.ts +1 -0
  26. package/src/lib/engine/index.js +1 -0
  27. package/src/lib/engine/index.js.map +1 -1
  28. package/src/lib/engine/mailbox-notice.d.ts +5 -2
  29. package/src/lib/engine/mailbox-notice.js +6 -2
  30. package/src/lib/engine/mailbox-notice.js.map +1 -1
  31. package/src/lib/engine/mailbox-rotation.d.ts +41 -0
  32. package/src/lib/engine/mailbox-rotation.js +71 -0
  33. package/src/lib/engine/mailbox-rotation.js.map +1 -0
  34. package/src/lib/mailboxes/mailbox-api.d.ts +30 -11
  35. package/src/lib/mailboxes/mailbox-api.js +7 -3
  36. package/src/lib/mailboxes/mailbox-api.js.map +1 -1
  37. package/src/lib/mailboxes/mailbox-credentials.d.ts +15 -12
  38. package/src/lib/mailboxes/mailbox-credentials.js +12 -8
  39. package/src/lib/mailboxes/mailbox-credentials.js.map +1 -1
  40. package/src/lib/mailboxes/mailbox-erasure.js +3 -0
  41. package/src/lib/mailboxes/mailbox-erasure.js.map +1 -1
  42. package/src/lib/mailboxes/mailbox-revoke.d.ts +10 -5
  43. package/src/lib/mailboxes/mailbox-revoke.js +1 -0
  44. package/src/lib/mailboxes/mailbox-revoke.js.map +1 -1
  45. package/src/lib/mailboxes/mailbox-routes.d.ts +11 -3
  46. package/src/lib/mailboxes/mailbox-routes.js +218 -35
  47. package/src/lib/mailboxes/mailbox-routes.js.map +1 -1
  48. package/src/lib/mailboxes/mailbox-settings.d.ts +6 -2
  49. package/src/lib/mailboxes/mailbox-settings.js +5 -1
  50. package/src/lib/mailboxes/mailbox-settings.js.map +1 -1
  51. package/src/lib/mailboxes/mailbox-transport.d.ts +15 -9
  52. package/src/lib/mailboxes/mailbox-transport.js +47 -17
  53. package/src/lib/mailboxes/mailbox-transport.js.map +1 -1
  54. package/src/lib/mailboxes/oauth-state.d.ts +11 -3
  55. package/src/lib/mailboxes/oauth-state.js +17 -8
  56. package/src/lib/mailboxes/oauth-state.js.map +1 -1
  57. package/src/lib/mailboxes/outreach-config.d.ts +30 -0
  58. package/src/lib/mailboxes/outreach-config.js +53 -10
  59. package/src/lib/mailboxes/outreach-config.js.map +1 -1
  60. package/src/lib/mailboxes/register-mailbox-routes.js +2 -1
  61. package/src/lib/mailboxes/register-mailbox-routes.js.map +1 -1
  62. package/src/lib/model/outreach.types.d.ts +13 -2
  63. package/src/lib/model/outreach.types.js +7 -2
  64. package/src/lib/model/outreach.types.js.map +1 -1
  65. package/src/lib/model/sequence-draft.d.ts +6 -1
  66. package/src/lib/model/sequence-draft.js +16 -4
  67. package/src/lib/model/sequence-draft.js.map +1 -1
  68. package/src/lib/routes/enroll-routes.js +52 -1
  69. package/src/lib/routes/enroll-routes.js.map +1 -1
  70. package/src/lib/routes/sequence-routes.js +11 -3
  71. package/src/lib/routes/sequence-routes.js.map +1 -1
  72. package/src/lib/runtime/fixtures/fake-gmail.d.ts +18 -3
  73. package/src/lib/runtime/fixtures/fake-gmail.js +21 -1
  74. package/src/lib/runtime/fixtures/fake-gmail.js.map +1 -1
  75. package/src/lib/runtime/mailbox-notices.js +2 -2
  76. package/src/lib/runtime/mailbox-notices.js.map +1 -1
  77. package/src/lib/runtime/send-job.js +2 -8
  78. package/src/lib/runtime/send-job.js.map +1 -1
  79. package/src/lib/runtime/sync-job.js +24 -11
  80. package/src/lib/runtime/sync-job.js.map +1 -1
  81. package/src/lib/subprocessors.d.ts +12 -1
  82. package/src/lib/subprocessors.js +25 -2
  83. package/src/lib/subprocessors.js.map +1 -1
  84. package/src/lib/transfer/sequences-package.js +7 -2
  85. package/src/lib/transfer/sequences-package.js.map +1 -1
  86. package/src/lib/transport/gmail-client.d.ts +4 -11
  87. package/src/lib/transport/gmail-client.js +42 -17
  88. package/src/lib/transport/gmail-client.js.map +1 -1
  89. package/src/lib/transport/graph-client.d.ts +87 -0
  90. package/src/lib/transport/graph-client.js +359 -0
  91. package/src/lib/transport/graph-client.js.map +1 -0
  92. package/src/lib/transport/mail-client.d.ts +138 -0
  93. package/src/lib/transport/mail-client.js +34 -0
  94. package/src/lib/transport/mail-client.js.map +1 -0
  95. package/src/lib/transport/microsoft-errors.d.ts +32 -0
  96. package/src/lib/transport/microsoft-errors.js +94 -0
  97. package/src/lib/transport/microsoft-errors.js.map +1 -0
  98. package/src/lib/transport/microsoft-oauth.d.ts +140 -0
  99. package/src/lib/transport/microsoft-oauth.js +225 -0
  100. package/src/lib/transport/microsoft-oauth.js.map +1 -0
  101. package/src/lib/transport/mime-message.d.ts +30 -0
  102. package/src/lib/transport/mime-message.js +235 -0
  103. package/src/lib/transport/mime-message.js.map +1 -0
  104. package/src/lib/transport/send-message.d.ts +15 -8
  105. package/src/lib/transport/send-message.js +4 -3
  106. package/src/lib/transport/send-message.js.map +1 -1
package/README.md CHANGED
@@ -48,21 +48,27 @@ Every `outreach*` collection is written by the server alone.
48
48
  ## Mailboxes
49
49
 
50
50
  `src/lib/mailboxes` and `src/lib/transport` connect a rep's own
51
- Google mailbox and talk to it:
51
+ Google or Microsoft 365 mailbox and talk to it:
52
52
 
53
53
  | module | does |
54
54
  | -- | -- |
55
55
  | `mailboxes/mailbox-routes` | connect (signed single-use state, PKCE, OpenID nonce), settings, pause, test and disconnect |
56
56
  | `mailboxes/oauth-state` | the signed `state` and its pending record under `orgs/{orgId}/outreachOAuthStates` |
57
57
  | `mailboxes/mailbox-credentials` | the refresh token sealed with the shared secret box, in `outreachMailboxCredentials` |
58
- | `mailboxes/mailbox-transport` | opens a mailbox's Gmail client for the runtime, and marks one reconnect-required |
58
+ | `mailboxes/mailbox-transport` | opens a mailbox's client for its provider, and marks one reconnect-required |
59
59
  | `mailboxes/mailbox-erasure` | what a workspace or account erasure revokes and deletes |
60
+ | `transport/mail-client` | the provider seam the runtime reaches a mailbox through, and the structured search |
60
61
  | `transport/gmail-client` | the fetch-based Gmail API client: send, full and metadata thread reads, search, send-as |
62
+ | `transport/graph-client` | the Microsoft Graph client: a step sent as a draft from its own MIME, conversation and message reads, the windowed search |
63
+ | `transport/microsoft-oauth` | Microsoft's identity platform: consent address, code exchange, refresh, ID token |
64
+ | `transport/mime-message` | a raw MIME message read into the Gmail API shape the classifier takes |
61
65
  | `transport/send-message` | the one door a send goes through, including the engine's composed email |
62
66
  | `transport/rfc5322` | the plain-text RFC 5322 writer |
63
67
 
64
- `OUTREACH_TOKEN_KEY`, `GOOGLE_OUTREACH_CLIENT_ID` and
65
- `GOOGLE_OUTREACH_CLIENT_SECRET` are read by `mailboxes/outreach-config` alone,
68
+ `OUTREACH_TOKEN_KEY`, `GOOGLE_OUTREACH_CLIENT_ID`,
69
+ `GOOGLE_OUTREACH_CLIENT_SECRET`, `MICROSOFT_OUTREACH_CLIENT_ID`,
70
+ `MICROSOFT_OUTREACH_CLIENT_SECRET` and `MICROSOFT_OUTREACH_TENANT` are read by
71
+ `mailboxes/outreach-config` alone,
66
72
  and `outreach-credential-isolation.spec.ts` holds that no tenant file reaches it.
67
73
 
68
74
  ## The engine
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aglyn/plugins-outreach",
3
- "version": "1.0.0-beta.223",
3
+ "version": "1.0.0-beta.225",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://aglyn.com",
6
6
  "repository": {
@@ -25,19 +25,19 @@
25
25
  "./package.json": "./package.json"
26
26
  },
27
27
  "dependencies": {
28
- "@aglyn/aglyn": "1.0.0-beta.223",
29
- "@aglyn/shared-data-mdi": "1.0.0-beta.223",
30
- "@aglyn/shared-ui-email-campaigns": "1.0.0-beta.223",
31
- "@aglyn/shared-ui-jsx": "1.0.0-beta.223",
32
- "@aglyn/shared-ui-next": "1.0.0-beta.223",
33
- "@aglyn/shared-ui-snackstack": "1.0.0-beta.223",
34
- "@aglyn/shared-util-email": "1.0.0-beta.223",
35
- "@aglyn/shared-util-http": "1.0.0-beta.223",
36
- "@aglyn/shared-util-timestamp": "1.0.0-beta.223",
37
- "@aglyn/shared-util-tools": "1.0.0-beta.223",
38
- "@aglyn/tenant-data-admin": "1.0.0-beta.223",
39
- "@aglyn/tenant-feature-instance": "1.0.0-beta.223",
40
- "@aglyn/tenant-runtime": "1.0.0-beta.223",
28
+ "@aglyn/aglyn": "1.0.0-beta.225",
29
+ "@aglyn/shared-data-mdi": "1.0.0-beta.225",
30
+ "@aglyn/shared-ui-email-campaigns": "1.0.0-beta.225",
31
+ "@aglyn/shared-ui-jsx": "1.0.0-beta.225",
32
+ "@aglyn/shared-ui-next": "1.0.0-beta.225",
33
+ "@aglyn/shared-ui-snackstack": "1.0.0-beta.225",
34
+ "@aglyn/shared-util-email": "1.0.0-beta.225",
35
+ "@aglyn/shared-util-http": "1.0.0-beta.225",
36
+ "@aglyn/shared-util-timestamp": "1.0.0-beta.225",
37
+ "@aglyn/shared-util-tools": "1.0.0-beta.225",
38
+ "@aglyn/tenant-data-admin": "1.0.0-beta.225",
39
+ "@aglyn/tenant-feature-instance": "1.0.0-beta.225",
40
+ "@aglyn/tenant-runtime": "1.0.0-beta.225",
41
41
  "@swc/helpers": "0.5.23"
42
42
  },
43
43
  "peerDependencies": {
@@ -16,6 +16,14 @@ export interface OutreachEnrollmentDetailProps {
16
16
  * leads and contacts publishes, or `null` where none does.
17
17
  */
18
18
  export declare function outreachCrmRecordHref(kind: 'lead' | 'contact', id: string | null | undefined, hostId: string, orgMount: Pick<ConsolePluginOrgMount, 'orgSlug' | 'hosts'> | undefined): string | null;
19
+ /**
20
+ * Whether a mailbox's threads open in Gmail. A Microsoft 365 mailbox's
21
+ * conversation has no address of its own in Outlook (AGL-3489), so its
22
+ * thread is shown without a link.
23
+ */
24
+ export declare const outreachThreadOpensInGmail: (mailbox: {
25
+ provider?: string;
26
+ } | null | undefined) => boolean;
19
27
  /** A Gmail thread, opened in the mailbox's own account. */
20
28
  export declare function outreachGmailThreadUrl(threadId: string, mailboxEmail: string | null | undefined): string;
21
29
  export declare function OutreachEnrollmentDetail(props: OutreachEnrollmentDetailProps): import("react").JSX.Element;
@@ -53,6 +53,11 @@ import { useOutreachEnrollment, useOutreachEnrollmentGateway, useOutreachEnrollm
53
53
  host
54
54
  }, id);
55
55
  }
56
+ /**
57
+ * Whether a mailbox's threads open in Gmail. A Microsoft 365 mailbox's
58
+ * conversation has no address of its own in Outlook (AGL-3489), so its
59
+ * thread is shown without a link.
60
+ */ export const outreachThreadOpensInGmail = (mailbox)=>(mailbox == null ? void 0 : mailbox.provider) !== 'microsoft';
56
61
  /** A Gmail thread, opened in the mailbox's own account. */ export function outreachGmailThreadUrl(threadId, mailboxEmail) {
57
62
  const account = mailboxEmail ? `?authuser=${encodeURIComponent(mailboxEmail)}` : '';
58
63
  return `https://mail.google.com/mail/${account}#all/${encodeURIComponent(threadId)}`;
@@ -179,13 +184,13 @@ const TONE_COLORS = {
179
184
  },
180
185
  children: entry.detail
181
186
  }) : null,
182
- entry.facts.length || entry.gmailThreadId ? /*#__PURE__*/ _jsxs(Typography, {
187
+ entry.facts.length || entry.gmailThreadId && props.threadsOpenInGmail !== false ? /*#__PURE__*/ _jsxs(Typography, {
183
188
  variant: "caption",
184
189
  color: "text.secondary",
185
190
  component: "div",
186
191
  children: [
187
192
  entry.facts.join(' · '),
188
- entry.gmailThreadId ? /*#__PURE__*/ _jsxs(_Fragment, {
193
+ entry.gmailThreadId && props.threadsOpenInGmail !== false ? /*#__PURE__*/ _jsxs(_Fragment, {
189
194
  children: [
190
195
  entry.facts.length ? ' · ' : null,
191
196
  /*#__PURE__*/ _jsx(Link, {
@@ -435,7 +440,7 @@ const TONE_COLORS = {
435
440
  }) : '—'
436
441
  }),
437
442
  /*#__PURE__*/ _jsx(Fact, {
438
- label: "Gmail threads",
443
+ label: outreachThreadOpensInGmail(props.mailbox) ? 'Gmail threads' : 'Threads',
439
444
  children: threads.length ? /*#__PURE__*/ _jsxs(Stack, {
440
445
  spacing: 0.25,
441
446
  children: [
@@ -443,12 +448,18 @@ const TONE_COLORS = {
443
448
  var _props_mailbox;
444
449
  return /*#__PURE__*/ _jsxs("span", {
445
450
  children: [
446
- /*#__PURE__*/ _jsx(Link, {
451
+ outreachThreadOpensInGmail(props.mailbox) ? /*#__PURE__*/ _jsx(Link, {
447
452
  href: outreachGmailThreadUrl(thread, (_props_mailbox = props.mailbox) == null ? void 0 : _props_mailbox.email),
448
453
  target: "_blank",
449
454
  rel: "noopener noreferrer",
450
455
  underline: "hover",
451
456
  children: thread
457
+ }) : /*#__PURE__*/ _jsx(Box, {
458
+ component: "span",
459
+ sx: {
460
+ wordBreak: 'break-all'
461
+ },
462
+ children: thread
452
463
  }),
453
464
  thread === enrollment.gmailThreadId ? ' (current)' : null
454
465
  ]
@@ -808,7 +819,7 @@ export function OutreachEnrollmentDetail(props) {
808
819
  }),
809
820
  contentGutterX: true,
810
821
  contentGutterY: true,
811
- HeaderProps: thread ? {
822
+ HeaderProps: thread && outreachThreadOpensInGmail(mailbox) ? {
812
823
  action: /*#__PURE__*/ _jsx(Button, {
813
824
  size: "small",
814
825
  href: outreachGmailThreadUrl(thread, mailbox == null ? void 0 : mailbox.email),
@@ -839,6 +850,7 @@ export function OutreachEnrollmentDetail(props) {
839
850
  entry: entry,
840
851
  timeZone: timeZone,
841
852
  mailboxEmail: (_ref = mailbox == null ? void 0 : mailbox.email) != null ? _ref : null,
853
+ threadsOpenInGmail: outreachThreadOpensInGmail(mailbox),
842
854
  divider: index < timeline.length - 1
843
855
  }, entry.key);
844
856
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/enrollment-detail.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type ConsolePluginOrgMount,\n PageHeaderRecord,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport { pluginRecordHref } from '@aglyn/aglyn/plugin-manager/plugin-record-routes'\nimport {\n mdiAccountCancelOutline,\n mdiAccountOutline,\n mdiAccountPlusOutline,\n mdiAlertCircleOutline,\n mdiCheckCircleOutline,\n mdiChevronDown,\n mdiChevronUp,\n mdiClipboardCheckOutline,\n mdiContentCopy,\n mdiCursorDefaultClickOutline,\n mdiEmailAlertOutline,\n mdiEmailOffOutline,\n mdiEmailOpenOutline,\n mdiEmailOutline,\n mdiHandBackLeftOutline,\n mdiPauseCircleOutline,\n mdiPencilOutline,\n mdiPlayCircleOutline,\n mdiReply,\n mdiShieldSearch,\n mdiSkipNext,\n mdiStopCircleOutline,\n} from '@aglyn/shared-data-mdi'\nimport { AppLink, CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport RowActionsMenu from '@aglyn/shared-ui-jsx/components/row-actions-menu.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useOrgContainerOptions, useOrgMemberOptions } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n Card,\n Chip,\n Collapse,\n Divider,\n IconButton,\n Link,\n List,\n ListItem,\n ListItemIcon,\n ListItemText,\n Stack,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { type ReactNode, useCallback, useMemo, useState } from 'react'\nimport { OUTREACH_MAIL_GATEWAY_LABELS } from '../engine/mail-gateway'\nimport { outreachNextSendState } from '../engine/next-send'\nimport { outreachClickSummary } from '../model/enrollment-engagement'\nimport {\n outreachEnrollmentFigures,\n outreachEnrollmentTimeline,\n outreachStepName,\n type OutreachTimelineEntry,\n type OutreachTimelineKind,\n type OutreachTimelineTone,\n} from '../model/enrollment-timeline'\nimport {\n OUTREACH_ATTESTATION_KINDS,\n OUTREACH_ATTESTATION_LABELS,\n type OutreachEnrollment,\n type OutreachMailbox,\n type OutreachSequence,\n} from '../model/outreach.types'\nimport {\n OUTREACH_ENROLLMENT_ACTION_LABELS,\n outreachEnrollmentActionsFor,\n type OutreachEnrollmentRowAction,\n useOutreachEnrollmentActions,\n} from './enrollment-actions'\nimport { outreachCurrentStepLabel, outreachStepIsCurated, outreachStopLabel } from './enrollments-table'\nimport {\n formatOutreachTime,\n OutreachEnrollmentStatusChip,\n OutreachLoading,\n OutreachLoadProblem,\n} from './outreach-ui'\nimport { outreachNextSendDetail, outreachNextSendLabel, useOutreachNowMs } from './next-send'\nimport { OutreachFigure } from './sequence-report-card'\nimport { useOutreachApi } from './use-outreach-api'\nimport { useOutreachSequence } from './use-outreach-data'\nimport type { OutreachEnrollmentGatewayResponse } from '../model/outreach-api'\nimport {\n useOutreachEnrollment,\n useOutreachEnrollmentGateway,\n useOutreachEnrollmentHistory,\n} from './use-outreach-enrollment'\nimport type { OutreachMailboxesResult } from './use-outreach-mailboxes'\n\n/*==========================================\n * ONE PERSON IN ONE SEQUENCE (AGL-3332):\n * `/[orgSlug]/outreach/sequences/{sequenceId}/enrollments/{enrollmentId}`.\n *\n * A row of the Enrollments tab opens it, and its URL is the person's: a\n * comment or a message can link straight to them.\n *\n * Laid out the way every record page in the console is (the CRM's\n * `CrmRecordHeader` grammar): the page heading names the person; the first\n * card says what the record is, with the way back and the actions in its\n * HEADER — the one that changes things as a button, the rest and the\n * destructive ones behind the menu — and the facts that identify it as\n * chips. Under the chips, five numbers.\n *\n * Then ONE timeline, newest first, which is the page: every send, click,\n * reply, bounce, stop, hold and resume, from `model/enrollment-timeline.ts`.\n * Everything else stored on the enrollment is under Details, closed until\n * asked for — nothing is left out, and nothing is in the way.\n *=========================================*/\n\nexport interface OutreachEnrollmentDetailProps {\n orgId: string\n /** The org the hub is mounted under: its slug and sites, for the CRM record's address. */\n orgMount?: ConsolePluginOrgMount\n /** `/[orgSlug]/outreach/sequences`. */\n sectionPath: string\n sequenceId: string\n enrollmentId: string\n mailboxes: OutreachMailboxesResult\n}\n\n/**\n * Where the CRM record the person is lives — the site's own CRM when the site\n * is known, else the organization's — at the address the plugin that keeps\n * leads and contacts publishes, or `null` where none does.\n */\nexport function outreachCrmRecordHref(\n kind: 'lead' | 'contact',\n id: string | null | undefined,\n hostId: string,\n orgMount: Pick<ConsolePluginOrgMount, 'orgSlug' | 'hosts'> | undefined,\n): string | null {\n if (!id || !orgMount?.orgSlug) return null\n const host = orgMount.hosts.find((entry) => entry.id === hostId)?.subdomain ?? null\n return pluginRecordHref(kind, { orgSlug: orgMount.orgSlug, host }, id)\n}\n\n/** A Gmail thread, opened in the mailbox's own account. */\nexport function outreachGmailThreadUrl(threadId: string, mailboxEmail: string | null | undefined): string {\n const account = mailboxEmail ? `?authuser=${encodeURIComponent(mailboxEmail)}` : ''\n return `https://mail.google.com/mail/${account}#all/${encodeURIComponent(threadId)}`\n}\n\nconst KIND_ICONS: Record<OutreachTimelineKind, { path: string }> = {\n enrolled: mdiAccountPlusOutline,\n skipped: mdiSkipNext,\n curated: mdiPencilOutline,\n sent: mdiEmailOutline,\n task: mdiClipboardCheckOutline,\n click: mdiCursorDefaultClickOutline,\n scanner: mdiShieldSearch,\n 'earlier-clicks': mdiCursorDefaultClickOutline,\n open: mdiEmailOpenOutline,\n 'machine-open': mdiShieldSearch,\n paused: mdiPauseCircleOutline,\n resumed: mdiPlayCircleOutline,\n stopped: mdiStopCircleOutline,\n 'do-not-contact': mdiAccountCancelOutline,\n replied: mdiReply,\n bounced: mdiEmailAlertOutline,\n 'opted-out': mdiEmailOffOutline,\n held: mdiHandBackLeftOutline,\n released: mdiPlayCircleOutline,\n failed: mdiAlertCircleOutline,\n finished: mdiCheckCircleOutline,\n}\n\nconst TONE_COLORS: Record<OutreachTimelineTone, string> = {\n default: 'text.secondary',\n success: 'success.main',\n info: 'info.main',\n warning: 'warning.main',\n error: 'error.main',\n}\n\n/** A destination, whole, opening in a new tab. */\nfunction Destination(props: { url: string; label?: string }) {\n return (\n <Typography variant=\"body2\" component=\"span\" sx={{ display: 'block', wordBreak: 'break-all' }}>\n {props.label ? `${props.label}: ` : null}\n <Link href={props.url} target=\"_blank\" rel=\"noopener noreferrer\" underline=\"hover\">\n {props.url}\n </Link>\n </Typography>\n )\n}\n\n/** One line of the timeline. */\nfunction TimelineRow(props: {\n entry: OutreachTimelineEntry\n timeZone: string | null\n mailboxEmail: string | null\n divider: boolean\n}) {\n const { entry } = props\n return (\n <ListItem alignItems=\"flex-start\" divider={props.divider} disableGutters data-kind={entry.kind}>\n <ListItemIcon sx={{ minWidth: 36, mt: 0.75, color: TONE_COLORS[entry.tone] }}>\n <MdiIcon path={KIND_ICONS[entry.kind].path} fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText\n disableTypography\n primary={\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n spacing={{ xs: 0, sm: 1 }}\n sx={{ justifyContent: 'space-between', alignItems: { sm: 'baseline' } }}\n >\n <Typography variant=\"body2\" sx={{ fontWeight: 500 }}>\n {entry.title}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ whiteSpace: 'nowrap' }}>\n {formatOutreachTime(entry.atMs, props.timeZone)}\n </Typography>\n </Stack>\n }\n secondary={\n <Stack spacing={0.25} sx={{ mt: 0.25 }}>\n {entry.url ? <Destination url={entry.url} label={entry.urlLabel} /> : null}\n {entry.detail ? (\n <Typography variant=\"body2\" sx={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>\n {entry.detail}\n </Typography>\n ) : null}\n {entry.facts.length || entry.gmailThreadId ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {entry.facts.join(' · ')}\n {entry.gmailThreadId ? (\n <>\n {entry.facts.length ? ' · ' : null}\n <Link\n href={outreachGmailThreadUrl(entry.gmailThreadId, props.mailboxEmail)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n underline=\"hover\"\n >\n Open thread in Gmail\n </Link>\n </>\n ) : null}\n </Typography>\n ) : null}\n </Stack>\n }\n />\n </ListItem>\n )\n}\n\n/** One fact of the Details list. */\nfunction Fact(props: { label: string; children: ReactNode }) {\n return (\n <>\n <Typography component=\"dt\" variant=\"body2\" color=\"text.secondary\">\n {props.label}\n </Typography>\n <Box component=\"dd\" sx={{ m: 0, minWidth: 0, typography: 'body2', wordBreak: 'break-word' }}>\n {props.children}\n </Box>\n </>\n )\n}\n\n/** What mail from the sequence's sending domain met at the person's domain, in a line. */\nfunction gatewaySentence(answer: OutreachEnrollmentGatewayResponse, timeZone: string | null): string {\n const { intel, standing } = answer\n if (!intel) return 'Could not be looked up'\n if (intel.status === 'no_mx' || intel.status === 'null_mx') {\n return `${answer.domain ?? 'The domain'} takes no mail · looked up ${formatOutreachTime(intel.resolvedAtMs, timeZone)}`\n }\n const from = answer.sendingDomain ? ` from ${answer.sendingDomain}` : ''\n const parts = [\n OUTREACH_MAIL_GATEWAY_LABELS[intel.gateway],\n intel.mx.length ? `MX ${intel.mx.join(', ')}` : 'no MX; delivered to its address record',\n standing\n ? `${standing.delivered30} delivered, ${standing.blocked30} refused${from} in the last 30 days`\n : null,\n `looked up ${formatOutreachTime(intel.resolvedAtMs, timeZone)}`,\n ]\n return parts.filter(Boolean).join(' · ')\n}\n\n/**\n * Everything else the enrollment holds, all of it, behind one toggle.\n */\nfunction EnrollmentDetails(props: {\n enrollment: OutreachEnrollment\n sequence: OutreachSequence\n mailbox: OutreachMailbox | null\n gateway: OutreachEnrollmentGatewayResponse | null\n /** What the Mail gateway line says while there is no answer to show. */\n gatewayUnread: string\n campaignName: (id: string) => string\n memberName: (uid: string) => string\n orgMount?: ConsolePluginOrgMount\n timeZone: string | null\n}) {\n const { enrollment, sequence, memberName, timeZone } = props\n const { enqueueSnackbar } = useSnackbar()\n const time = (ms: number | null | undefined) => formatOutreachTime(ms, timeZone)\n const leadHref = outreachCrmRecordHref('lead', enrollment.leadId, enrollment.hostId, props.orgMount)\n const contactHref = outreachCrmRecordHref('contact', enrollment.contactId, enrollment.hostId, props.orgMount)\n const clicks = outreachClickSummary(enrollment.engagement)\n const overrides = Object.entries(enrollment.stepOverrides ?? {}).sort(\n ([a], [b]) => Number(a) - Number(b),\n )\n const attested = OUTREACH_ATTESTATION_KINDS.filter((kind) => enrollment.attestations?.[kind])\n const threads = enrollment.gmailThreadIds.length\n ? enrollment.gmailThreadIds\n : enrollment.gmailThreadId\n ? [enrollment.gmailThreadId]\n : []\n const copyId = () => {\n void navigator.clipboard\n ?.writeText(enrollment.id)\n .then(() => enqueueSnackbar('Enrollment id copied.', { variant: 'success' }))\n .catch(() => enqueueSnackbar('The id could not be copied.', { variant: 'error' }))\n }\n const link = (href: string | null, label: string) =>\n href ? (\n <Link {...({ component: AppLink, componentVariant: 'naked' } as object)} href={href} underline=\"hover\">\n {label}\n </Link>\n ) : (\n label\n )\n\n return (\n <Box\n component=\"dl\"\n sx={{\n m: 0,\n display: 'grid',\n gridTemplateColumns: { xs: '1fr', sm: 'minmax(160px, 220px) 1fr' },\n columnGap: 2,\n rowGap: 1.25,\n }}\n >\n <Fact label=\"Personal line\">\n {enrollment.personalLine ? (\n <Typography variant=\"body2\" sx={{ whiteSpace: 'pre-wrap' }}>\n {enrollment.personalLine}\n </Typography>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Enrolled as\">\n {enrollment.target === 'lead' ? (\n link(leadHref, 'Lead')\n ) : enrollment.leadId ? (\n <>\n {link(contactHref, 'Contact')}\n {', converted from a '}\n {link(leadHref, 'lead')}\n </>\n ) : (\n link(contactHref, 'Contact')\n )}\n </Fact>\n <Fact label=\"Enrolled\">\n {`${time(enrollment.createdAtMs)}${enrollment.enrolledByUid ? ` by ${memberName(enrollment.enrolledByUid)}` : ''}`}\n </Fact>\n <Fact label=\"Cold contact\">\n {enrollment.cold\n ? 'Yes — no inbound capture behind them, so the member confirmed the address before enrolling'\n : 'No'}\n </Fact>\n <Fact label=\"Attestations\">\n {attested.length ? (\n <Stack component=\"ul\" spacing={0.25} sx={{ m: 0, pl: 2.5 }}>\n {attested.map((kind) => {\n const entry = enrollment.attestations?.[kind]\n return (\n <li key={kind}>\n {`${OUTREACH_ATTESTATION_LABELS[kind]} — ${memberName(entry?.uid ?? '')}, ${time(entry?.atMs)}`}\n </li>\n )\n })}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Mailbox\">\n {props.mailbox\n ? `${props.mailbox.sendAs || props.mailbox.email}${props.mailbox.sendAs && props.mailbox.sendAs !== props.mailbox.email ? ` (${props.mailbox.email})` : ''}`\n : enrollment.mailboxId\n ? 'No longer connected'\n : '—'}\n </Fact>\n <Fact label=\"Campaigns\">\n {enrollment.campaignIds?.length\n ? enrollment.campaignIds.map(props.campaignName).join(', ')\n : '—'}\n </Fact>\n <Fact label=\"Mail gateway\">\n {props.gateway ? gatewaySentence(props.gateway, timeZone) : props.gatewayUnread}\n </Fact>\n <Fact label=\"Gateway hold\">\n {enrollment.gatewayHold\n ? [\n OUTREACH_MAIL_GATEWAY_LABELS[enrollment.gatewayHold.gateway],\n enrollment.gatewayHold.heldAtMs ? `held ${time(enrollment.gatewayHold.heldAtMs)}` : 'never held',\n enrollment.gatewayHold.releasedAtMs\n ? `released ${time(enrollment.gatewayHold.releasedAtMs)}${enrollment.gatewayHold.releasedByUid ? ` by ${memberName(enrollment.gatewayHold.releasedByUid)}` : ''}`\n : 'not released',\n ].join(' · ')\n : '—'}\n {enrollment.gatewayDeliveredSteps\n ? ` (${enrollment.gatewayDeliveredSteps} of their emails counted as delivered on the gateway ledger)`\n : null}\n </Fact>\n <Fact label=\"Clicks\">\n {clicks.clicks || clicks.machineClicks\n ? [\n `${clicks.clicks} by the person`,\n `${clicks.machineClicks} by scanners, not counted`,\n `${clicks.clicks - clicks.unloggedClicks + clicks.machineClicks - clicks.unloggedMachineClicks} listed one by one`,\n enrollment.engagement?.firstClickAtMs ? `first ${time(enrollment.engagement.firstClickAtMs)}` : null,\n enrollment.engagement?.lastClickAtMs ? `last ${time(enrollment.engagement.lastClickAtMs)}` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n : '—'}\n {clicks.followed.length ? (\n <Box sx={{ mt: 0.5 }}>\n {clicks.followed.map((url) => (\n <Destination key={url} url={url} />\n ))}\n </Box>\n ) : null}\n </Fact>\n <Fact label=\"Curated steps\">\n {overrides.length ? (\n <Stack spacing={1.5}>\n {overrides.map(([key, override]) => (\n <Box key={key}>\n <Typography variant=\"body2\" sx={{ fontWeight: 500 }}>\n {outreachStepName(sequence.steps, Number(key))}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {[\n override.source === 'ai' ? (override.edited ? 'AI draft, edited' : 'AI draft') : 'Written by a member',\n override.draftedByUid ? `confirmed by ${memberName(override.draftedByUid)}` : null,\n override.draftedAtMs ? time(override.draftedAtMs) : null,\n override.model ? `model ${override.model}` : null,\n ]\n .filter(Boolean)\n .join(' · ')}\n </Typography>\n {override.subject !== undefined ? (\n <Typography variant=\"body2\">{`Subject: ${override.subject}`}</Typography>\n ) : null}\n {override.body !== undefined ? (\n <Typography\n variant=\"body2\"\n sx={{ whiteSpace: 'pre-wrap', mt: 0.5, pl: 1.5, borderLeft: 2, borderColor: 'divider' }}\n >\n {override.body}\n </Typography>\n ) : null}\n {override.prompt ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ whiteSpace: 'pre-wrap', mt: 0.5 }}>\n {`Prompt: ${override.prompt}`}\n </Typography>\n ) : null}\n </Box>\n ))}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Gmail threads\">\n {threads.length ? (\n <Stack spacing={0.25}>\n {threads.map((thread) => (\n <span key={thread}>\n <Link\n href={outreachGmailThreadUrl(thread, props.mailbox?.email)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n underline=\"hover\"\n >\n {thread}\n </Link>\n {thread === enrollment.gmailThreadId ? ' (current)' : null}\n </span>\n ))}\n {enrollment.threadSubject ? (\n <Typography variant=\"caption\" color=\"text.secondary\">{`Started as “${enrollment.threadSubject}”`}</Typography>\n ) : null}\n {enrollment.messageIds.length ? (\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ wordBreak: 'break-all' }}>\n {`Message-IDs in the current thread: ${enrollment.messageIds.join(' ')}`}\n </Typography>\n ) : null}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Stop\">\n {enrollment.stopReason\n ? `${outreachStopLabel(enrollment)} · ${time(enrollment.stoppedAtMs)}${enrollment.stoppedByUid ? ` · by ${memberName(enrollment.stoppedByUid)}` : ''}`\n : '—'}\n </Fact>\n <Fact label=\"Created · updated\">{`${time(enrollment.createdAtMs)} · ${time(enrollment.updatedAtMs)}`}</Fact>\n <Fact label=\"Enrollment id\">\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ fontFamily: 'monospace', wordBreak: 'break-all' }}>\n {enrollment.id}\n </Typography>\n <Tooltip title=\"Copy the id\">\n <IconButton size=\"small\" aria-label=\"Copy the enrollment id\" onClick={copyId}>\n <MdiIcon path={mdiContentCopy.path} fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Stack>\n </Fact>\n </Box>\n )\n}\n\nexport function OutreachEnrollmentDetail(props: OutreachEnrollmentDetailProps) {\n const { orgId, sectionPath, sequenceId, enrollmentId, orgMount } = props\n const api = useOutreachApi(orgId)\n const loadedSequence = useOutreachSequence(orgId, sequenceId)\n const loaded = useOutreachEnrollment(orgId, enrollmentId)\n const history = useOutreachEnrollmentHistory(orgId, enrollmentId)\n const gateway = useOutreachEnrollmentGateway(api, enrollmentId)\n const roster = useOrgMemberOptions(orgId, { enabled: true })\n const [detailsOpen, setDetailsOpen] = useState(false)\n const nowMs = useOutreachNowMs()\n const enrollment = loaded.data\n const sequence = loadedSequence.data\n const campaigns = useOrgContainerOptions('campaign', orgId, {\n enabled: detailsOpen && Boolean(enrollment?.campaignIds?.length),\n })\n const steps = useMemo(() => sequence?.steps ?? [], [sequence])\n const actions = useOutreachEnrollmentActions({ api, steps })\n\n const memberName = useCallback(\n (uid: string) => roster.options.find((option) => option.uid === uid)?.label ?? 'a member',\n [roster.options],\n )\n const campaignName = useCallback(\n (id: string) => campaigns.options.find((option) => option.value === id)?.label ?? id,\n [campaigns.options],\n )\n\n const enrollmentsPath = `${sectionPath}/${sequenceId}/enrollments`\n const mailbox =\n props.mailboxes.mailboxes.find((entry) => entry.id === (enrollment?.mailboxId || sequence?.mailboxId)) ?? null\n const timeZone = mailbox?.timezone ?? null\n const time = (ms: number | null | undefined) => formatOutreachTime(ms, timeZone)\n const timeline = useMemo(\n () =>\n enrollment\n ? outreachEnrollmentTimeline({\n enrollment,\n steps,\n history: history.status === 'ready' ? history.data : null,\n memberName,\n formatTime: (ms) => formatOutreachTime(ms, timeZone),\n gateway: gateway.data?.intel?.gateway ?? null,\n })\n : [],\n [enrollment, steps, history, memberName, timeZone, gateway.data],\n )\n\n const back = (\n <Button\n // A real link, as the CRM record header's is: it opens in a new tab when asked.\n {...({ component: AppLink, componentVariant: 'naked', nativeButton: false } as object)}\n href={enrollmentsPath}\n size=\"small\"\n color=\"primary\"\n >\n Back to enrollments\n </Button>\n )\n\n if (loaded.status === 'loading' || loadedSequence.status === 'loading') {\n return <OutreachLoading label=\"Loading this person…\" />\n }\n if (loaded.status === 'error' || loaded.status === 'refused') {\n return <OutreachLoadProblem status={loaded.status} what=\"enrollment\" />\n }\n if (loadedSequence.status === 'error' || loadedSequence.status === 'refused') {\n return <OutreachLoadProblem status={loadedSequence.status} what=\"sequence\" />\n }\n // An id from another sequence reads as not here: the URL names both.\n if (!enrollment || !sequence || enrollment.sequenceId !== sequenceId) {\n return (\n <Card variant=\"outlined\">\n <EmptyStateComponent\n label=\"This person isn’t in this sequence\"\n description=\"They may have been removed from the workspace, or the link names a different sequence.\"\n action={back}\n />\n </Card>\n )\n }\n\n const name = enrollment.contactName || enrollment.email\n const kind = enrollment.target === 'lead' ? 'lead' : 'contact'\n const recordHref = outreachCrmRecordHref(\n kind,\n kind === 'lead' ? enrollment.leadId : enrollment.contactId,\n enrollment.hostId,\n orgMount,\n )\n const figures = outreachEnrollmentFigures(enrollment)\n const trackClicks = sequence.settings.trackClicks || sequence.stats?.clickTracked === true\n // Opens are shown for a sequence that counts them or once did (AGL-3395),\n // and for a person with any recorded, whatever the sequence says now.\n const countOpens =\n sequence.settings.countOpens ||\n sequence.stats?.openTracked === true ||\n figures.opens > 0 ||\n figures.machineOpens > 0\n const open = enrollment.status === 'active' || enrollment.status === 'paused'\n const held = enrollment.status === 'paused' && enrollment.stopReason === 'gateway_blocked_here'\n\n /*\n * The one act that moves the person forward is the button: resuming a\n * paused one, else curating the next email. Everything else is in the\n * menu, the destructive acts included, as on every record page.\n */\n const available = outreachEnrollmentActionsFor(enrollment, steps)\n const primary: OutreachEnrollmentRowAction | null = available.includes('resume')\n ? 'resume'\n : available.includes('curate')\n ? 'curate'\n : null\n const menu = actions.menuItems(enrollment, (action) => action !== primary)\n const dash = (value: number) => (value ? value.toLocaleString() : '—')\n const notTracked = !trackClicks && !figures.clicks && !figures.scannerClicks ? 'Not tracked' : undefined\n const thread = enrollment.gmailThreadId ?? enrollment.gmailThreadIds.at(-1) ?? null\n const nextSend = outreachNextSendState({\n enrollment,\n sequence,\n mailbox: props.mailboxes.status === 'ready' ? mailbox : undefined,\n nowMs,\n })\n const nothingYet =\n enrollment.status === 'active' && enrollment.nextDueAtMs\n ? nextSend.kind === 'queued'\n ? `Nothing yet — step ${enrollment.stepIndex + 1} is due and queued to send.`\n : `Nothing yet — step ${enrollment.stepIndex + 1} sends ${time(enrollment.nextDueAtMs)}.`\n : 'Nothing yet.'\n\n return (\n <Stack spacing={2}>\n {/* The page heading and the trail name the person; the card says what they are in. */}\n <PageHeaderRecord title={name} />\n <CardDisplay\n header=\"Enrollment\"\n subheader={\n <>\n {enrollment.contactName ? `${enrollment.email} · ` : ''}\n {`In ${sequence.name || 'Untitled'}`}\n </>\n }\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n action: (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}>\n {back}\n {primary ? (\n <Button\n variant=\"outlined\"\n size=\"small\"\n disabled={actions.busy === enrollment.id}\n onClick={() => actions.choose(enrollment, primary)}\n >\n {held ? 'Resume and send' : OUTREACH_ENROLLMENT_ACTION_LABELS[primary]}\n </Button>\n ) : null}\n {menu.length ? <RowActionsMenu label={name} items={menu} /> : null}\n </Stack>\n ),\n }}\n >\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}>\n <Tooltip\n describeChild\n title={recordHref ? `Open the ${kind} in the CRM` : `The ${kind}’s record can’t be linked`}\n >\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color={recordHref ? 'primary' : 'default'}\n icon={<MdiIcon path={mdiAccountOutline.path} fontSize=\"small\" />}\n label={kind === 'lead' ? 'Lead' : 'Contact'}\n {...(recordHref\n ? ({ component: AppLink, href: recordHref, clickable: true, componentVariant: 'naked' } as object)\n : {})}\n />\n </Tooltip>\n <OutreachEnrollmentStatusChip status={enrollment.status} />\n <Chip size=\"small\" variant=\"outlined\" label={outreachCurrentStepLabel(enrollment, steps)} />\n {outreachStepIsCurated(enrollment) ? (\n <Chip size=\"small\" variant=\"outlined\" color=\"success\" label=\"Curated\" />\n ) : null}\n {open && enrollment.nextDueAtMs ? (\n nextSend.kind === 'queued' ? (\n <Tooltip describeChild title={outreachNextSendDetail(nextSend, timeZone)}>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color={\n nextSend.reason === 'mailbox_not_sending' || nextSend.reason === 'sequence_not_active'\n ? 'warning'\n : 'default'\n }\n label={`Next send ${outreachNextSendLabel(nextSend, timeZone)}`}\n />\n </Tooltip>\n ) : (\n <Chip size=\"small\" variant=\"outlined\" label={`Next send ${time(enrollment.nextDueAtMs)}`} />\n )\n ) : null}\n </Stack>\n {held ? (\n <Alert severity=\"warning\">\n {enrollment.stopDetail ||\n 'Their mail gateway refused this sender, so the next email is held. Resume to send it anyway.'}\n </Alert>\n ) : null}\n {figures.anything ? (\n <Stack direction=\"row\" spacing={3} sx={{ flexWrap: 'wrap', rowGap: 2 }} role=\"group\" aria-label=\"In numbers\">\n <OutreachFigure label=\"Emails sent\" value={dash(figures.emailsSent)} />\n {countOpens ? (\n <OutreachFigure\n label=\"Opens\"\n value={dash(figures.opens)}\n hint={figures.machineOpens ? `${figures.machineOpens.toLocaleString()} by machines, not counted` : undefined}\n />\n ) : null}\n <OutreachFigure label=\"Clicks\" value={dash(figures.clicks)} hint={notTracked} />\n <OutreachFigure\n label=\"Links followed\"\n value={\n figures.linksFollowed.count\n ? `${figures.linksFollowed.count}${figures.linksFollowed.atLeast ? '+' : ''}`\n : '—'\n }\n hint={\n notTracked ??\n (figures.linksFollowed.atLeast && figures.linksFollowed.count\n ? 'Earlier clicks kept the last link only'\n : undefined)\n }\n />\n <OutreachFigure label=\"Scanner clicks\" value={dash(figures.scannerClicks)} hint={notTracked ?? 'Not counted'} />\n <OutreachFigure label=\"Replies\" value={dash(figures.replies)} />\n </Stack>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {nothingYet}\n </Typography>\n )}\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header=\"Activity\"\n subheader=\"Newest first\"\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n contentGutterY\n HeaderProps={\n thread\n ? {\n action: (\n <Button\n size=\"small\"\n href={outreachGmailThreadUrl(thread, mailbox?.email)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Open thread in Gmail\n </Button>\n ),\n }\n : undefined\n }\n >\n <Stack spacing={1}>\n {history.status === 'loading' ? <OutreachLoading label=\"Loading their history…\" /> : null}\n {history.status === 'error' || history.status === 'refused' ? (\n <OutreachLoadProblem\n status={history.status}\n what=\"list of their clicks\"\n // Only the one-by-one list is missing: the totals, the sends and\n // every stop above come from the enrollment, which was read.\n message={\n history.status === 'refused'\n ? 'Their clicks can’t be listed one by one here; the numbers above still count them.'\n : 'Their clicks couldn’t be listed one by one. Reload the page to try again.'\n }\n />\n ) : null}\n <List disablePadding aria-label=\"Activity\">\n {timeline.map((entry, index) => (\n <TimelineRow\n key={entry.key}\n entry={entry}\n timeZone={timeZone}\n mailboxEmail={mailbox?.email ?? null}\n divider={index < timeline.length - 1}\n />\n ))}\n </List>\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header=\"Details\"\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n HeaderProps={{\n action: (\n <Button\n size=\"small\"\n aria-expanded={detailsOpen}\n aria-controls=\"outreach-enrollment-details\"\n endIcon={<MdiIcon path={(detailsOpen ? mdiChevronUp : mdiChevronDown).path} fontSize=\"small\" />}\n onClick={() => setDetailsOpen((was) => !was)}\n >\n {detailsOpen ? 'Hide' : 'Show'}\n </Button>\n ),\n }}\n >\n <Collapse in={detailsOpen} unmountOnExit>\n <Box id=\"outreach-enrollment-details\" sx={{ pb: 2 }}>\n <Divider sx={{ mb: 2 }} />\n <EnrollmentDetails\n enrollment={enrollment}\n sequence={sequence}\n mailbox={mailbox}\n gateway={gateway.status === 'ready' ? gateway.data : null}\n gatewayUnread={\n gateway.status === 'loading'\n ? 'Looking it up…'\n : gateway.status === 'refused'\n ? 'Your role cannot look it up'\n : 'Could not be looked up'\n }\n campaignName={campaignName}\n memberName={memberName}\n orgMount={orgMount}\n timeZone={timeZone}\n />\n </Box>\n </Collapse>\n </CardDisplay>\n\n {actions.dialogs}\n </Stack>\n )\n}\nOutreachEnrollmentDetail.displayName = 'OutreachEnrollmentDetail'\n\nexport default OutreachEnrollmentDetail\n"],"names":["PageHeaderRecord","pluginDocsHelp","pluginRecordHref","mdiAccountCancelOutline","mdiAccountOutline","mdiAccountPlusOutline","mdiAlertCircleOutline","mdiCheckCircleOutline","mdiChevronDown","mdiChevronUp","mdiClipboardCheckOutline","mdiContentCopy","mdiCursorDefaultClickOutline","mdiEmailAlertOutline","mdiEmailOffOutline","mdiEmailOpenOutline","mdiEmailOutline","mdiHandBackLeftOutline","mdiPauseCircleOutline","mdiPencilOutline","mdiPlayCircleOutline","mdiReply","mdiShieldSearch","mdiSkipNext","mdiStopCircleOutline","AppLink","CardDisplay","MdiIcon","EmptyStateComponent","RowActionsMenu","useSnackbar","useOrgContainerOptions","useOrgMemberOptions","Alert","Box","Button","Card","Chip","Collapse","Divider","IconButton","Link","List","ListItem","ListItemIcon","ListItemText","Stack","Tooltip","Typography","useCallback","useMemo","useState","OUTREACH_MAIL_GATEWAY_LABELS","outreachNextSendState","outreachClickSummary","outreachEnrollmentFigures","outreachEnrollmentTimeline","outreachStepName","OUTREACH_ATTESTATION_KINDS","OUTREACH_ATTESTATION_LABELS","OUTREACH_ENROLLMENT_ACTION_LABELS","outreachEnrollmentActionsFor","useOutreachEnrollmentActions","outreachCurrentStepLabel","outreachStepIsCurated","outreachStopLabel","formatOutreachTime","OutreachEnrollmentStatusChip","OutreachLoading","OutreachLoadProblem","outreachNextSendDetail","outreachNextSendLabel","useOutreachNowMs","OutreachFigure","useOutreachApi","useOutreachSequence","useOutreachEnrollment","useOutreachEnrollmentGateway","useOutreachEnrollmentHistory","outreachCrmRecordHref","kind","id","hostId","orgMount","orgSlug","host","hosts","find","entry","subdomain","outreachGmailThreadUrl","threadId","mailboxEmail","account","encodeURIComponent","KIND_ICONS","enrolled","skipped","curated","sent","task","click","scanner","open","paused","resumed","stopped","replied","bounced","held","released","failed","finished","TONE_COLORS","default","success","info","warning","error","Destination","props","variant","component","sx","display","wordBreak","label","href","url","target","rel","underline","TimelineRow","alignItems","divider","disableGutters","data-kind","minWidth","mt","color","tone","path","fontSize","disableTypography","primary","direction","xs","sm","spacing","justifyContent","fontWeight","title","whiteSpace","atMs","timeZone","secondary","urlLabel","detail","facts","length","gmailThreadId","join","Fact","m","typography","children","gatewaySentence","answer","intel","standing","status","domain","resolvedAtMs","from","sendingDomain","parts","gateway","mx","delivered30","blocked30","filter","Boolean","EnrollmentDetails","enrollment","sequence","memberName","enqueueSnackbar","time","ms","leadHref","leadId","contactHref","contactId","clicks","engagement","overrides","Object","entries","stepOverrides","sort","a","b","Number","attested","attestations","threads","gmailThreadIds","copyId","navigator","clipboard","writeText","then","catch","link","componentVariant","gridTemplateColumns","columnGap","rowGap","personalLine","createdAtMs","enrolledByUid","cold","pl","map","li","uid","mailbox","sendAs","email","mailboxId","campaignIds","campaignName","gatewayUnread","gatewayHold","heldAtMs","releasedAtMs","releasedByUid","gatewayDeliveredSteps","machineClicks","unloggedClicks","unloggedMachineClicks","firstClickAtMs","lastClickAtMs","followed","key","override","steps","source","edited","draftedByUid","draftedAtMs","model","subject","undefined","body","borderLeft","borderColor","prompt","thread","span","threadSubject","messageIds","stopReason","stoppedAtMs","stoppedByUid","updatedAtMs","fontFamily","size","aria-label","onClick","OutreachEnrollmentDetail","orgId","sectionPath","sequenceId","enrollmentId","api","loadedSequence","loaded","history","roster","enabled","detailsOpen","setDetailsOpen","nowMs","data","campaigns","actions","options","option","value","enrollmentsPath","mailboxes","timezone","timeline","formatTime","back","nativeButton","what","description","action","name","contactName","recordHref","figures","trackClicks","settings","stats","clickTracked","countOpens","openTracked","opens","machineOpens","available","includes","menu","menuItems","dash","toLocaleString","notTracked","scannerClicks","at","nextSend","nothingYet","nextDueAtMs","stepIndex","header","subheader","help","anchor","contentGutterX","contentGutterY","HeaderProps","flexWrap","disabled","busy","choose","items","describeChild","icon","clickable","reason","severity","stopDetail","anything","role","emailsSent","hint","linksFollowed","count","atLeast","replies","message","disablePadding","index","aria-expanded","aria-controls","endIcon","was","in","unmountOnExit","pb","mb","dialogs","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/enrollment-detail.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type ConsolePluginOrgMount,\n PageHeaderRecord,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport { pluginRecordHref } from '@aglyn/aglyn/plugin-manager/plugin-record-routes'\nimport {\n mdiAccountCancelOutline,\n mdiAccountOutline,\n mdiAccountPlusOutline,\n mdiAlertCircleOutline,\n mdiCheckCircleOutline,\n mdiChevronDown,\n mdiChevronUp,\n mdiClipboardCheckOutline,\n mdiContentCopy,\n mdiCursorDefaultClickOutline,\n mdiEmailAlertOutline,\n mdiEmailOffOutline,\n mdiEmailOpenOutline,\n mdiEmailOutline,\n mdiHandBackLeftOutline,\n mdiPauseCircleOutline,\n mdiPencilOutline,\n mdiPlayCircleOutline,\n mdiReply,\n mdiShieldSearch,\n mdiSkipNext,\n mdiStopCircleOutline,\n} from '@aglyn/shared-data-mdi'\nimport { AppLink, CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport RowActionsMenu from '@aglyn/shared-ui-jsx/components/row-actions-menu.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useOrgContainerOptions, useOrgMemberOptions } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n Card,\n Chip,\n Collapse,\n Divider,\n IconButton,\n Link,\n List,\n ListItem,\n ListItemIcon,\n ListItemText,\n Stack,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { type ReactNode, useCallback, useMemo, useState } from 'react'\nimport { OUTREACH_MAIL_GATEWAY_LABELS } from '../engine/mail-gateway'\nimport { outreachNextSendState } from '../engine/next-send'\nimport { outreachClickSummary } from '../model/enrollment-engagement'\nimport {\n outreachEnrollmentFigures,\n outreachEnrollmentTimeline,\n outreachStepName,\n type OutreachTimelineEntry,\n type OutreachTimelineKind,\n type OutreachTimelineTone,\n} from '../model/enrollment-timeline'\nimport {\n OUTREACH_ATTESTATION_KINDS,\n OUTREACH_ATTESTATION_LABELS,\n type OutreachEnrollment,\n type OutreachMailbox,\n type OutreachSequence,\n} from '../model/outreach.types'\nimport {\n OUTREACH_ENROLLMENT_ACTION_LABELS,\n outreachEnrollmentActionsFor,\n type OutreachEnrollmentRowAction,\n useOutreachEnrollmentActions,\n} from './enrollment-actions'\nimport { outreachCurrentStepLabel, outreachStepIsCurated, outreachStopLabel } from './enrollments-table'\nimport {\n formatOutreachTime,\n OutreachEnrollmentStatusChip,\n OutreachLoading,\n OutreachLoadProblem,\n} from './outreach-ui'\nimport { outreachNextSendDetail, outreachNextSendLabel, useOutreachNowMs } from './next-send'\nimport { OutreachFigure } from './sequence-report-card'\nimport { useOutreachApi } from './use-outreach-api'\nimport { useOutreachSequence } from './use-outreach-data'\nimport type { OutreachEnrollmentGatewayResponse } from '../model/outreach-api'\nimport {\n useOutreachEnrollment,\n useOutreachEnrollmentGateway,\n useOutreachEnrollmentHistory,\n} from './use-outreach-enrollment'\nimport type { OutreachMailboxesResult } from './use-outreach-mailboxes'\n\n/*==========================================\n * ONE PERSON IN ONE SEQUENCE (AGL-3332):\n * `/[orgSlug]/outreach/sequences/{sequenceId}/enrollments/{enrollmentId}`.\n *\n * A row of the Enrollments tab opens it, and its URL is the person's: a\n * comment or a message can link straight to them.\n *\n * Laid out the way every record page in the console is (the CRM's\n * `CrmRecordHeader` grammar): the page heading names the person; the first\n * card says what the record is, with the way back and the actions in its\n * HEADER — the one that changes things as a button, the rest and the\n * destructive ones behind the menu — and the facts that identify it as\n * chips. Under the chips, five numbers.\n *\n * Then ONE timeline, newest first, which is the page: every send, click,\n * reply, bounce, stop, hold and resume, from `model/enrollment-timeline.ts`.\n * Everything else stored on the enrollment is under Details, closed until\n * asked for — nothing is left out, and nothing is in the way.\n *=========================================*/\n\nexport interface OutreachEnrollmentDetailProps {\n orgId: string\n /** The org the hub is mounted under: its slug and sites, for the CRM record's address. */\n orgMount?: ConsolePluginOrgMount\n /** `/[orgSlug]/outreach/sequences`. */\n sectionPath: string\n sequenceId: string\n enrollmentId: string\n mailboxes: OutreachMailboxesResult\n}\n\n/**\n * Where the CRM record the person is lives — the site's own CRM when the site\n * is known, else the organization's — at the address the plugin that keeps\n * leads and contacts publishes, or `null` where none does.\n */\nexport function outreachCrmRecordHref(\n kind: 'lead' | 'contact',\n id: string | null | undefined,\n hostId: string,\n orgMount: Pick<ConsolePluginOrgMount, 'orgSlug' | 'hosts'> | undefined,\n): string | null {\n if (!id || !orgMount?.orgSlug) return null\n const host = orgMount.hosts.find((entry) => entry.id === hostId)?.subdomain ?? null\n return pluginRecordHref(kind, { orgSlug: orgMount.orgSlug, host }, id)\n}\n\n/**\n * Whether a mailbox's threads open in Gmail. A Microsoft 365 mailbox's\n * conversation has no address of its own in Outlook (AGL-3489), so its\n * thread is shown without a link.\n */\nexport const outreachThreadOpensInGmail = (mailbox: { provider?: string } | null | undefined): boolean =>\n mailbox?.provider !== 'microsoft'\n\n/** A Gmail thread, opened in the mailbox's own account. */\nexport function outreachGmailThreadUrl(threadId: string, mailboxEmail: string | null | undefined): string {\n const account = mailboxEmail ? `?authuser=${encodeURIComponent(mailboxEmail)}` : ''\n return `https://mail.google.com/mail/${account}#all/${encodeURIComponent(threadId)}`\n}\n\nconst KIND_ICONS: Record<OutreachTimelineKind, { path: string }> = {\n enrolled: mdiAccountPlusOutline,\n skipped: mdiSkipNext,\n curated: mdiPencilOutline,\n sent: mdiEmailOutline,\n task: mdiClipboardCheckOutline,\n click: mdiCursorDefaultClickOutline,\n scanner: mdiShieldSearch,\n 'earlier-clicks': mdiCursorDefaultClickOutline,\n open: mdiEmailOpenOutline,\n 'machine-open': mdiShieldSearch,\n paused: mdiPauseCircleOutline,\n resumed: mdiPlayCircleOutline,\n stopped: mdiStopCircleOutline,\n 'do-not-contact': mdiAccountCancelOutline,\n replied: mdiReply,\n bounced: mdiEmailAlertOutline,\n 'opted-out': mdiEmailOffOutline,\n held: mdiHandBackLeftOutline,\n released: mdiPlayCircleOutline,\n failed: mdiAlertCircleOutline,\n finished: mdiCheckCircleOutline,\n}\n\nconst TONE_COLORS: Record<OutreachTimelineTone, string> = {\n default: 'text.secondary',\n success: 'success.main',\n info: 'info.main',\n warning: 'warning.main',\n error: 'error.main',\n}\n\n/** A destination, whole, opening in a new tab. */\nfunction Destination(props: { url: string; label?: string }) {\n return (\n <Typography variant=\"body2\" component=\"span\" sx={{ display: 'block', wordBreak: 'break-all' }}>\n {props.label ? `${props.label}: ` : null}\n <Link href={props.url} target=\"_blank\" rel=\"noopener noreferrer\" underline=\"hover\">\n {props.url}\n </Link>\n </Typography>\n )\n}\n\n/** One line of the timeline. */\nfunction TimelineRow(props: {\n entry: OutreachTimelineEntry\n timeZone: string | null\n mailboxEmail: string | null\n /** False for a mailbox whose threads do not open in Gmail. */\n threadsOpenInGmail?: boolean\n divider: boolean\n}) {\n const { entry } = props\n return (\n <ListItem alignItems=\"flex-start\" divider={props.divider} disableGutters data-kind={entry.kind}>\n <ListItemIcon sx={{ minWidth: 36, mt: 0.75, color: TONE_COLORS[entry.tone] }}>\n <MdiIcon path={KIND_ICONS[entry.kind].path} fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText\n disableTypography\n primary={\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n spacing={{ xs: 0, sm: 1 }}\n sx={{ justifyContent: 'space-between', alignItems: { sm: 'baseline' } }}\n >\n <Typography variant=\"body2\" sx={{ fontWeight: 500 }}>\n {entry.title}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ whiteSpace: 'nowrap' }}>\n {formatOutreachTime(entry.atMs, props.timeZone)}\n </Typography>\n </Stack>\n }\n secondary={\n <Stack spacing={0.25} sx={{ mt: 0.25 }}>\n {entry.url ? <Destination url={entry.url} label={entry.urlLabel} /> : null}\n {entry.detail ? (\n <Typography variant=\"body2\" sx={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>\n {entry.detail}\n </Typography>\n ) : null}\n {entry.facts.length || (entry.gmailThreadId && props.threadsOpenInGmail !== false) ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {entry.facts.join(' · ')}\n {entry.gmailThreadId && props.threadsOpenInGmail !== false ? (\n <>\n {entry.facts.length ? ' · ' : null}\n <Link\n href={outreachGmailThreadUrl(entry.gmailThreadId, props.mailboxEmail)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n underline=\"hover\"\n >\n Open thread in Gmail\n </Link>\n </>\n ) : null}\n </Typography>\n ) : null}\n </Stack>\n }\n />\n </ListItem>\n )\n}\n\n/** One fact of the Details list. */\nfunction Fact(props: { label: string; children: ReactNode }) {\n return (\n <>\n <Typography component=\"dt\" variant=\"body2\" color=\"text.secondary\">\n {props.label}\n </Typography>\n <Box component=\"dd\" sx={{ m: 0, minWidth: 0, typography: 'body2', wordBreak: 'break-word' }}>\n {props.children}\n </Box>\n </>\n )\n}\n\n/** What mail from the sequence's sending domain met at the person's domain, in a line. */\nfunction gatewaySentence(answer: OutreachEnrollmentGatewayResponse, timeZone: string | null): string {\n const { intel, standing } = answer\n if (!intel) return 'Could not be looked up'\n if (intel.status === 'no_mx' || intel.status === 'null_mx') {\n return `${answer.domain ?? 'The domain'} takes no mail · looked up ${formatOutreachTime(intel.resolvedAtMs, timeZone)}`\n }\n const from = answer.sendingDomain ? ` from ${answer.sendingDomain}` : ''\n const parts = [\n OUTREACH_MAIL_GATEWAY_LABELS[intel.gateway],\n intel.mx.length ? `MX ${intel.mx.join(', ')}` : 'no MX; delivered to its address record',\n standing\n ? `${standing.delivered30} delivered, ${standing.blocked30} refused${from} in the last 30 days`\n : null,\n `looked up ${formatOutreachTime(intel.resolvedAtMs, timeZone)}`,\n ]\n return parts.filter(Boolean).join(' · ')\n}\n\n/**\n * Everything else the enrollment holds, all of it, behind one toggle.\n */\nfunction EnrollmentDetails(props: {\n enrollment: OutreachEnrollment\n sequence: OutreachSequence\n mailbox: OutreachMailbox | null\n gateway: OutreachEnrollmentGatewayResponse | null\n /** What the Mail gateway line says while there is no answer to show. */\n gatewayUnread: string\n campaignName: (id: string) => string\n memberName: (uid: string) => string\n orgMount?: ConsolePluginOrgMount\n timeZone: string | null\n}) {\n const { enrollment, sequence, memberName, timeZone } = props\n const { enqueueSnackbar } = useSnackbar()\n const time = (ms: number | null | undefined) => formatOutreachTime(ms, timeZone)\n const leadHref = outreachCrmRecordHref('lead', enrollment.leadId, enrollment.hostId, props.orgMount)\n const contactHref = outreachCrmRecordHref('contact', enrollment.contactId, enrollment.hostId, props.orgMount)\n const clicks = outreachClickSummary(enrollment.engagement)\n const overrides = Object.entries(enrollment.stepOverrides ?? {}).sort(\n ([a], [b]) => Number(a) - Number(b),\n )\n const attested = OUTREACH_ATTESTATION_KINDS.filter((kind) => enrollment.attestations?.[kind])\n const threads = enrollment.gmailThreadIds.length\n ? enrollment.gmailThreadIds\n : enrollment.gmailThreadId\n ? [enrollment.gmailThreadId]\n : []\n const copyId = () => {\n void navigator.clipboard\n ?.writeText(enrollment.id)\n .then(() => enqueueSnackbar('Enrollment id copied.', { variant: 'success' }))\n .catch(() => enqueueSnackbar('The id could not be copied.', { variant: 'error' }))\n }\n const link = (href: string | null, label: string) =>\n href ? (\n <Link {...({ component: AppLink, componentVariant: 'naked' } as object)} href={href} underline=\"hover\">\n {label}\n </Link>\n ) : (\n label\n )\n\n return (\n <Box\n component=\"dl\"\n sx={{\n m: 0,\n display: 'grid',\n gridTemplateColumns: { xs: '1fr', sm: 'minmax(160px, 220px) 1fr' },\n columnGap: 2,\n rowGap: 1.25,\n }}\n >\n <Fact label=\"Personal line\">\n {enrollment.personalLine ? (\n <Typography variant=\"body2\" sx={{ whiteSpace: 'pre-wrap' }}>\n {enrollment.personalLine}\n </Typography>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Enrolled as\">\n {enrollment.target === 'lead' ? (\n link(leadHref, 'Lead')\n ) : enrollment.leadId ? (\n <>\n {link(contactHref, 'Contact')}\n {', converted from a '}\n {link(leadHref, 'lead')}\n </>\n ) : (\n link(contactHref, 'Contact')\n )}\n </Fact>\n <Fact label=\"Enrolled\">\n {`${time(enrollment.createdAtMs)}${enrollment.enrolledByUid ? ` by ${memberName(enrollment.enrolledByUid)}` : ''}`}\n </Fact>\n <Fact label=\"Cold contact\">\n {enrollment.cold\n ? 'Yes — no inbound capture behind them, so the member confirmed the address before enrolling'\n : 'No'}\n </Fact>\n <Fact label=\"Attestations\">\n {attested.length ? (\n <Stack component=\"ul\" spacing={0.25} sx={{ m: 0, pl: 2.5 }}>\n {attested.map((kind) => {\n const entry = enrollment.attestations?.[kind]\n return (\n <li key={kind}>\n {`${OUTREACH_ATTESTATION_LABELS[kind]} — ${memberName(entry?.uid ?? '')}, ${time(entry?.atMs)}`}\n </li>\n )\n })}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Mailbox\">\n {props.mailbox\n ? `${props.mailbox.sendAs || props.mailbox.email}${props.mailbox.sendAs && props.mailbox.sendAs !== props.mailbox.email ? ` (${props.mailbox.email})` : ''}`\n : enrollment.mailboxId\n ? 'No longer connected'\n : '—'}\n </Fact>\n <Fact label=\"Campaigns\">\n {enrollment.campaignIds?.length\n ? enrollment.campaignIds.map(props.campaignName).join(', ')\n : '—'}\n </Fact>\n <Fact label=\"Mail gateway\">\n {props.gateway ? gatewaySentence(props.gateway, timeZone) : props.gatewayUnread}\n </Fact>\n <Fact label=\"Gateway hold\">\n {enrollment.gatewayHold\n ? [\n OUTREACH_MAIL_GATEWAY_LABELS[enrollment.gatewayHold.gateway],\n enrollment.gatewayHold.heldAtMs ? `held ${time(enrollment.gatewayHold.heldAtMs)}` : 'never held',\n enrollment.gatewayHold.releasedAtMs\n ? `released ${time(enrollment.gatewayHold.releasedAtMs)}${enrollment.gatewayHold.releasedByUid ? ` by ${memberName(enrollment.gatewayHold.releasedByUid)}` : ''}`\n : 'not released',\n ].join(' · ')\n : '—'}\n {enrollment.gatewayDeliveredSteps\n ? ` (${enrollment.gatewayDeliveredSteps} of their emails counted as delivered on the gateway ledger)`\n : null}\n </Fact>\n <Fact label=\"Clicks\">\n {clicks.clicks || clicks.machineClicks\n ? [\n `${clicks.clicks} by the person`,\n `${clicks.machineClicks} by scanners, not counted`,\n `${clicks.clicks - clicks.unloggedClicks + clicks.machineClicks - clicks.unloggedMachineClicks} listed one by one`,\n enrollment.engagement?.firstClickAtMs ? `first ${time(enrollment.engagement.firstClickAtMs)}` : null,\n enrollment.engagement?.lastClickAtMs ? `last ${time(enrollment.engagement.lastClickAtMs)}` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n : '—'}\n {clicks.followed.length ? (\n <Box sx={{ mt: 0.5 }}>\n {clicks.followed.map((url) => (\n <Destination key={url} url={url} />\n ))}\n </Box>\n ) : null}\n </Fact>\n <Fact label=\"Curated steps\">\n {overrides.length ? (\n <Stack spacing={1.5}>\n {overrides.map(([key, override]) => (\n <Box key={key}>\n <Typography variant=\"body2\" sx={{ fontWeight: 500 }}>\n {outreachStepName(sequence.steps, Number(key))}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {[\n override.source === 'ai' ? (override.edited ? 'AI draft, edited' : 'AI draft') : 'Written by a member',\n override.draftedByUid ? `confirmed by ${memberName(override.draftedByUid)}` : null,\n override.draftedAtMs ? time(override.draftedAtMs) : null,\n override.model ? `model ${override.model}` : null,\n ]\n .filter(Boolean)\n .join(' · ')}\n </Typography>\n {override.subject !== undefined ? (\n <Typography variant=\"body2\">{`Subject: ${override.subject}`}</Typography>\n ) : null}\n {override.body !== undefined ? (\n <Typography\n variant=\"body2\"\n sx={{ whiteSpace: 'pre-wrap', mt: 0.5, pl: 1.5, borderLeft: 2, borderColor: 'divider' }}\n >\n {override.body}\n </Typography>\n ) : null}\n {override.prompt ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ whiteSpace: 'pre-wrap', mt: 0.5 }}>\n {`Prompt: ${override.prompt}`}\n </Typography>\n ) : null}\n </Box>\n ))}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label={outreachThreadOpensInGmail(props.mailbox) ? 'Gmail threads' : 'Threads'}>\n {threads.length ? (\n <Stack spacing={0.25}>\n {threads.map((thread) => (\n <span key={thread}>\n {outreachThreadOpensInGmail(props.mailbox) ? (\n <Link\n href={outreachGmailThreadUrl(thread, props.mailbox?.email)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n underline=\"hover\"\n >\n {thread}\n </Link>\n ) : (\n <Box component=\"span\" sx={{ wordBreak: 'break-all' }}>\n {thread}\n </Box>\n )}\n {thread === enrollment.gmailThreadId ? ' (current)' : null}\n </span>\n ))}\n {enrollment.threadSubject ? (\n <Typography variant=\"caption\" color=\"text.secondary\">{`Started as “${enrollment.threadSubject}”`}</Typography>\n ) : null}\n {enrollment.messageIds.length ? (\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ wordBreak: 'break-all' }}>\n {`Message-IDs in the current thread: ${enrollment.messageIds.join(' ')}`}\n </Typography>\n ) : null}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Stop\">\n {enrollment.stopReason\n ? `${outreachStopLabel(enrollment)} · ${time(enrollment.stoppedAtMs)}${enrollment.stoppedByUid ? ` · by ${memberName(enrollment.stoppedByUid)}` : ''}`\n : '—'}\n </Fact>\n <Fact label=\"Created · updated\">{`${time(enrollment.createdAtMs)} · ${time(enrollment.updatedAtMs)}`}</Fact>\n <Fact label=\"Enrollment id\">\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ fontFamily: 'monospace', wordBreak: 'break-all' }}>\n {enrollment.id}\n </Typography>\n <Tooltip title=\"Copy the id\">\n <IconButton size=\"small\" aria-label=\"Copy the enrollment id\" onClick={copyId}>\n <MdiIcon path={mdiContentCopy.path} fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Stack>\n </Fact>\n </Box>\n )\n}\n\nexport function OutreachEnrollmentDetail(props: OutreachEnrollmentDetailProps) {\n const { orgId, sectionPath, sequenceId, enrollmentId, orgMount } = props\n const api = useOutreachApi(orgId)\n const loadedSequence = useOutreachSequence(orgId, sequenceId)\n const loaded = useOutreachEnrollment(orgId, enrollmentId)\n const history = useOutreachEnrollmentHistory(orgId, enrollmentId)\n const gateway = useOutreachEnrollmentGateway(api, enrollmentId)\n const roster = useOrgMemberOptions(orgId, { enabled: true })\n const [detailsOpen, setDetailsOpen] = useState(false)\n const nowMs = useOutreachNowMs()\n const enrollment = loaded.data\n const sequence = loadedSequence.data\n const campaigns = useOrgContainerOptions('campaign', orgId, {\n enabled: detailsOpen && Boolean(enrollment?.campaignIds?.length),\n })\n const steps = useMemo(() => sequence?.steps ?? [], [sequence])\n const actions = useOutreachEnrollmentActions({ api, steps })\n\n const memberName = useCallback(\n (uid: string) => roster.options.find((option) => option.uid === uid)?.label ?? 'a member',\n [roster.options],\n )\n const campaignName = useCallback(\n (id: string) => campaigns.options.find((option) => option.value === id)?.label ?? id,\n [campaigns.options],\n )\n\n const enrollmentsPath = `${sectionPath}/${sequenceId}/enrollments`\n const mailbox =\n props.mailboxes.mailboxes.find((entry) => entry.id === (enrollment?.mailboxId || sequence?.mailboxId)) ?? null\n const timeZone = mailbox?.timezone ?? null\n const time = (ms: number | null | undefined) => formatOutreachTime(ms, timeZone)\n const timeline = useMemo(\n () =>\n enrollment\n ? outreachEnrollmentTimeline({\n enrollment,\n steps,\n history: history.status === 'ready' ? history.data : null,\n memberName,\n formatTime: (ms) => formatOutreachTime(ms, timeZone),\n gateway: gateway.data?.intel?.gateway ?? null,\n })\n : [],\n [enrollment, steps, history, memberName, timeZone, gateway.data],\n )\n\n const back = (\n <Button\n // A real link, as the CRM record header's is: it opens in a new tab when asked.\n {...({ component: AppLink, componentVariant: 'naked', nativeButton: false } as object)}\n href={enrollmentsPath}\n size=\"small\"\n color=\"primary\"\n >\n Back to enrollments\n </Button>\n )\n\n if (loaded.status === 'loading' || loadedSequence.status === 'loading') {\n return <OutreachLoading label=\"Loading this person…\" />\n }\n if (loaded.status === 'error' || loaded.status === 'refused') {\n return <OutreachLoadProblem status={loaded.status} what=\"enrollment\" />\n }\n if (loadedSequence.status === 'error' || loadedSequence.status === 'refused') {\n return <OutreachLoadProblem status={loadedSequence.status} what=\"sequence\" />\n }\n // An id from another sequence reads as not here: the URL names both.\n if (!enrollment || !sequence || enrollment.sequenceId !== sequenceId) {\n return (\n <Card variant=\"outlined\">\n <EmptyStateComponent\n label=\"This person isn’t in this sequence\"\n description=\"They may have been removed from the workspace, or the link names a different sequence.\"\n action={back}\n />\n </Card>\n )\n }\n\n const name = enrollment.contactName || enrollment.email\n const kind = enrollment.target === 'lead' ? 'lead' : 'contact'\n const recordHref = outreachCrmRecordHref(\n kind,\n kind === 'lead' ? enrollment.leadId : enrollment.contactId,\n enrollment.hostId,\n orgMount,\n )\n const figures = outreachEnrollmentFigures(enrollment)\n const trackClicks = sequence.settings.trackClicks || sequence.stats?.clickTracked === true\n // Opens are shown for a sequence that counts them or once did (AGL-3395),\n // and for a person with any recorded, whatever the sequence says now.\n const countOpens =\n sequence.settings.countOpens ||\n sequence.stats?.openTracked === true ||\n figures.opens > 0 ||\n figures.machineOpens > 0\n const open = enrollment.status === 'active' || enrollment.status === 'paused'\n const held = enrollment.status === 'paused' && enrollment.stopReason === 'gateway_blocked_here'\n\n /*\n * The one act that moves the person forward is the button: resuming a\n * paused one, else curating the next email. Everything else is in the\n * menu, the destructive acts included, as on every record page.\n */\n const available = outreachEnrollmentActionsFor(enrollment, steps)\n const primary: OutreachEnrollmentRowAction | null = available.includes('resume')\n ? 'resume'\n : available.includes('curate')\n ? 'curate'\n : null\n const menu = actions.menuItems(enrollment, (action) => action !== primary)\n const dash = (value: number) => (value ? value.toLocaleString() : '—')\n const notTracked = !trackClicks && !figures.clicks && !figures.scannerClicks ? 'Not tracked' : undefined\n const thread = enrollment.gmailThreadId ?? enrollment.gmailThreadIds.at(-1) ?? null\n const nextSend = outreachNextSendState({\n enrollment,\n sequence,\n mailbox: props.mailboxes.status === 'ready' ? mailbox : undefined,\n nowMs,\n })\n const nothingYet =\n enrollment.status === 'active' && enrollment.nextDueAtMs\n ? nextSend.kind === 'queued'\n ? `Nothing yet — step ${enrollment.stepIndex + 1} is due and queued to send.`\n : `Nothing yet — step ${enrollment.stepIndex + 1} sends ${time(enrollment.nextDueAtMs)}.`\n : 'Nothing yet.'\n\n return (\n <Stack spacing={2}>\n {/* The page heading and the trail name the person; the card says what they are in. */}\n <PageHeaderRecord title={name} />\n <CardDisplay\n header=\"Enrollment\"\n subheader={\n <>\n {enrollment.contactName ? `${enrollment.email} · ` : ''}\n {`In ${sequence.name || 'Untitled'}`}\n </>\n }\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n action: (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}>\n {back}\n {primary ? (\n <Button\n variant=\"outlined\"\n size=\"small\"\n disabled={actions.busy === enrollment.id}\n onClick={() => actions.choose(enrollment, primary)}\n >\n {held ? 'Resume and send' : OUTREACH_ENROLLMENT_ACTION_LABELS[primary]}\n </Button>\n ) : null}\n {menu.length ? <RowActionsMenu label={name} items={menu} /> : null}\n </Stack>\n ),\n }}\n >\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}>\n <Tooltip\n describeChild\n title={recordHref ? `Open the ${kind} in the CRM` : `The ${kind}’s record can’t be linked`}\n >\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color={recordHref ? 'primary' : 'default'}\n icon={<MdiIcon path={mdiAccountOutline.path} fontSize=\"small\" />}\n label={kind === 'lead' ? 'Lead' : 'Contact'}\n {...(recordHref\n ? ({ component: AppLink, href: recordHref, clickable: true, componentVariant: 'naked' } as object)\n : {})}\n />\n </Tooltip>\n <OutreachEnrollmentStatusChip status={enrollment.status} />\n <Chip size=\"small\" variant=\"outlined\" label={outreachCurrentStepLabel(enrollment, steps)} />\n {outreachStepIsCurated(enrollment) ? (\n <Chip size=\"small\" variant=\"outlined\" color=\"success\" label=\"Curated\" />\n ) : null}\n {open && enrollment.nextDueAtMs ? (\n nextSend.kind === 'queued' ? (\n <Tooltip describeChild title={outreachNextSendDetail(nextSend, timeZone)}>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color={\n nextSend.reason === 'mailbox_not_sending' || nextSend.reason === 'sequence_not_active'\n ? 'warning'\n : 'default'\n }\n label={`Next send ${outreachNextSendLabel(nextSend, timeZone)}`}\n />\n </Tooltip>\n ) : (\n <Chip size=\"small\" variant=\"outlined\" label={`Next send ${time(enrollment.nextDueAtMs)}`} />\n )\n ) : null}\n </Stack>\n {held ? (\n <Alert severity=\"warning\">\n {enrollment.stopDetail ||\n 'Their mail gateway refused this sender, so the next email is held. Resume to send it anyway.'}\n </Alert>\n ) : null}\n {figures.anything ? (\n <Stack direction=\"row\" spacing={3} sx={{ flexWrap: 'wrap', rowGap: 2 }} role=\"group\" aria-label=\"In numbers\">\n <OutreachFigure label=\"Emails sent\" value={dash(figures.emailsSent)} />\n {countOpens ? (\n <OutreachFigure\n label=\"Opens\"\n value={dash(figures.opens)}\n hint={figures.machineOpens ? `${figures.machineOpens.toLocaleString()} by machines, not counted` : undefined}\n />\n ) : null}\n <OutreachFigure label=\"Clicks\" value={dash(figures.clicks)} hint={notTracked} />\n <OutreachFigure\n label=\"Links followed\"\n value={\n figures.linksFollowed.count\n ? `${figures.linksFollowed.count}${figures.linksFollowed.atLeast ? '+' : ''}`\n : '—'\n }\n hint={\n notTracked ??\n (figures.linksFollowed.atLeast && figures.linksFollowed.count\n ? 'Earlier clicks kept the last link only'\n : undefined)\n }\n />\n <OutreachFigure label=\"Scanner clicks\" value={dash(figures.scannerClicks)} hint={notTracked ?? 'Not counted'} />\n <OutreachFigure label=\"Replies\" value={dash(figures.replies)} />\n </Stack>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {nothingYet}\n </Typography>\n )}\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header=\"Activity\"\n subheader=\"Newest first\"\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n contentGutterY\n HeaderProps={\n thread && outreachThreadOpensInGmail(mailbox)\n ? {\n action: (\n <Button\n size=\"small\"\n href={outreachGmailThreadUrl(thread, mailbox?.email)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Open thread in Gmail\n </Button>\n ),\n }\n : undefined\n }\n >\n <Stack spacing={1}>\n {history.status === 'loading' ? <OutreachLoading label=\"Loading their history…\" /> : null}\n {history.status === 'error' || history.status === 'refused' ? (\n <OutreachLoadProblem\n status={history.status}\n what=\"list of their clicks\"\n // Only the one-by-one list is missing: the totals, the sends and\n // every stop above come from the enrollment, which was read.\n message={\n history.status === 'refused'\n ? 'Their clicks can’t be listed one by one here; the numbers above still count them.'\n : 'Their clicks couldn’t be listed one by one. Reload the page to try again.'\n }\n />\n ) : null}\n <List disablePadding aria-label=\"Activity\">\n {timeline.map((entry, index) => (\n <TimelineRow\n key={entry.key}\n entry={entry}\n timeZone={timeZone}\n mailboxEmail={mailbox?.email ?? null}\n threadsOpenInGmail={outreachThreadOpensInGmail(mailbox)}\n divider={index < timeline.length - 1}\n />\n ))}\n </List>\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header=\"Details\"\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n HeaderProps={{\n action: (\n <Button\n size=\"small\"\n aria-expanded={detailsOpen}\n aria-controls=\"outreach-enrollment-details\"\n endIcon={<MdiIcon path={(detailsOpen ? mdiChevronUp : mdiChevronDown).path} fontSize=\"small\" />}\n onClick={() => setDetailsOpen((was) => !was)}\n >\n {detailsOpen ? 'Hide' : 'Show'}\n </Button>\n ),\n }}\n >\n <Collapse in={detailsOpen} unmountOnExit>\n <Box id=\"outreach-enrollment-details\" sx={{ pb: 2 }}>\n <Divider sx={{ mb: 2 }} />\n <EnrollmentDetails\n enrollment={enrollment}\n sequence={sequence}\n mailbox={mailbox}\n gateway={gateway.status === 'ready' ? gateway.data : null}\n gatewayUnread={\n gateway.status === 'loading'\n ? 'Looking it up…'\n : gateway.status === 'refused'\n ? 'Your role cannot look it up'\n : 'Could not be looked up'\n }\n campaignName={campaignName}\n memberName={memberName}\n orgMount={orgMount}\n timeZone={timeZone}\n />\n </Box>\n </Collapse>\n </CardDisplay>\n\n {actions.dialogs}\n </Stack>\n )\n}\nOutreachEnrollmentDetail.displayName = 'OutreachEnrollmentDetail'\n\nexport default OutreachEnrollmentDetail\n"],"names":["PageHeaderRecord","pluginDocsHelp","pluginRecordHref","mdiAccountCancelOutline","mdiAccountOutline","mdiAccountPlusOutline","mdiAlertCircleOutline","mdiCheckCircleOutline","mdiChevronDown","mdiChevronUp","mdiClipboardCheckOutline","mdiContentCopy","mdiCursorDefaultClickOutline","mdiEmailAlertOutline","mdiEmailOffOutline","mdiEmailOpenOutline","mdiEmailOutline","mdiHandBackLeftOutline","mdiPauseCircleOutline","mdiPencilOutline","mdiPlayCircleOutline","mdiReply","mdiShieldSearch","mdiSkipNext","mdiStopCircleOutline","AppLink","CardDisplay","MdiIcon","EmptyStateComponent","RowActionsMenu","useSnackbar","useOrgContainerOptions","useOrgMemberOptions","Alert","Box","Button","Card","Chip","Collapse","Divider","IconButton","Link","List","ListItem","ListItemIcon","ListItemText","Stack","Tooltip","Typography","useCallback","useMemo","useState","OUTREACH_MAIL_GATEWAY_LABELS","outreachNextSendState","outreachClickSummary","outreachEnrollmentFigures","outreachEnrollmentTimeline","outreachStepName","OUTREACH_ATTESTATION_KINDS","OUTREACH_ATTESTATION_LABELS","OUTREACH_ENROLLMENT_ACTION_LABELS","outreachEnrollmentActionsFor","useOutreachEnrollmentActions","outreachCurrentStepLabel","outreachStepIsCurated","outreachStopLabel","formatOutreachTime","OutreachEnrollmentStatusChip","OutreachLoading","OutreachLoadProblem","outreachNextSendDetail","outreachNextSendLabel","useOutreachNowMs","OutreachFigure","useOutreachApi","useOutreachSequence","useOutreachEnrollment","useOutreachEnrollmentGateway","useOutreachEnrollmentHistory","outreachCrmRecordHref","kind","id","hostId","orgMount","orgSlug","host","hosts","find","entry","subdomain","outreachThreadOpensInGmail","mailbox","provider","outreachGmailThreadUrl","threadId","mailboxEmail","account","encodeURIComponent","KIND_ICONS","enrolled","skipped","curated","sent","task","click","scanner","open","paused","resumed","stopped","replied","bounced","held","released","failed","finished","TONE_COLORS","default","success","info","warning","error","Destination","props","variant","component","sx","display","wordBreak","label","href","url","target","rel","underline","TimelineRow","alignItems","divider","disableGutters","data-kind","minWidth","mt","color","tone","path","fontSize","disableTypography","primary","direction","xs","sm","spacing","justifyContent","fontWeight","title","whiteSpace","atMs","timeZone","secondary","urlLabel","detail","facts","length","gmailThreadId","threadsOpenInGmail","join","Fact","m","typography","children","gatewaySentence","answer","intel","standing","status","domain","resolvedAtMs","from","sendingDomain","parts","gateway","mx","delivered30","blocked30","filter","Boolean","EnrollmentDetails","enrollment","sequence","memberName","enqueueSnackbar","time","ms","leadHref","leadId","contactHref","contactId","clicks","engagement","overrides","Object","entries","stepOverrides","sort","a","b","Number","attested","attestations","threads","gmailThreadIds","copyId","navigator","clipboard","writeText","then","catch","link","componentVariant","gridTemplateColumns","columnGap","rowGap","personalLine","createdAtMs","enrolledByUid","cold","pl","map","li","uid","sendAs","email","mailboxId","campaignIds","campaignName","gatewayUnread","gatewayHold","heldAtMs","releasedAtMs","releasedByUid","gatewayDeliveredSteps","machineClicks","unloggedClicks","unloggedMachineClicks","firstClickAtMs","lastClickAtMs","followed","key","override","steps","source","edited","draftedByUid","draftedAtMs","model","subject","undefined","body","borderLeft","borderColor","prompt","thread","span","threadSubject","messageIds","stopReason","stoppedAtMs","stoppedByUid","updatedAtMs","fontFamily","size","aria-label","onClick","OutreachEnrollmentDetail","orgId","sectionPath","sequenceId","enrollmentId","api","loadedSequence","loaded","history","roster","enabled","detailsOpen","setDetailsOpen","nowMs","data","campaigns","actions","options","option","value","enrollmentsPath","mailboxes","timezone","timeline","formatTime","back","nativeButton","what","description","action","name","contactName","recordHref","figures","trackClicks","settings","stats","clickTracked","countOpens","openTracked","opens","machineOpens","available","includes","menu","menuItems","dash","toLocaleString","notTracked","scannerClicks","at","nextSend","nothingYet","nextDueAtMs","stepIndex","header","subheader","help","anchor","contentGutterX","contentGutterY","HeaderProps","flexWrap","disabled","busy","choose","items","describeChild","icon","clickable","reason","severity","stopDetail","anything","role","emailsSent","hint","linksFollowed","count","atLeast","replies","message","disablePadding","index","aria-expanded","aria-controls","endIcon","was","in","unmountOnExit","pb","mb","dialogs","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,SAEEA,gBAAgB,EAChBC,cAAc,QACT,eAAc;AACrB,SAASC,gBAAgB,QAAQ,mDAAkD;AACnF,SACEC,uBAAuB,EACvBC,iBAAiB,EACjBC,qBAAqB,EACrBC,qBAAqB,EACrBC,qBAAqB,EACrBC,cAAc,EACdC,YAAY,EACZC,wBAAwB,EACxBC,cAAc,EACdC,4BAA4B,EAC5BC,oBAAoB,EACpBC,kBAAkB,EAClBC,mBAAmB,EACnBC,eAAe,EACfC,sBAAsB,EACtBC,qBAAqB,EACrBC,gBAAgB,EAChBC,oBAAoB,EACpBC,QAAQ,EACRC,eAAe,EACfC,WAAW,EACXC,oBAAoB,QACf,yBAAwB;AAC/B,SAASC,OAAO,EAAEC,WAAW,EAAEC,OAAO,QAAQ,uBAAsB;AACpE,OAAOC,yBAAyB,wDAAuD;AACvF,OAAOC,oBAAoB,6DAA4D;AACvF,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,sBAAsB,EAAEC,mBAAmB,QAAQ,iCAAgC;AAC5F,SACEC,KAAK,EACLC,GAAG,EACHC,MAAM,EACNC,IAAI,EACJC,IAAI,EACJC,QAAQ,EACRC,OAAO,EACPC,UAAU,EACVC,IAAI,EACJC,IAAI,EACJC,QAAQ,EACRC,YAAY,EACZC,YAAY,EACZC,KAAK,EACLC,OAAO,EACPC,UAAU,QACL,gBAAe;AACtB,SAAyBC,WAAW,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AACtE,SAASC,4BAA4B,QAAQ,4BAAwB;AACrE,SAASC,qBAAqB,QAAQ,yBAAqB;AAC3D,SAASC,oBAAoB,QAAQ,oCAAgC;AACrE,SACEC,yBAAyB,EACzBC,0BAA0B,EAC1BC,gBAAgB,QAIX,kCAA8B;AACrC,SACEC,0BAA0B,EAC1BC,2BAA2B,QAItB,6BAAyB;AAChC,SACEC,iCAAiC,EACjCC,4BAA4B,EAE5BC,4BAA4B,QACvB,0BAAsB;AAC7B,SAASC,wBAAwB,EAAEC,qBAAqB,EAAEC,iBAAiB,QAAQ,yBAAqB;AACxG,SACEC,kBAAkB,EAClBC,4BAA4B,EAC5BC,eAAe,EACfC,mBAAmB,QACd,mBAAe;AACtB,SAASC,sBAAsB,EAAEC,qBAAqB,EAAEC,gBAAgB,QAAQ,iBAAa;AAC7F,SAASC,cAAc,QAAQ,4BAAwB;AACvD,SAASC,cAAc,QAAQ,wBAAoB;AACnD,SAASC,mBAAmB,QAAQ,yBAAqB;AAEzD,SACEC,qBAAqB,EACrBC,4BAA4B,EAC5BC,4BAA4B,QACvB,+BAA2B;AAkClC;;;;CAIC,GACD,OAAO,SAASC,sBACdC,IAAwB,EACxBC,EAA6B,EAC7BC,MAAc,EACdC,QAAsE;;QAGzDA;IADb,IAAI,CAACF,MAAM,EAACE,4BAAAA,SAAUC,OAAO,GAAE,OAAO;IACtC,MAAMC,gBAAOF,uBAAAA,SAASG,KAAK,CAACC,IAAI,CAAC,CAACC,QAAUA,MAAMP,EAAE,KAAKC,4BAA5CC,qBAAqDM,SAAS,mBAAI;IAC/E,OAAOvF,iBAAiB8E,MAAM;QAAEI,SAASD,SAASC,OAAO;QAAEC;IAAK,GAAGJ;AACrE;AAEA;;;;CAIC,GACD,OAAO,MAAMS,6BAA6B,CAACC,UACzCA,CAAAA,2BAAAA,QAASC,QAAQ,MAAK,YAAW;AAEnC,yDAAyD,GACzD,OAAO,SAASC,uBAAuBC,QAAgB,EAAEC,YAAuC;IAC9F,MAAMC,UAAUD,eAAe,CAAC,UAAU,EAAEE,mBAAmBF,eAAe,GAAG;IACjF,OAAO,CAAC,6BAA6B,EAAEC,QAAQ,KAAK,EAAEC,mBAAmBH,WAAW;AACtF;AAEA,MAAMI,aAA6D;IACjEC,UAAU9F;IACV+F,SAAS7E;IACT8E,SAASlF;IACTmF,MAAMtF;IACNuF,MAAM7F;IACN8F,OAAO5F;IACP6F,SAASnF;IACT,kBAAkBV;IAClB8F,MAAM3F;IACN,gBAAgBO;IAChBqF,QAAQzF;IACR0F,SAASxF;IACTyF,SAASrF;IACT,kBAAkBrB;IAClB2G,SAASzF;IACT0F,SAASlG;IACT,aAAaC;IACbkG,MAAM/F;IACNgG,UAAU7F;IACV8F,QAAQ5G;IACR6G,UAAU5G;AACZ;AAEA,MAAM6G,cAAoD;IACxDC,SAAS;IACTC,SAAS;IACTC,MAAM;IACNC,SAAS;IACTC,OAAO;AACT;AAEA,gDAAgD,GAChD,SAASC,YAAYC,KAAsC;IACzD,qBACE,MAAC3E;QAAW4E,SAAQ;QAAQC,WAAU;QAAOC,IAAI;YAAEC,SAAS;YAASC,WAAW;QAAY;;YACzFL,MAAMM,KAAK,GAAG,GAAGN,MAAMM,KAAK,CAAC,EAAE,CAAC,GAAG;0BACpC,KAACxF;gBAAKyF,MAAMP,MAAMQ,GAAG;gBAAEC,QAAO;gBAASC,KAAI;gBAAsBC,WAAU;0BACxEX,MAAMQ,GAAG;;;;AAIlB;AAEA,8BAA8B,GAC9B,SAASI,YAAYZ,KAOpB;IACC,MAAM,EAAEnC,KAAK,EAAE,GAAGmC;IAClB,qBACE,MAAChF;QAAS6F,YAAW;QAAaC,SAASd,MAAMc,OAAO;QAAEC,cAAc;QAACC,aAAWnD,MAAMR,IAAI;;0BAC5F,KAACpC;gBAAakF,IAAI;oBAAEc,UAAU;oBAAIC,IAAI;oBAAMC,OAAO1B,WAAW,CAAC5B,MAAMuD,IAAI,CAAC;gBAAC;0BACzE,cAAA,KAACpH;oBAAQqH,MAAM9C,UAAU,CAACV,MAAMR,IAAI,CAAC,CAACgE,IAAI;oBAAEC,UAAS;;;0BAEvD,KAACpG;gBACCqG,iBAAiB;gBACjBC,uBACE,MAACrG;oBACCsG,WAAW;wBAAEC,IAAI;wBAAUC,IAAI;oBAAM;oBACrCC,SAAS;wBAAEF,IAAI;wBAAGC,IAAI;oBAAE;oBACxBxB,IAAI;wBAAE0B,gBAAgB;wBAAiBhB,YAAY;4BAAEc,IAAI;wBAAW;oBAAE;;sCAEtE,KAACtG;4BAAW4E,SAAQ;4BAAQE,IAAI;gCAAE2B,YAAY;4BAAI;sCAC/CjE,MAAMkE,KAAK;;sCAEd,KAAC1G;4BAAW4E,SAAQ;4BAAUkB,OAAM;4BAAiBhB,IAAI;gCAAE6B,YAAY;4BAAS;sCAC7EzF,mBAAmBsB,MAAMoE,IAAI,EAAEjC,MAAMkC,QAAQ;;;;gBAIpDC,yBACE,MAAChH;oBAAMyG,SAAS;oBAAMzB,IAAI;wBAAEe,IAAI;oBAAK;;wBAClCrD,MAAM2C,GAAG,iBAAG,KAACT;4BAAYS,KAAK3C,MAAM2C,GAAG;4BAAEF,OAAOzC,MAAMuE,QAAQ;6BAAO;wBACrEvE,MAAMwE,MAAM,iBACX,KAAChH;4BAAW4E,SAAQ;4BAAQE,IAAI;gCAAE6B,YAAY;gCAAY3B,WAAW;4BAAa;sCAC/ExC,MAAMwE,MAAM;6BAEb;wBACHxE,MAAMyE,KAAK,CAACC,MAAM,IAAK1E,MAAM2E,aAAa,IAAIxC,MAAMyC,kBAAkB,KAAK,sBAC1E,MAACpH;4BAAW4E,SAAQ;4BAAUkB,OAAM;4BAAiBjB,WAAU;;gCAC5DrC,MAAMyE,KAAK,CAACI,IAAI,CAAC;gCACjB7E,MAAM2E,aAAa,IAAIxC,MAAMyC,kBAAkB,KAAK,sBACnD;;wCACG5E,MAAMyE,KAAK,CAACC,MAAM,GAAG,QAAQ;sDAC9B,KAACzH;4CACCyF,MAAMrC,uBAAuBL,MAAM2E,aAAa,EAAExC,MAAM5B,YAAY;4CACpEqC,QAAO;4CACPC,KAAI;4CACJC,WAAU;sDACX;;;qCAID;;6BAEJ;;;;;;AAMhB;AAEA,kCAAkC,GAClC,SAASgC,KAAK3C,KAA6C;IACzD,qBACE;;0BACE,KAAC3E;gBAAW6E,WAAU;gBAAKD,SAAQ;gBAAQkB,OAAM;0BAC9CnB,MAAMM,KAAK;;0BAEd,KAAC/F;gBAAI2F,WAAU;gBAAKC,IAAI;oBAAEyC,GAAG;oBAAG3B,UAAU;oBAAG4B,YAAY;oBAASxC,WAAW;gBAAa;0BACvFL,MAAM8C,QAAQ;;;;AAIvB;AAEA,wFAAwF,GACxF,SAASC,gBAAgBC,MAAyC,EAAEd,QAAuB;IACzF,MAAM,EAAEe,KAAK,EAAEC,QAAQ,EAAE,GAAGF;IAC5B,IAAI,CAACC,OAAO,OAAO;IACnB,IAAIA,MAAME,MAAM,KAAK,WAAWF,MAAME,MAAM,KAAK,WAAW;YAChDH;QAAV,OAAO,IAAGA,iBAAAA,OAAOI,MAAM,YAAbJ,iBAAiB,aAAa,2BAA2B,EAAEzG,mBAAmB0G,MAAMI,YAAY,EAAEnB,WAAW;IACzH;IACA,MAAMoB,OAAON,OAAOO,aAAa,GAAG,CAAC,MAAM,EAAEP,OAAOO,aAAa,EAAE,GAAG;IACtE,MAAMC,QAAQ;QACZ/H,4BAA4B,CAACwH,MAAMQ,OAAO,CAAC;QAC3CR,MAAMS,EAAE,CAACnB,MAAM,GAAG,CAAC,GAAG,EAAEU,MAAMS,EAAE,CAAChB,IAAI,CAAC,OAAO,GAAG;QAChDQ,WACI,GAAGA,SAASS,WAAW,CAAC,YAAY,EAAET,SAASU,SAAS,CAAC,QAAQ,EAAEN,KAAK,oBAAoB,CAAC,GAC7F;QACJ,CAAC,UAAU,EAAE/G,mBAAmB0G,MAAMI,YAAY,EAAEnB,WAAW;KAChE;IACD,OAAOsB,MAAMK,MAAM,CAACC,SAASpB,IAAI,CAAC;AACpC;AAEA;;CAEC,GACD,SAASqB,kBAAkB/D,KAW1B;QAOkCgE;QAyF1BA,yBA2BKA,wBACAA;IA3HZ,MAAM,EAAEA,UAAU,EAAEC,QAAQ,EAAEC,UAAU,EAAEhC,QAAQ,EAAE,GAAGlC;IACvD,MAAM,EAAEmE,eAAe,EAAE,GAAGhK;IAC5B,MAAMiK,OAAO,CAACC,KAAkC9H,mBAAmB8H,IAAInC;IACvE,MAAMoC,WAAWlH,sBAAsB,QAAQ4G,WAAWO,MAAM,EAAEP,WAAWzG,MAAM,EAAEyC,MAAMxC,QAAQ;IACnG,MAAMgH,cAAcpH,sBAAsB,WAAW4G,WAAWS,SAAS,EAAET,WAAWzG,MAAM,EAAEyC,MAAMxC,QAAQ;IAC5G,MAAMkH,SAAS/I,qBAAqBqI,WAAWW,UAAU;IACzD,MAAMC,YAAYC,OAAOC,OAAO,EAACd,4BAAAA,WAAWe,aAAa,YAAxBf,4BAA4B,CAAC,GAAGgB,IAAI,CACnE,CAAC,CAACC,EAAE,EAAE,CAACC,EAAE,GAAKC,OAAOF,KAAKE,OAAOD;IAEnC,MAAME,WAAWrJ,2BAA2B8H,MAAM,CAAC,CAACxG;YAAS2G;gBAAAA,2BAAAA,WAAWqB,YAAY,qBAAvBrB,wBAAyB,CAAC3G,KAAK;;IAC5F,MAAMiI,UAAUtB,WAAWuB,cAAc,CAAChD,MAAM,GAC5CyB,WAAWuB,cAAc,GACzBvB,WAAWxB,aAAa,GACtB;QAACwB,WAAWxB,aAAa;KAAC,GAC1B,EAAE;IACR,MAAMgD,SAAS;YACRC;QAAL,OAAKA,uBAAAA,UAAUC,SAAS,qBAAnBD,qBACDE,SAAS,CAAC3B,WAAW1G,EAAE,EACxBsI,IAAI,CAAC,IAAMzB,gBAAgB,yBAAyB;gBAAElE,SAAS;YAAU,IACzE4F,KAAK,CAAC,IAAM1B,gBAAgB,+BAA+B;gBAAElE,SAAS;YAAQ;IACnF;IACA,MAAM6F,OAAO,CAACvF,MAAqBD,QACjCC,qBACE,KAACzF,mBAAU;YAAEoF,WAAWpG;YAASiM,kBAAkB;QAAQ;YAAcxF,MAAMA;YAAMI,WAAU;sBAC5FL;cAGHA;IAGJ,qBACE,MAAC/F;QACC2F,WAAU;QACVC,IAAI;YACFyC,GAAG;YACHxC,SAAS;YACT4F,qBAAqB;gBAAEtE,IAAI;gBAAOC,IAAI;YAA2B;YACjEsE,WAAW;YACXC,QAAQ;QACV;;0BAEA,KAACvD;gBAAKrC,OAAM;0BACT0D,WAAWmC,YAAY,iBACtB,KAAC9K;oBAAW4E,SAAQ;oBAAQE,IAAI;wBAAE6B,YAAY;oBAAW;8BACtDgC,WAAWmC,YAAY;qBAG1B;;0BAGJ,KAACxD;gBAAKrC,OAAM;0BACT0D,WAAWvD,MAAM,KAAK,SACrBqF,KAAKxB,UAAU,UACbN,WAAWO,MAAM,iBACnB;;wBACGuB,KAAKtB,aAAa;wBAClB;wBACAsB,KAAKxB,UAAU;;qBAGlBwB,KAAKtB,aAAa;;0BAGtB,KAAC7B;gBAAKrC,OAAM;0BACT,GAAG8D,KAAKJ,WAAWoC,WAAW,IAAIpC,WAAWqC,aAAa,GAAG,CAAC,IAAI,EAAEnC,WAAWF,WAAWqC,aAAa,GAAG,GAAG,IAAI;;0BAEpH,KAAC1D;gBAAKrC,OAAM;0BACT0D,WAAWsC,IAAI,GACZ,+FACA;;0BAEN,KAAC3D;gBAAKrC,OAAM;0BACT8E,SAAS7C,MAAM,iBACd,KAACpH;oBAAM+E,WAAU;oBAAK0B,SAAS;oBAAMzB,IAAI;wBAAEyC,GAAG;wBAAG2D,IAAI;oBAAI;8BACtDnB,SAASoB,GAAG,CAAC,CAACnJ;;4BACC2G;wBAAd,MAAMnG,SAAQmG,2BAAAA,WAAWqB,YAAY,qBAAvBrB,wBAAyB,CAAC3G,KAAK;wBAC7C,qBACE,KAACoJ;sCACE,GAAGzK,2BAA2B,CAACqB,KAAK,CAAC,GAAG,EAAE6G,mBAAWrG,yBAAAA,MAAO6I,GAAG,mBAAI,IAAI,EAAE,EAAEtC,KAAKvG,yBAAAA,MAAOoE,IAAI,GAAG;2BADxF5E;oBAIb;qBAGF;;0BAGJ,KAACsF;gBAAKrC,OAAM;0BACTN,MAAMhC,OAAO,GACV,GAAGgC,MAAMhC,OAAO,CAAC2I,MAAM,IAAI3G,MAAMhC,OAAO,CAAC4I,KAAK,GAAG5G,MAAMhC,OAAO,CAAC2I,MAAM,IAAI3G,MAAMhC,OAAO,CAAC2I,MAAM,KAAK3G,MAAMhC,OAAO,CAAC4I,KAAK,GAAG,CAAC,EAAE,EAAE5G,MAAMhC,OAAO,CAAC4I,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAC1J5C,WAAW6C,SAAS,GAClB,wBACA;;0BAER,KAAClE;gBAAKrC,OAAM;0BACT0D,EAAAA,0BAAAA,WAAW8C,WAAW,qBAAtB9C,wBAAwBzB,MAAM,IAC3ByB,WAAW8C,WAAW,CAACN,GAAG,CAACxG,MAAM+G,YAAY,EAAErE,IAAI,CAAC,QACpD;;0BAEN,KAACC;gBAAKrC,OAAM;0BACTN,MAAMyD,OAAO,GAAGV,gBAAgB/C,MAAMyD,OAAO,EAAEvB,YAAYlC,MAAMgH,aAAa;;0BAEjF,MAACrE;gBAAKrC,OAAM;;oBACT0D,WAAWiD,WAAW,GACnB;wBACExL,4BAA4B,CAACuI,WAAWiD,WAAW,CAACxD,OAAO,CAAC;wBAC5DO,WAAWiD,WAAW,CAACC,QAAQ,GAAG,CAAC,KAAK,EAAE9C,KAAKJ,WAAWiD,WAAW,CAACC,QAAQ,GAAG,GAAG;wBACpFlD,WAAWiD,WAAW,CAACE,YAAY,GAC/B,CAAC,SAAS,EAAE/C,KAAKJ,WAAWiD,WAAW,CAACE,YAAY,IAAInD,WAAWiD,WAAW,CAACG,aAAa,GAAG,CAAC,IAAI,EAAElD,WAAWF,WAAWiD,WAAW,CAACG,aAAa,GAAG,GAAG,IAAI,GAC/J;qBACL,CAAC1E,IAAI,CAAC,SACP;oBACHsB,WAAWqD,qBAAqB,GAC7B,CAAC,EAAE,EAAErD,WAAWqD,qBAAqB,CAAC,4DAA4D,CAAC,GACnG;;;0BAEN,MAAC1E;gBAAKrC,OAAM;;oBACToE,OAAOA,MAAM,IAAIA,OAAO4C,aAAa,GAClC;wBACE,GAAG5C,OAAOA,MAAM,CAAC,cAAc,CAAC;wBAChC,GAAGA,OAAO4C,aAAa,CAAC,yBAAyB,CAAC;wBAClD,GAAG5C,OAAOA,MAAM,GAAGA,OAAO6C,cAAc,GAAG7C,OAAO4C,aAAa,GAAG5C,OAAO8C,qBAAqB,CAAC,kBAAkB,CAAC;wBAClHxD,EAAAA,yBAAAA,WAAWW,UAAU,qBAArBX,uBAAuByD,cAAc,IAAG,CAAC,MAAM,EAAErD,KAAKJ,WAAWW,UAAU,CAAC8C,cAAc,GAAG,GAAG;wBAChGzD,EAAAA,0BAAAA,WAAWW,UAAU,qBAArBX,wBAAuB0D,aAAa,IAAG,CAAC,KAAK,EAAEtD,KAAKJ,WAAWW,UAAU,CAAC+C,aAAa,GAAG,GAAG;qBAC9F,CACE7D,MAAM,CAACC,SACPpB,IAAI,CAAC,SACR;oBACHgC,OAAOiD,QAAQ,CAACpF,MAAM,iBACrB,KAAChI;wBAAI4F,IAAI;4BAAEe,IAAI;wBAAI;kCAChBwD,OAAOiD,QAAQ,CAACnB,GAAG,CAAC,CAAChG,oBACpB,KAACT;gCAAsBS,KAAKA;+BAAVA;yBAGpB;;;0BAEN,KAACmC;gBAAKrC,OAAM;0BACTsE,UAAUrC,MAAM,iBACf,KAACpH;oBAAMyG,SAAS;8BACbgD,UAAU4B,GAAG,CAAC,CAAC,CAACoB,KAAKC,SAAS,iBAC7B,MAACtN;;8CACC,KAACc;oCAAW4E,SAAQ;oCAAQE,IAAI;wCAAE2B,YAAY;oCAAI;8CAC/ChG,iBAAiBmI,SAAS6D,KAAK,EAAE3C,OAAOyC;;8CAE3C,KAACvM;oCAAW4E,SAAQ;oCAAUkB,OAAM;oCAAiBjB,WAAU;8CAC5D;wCACC2H,SAASE,MAAM,KAAK,OAAQF,SAASG,MAAM,GAAG,qBAAqB,aAAc;wCACjFH,SAASI,YAAY,GAAG,CAAC,aAAa,EAAE/D,WAAW2D,SAASI,YAAY,GAAG,GAAG;wCAC9EJ,SAASK,WAAW,GAAG9D,KAAKyD,SAASK,WAAW,IAAI;wCACpDL,SAASM,KAAK,GAAG,CAAC,MAAM,EAAEN,SAASM,KAAK,EAAE,GAAG;qCAC9C,CACEtE,MAAM,CAACC,SACPpB,IAAI,CAAC;;gCAETmF,SAASO,OAAO,KAAKC,0BACpB,KAAChN;oCAAW4E,SAAQ;8CAAS,CAAC,SAAS,EAAE4H,SAASO,OAAO,EAAE;qCACzD;gCACHP,SAASS,IAAI,KAAKD,0BACjB,KAAChN;oCACC4E,SAAQ;oCACRE,IAAI;wCAAE6B,YAAY;wCAAYd,IAAI;wCAAKqF,IAAI;wCAAKgC,YAAY;wCAAGC,aAAa;oCAAU;8CAErFX,SAASS,IAAI;qCAEd;gCACHT,SAASY,MAAM,iBACd,KAACpN;oCAAW4E,SAAQ;oCAAUkB,OAAM;oCAAiBjB,WAAU;oCAAMC,IAAI;wCAAE6B,YAAY;wCAAYd,IAAI;oCAAI;8CACxG,CAAC,QAAQ,EAAE2G,SAASY,MAAM,EAAE;qCAE7B;;2BA7BIb;qBAkCd;;0BAGJ,KAACjF;gBAAKrC,OAAOvC,2BAA2BiC,MAAMhC,OAAO,IAAI,kBAAkB;0BACxEsH,QAAQ/C,MAAM,iBACb,MAACpH;oBAAMyG,SAAS;;wBACb0D,QAAQkB,GAAG,CAAC,CAACkC;gCAI+B1I;iDAH3C,MAAC2I;;oCACE5K,2BAA2BiC,MAAMhC,OAAO,kBACvC,KAAClD;wCACCyF,MAAMrC,uBAAuBwK,SAAQ1I,iBAAAA,MAAMhC,OAAO,qBAAbgC,eAAe4G,KAAK;wCACzDnG,QAAO;wCACPC,KAAI;wCACJC,WAAU;kDAET+H;uDAGH,KAACnO;wCAAI2F,WAAU;wCAAOC,IAAI;4CAAEE,WAAW;wCAAY;kDAChDqI;;oCAGJA,WAAW1E,WAAWxB,aAAa,GAAG,eAAe;;+BAf7CkG;;wBAkBZ1E,WAAW4E,aAAa,iBACvB,KAACvN;4BAAW4E,SAAQ;4BAAUkB,OAAM;sCAAkB,CAAC,YAAY,EAAE6C,WAAW4E,aAAa,CAAC,CAAC,CAAC;6BAC9F;wBACH5E,WAAW6E,UAAU,CAACtG,MAAM,iBAC3B,KAAClH;4BAAW4E,SAAQ;4BAAUkB,OAAM;4BAAiBhB,IAAI;gCAAEE,WAAW;4BAAY;sCAC/E,CAAC,mCAAmC,EAAE2D,WAAW6E,UAAU,CAACnG,IAAI,CAAC,MAAM;6BAExE;;qBAGN;;0BAGJ,KAACC;gBAAKrC,OAAM;0BACT0D,WAAW8E,UAAU,GAClB,GAAGxM,kBAAkB0H,YAAY,GAAG,EAAEI,KAAKJ,WAAW+E,WAAW,IAAI/E,WAAWgF,YAAY,GAAG,CAAC,MAAM,EAAE9E,WAAWF,WAAWgF,YAAY,GAAG,GAAG,IAAI,GACpJ;;0BAEN,KAACrG;gBAAKrC,OAAM;0BAAqB,GAAG8D,KAAKJ,WAAWoC,WAAW,EAAE,GAAG,EAAEhC,KAAKJ,WAAWiF,WAAW,GAAG;;0BACpG,KAACtG;gBAAKrC,OAAM;0BACV,cAAA,MAACnF;oBAAMsG,WAAU;oBAAMG,SAAS;oBAAKzB,IAAI;wBAAEU,YAAY;oBAAS;;sCAC9D,KAACxF;4BAAW4E,SAAQ;4BAAQE,IAAI;gCAAE+I,YAAY;gCAAa7I,WAAW;4BAAY;sCAC/E2D,WAAW1G,EAAE;;sCAEhB,KAAClC;4BAAQ2G,OAAM;sCACb,cAAA,KAAClH;gCAAWsO,MAAK;gCAAQC,cAAW;gCAAyBC,SAAS7D;0CACpE,cAAA,KAACxL;oCAAQqH,MAAMrI,eAAeqI,IAAI;oCAAEC,UAAS;;;;;;;;;AAO3D;AAEA,OAAO,SAASgI,yBAAyBtJ,KAAoC;QA6BzEA,uCAsFagE,OAAAA;QAtGmBA,yBA6EmBC,iBAKnDA;IA9FF,MAAM,EAAEsF,KAAK,EAAEC,WAAW,EAAEC,UAAU,EAAEC,YAAY,EAAElM,QAAQ,EAAE,GAAGwC;IACnE,MAAM2J,MAAM5M,eAAewM;IAC3B,MAAMK,iBAAiB5M,oBAAoBuM,OAAOE;IAClD,MAAMI,SAAS5M,sBAAsBsM,OAAOG;IAC5C,MAAMI,UAAU3M,6BAA6BoM,OAAOG;IACpD,MAAMjG,UAAUvG,6BAA6ByM,KAAKD;IAClD,MAAMK,SAAS1P,oBAAoBkP,OAAO;QAAES,SAAS;IAAK;IAC1D,MAAM,CAACC,aAAaC,eAAe,GAAG1O,SAAS;IAC/C,MAAM2O,QAAQtN;IACd,MAAMmH,aAAa6F,OAAOO,IAAI;IAC9B,MAAMnG,WAAW2F,eAAeQ,IAAI;IACpC,MAAMC,YAAYjQ,uBAAuB,YAAYmP,OAAO;QAC1DS,SAASC,eAAenG,QAAQE,+BAAAA,0BAAAA,WAAY8C,WAAW,qBAAvB9C,wBAAyBzB,MAAM;IACjE;IACA,MAAMuF,QAAQvM,QAAQ;;uBAAM0I,4BAAAA,SAAU6D,KAAK,mBAAI,EAAE;OAAE;QAAC7D;KAAS;IAC7D,MAAMqG,UAAUnO,6BAA6B;QAAEwN;QAAK7B;IAAM;IAE1D,MAAM5D,aAAa5I,YACjB,CAACoL;;YAAgBqD;wBAAAA,uBAAAA,OAAOQ,OAAO,CAAC3M,IAAI,CAAC,CAAC4M,SAAWA,OAAO9D,GAAG,KAAKA,yBAA/CqD,qBAAqDzJ,KAAK,mBAAI;OAC/E;QAACyJ,OAAOQ,OAAO;KAAC;IAElB,MAAMxD,eAAezL,YACnB,CAACgC;;YAAe+M;wBAAAA,0BAAAA,UAAUE,OAAO,CAAC3M,IAAI,CAAC,CAAC4M,SAAWA,OAAOC,KAAK,KAAKnN,wBAApD+M,wBAAyD/J,KAAK,mBAAIhD;OAClF;QAAC+M,UAAUE,OAAO;KAAC;IAGrB,MAAMG,kBAAkB,GAAGlB,YAAY,CAAC,EAAEC,WAAW,YAAY,CAAC;IAClE,MAAMzL,WACJgC,kCAAAA,MAAM2K,SAAS,CAACA,SAAS,CAAC/M,IAAI,CAAC,CAACC,QAAUA,MAAMP,EAAE,KAAM0G,CAAAA,CAAAA,8BAAAA,WAAY6C,SAAS,MAAI5C,4BAAAA,SAAU4C,SAAS,CAAD,cAAnG7G,kCAA0G;IAC5G,MAAMkC,mBAAWlE,2BAAAA,QAAS4M,QAAQ,mBAAI;IACtC,MAAMxG,OAAO,CAACC,KAAkC9H,mBAAmB8H,IAAInC;IACvE,MAAM2I,WAAWtP,QACf;;YAQiBkI,qBAAAA;eAPfO,aACInI,2BAA2B;YACzBmI;YACA8D;YACAgC,SAASA,QAAQ3G,MAAM,KAAK,UAAU2G,QAAQM,IAAI,GAAG;YACrDlG;YACA4G,YAAY,CAACzG,KAAO9H,mBAAmB8H,IAAInC;YAC3CuB,OAAO,WAAEA,gBAAAA,QAAQ2G,IAAI,sBAAZ3G,sBAAAA,cAAcR,KAAK,qBAAnBQ,oBAAqBA,OAAO,mBAAI;QAC3C,KACA,EAAE;OACR;QAACO;QAAY8D;QAAOgC;QAAS5F;QAAYhC;QAAUuB,QAAQ2G,IAAI;KAAC;IAGlE,MAAMW,qBACJ,KAACvQ,qBAEM;QAAE0F,WAAWpG;QAASiM,kBAAkB;QAASiF,cAAc;IAAM;QAC1EzK,MAAMmK;QACNvB,MAAK;QACLhI,OAAM;kBACP;;IAKH,IAAI0I,OAAO1G,MAAM,KAAK,aAAayG,eAAezG,MAAM,KAAK,WAAW;QACtE,qBAAO,KAAC1G;YAAgB6D,OAAM;;IAChC;IACA,IAAIuJ,OAAO1G,MAAM,KAAK,WAAW0G,OAAO1G,MAAM,KAAK,WAAW;QAC5D,qBAAO,KAACzG;YAAoByG,QAAQ0G,OAAO1G,MAAM;YAAE8H,MAAK;;IAC1D;IACA,IAAIrB,eAAezG,MAAM,KAAK,WAAWyG,eAAezG,MAAM,KAAK,WAAW;QAC5E,qBAAO,KAACzG;YAAoByG,QAAQyG,eAAezG,MAAM;YAAE8H,MAAK;;IAClE;IACA,qEAAqE;IACrE,IAAI,CAACjH,cAAc,CAACC,YAAYD,WAAWyF,UAAU,KAAKA,YAAY;QACpE,qBACE,KAAChP;YAAKwF,SAAQ;sBACZ,cAAA,KAAChG;gBACCqG,OAAM;gBACN4K,aAAY;gBACZC,QAAQJ;;;IAIhB;IAEA,MAAMK,OAAOpH,WAAWqH,WAAW,IAAIrH,WAAW4C,KAAK;IACvD,MAAMvJ,OAAO2G,WAAWvD,MAAM,KAAK,SAAS,SAAS;IACrD,MAAM6K,aAAalO,sBACjBC,MACAA,SAAS,SAAS2G,WAAWO,MAAM,GAAGP,WAAWS,SAAS,EAC1DT,WAAWzG,MAAM,EACjBC;IAEF,MAAM+N,UAAU3P,0BAA0BoI;IAC1C,MAAMwH,cAAcvH,SAASwH,QAAQ,CAACD,WAAW,IAAIvH,EAAAA,kBAAAA,SAASyH,KAAK,qBAAdzH,gBAAgB0H,YAAY,MAAK;IACtF,0EAA0E;IAC1E,sEAAsE;IACtE,MAAMC,aACJ3H,SAASwH,QAAQ,CAACG,UAAU,IAC5B3H,EAAAA,mBAAAA,SAASyH,KAAK,qBAAdzH,iBAAgB4H,WAAW,MAAK,QAChCN,QAAQO,KAAK,GAAG,KAChBP,QAAQQ,YAAY,GAAG;IACzB,MAAMhN,OAAOiF,WAAWb,MAAM,KAAK,YAAYa,WAAWb,MAAM,KAAK;IACrE,MAAM9D,OAAO2E,WAAWb,MAAM,KAAK,YAAYa,WAAW8E,UAAU,KAAK;IAEzE;;;;GAIC,GACD,MAAMkD,YAAY9P,6BAA6B8H,YAAY8D;IAC3D,MAAMtG,UAA8CwK,UAAUC,QAAQ,CAAC,YACnE,WACAD,UAAUC,QAAQ,CAAC,YACjB,WACA;IACN,MAAMC,OAAO5B,QAAQ6B,SAAS,CAACnI,YAAY,CAACmH,SAAWA,WAAW3J;IAClE,MAAM4K,OAAO,CAAC3B,QAAmBA,QAAQA,MAAM4B,cAAc,KAAK;IAClE,MAAMC,aAAa,CAACd,eAAe,CAACD,QAAQ7G,MAAM,IAAI,CAAC6G,QAAQgB,aAAa,GAAG,gBAAgBlE;IAC/F,MAAMK,UAAS1E,SAAAA,4BAAAA,WAAWxB,aAAa,YAAxBwB,4BAA4BA,WAAWuB,cAAc,CAACiH,EAAE,CAAC,CAAC,cAA1DxI,QAAgE;IAC/E,MAAMyI,WAAW/Q,sBAAsB;QACrCsI;QACAC;QACAjG,SAASgC,MAAM2K,SAAS,CAACxH,MAAM,KAAK,UAAUnF,UAAUqK;QACxD8B;IACF;IACA,MAAMuC,aACJ1I,WAAWb,MAAM,KAAK,YAAYa,WAAW2I,WAAW,GACpDF,SAASpP,IAAI,KAAK,WAChB,CAAC,mBAAmB,EAAE2G,WAAW4I,SAAS,GAAG,EAAE,2BAA2B,CAAC,GAC3E,CAAC,mBAAmB,EAAE5I,WAAW4I,SAAS,GAAG,EAAE,OAAO,EAAExI,KAAKJ,WAAW2I,WAAW,EAAE,CAAC,CAAC,GACzF;IAEN,qBACE,MAACxR;QAAMyG,SAAS;;0BAEd,KAACvJ;gBAAiB0J,OAAOqJ;;0BACzB,KAACrR;gBACC8S,QAAO;gBACPC,yBACE;;wBACG9I,WAAWqH,WAAW,GAAG,GAAGrH,WAAW4C,KAAK,CAAC,GAAG,CAAC,GAAG;wBACpD,CAAC,GAAG,EAAE3C,SAASmH,IAAI,IAAI,YAAY;;;gBAGxC2B,MAAMzU,eAAe,aAAa;oBAAE0U,QAAQ;gBAAkB;gBAC9DC,cAAc;gBACdC,cAAc;gBACdC,aAAa;oBACXhC,sBACE,MAAChQ;wBAAMsG,WAAU;wBAAMG,SAAS;wBAAGzB,IAAI;4BAAEU,YAAY;4BAAUuM,UAAU;4BAAQlH,QAAQ;wBAAE;;4BACxF6E;4BACAvJ,wBACC,KAAChH;gCACCyF,SAAQ;gCACRkJ,MAAK;gCACLkE,UAAU/C,QAAQgD,IAAI,KAAKtJ,WAAW1G,EAAE;gCACxC+L,SAAS,IAAMiB,QAAQiD,MAAM,CAACvJ,YAAYxC;0CAEzCnC,OAAO,oBAAoBpD,iCAAiC,CAACuF,QAAQ;iCAEtE;4BACH0K,KAAK3J,MAAM,iBAAG,KAACrI;gCAAeoG,OAAO8K;gCAAMoC,OAAOtB;iCAAW;;;gBAGpE;0BAEA,cAAA,MAAC/Q;oBAAMyG,SAAS;;sCACd,MAACzG;4BAAMsG,WAAU;4BAAMG,SAAS;4BAAGzB,IAAI;gCAAEU,YAAY;gCAAUuM,UAAU;gCAAQlH,QAAQ;4BAAE;;8CACzF,KAAC9K;oCACCqS,aAAa;oCACb1L,OAAOuJ,aAAa,CAAC,SAAS,EAAEjO,KAAK,WAAW,CAAC,GAAG,CAAC,IAAI,EAAEA,KAAK,yBAAyB,CAAC;8CAE1F,cAAA,KAAC3C;wCACCyO,MAAK;wCACLlJ,SAAQ;wCACRkB,OAAOmK,aAAa,YAAY;wCAChCoC,oBAAM,KAAC1T;4CAAQqH,MAAM5I,kBAAkB4I,IAAI;4CAAEC,UAAS;;wCACtDhB,OAAOjD,SAAS,SAAS,SAAS;uCAC7BiO,aACA;wCAAEpL,WAAWpG;wCAASyG,MAAM+K;wCAAYqC,WAAW;wCAAM5H,kBAAkB;oCAAQ,IACpF,CAAC;;8CAGT,KAACvJ;oCAA6B2G,QAAQa,WAAWb,MAAM;;8CACvD,KAACzI;oCAAKyO,MAAK;oCAAQlJ,SAAQ;oCAAWK,OAAOlE,yBAAyB4H,YAAY8D;;gCACjFzL,sBAAsB2H,4BACrB,KAACtJ;oCAAKyO,MAAK;oCAAQlJ,SAAQ;oCAAWkB,OAAM;oCAAUb,OAAM;qCAC1D;gCACHvB,QAAQiF,WAAW2I,WAAW,GAC7BF,SAASpP,IAAI,KAAK,yBAChB,KAACjC;oCAAQqS,aAAa;oCAAC1L,OAAOpF,uBAAuB8P,UAAUvK;8CAC7D,cAAA,KAACxH;wCACCyO,MAAK;wCACLlJ,SAAQ;wCACRkB,OACEsL,SAASmB,MAAM,KAAK,yBAAyBnB,SAASmB,MAAM,KAAK,wBAC7D,YACA;wCAENtN,OAAO,CAAC,UAAU,EAAE1D,sBAAsB6P,UAAUvK,WAAW;;mDAInE,KAACxH;oCAAKyO,MAAK;oCAAQlJ,SAAQ;oCAAWK,OAAO,CAAC,UAAU,EAAE8D,KAAKJ,WAAW2I,WAAW,GAAG;qCAExF;;;wBAELtN,qBACC,KAAC/E;4BAAMuT,UAAS;sCACb7J,WAAW8J,UAAU,IACpB;6BAEF;wBACHvC,QAAQwC,QAAQ,iBACf,MAAC5S;4BAAMsG,WAAU;4BAAMG,SAAS;4BAAGzB,IAAI;gCAAEiN,UAAU;gCAAQlH,QAAQ;4BAAE;4BAAG8H,MAAK;4BAAQ5E,cAAW;;8CAC9F,KAACtM;oCAAewD,OAAM;oCAAcmK,OAAO2B,KAAKb,QAAQ0C,UAAU;;gCACjErC,2BACC,KAAC9O;oCACCwD,OAAM;oCACNmK,OAAO2B,KAAKb,QAAQO,KAAK;oCACzBoC,MAAM3C,QAAQQ,YAAY,GAAG,GAAGR,QAAQQ,YAAY,CAACM,cAAc,GAAG,yBAAyB,CAAC,GAAGhE;qCAEnG;8CACJ,KAACvL;oCAAewD,OAAM;oCAASmK,OAAO2B,KAAKb,QAAQ7G,MAAM;oCAAGwJ,MAAM5B;;8CAClE,KAACxP;oCACCwD,OAAM;oCACNmK,OACEc,QAAQ4C,aAAa,CAACC,KAAK,GACvB,GAAG7C,QAAQ4C,aAAa,CAACC,KAAK,GAAG7C,QAAQ4C,aAAa,CAACE,OAAO,GAAG,MAAM,IAAI,GAC3E;oCAENH,IAAI,EACF5B,qBAAAA,aACCf,QAAQ4C,aAAa,CAACE,OAAO,IAAI9C,QAAQ4C,aAAa,CAACC,KAAK,GACzD,2CACA/F;;8CAGR,KAACvL;oCAAewD,OAAM;oCAAiBmK,OAAO2B,KAAKb,QAAQgB,aAAa;oCAAG2B,IAAI,EAAE5B,qBAAAA,aAAc;;8CAC/F,KAACxP;oCAAewD,OAAM;oCAAUmK,OAAO2B,KAAKb,QAAQ+C,OAAO;;;2CAG7D,KAACjT;4BAAW4E,SAAQ;4BAAQkB,OAAM;sCAC/BuL;;;;;0BAMT,KAAC3S;gBACC8S,QAAO;gBACPC,WAAU;gBACVC,MAAMzU,eAAe,aAAa;oBAAE0U,QAAQ;gBAAkB;gBAC9DC,cAAc;gBACdC,cAAc;gBACdC,aACEzE,UAAU3K,2BAA2BC,WACjC;oBACEmN,sBACE,KAAC3Q;wBACC2O,MAAK;wBACL5I,MAAMrC,uBAAuBwK,QAAQ1K,2BAAAA,QAAS4I,KAAK;wBACnDnG,QAAO;wBACPC,KAAI;kCACL;;gBAIL,IACA2H;0BAGN,cAAA,MAAClN;oBAAMyG,SAAS;;wBACbkI,QAAQ3G,MAAM,KAAK,0BAAY,KAAC1G;4BAAgB6D,OAAM;6BAA8B;wBACpFwJ,QAAQ3G,MAAM,KAAK,WAAW2G,QAAQ3G,MAAM,KAAK,0BAChD,KAACzG;4BACCyG,QAAQ2G,QAAQ3G,MAAM;4BACtB8H,MAAK;4BACL,iEAAiE;4BACjE,6DAA6D;4BAC7DsD,SACEzE,QAAQ3G,MAAM,KAAK,YACf,sFACA;6BAGN;sCACJ,KAACpI;4BAAKyT,cAAc;4BAACpF,cAAW;sCAC7ByB,SAASrE,GAAG,CAAC,CAAC3I,OAAO4Q;;qDACpB,KAAC7N;oCAEC/C,OAAOA;oCACPqE,UAAUA;oCACV9D,YAAY,UAAEJ,2BAAAA,QAAS4I,KAAK,mBAAI;oCAChCnE,oBAAoB1E,2BAA2BC;oCAC/C8C,SAAS2N,QAAQ5D,SAAStI,MAAM,GAAG;mCAL9B1E,MAAM+J,GAAG;;;;;;0BAYxB,KAAC7N;gBACC8S,QAAO;gBACPE,MAAMzU,eAAe,aAAa;oBAAE0U,QAAQ;gBAAkB;gBAC9DC,cAAc;gBACdE,aAAa;oBACXhC,sBACE,KAAC3Q;wBACC2O,MAAK;wBACLuF,iBAAezE;wBACf0E,iBAAc;wBACdC,uBAAS,KAAC5U;4BAAQqH,MAAM,AAAC4I,CAAAA,cAAcnR,eAAeD,cAAa,EAAGwI,IAAI;4BAAEC,UAAS;;wBACrF+H,SAAS,IAAMa,eAAe,CAAC2E,MAAQ,CAACA;kCAEvC5E,cAAc,SAAS;;gBAG9B;0BAEA,cAAA,KAACtP;oBAASmU,IAAI7E;oBAAa8E,aAAa;8BACtC,cAAA,MAACxU;wBAAI+C,IAAG;wBAA8B6C,IAAI;4BAAE6O,IAAI;wBAAE;;0CAChD,KAACpU;gCAAQuF,IAAI;oCAAE8O,IAAI;gCAAE;;0CACrB,KAAClL;gCACCC,YAAYA;gCACZC,UAAUA;gCACVjG,SAASA;gCACTyF,SAASA,QAAQN,MAAM,KAAK,UAAUM,QAAQ2G,IAAI,GAAG;gCACrDpD,eACEvD,QAAQN,MAAM,KAAK,YACf,mBACAM,QAAQN,MAAM,KAAK,YACjB,gCACA;gCAER4D,cAAcA;gCACd7C,YAAYA;gCACZ1G,UAAUA;gCACV0E,UAAUA;;;;;;YAMjBoI,QAAQ4E,OAAO;;;AAGtB;AACA5F,yBAAyB6F,WAAW,GAAG;AAEvC,eAAe7F,yBAAwB"}
@@ -7,9 +7,9 @@ export interface MailboxCardProps {
7
7
  /** The viewer may change, pause and disconnect it: its member, or an org owner or admin. */
8
8
  canManage: boolean;
9
9
  api: OutreachMailboxApi;
10
- /** Starts a new Google connect, for a mailbox that needs reconnecting. */
10
+ /** Starts a new connect with the mailbox's provider, for a mailbox that needs reconnecting. */
11
11
  onReconnect(): void;
12
- /** True while that connect is on its way to Google. */
12
+ /** True while that connect is on its way to the provider. */
13
13
  reconnecting?: boolean;
14
14
  /** The clock the health window and today's limit are read on. */
15
15
  nowMs?: number;
@@ -41,7 +41,7 @@ export declare const MAILBOX_ACTION_LABELS: {
41
41
  * Every control is offered only where the route will allow it: the settings
42
42
  * form and pause and disconnect to the member who connected the mailbox or an
43
43
  * org owner or admin, and the test and the reconnect to its member alone,
44
- * because both act in that member's own Google account.
44
+ * because both act in that member's own Google or Microsoft account.
45
45
  */
46
46
  export declare function MailboxCard(props: MailboxCardProps): import("react").JSX.Element;
47
47
  export declare namespace MailboxCard {
@@ -108,19 +108,21 @@ const draftOf = (mailbox)=>{
108
108
  * Every control is offered only where the route will allow it: the settings
109
109
  * form and pause and disconnect to the member who connected the mailbox or an
110
110
  * org owner or admin, and the test and the reconnect to its member alone,
111
- * because both act in that member's own Google account.
111
+ * because both act in that member's own Google or Microsoft account.
112
112
  */ export function MailboxCard(props) {
113
113
  var _mailbox_rampStartedAtMs, _OUTREACH_MAILBOX_STATUS_LABELS_mailbox_status, _STATUS_COLOR_mailbox_status;
114
114
  var _mailbox_health_daily_outreachLocalDay, _mailbox_health_daily, _mailbox_health, _mailbox_sendAsOptions;
115
115
  const { mailbox, isMine, canManage, api, onReconnect, reconnecting = false, nowMs = Date.now() } = props;
116
116
  const { enqueueSnackbar } = useSnackbar();
117
117
  const { confirm } = useConfirmationContext();
118
+ const microsoft = mailbox.provider === 'microsoft';
119
+ const providerName = microsoft ? 'Microsoft' : 'Google';
118
120
  const [draft, setDraft] = useState(()=>draftOf(mailbox));
119
121
  const [saving, setSaving] = useState(false);
120
122
  const [saveError, setSaveError] = useState(null);
121
123
  const [busy, setBusy] = useState(null);
122
124
  // Where a test goes when not to the member themself (AGL-3228): a test to
123
- // one's own address never leaves Google and shows no authentication result.
125
+ // one's own address never leaves the provider and shows no authentication result.
124
126
  const [testAddress, setTestAddress] = useState('');
125
127
  /*
126
128
  * SPF, DKIM and DMARC for the address this mailbox sends as (AGL-3328),
@@ -257,7 +259,7 @@ const draftOf = (mailbox)=>{
257
259
  const disconnect = async ()=>{
258
260
  const confirmed = await confirm({
259
261
  title: 'Disconnect this mailbox?',
260
- description: 'Disconnecting deletes the access stored for this mailbox and asks Google to revoke it. ' + 'Nothing is sent from it again unless it is connected again.',
262
+ description: (microsoft ? 'Disconnecting deletes the access stored for this mailbox. ' : 'Disconnecting deletes the access stored for this mailbox and asks Google to revoke it. ') + 'Nothing is sent from it again unless it is connected again.',
261
263
  confirmationText: MAILBOX_ACTION_LABELS.disconnect,
262
264
  confirmationButtonProps: {
263
265
  color: 'error'
@@ -272,6 +274,10 @@ const draftOf = (mailbox)=>{
272
274
  variant: 'warning',
273
275
  persist: true
274
276
  });
277
+ } else if (revocation === 'unsupported') {
278
+ enqueueSnackbar('Mailbox disconnected. To end the access at Microsoft too, remove the app at myapps.microsoft.com.', {
279
+ variant: 'success'
280
+ });
275
281
  } else if (revocation === 'kept-for-other-mailbox') {
276
282
  enqueueSnackbar('Mailbox disconnected. Google access stays in place for another connected mailbox on the same account.', {
277
283
  variant: 'success'
@@ -321,7 +327,7 @@ const draftOf = (mailbox)=>{
321
327
  onClick: onReconnect,
322
328
  children: MAILBOX_ACTION_LABELS.reconnect
323
329
  }) : undefined,
324
- children: `${mailbox.status === 'disconnected' ? 'This mailbox was disconnected.' : 'Google stopped accepting this mailbox’s connection.'} ${isMine ? 'Nothing sends from it until you connect it again.' : 'Only the member who connected it can reconnect it.'}`
330
+ children: `${mailbox.status === 'disconnected' ? 'This mailbox was disconnected.' : `${providerName} stopped accepting this mailbox’s connection.`} ${isMine ? 'Nothing sends from it until you connect it again.' : 'Only the member who connected it can reconnect it.'}`
325
331
  }) : null,
326
332
  mailbox.status === 'paused' && mailbox.autoPause ? /*#__PURE__*/ _jsx(Alert, {
327
333
  severity: "error",
@@ -407,7 +413,7 @@ const draftOf = (mailbox)=>{
407
413
  }) : readiness ? /*#__PURE__*/ _jsx(Typography, {
408
414
  variant: "caption",
409
415
  color: "text.secondary",
410
- children: `Google authenticates mail from ${readiness.sendAs.slice(readiness.sendAs.lastIndexOf('@') + 1)} ` + 'itself, so there are no records to publish for this address.'
416
+ children: `${providerName} authenticates mail from ${readiness.sendAs.slice(readiness.sendAs.lastIndexOf('@') + 1)} ` + 'itself, so there are no records to publish for this address.'
411
417
  }) : null,
412
418
  canManage ? /*#__PURE__*/ _jsxs(Stack, {
413
419
  spacing: 2,