@aglyn/plugins-outreach 1.0.0-beta.217 → 1.0.0-beta.219

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 (72) hide show
  1. package/package.json +14 -14
  2. package/src/lib/components/compliance-section.js +72 -34
  3. package/src/lib/components/compliance-section.js.map +1 -1
  4. package/src/lib/components/enroll-dialog.d.ts +12 -2
  5. package/src/lib/components/enroll-dialog.js +72 -18
  6. package/src/lib/components/enroll-dialog.js.map +1 -1
  7. package/src/lib/components/enrollment-detail.d.ts +5 -1
  8. package/src/lib/components/enrollment-detail.js +12 -6
  9. package/src/lib/components/enrollment-detail.js.map +1 -1
  10. package/src/lib/components/outreach-console-sections.d.ts +1 -1
  11. package/src/lib/components/outreach-console-sections.js +1 -1
  12. package/src/lib/components/outreach-console-sections.js.map +1 -1
  13. package/src/lib/components/sequence-editor.js +85 -40
  14. package/src/lib/components/sequence-editor.js.map +1 -1
  15. package/src/lib/components/use-outreach-api.d.ts +2 -1
  16. package/src/lib/components/use-outreach-api.js +5 -3
  17. package/src/lib/components/use-outreach-api.js.map +1 -1
  18. package/src/lib/engine/compose.d.ts +1 -1
  19. package/src/lib/engine/compose.js +8 -4
  20. package/src/lib/engine/compose.js.map +1 -1
  21. package/src/lib/engine/enrollment-activity.d.ts +9 -1
  22. package/src/lib/engine/enrollment-activity.js +15 -2
  23. package/src/lib/engine/enrollment-activity.js.map +1 -1
  24. package/src/lib/engine/enrollment-state.d.ts +33 -2
  25. package/src/lib/engine/enrollment-state.js +66 -7
  26. package/src/lib/engine/enrollment-state.js.map +1 -1
  27. package/src/lib/engine/sending-capacity.d.ts +1 -1
  28. package/src/lib/engine/sending-capacity.js +1 -1
  29. package/src/lib/engine/sending-capacity.js.map +1 -1
  30. package/src/lib/engine/sequence-validation.d.ts +20 -3
  31. package/src/lib/engine/sequence-validation.js +30 -4
  32. package/src/lib/engine/sequence-validation.js.map +1 -1
  33. package/src/lib/enrollment/enroll-people.js +6 -4
  34. package/src/lib/enrollment/enroll-people.js.map +1 -1
  35. package/src/lib/enrollment/step-overrides.d.ts +4 -2
  36. package/src/lib/enrollment/step-overrides.js +11 -4
  37. package/src/lib/enrollment/step-overrides.js.map +1 -1
  38. package/src/lib/mailboxes/mailbox-api.d.ts +5 -1
  39. package/src/lib/mailboxes/mailbox-api.js.map +1 -1
  40. package/src/lib/mailboxes/mailbox-routes.d.ts +5 -2
  41. package/src/lib/mailboxes/mailbox-routes.js +10 -7
  42. package/src/lib/mailboxes/mailbox-routes.js.map +1 -1
  43. package/src/lib/mailboxes/mailbox-settings.d.ts +2 -2
  44. package/src/lib/mailboxes/mailbox-settings.js +1 -1
  45. package/src/lib/mailboxes/mailbox-settings.js.map +1 -1
  46. package/src/lib/model/enrollment-timeline.d.ts +1 -1
  47. package/src/lib/model/enrollment-timeline.js +22 -3
  48. package/src/lib/model/enrollment-timeline.js.map +1 -1
  49. package/src/lib/model/outreach-api.d.ts +19 -1
  50. package/src/lib/model/outreach-api.js.map +1 -1
  51. package/src/lib/model/outreach.types.d.ts +25 -0
  52. package/src/lib/model/outreach.types.js.map +1 -1
  53. package/src/lib/model/step-preview.d.ts +2 -0
  54. package/src/lib/model/step-preview.js +11 -7
  55. package/src/lib/model/step-preview.js.map +1 -1
  56. package/src/lib/model/stored-records.js +26 -0
  57. package/src/lib/model/stored-records.js.map +1 -1
  58. package/src/lib/plugin.js +1 -1
  59. package/src/lib/plugin.js.map +1 -1
  60. package/src/lib/routes/enroll-routes.d.ts +6 -0
  61. package/src/lib/routes/enroll-routes.js +21 -6
  62. package/src/lib/routes/enroll-routes.js.map +1 -1
  63. package/src/lib/routes/preview-routes.js +14 -5
  64. package/src/lib/routes/preview-routes.js.map +1 -1
  65. package/src/lib/routes/step-test-routes.js +3 -3
  66. package/src/lib/routes/step-test-routes.js.map +1 -1
  67. package/src/lib/testing/stand-in-crm-record-routes.d.ts +25 -0
  68. package/src/lib/testing/stand-in-crm-record-routes.js +46 -0
  69. package/src/lib/testing/stand-in-crm-record-routes.js.map +1 -0
  70. package/src/lib/transport/gmail-errors.d.ts +27 -0
  71. package/src/lib/transport/gmail-errors.js +56 -0
  72. package/src/lib/transport/gmail-errors.js.map +1 -1
