@aglyn/plugins-outreach 1.0.0-beta.224 → 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
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/mailbox-card.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 { pluginDocsHelp } from '@aglyn/aglyn'\nimport { CardDisplay, useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport SenderReadinessPanel from '@aglyn/tenant-feature-instance/components/sender-readiness-panel'\nimport {\n Alert,\n Autocomplete,\n Box,\n Button,\n Chip,\n FormControlLabel,\n FormHelperText,\n MenuItem,\n Stack,\n Switch,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport {\n formatMinuteOfDay,\n isValidTimezone,\n OUTREACH_DEFAULT_WINDOW,\n OUTREACH_MAILBOX_STATUS_LABELS,\n OUTREACH_MAX_DAILY_CAP,\n OUTREACH_RAMP_STEPS,\n OUTREACH_WEEKDAY_LABELS,\n outreachEffectiveDailyCap,\n outreachLocalDay,\n summarizeMailboxHealth,\n validateDailyCap,\n validateDisplayName,\n validateSendWindow,\n} from '../mailboxes/mailbox-settings'\nimport type { OutreachMailboxReadinessResponse } from '../mailboxes/mailbox-api'\nimport type {\n OutreachMailbox,\n OutreachMailboxStatus,\n OutreachSendWindow,\n} from '../model/outreach.types'\nimport { outreachPacingNote } from './next-send'\nimport type { OutreachMailboxApi } from './use-outreach-mailbox-api'\n\nexport interface MailboxCardProps {\n mailbox: OutreachMailbox\n /** The viewer is the member who connected it. */\n isMine: boolean\n /** The viewer may change, pause and disconnect it: its member, or an org owner or admin. */\n canManage: boolean\n api: OutreachMailboxApi\n /** Starts a new Google connect, for a mailbox that needs reconnecting. */\n onReconnect(): void\n /** True while that connect is on its way to Google. */\n reconnecting?: boolean\n /** The clock the health window and today's limit are read on. */\n nowMs?: number\n}\n\n/**\n * What the card says about a mailbox that paused ITSELF (AGL-2981): the\n * engine's own sentence, when it paused, and — after a complaint — the day\n * resuming stops being premature. Nothing sends from it until a member\n * resumes it.\n */\nexport function autoPauseSentence(mailbox: Pick<OutreachMailbox, 'autoPause' | 'timezone'>): string {\n const pause = mailbox.autoPause\n if (!pause) return ''\n const day = (atMs: number) => {\n try {\n return new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeZone: mailbox.timezone }).format(atMs)\n } catch {\n return new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeZone: 'UTC' }).format(atMs)\n }\n }\n const until = typeof pause.untilMs === 'number' ? ` Wait until ${day(pause.untilMs)} before resuming it.` : ''\n return `Sequences paused this mailbox on ${day(pause.atMs)}. ${pause.message}${until} Nothing sends from it until it is resumed.`\n}\n\n/** Accessible names of the card's actions, spelled once for the specs. */\nexport const MAILBOX_ACTION_LABELS = {\n save: 'Save settings',\n pause: 'Pause',\n resume: 'Resume',\n test: 'Send a test to myself',\n testElsewhere: 'Send a test',\n testAddress: 'Test address',\n warmUp: 'Warm up gradually',\n disconnect: 'Disconnect',\n reconnect: 'Reconnect',\n recheckReadiness: 'Check DNS again',\n} as const\n\nconst WEEKDAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']\n\nconst STATUS_COLOR: Record<OutreachMailboxStatus, 'success' | 'default' | 'warning' | 'error'> = {\n connected: 'success',\n paused: 'default',\n reconnect_required: 'warning',\n disconnected: 'error',\n}\n\n/** Every half hour of the day, and midnight at its end. */\nconst MINUTE_OPTIONS = Array.from({ length: 49 }, (_, index) => index * 30)\n\n/** The zones this runtime knows, the mailbox's own included whatever it is. */\nfunction timezoneOptions(current: string): string[] {\n const supported = (Intl as { supportedValuesOf?: (key: string) => string[] }).supportedValuesOf?.('timeZone') ?? []\n const zones = supported.length ? supported : ['UTC']\n return zones.includes(current) ? zones : [current, ...zones]\n}\n\n/** The ramp, as the cap's helper text reads it. */\nconst RAMP_SENTENCE = `Warm-up: ${OUTREACH_RAMP_STEPS.map((step, index) =>\n `week ${step.week}${index === OUTREACH_RAMP_STEPS.length - 1 ? '+' : ''}: ${step.limit}`,\n).join(' · ')} a day, never above the cap.`\n\ninterface Draft {\n sendAs: string\n displayName: string\n dailyCap: string\n window: OutreachSendWindow\n timezone: string\n /** Whether the warm-up ramp applies — `rampStartedAtMs` as a switch. */\n warmUp: boolean\n}\n\nconst draftOf = (mailbox: OutreachMailbox): Draft => ({\n sendAs: mailbox.sendAs ?? mailbox.email,\n displayName: mailbox.displayName ?? '',\n dailyCap: String(mailbox.dailyCap ?? ''),\n window: mailbox.window ?? OUTREACH_DEFAULT_WINDOW,\n timezone: mailbox.timezone ?? 'UTC',\n warmUp: typeof mailbox.rampStartedAtMs === 'number',\n})\n\n/**\n * One connected mailbox (AGL-2978): its account and status, its last seven\n * days, its settings, and pause, test and disconnect.\n *\n * Every control is offered only where the route will allow it: the settings\n * form and pause and disconnect to the member who connected the mailbox or an\n * org owner or admin, and the test and the reconnect to its member alone,\n * because both act in that member's own Google account.\n */\nexport function MailboxCard(props: MailboxCardProps) {\n const { mailbox, isMine, canManage, api, onReconnect, reconnecting = false, nowMs = Date.now() } = props\n const { enqueueSnackbar } = useSnackbar()\n const { confirm } = useConfirmationContext()\n const [draft, setDraft] = useState<Draft>(() => draftOf(mailbox))\n const [saving, setSaving] = useState(false)\n const [saveError, setSaveError] = useState<string | null>(null)\n const [busy, setBusy] = useState<'status' | 'test' | 'disconnect' | null>(null)\n // Where a test goes when not to the member themself (AGL-3228): a test to\n // one's own address never leaves Google and shows no authentication result.\n const [testAddress, setTestAddress] = useState('')\n\n /*\n * SPF, DKIM and DMARC for the address this mailbox sends as (AGL-3328),\n * read by the server and remembered there briefly. Re-read when the\n * send-as address changes; a failed read shows nothing rather than a\n * verdict nobody made.\n */\n const sendAsAddress = mailbox.sendAs || mailbox.email\n const [readiness, setReadiness] = useState<OutreachMailboxReadinessResponse | null>(null)\n const [readinessBusy, setReadinessBusy] = useState(false)\n useEffect(() => {\n let active = true\n api\n .readiness(mailbox.id)\n .then((answer) => {\n if (active) setReadiness(answer)\n })\n .catch(() => {\n if (active) setReadiness(null)\n })\n return () => {\n active = false\n }\n }, [api, mailbox.id, sendAsAddress])\n const recheckReadiness = async () => {\n setReadinessBusy(true)\n try {\n setReadiness(await api.readiness(mailbox.id, true))\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n } finally {\n setReadinessBusy(false)\n }\n }\n\n // A save here, a change made from another tab, or a reconnect rewrites the\n // stored settings; the form follows them, unless the member has unsaved\n // edits of their own, which are never thrown away.\n const stored = useMemo(() => draftOf(mailbox), [mailbox])\n const storedKey = JSON.stringify(stored)\n const seededFrom = useRef(storedKey)\n const dirty = JSON.stringify(draft) !== storedKey\n useEffect(() => {\n if (seededFrom.current === storedKey) return\n const previous = seededFrom.current\n seededFrom.current = storedKey\n setDraft((current) => (JSON.stringify(current) === previous ? stored : current))\n }, [storedKey, stored])\n\n const health = summarizeMailboxHealth(mailbox.health, mailbox.timezone, nowMs)\n // Tests of a sequence step sent today (AGL-3325): counted beside the\n // sends, never among them, so the cap and the seven-day sum stay honest.\n const testsToday = Math.max(\n 0,\n Number(mailbox.health?.daily?.[outreachLocalDay(nowMs, mailbox.timezone)]?.tests) || 0,\n )\n const needsReconnect = mailbox.status === 'reconnect_required' || mailbox.status === 'disconnected'\n const capCheck = validateDailyCap(draft.dailyCap === '' ? Number.NaN : Number(draft.dailyCap))\n const windowCheck = validateSendWindow(draft.window)\n const nameCheck = validateDisplayName(draft.displayName)\n const timezoneValid = isValidTimezone(draft.timezone)\n const invalid =\n typeof capCheck !== 'number' || !('days' in windowCheck) || typeof nameCheck !== 'string' || !timezoneValid\n const todayLimit = outreachEffectiveDailyCap(\n {\n dailyCap: typeof capCheck === 'number' ? capCheck : mailbox.dailyCap,\n // A ramp switched on in the draft reads as starting today.\n rampStartedAtMs: draft.warmUp ? (mailbox.rampStartedAtMs ?? nowMs) : null,\n timezone: timezoneValid ? draft.timezone : mailbox.timezone,\n },\n nowMs,\n )\n\n const save = async () => {\n setSaving(true)\n setSaveError(null)\n try {\n await api.saveSettings({\n mailboxId: mailbox.id,\n ...(draft.sendAs !== stored.sendAs ? { sendAs: draft.sendAs } : {}),\n ...(draft.displayName !== stored.displayName ? { displayName: draft.displayName } : {}),\n ...(draft.dailyCap !== stored.dailyCap ? { dailyCap: Number(draft.dailyCap) } : {}),\n ...(JSON.stringify(draft.window) !== JSON.stringify(stored.window) ? { window: draft.window } : {}),\n ...(draft.timezone !== stored.timezone ? { timezone: draft.timezone } : {}),\n ...(draft.warmUp !== stored.warmUp ? { warmUp: draft.warmUp } : {}),\n })\n enqueueSnackbar('Mailbox settings saved', { variant: 'success' })\n } catch (error) {\n setSaveError((error as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n const togglePaused = async () => {\n const paused = mailbox.status !== 'paused'\n setBusy('status')\n try {\n await api.setPaused(mailbox.id, paused)\n enqueueSnackbar(paused ? 'Mailbox paused' : 'Mailbox resumed', { variant: 'success' })\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n } finally {\n setBusy(null)\n }\n }\n\n const sendTest = async () => {\n setBusy('test')\n try {\n const to = testAddress.trim()\n const sent = await api.sendTest(mailbox.id, to || undefined)\n enqueueSnackbar(\n to\n ? `Test sent to ${sent.sentTo}. Its original source shows whether the sender authenticated.`\n : `Test sent to ${sent.sentTo}. Check your inbox.`,\n { variant: 'success' },\n )\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n } finally {\n setBusy(null)\n }\n }\n\n const disconnect = async () => {\n const confirmed = await confirm({\n title: 'Disconnect this mailbox?',\n description:\n 'Disconnecting deletes the access stored for this mailbox and asks Google to revoke it. ' +\n 'Nothing is sent from it again unless it is connected again.',\n confirmationText: MAILBOX_ACTION_LABELS.disconnect,\n confirmationButtonProps: { color: 'error' },\n })\n .then(() => true)\n .catch(() => false)\n if (!confirmed) return\n setBusy('disconnect')\n try {\n const { revocation } = await api.disconnect(mailbox.id)\n if (revocation === 'failed') {\n enqueueSnackbar(\n 'Mailbox disconnected, but Google could not confirm the access was revoked. ' +\n 'Remove it from the Google Account’s third-party connections to be sure.',\n { variant: 'warning', persist: true },\n )\n } else if (revocation === 'kept-for-other-mailbox') {\n enqueueSnackbar(\n 'Mailbox disconnected. Google access stays in place for another connected mailbox on the same account.',\n { variant: 'success' },\n )\n } else {\n enqueueSnackbar('Mailbox disconnected', { variant: 'success' })\n }\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n setBusy(null)\n }\n }\n\n const sendAsLabel = (email: string) => {\n const option = mailbox.sendAsOptions?.find((entry) => entry.email === email)\n return option?.displayName ? `${option.displayName} <${option.email}>` : email\n }\n\n return (\n <CardDisplay\n header={mailbox.email}\n subheader={isMine ? 'Your mailbox' : 'A teammate’s mailbox'}\n help={pluginDocsHelp('sequences', { anchor: '#connect-a-mailbox' })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n action: (\n <Chip\n size=\"small\"\n label={OUTREACH_MAILBOX_STATUS_LABELS[mailbox.status] ?? mailbox.status}\n color={STATUS_COLOR[mailbox.status] ?? 'default'}\n />\n ),\n }}\n >\n <Stack spacing={2}>\n {needsReconnect ? (\n <Alert\n severity=\"warning\"\n action={\n isMine ? (\n <Button color=\"inherit\" size=\"small\" disabled={reconnecting} onClick={onReconnect}>\n {MAILBOX_ACTION_LABELS.reconnect}\n </Button>\n ) : undefined\n }\n >\n {`${\n mailbox.status === 'disconnected'\n ? 'This mailbox was disconnected.'\n : 'Google stopped accepting this mailbox’s connection.'\n } ${\n isMine\n ? 'Nothing sends from it until you connect it again.'\n : 'Only the member who connected it can reconnect it.'\n }`}\n </Alert>\n ) : null}\n {mailbox.status === 'paused' && mailbox.autoPause ? (\n <Alert severity=\"error\" role=\"alert\">\n {autoPauseSentence(mailbox)}\n </Alert>\n ) : null}\n\n <Box>\n <Typography variant=\"subtitle2\">Last 7 days</Typography>\n {health.hasSent ? null : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n No sends yet\n </Typography>\n )}\n <Stack direction=\"row\" spacing={3} sx={{ mt: 0.5 }}>\n {[\n ['Sent', health.sent],\n ['Bounces', health.bounces],\n ['Replies', health.replies],\n ].map(([label, value]) => (\n <Box key={label as string} aria-label={`${label} in the last 7 days`}>\n <Typography variant=\"h6\" component=\"p\">\n {value}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {label}\n </Typography>\n </Box>\n ))}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\" aria-label=\"Tests today\">\n {`Tests today: ${testsToday}`}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\" aria-label=\"Pacing\">\n {outreachPacingNote(mailbox, nowMs)}\n </Typography>\n </Box>\n\n {readiness?.readiness ? (\n <Stack spacing={1}>\n <SenderReadinessPanel readiness={readiness.readiness} />\n <Box>\n <Button size=\"small\" disabled={readinessBusy} onClick={() => void recheckReadiness()}>\n {MAILBOX_ACTION_LABELS.recheckReadiness}\n </Button>\n </Box>\n </Stack>\n ) : readiness ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`Google authenticates mail from ${readiness.sendAs.slice(readiness.sendAs.lastIndexOf('@') + 1)} ` +\n 'itself, so there are no records to publish for this address.'}\n </Typography>\n ) : null}\n\n {canManage ? (\n <Stack spacing={2} component=\"form\" onSubmit={(event) => event.preventDefault()}>\n <TextField\n select\n size=\"small\"\n label=\"Send as\"\n value={draft.sendAs}\n onChange={(event) => setDraft({ ...draft, sendAs: event.target.value })}\n helperText=\"Addresses Gmail has verified for this account.\"\n >\n {(mailbox.sendAsOptions?.length ? mailbox.sendAsOptions : [{ email: mailbox.sendAs }]).map((option) => (\n <MenuItem key={option.email} value={option.email}>\n {sendAsLabel(option.email)}\n </MenuItem>\n ))}\n </TextField>\n <TextField\n size=\"small\"\n label=\"Display name\"\n value={draft.displayName}\n onChange={(event) => setDraft({ ...draft, displayName: event.target.value })}\n error={typeof nameCheck !== 'string'}\n helperText={typeof nameCheck !== 'string' ? nameCheck.message : 'The name recipients see beside the address.'}\n />\n <TextField\n size=\"small\"\n type=\"number\"\n label=\"Daily cap\"\n value={draft.dailyCap}\n onChange={(event) => setDraft({ ...draft, dailyCap: event.target.value })}\n error={typeof capCheck !== 'number'}\n slotProps={{ htmlInput: { min: 1, max: OUTREACH_MAX_DAILY_CAP, step: 1 } }}\n helperText={\n typeof capCheck !== 'number'\n ? capCheck.message\n : draft.warmUp\n ? `${RAMP_SENTENCE} Today’s limit: ${todayLimit}.`\n : `No warm-up: today’s limit is the cap, ${todayLimit}.`\n }\n />\n <FormControlLabel\n control={\n <Switch\n checked={draft.warmUp}\n onChange={(event) => setDraft({ ...draft, warmUp: event.target.checked })}\n />\n }\n label={MAILBOX_ACTION_LABELS.warmUp}\n />\n <FormHelperText sx={{ mt: -1 }}>\n {'For a mailbox that is new or has not sent much. One that has sent mail for years already has ' +\n 'its reputation and can start at its cap.'}\n </FormHelperText>\n <Box>\n <Typography variant=\"subtitle2\" gutterBottom>\n Sending window\n </Typography>\n <ToggleButtonGroup\n size=\"small\"\n aria-label=\"Sending days\"\n value={draft.window.days}\n onChange={(_event, days: number[]) =>\n setDraft({ ...draft, window: { ...draft.window, days: [...days].sort((a, b) => a - b) } })\n }\n >\n {OUTREACH_WEEKDAY_LABELS.map((label, day) => (\n <ToggleButton key={label} value={day} aria-label={WEEKDAY_NAMES[day]}>\n {label}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} sx={{ mt: 2 }}>\n <TextField\n select\n size=\"small\"\n label=\"From\"\n value={draft.window.startMinute}\n onChange={(event) =>\n setDraft({ ...draft, window: { ...draft.window, startMinute: Number(event.target.value) } })\n }\n >\n {MINUTE_OPTIONS.slice(0, -1).map((minute) => (\n <MenuItem key={minute} value={minute}>\n {formatMinuteOfDay(minute)}\n </MenuItem>\n ))}\n </TextField>\n <TextField\n select\n size=\"small\"\n label=\"Until\"\n value={draft.window.endMinute}\n onChange={(event) =>\n setDraft({ ...draft, window: { ...draft.window, endMinute: Number(event.target.value) } })\n }\n >\n {MINUTE_OPTIONS.slice(1).map((minute) => (\n <MenuItem key={minute} value={minute}>\n {formatMinuteOfDay(minute)}\n </MenuItem>\n ))}\n </TextField>\n <Autocomplete\n size=\"small\"\n disableClearable\n options={timezoneOptions(mailbox.timezone)}\n value={draft.timezone}\n onChange={(_event, timezone) => setDraft({ ...draft, timezone: timezone ?? draft.timezone })}\n sx={{ minWidth: 240 }}\n renderInput={(params) => <TextField {...params} label=\"Timezone\" />}\n />\n </Stack>\n {'days' in windowCheck ? null : <FormHelperText error>{windowCheck.message}</FormHelperText>}\n </Box>\n {saveError ? <FormHelperText error>{saveError}</FormHelperText> : null}\n <Box>\n <Button variant=\"contained\" disabled={!dirty || invalid || saving} onClick={() => void save()}>\n {MAILBOX_ACTION_LABELS.save}\n </Button>\n </Box>\n </Stack>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Sends as ${sendAsLabel(stored.sendAs)}, at most ${stored.dailyCap} a day, ` +\n `${stored.window.days.map((day) => OUTREACH_WEEKDAY_LABELS[day]).join(', ')} ` +\n `${formatMinuteOfDay(stored.window.startMinute)}–${formatMinuteOfDay(stored.window.endMinute)} ` +\n `(${stored.timezone}).`}\n </Typography>\n )}\n\n {isMine && !needsReconnect ? (\n <TextField\n label={MAILBOX_ACTION_LABELS.testAddress}\n value={testAddress}\n onChange={(event) => setTestAddress(event.target.value)}\n disabled={busy !== null}\n size=\"small\"\n type=\"email\"\n helperText={\n 'Leave empty to send the test to yourself. A test to an outside mailbox you can ' +\n 'read is the only one whose original source shows the sender authentication results.'\n }\n fullWidth\n />\n ) : null}\n\n {canManage || isMine ? (\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ flexWrap: 'wrap' }}>\n {canManage && !needsReconnect ? (\n <Button variant=\"outlined\" disabled={busy !== null} onClick={() => void togglePaused()}>\n {mailbox.status === 'paused' ? MAILBOX_ACTION_LABELS.resume : MAILBOX_ACTION_LABELS.pause}\n </Button>\n ) : null}\n {isMine && !needsReconnect ? (\n <Button variant=\"outlined\" disabled={busy !== null} onClick={() => void sendTest()}>\n {testAddress.trim() ? MAILBOX_ACTION_LABELS.testElsewhere : MAILBOX_ACTION_LABELS.test}\n </Button>\n ) : null}\n {canManage ? (\n <Button color=\"error\" disabled={busy !== null} onClick={() => void disconnect()}>\n {MAILBOX_ACTION_LABELS.disconnect}\n </Button>\n ) : null}\n </Stack>\n ) : null}\n </Stack>\n </CardDisplay>\n )\n}\nMailboxCard.displayName = 'MailboxCard'\n\nexport default MailboxCard\n"],"names":["pluginDocsHelp","CardDisplay","useConfirmationContext","useSnackbar","SenderReadinessPanel","Alert","Autocomplete","Box","Button","Chip","FormControlLabel","FormHelperText","MenuItem","Stack","Switch","TextField","ToggleButton","ToggleButtonGroup","Typography","useEffect","useMemo","useRef","useState","formatMinuteOfDay","isValidTimezone","OUTREACH_DEFAULT_WINDOW","OUTREACH_MAILBOX_STATUS_LABELS","OUTREACH_MAX_DAILY_CAP","OUTREACH_RAMP_STEPS","OUTREACH_WEEKDAY_LABELS","outreachEffectiveDailyCap","outreachLocalDay","summarizeMailboxHealth","validateDailyCap","validateDisplayName","validateSendWindow","outreachPacingNote","autoPauseSentence","mailbox","pause","autoPause","day","atMs","Intl","DateTimeFormat","dateStyle","timeZone","timezone","format","until","untilMs","message","MAILBOX_ACTION_LABELS","save","resume","test","testElsewhere","testAddress","warmUp","disconnect","reconnect","recheckReadiness","WEEKDAY_NAMES","STATUS_COLOR","connected","paused","reconnect_required","disconnected","MINUTE_OPTIONS","Array","from","length","_","index","timezoneOptions","current","supported","supportedValuesOf","zones","includes","RAMP_SENTENCE","map","step","week","limit","join","draftOf","sendAs","email","displayName","dailyCap","String","window","rampStartedAtMs","MailboxCard","props","isMine","canManage","api","onReconnect","reconnecting","nowMs","Date","now","enqueueSnackbar","confirm","draft","setDraft","saving","setSaving","saveError","setSaveError","busy","setBusy","setTestAddress","sendAsAddress","readiness","setReadiness","readinessBusy","setReadinessBusy","active","id","then","answer","catch","error","variant","allowDuplicate","stored","storedKey","JSON","stringify","seededFrom","dirty","previous","health","testsToday","Math","max","Number","daily","tests","needsReconnect","status","capCheck","NaN","windowCheck","nameCheck","timezoneValid","invalid","todayLimit","saveSettings","mailboxId","togglePaused","setPaused","sendTest","to","trim","sent","undefined","sentTo","confirmed","title","description","confirmationText","confirmationButtonProps","color","revocation","persist","sendAsLabel","option","sendAsOptions","find","entry","header","subheader","help","anchor","contentGutterX","contentGutterY","HeaderProps","action","size","label","spacing","severity","disabled","onClick","role","hasSent","direction","sx","mt","bounces","replies","value","aria-label","component","slice","lastIndexOf","onSubmit","event","preventDefault","select","onChange","target","helperText","type","slotProps","htmlInput","min","control","checked","gutterBottom","days","_event","sort","a","b","xs","sm","startMinute","minute","endMinute","disableClearable","options","minWidth","renderInput","params","fullWidth","useFlexGap","flexWrap"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/mailbox-card.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 { pluginDocsHelp } from '@aglyn/aglyn'\nimport { CardDisplay, useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport SenderReadinessPanel from '@aglyn/tenant-feature-instance/components/sender-readiness-panel'\nimport {\n Alert,\n Autocomplete,\n Box,\n Button,\n Chip,\n FormControlLabel,\n FormHelperText,\n MenuItem,\n Stack,\n Switch,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport {\n formatMinuteOfDay,\n isValidTimezone,\n OUTREACH_DEFAULT_WINDOW,\n OUTREACH_MAILBOX_STATUS_LABELS,\n OUTREACH_MAX_DAILY_CAP,\n OUTREACH_RAMP_STEPS,\n OUTREACH_WEEKDAY_LABELS,\n outreachEffectiveDailyCap,\n outreachLocalDay,\n summarizeMailboxHealth,\n validateDailyCap,\n validateDisplayName,\n validateSendWindow,\n} from '../mailboxes/mailbox-settings'\nimport type { OutreachMailboxReadinessResponse } from '../mailboxes/mailbox-api'\nimport type {\n OutreachMailbox,\n OutreachMailboxStatus,\n OutreachSendWindow,\n} from '../model/outreach.types'\nimport { outreachPacingNote } from './next-send'\nimport type { OutreachMailboxApi } from './use-outreach-mailbox-api'\n\nexport interface MailboxCardProps {\n mailbox: OutreachMailbox\n /** The viewer is the member who connected it. */\n isMine: boolean\n /** The viewer may change, pause and disconnect it: its member, or an org owner or admin. */\n canManage: boolean\n api: OutreachMailboxApi\n /** Starts a new connect with the mailbox's provider, for a mailbox that needs reconnecting. */\n onReconnect(): void\n /** True while that connect is on its way to the provider. */\n reconnecting?: boolean\n /** The clock the health window and today's limit are read on. */\n nowMs?: number\n}\n\n/**\n * What the card says about a mailbox that paused ITSELF (AGL-2981): the\n * engine's own sentence, when it paused, and — after a complaint — the day\n * resuming stops being premature. Nothing sends from it until a member\n * resumes it.\n */\nexport function autoPauseSentence(mailbox: Pick<OutreachMailbox, 'autoPause' | 'timezone'>): string {\n const pause = mailbox.autoPause\n if (!pause) return ''\n const day = (atMs: number) => {\n try {\n return new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeZone: mailbox.timezone }).format(atMs)\n } catch {\n return new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeZone: 'UTC' }).format(atMs)\n }\n }\n const until = typeof pause.untilMs === 'number' ? ` Wait until ${day(pause.untilMs)} before resuming it.` : ''\n return `Sequences paused this mailbox on ${day(pause.atMs)}. ${pause.message}${until} Nothing sends from it until it is resumed.`\n}\n\n/** Accessible names of the card's actions, spelled once for the specs. */\nexport const MAILBOX_ACTION_LABELS = {\n save: 'Save settings',\n pause: 'Pause',\n resume: 'Resume',\n test: 'Send a test to myself',\n testElsewhere: 'Send a test',\n testAddress: 'Test address',\n warmUp: 'Warm up gradually',\n disconnect: 'Disconnect',\n reconnect: 'Reconnect',\n recheckReadiness: 'Check DNS again',\n} as const\n\nconst WEEKDAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']\n\nconst STATUS_COLOR: Record<OutreachMailboxStatus, 'success' | 'default' | 'warning' | 'error'> = {\n connected: 'success',\n paused: 'default',\n reconnect_required: 'warning',\n disconnected: 'error',\n}\n\n/** Every half hour of the day, and midnight at its end. */\nconst MINUTE_OPTIONS = Array.from({ length: 49 }, (_, index) => index * 30)\n\n/** The zones this runtime knows, the mailbox's own included whatever it is. */\nfunction timezoneOptions(current: string): string[] {\n const supported = (Intl as { supportedValuesOf?: (key: string) => string[] }).supportedValuesOf?.('timeZone') ?? []\n const zones = supported.length ? supported : ['UTC']\n return zones.includes(current) ? zones : [current, ...zones]\n}\n\n/** The ramp, as the cap's helper text reads it. */\nconst RAMP_SENTENCE = `Warm-up: ${OUTREACH_RAMP_STEPS.map((step, index) =>\n `week ${step.week}${index === OUTREACH_RAMP_STEPS.length - 1 ? '+' : ''}: ${step.limit}`,\n).join(' · ')} a day, never above the cap.`\n\ninterface Draft {\n sendAs: string\n displayName: string\n dailyCap: string\n window: OutreachSendWindow\n timezone: string\n /** Whether the warm-up ramp applies — `rampStartedAtMs` as a switch. */\n warmUp: boolean\n}\n\nconst draftOf = (mailbox: OutreachMailbox): Draft => ({\n sendAs: mailbox.sendAs ?? mailbox.email,\n displayName: mailbox.displayName ?? '',\n dailyCap: String(mailbox.dailyCap ?? ''),\n window: mailbox.window ?? OUTREACH_DEFAULT_WINDOW,\n timezone: mailbox.timezone ?? 'UTC',\n warmUp: typeof mailbox.rampStartedAtMs === 'number',\n})\n\n/**\n * One connected mailbox (AGL-2978): its account and status, its last seven\n * days, its settings, and pause, test and disconnect.\n *\n * Every control is offered only where the route will allow it: the settings\n * form and pause and disconnect to the member who connected the mailbox or an\n * org owner or admin, and the test and the reconnect to its member alone,\n * because both act in that member's own Google or Microsoft account.\n */\nexport function MailboxCard(props: MailboxCardProps) {\n const { mailbox, isMine, canManage, api, onReconnect, reconnecting = false, nowMs = Date.now() } = props\n const { enqueueSnackbar } = useSnackbar()\n const { confirm } = useConfirmationContext()\n const microsoft = mailbox.provider === 'microsoft'\n const providerName = microsoft ? 'Microsoft' : 'Google'\n const [draft, setDraft] = useState<Draft>(() => draftOf(mailbox))\n const [saving, setSaving] = useState(false)\n const [saveError, setSaveError] = useState<string | null>(null)\n const [busy, setBusy] = useState<'status' | 'test' | 'disconnect' | null>(null)\n // Where a test goes when not to the member themself (AGL-3228): a test to\n // one's own address never leaves the provider and shows no authentication result.\n const [testAddress, setTestAddress] = useState('')\n\n /*\n * SPF, DKIM and DMARC for the address this mailbox sends as (AGL-3328),\n * read by the server and remembered there briefly. Re-read when the\n * send-as address changes; a failed read shows nothing rather than a\n * verdict nobody made.\n */\n const sendAsAddress = mailbox.sendAs || mailbox.email\n const [readiness, setReadiness] = useState<OutreachMailboxReadinessResponse | null>(null)\n const [readinessBusy, setReadinessBusy] = useState(false)\n useEffect(() => {\n let active = true\n api\n .readiness(mailbox.id)\n .then((answer) => {\n if (active) setReadiness(answer)\n })\n .catch(() => {\n if (active) setReadiness(null)\n })\n return () => {\n active = false\n }\n }, [api, mailbox.id, sendAsAddress])\n const recheckReadiness = async () => {\n setReadinessBusy(true)\n try {\n setReadiness(await api.readiness(mailbox.id, true))\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n } finally {\n setReadinessBusy(false)\n }\n }\n\n // A save here, a change made from another tab, or a reconnect rewrites the\n // stored settings; the form follows them, unless the member has unsaved\n // edits of their own, which are never thrown away.\n const stored = useMemo(() => draftOf(mailbox), [mailbox])\n const storedKey = JSON.stringify(stored)\n const seededFrom = useRef(storedKey)\n const dirty = JSON.stringify(draft) !== storedKey\n useEffect(() => {\n if (seededFrom.current === storedKey) return\n const previous = seededFrom.current\n seededFrom.current = storedKey\n setDraft((current) => (JSON.stringify(current) === previous ? stored : current))\n }, [storedKey, stored])\n\n const health = summarizeMailboxHealth(mailbox.health, mailbox.timezone, nowMs)\n // Tests of a sequence step sent today (AGL-3325): counted beside the\n // sends, never among them, so the cap and the seven-day sum stay honest.\n const testsToday = Math.max(\n 0,\n Number(mailbox.health?.daily?.[outreachLocalDay(nowMs, mailbox.timezone)]?.tests) || 0,\n )\n const needsReconnect = mailbox.status === 'reconnect_required' || mailbox.status === 'disconnected'\n const capCheck = validateDailyCap(draft.dailyCap === '' ? Number.NaN : Number(draft.dailyCap))\n const windowCheck = validateSendWindow(draft.window)\n const nameCheck = validateDisplayName(draft.displayName)\n const timezoneValid = isValidTimezone(draft.timezone)\n const invalid =\n typeof capCheck !== 'number' || !('days' in windowCheck) || typeof nameCheck !== 'string' || !timezoneValid\n const todayLimit = outreachEffectiveDailyCap(\n {\n dailyCap: typeof capCheck === 'number' ? capCheck : mailbox.dailyCap,\n // A ramp switched on in the draft reads as starting today.\n rampStartedAtMs: draft.warmUp ? (mailbox.rampStartedAtMs ?? nowMs) : null,\n timezone: timezoneValid ? draft.timezone : mailbox.timezone,\n },\n nowMs,\n )\n\n const save = async () => {\n setSaving(true)\n setSaveError(null)\n try {\n await api.saveSettings({\n mailboxId: mailbox.id,\n ...(draft.sendAs !== stored.sendAs ? { sendAs: draft.sendAs } : {}),\n ...(draft.displayName !== stored.displayName ? { displayName: draft.displayName } : {}),\n ...(draft.dailyCap !== stored.dailyCap ? { dailyCap: Number(draft.dailyCap) } : {}),\n ...(JSON.stringify(draft.window) !== JSON.stringify(stored.window) ? { window: draft.window } : {}),\n ...(draft.timezone !== stored.timezone ? { timezone: draft.timezone } : {}),\n ...(draft.warmUp !== stored.warmUp ? { warmUp: draft.warmUp } : {}),\n })\n enqueueSnackbar('Mailbox settings saved', { variant: 'success' })\n } catch (error) {\n setSaveError((error as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n const togglePaused = async () => {\n const paused = mailbox.status !== 'paused'\n setBusy('status')\n try {\n await api.setPaused(mailbox.id, paused)\n enqueueSnackbar(paused ? 'Mailbox paused' : 'Mailbox resumed', { variant: 'success' })\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n } finally {\n setBusy(null)\n }\n }\n\n const sendTest = async () => {\n setBusy('test')\n try {\n const to = testAddress.trim()\n const sent = await api.sendTest(mailbox.id, to || undefined)\n enqueueSnackbar(\n to\n ? `Test sent to ${sent.sentTo}. Its original source shows whether the sender authenticated.`\n : `Test sent to ${sent.sentTo}. Check your inbox.`,\n { variant: 'success' },\n )\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n } finally {\n setBusy(null)\n }\n }\n\n const disconnect = async () => {\n const confirmed = await confirm({\n title: 'Disconnect this mailbox?',\n description:\n (microsoft\n ? 'Disconnecting deletes the access stored for this mailbox. '\n : 'Disconnecting deletes the access stored for this mailbox and asks Google to revoke it. ') +\n 'Nothing is sent from it again unless it is connected again.',\n confirmationText: MAILBOX_ACTION_LABELS.disconnect,\n confirmationButtonProps: { color: 'error' },\n })\n .then(() => true)\n .catch(() => false)\n if (!confirmed) return\n setBusy('disconnect')\n try {\n const { revocation } = await api.disconnect(mailbox.id)\n if (revocation === 'failed') {\n enqueueSnackbar(\n 'Mailbox disconnected, but Google could not confirm the access was revoked. ' +\n 'Remove it from the Google Account’s third-party connections to be sure.',\n { variant: 'warning', persist: true },\n )\n } else if (revocation === 'unsupported') {\n enqueueSnackbar(\n 'Mailbox disconnected. To end the access at Microsoft too, remove the app at myapps.microsoft.com.',\n { variant: 'success' },\n )\n } else if (revocation === 'kept-for-other-mailbox') {\n enqueueSnackbar(\n 'Mailbox disconnected. Google access stays in place for another connected mailbox on the same account.',\n { variant: 'success' },\n )\n } else {\n enqueueSnackbar('Mailbox disconnected', { variant: 'success' })\n }\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n setBusy(null)\n }\n }\n\n const sendAsLabel = (email: string) => {\n const option = mailbox.sendAsOptions?.find((entry) => entry.email === email)\n return option?.displayName ? `${option.displayName} <${option.email}>` : email\n }\n\n return (\n <CardDisplay\n header={mailbox.email}\n subheader={isMine ? 'Your mailbox' : 'A teammate’s mailbox'}\n help={pluginDocsHelp('sequences', { anchor: '#connect-a-mailbox' })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n action: (\n <Chip\n size=\"small\"\n label={OUTREACH_MAILBOX_STATUS_LABELS[mailbox.status] ?? mailbox.status}\n color={STATUS_COLOR[mailbox.status] ?? 'default'}\n />\n ),\n }}\n >\n <Stack spacing={2}>\n {needsReconnect ? (\n <Alert\n severity=\"warning\"\n action={\n isMine ? (\n <Button color=\"inherit\" size=\"small\" disabled={reconnecting} onClick={onReconnect}>\n {MAILBOX_ACTION_LABELS.reconnect}\n </Button>\n ) : undefined\n }\n >\n {`${\n mailbox.status === 'disconnected'\n ? 'This mailbox was disconnected.'\n : `${providerName} stopped accepting this mailbox’s connection.`\n } ${\n isMine\n ? 'Nothing sends from it until you connect it again.'\n : 'Only the member who connected it can reconnect it.'\n }`}\n </Alert>\n ) : null}\n {mailbox.status === 'paused' && mailbox.autoPause ? (\n <Alert severity=\"error\" role=\"alert\">\n {autoPauseSentence(mailbox)}\n </Alert>\n ) : null}\n\n <Box>\n <Typography variant=\"subtitle2\">Last 7 days</Typography>\n {health.hasSent ? null : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n No sends yet\n </Typography>\n )}\n <Stack direction=\"row\" spacing={3} sx={{ mt: 0.5 }}>\n {[\n ['Sent', health.sent],\n ['Bounces', health.bounces],\n ['Replies', health.replies],\n ].map(([label, value]) => (\n <Box key={label as string} aria-label={`${label} in the last 7 days`}>\n <Typography variant=\"h6\" component=\"p\">\n {value}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {label}\n </Typography>\n </Box>\n ))}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\" aria-label=\"Tests today\">\n {`Tests today: ${testsToday}`}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\" aria-label=\"Pacing\">\n {outreachPacingNote(mailbox, nowMs)}\n </Typography>\n </Box>\n\n {readiness?.readiness ? (\n <Stack spacing={1}>\n <SenderReadinessPanel readiness={readiness.readiness} />\n <Box>\n <Button size=\"small\" disabled={readinessBusy} onClick={() => void recheckReadiness()}>\n {MAILBOX_ACTION_LABELS.recheckReadiness}\n </Button>\n </Box>\n </Stack>\n ) : readiness ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`${providerName} authenticates mail from ${readiness.sendAs.slice(readiness.sendAs.lastIndexOf('@') + 1)} ` +\n 'itself, so there are no records to publish for this address.'}\n </Typography>\n ) : null}\n\n {canManage ? (\n <Stack spacing={2} component=\"form\" onSubmit={(event) => event.preventDefault()}>\n <TextField\n select\n size=\"small\"\n label=\"Send as\"\n value={draft.sendAs}\n onChange={(event) => setDraft({ ...draft, sendAs: event.target.value })}\n helperText=\"Addresses Gmail has verified for this account.\"\n >\n {(mailbox.sendAsOptions?.length ? mailbox.sendAsOptions : [{ email: mailbox.sendAs }]).map((option) => (\n <MenuItem key={option.email} value={option.email}>\n {sendAsLabel(option.email)}\n </MenuItem>\n ))}\n </TextField>\n <TextField\n size=\"small\"\n label=\"Display name\"\n value={draft.displayName}\n onChange={(event) => setDraft({ ...draft, displayName: event.target.value })}\n error={typeof nameCheck !== 'string'}\n helperText={typeof nameCheck !== 'string' ? nameCheck.message : 'The name recipients see beside the address.'}\n />\n <TextField\n size=\"small\"\n type=\"number\"\n label=\"Daily cap\"\n value={draft.dailyCap}\n onChange={(event) => setDraft({ ...draft, dailyCap: event.target.value })}\n error={typeof capCheck !== 'number'}\n slotProps={{ htmlInput: { min: 1, max: OUTREACH_MAX_DAILY_CAP, step: 1 } }}\n helperText={\n typeof capCheck !== 'number'\n ? capCheck.message\n : draft.warmUp\n ? `${RAMP_SENTENCE} Today’s limit: ${todayLimit}.`\n : `No warm-up: today’s limit is the cap, ${todayLimit}.`\n }\n />\n <FormControlLabel\n control={\n <Switch\n checked={draft.warmUp}\n onChange={(event) => setDraft({ ...draft, warmUp: event.target.checked })}\n />\n }\n label={MAILBOX_ACTION_LABELS.warmUp}\n />\n <FormHelperText sx={{ mt: -1 }}>\n {'For a mailbox that is new or has not sent much. One that has sent mail for years already has ' +\n 'its reputation and can start at its cap.'}\n </FormHelperText>\n <Box>\n <Typography variant=\"subtitle2\" gutterBottom>\n Sending window\n </Typography>\n <ToggleButtonGroup\n size=\"small\"\n aria-label=\"Sending days\"\n value={draft.window.days}\n onChange={(_event, days: number[]) =>\n setDraft({ ...draft, window: { ...draft.window, days: [...days].sort((a, b) => a - b) } })\n }\n >\n {OUTREACH_WEEKDAY_LABELS.map((label, day) => (\n <ToggleButton key={label} value={day} aria-label={WEEKDAY_NAMES[day]}>\n {label}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} sx={{ mt: 2 }}>\n <TextField\n select\n size=\"small\"\n label=\"From\"\n value={draft.window.startMinute}\n onChange={(event) =>\n setDraft({ ...draft, window: { ...draft.window, startMinute: Number(event.target.value) } })\n }\n >\n {MINUTE_OPTIONS.slice(0, -1).map((minute) => (\n <MenuItem key={minute} value={minute}>\n {formatMinuteOfDay(minute)}\n </MenuItem>\n ))}\n </TextField>\n <TextField\n select\n size=\"small\"\n label=\"Until\"\n value={draft.window.endMinute}\n onChange={(event) =>\n setDraft({ ...draft, window: { ...draft.window, endMinute: Number(event.target.value) } })\n }\n >\n {MINUTE_OPTIONS.slice(1).map((minute) => (\n <MenuItem key={minute} value={minute}>\n {formatMinuteOfDay(minute)}\n </MenuItem>\n ))}\n </TextField>\n <Autocomplete\n size=\"small\"\n disableClearable\n options={timezoneOptions(mailbox.timezone)}\n value={draft.timezone}\n onChange={(_event, timezone) => setDraft({ ...draft, timezone: timezone ?? draft.timezone })}\n sx={{ minWidth: 240 }}\n renderInput={(params) => <TextField {...params} label=\"Timezone\" />}\n />\n </Stack>\n {'days' in windowCheck ? null : <FormHelperText error>{windowCheck.message}</FormHelperText>}\n </Box>\n {saveError ? <FormHelperText error>{saveError}</FormHelperText> : null}\n <Box>\n <Button variant=\"contained\" disabled={!dirty || invalid || saving} onClick={() => void save()}>\n {MAILBOX_ACTION_LABELS.save}\n </Button>\n </Box>\n </Stack>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Sends as ${sendAsLabel(stored.sendAs)}, at most ${stored.dailyCap} a day, ` +\n `${stored.window.days.map((day) => OUTREACH_WEEKDAY_LABELS[day]).join(', ')} ` +\n `${formatMinuteOfDay(stored.window.startMinute)}–${formatMinuteOfDay(stored.window.endMinute)} ` +\n `(${stored.timezone}).`}\n </Typography>\n )}\n\n {isMine && !needsReconnect ? (\n <TextField\n label={MAILBOX_ACTION_LABELS.testAddress}\n value={testAddress}\n onChange={(event) => setTestAddress(event.target.value)}\n disabled={busy !== null}\n size=\"small\"\n type=\"email\"\n helperText={\n 'Leave empty to send the test to yourself. A test to an outside mailbox you can ' +\n 'read is the only one whose original source shows the sender authentication results.'\n }\n fullWidth\n />\n ) : null}\n\n {canManage || isMine ? (\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ flexWrap: 'wrap' }}>\n {canManage && !needsReconnect ? (\n <Button variant=\"outlined\" disabled={busy !== null} onClick={() => void togglePaused()}>\n {mailbox.status === 'paused' ? MAILBOX_ACTION_LABELS.resume : MAILBOX_ACTION_LABELS.pause}\n </Button>\n ) : null}\n {isMine && !needsReconnect ? (\n <Button variant=\"outlined\" disabled={busy !== null} onClick={() => void sendTest()}>\n {testAddress.trim() ? MAILBOX_ACTION_LABELS.testElsewhere : MAILBOX_ACTION_LABELS.test}\n </Button>\n ) : null}\n {canManage ? (\n <Button color=\"error\" disabled={busy !== null} onClick={() => void disconnect()}>\n {MAILBOX_ACTION_LABELS.disconnect}\n </Button>\n ) : null}\n </Stack>\n ) : null}\n </Stack>\n </CardDisplay>\n )\n}\nMailboxCard.displayName = 'MailboxCard'\n\nexport default MailboxCard\n"],"names":["pluginDocsHelp","CardDisplay","useConfirmationContext","useSnackbar","SenderReadinessPanel","Alert","Autocomplete","Box","Button","Chip","FormControlLabel","FormHelperText","MenuItem","Stack","Switch","TextField","ToggleButton","ToggleButtonGroup","Typography","useEffect","useMemo","useRef","useState","formatMinuteOfDay","isValidTimezone","OUTREACH_DEFAULT_WINDOW","OUTREACH_MAILBOX_STATUS_LABELS","OUTREACH_MAX_DAILY_CAP","OUTREACH_RAMP_STEPS","OUTREACH_WEEKDAY_LABELS","outreachEffectiveDailyCap","outreachLocalDay","summarizeMailboxHealth","validateDailyCap","validateDisplayName","validateSendWindow","outreachPacingNote","autoPauseSentence","mailbox","pause","autoPause","day","atMs","Intl","DateTimeFormat","dateStyle","timeZone","timezone","format","until","untilMs","message","MAILBOX_ACTION_LABELS","save","resume","test","testElsewhere","testAddress","warmUp","disconnect","reconnect","recheckReadiness","WEEKDAY_NAMES","STATUS_COLOR","connected","paused","reconnect_required","disconnected","MINUTE_OPTIONS","Array","from","length","_","index","timezoneOptions","current","supported","supportedValuesOf","zones","includes","RAMP_SENTENCE","map","step","week","limit","join","draftOf","sendAs","email","displayName","dailyCap","String","window","rampStartedAtMs","MailboxCard","props","isMine","canManage","api","onReconnect","reconnecting","nowMs","Date","now","enqueueSnackbar","confirm","microsoft","provider","providerName","draft","setDraft","saving","setSaving","saveError","setSaveError","busy","setBusy","setTestAddress","sendAsAddress","readiness","setReadiness","readinessBusy","setReadinessBusy","active","id","then","answer","catch","error","variant","allowDuplicate","stored","storedKey","JSON","stringify","seededFrom","dirty","previous","health","testsToday","Math","max","Number","daily","tests","needsReconnect","status","capCheck","NaN","windowCheck","nameCheck","timezoneValid","invalid","todayLimit","saveSettings","mailboxId","togglePaused","setPaused","sendTest","to","trim","sent","undefined","sentTo","confirmed","title","description","confirmationText","confirmationButtonProps","color","revocation","persist","sendAsLabel","option","sendAsOptions","find","entry","header","subheader","help","anchor","contentGutterX","contentGutterY","HeaderProps","action","size","label","spacing","severity","disabled","onClick","role","hasSent","direction","sx","mt","bounces","replies","value","aria-label","component","slice","lastIndexOf","onSubmit","event","preventDefault","select","onChange","target","helperText","type","slotProps","htmlInput","min","control","checked","gutterBottom","days","_event","sort","a","b","xs","sm","startMinute","minute","endMinute","disableClearable","options","minWidth","renderInput","params","fullWidth","useFlexGap","flexWrap"],"mappings":"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"}
@@ -1,16 +1,17 @@
1
1
  export interface OutreachMailboxesSectionProps {
2
2
  /** The organization the hub is mounted under; `null` until the shell knows it. */
3
3
  orgId: string | null;
4
- /** Sends the browser to Google's consent screen. A test seam; the page's own location by default. */
4
+ /** Sends the browser to the provider's consent screen. A test seam; the page's own location by default. */
5
5
  navigate?: (url: string) => void;
6
6
  }
7
- /** The connect button's accessible name, spelled once for the specs. */
7
+ /** The connect buttons' accessible names, spelled once for the specs. */
8
8
  export declare const CONNECT_WITH_GOOGLE_LABEL = "Connect with Google";
9
+ export declare const CONNECT_WITH_MICROSOFT_LABEL = "Connect with Microsoft";
9
10
  /**
10
- * The Mailboxes section (AGL-2978): the organization's connected Google
11
- * mailboxes, and the connect that adds one.
11
+ * The Mailboxes section (AGL-2978): the organization's connected Google and
12
+ * Microsoft 365 mailboxes (AGL-3489), and the connects that add one.
12
13
  *
13
- * A connect leaves the console for Google's consent screen and comes back
14
+ * A connect leaves the console for the provider's consent screen and comes back
14
15
  * here through the callback route, which puts the authorization code in this
15
16
  * page's URL fragment. The section reads the fragment once, takes it out of
16
17
  * the address bar before anything else, and finishes the connect with the
@@ -29,12 +29,19 @@ import { MailboxCard } from "./mailbox-card.js";
29
29
  import { useOutreachMailboxApi } from "./use-outreach-mailbox-api.js";
30
30
  import { useOutreachMailboxes } from "./use-outreach-mailboxes.js";
31
31
  const leavePage = (url)=>window.location.assign(url);
32
- /** The connect button's accessible name, spelled once for the specs. */ export const CONNECT_WITH_GOOGLE_LABEL = 'Connect with Google';
33
- /** What Google's redirect back said, in the words the panel shows. */ const RETURN_ERROR_MESSAGES = {
34
- access_denied: 'Google access was not granted, so no mailbox was connected.',
35
- expired: 'The connection took too long. Connect the mailbox again.',
36
- google_error: 'Google could not complete the connection. Connect the mailbox again.'
37
- };
32
+ /** The connect buttons' accessible names, spelled once for the specs. */ export const CONNECT_WITH_GOOGLE_LABEL = 'Connect with Google';
33
+ export const CONNECT_WITH_MICROSOFT_LABEL = 'Connect with Microsoft';
34
+ /** What the provider's redirect back said, in the words the panel shows. */ function returnErrorMessage(reason, provider) {
35
+ const name = provider === 'microsoft' ? 'Microsoft' : 'Google';
36
+ if (reason === 'access_denied') return `${name} access was not granted, so no mailbox was connected.`;
37
+ if (reason === 'expired') return 'The connection took too long. Connect the mailbox again.';
38
+ return `${name} could not complete the connection. Connect the mailbox again.`;
39
+ }
40
+ /** Whether a provider's mailboxes can be connected, from an availability answer. */ function providerReady(availability, provider) {
41
+ if (availability.status !== 'ready') return false;
42
+ // An answer with no `providers` is from a deployment that connects Google only.
43
+ return availability.providers ? availability.providers[provider] === true : provider === 'google' && availability.configured;
44
+ }
38
45
  /** Takes a connect's return fragment out of the address bar without a history entry. */ function stripFragment() {
39
46
  try {
40
47
  window.history.replaceState(null, '', window.location.pathname + window.location.search);
@@ -50,10 +57,10 @@ const leavePage = (url)=>window.location.assign(url);
50
57
  }
51
58
  }
52
59
  /**
53
- * The Mailboxes section (AGL-2978): the organization's connected Google
54
- * mailboxes, and the connect that adds one.
60
+ * The Mailboxes section (AGL-2978): the organization's connected Google and
61
+ * Microsoft 365 mailboxes (AGL-3489), and the connects that add one.
55
62
  *
56
- * A connect leaves the console for Google's consent screen and comes back
63
+ * A connect leaves the console for the provider's consent screen and comes back
57
64
  * here through the callback route, which puts the authorization code in this
58
65
  * page's URL fragment. The section reads the fragment once, takes it out of
59
66
  * the address bar before anything else, and finishes the connect with the
@@ -84,9 +91,10 @@ const leavePage = (url)=>window.location.assign(url);
84
91
  if (!fragment) return;
85
92
  stripFragment();
86
93
  if (fragment.kind === 'error') {
94
+ var _fragment_provider;
87
95
  setReturned({
88
96
  status: 'failed',
89
- message: RETURN_ERROR_MESSAGES[fragment.reason]
97
+ message: returnErrorMessage(fragment.reason, (_fragment_provider = fragment.provider) != null ? _fragment_provider : 'google')
90
98
  });
91
99
  return;
92
100
  }
@@ -131,10 +139,14 @@ const leavePage = (url)=>window.location.assign(url);
131
139
  orgId,
132
140
  uid
133
141
  ]);
134
- const connect = useCallback(async ()=>{
142
+ const connect = useCallback(async (provider, loginHint)=>{
135
143
  setConnecting(true);
136
144
  try {
137
- navigate(await api.connect());
145
+ navigate(await api.connect(_extends({
146
+ provider
147
+ }, loginHint ? {
148
+ loginHint
149
+ } : {})));
138
150
  } catch (error) {
139
151
  setConnecting(false);
140
152
  enqueueSnackbar(error.message, {
@@ -147,14 +159,37 @@ const leavePage = (url)=>window.location.assign(url);
147
159
  enqueueSnackbar,
148
160
  navigate
149
161
  ]);
150
- const configured = availability.status === 'ready' && availability.configured;
162
+ const googleReady = providerReady(availability, 'google');
163
+ const microsoftReady = providerReady(availability, 'microsoft');
164
+ const configured = googleReady || microsoftReady;
151
165
  const canManageAll = availability.status === 'ready' && availability.canManageAll;
152
- const connectButton = /*#__PURE__*/ _jsx(Button, {
153
- variant: "contained",
154
- disabled: !configured || connecting,
155
- onClick: ()=>void connect(),
156
- children: CONNECT_WITH_GOOGLE_LABEL
166
+ const connectButtons = /*#__PURE__*/ _jsxs(Stack, {
167
+ direction: "row",
168
+ spacing: 1,
169
+ sx: {
170
+ flexWrap: 'wrap',
171
+ justifyContent: 'center'
172
+ },
173
+ children: [
174
+ /*#__PURE__*/ _jsx(Button, {
175
+ variant: "contained",
176
+ disabled: !googleReady || connecting,
177
+ onClick: ()=>void connect('google'),
178
+ children: CONNECT_WITH_GOOGLE_LABEL
179
+ }),
180
+ /*#__PURE__*/ _jsx(Button, {
181
+ variant: "outlined",
182
+ disabled: !microsoftReady || connecting,
183
+ onClick: ()=>void connect('microsoft'),
184
+ children: CONNECT_WITH_MICROSOFT_LABEL
185
+ })
186
+ ]
157
187
  });
188
+ const reconnect = (mailbox)=>mailbox.provider === 'microsoft' ? connect('microsoft', mailbox.email) : connect('google');
189
+ const unconfigured = [
190
+ 'google',
191
+ 'microsoft'
192
+ ].filter((provider)=>!providerReady(availability, provider));
158
193
  const mine = listed.mailboxes.filter((mailbox)=>mailbox.connectedByUid === uid);
159
194
  const others = listed.mailboxes.filter((mailbox)=>mailbox.connectedByUid !== uid);
160
195
  return /*#__PURE__*/ _jsxs(Stack, {
@@ -168,7 +203,7 @@ const leavePage = (url)=>window.location.assign(url);
168
203
  contentGutterX: true,
169
204
  contentGutterY: true,
170
205
  HeaderProps: {
171
- action: listed.mailboxes.length ? connectButton : undefined
206
+ action: listed.mailboxes.length ? connectButtons : undefined
172
207
  },
173
208
  children: /*#__PURE__*/ _jsxs(Stack, {
174
209
  spacing: 1.5,
@@ -176,11 +211,11 @@ const leavePage = (url)=>window.location.assign(url);
176
211
  /*#__PURE__*/ _jsx(Typography, {
177
212
  variant: "body2",
178
213
  color: "text.secondary",
179
- children: 'A sequence sends from your own Google mailbox, so a message sits in your Sent mail ' + 'and a reply comes back to your inbox. Each member connects their own.'
214
+ children: 'A sequence sends from your own Google or Microsoft 365 mailbox, so a message sits in your ' + 'Sent mail and a reply comes back to your inbox. Each member connects their own.'
180
215
  }),
181
- availability.status === 'ready' && !availability.configured ? /*#__PURE__*/ _jsx(Alert, {
216
+ availability.status === 'ready' && unconfigured.length ? /*#__PURE__*/ _jsx(Alert, {
182
217
  severity: "info",
183
- children: "Connecting a Google mailbox is not configured on this deployment."
218
+ children: unconfigured.length === 2 ? 'Connecting a mailbox is not configured on this deployment.' : unconfigured[0] === 'microsoft' ? 'Connecting a Microsoft 365 mailbox is not configured on this deployment.' : 'Connecting a Google mailbox is not configured on this deployment.'
184
219
  }) : null,
185
220
  availability.status === 'error' ? /*#__PURE__*/ _jsx(Alert, {
186
221
  severity: "error",
@@ -232,8 +267,8 @@ const leavePage = (url)=>window.location.assign(url);
232
267
  variant: "outlined",
233
268
  children: /*#__PURE__*/ _jsx(EmptyStateComponent, {
234
269
  label: "No mailboxes connected",
235
- description: configured ? 'Connect your Google mailbox to send sequences from your own address.' : undefined,
236
- action: configured ? connectButton : undefined
270
+ description: configured ? 'Connect your Google or Microsoft 365 mailbox to send sequences from your own address.' : undefined,
271
+ action: configured ? connectButtons : undefined
237
272
  })
238
273
  }) : null,
239
274
  [
@@ -246,8 +281,8 @@ const leavePage = (url)=>window.location.assign(url);
246
281
  isMine: isMine,
247
282
  canManage: isMine || canManageAll,
248
283
  api: api,
249
- onReconnect: ()=>void connect(),
250
- reconnecting: connecting || !configured
284
+ onReconnect: ()=>void reconnect(mailbox),
285
+ reconnecting: connecting || !providerReady(availability, mailbox.provider === 'microsoft' ? 'microsoft' : 'google')
251
286
  }, mailbox.id);
252
287
  }),
253
288
  listed.status === 'ready' && listed.mailboxes.length ? /*#__PURE__*/ _jsx(OutreachLinkDomainsCard, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/mailboxes-section.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 { pluginDocsHelp } from '@aglyn/aglyn'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { Alert, Button, Card, CircularProgress, Stack, Typography } from '@mui/material'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport {\n parseConnectReturnFragment,\n type OutreachConnectReturnError,\n type OutreachMailboxAvailability,\n} from '../mailboxes/mailbox-api'\nimport { OutreachLinkDomainsCard } from './link-domains-card'\nimport { MailboxCard } from './mailbox-card'\nimport { useOutreachMailboxApi } from './use-outreach-mailbox-api'\nimport { useOutreachMailboxes } from './use-outreach-mailboxes'\n\nexport interface OutreachMailboxesSectionProps {\n /** The organization the hub is mounted under; `null` until the shell knows it. */\n orgId: string | null\n /** Sends the browser to Google's consent screen. A test seam; the page's own location by default. */\n navigate?: (url: string) => void\n}\n\nconst leavePage = (url: string) => window.location.assign(url)\n\n/** The connect button's accessible name, spelled once for the specs. */\nexport const CONNECT_WITH_GOOGLE_LABEL = 'Connect with Google'\n\n/** What Google's redirect back said, in the words the panel shows. */\nconst RETURN_ERROR_MESSAGES: Record<OutreachConnectReturnError, string> = {\n access_denied: 'Google access was not granted, so no mailbox was connected.',\n expired: 'The connection took too long. Connect the mailbox again.',\n google_error: 'Google could not complete the connection. Connect the mailbox again.',\n}\n\ntype Availability =\n | { status: 'loading' }\n | ({ status: 'ready' } & OutreachMailboxAvailability)\n | { status: 'error'; message: string }\n\ntype Returned =\n | { status: 'completing' }\n | { status: 'connected'; email: string; created: boolean; confirmedAliases: string[] }\n | { status: 'failed'; message: string }\n\n/** Takes a connect's return fragment out of the address bar without a history entry. */\nfunction stripFragment(): void {\n try {\n window.history.replaceState(null, '', window.location.pathname + window.location.search)\n } catch {\n // A restricted document: the connect still finishes.\n }\n}\n\n/** The browser's IANA timezone, for a new mailbox's sending window. */\nfunction browserTimezone(): string | undefined {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * The Mailboxes section (AGL-2978): the organization's connected Google\n * mailboxes, and the connect that adds one.\n *\n * A connect leaves the console for Google's consent screen and comes back\n * here through the callback route, which puts the authorization code in this\n * page's URL fragment. The section reads the fragment once, takes it out of\n * the address bar before anything else, and finishes the connect with the\n * member's own session — the step that refuses a connect started by anyone\n * else.\n */\nexport function OutreachMailboxesSection(props: OutreachMailboxesSectionProps) {\n const { orgId, navigate = leavePage } = props\n const { data: user } = useUser()\n // Effects key on the uid, never on the account object: a fresh object for\n // the same person must not re-run a connect's completion or a fetch.\n const uid = user?.uid ?? null\n const api = useOutreachMailboxApi(orgId)\n const listed = useOutreachMailboxes(orgId)\n const { enqueueSnackbar } = useSnackbar()\n const [availability, setAvailability] = useState<Availability>({ status: 'loading' })\n const [returned, setReturned] = useState<Returned | null>(null)\n const [connecting, setConnecting] = useState(false)\n const returnHandled = useRef(false)\n\n // The connect's return: read once per mount, before availability, so the\n // code leaves the address bar as early as the page can take it.\n useEffect(() => {\n if (returnHandled.current || !orgId || !uid) return\n const fragment = parseConnectReturnFragment(window.location.hash)\n returnHandled.current = true\n if (!fragment) return\n stripFragment()\n if (fragment.kind === 'error') {\n setReturned({ status: 'failed', message: RETURN_ERROR_MESSAGES[fragment.reason] })\n return\n }\n setReturned({ status: 'completing' })\n api\n .complete({ code: fragment.code, state: fragment.state, timezone: browserTimezone() })\n .then((done) =>\n setReturned({\n status: 'connected',\n email: done.mailbox.email,\n created: done.created,\n confirmedAliases: done.confirmedAliases,\n }),\n )\n .catch((error: Error) => setReturned({ status: 'failed', message: error.message }))\n }, [api, orgId, uid])\n\n useEffect(() => {\n if (!orgId || !uid) return undefined\n let current = true\n setAvailability({ status: 'loading' })\n api\n .availability()\n .then((answer) => current && setAvailability({ status: 'ready', ...answer }))\n .catch((error: Error) => current && setAvailability({ status: 'error', message: error.message }))\n return () => {\n current = false\n }\n }, [api, orgId, uid])\n\n const connect = useCallback(async () => {\n setConnecting(true)\n try {\n navigate(await api.connect())\n } catch (error) {\n setConnecting(false)\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n }\n }, [api, enqueueSnackbar, navigate])\n\n const configured = availability.status === 'ready' && availability.configured\n const canManageAll = availability.status === 'ready' && availability.canManageAll\n const connectButton = (\n <Button variant=\"contained\" disabled={!configured || connecting} onClick={() => void connect()}>\n {CONNECT_WITH_GOOGLE_LABEL}\n </Button>\n )\n const mine = listed.mailboxes.filter((mailbox) => mailbox.connectedByUid === uid)\n const others = listed.mailboxes.filter((mailbox) => mailbox.connectedByUid !== uid)\n\n return (\n <Stack spacing={2}>\n <CardDisplay\n header=\"Mailboxes\"\n help={pluginDocsHelp('sequences', { anchor: '#connect-a-mailbox' })}\n contentGutterX\n contentGutterY\n HeaderProps={{ action: listed.mailboxes.length ? connectButton : undefined }}\n >\n <Stack spacing={1.5}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'A sequence sends from your own Google mailbox, so a message sits in your Sent mail ' +\n 'and a reply comes back to your inbox. Each member connects their own.'}\n </Typography>\n {availability.status === 'ready' && !availability.configured ? (\n <Alert severity=\"info\">Connecting a Google mailbox is not configured on this deployment.</Alert>\n ) : null}\n {availability.status === 'error' ? <Alert severity=\"error\">{availability.message}</Alert> : null}\n {returned?.status === 'completing' ? (\n <Alert severity=\"info\" icon={<CircularProgress size={18} />}>\n Finishing the connection…\n </Alert>\n ) : null}\n {returned?.status === 'connected' ? (\n <Alert severity=\"success\" onClose={() => setReturned(null)}>\n {`${returned.created ? 'Connected' : 'Reconnected'} ${returned.email}.` +\n (returned.confirmedAliases.length\n ? ` Verified ${returned.confirmedAliases.join(', ')} as your own.`\n : '')}\n </Alert>\n ) : null}\n {returned?.status === 'failed' ? (\n <Alert severity=\"error\" onClose={() => setReturned(null)}>\n {returned.message}\n </Alert>\n ) : null}\n </Stack>\n </CardDisplay>\n\n {listed.status === 'loading' ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }} role=\"status\">\n <CircularProgress size={18} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n Loading mailboxes…\n </Typography>\n </Stack>\n ) : null}\n {listed.status === 'error' ? (\n <Alert severity=\"error\">The mailboxes could not be loaded. Reload the page to try again.</Alert>\n ) : null}\n {listed.status === 'ready' && !listed.mailboxes.length ? (\n <Card variant=\"outlined\">\n <EmptyStateComponent\n label=\"No mailboxes connected\"\n description={\n configured\n ? 'Connect your Google mailbox to send sequences from your own address.'\n : undefined\n }\n action={configured ? connectButton : undefined}\n />\n </Card>\n ) : null}\n {[...mine, ...others].map((mailbox) => {\n const isMine = mailbox.connectedByUid === uid\n return (\n <MailboxCard\n key={mailbox.id}\n mailbox={mailbox}\n isMine={isMine}\n canManage={isMine || canManageAll}\n api={api}\n onReconnect={() => void connect()}\n reconnecting={connecting || !configured}\n />\n )\n })}\n {listed.status === 'ready' && listed.mailboxes.length ? <OutreachLinkDomainsCard orgId={orgId} /> : null}\n </Stack>\n )\n}\nOutreachMailboxesSection.displayName = 'OutreachMailboxesSection'\n\nexport default OutreachMailboxesSection\n"],"names":["pluginDocsHelp","EmptyStateComponent","CardDisplay","useSnackbar","useUser","Alert","Button","Card","CircularProgress","Stack","Typography","useCallback","useEffect","useRef","useState","parseConnectReturnFragment","OutreachLinkDomainsCard","MailboxCard","useOutreachMailboxApi","useOutreachMailboxes","leavePage","url","window","location","assign","CONNECT_WITH_GOOGLE_LABEL","RETURN_ERROR_MESSAGES","access_denied","expired","google_error","stripFragment","history","replaceState","pathname","search","browserTimezone","Intl","DateTimeFormat","resolvedOptions","timeZone","undefined","OutreachMailboxesSection","props","orgId","navigate","data","user","uid","api","listed","enqueueSnackbar","availability","setAvailability","status","returned","setReturned","connecting","setConnecting","returnHandled","current","fragment","hash","kind","message","reason","complete","code","state","timezone","then","done","email","mailbox","created","confirmedAliases","catch","error","answer","connect","variant","allowDuplicate","configured","canManageAll","connectButton","disabled","onClick","mine","mailboxes","filter","connectedByUid","others","spacing","header","help","anchor","contentGutterX","contentGutterY","HeaderProps","action","length","color","severity","icon","size","onClose","join","direction","sx","alignItems","role","label","description","map","isMine","canManage","onReconnect","reconnecting","id","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/mailboxes-section.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 { pluginDocsHelp } from '@aglyn/aglyn'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { Alert, Button, Card, CircularProgress, Stack, Typography } from '@mui/material'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport {\n parseConnectReturnFragment,\n type OutreachConnectReturnError,\n type OutreachMailboxAvailability,\n} from '../mailboxes/mailbox-api'\nimport type { OutreachMailbox, OutreachMailboxProvider } from '../model/outreach.types'\nimport { OutreachLinkDomainsCard } from './link-domains-card'\nimport { MailboxCard } from './mailbox-card'\nimport { useOutreachMailboxApi } from './use-outreach-mailbox-api'\nimport { useOutreachMailboxes } from './use-outreach-mailboxes'\n\nexport interface OutreachMailboxesSectionProps {\n /** The organization the hub is mounted under; `null` until the shell knows it. */\n orgId: string | null\n /** Sends the browser to the provider's consent screen. A test seam; the page's own location by default. */\n navigate?: (url: string) => void\n}\n\nconst leavePage = (url: string) => window.location.assign(url)\n\n/** The connect buttons' accessible names, spelled once for the specs. */\nexport const CONNECT_WITH_GOOGLE_LABEL = 'Connect with Google'\nexport const CONNECT_WITH_MICROSOFT_LABEL = 'Connect with Microsoft'\n\n/** What the provider's redirect back said, in the words the panel shows. */\nfunction returnErrorMessage(reason: OutreachConnectReturnError, provider: OutreachMailboxProvider): string {\n const name = provider === 'microsoft' ? 'Microsoft' : 'Google'\n if (reason === 'access_denied') return `${name} access was not granted, so no mailbox was connected.`\n if (reason === 'expired') return 'The connection took too long. Connect the mailbox again.'\n return `${name} could not complete the connection. Connect the mailbox again.`\n}\n\n/** Whether a provider's mailboxes can be connected, from an availability answer. */\nfunction providerReady(availability: Availability, provider: OutreachMailboxProvider): boolean {\n if (availability.status !== 'ready') return false\n // An answer with no `providers` is from a deployment that connects Google only.\n return availability.providers ? availability.providers[provider] === true : provider === 'google' && availability.configured\n}\n\ntype Availability =\n | { status: 'loading' }\n | ({ status: 'ready' } & OutreachMailboxAvailability)\n | { status: 'error'; message: string }\n\ntype Returned =\n | { status: 'completing' }\n | { status: 'connected'; email: string; created: boolean; confirmedAliases: string[] }\n | { status: 'failed'; message: string }\n\n/** Takes a connect's return fragment out of the address bar without a history entry. */\nfunction stripFragment(): void {\n try {\n window.history.replaceState(null, '', window.location.pathname + window.location.search)\n } catch {\n // A restricted document: the connect still finishes.\n }\n}\n\n/** The browser's IANA timezone, for a new mailbox's sending window. */\nfunction browserTimezone(): string | undefined {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * The Mailboxes section (AGL-2978): the organization's connected Google and\n * Microsoft 365 mailboxes (AGL-3489), and the connects that add one.\n *\n * A connect leaves the console for the provider's consent screen and comes back\n * here through the callback route, which puts the authorization code in this\n * page's URL fragment. The section reads the fragment once, takes it out of\n * the address bar before anything else, and finishes the connect with the\n * member's own session — the step that refuses a connect started by anyone\n * else.\n */\nexport function OutreachMailboxesSection(props: OutreachMailboxesSectionProps) {\n const { orgId, navigate = leavePage } = props\n const { data: user } = useUser()\n // Effects key on the uid, never on the account object: a fresh object for\n // the same person must not re-run a connect's completion or a fetch.\n const uid = user?.uid ?? null\n const api = useOutreachMailboxApi(orgId)\n const listed = useOutreachMailboxes(orgId)\n const { enqueueSnackbar } = useSnackbar()\n const [availability, setAvailability] = useState<Availability>({ status: 'loading' })\n const [returned, setReturned] = useState<Returned | null>(null)\n const [connecting, setConnecting] = useState(false)\n const returnHandled = useRef(false)\n\n // The connect's return: read once per mount, before availability, so the\n // code leaves the address bar as early as the page can take it.\n useEffect(() => {\n if (returnHandled.current || !orgId || !uid) return\n const fragment = parseConnectReturnFragment(window.location.hash)\n returnHandled.current = true\n if (!fragment) return\n stripFragment()\n if (fragment.kind === 'error') {\n setReturned({ status: 'failed', message: returnErrorMessage(fragment.reason, fragment.provider ?? 'google') })\n return\n }\n setReturned({ status: 'completing' })\n api\n .complete({ code: fragment.code, state: fragment.state, timezone: browserTimezone() })\n .then((done) =>\n setReturned({\n status: 'connected',\n email: done.mailbox.email,\n created: done.created,\n confirmedAliases: done.confirmedAliases,\n }),\n )\n .catch((error: Error) => setReturned({ status: 'failed', message: error.message }))\n }, [api, orgId, uid])\n\n useEffect(() => {\n if (!orgId || !uid) return undefined\n let current = true\n setAvailability({ status: 'loading' })\n api\n .availability()\n .then((answer) => current && setAvailability({ status: 'ready', ...answer }))\n .catch((error: Error) => current && setAvailability({ status: 'error', message: error.message }))\n return () => {\n current = false\n }\n }, [api, orgId, uid])\n\n const connect = useCallback(\n async (provider: OutreachMailboxProvider, loginHint?: string) => {\n setConnecting(true)\n try {\n navigate(await api.connect({ provider, ...(loginHint ? { loginHint } : {}) }))\n } catch (error) {\n setConnecting(false)\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n }\n },\n [api, enqueueSnackbar, navigate],\n )\n\n const googleReady = providerReady(availability, 'google')\n const microsoftReady = providerReady(availability, 'microsoft')\n const configured = googleReady || microsoftReady\n const canManageAll = availability.status === 'ready' && availability.canManageAll\n const connectButtons = (\n <Stack direction=\"row\" spacing={1} sx={{ flexWrap: 'wrap', justifyContent: 'center' }}>\n <Button variant=\"contained\" disabled={!googleReady || connecting} onClick={() => void connect('google')}>\n {CONNECT_WITH_GOOGLE_LABEL}\n </Button>\n <Button variant=\"outlined\" disabled={!microsoftReady || connecting} onClick={() => void connect('microsoft')}>\n {CONNECT_WITH_MICROSOFT_LABEL}\n </Button>\n </Stack>\n )\n const reconnect = (mailbox: OutreachMailbox) =>\n mailbox.provider === 'microsoft' ? connect('microsoft', mailbox.email) : connect('google')\n const unconfigured = (['google', 'microsoft'] as const).filter((provider) => !providerReady(availability, provider))\n const mine = listed.mailboxes.filter((mailbox) => mailbox.connectedByUid === uid)\n const others = listed.mailboxes.filter((mailbox) => mailbox.connectedByUid !== uid)\n\n return (\n <Stack spacing={2}>\n <CardDisplay\n header=\"Mailboxes\"\n help={pluginDocsHelp('sequences', { anchor: '#connect-a-mailbox' })}\n contentGutterX\n contentGutterY\n HeaderProps={{ action: listed.mailboxes.length ? connectButtons : undefined }}\n >\n <Stack spacing={1.5}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'A sequence sends from your own Google or Microsoft 365 mailbox, so a message sits in your ' +\n 'Sent mail and a reply comes back to your inbox. Each member connects their own.'}\n </Typography>\n {availability.status === 'ready' && unconfigured.length ? (\n <Alert severity=\"info\">\n {unconfigured.length === 2\n ? 'Connecting a mailbox is not configured on this deployment.'\n : unconfigured[0] === 'microsoft'\n ? 'Connecting a Microsoft 365 mailbox is not configured on this deployment.'\n : 'Connecting a Google mailbox is not configured on this deployment.'}\n </Alert>\n ) : null}\n {availability.status === 'error' ? <Alert severity=\"error\">{availability.message}</Alert> : null}\n {returned?.status === 'completing' ? (\n <Alert severity=\"info\" icon={<CircularProgress size={18} />}>\n Finishing the connection…\n </Alert>\n ) : null}\n {returned?.status === 'connected' ? (\n <Alert severity=\"success\" onClose={() => setReturned(null)}>\n {`${returned.created ? 'Connected' : 'Reconnected'} ${returned.email}.` +\n (returned.confirmedAliases.length\n ? ` Verified ${returned.confirmedAliases.join(', ')} as your own.`\n : '')}\n </Alert>\n ) : null}\n {returned?.status === 'failed' ? (\n <Alert severity=\"error\" onClose={() => setReturned(null)}>\n {returned.message}\n </Alert>\n ) : null}\n </Stack>\n </CardDisplay>\n\n {listed.status === 'loading' ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }} role=\"status\">\n <CircularProgress size={18} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n Loading mailboxes…\n </Typography>\n </Stack>\n ) : null}\n {listed.status === 'error' ? (\n <Alert severity=\"error\">The mailboxes could not be loaded. Reload the page to try again.</Alert>\n ) : null}\n {listed.status === 'ready' && !listed.mailboxes.length ? (\n <Card variant=\"outlined\">\n <EmptyStateComponent\n label=\"No mailboxes connected\"\n description={\n configured\n ? 'Connect your Google or Microsoft 365 mailbox to send sequences from your own address.'\n : undefined\n }\n action={configured ? connectButtons : undefined}\n />\n </Card>\n ) : null}\n {[...mine, ...others].map((mailbox) => {\n const isMine = mailbox.connectedByUid === uid\n return (\n <MailboxCard\n key={mailbox.id}\n mailbox={mailbox}\n isMine={isMine}\n canManage={isMine || canManageAll}\n api={api}\n onReconnect={() => void reconnect(mailbox)}\n reconnecting={connecting || !providerReady(availability, mailbox.provider === 'microsoft' ? 'microsoft' : 'google')}\n />\n )\n })}\n {listed.status === 'ready' && listed.mailboxes.length ? <OutreachLinkDomainsCard orgId={orgId} /> : null}\n </Stack>\n )\n}\nOutreachMailboxesSection.displayName = 'OutreachMailboxesSection'\n\nexport default OutreachMailboxesSection\n"],"names":["pluginDocsHelp","EmptyStateComponent","CardDisplay","useSnackbar","useUser","Alert","Button","Card","CircularProgress","Stack","Typography","useCallback","useEffect","useRef","useState","parseConnectReturnFragment","OutreachLinkDomainsCard","MailboxCard","useOutreachMailboxApi","useOutreachMailboxes","leavePage","url","window","location","assign","CONNECT_WITH_GOOGLE_LABEL","CONNECT_WITH_MICROSOFT_LABEL","returnErrorMessage","reason","provider","name","providerReady","availability","status","providers","configured","stripFragment","history","replaceState","pathname","search","browserTimezone","Intl","DateTimeFormat","resolvedOptions","timeZone","undefined","OutreachMailboxesSection","props","orgId","navigate","data","user","uid","api","listed","enqueueSnackbar","setAvailability","returned","setReturned","connecting","setConnecting","returnHandled","current","fragment","hash","kind","message","complete","code","state","timezone","then","done","email","mailbox","created","confirmedAliases","catch","error","answer","connect","loginHint","variant","allowDuplicate","googleReady","microsoftReady","canManageAll","connectButtons","direction","spacing","sx","flexWrap","justifyContent","disabled","onClick","reconnect","unconfigured","filter","mine","mailboxes","connectedByUid","others","header","help","anchor","contentGutterX","contentGutterY","HeaderProps","action","length","color","severity","icon","size","onClose","join","alignItems","role","label","description","map","isMine","canManage","onReconnect","reconnecting","id","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,SAASA,cAAc,QAAQ,eAAc;AAC7C,OAAOC,yBAAyB,wDAAuD;AACvF,SAASC,WAAW,QAAQ,uBAAsB;AAClD,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,OAAO,QAAQ,iCAAgC;AACxD,SAASC,KAAK,EAAEC,MAAM,EAAEC,IAAI,EAAEC,gBAAgB,EAAEC,KAAK,EAAEC,UAAU,QAAQ,gBAAe;AACxF,SAASC,WAAW,EAAEC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAChE,SACEC,0BAA0B,QAGrB,8BAA0B;AAEjC,SAASC,uBAAuB,QAAQ,yBAAqB;AAC7D,SAASC,WAAW,QAAQ,oBAAgB;AAC5C,SAASC,qBAAqB,QAAQ,gCAA4B;AAClE,SAASC,oBAAoB,QAAQ,8BAA0B;AAS/D,MAAMC,YAAY,CAACC,MAAgBC,OAAOC,QAAQ,CAACC,MAAM,CAACH;AAE1D,uEAAuE,GACvE,OAAO,MAAMI,4BAA4B,sBAAqB;AAC9D,OAAO,MAAMC,+BAA+B,yBAAwB;AAEpE,0EAA0E,GAC1E,SAASC,mBAAmBC,MAAkC,EAAEC,QAAiC;IAC/F,MAAMC,OAAOD,aAAa,cAAc,cAAc;IACtD,IAAID,WAAW,iBAAiB,OAAO,GAAGE,KAAK,qDAAqD,CAAC;IACrG,IAAIF,WAAW,WAAW,OAAO;IACjC,OAAO,GAAGE,KAAK,8DAA8D,CAAC;AAChF;AAEA,kFAAkF,GAClF,SAASC,cAAcC,YAA0B,EAAEH,QAAiC;IAClF,IAAIG,aAAaC,MAAM,KAAK,SAAS,OAAO;IAC5C,gFAAgF;IAChF,OAAOD,aAAaE,SAAS,GAAGF,aAAaE,SAAS,CAACL,SAAS,KAAK,OAAOA,aAAa,YAAYG,aAAaG,UAAU;AAC9H;AAYA,sFAAsF,GACtF,SAASC;IACP,IAAI;QACFd,OAAOe,OAAO,CAACC,YAAY,CAAC,MAAM,IAAIhB,OAAOC,QAAQ,CAACgB,QAAQ,GAAGjB,OAAOC,QAAQ,CAACiB,MAAM;IACzF,EAAE,eAAM;IACN,qDAAqD;IACvD;AACF;AAEA,qEAAqE,GACrE,SAASC;IACP,IAAI;QACF,OAAOC,KAAKC,cAAc,GAAGC,eAAe,GAAGC,QAAQ,IAAIC;IAC7D,EAAE,eAAM;QACN,OAAOA;IACT;AACF;AAEA;;;;;;;;;;CAUC,GACD,OAAO,SAASC,yBAAyBC,KAAoC;;IAC3E,MAAM,EAAEC,KAAK,EAAEC,WAAW9B,SAAS,EAAE,GAAG4B;IACxC,MAAM,EAAEG,MAAMC,IAAI,EAAE,GAAGhD;IACvB,0EAA0E;IAC1E,qEAAqE;IACrE,MAAMiD,cAAMD,wBAAAA,KAAMC,GAAG,mBAAI;IACzB,MAAMC,MAAMpC,sBAAsB+B;IAClC,MAAMM,SAASpC,qBAAqB8B;IACpC,MAAM,EAAEO,eAAe,EAAE,GAAGrD;IAC5B,MAAM,CAAC6B,cAAcyB,gBAAgB,GAAG3C,SAAuB;QAAEmB,QAAQ;IAAU;IACnF,MAAM,CAACyB,UAAUC,YAAY,GAAG7C,SAA0B;IAC1D,MAAM,CAAC8C,YAAYC,cAAc,GAAG/C,SAAS;IAC7C,MAAMgD,gBAAgBjD,OAAO;IAE7B,yEAAyE;IACzE,gEAAgE;IAChED,UAAU;QACR,IAAIkD,cAAcC,OAAO,IAAI,CAACd,SAAS,CAACI,KAAK;QAC7C,MAAMW,WAAWjD,2BAA2BO,OAAOC,QAAQ,CAAC0C,IAAI;QAChEH,cAAcC,OAAO,GAAG;QACxB,IAAI,CAACC,UAAU;QACf5B;QACA,IAAI4B,SAASE,IAAI,KAAK,SAAS;gBACgDF;YAA7EL,YAAY;gBAAE1B,QAAQ;gBAAUkC,SAASxC,mBAAmBqC,SAASpC,MAAM,GAAEoC,qBAAAA,SAASnC,QAAQ,YAAjBmC,qBAAqB;YAAU;YAC5G;QACF;QACAL,YAAY;YAAE1B,QAAQ;QAAa;QACnCqB,IACGc,QAAQ,CAAC;YAAEC,MAAML,SAASK,IAAI;YAAEC,OAAON,SAASM,KAAK;YAAEC,UAAU9B;QAAkB,GACnF+B,IAAI,CAAC,CAACC,OACLd,YAAY;gBACV1B,QAAQ;gBACRyC,OAAOD,KAAKE,OAAO,CAACD,KAAK;gBACzBE,SAASH,KAAKG,OAAO;gBACrBC,kBAAkBJ,KAAKI,gBAAgB;YACzC,IAEDC,KAAK,CAAC,CAACC,QAAiBpB,YAAY;gBAAE1B,QAAQ;gBAAUkC,SAASY,MAAMZ,OAAO;YAAC;IACpF,GAAG;QAACb;QAAKL;QAAOI;KAAI;IAEpBzC,UAAU;QACR,IAAI,CAACqC,SAAS,CAACI,KAAK,OAAOP;QAC3B,IAAIiB,UAAU;QACdN,gBAAgB;YAAExB,QAAQ;QAAU;QACpCqB,IACGtB,YAAY,GACZwC,IAAI,CAAC,CAACQ,SAAWjB,WAAWN,gBAAgB;gBAAExB,QAAQ;eAAY+C,UAClEF,KAAK,CAAC,CAACC,QAAiBhB,WAAWN,gBAAgB;gBAAExB,QAAQ;gBAASkC,SAASY,MAAMZ,OAAO;YAAC;QAChG,OAAO;YACLJ,UAAU;QACZ;IACF,GAAG;QAACT;QAAKL;QAAOI;KAAI;IAEpB,MAAM4B,UAAUtE,YACd,OAAOkB,UAAmCqD;QACxCrB,cAAc;QACd,IAAI;YACFX,SAAS,MAAMI,IAAI2B,OAAO,CAAC;gBAAEpD;eAAcqD,YAAY;gBAAEA;YAAU,IAAI,CAAC;QAC1E,EAAE,OAAOH,OAAO;YACdlB,cAAc;YACdL,gBAAgB,AAACuB,MAAgBZ,OAAO,EAAE;gBAAEgB,SAAS;gBAASC,gBAAgB;YAAK;QACrF;IACF,GACA;QAAC9B;QAAKE;QAAiBN;KAAS;IAGlC,MAAMmC,cAActD,cAAcC,cAAc;IAChD,MAAMsD,iBAAiBvD,cAAcC,cAAc;IACnD,MAAMG,aAAakD,eAAeC;IAClC,MAAMC,eAAevD,aAAaC,MAAM,KAAK,WAAWD,aAAauD,YAAY;IACjF,MAAMC,+BACJ,MAAC/E;QAAMgF,WAAU;QAAMC,SAAS;QAAGC,IAAI;YAAEC,UAAU;YAAQC,gBAAgB;QAAS;;0BAClF,KAACvF;gBAAO6E,SAAQ;gBAAYW,UAAU,CAACT,eAAezB;gBAAYmC,SAAS,IAAM,KAAKd,QAAQ;0BAC3FxD;;0BAEH,KAACnB;gBAAO6E,SAAQ;gBAAWW,UAAU,CAACR,kBAAkB1B;gBAAYmC,SAAS,IAAM,KAAKd,QAAQ;0BAC7FvD;;;;IAIP,MAAMsE,YAAY,CAACrB,UACjBA,QAAQ9C,QAAQ,KAAK,cAAcoD,QAAQ,aAAaN,QAAQD,KAAK,IAAIO,QAAQ;IACnF,MAAMgB,eAAe,AAAC;QAAC;QAAU;KAAY,CAAWC,MAAM,CAAC,CAACrE,WAAa,CAACE,cAAcC,cAAcH;IAC1G,MAAMsE,OAAO5C,OAAO6C,SAAS,CAACF,MAAM,CAAC,CAACvB,UAAYA,QAAQ0B,cAAc,KAAKhD;IAC7E,MAAMiD,SAAS/C,OAAO6C,SAAS,CAACF,MAAM,CAAC,CAACvB,UAAYA,QAAQ0B,cAAc,KAAKhD;IAE/E,qBACE,MAAC5C;QAAMiF,SAAS;;0BACd,KAACxF;gBACCqG,QAAO;gBACPC,MAAMxG,eAAe,aAAa;oBAAEyG,QAAQ;gBAAqB;gBACjEC,cAAc;gBACdC,cAAc;gBACdC,aAAa;oBAAEC,QAAQtD,OAAO6C,SAAS,CAACU,MAAM,GAAGtB,iBAAiB1C;gBAAU;0BAE5E,cAAA,MAACrC;oBAAMiF,SAAS;;sCACd,KAAChF;4BAAWyE,SAAQ;4BAAQ4B,OAAM;sCAC/B,+FACC;;wBAEH/E,aAAaC,MAAM,KAAK,WAAWgE,aAAaa,MAAM,iBACrD,KAACzG;4BAAM2G,UAAS;sCACbf,aAAaa,MAAM,KAAK,IACrB,+DACAb,YAAY,CAAC,EAAE,KAAK,cAClB,6EACA;6BAEN;wBACHjE,aAAaC,MAAM,KAAK,wBAAU,KAAC5B;4BAAM2G,UAAS;sCAAShF,aAAamC,OAAO;6BAAY;wBAC3FT,CAAAA,4BAAAA,SAAUzB,MAAM,MAAK,6BACpB,KAAC5B;4BAAM2G,UAAS;4BAAOC,oBAAM,KAACzG;gCAAiB0G,MAAM;;sCAAQ;6BAG3D;wBACHxD,CAAAA,4BAAAA,SAAUzB,MAAM,MAAK,4BACpB,KAAC5B;4BAAM2G,UAAS;4BAAUG,SAAS,IAAMxD,YAAY;sCAClD,GAAGD,SAASkB,OAAO,GAAG,cAAc,cAAc,CAAC,EAAElB,SAASgB,KAAK,CAAC,CAAC,CAAC,GACpEhB,CAAAA,SAASmB,gBAAgB,CAACiC,MAAM,GAC7B,CAAC,UAAU,EAAEpD,SAASmB,gBAAgB,CAACuC,IAAI,CAAC,MAAM,aAAa,CAAC,GAChE,EAAC;6BAEP;wBACH1D,CAAAA,4BAAAA,SAAUzB,MAAM,MAAK,yBACpB,KAAC5B;4BAAM2G,UAAS;4BAAQG,SAAS,IAAMxD,YAAY;sCAChDD,SAASS,OAAO;6BAEjB;;;;YAIPZ,OAAOtB,MAAM,KAAK,0BACjB,MAACxB;gBAAMgF,WAAU;gBAAMC,SAAS;gBAAGC,IAAI;oBAAE0B,YAAY;gBAAS;gBAAGC,MAAK;;kCACpE,KAAC9G;wBAAiB0G,MAAM;;kCACxB,KAACxG;wBAAWyE,SAAQ;wBAAQ4B,OAAM;kCAAiB;;;iBAInD;YACHxD,OAAOtB,MAAM,KAAK,wBACjB,KAAC5B;gBAAM2G,UAAS;0BAAQ;iBACtB;YACHzD,OAAOtB,MAAM,KAAK,WAAW,CAACsB,OAAO6C,SAAS,CAACU,MAAM,iBACpD,KAACvG;gBAAK4E,SAAQ;0BACZ,cAAA,KAAClF;oBACCsH,OAAM;oBACNC,aACErF,aACI,0FACAW;oBAEN+D,QAAQ1E,aAAaqD,iBAAiB1C;;iBAGxC;YACH;mBAAIqD;mBAASG;aAAO,CAACmB,GAAG,CAAC,CAAC9C;gBACzB,MAAM+C,SAAS/C,QAAQ0B,cAAc,KAAKhD;gBAC1C,qBACE,KAACpC;oBAEC0D,SAASA;oBACT+C,QAAQA;oBACRC,WAAWD,UAAUnC;oBACrBjC,KAAKA;oBACLsE,aAAa,IAAM,KAAK5B,UAAUrB;oBAClCkD,cAAcjE,cAAc,CAAC7B,cAAcC,cAAc2C,QAAQ9C,QAAQ,KAAK,cAAc,cAAc;mBANrG8C,QAAQmD,EAAE;YASrB;YACCvE,OAAOtB,MAAM,KAAK,WAAWsB,OAAO6C,SAAS,CAACU,MAAM,iBAAG,KAAC9F;gBAAwBiC,OAAOA;iBAAY;;;AAG1G;AACAF,yBAAyBgF,WAAW,GAAG;AAEvC,eAAehF,yBAAwB"}
@@ -73,7 +73,7 @@ import { useOutreachSequence, useOutreachSequenceLinks } from "./use-outreach-da
73
73
  none: 'This sequence has no mailbox, so nothing is sent from it.',
74
74
  gone: 'This sequence’s mailbox is no longer connected, so nothing is sent from it.',
75
75
  paused: 'This sequence’s mailbox is paused, so nothing is sent until it is resumed.',
76
- reconnect_required: 'Google stopped accepting this sequence’s mailbox, so nothing is sent until it is reconnected.'
76
+ reconnect_required: 'The provider stopped accepting this sequence’s mailbox, so nothing is sent until it is reconnected.'
77
77
  };
78
78
  /** One person's page (AGL-3332): `…/sequences/{id}/enrollments/{enrollmentId}`. */ export function outreachEnrollmentPath(sectionPath, sequenceId, enrollmentId) {
79
79
  return `${sectionPath}/${sequenceId}/enrollments/${encodeURIComponent(enrollmentId)}`;