@@ -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 { crmOrgRecordHref, crmRecordHref } from '@aglyn/aglyn/app-utils/console-record-links'\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 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 { useOrgCampaigns, 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/** Where the CRM record the person is lives — the site's own CRM when the site is known. */\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\n return host\n ? crmRecordHref({ orgSlug: orgMount.orgSlug, host }, kind, id)\n : crmOrgRecordHref(orgMount.orgSlug, kind, 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 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 = useOrgCampaigns(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","crmOrgRecordHref","crmRecordHref","mdiAccountCancelOutline","mdiAccountOutline","mdiAccountPlusOutline","mdiAlertCircleOutline","mdiCheckCircleOutline","mdiChevronDown","mdiChevronUp","mdiClipboardCheckOutline","mdiContentCopy","mdiCursorDefaultClickOutline","mdiEmailAlertOutline","mdiEmailOffOutline","mdiEmailOpenOutline","mdiEmailOutline","mdiHandBackLeftOutline","mdiPauseCircleOutline","mdiPencilOutline","mdiPlayCircleOutline","mdiReply","mdiShieldSearch","mdiStopCircleOutline","AppLink","CardDisplay","MdiIcon","EmptyStateComponent","RowActionsMenu","useSnackbar","useOrgCampaigns","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","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 { useOrgCampaigns, 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 = useOrgCampaigns(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","useOrgCampaigns","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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"}
@@ -22,7 +22,7 @@ export type OutreachConsoleSectionId = 'sequences' | 'mailboxes' | 'compliance';
22
22
  * Read twice and never copied, the CRM's rule: `plugin.ts` registers the list
23
23
  * on the org nav item so the shell routes and gates each section, and the hub
24
24
  * page switches its body on the id the shell resolves back. The console's
25
- * `PLUGIN_SECTIONS` title table keeps a checked copy for its server layout.
25
+ * generated titles manifest compiles a copy for its server layout.
26
26
  *
27
27
  * Ids are persisted vocabulary — `/[orgSlug]/outreach/sequences` is a link
28
28
  * people keep, and the surface slug stays `outreach` for the same reason the
@@ -19,7 +19,7 @@
19
19
  * Read twice and never copied, the CRM's rule: `plugin.ts` registers the list
20
20
  * on the org nav item so the shell routes and gates each section, and the hub
21
21
  * page switches its body on the id the shell resolves back. The console's
22
- * `PLUGIN_SECTIONS` title table keeps a checked copy for its server layout.
22
+ * generated titles manifest compiles a copy for its server layout.
23
23
  *
24
24
  * Ids are persisted vocabulary — `/[orgSlug]/outreach/sequences` is a link
25
25
  * people keep, and the surface slug stays `outreach` for the same reason the
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/outreach-console-sections.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ConsoleNavSection } from '@aglyn/aglyn'\n\nexport type OutreachConsoleSectionId = 'sequences' | 'mailboxes' | 'compliance'\n\n/**\n * The Sequences hub's sections, in rail order (AGL-2974).\n *\n * Read twice and never copied, the CRM's rule: `plugin.ts` registers the list\n * on the org nav item so the shell routes and gates each section, and the hub\n * page switches its body on the id the shell resolves back. The console's\n * `PLUGIN_SECTIONS` title table keeps a checked copy for its server layout.\n *\n * Ids are persisted vocabulary — `/[orgSlug]/outreach/sequences` is a link\n * people keep, and the surface slug stays `outreach` for the same reason the\n * plugin id does (AGL-3199). The sequence list is first because it is where\n * the work is, and so it is where a bare `/outreach` lands.\n *\n * Its LABEL is \"All sequences\" rather than \"Sequences\", because the hub is\n * called Sequences and the shell prints the two together — in the tab title,\n * the page header and the breadcrumb. A section named after its surface says\n * one word twice and tells the reader nothing;\n * `plugin-section-tab-titles.spec.ts` refuses it.\n *\n * Every section inherits the nav item's `release_outreach` gate and the\n * extension's `features.outreach` entitlement and `outreach.use` permission;\n * a section that later needs a narrower one declares it, which can only\n * narrow.\n */\nexport const OUTREACH_CONSOLE_SECTIONS: readonly ConsoleNavSection[] = [\n { id: 'sequences', label: 'All sequences' },\n { id: 'mailboxes', label: 'Mailboxes' },\n // The footer's sender identity and the allowed countries (AGL-2980).\n { id: 'compliance', label: 'Compliance' },\n]\n"],"names":["OUTREACH_CONSOLE_SECTIONS","id","label"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAMD;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GACD,OAAO,MAAMA,4BAA0D;IACrE;QAAEC,IAAI;QAAaC,OAAO;IAAgB;IAC1C;QAAED,IAAI;QAAaC,OAAO;IAAY;IACtC,qEAAqE;IACrE;QAAED,IAAI;QAAcC,OAAO;IAAa;CACzC,CAAA"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/outreach-console-sections.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ConsoleNavSection } from '@aglyn/aglyn'\n\nexport type OutreachConsoleSectionId = 'sequences' | 'mailboxes' | 'compliance'\n\n/**\n * The Sequences hub's sections, in rail order (AGL-2974).\n *\n * Read twice and never copied, the CRM's rule: `plugin.ts` registers the list\n * on the org nav item so the shell routes and gates each section, and the hub\n * page switches its body on the id the shell resolves back. The console's\n * generated titles manifest compiles a copy for its server layout.\n *\n * Ids are persisted vocabulary — `/[orgSlug]/outreach/sequences` is a link\n * people keep, and the surface slug stays `outreach` for the same reason the\n * plugin id does (AGL-3199). The sequence list is first because it is where\n * the work is, and so it is where a bare `/outreach` lands.\n *\n * Its LABEL is \"All sequences\" rather than \"Sequences\", because the hub is\n * called Sequences and the shell prints the two together — in the tab title,\n * the page header and the breadcrumb. A section named after its surface says\n * one word twice and tells the reader nothing;\n * `plugin-section-tab-titles.spec.ts` refuses it.\n *\n * Every section inherits the nav item's `release_outreach` gate and the\n * extension's `features.outreach` entitlement and `outreach.use` permission;\n * a section that later needs a narrower one declares it, which can only\n * narrow.\n */\nexport const OUTREACH_CONSOLE_SECTIONS: readonly ConsoleNavSection[] = [\n { id: 'sequences', label: 'All sequences' },\n { id: 'mailboxes', label: 'Mailboxes' },\n // The footer's sender identity and the allowed countries (AGL-2980).\n { id: 'compliance', label: 'Compliance' },\n]\n"],"names":["OUTREACH_CONSOLE_SECTIONS","id","label"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAMD;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GACD,OAAO,MAAMA,4BAA0D;IACrE;QAAEC,IAAI;QAAaC,OAAO;IAAgB;IAC1C;QAAED,IAAI;QAAaC,OAAO;IAAY;IACtC,qEAAqE;IACrE;QAAED,IAAI;QAAcC,OAAO;IAAa;CACzC,CAAA"}
@@ -25,7 +25,7 @@ import CampaignPicker from "@aglyn/shared-ui-email-campaigns/components/campaign
25
25
  import { useSnackbar } from "@aglyn/shared-ui-snackstack";
26
26
  import { useOrgCampaigns, useUser } from "@aglyn/tenant-feature-instance";
27
27
  import { Alert, Autocomplete, Box, Button, Chip, FormControlLabel, Grid, Menu, MenuItem, Stack, Switch, TextField, Typography } from "@mui/material";
28
- import { useEffect, useMemo, useState } from "react";
28
+ import { memo, useCallback, useEffect, useMemo, useState } from "react";
29
29
  import { isInThreadEmailStep, OUTREACH_SEQUENCE_NAME_MAX, validateOutreachSequence } from "../engine/sequence-validation.js";
30
30
  import { outreachCountryLabel } from "../model/compliance-settings.js";
31
31
  import { OUTREACH_MAX_EMAIL_STEPS, OUTREACH_MAX_STEPS, OUTREACH_TASK_KIND_LABELS, OUTREACH_TASK_KINDS } from "../model/outreach.types.js";
@@ -47,6 +47,50 @@ import { useOutreachEmailTemplates } from "./use-outreach-crm.js";
47
47
  field: field === 'id' ? 'step' : field
48
48
  };
49
49
  }
50
+ /**
51
+ * The countries a sequence sends to, as chips in an Autocomplete.
52
+ *
53
+ * MEMOIZED, AND EVERY PROP IT TAKES IS STABLE WHILE THE COUNTRIES ARE
54
+ * (AGL-3423). A multiple Autocomplete hands its input a new chip array as
55
+ * `startAdornment` on every render, and MUI's `InputBase` copies that into
56
+ * its `FormControl` from a passive effect — a state update after every
57
+ * commit this field takes part in. React 19 counts a commit that leaves such
58
+ * an update pending as a nested update, and keystrokes the browser delivers
59
+ * back to back (a held key, fast typing on a busy page) commit one after
60
+ * another with nothing in between to clear the count: fifty-one of them and
61
+ * the next keystroke's own `setState` throws "Maximum update depth exceeded"
62
+ * (minified error #185), which is what typing a step's body reported. Kept
63
+ * out of the editor's other renders, the field commits only when the
64
+ * countries, their options or their issue change.
65
+ */ const OutreachCountriesField = /*#__PURE__*/ memo(function OutreachCountriesField(props) {
66
+ return /*#__PURE__*/ _jsx(Autocomplete, {
67
+ multiple: true,
68
+ options: props.options,
69
+ value: props.value,
70
+ getOptionLabel: outreachCountryLabel,
71
+ onChange: (_event, next)=>props.onChange(next),
72
+ disabled: props.disabled,
73
+ renderValue: (value, getItemProps)=>value.map((code, index)=>{
74
+ const _getItemProps = getItemProps({
75
+ index
76
+ }), { key } = _getItemProps, item = _object_without_properties_loose(_getItemProps, [
77
+ "key"
78
+ ]);
79
+ return /*#__PURE__*/ _jsx(Chip, _extends({
80
+ size: "small",
81
+ label: outreachCountryLabel(code)
82
+ }, item), key);
83
+ }),
84
+ renderInput: (params)=>{
85
+ var _props_issue;
86
+ return /*#__PURE__*/ _jsx(TextField, _extends({}, params, {
87
+ label: "Countries",
88
+ error: Boolean(props.issue),
89
+ helperText: (_props_issue = props.issue) != null ? _props_issue : 'Among the countries your organization allows. Cold contacts are emailed only in the United States.'
90
+ }));
91
+ }
92
+ });
93
+ });
50
94
  /**
51
95
  * The sequence editor (AGL-2980): the name, the site and mailbox, the steps,
52
96
  * who it sends to and when, beside a live preview of each email.
@@ -58,7 +102,7 @@ import { useOutreachEmailTemplates } from "./use-outreach-crm.js";
58
102
  * no longer change once people are enrolled) comes back from the save and
59
103
  * is shown in the same places.
60
104
  */ export function OutreachSequenceEditor(props) {
61
- var _ref, _ref1, _props_mailboxes_mailboxes_find, _ref2, _issueAt, _issueAt1, _props_org, _ref3;
105
+ var _ref, _props_mailboxes_mailboxes_find, _ref1, _issueAt, _issueAt1, _props_org, _ref2;
62
106
  var _settings_settings, _settings_settings1, _issues_find, _hosts_find;
63
107
  const { orgId, orgMount, sequence, settings } = props;
64
108
  const api = useOutreachApi(orgId);
@@ -69,9 +113,12 @@ import { useOutreachEmailTemplates } from "./use-outreach-crm.js";
69
113
  const hosts = useMemo(()=>mountedHosts != null ? mountedHosts : [], [
70
114
  mountedHosts
71
115
  ]);
72
- const orgCountries = (_ref1 = (_settings_settings = settings.settings) == null ? void 0 : _settings_settings.allowedCountries) != null ? _ref1 : [
73
- 'US'
74
- ];
116
+ const allowedCountries = (_settings_settings = settings.settings) == null ? void 0 : _settings_settings.allowedCountries;
117
+ const orgCountries = useMemo(()=>allowedCountries != null ? allowedCountries : [
118
+ 'US'
119
+ ], [
120
+ allowedCountries
121
+ ]);
75
122
  const [draft, setDraft] = useState(()=>sequence ? outreachSequenceDraftOf(sequence) : emptyOutreachSequenceDraft({
76
123
  hostId: hosts.length === 1 ? hosts[0].id : '',
77
124
  allowedCountries: orgCountries
@@ -161,10 +208,25 @@ import { useOutreachEmailTemplates } from "./use-outreach-crm.js";
161
208
  };
162
209
  const listIssue = issueAt('steps');
163
210
  const countriesIssue = (_issues_find = issues.find((issue)=>issue.path.startsWith('settings.allowedCountries'))) == null ? void 0 : _issues_find.message;
211
+ // An edit clears what the last save refused. The empty list stays the same
212
+ // list, so an edit with nothing to clear does not change that state.
213
+ const clearServerIssues = useCallback(()=>setServerIssues((previous)=>previous.length ? [] : previous), []);
164
214
  const update = (next)=>{
165
- setServerIssues([]);
215
+ clearServerIssues();
166
216
  setDraft((previous)=>_extends({}, previous, next));
167
217
  };
218
+ // Stable, for the memoized countries field: it reads the settings it
219
+ // replaces from the draft it is given rather than from this render's.
220
+ const setCountries = useCallback((next)=>{
221
+ clearServerIssues();
222
+ setDraft((previous)=>_extends({}, previous, {
223
+ settings: _extends({}, previous.settings, {
224
+ allowedCountries: next
225
+ })
226
+ }));
227
+ }, [
228
+ clearServerIssues
229
+ ]);
168
230
  const setStep = (index, step)=>update({
169
231
  steps: draft.steps.map((entry, position)=>position === index ? step : entry)
170
232
  });
@@ -212,13 +274,17 @@ import { useOutreachEmailTemplates } from "./use-outreach-crm.js";
212
274
  setSaving(false);
213
275
  }
214
276
  };
215
- const siteName = (_ref2 = (_hosts_find = hosts.find((host)=>host.id === draft.hostId)) == null ? void 0 : _hosts_find.name) != null ? _ref2 : '';
216
- const countryOptions = [
217
- ...new Set([
218
- ...orgCountries,
219
- ...draft.settings.allowedCountries
220
- ])
221
- ];
277
+ const siteName = (_ref1 = (_hosts_find = hosts.find((host)=>host.id === draft.hostId)) == null ? void 0 : _hosts_find.name) != null ? _ref1 : '';
278
+ const draftCountries = draft.settings.allowedCountries;
279
+ const countryOptions = useMemo(()=>[
280
+ ...new Set([
281
+ ...orgCountries,
282
+ ...draftCountries
283
+ ])
284
+ ], [
285
+ orgCountries,
286
+ draftCountries
287
+ ]);
222
288
  /*
223
289
  * A test sends the step as STORED (AGL-3325): the route reads the saved
224
290
  * sequence, so a new one has nothing to send yet and an edited one sends
@@ -427,33 +493,12 @@ import { useOutreachEmailTemplates } from "./use-outreach-crm.js";
427
493
  children: /*#__PURE__*/ _jsxs(Stack, {
428
494
  spacing: 2,
429
495
  children: [
430
- /*#__PURE__*/ _jsx(Autocomplete, {
431
- multiple: true,
496
+ /*#__PURE__*/ _jsx(OutreachCountriesField, {
432
497
  options: countryOptions,
433
- value: draft.settings.allowedCountries,
434
- getOptionLabel: outreachCountryLabel,
435
- onChange: (_event, next)=>update({
436
- settings: _extends({}, draft.settings, {
437
- allowedCountries: next
438
- })
439
- }),
440
- disabled: archived,
441
- renderValue: (value, getItemProps)=>value.map((code, index)=>{
442
- const _getItemProps = getItemProps({
443
- index
444
- }), { key } = _getItemProps, item = _object_without_properties_loose(_getItemProps, [
445
- "key"
446
- ]);
447
- return /*#__PURE__*/ _jsx(Chip, _extends({
448
- size: "small",
449
- label: outreachCountryLabel(code)
450
- }, item), key);
451
- }),
452
- renderInput: (params)=>/*#__PURE__*/ _jsx(TextField, _extends({}, params, {
453
- label: "Countries",
454
- error: Boolean(countriesIssue),
455
- helperText: countriesIssue != null ? countriesIssue : 'Among the countries your organization allows. Cold contacts are emailed only in the United States.'
456
- }))
498
+ value: draftCountries,
499
+ onChange: setCountries,
500
+ issue: countriesIssue,
501
+ disabled: archived
457
502
  }),
458
503
  /*#__PURE__*/ _jsx(FormControlLabel, {
459
504
  control: /*#__PURE__*/ _jsx(Switch, {
@@ -557,7 +602,7 @@ import { useOutreachEmailTemplates } from "./use-outreach-crm.js";
557
602
  sequence: sequence,
558
603
  stepIndex: testing,
559
604
  contactGroupId: sequence.hostId ? consentGroupForHost((_props_org = props.org) != null ? _props_org : null, sequence.hostId).groupId : '',
560
- selfEmail: (_ref3 = user == null ? void 0 : user.email) != null ? _ref3 : null,
605
+ selfEmail: (_ref2 = user == null ? void 0 : user.email) != null ? _ref2 : null,
561
606
  unsaved: unsaved,
562
607
  api: api
563
608
  }) : null,