@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.
- package/README.md +10 -4
- package/package.json +14 -14
- package/src/lib/components/enrollment-detail.d.ts +8 -0
- package/src/lib/components/enrollment-detail.js +17 -5
- package/src/lib/components/enrollment-detail.js.map +1 -1
- package/src/lib/components/mailbox-card.d.ts +3 -3
- package/src/lib/components/mailbox-card.js +11 -5
- package/src/lib/components/mailbox-card.js.map +1 -1
- package/src/lib/components/mailboxes-section.d.ts +6 -5
- package/src/lib/components/mailboxes-section.js +61 -26
- package/src/lib/components/mailboxes-section.js.map +1 -1
- package/src/lib/components/sequence-detail.js +1 -1
- package/src/lib/components/sequence-detail.js.map +1 -1
- package/src/lib/components/sequence-editor.js +29 -4
- package/src/lib/components/sequence-editor.js.map +1 -1
- package/src/lib/components/sequence-mailbox-picker.d.ts +21 -0
- package/src/lib/components/sequence-mailbox-picker.js +74 -13
- package/src/lib/components/sequence-mailbox-picker.js.map +1 -1
- package/src/lib/components/use-outreach-mailbox-api.d.ts +10 -2
- package/src/lib/components/use-outreach-mailbox-api.js +7 -2
- package/src/lib/components/use-outreach-mailbox-api.js.map +1 -1
- package/src/lib/engine/enrollment-state.d.ts +6 -0
- package/src/lib/engine/enrollment-state.js +1 -1
- package/src/lib/engine/enrollment-state.js.map +1 -1
- package/src/lib/engine/index.d.ts +1 -0
- package/src/lib/engine/index.js +1 -0
- package/src/lib/engine/index.js.map +1 -1
- package/src/lib/engine/mailbox-notice.d.ts +5 -2
- package/src/lib/engine/mailbox-notice.js +6 -2
- package/src/lib/engine/mailbox-notice.js.map +1 -1
- package/src/lib/engine/mailbox-rotation.d.ts +41 -0
- package/src/lib/engine/mailbox-rotation.js +71 -0
- package/src/lib/engine/mailbox-rotation.js.map +1 -0
- package/src/lib/mailboxes/mailbox-api.d.ts +30 -11
- package/src/lib/mailboxes/mailbox-api.js +7 -3
- package/src/lib/mailboxes/mailbox-api.js.map +1 -1
- package/src/lib/mailboxes/mailbox-credentials.d.ts +15 -12
- package/src/lib/mailboxes/mailbox-credentials.js +12 -8
- package/src/lib/mailboxes/mailbox-credentials.js.map +1 -1
- package/src/lib/mailboxes/mailbox-erasure.js +3 -0
- package/src/lib/mailboxes/mailbox-erasure.js.map +1 -1
- package/src/lib/mailboxes/mailbox-revoke.d.ts +10 -5
- package/src/lib/mailboxes/mailbox-revoke.js +1 -0
- package/src/lib/mailboxes/mailbox-revoke.js.map +1 -1
- package/src/lib/mailboxes/mailbox-routes.d.ts +11 -3
- package/src/lib/mailboxes/mailbox-routes.js +218 -35
- package/src/lib/mailboxes/mailbox-routes.js.map +1 -1
- package/src/lib/mailboxes/mailbox-settings.d.ts +6 -2
- package/src/lib/mailboxes/mailbox-settings.js +5 -1
- package/src/lib/mailboxes/mailbox-settings.js.map +1 -1
- package/src/lib/mailboxes/mailbox-transport.d.ts +15 -9
- package/src/lib/mailboxes/mailbox-transport.js +47 -17
- package/src/lib/mailboxes/mailbox-transport.js.map +1 -1
- package/src/lib/mailboxes/oauth-state.d.ts +11 -3
- package/src/lib/mailboxes/oauth-state.js +17 -8
- package/src/lib/mailboxes/oauth-state.js.map +1 -1
- package/src/lib/mailboxes/outreach-config.d.ts +30 -0
- package/src/lib/mailboxes/outreach-config.js +53 -10
- package/src/lib/mailboxes/outreach-config.js.map +1 -1
- package/src/lib/mailboxes/register-mailbox-routes.js +2 -1
- package/src/lib/mailboxes/register-mailbox-routes.js.map +1 -1
- package/src/lib/model/outreach.types.d.ts +13 -2
- package/src/lib/model/outreach.types.js +7 -2
- package/src/lib/model/outreach.types.js.map +1 -1
- package/src/lib/model/sequence-draft.d.ts +6 -1
- package/src/lib/model/sequence-draft.js +16 -4
- package/src/lib/model/sequence-draft.js.map +1 -1
- package/src/lib/routes/enroll-routes.js +52 -1
- package/src/lib/routes/enroll-routes.js.map +1 -1
- package/src/lib/routes/sequence-routes.js +11 -3
- package/src/lib/routes/sequence-routes.js.map +1 -1
- package/src/lib/runtime/fixtures/fake-gmail.d.ts +18 -3
- package/src/lib/runtime/fixtures/fake-gmail.js +21 -1
- package/src/lib/runtime/fixtures/fake-gmail.js.map +1 -1
- package/src/lib/runtime/mailbox-notices.js +2 -2
- package/src/lib/runtime/mailbox-notices.js.map +1 -1
- package/src/lib/runtime/send-job.js +2 -8
- package/src/lib/runtime/send-job.js.map +1 -1
- package/src/lib/runtime/sync-job.js +24 -11
- package/src/lib/runtime/sync-job.js.map +1 -1
- package/src/lib/subprocessors.d.ts +12 -1
- package/src/lib/subprocessors.js +25 -2
- package/src/lib/subprocessors.js.map +1 -1
- package/src/lib/transfer/sequences-package.js +7 -2
- package/src/lib/transfer/sequences-package.js.map +1 -1
- package/src/lib/transport/gmail-client.d.ts +4 -11
- package/src/lib/transport/gmail-client.js +42 -17
- package/src/lib/transport/gmail-client.js.map +1 -1
- package/src/lib/transport/graph-client.d.ts +87 -0
- package/src/lib/transport/graph-client.js +359 -0
- package/src/lib/transport/graph-client.js.map +1 -0
- package/src/lib/transport/mail-client.d.ts +138 -0
- package/src/lib/transport/mail-client.js +34 -0
- package/src/lib/transport/mail-client.js.map +1 -0
- package/src/lib/transport/microsoft-errors.d.ts +32 -0
- package/src/lib/transport/microsoft-errors.js +94 -0
- package/src/lib/transport/microsoft-errors.js.map +1 -0
- package/src/lib/transport/microsoft-oauth.d.ts +140 -0
- package/src/lib/transport/microsoft-oauth.js +225 -0
- package/src/lib/transport/microsoft-oauth.js.map +1 -0
- package/src/lib/transport/mime-message.d.ts +30 -0
- package/src/lib/transport/mime-message.js +235 -0
- package/src/lib/transport/mime-message.js.map +1 -0
- package/src/lib/transport/send-message.d.ts +15 -8
- package/src/lib/transport/send-message.js +4 -3
- package/src/lib/transport/send-message.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/sequence-detail.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { consentGroupForHost } from '@aglyn/aglyn/app-utils/consent-groups'\nimport type { ConsolePluginOrgMount } from '@aglyn/aglyn'\nimport {\n mdiAccountMultiplePlusOutline,\n mdiChevronLeft,\n} from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Button,\n Card,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n Stack,\n Tab,\n Tabs,\n Typography,\n} from '@mui/material'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport type { ListFilterClause } from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport { useMemo, useState } from 'react'\nimport { validateOutreachOrgSettings } from '../engine/sequence-validation'\nimport type { OutreachSequenceAction } from '../model/outreach-api'\nimport type { OutreachEnrollment } from '../model/outreach.types'\nimport { outreachSequenceLinkReport } from '../model/sequence-report'\nimport {\n outreachMailboxActivationIssue,\n outreachSequenceMailboxState,\n type OutreachSequenceIssue,\n type OutreachSequenceMailboxState,\n} from '../model/sequence-draft'\nimport { OutreachEnrollDialog } from './enroll-dialog'\nimport {\n outreachClauseLivesInUrl,\n outreachEnrollmentFilterSearch,\n outreachEnrollmentsFilterHref,\n outreachEnrollmentUrlClauses,\n} from './enrollment-filter-params'\nimport { OutreachEnrollmentsTable } from './enrollments-table'\nimport {\n OutreachLink,\n OutreachLoading,\n OutreachLoadProblem,\n OutreachSequenceStatusChip,\n useOutreachNavigate,\n} from './outreach-ui'\nimport { OutreachSequenceEditor } from './sequence-editor'\nimport { OutreachSequenceReportCard } from './sequence-report-card'\nimport { OutreachRouteError, useOutreachApi } from './use-outreach-api'\nimport {\n useOutreachSequence,\n useOutreachSequenceLinks,\n} from './use-outreach-data'\nimport type { OutreachMailboxesResult } from './use-outreach-mailboxes'\nimport type { OutreachSettingsLoad } from './use-outreach-settings'\n\nexport type OutreachSequenceTab = 'steps' | 'enrollments'\n\nexport interface OutreachSequenceDetailProps {\n orgId: string\n orgMount?: ConsolePluginOrgMount\n /** The organization document the shell loaded: whose consent groups name a site's contacts. */\n org?: Record<string, unknown> | null\n /** Where the Sequences section lives: `/[orgSlug]/outreach/sequences`. */\n sectionPath: string\n sequenceId: string\n tab: OutreachSequenceTab\n settings: OutreachSettingsLoad\n mailboxes: OutreachMailboxesResult\n /** The Mailboxes section: where a mailbox is connected, resumed or reconnected. */\n mailboxesPath: string\n /** The Compliance section: where the footer's legal name and address are set. */\n compliancePath: string\n}\n\n/** Something activation would refuse, and where it is put right. */\nexport interface OutreachActivationBlocker {\n message: string\n href: string\n linkLabel: string\n}\n\n/**\n * What stops a sequence being activated, read before anyone clicks: its\n * mailbox not sending, and a footer the organization cannot write yet —\n * each in the words the status route refuses with. Only a finished read\n * says something is missing, so nothing is claimed while one is loading.\n */\nexport function outreachActivationBlockers(input: {\n sequence: { mailboxId: string }\n mailboxes: OutreachMailboxesResult\n settings: OutreachSettingsLoad\n paths: { steps: string; mailboxes: string; compliance: string }\n}): OutreachActivationBlocker[] {\n const blockers: OutreachActivationBlocker[] = []\n if (input.mailboxes.status === 'ready') {\n const mailbox =\n input.mailboxes.mailboxes.find((entry) => entry.id === input.sequence.mailboxId) ?? null\n const issue = outreachMailboxActivationIssue(input.sequence.mailboxId, mailbox)\n if (issue) {\n blockers.push(\n issue.code === 'mailbox_not_sending'\n ? { message: issue.message, href: input.paths.mailboxes, linkLabel: 'Open Mailboxes' }\n : { message: issue.message, href: input.paths.steps, linkLabel: 'Choose a mailbox' },\n )\n }\n }\n if (input.settings.status === 'ready') {\n for (const issue of validateOutreachOrgSettings(input.settings.settings)) {\n blockers.push({ message: issue.message, href: input.paths.compliance, linkLabel: 'Open Compliance' })\n }\n }\n return blockers\n}\n\n/** What an active sequence's page says while its mailbox is not sending. */\nconst NOT_SENDING: Record<Exclude<OutreachSequenceMailboxState, 'sending'>, string> = {\n none: 'This sequence has no mailbox, so nothing is sent from it.',\n gone: 'This sequence’s mailbox is no longer connected, so nothing is sent from it.',\n paused: 'This sequence’s mailbox is paused, so nothing is sent until it is resumed.',\n reconnect_required:\n 'Google stopped accepting this sequence’s mailbox, so nothing is sent until it is reconnected.',\n}\n\n/** One person's page (AGL-3332): `…/sequences/{id}/enrollments/{enrollmentId}`. */\nexport function outreachEnrollmentPath(\n sectionPath: string,\n sequenceId: string,\n enrollmentId: string,\n): string {\n return `${sectionPath}/${sequenceId}/enrollments/${encodeURIComponent(enrollmentId)}`\n}\n\n/** The words an action's button and its snackbar use. */\nconst ACTIONS: Record<OutreachSequenceAction, { label: string; done: string }> =\n {\n activate: { label: 'Activate', done: 'Sequence activated.' },\n pause: { label: 'Pause', done: 'Sequence paused.' },\n archive: { label: 'Archive', done: 'Sequence archived.' },\n }\n\n/**\n * One sequence (AGL-2980): its steps in the editor, the people enrolled in\n * it, and what can be done with it — activate, pause, archive, delete a\n * draft, and enroll people in an active one.\n */\nexport function OutreachSequenceDetail(props: OutreachSequenceDetailProps) {\n const { orgId, sequenceId, sectionPath } = props\n const api = useOutreachApi(orgId)\n const navigate = useOutreachNavigate()\n const { enqueueSnackbar } = useSnackbar()\n const { data: user } = useUser()\n const loaded = useOutreachSequence(orgId, sequenceId)\n // One document however large the sequence, and read on both tabs, because\n // the report card sits above them (AGL-3239).\n const links = useOutreachSequenceLinks(orgId, sequenceId)\n const [busy, setBusy] = useState(false)\n const [refusal, setRefusal] = useState<{\n message: string\n issues: OutreachSequenceIssue[]\n } | null>(null)\n const [confirming, setConfirming] = useState<'archive' | 'delete' | null>(\n null,\n )\n const [enrolling, setEnrolling] = useState(false)\n\n /*\n * The enrollments table's filter (AGL-3332). \"Who clicked\" and \"who\n * followed this destination\" live in the URL, where the Results card\n * sets them and where back from a person finds them again; every other\n * clause the panel sets is the page's own.\n */\n const router = useRouter()\n const pathname = usePathname()\n const searchParams = useSearchParams()\n const search = searchParams?.toString() ?? ''\n const urlClauses = useMemo(\n () => outreachEnrollmentUrlClauses(new URLSearchParams(search)),\n [search],\n )\n const [ownClauses, setOwnClauses] = useState<ListFilterClause[]>([])\n const clauses = useMemo(() => [...ownClauses, ...urlClauses], [ownClauses, urlClauses])\n const setClauses = (next: ListFilterClause[]) => {\n setOwnClauses(next.filter((clause) => !outreachClauseLivesInUrl(clause)))\n const nextSearch = outreachEnrollmentFilterSearch(next, search)\n if (nextSearch !== search) {\n router.replace(nextSearch ? `${pathname}?${nextSearch}` : pathname, { scroll: false })\n }\n }\n const linkOptions = useMemo(\n () =>\n outreachSequenceLinkReport(\n links.status === 'ready' ? (links.data ?? undefined) : undefined,\n ).rows.map((row) => ({ value: row.url, label: row.url })),\n [links],\n )\n\n const sequence = loaded.data\n const detailPath = `${sectionPath}/${sequenceId}`\n const enrollmentsPath = `${detailPath}/enrollments`\n const enrollmentHref = (enrollment: OutreachEnrollment) =>\n outreachEnrollmentPath(sectionPath, sequenceId, enrollment.id)\n const back = (\n <OutreachLink href={sectionPath}>\n <Stack\n direction=\"row\"\n spacing={0.5}\n component=\"span\"\n sx={{ alignItems: 'center', display: 'inline-flex' }}\n >\n <MdiIcon path={mdiChevronLeft.path} fontSize=\"small\" />\n <span>Sequences</span>\n </Stack>\n </OutreachLink>\n )\n\n if (loaded.status === 'loading')\n return <OutreachLoading label=\"Loading the sequence…\" />\n if (loaded.status === 'error' || loaded.status === 'refused') {\n return <OutreachLoadProblem status={loaded.status} what=\"sequence\" />\n }\n if (!sequence) {\n return (\n <Stack spacing={2}>\n {back}\n <Card variant=\"outlined\">\n <EmptyStateComponent label=\"This sequence no longer exists\" />\n </Card>\n </Stack>\n )\n }\n\n const mailbox =\n props.mailboxes.mailboxes.find((entry) => entry.id === sequence.mailboxId) ??\n null\n const mailboxState =\n props.mailboxes.status === 'ready'\n ? outreachSequenceMailboxState(sequence.mailboxId, mailbox)\n : 'sending'\n const activatable = sequence.status === 'draft' || sequence.status === 'paused'\n const blockers = activatable\n ? outreachActivationBlockers({\n sequence,\n mailboxes: props.mailboxes,\n settings: props.settings,\n paths: {\n steps: detailPath,\n mailboxes: props.mailboxesPath,\n compliance: props.compliancePath,\n },\n })\n : []\n // Enrolling onto a mailbox that is gone is refused by the route; a paused\n // one only makes the new people wait with everyone else.\n const canEnroll =\n sequence.status === 'active' &&\n mailboxState !== 'gone' &&\n mailboxState !== 'none'\n const act = async (action: OutreachSequenceAction) => {\n setBusy(true)\n setRefusal(null)\n try {\n const answer = await api.setSequenceStatus(sequence.id, action)\n enqueueSnackbar(\n action === 'archive' && answer.stoppedEnrollments\n ? `${ACTIONS.archive.done} ${answer.stoppedEnrollments} ${answer.stoppedEnrollments === 1 ? 'person was' : 'people were'} stopped.`\n : ACTIONS[action].done,\n { variant: 'success' },\n )\n } catch (error) {\n setRefusal({\n message: (error as Error).message,\n issues:\n error instanceof OutreachRouteError\n ? error.issues.filter(\n (issue): issue is OutreachSequenceIssue => 'path' in issue,\n )\n : [],\n })\n } finally {\n setBusy(false)\n }\n }\n const remove = async () => {\n setBusy(true)\n setRefusal(null)\n try {\n await api.deleteSequence(sequence.id)\n enqueueSnackbar('Sequence deleted.', { variant: 'success' })\n navigate(sectionPath)\n } catch (error) {\n setRefusal({ message: (error as Error).message, issues: [] })\n setBusy(false)\n }\n }\n\n const enrollButton = (\n <Button\n variant=\"contained\"\n startIcon={\n <MdiIcon path={mdiAccountMultiplePlusOutline.path} fontSize=\"small\" />\n }\n disabled={!canEnroll}\n onClick={() => setEnrolling(true)}\n >\n Enroll people\n </Button>\n )\n\n return (\n <Stack spacing={2}>\n {back}\n <Stack\n direction={{ xs: 'column', md: 'row' }}\n spacing={1.5}\n sx={{ alignItems: { md: 'center' }, justifyContent: 'space-between' }}\n >\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', minWidth: 0 }}\n >\n <Typography\n variant=\"h5\"\n component=\"h2\"\n sx={{ wordBreak: 'break-word' }}\n >\n {sequence.name}\n </Typography>\n <OutreachSequenceStatusChip status={sequence.status} />\n </Stack>\n <Stack direction=\"row\" spacing={1} sx={{ flexWrap: 'wrap', rowGap: 1 }}>\n {activatable ? (\n <Button\n variant=\"outlined\"\n disabled={busy || blockers.length > 0}\n onClick={() => void act('activate')}\n >\n {ACTIONS.activate.label}\n </Button>\n ) : null}\n {sequence.status === 'active' ? (\n <Button\n variant=\"outlined\"\n disabled={busy}\n onClick={() => void act('pause')}\n >\n {ACTIONS.pause.label}\n </Button>\n ) : null}\n {sequence.status !== 'archived' ? (\n <Button\n variant=\"outlined\"\n color=\"error\"\n disabled={busy}\n onClick={() => setConfirming('archive')}\n >\n {ACTIONS.archive.label}\n </Button>\n ) : null}\n {sequence.status === 'draft' ? (\n <Button\n variant=\"text\"\n color=\"error\"\n disabled={busy}\n onClick={() => setConfirming('delete')}\n >\n Delete\n </Button>\n ) : null}\n {sequence.status === 'active' ? enrollButton : null}\n </Stack>\n </Stack>\n\n {refusal ? (\n <Alert severity=\"error\" onClose={() => setRefusal(null)}>\n <Stack spacing={0.5}>\n <span>{refusal.message}</span>\n {refusal.issues.length > 1 ? (\n <Stack component=\"ul\" spacing={0.25} sx={{ m: 0, pl: 2.5 }}>\n {refusal.issues.slice(1).map((issue) => (\n <li key={`${issue.path}:${issue.code}`}>{issue.message}</li>\n ))}\n </Stack>\n ) : null}\n </Stack>\n </Alert>\n ) : null}\n {blockers.length ? (\n <Alert severity=\"warning\" data-testid=\"outreach-activation-blockers\">\n <Stack spacing={0.5}>\n <span>\n {sequence.status === 'draft'\n ? 'A draft sends nothing, and this one can’t be activated yet:'\n : 'This sequence can’t be activated again yet:'}\n </span>\n <Stack component=\"ul\" spacing={0.25} sx={{ m: 0, pl: 2.5 }}>\n {blockers.map((blocker) => (\n <li key={blocker.message}>\n {blocker.message}{' '}\n <OutreachLink href={blocker.href}>{blocker.linkLabel}</OutreachLink>\n </li>\n ))}\n </Stack>\n </Stack>\n </Alert>\n ) : sequence.status === 'draft' ? (\n <Alert severity=\"info\">\n A draft sends nothing. Activate it to enroll people.\n </Alert>\n ) : null}\n {sequence.status === 'active' && mailboxState !== 'sending' ? (\n <Alert severity=\"warning\">\n {NOT_SENDING[mailboxState]}{' '}\n <OutreachLink href={props.mailboxesPath}>Open Mailboxes</OutreachLink>\n </Alert>\n ) : null}\n\n {/*\n * Above the tabs, not inside one (AGL-3239): what a sequence is doing\n * is the question a rep opens it with, and putting it behind a tab\n * makes the steps the first answer to \"how is this going\".\n *\n * A draft has sent nothing and measured nothing, so it gets no card\n * rather than a row of zeroes.\n */}\n {sequence.status === 'draft' ? null : (\n <OutreachSequenceReportCard\n sequence={sequence}\n links={links}\n timeZone={mailbox?.timezone ?? null}\n // Each leads to the people behind it, on the Enrollments tab's own\n // filter (AGL-3332).\n onShowClickers={() =>\n navigate(outreachEnrollmentsFilterHref(enrollmentsPath, { clicked: true }))\n }\n onShowLink={(url) =>\n navigate(outreachEnrollmentsFilterHref(enrollmentsPath, { link: url }))\n }\n />\n )}\n\n <Tabs\n value={props.tab}\n onChange={(_event, next: OutreachSequenceTab) =>\n navigate(next === 'steps' ? detailPath : enrollmentsPath)\n }\n aria-label=\"Sequence\"\n >\n <Tab value=\"steps\" label=\"Steps\" />\n <Tab value=\"enrollments\" label=\"Enrollments\" />\n </Tabs>\n\n {props.tab === 'steps' ? (\n <OutreachSequenceEditor\n orgId={orgId}\n orgMount={props.orgMount}\n org={props.org}\n sequence={sequence}\n settings={props.settings}\n mailboxes={props.mailboxes}\n mailboxesPath={props.mailboxesPath}\n onSaved={() => undefined}\n />\n ) : (\n <OutreachEnrollmentsTable\n orgId={orgId}\n sequenceId={sequence.id}\n steps={sequence.steps}\n // A sequence that counted clicks once has them to show, whether or\n // not it counts them now.\n trackClicks={sequence.settings.trackClicks || sequence.stats?.clickTracked === true}\n // The same for opens (AGL-3488).\n countOpens={sequence.settings.countOpens || sequence.stats?.openTracked === true}\n timeZone={mailbox?.timezone ?? null}\n mailbox={props.mailboxes.status === 'ready' ? mailbox : undefined}\n sequence={sequence}\n api={api}\n enrollAction={sequence.status === 'active' ? enrollButton : undefined}\n onOpen={(enrollment) => navigate(enrollmentHref(enrollment))}\n hrefFor={enrollmentHref}\n clauses={clauses}\n onClausesChange={setClauses}\n linkOptions={linkOptions}\n />\n )}\n\n <OutreachEnrollDialog\n open={enrolling}\n onClose={() => setEnrolling(false)}\n orgId={orgId}\n sequence={sequence}\n contactGroupId={\n sequence.hostId\n ? consentGroupForHost(props.org ?? null, sequence.hostId).groupId\n : ''\n }\n uid={user?.uid ?? null}\n api={api}\n />\n\n <Dialog\n open={Boolean(confirming)}\n onClose={() => setConfirming(null)}\n fullWidth\n maxWidth=\"xs\"\n >\n <DialogTitle>\n {confirming === 'delete'\n ? 'Delete this draft?'\n : 'Archive this sequence?'}\n </DialogTitle>\n <DialogContent>\n <DialogContentText>\n {confirming === 'delete'\n ? 'It is removed for good. Nobody was ever enrolled in it.'\n : 'Archiving is final. Everyone still in it is stopped, and it takes no one new.'}\n </DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setConfirming(null)}>Cancel</Button>\n <Button\n color=\"error\"\n variant=\"contained\"\n onClick={() => {\n const chosen = confirming\n setConfirming(null)\n if (chosen === 'delete') void remove()\n else void act('archive')\n }}\n >\n {confirming === 'delete' ? 'Delete' : 'Archive'}\n </Button>\n </DialogActions>\n </Dialog>\n </Stack>\n )\n}\nOutreachSequenceDetail.displayName = 'OutreachSequenceDetail'\n\nexport default OutreachSequenceDetail\n"],"names":["consentGroupForHost","mdiAccountMultiplePlusOutline","mdiChevronLeft","MdiIcon","useSnackbar","useUser","Alert","Button","Card","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","Stack","Tab","Tabs","Typography","EmptyStateComponent","usePathname","useRouter","useSearchParams","useMemo","useState","validateOutreachOrgSettings","outreachSequenceLinkReport","outreachMailboxActivationIssue","outreachSequenceMailboxState","OutreachEnrollDialog","outreachClauseLivesInUrl","outreachEnrollmentFilterSearch","outreachEnrollmentsFilterHref","outreachEnrollmentUrlClauses","OutreachEnrollmentsTable","OutreachLink","OutreachLoading","OutreachLoadProblem","OutreachSequenceStatusChip","useOutreachNavigate","OutreachSequenceEditor","OutreachSequenceReportCard","OutreachRouteError","useOutreachApi","useOutreachSequence","useOutreachSequenceLinks","outreachActivationBlockers","input","blockers","mailboxes","status","mailbox","find","entry","id","sequence","mailboxId","issue","push","code","message","href","paths","linkLabel","steps","settings","compliance","NOT_SENDING","none","gone","paused","reconnect_required","outreachEnrollmentPath","sectionPath","sequenceId","enrollmentId","encodeURIComponent","ACTIONS","activate","label","done","pause","archive","OutreachSequenceDetail","props","orgId","api","navigate","enqueueSnackbar","data","user","loaded","links","busy","setBusy","refusal","setRefusal","confirming","setConfirming","enrolling","setEnrolling","router","pathname","searchParams","search","toString","urlClauses","URLSearchParams","ownClauses","setOwnClauses","clauses","setClauses","next","filter","clause","nextSearch","replace","scroll","linkOptions","undefined","rows","map","row","value","url","detailPath","enrollmentsPath","enrollmentHref","enrollment","back","direction","spacing","component","sx","alignItems","display","path","fontSize","span","what","variant","mailboxState","activatable","mailboxesPath","compliancePath","canEnroll","act","action","answer","setSequenceStatus","stoppedEnrollments","error","issues","remove","deleteSequence","enrollButton","startIcon","disabled","onClick","xs","md","justifyContent","minWidth","wordBreak","name","flexWrap","rowGap","length","color","severity","onClose","m","pl","slice","li","data-testid","blocker","timeZone","timezone","onShowClickers","clicked","onShowLink","link","tab","onChange","_event","aria-label","orgMount","org","onSaved","trackClicks","stats","clickTracked","countOpens","openTracked","enrollAction","onOpen","hrefFor","onClausesChange","open","contactGroupId","hostId","groupId","uid","Boolean","fullWidth","maxWidth","chosen","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/sequence-detail.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { consentGroupForHost } from '@aglyn/aglyn/app-utils/consent-groups'\nimport type { ConsolePluginOrgMount } from '@aglyn/aglyn'\nimport {\n mdiAccountMultiplePlusOutline,\n mdiChevronLeft,\n} from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Button,\n Card,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n Stack,\n Tab,\n Tabs,\n Typography,\n} from '@mui/material'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport type { ListFilterClause } from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport { useMemo, useState } from 'react'\nimport { validateOutreachOrgSettings } from '../engine/sequence-validation'\nimport type { OutreachSequenceAction } from '../model/outreach-api'\nimport type { OutreachEnrollment } from '../model/outreach.types'\nimport { outreachSequenceLinkReport } from '../model/sequence-report'\nimport {\n outreachMailboxActivationIssue,\n outreachSequenceMailboxState,\n type OutreachSequenceIssue,\n type OutreachSequenceMailboxState,\n} from '../model/sequence-draft'\nimport { OutreachEnrollDialog } from './enroll-dialog'\nimport {\n outreachClauseLivesInUrl,\n outreachEnrollmentFilterSearch,\n outreachEnrollmentsFilterHref,\n outreachEnrollmentUrlClauses,\n} from './enrollment-filter-params'\nimport { OutreachEnrollmentsTable } from './enrollments-table'\nimport {\n OutreachLink,\n OutreachLoading,\n OutreachLoadProblem,\n OutreachSequenceStatusChip,\n useOutreachNavigate,\n} from './outreach-ui'\nimport { OutreachSequenceEditor } from './sequence-editor'\nimport { OutreachSequenceReportCard } from './sequence-report-card'\nimport { OutreachRouteError, useOutreachApi } from './use-outreach-api'\nimport {\n useOutreachSequence,\n useOutreachSequenceLinks,\n} from './use-outreach-data'\nimport type { OutreachMailboxesResult } from './use-outreach-mailboxes'\nimport type { OutreachSettingsLoad } from './use-outreach-settings'\n\nexport type OutreachSequenceTab = 'steps' | 'enrollments'\n\nexport interface OutreachSequenceDetailProps {\n orgId: string\n orgMount?: ConsolePluginOrgMount\n /** The organization document the shell loaded: whose consent groups name a site's contacts. */\n org?: Record<string, unknown> | null\n /** Where the Sequences section lives: `/[orgSlug]/outreach/sequences`. */\n sectionPath: string\n sequenceId: string\n tab: OutreachSequenceTab\n settings: OutreachSettingsLoad\n mailboxes: OutreachMailboxesResult\n /** The Mailboxes section: where a mailbox is connected, resumed or reconnected. */\n mailboxesPath: string\n /** The Compliance section: where the footer's legal name and address are set. */\n compliancePath: string\n}\n\n/** Something activation would refuse, and where it is put right. */\nexport interface OutreachActivationBlocker {\n message: string\n href: string\n linkLabel: string\n}\n\n/**\n * What stops a sequence being activated, read before anyone clicks: its\n * mailbox not sending, and a footer the organization cannot write yet —\n * each in the words the status route refuses with. Only a finished read\n * says something is missing, so nothing is claimed while one is loading.\n */\nexport function outreachActivationBlockers(input: {\n sequence: { mailboxId: string }\n mailboxes: OutreachMailboxesResult\n settings: OutreachSettingsLoad\n paths: { steps: string; mailboxes: string; compliance: string }\n}): OutreachActivationBlocker[] {\n const blockers: OutreachActivationBlocker[] = []\n if (input.mailboxes.status === 'ready') {\n const mailbox =\n input.mailboxes.mailboxes.find((entry) => entry.id === input.sequence.mailboxId) ?? null\n const issue = outreachMailboxActivationIssue(input.sequence.mailboxId, mailbox)\n if (issue) {\n blockers.push(\n issue.code === 'mailbox_not_sending'\n ? { message: issue.message, href: input.paths.mailboxes, linkLabel: 'Open Mailboxes' }\n : { message: issue.message, href: input.paths.steps, linkLabel: 'Choose a mailbox' },\n )\n }\n }\n if (input.settings.status === 'ready') {\n for (const issue of validateOutreachOrgSettings(input.settings.settings)) {\n blockers.push({ message: issue.message, href: input.paths.compliance, linkLabel: 'Open Compliance' })\n }\n }\n return blockers\n}\n\n/** What an active sequence's page says while its mailbox is not sending. */\nconst NOT_SENDING: Record<Exclude<OutreachSequenceMailboxState, 'sending'>, string> = {\n none: 'This sequence has no mailbox, so nothing is sent from it.',\n gone: 'This sequence’s mailbox is no longer connected, so nothing is sent from it.',\n paused: 'This sequence’s mailbox is paused, so nothing is sent until it is resumed.',\n reconnect_required:\n 'The provider stopped accepting this sequence’s mailbox, so nothing is sent until it is reconnected.',\n}\n\n/** One person's page (AGL-3332): `…/sequences/{id}/enrollments/{enrollmentId}`. */\nexport function outreachEnrollmentPath(\n sectionPath: string,\n sequenceId: string,\n enrollmentId: string,\n): string {\n return `${sectionPath}/${sequenceId}/enrollments/${encodeURIComponent(enrollmentId)}`\n}\n\n/** The words an action's button and its snackbar use. */\nconst ACTIONS: Record<OutreachSequenceAction, { label: string; done: string }> =\n {\n activate: { label: 'Activate', done: 'Sequence activated.' },\n pause: { label: 'Pause', done: 'Sequence paused.' },\n archive: { label: 'Archive', done: 'Sequence archived.' },\n }\n\n/**\n * One sequence (AGL-2980): its steps in the editor, the people enrolled in\n * it, and what can be done with it — activate, pause, archive, delete a\n * draft, and enroll people in an active one.\n */\nexport function OutreachSequenceDetail(props: OutreachSequenceDetailProps) {\n const { orgId, sequenceId, sectionPath } = props\n const api = useOutreachApi(orgId)\n const navigate = useOutreachNavigate()\n const { enqueueSnackbar } = useSnackbar()\n const { data: user } = useUser()\n const loaded = useOutreachSequence(orgId, sequenceId)\n // One document however large the sequence, and read on both tabs, because\n // the report card sits above them (AGL-3239).\n const links = useOutreachSequenceLinks(orgId, sequenceId)\n const [busy, setBusy] = useState(false)\n const [refusal, setRefusal] = useState<{\n message: string\n issues: OutreachSequenceIssue[]\n } | null>(null)\n const [confirming, setConfirming] = useState<'archive' | 'delete' | null>(\n null,\n )\n const [enrolling, setEnrolling] = useState(false)\n\n /*\n * The enrollments table's filter (AGL-3332). \"Who clicked\" and \"who\n * followed this destination\" live in the URL, where the Results card\n * sets them and where back from a person finds them again; every other\n * clause the panel sets is the page's own.\n */\n const router = useRouter()\n const pathname = usePathname()\n const searchParams = useSearchParams()\n const search = searchParams?.toString() ?? ''\n const urlClauses = useMemo(\n () => outreachEnrollmentUrlClauses(new URLSearchParams(search)),\n [search],\n )\n const [ownClauses, setOwnClauses] = useState<ListFilterClause[]>([])\n const clauses = useMemo(() => [...ownClauses, ...urlClauses], [ownClauses, urlClauses])\n const setClauses = (next: ListFilterClause[]) => {\n setOwnClauses(next.filter((clause) => !outreachClauseLivesInUrl(clause)))\n const nextSearch = outreachEnrollmentFilterSearch(next, search)\n if (nextSearch !== search) {\n router.replace(nextSearch ? `${pathname}?${nextSearch}` : pathname, { scroll: false })\n }\n }\n const linkOptions = useMemo(\n () =>\n outreachSequenceLinkReport(\n links.status === 'ready' ? (links.data ?? undefined) : undefined,\n ).rows.map((row) => ({ value: row.url, label: row.url })),\n [links],\n )\n\n const sequence = loaded.data\n const detailPath = `${sectionPath}/${sequenceId}`\n const enrollmentsPath = `${detailPath}/enrollments`\n const enrollmentHref = (enrollment: OutreachEnrollment) =>\n outreachEnrollmentPath(sectionPath, sequenceId, enrollment.id)\n const back = (\n <OutreachLink href={sectionPath}>\n <Stack\n direction=\"row\"\n spacing={0.5}\n component=\"span\"\n sx={{ alignItems: 'center', display: 'inline-flex' }}\n >\n <MdiIcon path={mdiChevronLeft.path} fontSize=\"small\" />\n <span>Sequences</span>\n </Stack>\n </OutreachLink>\n )\n\n if (loaded.status === 'loading')\n return <OutreachLoading label=\"Loading the sequence…\" />\n if (loaded.status === 'error' || loaded.status === 'refused') {\n return <OutreachLoadProblem status={loaded.status} what=\"sequence\" />\n }\n if (!sequence) {\n return (\n <Stack spacing={2}>\n {back}\n <Card variant=\"outlined\">\n <EmptyStateComponent label=\"This sequence no longer exists\" />\n </Card>\n </Stack>\n )\n }\n\n const mailbox =\n props.mailboxes.mailboxes.find((entry) => entry.id === sequence.mailboxId) ??\n null\n const mailboxState =\n props.mailboxes.status === 'ready'\n ? outreachSequenceMailboxState(sequence.mailboxId, mailbox)\n : 'sending'\n const activatable = sequence.status === 'draft' || sequence.status === 'paused'\n const blockers = activatable\n ? outreachActivationBlockers({\n sequence,\n mailboxes: props.mailboxes,\n settings: props.settings,\n paths: {\n steps: detailPath,\n mailboxes: props.mailboxesPath,\n compliance: props.compliancePath,\n },\n })\n : []\n // Enrolling onto a mailbox that is gone is refused by the route; a paused\n // one only makes the new people wait with everyone else.\n const canEnroll =\n sequence.status === 'active' &&\n mailboxState !== 'gone' &&\n mailboxState !== 'none'\n const act = async (action: OutreachSequenceAction) => {\n setBusy(true)\n setRefusal(null)\n try {\n const answer = await api.setSequenceStatus(sequence.id, action)\n enqueueSnackbar(\n action === 'archive' && answer.stoppedEnrollments\n ? `${ACTIONS.archive.done} ${answer.stoppedEnrollments} ${answer.stoppedEnrollments === 1 ? 'person was' : 'people were'} stopped.`\n : ACTIONS[action].done,\n { variant: 'success' },\n )\n } catch (error) {\n setRefusal({\n message: (error as Error).message,\n issues:\n error instanceof OutreachRouteError\n ? error.issues.filter(\n (issue): issue is OutreachSequenceIssue => 'path' in issue,\n )\n : [],\n })\n } finally {\n setBusy(false)\n }\n }\n const remove = async () => {\n setBusy(true)\n setRefusal(null)\n try {\n await api.deleteSequence(sequence.id)\n enqueueSnackbar('Sequence deleted.', { variant: 'success' })\n navigate(sectionPath)\n } catch (error) {\n setRefusal({ message: (error as Error).message, issues: [] })\n setBusy(false)\n }\n }\n\n const enrollButton = (\n <Button\n variant=\"contained\"\n startIcon={\n <MdiIcon path={mdiAccountMultiplePlusOutline.path} fontSize=\"small\" />\n }\n disabled={!canEnroll}\n onClick={() => setEnrolling(true)}\n >\n Enroll people\n </Button>\n )\n\n return (\n <Stack spacing={2}>\n {back}\n <Stack\n direction={{ xs: 'column', md: 'row' }}\n spacing={1.5}\n sx={{ alignItems: { md: 'center' }, justifyContent: 'space-between' }}\n >\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', minWidth: 0 }}\n >\n <Typography\n variant=\"h5\"\n component=\"h2\"\n sx={{ wordBreak: 'break-word' }}\n >\n {sequence.name}\n </Typography>\n <OutreachSequenceStatusChip status={sequence.status} />\n </Stack>\n <Stack direction=\"row\" spacing={1} sx={{ flexWrap: 'wrap', rowGap: 1 }}>\n {activatable ? (\n <Button\n variant=\"outlined\"\n disabled={busy || blockers.length > 0}\n onClick={() => void act('activate')}\n >\n {ACTIONS.activate.label}\n </Button>\n ) : null}\n {sequence.status === 'active' ? (\n <Button\n variant=\"outlined\"\n disabled={busy}\n onClick={() => void act('pause')}\n >\n {ACTIONS.pause.label}\n </Button>\n ) : null}\n {sequence.status !== 'archived' ? (\n <Button\n variant=\"outlined\"\n color=\"error\"\n disabled={busy}\n onClick={() => setConfirming('archive')}\n >\n {ACTIONS.archive.label}\n </Button>\n ) : null}\n {sequence.status === 'draft' ? (\n <Button\n variant=\"text\"\n color=\"error\"\n disabled={busy}\n onClick={() => setConfirming('delete')}\n >\n Delete\n </Button>\n ) : null}\n {sequence.status === 'active' ? enrollButton : null}\n </Stack>\n </Stack>\n\n {refusal ? (\n <Alert severity=\"error\" onClose={() => setRefusal(null)}>\n <Stack spacing={0.5}>\n <span>{refusal.message}</span>\n {refusal.issues.length > 1 ? (\n <Stack component=\"ul\" spacing={0.25} sx={{ m: 0, pl: 2.5 }}>\n {refusal.issues.slice(1).map((issue) => (\n <li key={`${issue.path}:${issue.code}`}>{issue.message}</li>\n ))}\n </Stack>\n ) : null}\n </Stack>\n </Alert>\n ) : null}\n {blockers.length ? (\n <Alert severity=\"warning\" data-testid=\"outreach-activation-blockers\">\n <Stack spacing={0.5}>\n <span>\n {sequence.status === 'draft'\n ? 'A draft sends nothing, and this one can’t be activated yet:'\n : 'This sequence can’t be activated again yet:'}\n </span>\n <Stack component=\"ul\" spacing={0.25} sx={{ m: 0, pl: 2.5 }}>\n {blockers.map((blocker) => (\n <li key={blocker.message}>\n {blocker.message}{' '}\n <OutreachLink href={blocker.href}>{blocker.linkLabel}</OutreachLink>\n </li>\n ))}\n </Stack>\n </Stack>\n </Alert>\n ) : sequence.status === 'draft' ? (\n <Alert severity=\"info\">\n A draft sends nothing. Activate it to enroll people.\n </Alert>\n ) : null}\n {sequence.status === 'active' && mailboxState !== 'sending' ? (\n <Alert severity=\"warning\">\n {NOT_SENDING[mailboxState]}{' '}\n <OutreachLink href={props.mailboxesPath}>Open Mailboxes</OutreachLink>\n </Alert>\n ) : null}\n\n {/*\n * Above the tabs, not inside one (AGL-3239): what a sequence is doing\n * is the question a rep opens it with, and putting it behind a tab\n * makes the steps the first answer to \"how is this going\".\n *\n * A draft has sent nothing and measured nothing, so it gets no card\n * rather than a row of zeroes.\n */}\n {sequence.status === 'draft' ? null : (\n <OutreachSequenceReportCard\n sequence={sequence}\n links={links}\n timeZone={mailbox?.timezone ?? null}\n // Each leads to the people behind it, on the Enrollments tab's own\n // filter (AGL-3332).\n onShowClickers={() =>\n navigate(outreachEnrollmentsFilterHref(enrollmentsPath, { clicked: true }))\n }\n onShowLink={(url) =>\n navigate(outreachEnrollmentsFilterHref(enrollmentsPath, { link: url }))\n }\n />\n )}\n\n <Tabs\n value={props.tab}\n onChange={(_event, next: OutreachSequenceTab) =>\n navigate(next === 'steps' ? detailPath : enrollmentsPath)\n }\n aria-label=\"Sequence\"\n >\n <Tab value=\"steps\" label=\"Steps\" />\n <Tab value=\"enrollments\" label=\"Enrollments\" />\n </Tabs>\n\n {props.tab === 'steps' ? (\n <OutreachSequenceEditor\n orgId={orgId}\n orgMount={props.orgMount}\n org={props.org}\n sequence={sequence}\n settings={props.settings}\n mailboxes={props.mailboxes}\n mailboxesPath={props.mailboxesPath}\n onSaved={() => undefined}\n />\n ) : (\n <OutreachEnrollmentsTable\n orgId={orgId}\n sequenceId={sequence.id}\n steps={sequence.steps}\n // A sequence that counted clicks once has them to show, whether or\n // not it counts them now.\n trackClicks={sequence.settings.trackClicks || sequence.stats?.clickTracked === true}\n // The same for opens (AGL-3488).\n countOpens={sequence.settings.countOpens || sequence.stats?.openTracked === true}\n timeZone={mailbox?.timezone ?? null}\n mailbox={props.mailboxes.status === 'ready' ? mailbox : undefined}\n sequence={sequence}\n api={api}\n enrollAction={sequence.status === 'active' ? enrollButton : undefined}\n onOpen={(enrollment) => navigate(enrollmentHref(enrollment))}\n hrefFor={enrollmentHref}\n clauses={clauses}\n onClausesChange={setClauses}\n linkOptions={linkOptions}\n />\n )}\n\n <OutreachEnrollDialog\n open={enrolling}\n onClose={() => setEnrolling(false)}\n orgId={orgId}\n sequence={sequence}\n contactGroupId={\n sequence.hostId\n ? consentGroupForHost(props.org ?? null, sequence.hostId).groupId\n : ''\n }\n uid={user?.uid ?? null}\n api={api}\n />\n\n <Dialog\n open={Boolean(confirming)}\n onClose={() => setConfirming(null)}\n fullWidth\n maxWidth=\"xs\"\n >\n <DialogTitle>\n {confirming === 'delete'\n ? 'Delete this draft?'\n : 'Archive this sequence?'}\n </DialogTitle>\n <DialogContent>\n <DialogContentText>\n {confirming === 'delete'\n ? 'It is removed for good. Nobody was ever enrolled in it.'\n : 'Archiving is final. Everyone still in it is stopped, and it takes no one new.'}\n </DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setConfirming(null)}>Cancel</Button>\n <Button\n color=\"error\"\n variant=\"contained\"\n onClick={() => {\n const chosen = confirming\n setConfirming(null)\n if (chosen === 'delete') void remove()\n else void act('archive')\n }}\n >\n {confirming === 'delete' ? 'Delete' : 'Archive'}\n </Button>\n </DialogActions>\n </Dialog>\n </Stack>\n )\n}\nOutreachSequenceDetail.displayName = 'OutreachSequenceDetail'\n\nexport default OutreachSequenceDetail\n"],"names":["consentGroupForHost","mdiAccountMultiplePlusOutline","mdiChevronLeft","MdiIcon","useSnackbar","useUser","Alert","Button","Card","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","Stack","Tab","Tabs","Typography","EmptyStateComponent","usePathname","useRouter","useSearchParams","useMemo","useState","validateOutreachOrgSettings","outreachSequenceLinkReport","outreachMailboxActivationIssue","outreachSequenceMailboxState","OutreachEnrollDialog","outreachClauseLivesInUrl","outreachEnrollmentFilterSearch","outreachEnrollmentsFilterHref","outreachEnrollmentUrlClauses","OutreachEnrollmentsTable","OutreachLink","OutreachLoading","OutreachLoadProblem","OutreachSequenceStatusChip","useOutreachNavigate","OutreachSequenceEditor","OutreachSequenceReportCard","OutreachRouteError","useOutreachApi","useOutreachSequence","useOutreachSequenceLinks","outreachActivationBlockers","input","blockers","mailboxes","status","mailbox","find","entry","id","sequence","mailboxId","issue","push","code","message","href","paths","linkLabel","steps","settings","compliance","NOT_SENDING","none","gone","paused","reconnect_required","outreachEnrollmentPath","sectionPath","sequenceId","enrollmentId","encodeURIComponent","ACTIONS","activate","label","done","pause","archive","OutreachSequenceDetail","props","orgId","api","navigate","enqueueSnackbar","data","user","loaded","links","busy","setBusy","refusal","setRefusal","confirming","setConfirming","enrolling","setEnrolling","router","pathname","searchParams","search","toString","urlClauses","URLSearchParams","ownClauses","setOwnClauses","clauses","setClauses","next","filter","clause","nextSearch","replace","scroll","linkOptions","undefined","rows","map","row","value","url","detailPath","enrollmentsPath","enrollmentHref","enrollment","back","direction","spacing","component","sx","alignItems","display","path","fontSize","span","what","variant","mailboxState","activatable","mailboxesPath","compliancePath","canEnroll","act","action","answer","setSequenceStatus","stoppedEnrollments","error","issues","remove","deleteSequence","enrollButton","startIcon","disabled","onClick","xs","md","justifyContent","minWidth","wordBreak","name","flexWrap","rowGap","length","color","severity","onClose","m","pl","slice","li","data-testid","blocker","timeZone","timezone","onShowClickers","clicked","onShowLink","link","tab","onChange","_event","aria-label","orgMount","org","onSaved","trackClicks","stats","clickTracked","countOpens","openTracked","enrollAction","onOpen","hrefFor","onClausesChange","open","contactGroupId","hostId","groupId","uid","Boolean","fullWidth","maxWidth","chosen","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA,SAASA,mBAAmB,QAAQ,wCAAuC;AAE3E,SACEC,6BAA6B,EAC7BC,cAAc,QACT,yBAAwB;AAC/B,SAASC,OAAO,QAAQ,uBAAsB;AAC9C,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,OAAO,QAAQ,iCAAgC;AACxD,SACEC,KAAK,EACLC,MAAM,EACNC,IAAI,EACJC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,iBAAiB,EACjBC,WAAW,EACXC,KAAK,EACLC,GAAG,EACHC,IAAI,EACJC,UAAU,QACL,gBAAe;AACtB,OAAOC,yBAAyB,wDAAuD;AAEvF,SAASC,WAAW,EAAEC,SAAS,EAAEC,eAAe,QAAQ,kBAAiB;AACzE,SAASC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AACzC,SAASC,2BAA2B,QAAQ,mCAA+B;AAG3E,SAASC,0BAA0B,QAAQ,8BAA0B;AACrE,SACEC,8BAA8B,EAC9BC,4BAA4B,QAGvB,6BAAyB;AAChC,SAASC,oBAAoB,QAAQ,qBAAiB;AACtD,SACEC,wBAAwB,EACxBC,8BAA8B,EAC9BC,6BAA6B,EAC7BC,4BAA4B,QACvB,gCAA4B;AACnC,SAASC,wBAAwB,QAAQ,yBAAqB;AAC9D,SACEC,YAAY,EACZC,eAAe,EACfC,mBAAmB,EACnBC,0BAA0B,EAC1BC,mBAAmB,QACd,mBAAe;AACtB,SAASC,sBAAsB,QAAQ,uBAAmB;AAC1D,SAASC,0BAA0B,QAAQ,4BAAwB;AACnE,SAASC,kBAAkB,EAAEC,cAAc,QAAQ,wBAAoB;AACvE,SACEC,mBAAmB,EACnBC,wBAAwB,QACnB,yBAAqB;AA8B5B;;;;;CAKC,GACD,OAAO,SAASC,2BAA2BC,KAK1C;IACC,MAAMC,WAAwC,EAAE;IAChD,IAAID,MAAME,SAAS,CAACC,MAAM,KAAK,SAAS;YAEpCH;QADF,MAAMI,WACJJ,kCAAAA,MAAME,SAAS,CAACA,SAAS,CAACG,IAAI,CAAC,CAACC,QAAUA,MAAMC,EAAE,KAAKP,MAAMQ,QAAQ,CAACC,SAAS,aAA/ET,kCAAoF;QACtF,MAAMU,QAAQ9B,+BAA+BoB,MAAMQ,QAAQ,CAACC,SAAS,EAAEL;QACvE,IAAIM,OAAO;YACTT,SAASU,IAAI,CACXD,MAAME,IAAI,KAAK,wBACX;gBAAEC,SAASH,MAAMG,OAAO;gBAAEC,MAAMd,MAAMe,KAAK,CAACb,SAAS;gBAAEc,WAAW;YAAiB,IACnF;gBAAEH,SAASH,MAAMG,OAAO;gBAAEC,MAAMd,MAAMe,KAAK,CAACE,KAAK;gBAAED,WAAW;YAAmB;QAEzF;IACF;IACA,IAAIhB,MAAMkB,QAAQ,CAACf,MAAM,KAAK,SAAS;QACrC,KAAK,MAAMO,SAAShC,4BAA4BsB,MAAMkB,QAAQ,CAACA,QAAQ,EAAG;YACxEjB,SAASU,IAAI,CAAC;gBAAEE,SAASH,MAAMG,OAAO;gBAAEC,MAAMd,MAAMe,KAAK,CAACI,UAAU;gBAAEH,WAAW;YAAkB;QACrG;IACF;IACA,OAAOf;AACT;AAEA,0EAA0E,GAC1E,MAAMmB,cAAgF;IACpFC,MAAM;IACNC,MAAM;IACNC,QAAQ;IACRC,oBACE;AACJ;AAEA,iFAAiF,GACjF,OAAO,SAASC,uBACdC,WAAmB,EACnBC,UAAkB,EAClBC,YAAoB;IAEpB,OAAO,GAAGF,YAAY,CAAC,EAAEC,WAAW,aAAa,EAAEE,mBAAmBD,eAAe;AACvF;AAEA,uDAAuD,GACvD,MAAME,UACJ;IACEC,UAAU;QAAEC,OAAO;QAAYC,MAAM;IAAsB;IAC3DC,OAAO;QAAEF,OAAO;QAASC,MAAM;IAAmB;IAClDE,SAAS;QAAEH,OAAO;QAAWC,MAAM;IAAqB;AAC1D;AAEF;;;;CAIC,GACD,OAAO,SAASG,uBAAuBC,KAAkC;cAuFrEA,+CAqQ8BA;QAvBsB7B,iBAEFA;IAtUpD,MAAM,EAAE8B,KAAK,EAAEX,UAAU,EAAED,WAAW,EAAE,GAAGW;IAC3C,MAAME,MAAM3C,eAAe0C;IAC3B,MAAME,WAAWhD;IACjB,MAAM,EAAEiD,eAAe,EAAE,GAAGnF;IAC5B,MAAM,EAAEoF,MAAMC,IAAI,EAAE,GAAGpF;IACvB,MAAMqF,SAAS/C,oBAAoByC,OAAOX;IAC1C,0EAA0E;IAC1E,8CAA8C;IAC9C,MAAMkB,QAAQ/C,yBAAyBwC,OAAOX;IAC9C,MAAM,CAACmB,MAAMC,QAAQ,GAAGtE,SAAS;IACjC,MAAM,CAACuE,SAASC,WAAW,GAAGxE,SAGpB;IACV,MAAM,CAACyE,YAAYC,cAAc,GAAG1E,SAClC;IAEF,MAAM,CAAC2E,WAAWC,aAAa,GAAG5E,SAAS;IAE3C;;;;;GAKC,GACD,MAAM6E,SAAShF;IACf,MAAMiF,WAAWlF;IACjB,MAAMmF,eAAejF;IACrB,MAAMkF,iBAASD,gCAAAA,aAAcE,QAAQ,qBAAM;IAC3C,MAAMC,aAAanF,QACjB,IAAMU,6BAA6B,IAAI0E,gBAAgBH,UACvD;QAACA;KAAO;IAEV,MAAM,CAACI,YAAYC,cAAc,GAAGrF,SAA6B,EAAE;IACnE,MAAMsF,UAAUvF,QAAQ,IAAM;eAAIqF;eAAeF;SAAW,EAAE;QAACE;QAAYF;KAAW;IACtF,MAAMK,aAAa,CAACC;QAClBH,cAAcG,KAAKC,MAAM,CAAC,CAACC,SAAW,CAACpF,yBAAyBoF;QAChE,MAAMC,aAAapF,+BAA+BiF,MAAMR;QACxD,IAAIW,eAAeX,QAAQ;YACzBH,OAAOe,OAAO,CAACD,aAAa,GAAGb,SAAS,CAAC,EAAEa,YAAY,GAAGb,UAAU;gBAAEe,QAAQ;YAAM;QACtF;IACF;IACA,MAAMC,cAAc/F,QAClB;YAEgCqE;eAD9BlE,2BACEkE,MAAM1C,MAAM,KAAK,WAAW0C,cAAAA,MAAMH,IAAI,YAAVG,cAAc2B,YAAaA,WACvDC,IAAI,CAACC,GAAG,CAAC,CAACC,MAAS,CAAA;gBAAEC,OAAOD,IAAIE,GAAG;gBAAE7C,OAAO2C,IAAIE,GAAG;YAAC,CAAA;OACxD;QAAChC;KAAM;IAGT,MAAMrC,WAAWoC,OAAOF,IAAI;IAC5B,MAAMoC,aAAa,GAAGpD,YAAY,CAAC,EAAEC,YAAY;IACjD,MAAMoD,kBAAkB,GAAGD,WAAW,YAAY,CAAC;IACnD,MAAME,iBAAiB,CAACC,aACtBxD,uBAAuBC,aAAaC,YAAYsD,WAAW1E,EAAE;IAC/D,MAAM2E,qBACJ,KAAC9F;QAAa0B,MAAMY;kBAClB,cAAA,MAAC1D;YACCmH,WAAU;YACVC,SAAS;YACTC,WAAU;YACVC,IAAI;gBAAEC,YAAY;gBAAUC,SAAS;YAAc;;8BAEnD,KAACnI;oBAAQoI,MAAMrI,eAAeqI,IAAI;oBAAEC,UAAS;;8BAC7C,KAACC;8BAAK;;;;;IAKZ,IAAI/C,OAAOzC,MAAM,KAAK,WACpB,qBAAO,KAACd;QAAgB2C,OAAM;;IAChC,IAAIY,OAAOzC,MAAM,KAAK,WAAWyC,OAAOzC,MAAM,KAAK,WAAW;QAC5D,qBAAO,KAACb;YAAoBa,QAAQyC,OAAOzC,MAAM;YAAEyF,MAAK;;IAC1D;IACA,IAAI,CAACpF,UAAU;QACb,qBACE,MAACxC;YAAMoH,SAAS;;gBACbF;8BACD,KAACxH;oBAAKmI,SAAQ;8BACZ,cAAA,KAACzH;wBAAoB4D,OAAM;;;;;IAInC;IAEA,MAAM5B,WACJiC,kCAAAA,MAAMnC,SAAS,CAACA,SAAS,CAACG,IAAI,CAAC,CAACC,QAAUA,MAAMC,EAAE,KAAKC,SAASC,SAAS,aAAzE4B,kCACA;IACF,MAAMyD,eACJzD,MAAMnC,SAAS,CAACC,MAAM,KAAK,UACvBtB,6BAA6B2B,SAASC,SAAS,EAAEL,WACjD;IACN,MAAM2F,cAAcvF,SAASL,MAAM,KAAK,WAAWK,SAASL,MAAM,KAAK;IACvE,MAAMF,WAAW8F,cACbhG,2BAA2B;QACzBS;QACAN,WAAWmC,MAAMnC,SAAS;QAC1BgB,UAAUmB,MAAMnB,QAAQ;QACxBH,OAAO;YACLE,OAAO6D;YACP5E,WAAWmC,MAAM2D,aAAa;YAC9B7E,YAAYkB,MAAM4D,cAAc;QAClC;IACF,KACA,EAAE;IACN,0EAA0E;IAC1E,yDAAyD;IACzD,MAAMC,YACJ1F,SAASL,MAAM,KAAK,YACpB2F,iBAAiB,UACjBA,iBAAiB;IACnB,MAAMK,MAAM,OAAOC;QACjBrD,QAAQ;QACRE,WAAW;QACX,IAAI;YACF,MAAMoD,SAAS,MAAM9D,IAAI+D,iBAAiB,CAAC9F,SAASD,EAAE,EAAE6F;YACxD3D,gBACE2D,WAAW,aAAaC,OAAOE,kBAAkB,GAC7C,GAAGzE,QAAQK,OAAO,CAACF,IAAI,CAAC,CAAC,EAAEoE,OAAOE,kBAAkB,CAAC,CAAC,EAAEF,OAAOE,kBAAkB,KAAK,IAAI,eAAe,cAAc,SAAS,CAAC,GACjIzE,OAAO,CAACsE,OAAO,CAACnE,IAAI,EACxB;gBAAE4D,SAAS;YAAU;QAEzB,EAAE,OAAOW,OAAO;YACdvD,WAAW;gBACTpC,SAAS,AAAC2F,MAAgB3F,OAAO;gBACjC4F,QACED,iBAAiB7G,qBACb6G,MAAMC,MAAM,CAACvC,MAAM,CACjB,CAACxD,QAA0C,UAAUA,SAEvD,EAAE;YACV;QACF,SAAU;YACRqC,QAAQ;QACV;IACF;IACA,MAAM2D,SAAS;QACb3D,QAAQ;QACRE,WAAW;QACX,IAAI;YACF,MAAMV,IAAIoE,cAAc,CAACnG,SAASD,EAAE;YACpCkC,gBAAgB,qBAAqB;gBAAEoD,SAAS;YAAU;YAC1DrD,SAASd;QACX,EAAE,OAAO8E,OAAO;YACdvD,WAAW;gBAAEpC,SAAS,AAAC2F,MAAgB3F,OAAO;gBAAE4F,QAAQ,EAAE;YAAC;YAC3D1D,QAAQ;QACV;IACF;IAEA,MAAM6D,6BACJ,KAACnJ;QACCoI,SAAQ;QACRgB,yBACE,KAACxJ;YAAQoI,MAAMtI,8BAA8BsI,IAAI;YAAEC,UAAS;;QAE9DoB,UAAU,CAACZ;QACXa,SAAS,IAAM1D,aAAa;kBAC7B;;IAKH,qBACE,MAACrF;QAAMoH,SAAS;;YACbF;0BACD,MAAClH;gBACCmH,WAAW;oBAAE6B,IAAI;oBAAUC,IAAI;gBAAM;gBACrC7B,SAAS;gBACTE,IAAI;oBAAEC,YAAY;wBAAE0B,IAAI;oBAAS;oBAAGC,gBAAgB;gBAAgB;;kCAEpE,MAAClJ;wBACCmH,WAAU;wBACVC,SAAS;wBACTE,IAAI;4BAAEC,YAAY;4BAAU4B,UAAU;wBAAE;;0CAExC,KAAChJ;gCACC0H,SAAQ;gCACRR,WAAU;gCACVC,IAAI;oCAAE8B,WAAW;gCAAa;0CAE7B5G,SAAS6G,IAAI;;0CAEhB,KAAC9H;gCAA2BY,QAAQK,SAASL,MAAM;;;;kCAErD,MAACnC;wBAAMmH,WAAU;wBAAMC,SAAS;wBAAGE,IAAI;4BAAEgC,UAAU;4BAAQC,QAAQ;wBAAE;;4BAClExB,4BACC,KAACtI;gCACCoI,SAAQ;gCACRiB,UAAUhE,QAAQ7C,SAASuH,MAAM,GAAG;gCACpCT,SAAS,IAAM,KAAKZ,IAAI;0CAEvBrE,QAAQC,QAAQ,CAACC,KAAK;iCAEvB;4BACHxB,SAASL,MAAM,KAAK,yBACnB,KAAC1C;gCACCoI,SAAQ;gCACRiB,UAAUhE;gCACViE,SAAS,IAAM,KAAKZ,IAAI;0CAEvBrE,QAAQI,KAAK,CAACF,KAAK;iCAEpB;4BACHxB,SAASL,MAAM,KAAK,2BACnB,KAAC1C;gCACCoI,SAAQ;gCACR4B,OAAM;gCACNX,UAAUhE;gCACViE,SAAS,IAAM5D,cAAc;0CAE5BrB,QAAQK,OAAO,CAACH,KAAK;iCAEtB;4BACHxB,SAASL,MAAM,KAAK,wBACnB,KAAC1C;gCACCoI,SAAQ;gCACR4B,OAAM;gCACNX,UAAUhE;gCACViE,SAAS,IAAM5D,cAAc;0CAC9B;iCAGC;4BACH3C,SAASL,MAAM,KAAK,WAAWyG,eAAe;;;;;YAIlD5D,wBACC,KAACxF;gBAAMkK,UAAS;gBAAQC,SAAS,IAAM1E,WAAW;0BAChD,cAAA,MAACjF;oBAAMoH,SAAS;;sCACd,KAACO;sCAAM3C,QAAQnC,OAAO;;wBACrBmC,QAAQyD,MAAM,CAACe,MAAM,GAAG,kBACvB,KAACxJ;4BAAMqH,WAAU;4BAAKD,SAAS;4BAAME,IAAI;gCAAEsC,GAAG;gCAAGC,IAAI;4BAAI;sCACtD7E,QAAQyD,MAAM,CAACqB,KAAK,CAAC,GAAGpD,GAAG,CAAC,CAAChE,sBAC5B,KAACqH;8CAAwCrH,MAAMG,OAAO;mCAA7C,GAAGH,MAAM+E,IAAI,CAAC,CAAC,EAAE/E,MAAME,IAAI,EAAE;6BAGxC;;;iBAGN;YACHX,SAASuH,MAAM,iBACd,KAAChK;gBAAMkK,UAAS;gBAAUM,eAAY;0BACpC,cAAA,MAAChK;oBAAMoH,SAAS;;sCACd,KAACO;sCACEnF,SAASL,MAAM,KAAK,UACjB,gEACA;;sCAEN,KAACnC;4BAAMqH,WAAU;4BAAKD,SAAS;4BAAME,IAAI;gCAAEsC,GAAG;gCAAGC,IAAI;4BAAI;sCACtD5H,SAASyE,GAAG,CAAC,CAACuD,wBACb,MAACF;;wCACEE,QAAQpH,OAAO;wCAAE;sDAClB,KAACzB;4CAAa0B,MAAMmH,QAAQnH,IAAI;sDAAGmH,QAAQjH,SAAS;;;mCAF7CiH,QAAQpH,OAAO;;;;iBAQ9BL,SAASL,MAAM,KAAK,wBACtB,KAAC3C;gBAAMkK,UAAS;0BAAO;iBAGrB;YACHlH,SAASL,MAAM,KAAK,YAAY2F,iBAAiB,0BAChD,MAACtI;gBAAMkK,UAAS;;oBACbtG,WAAW,CAAC0E,aAAa;oBAAE;kCAC5B,KAAC1G;wBAAa0B,MAAMuB,MAAM2D,aAAa;kCAAE;;;iBAEzC;YAUHxF,SAASL,MAAM,KAAK,UAAU,qBAC7B,KAACT;gBACCc,UAAUA;gBACVqC,OAAOA;gBACPqF,QAAQ,WAAE9H,2BAAAA,QAAS+H,QAAQ,oBAAI;gBAC/B,mEAAmE;gBACnE,qBAAqB;gBACrBC,gBAAgB,IACd5F,SAASvD,8BAA8B8F,iBAAiB;wBAAEsD,SAAS;oBAAK;gBAE1EC,YAAY,CAACzD,MACXrC,SAASvD,8BAA8B8F,iBAAiB;wBAAEwD,MAAM1D;oBAAI;;0BAK1E,MAAC3G;gBACC0G,OAAOvC,MAAMmG,GAAG;gBAChBC,UAAU,CAACC,QAAQzE,OACjBzB,SAASyB,SAAS,UAAUa,aAAaC;gBAE3C4D,cAAW;;kCAEX,KAAC1K;wBAAI2G,OAAM;wBAAQ5C,OAAM;;kCACzB,KAAC/D;wBAAI2G,OAAM;wBAAc5C,OAAM;;;;YAGhCK,MAAMmG,GAAG,KAAK,wBACb,KAAC/I;gBACC6C,OAAOA;gBACPsG,UAAUvG,MAAMuG,QAAQ;gBACxBC,KAAKxG,MAAMwG,GAAG;gBACdrI,UAAUA;gBACVU,UAAUmB,MAAMnB,QAAQ;gBACxBhB,WAAWmC,MAAMnC,SAAS;gBAC1B8F,eAAe3D,MAAM2D,aAAa;gBAClC8C,SAAS,IAAMtE;+BAGjB,KAACrF;gBACCmD,OAAOA;gBACPX,YAAYnB,SAASD,EAAE;gBACvBU,OAAOT,SAASS,KAAK;gBACrB,mEAAmE;gBACnE,0BAA0B;gBAC1B8H,aAAavI,SAASU,QAAQ,CAAC6H,WAAW,IAAIvI,EAAAA,kBAAAA,SAASwI,KAAK,qBAAdxI,gBAAgByI,YAAY,MAAK;gBAC/E,iCAAiC;gBACjCC,YAAY1I,SAASU,QAAQ,CAACgI,UAAU,IAAI1I,EAAAA,mBAAAA,SAASwI,KAAK,qBAAdxI,iBAAgB2I,WAAW,MAAK;gBAC5EjB,QAAQ,WAAE9H,2BAAAA,QAAS+H,QAAQ,oBAAI;gBAC/B/H,SAASiC,MAAMnC,SAAS,CAACC,MAAM,KAAK,UAAUC,UAAUoE;gBACxDhE,UAAUA;gBACV+B,KAAKA;gBACL6G,cAAc5I,SAASL,MAAM,KAAK,WAAWyG,eAAepC;gBAC5D6E,QAAQ,CAACpE,aAAezC,SAASwC,eAAeC;gBAChDqE,SAAStE;gBACTjB,SAASA;gBACTwF,iBAAiBvF;gBACjBO,aAAaA;;0BAIjB,KAACzF;gBACC0K,MAAMpG;gBACNuE,SAAS,IAAMtE,aAAa;gBAC5Bf,OAAOA;gBACP9B,UAAUA;gBACViJ,gBACEjJ,SAASkJ,MAAM,GACXxM,qBAAoBmF,aAAAA,MAAMwG,GAAG,YAATxG,aAAa,MAAM7B,SAASkJ,MAAM,EAAEC,OAAO,GAC/D;gBAENC,GAAG,WAAEjH,wBAAAA,KAAMiH,GAAG,oBAAI;gBAClBrH,KAAKA;;0BAGP,MAAC5E;gBACC6L,MAAMK,QAAQ3G;gBACdyE,SAAS,IAAMxE,cAAc;gBAC7B2G,SAAS;gBACTC,UAAS;;kCAET,KAAChM;kCACEmF,eAAe,WACZ,uBACA;;kCAEN,KAACrF;kCACC,cAAA,KAACC;sCACEoF,eAAe,WACZ,4DACA;;;kCAGR,MAACtF;;0CACC,KAACH;gCAAOsJ,SAAS,IAAM5D,cAAc;0CAAO;;0CAC5C,KAAC1F;gCACCgK,OAAM;gCACN5B,SAAQ;gCACRkB,SAAS;oCACP,MAAMiD,SAAS9G;oCACfC,cAAc;oCACd,IAAI6G,WAAW,UAAU,KAAKtD;yCACzB,KAAKP,IAAI;gCAChB;0CAECjD,eAAe,WAAW,WAAW;;;;;;;;AAMlD;AACAd,uBAAuB6H,WAAW,GAAG;AAErC,eAAe7H,uBAAsB"}
|
|
@@ -31,7 +31,7 @@ import { outreachCountryLabel } from "../model/compliance-settings.js";
|
|
|
31
31
|
import { OUTREACH_MAX_EMAIL_STEPS, OUTREACH_MAX_STEPS, OUTREACH_TASK_KIND_LABELS, OUTREACH_TASK_KINDS } from "../model/outreach.types.js";
|
|
32
32
|
import { emptyOutreachSequenceDraft, newOutreachEmailStep, newOutreachTaskStep, outreachSequenceDraftOf } from "../model/sequence-draft.js";
|
|
33
33
|
import { OutreachSendWindowFields } from "./send-window-fields.js";
|
|
34
|
-
import { OutreachSequenceMailboxPicker } from "./sequence-mailbox-picker.js";
|
|
34
|
+
import { OutreachSequenceMailboxPicker, OutreachSequenceRotationPicker } from "./sequence-mailbox-picker.js";
|
|
35
35
|
import { OutreachSequencePreview } from "./sequence-preview.js";
|
|
36
36
|
import { OutreachStepCard } from "./sequence-step-card.js";
|
|
37
37
|
import { OutreachStepTestDialog } from "./step-test-dialog.js";
|
|
@@ -124,6 +124,8 @@ import { useOutreachEmailTemplates } from "./use-outreach-crm.js";
|
|
|
124
124
|
* The sections below are drawn from the one draft, and each redraws only
|
|
125
125
|
* when what it shows changes (AGL-3423).
|
|
126
126
|
*/ const MemoMailboxPicker = /*#__PURE__*/ memo(OutreachSequenceMailboxPicker);
|
|
127
|
+
const MemoRotationPicker = /*#__PURE__*/ memo(OutreachSequenceRotationPicker);
|
|
128
|
+
/** A stable empty rotation, so the picker's props hold still while there is none. */ const NO_ROTATION = [];
|
|
127
129
|
const MemoContainerPicker = /*#__PURE__*/ memo(ContainerPicker);
|
|
128
130
|
const MemoSendWindowFields = /*#__PURE__*/ memo(OutreachSendWindowFields);
|
|
129
131
|
const MemoSequencePreview = /*#__PURE__*/ memo(OutreachSequencePreview);
|
|
@@ -234,6 +236,16 @@ const SequenceSiteField = /*#__PURE__*/ memo(function SequenceSiteField(props) {
|
|
|
234
236
|
error: props.mailboxIssue,
|
|
235
237
|
disabled: archived
|
|
236
238
|
}),
|
|
239
|
+
/*#__PURE__*/ _jsx(MemoRotationPicker, {
|
|
240
|
+
orgId: props.orgId,
|
|
241
|
+
uid: props.uid,
|
|
242
|
+
mailboxes: props.mailboxes,
|
|
243
|
+
mailboxId: props.mailboxId,
|
|
244
|
+
value: props.mailboxIds,
|
|
245
|
+
onChange: props.onRotation,
|
|
246
|
+
error: props.rotationIssue,
|
|
247
|
+
disabled: archived
|
|
248
|
+
}),
|
|
237
249
|
/*#__PURE__*/ _jsx(MemoContainerPicker, {
|
|
238
250
|
kind: "campaign",
|
|
239
251
|
options: props.campaignOptions,
|
|
@@ -471,7 +483,7 @@ const SequenceSiteField = /*#__PURE__*/ memo(function SequenceSiteField(props) {
|
|
|
471
483
|
* from the draft as drawn still do, through `drawn`. A letter now redraws the
|
|
472
484
|
* field it lands in, and the preview when it shows that step's email.
|
|
473
485
|
*/ export function OutreachSequenceEditor(props) {
|
|
474
|
-
var _ref, _props_mailboxes_mailboxes_find, _ref1, _props_org, _ref2;
|
|
486
|
+
var _ref, _props_mailboxes_mailboxes_find, _ref1, _draft_mailboxIds, _props_org, _ref2;
|
|
475
487
|
var _settings_settings, _settings_settings1, _issues_find, _hosts_find;
|
|
476
488
|
const { orgId, orgMount, sequence, settings } = props;
|
|
477
489
|
const api = useOutreachApi(orgId);
|
|
@@ -609,8 +621,18 @@ const SequenceSiteField = /*#__PURE__*/ memo(function SequenceSiteField(props) {
|
|
|
609
621
|
}), [
|
|
610
622
|
update
|
|
611
623
|
]);
|
|
612
|
-
const setMailbox = useCallback((mailboxId)=>
|
|
613
|
-
|
|
624
|
+
const setMailbox = useCallback((mailboxId)=>{
|
|
625
|
+
var _drawn_current_mailboxIds;
|
|
626
|
+
return update({
|
|
627
|
+
mailboxId,
|
|
628
|
+
// The sequence's own mailbox is never also one it rotates through.
|
|
629
|
+
mailboxIds: ((_drawn_current_mailboxIds = drawn.current.mailboxIds) == null ? void 0 : _drawn_current_mailboxIds.filter((id)=>id !== mailboxId).length) ? drawn.current.mailboxIds.filter((id)=>id !== mailboxId) : undefined
|
|
630
|
+
});
|
|
631
|
+
}, [
|
|
632
|
+
update
|
|
633
|
+
]);
|
|
634
|
+
const setRotation = useCallback((mailboxIds)=>update({
|
|
635
|
+
mailboxIds: mailboxIds.length ? mailboxIds : undefined
|
|
614
636
|
}), [
|
|
615
637
|
update
|
|
616
638
|
]);
|
|
@@ -741,6 +763,7 @@ const SequenceSiteField = /*#__PURE__*/ memo(function SequenceSiteField(props) {
|
|
|
741
763
|
name: draft.name,
|
|
742
764
|
hostId: draft.hostId,
|
|
743
765
|
mailboxId: draft.mailboxId,
|
|
766
|
+
mailboxIds: (_draft_mailboxIds = draft.mailboxIds) != null ? _draft_mailboxIds : NO_ROTATION,
|
|
744
767
|
campaignIds: draft.campaignIds,
|
|
745
768
|
hosts: hosts,
|
|
746
769
|
mailboxes: props.mailboxes,
|
|
@@ -750,6 +773,7 @@ const SequenceSiteField = /*#__PURE__*/ memo(function SequenceSiteField(props) {
|
|
|
750
773
|
nameIssue: issueAt('name'),
|
|
751
774
|
hostIssue: issueAt('hostId'),
|
|
752
775
|
mailboxIssue: issueAt('mailboxId'),
|
|
776
|
+
rotationIssue: issueAt('mailboxIds'),
|
|
753
777
|
campaignsIssue: issueAt('campaignIds'),
|
|
754
778
|
archived: archived,
|
|
755
779
|
saving: saving,
|
|
@@ -759,6 +783,7 @@ const SequenceSiteField = /*#__PURE__*/ memo(function SequenceSiteField(props) {
|
|
|
759
783
|
onName: setName,
|
|
760
784
|
onHost: setHost,
|
|
761
785
|
onMailbox: setMailbox,
|
|
786
|
+
onRotation: setRotation,
|
|
762
787
|
onCampaigns: setCampaigns
|
|
763
788
|
}),
|
|
764
789
|
listIssue ? /*#__PURE__*/ _jsx(Alert, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/sequence-editor.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, type ConsolePluginOrgMount } from '@aglyn/aglyn'\nimport { consentGroupForHost } from '@aglyn/aglyn/app-utils/consent-groups'\nimport { mdiPlus } from '@aglyn/shared-data-mdi'\nimport { CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport ContainerPicker, {\n type ContainerPickerProps,\n} from '@aglyn/tenant-feature-instance/components/container-picker'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useOrgContainerOptions, useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Autocomplete,\n Box,\n Button,\n Chip,\n FormControlLabel,\n Grid,\n Menu,\n MenuItem,\n Stack,\n Switch,\n TextField,\n Typography,\n} from '@mui/material'\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n isInThreadEmailStep,\n OUTREACH_SEQUENCE_NAME_MAX,\n validateOutreachSequence,\n} from '../engine/sequence-validation'\nimport { outreachCountryLabel } from '../model/compliance-settings'\nimport {\n OUTREACH_MAX_EMAIL_STEPS,\n OUTREACH_MAX_STEPS,\n OUTREACH_TASK_KIND_LABELS,\n OUTREACH_TASK_KINDS,\n type OutreachSequence,\n type OutreachSequenceStep,\n type OutreachTaskKind,\n} from '../model/outreach.types'\nimport {\n emptyOutreachSequenceDraft,\n newOutreachEmailStep,\n newOutreachTaskStep,\n outreachSequenceDraftOf,\n type OutreachSequenceDraft,\n type OutreachSequenceIssue,\n} from '../model/sequence-draft'\nimport { OutreachSendWindowFields } from './send-window-fields'\nimport { OutreachSequenceMailboxPicker } from './sequence-mailbox-picker'\nimport { OutreachSequencePreview } from './sequence-preview'\nimport {\n OutreachStepCard,\n type OutreachStepCardProps,\n} from './sequence-step-card'\nimport { OutreachStepTestDialog } from './step-test-dialog'\nimport { OutreachRouteError, useOutreachApi } from './use-outreach-api'\nimport { useOutreachEmailTemplates } from './use-outreach-crm'\nimport type { OutreachMailboxesResult } from './use-outreach-mailboxes'\nimport type { OutreachSettingsLoad } from './use-outreach-settings'\n\nexport interface OutreachSequenceEditorProps {\n orgId: string\n orgMount?: ConsolePluginOrgMount\n /** The organization document, for the consent group a test send's person picker searches (AGL-3325). */\n org?: Record<string, unknown> | null\n /** The stored sequence, or `null` for a new one. */\n sequence: OutreachSequence | null\n /** The organization's compliance settings: its countries, and the preview's footer. */\n settings: OutreachSettingsLoad\n /**\n * The organization's mailboxes, from the Mailboxes section's listener:\n * what the picker offers, and who the preview's emails are from.\n */\n mailboxes: OutreachMailboxesResult\n /** The Mailboxes section, where the picker sends a member to connect one. */\n mailboxesPath: string\n onSaved(sequence: OutreachSequence): void\n onCancel?(): void\n}\n\n/** The step a dotted issue path is about, and the field within it. */\nfunction stepIssueKey(path: string): { index: number; field: string } | null {\n const match = /^steps\\.(\\d+)(?:\\.(.+))?$/.exec(path)\n if (!match) return null\n const field = match[2] ?? 'step'\n return { index: Number(match[1]), field: field === 'id' ? 'step' : field }\n}\n\ninterface OutreachCountriesFieldProps {\n options: readonly string[]\n value: readonly string[]\n onChange(next: string[]): void\n issue?: string\n disabled: boolean\n}\n\n/**\n * The countries a sequence sends to, as chips in an Autocomplete.\n *\n * MEMOIZED, AND EVERY PROP IT TAKES IS STABLE WHILE THE COUNTRIES ARE\n * (AGL-3423). A multiple Autocomplete hands its input a new chip array as\n * `startAdornment` on every render, and MUI's `InputBase` copies that into\n * its `FormControl` from a passive effect — a state update after every\n * commit this field takes part in. React 19 counts a commit that leaves such\n * an update pending as a nested update, and keystrokes the browser delivers\n * back to back (a held key, fast typing on a busy page) commit one after\n * another with nothing in between to clear the count: fifty-one of them and\n * the next keystroke's own `setState` throws \"Maximum update depth exceeded\"\n * (minified error #185), which is what typing a step's body reported. Kept\n * out of the editor's other renders, the field commits only when the\n * countries, their options or their issue change.\n */\nconst OutreachCountriesField = memo(function OutreachCountriesField(\n props: OutreachCountriesFieldProps,\n) {\n return (\n <Autocomplete<string, true>\n multiple\n options={props.options}\n value={props.value as string[]}\n getOptionLabel={outreachCountryLabel}\n onChange={(_event, next) => props.onChange(next)}\n disabled={props.disabled}\n renderValue={(value, getItemProps) =>\n value.map((code, index) => {\n const { key, ...item } = getItemProps({ index })\n return (\n <Chip\n key={key}\n size=\"small\"\n label={outreachCountryLabel(code)}\n {...item}\n />\n )\n })\n }\n renderInput={(params) => (\n <TextField\n {...params}\n label=\"Countries\"\n error={Boolean(props.issue)}\n helperText={\n props.issue ??\n 'Among the countries your organization allows. Cold contacts are emailed only in the United States.'\n }\n />\n )}\n />\n )\n})\n\n/** Each step's issues by the field they are about, as its card reads them. */\ntype StepIssues = Partial<Record<string, string>>\n\n/**\n * Each step's issues, the SAME record for a step while what it holds reads\n * the same (AGL-3423), so a step a keystroke did not touch keeps its props.\n */\nfunction useStepIssues(\n issues: readonly OutreachSequenceIssue[],\n count: number,\n): StepIssues[] {\n const held = useRef<Array<{ key: string; value: StepIssues }>>([])\n return useMemo(() => {\n const found: Record<string, string>[] = Array.from(\n { length: count },\n () => ({}),\n )\n for (const issue of issues) {\n const key = stepIssueKey(issue.path)\n const record = key ? found[key.index] : undefined\n if (key && record && !record[key.field])\n record[key.field] = issue.message\n }\n held.current = found.map((value, index) => {\n const key = JSON.stringify(value)\n const before = held.current[index]\n return before?.key === key ? before : { key, value }\n })\n return held.current.map((entry) => entry.value)\n }, [issues, count])\n}\n\n/** A text field that redraws only when what it shows changes (AGL-3423). */\nconst MemoTextField = memo(TextField) as typeof TextField\n\n/*\n * The sections below are drawn from the one draft, and each redraws only\n * when what it shows changes (AGL-3423).\n */\nconst MemoMailboxPicker = memo(OutreachSequenceMailboxPicker)\nconst MemoContainerPicker = memo(ContainerPicker)\nconst MemoSendWindowFields = memo(OutreachSendWindowFields)\nconst MemoSequencePreview = memo(OutreachSequencePreview)\n\ntype FieldChange = { target: { value: string } }\ntype SwitchChange = { target: { checked: boolean } }\ntype SequenceSettings = OutreachSequenceDraft['settings']\n\nconst NAME_SLOT_PROPS = {\n htmlInput: { maxLength: OUTREACH_SEQUENCE_NAME_MAX + 20 },\n}\nconst ADD_STEP_ROW = { flexWrap: 'wrap', rowGap: 1 } as const\nconst PREVIEW_COLUMN = {\n position: { md: 'sticky' },\n top: { md: 16 },\n} as const\n\nconst SequenceSiteField = memo(function SequenceSiteField(props: {\n hosts: ConsolePluginOrgMount['hosts']\n value: string\n issue?: string\n disabled: boolean\n onChange(event: FieldChange): void\n}) {\n const { hosts, value, issue } = props\n return (\n <TextField\n select\n label=\"Site\"\n value={hosts.some((host) => host.id === value) ? value : ''}\n onChange={props.onChange}\n disabled={props.disabled || !hosts.length}\n error={Boolean(issue)}\n helperText={issue ?? 'The site whose contacts this sequence emails.'}\n fullWidth\n >\n {hosts.map((host) => (\n <MenuItem key={host.id} value={host.id}>\n {host.name}\n </MenuItem>\n ))}\n </TextField>\n )\n})\n\n/** The sequence card's header actions: Cancel, and the save of the whole sequence. */\nconst SequenceSaveActions = memo(function SequenceSaveActions(props: {\n saving: boolean\n /** \"Save\" for a stored sequence, \"Create sequence\" for a new one. */\n saveLabel: string\n onCancel?(): void\n onSave(): void\n}) {\n return (\n <Stack direction=\"row\" spacing={1}>\n {props.onCancel ? (\n <Button\n size=\"small\"\n variant=\"text\"\n onClick={props.onCancel}\n disabled={props.saving}\n >\n Cancel\n </Button>\n ) : null}\n <Button\n size=\"small\"\n variant=\"contained\"\n onClick={props.onSave}\n disabled={props.saving}\n >\n {props.saving ? 'Saving…' : props.saveLabel}\n </Button>\n </Stack>\n )\n})\n\ninterface SequenceCardProps {\n orgId: string\n uid: string | null\n name: string\n hostId: string\n mailboxId: string\n campaignIds: readonly string[]\n hosts: ConsolePluginOrgMount['hosts']\n mailboxes: OutreachMailboxesResult\n mailboxesPath: string\n campaignOptions: ContainerPickerProps['options']\n /** The organization has no campaigns at all. */\n noCampaigns: boolean\n nameIssue?: string\n hostIssue?: string\n mailboxIssue?: string\n campaignsIssue?: string\n archived: boolean\n saving: boolean\n saveLabel: string\n onCancel?(): void\n onSave(): void\n onName(event: FieldChange): void\n onHost(event: FieldChange): void\n onMailbox(mailboxId: string): void\n onCampaigns(campaignIds: string[]): void\n}\n\n/** The sequence's own card: its name, site, mailbox and campaigns. */\nconst SequenceCard = memo(function SequenceCard(props: SequenceCardProps) {\n const { archived } = props\n return (\n <CardDisplay\n header=\"Sequence\"\n help={pluginDocsHelp('sequences', { anchor: '#build-a-sequence' })}\n // The whole sequence (steps and sending rules included) saves\n // from its first card's header, where the console puts a card's\n // actions (AGL-3333).\n HeaderProps={{\n action: archived ? undefined : (\n <SequenceSaveActions\n saving={props.saving}\n saveLabel={props.saveLabel}\n onCancel={props.onCancel}\n onSave={props.onSave}\n />\n ),\n }}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <MemoTextField\n label=\"Name\"\n value={props.name}\n onChange={props.onName}\n disabled={archived}\n error={Boolean(props.nameIssue)}\n helperText={props.nameIssue}\n slotProps={NAME_SLOT_PROPS}\n fullWidth\n />\n <SequenceSiteField\n hosts={props.hosts}\n value={props.hostId}\n issue={props.hostIssue}\n disabled={archived}\n onChange={props.onHost}\n />\n <MemoMailboxPicker\n orgId={props.orgId}\n uid={props.uid}\n mailboxes={props.mailboxes}\n mailboxesPath={props.mailboxesPath}\n value={props.mailboxId}\n onChange={props.onMailbox}\n error={props.mailboxIssue}\n disabled={archived}\n />\n {/*\n The campaigns this sequence is part of (AGL-3254), picked the\n way a form's page picks them. Everyone enrolled joins them,\n and what the sequence produces is reported under them; it\n does not change who is enrolled or what is sent.\n */}\n <MemoContainerPicker\n kind=\"campaign\"\n options={props.campaignOptions}\n value={props.campaignIds}\n onChange={props.onCampaigns}\n label=\"Campaigns\"\n helperText={\n props.campaignsIssue ??\n 'The campaigns this sequence is part of. Everyone enrolled joins them, and its sends, replies, meetings and conversions count on their pages.'\n }\n disabled={archived}\n empty={props.noCampaigns}\n emptyText=\"There are no campaigns yet. Create one from Marketing to file this sequence under it.\"\n />\n </Stack>\n </CardDisplay>\n )\n})\n\ninterface SequenceStepItemProps\n extends Omit<\n OutreachStepCardProps,\n 'onChange' | 'onMove' | 'onRemove' | 'onSendTest'\n > {\n /** Whether the step offers a test send: an email in a sequence that is not archived. */\n canSendTest: boolean\n onStepChange(index: number, step: OutreachSequenceStep): void\n onStepMove(index: number, direction: -1 | 1): void\n onStepRemove(index: number): void\n onStepTest(index: number): void\n}\n\n/**\n * One step's card, bound to its position. Memoized, with handlers that keep\n * their identity, so a keystroke in one step leaves the others undrawn.\n */\nconst SequenceStepItem = memo(function SequenceStepItem(\n props: SequenceStepItemProps,\n) {\n const {\n index,\n canSendTest,\n onStepChange,\n onStepMove,\n onStepRemove,\n onStepTest,\n ...card\n } = props\n const onChange = useCallback(\n (step: OutreachSequenceStep) => onStepChange(index, step),\n [index, onStepChange],\n )\n const onMove = useCallback(\n (direction: -1 | 1) => onStepMove(index, direction),\n [index, onStepMove],\n )\n const onRemove = useCallback(\n () => onStepRemove(index),\n [index, onStepRemove],\n )\n const onSendTest = useCallback(() => onStepTest(index), [index, onStepTest])\n return (\n <OutreachStepCard\n {...card}\n index={index}\n onChange={onChange}\n onMove={onMove}\n onRemove={onRemove}\n onSendTest={canSendTest ? onSendTest : undefined}\n />\n )\n})\n\n/** Adds an email, or a task of a kind picked from its menu. */\nconst SequenceAddStep = memo(function SequenceAddStep(props: {\n emailDisabled: boolean\n taskDisabled: boolean\n onAddEmail(): void\n onAddTask(kind: OutreachTaskKind): void\n}) {\n const { onAddTask } = props\n const [taskAnchor, setTaskAnchor] = useState<HTMLElement | null>(null)\n return (\n <Stack direction=\"row\" spacing={1} sx={ADD_STEP_ROW}>\n <Button\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiPlus.path} fontSize=\"small\" />}\n disabled={props.emailDisabled}\n onClick={props.onAddEmail}\n >\n Add email\n </Button>\n <Button\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiPlus.path} fontSize=\"small\" />}\n disabled={props.taskDisabled}\n onClick={(event) => setTaskAnchor(event.currentTarget)}\n aria-haspopup=\"menu\"\n >\n Add task\n </Button>\n <Menu\n anchorEl={taskAnchor}\n open={Boolean(taskAnchor)}\n onClose={() => setTaskAnchor(null)}\n >\n {OUTREACH_TASK_KINDS.map((kind: OutreachTaskKind) => (\n <MenuItem\n key={kind}\n onClick={() => {\n setTaskAnchor(null)\n onAddTask(kind)\n }}\n >\n {OUTREACH_TASK_KIND_LABELS[kind]}\n </MenuItem>\n ))}\n </Menu>\n </Stack>\n )\n})\n\ninterface SequenceSendingCardProps {\n settings: SequenceSettings\n countryOptions: readonly string[]\n countriesIssue?: string\n daysIssue?: string\n hoursIssue?: string\n disabled: boolean\n onCountries(next: string[]): void\n onSettings(patch: Partial<SequenceSettings>): void\n}\n\n/** Who the sequence sends to, and when: its countries, switches and hours. */\nconst SequenceSendingCard = memo(function SequenceSendingCard(\n props: SequenceSendingCardProps,\n) {\n const { settings, disabled, onSettings } = props\n const setAllowCustomers = useCallback(\n (event: SwitchChange) =>\n onSettings({ allowCustomers: event.target.checked }),\n [onSettings],\n )\n const setTrackClicks = useCallback(\n (event: SwitchChange) => onSettings({ trackClicks: event.target.checked }),\n [onSettings],\n )\n const setCountOpens = useCallback(\n (event: SwitchChange) => onSettings({ countOpens: event.target.checked }),\n [onSettings],\n )\n const setListUnsubscribe = useCallback(\n (event: SwitchChange) =>\n onSettings({ listUnsubscribe: event.target.checked }),\n [onSettings],\n )\n const setWindow = useCallback(\n (window: SequenceSettings['window']) => onSettings({ window }),\n [onSettings],\n )\n return (\n <CardDisplay\n header=\"Who it sends to, and when\"\n help={pluginDocsHelp('sequences', {\n anchor: '#build-a-sequence',\n excerpt:\n 'A sequence sends only to the countries both it and your organization allow, and in its mailbox’s sending hours unless it has its own.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <OutreachCountriesField\n options={props.countryOptions}\n value={settings.allowedCountries}\n onChange={props.onCountries}\n issue={props.countriesIssue}\n disabled={disabled}\n />\n <FormControlLabel\n control={\n <Switch\n checked={settings.allowCustomers}\n onChange={setAllowCustomers}\n disabled={disabled}\n />\n }\n label=\"Include customers\"\n />\n {/*\n * Click tracking (AGL-3239), with its cost stated where it is\n * chosen rather than in a document nobody opens. Off by\n * default: it changes the link a cold recipient sees. The\n * emails stay plain text either way; opens are the separate\n * switch below.\n */}\n <Stack spacing={0}>\n <FormControlLabel\n control={\n <Switch\n checked={settings.trackClicks}\n onChange={setTrackClicks}\n disabled={disabled}\n />\n }\n label=\"Count link clicks\"\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n Links in these emails are replaced with links of ours that\n forward to the same page, so clicks can be counted. The\n recipient sees the replacement, not your address. The\n emails stay plain text.\n </Typography>\n </Stack>\n {/*\n * Open counting (AGL-3395), off by default, its cost stated\n * where it is chosen: an HTML copy with a tracking image is the\n * least one-to-one thing a sequence email can carry, so it is\n * for measuring a slice, not for every sequence.\n */}\n <Stack spacing={0}>\n <FormControlLabel\n control={\n <Switch\n checked={settings.countOpens}\n onChange={setCountOpens}\n disabled={disabled}\n />\n }\n label=\"Count opens\"\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n Each email also goes out as HTML — the same words — with a\n tiny tracking image, so opens can be counted. The plain-text\n version is unchanged. It makes the email look less like one\n written by hand, and some spam filters score HTML with a\n remote image against you, so turn it on to measure a slice\n of your sends rather than for every sequence. Gmail opens\n count; Apple Mail loads every image on arrival, so its loads\n are counted separately.\n </Typography>\n </Stack>\n {/*\n * The mail-client unsubscribe button (AGL-3296), off by\n * default: the header is what makes Apple Mail, Gmail and\n * Outlook present a one-to-one email as a mailing list. The\n * footer's \"reply 'no'\" line is the way out either way.\n */}\n <Stack spacing={0}>\n <FormControlLabel\n control={\n <Switch\n checked={settings.listUnsubscribe}\n onChange={setListUnsubscribe}\n disabled={disabled}\n />\n }\n label=\"Add a mail-client unsubscribe button\"\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n Adds the List-Unsubscribe header, so the recipient’s mail\n app shows its own Unsubscribe button. It’s the easiest way\n out for them, and fewer people mark you as spam when they\n have it, but mail apps then label the email as coming from\n a mailing list. Off, the footer’s “reply ‘no’” line is the\n way out, and it’s always there.\n </Typography>\n </Stack>\n <MemoSendWindowFields\n window={settings.window}\n onChange={setWindow}\n daysIssue={props.daysIssue}\n hoursIssue={props.hoursIssue}\n disabled={disabled}\n />\n </Stack>\n </CardDisplay>\n )\n})\n\n/**\n * The sequence editor (AGL-2980): the name, the site and mailbox, the steps,\n * who it sends to and when, beside a live preview of each email.\n *\n * Every issue the engine's validator finds is shown beside its field — the\n * same validator the save route refuses with — errors once a save was\n * attempted, warnings as soon as they appear. What only the server can\n * judge (whose mailbox, which countries the organization allows, what may\n * no longer change once people are enrolled) comes back from the save and\n * is shown in the same places.\n *\n * ## A keystroke redraws its own field (AGL-3423)\n *\n * The whole sequence is one draft, so every letter typed anywhere is a new\n * draft, and drawing the editor from it inline redrew every field of every\n * step, the settings and the preview with each one: 17 inputs and some 1,150\n * components for one letter in a three-step sequence. That cost is what lets\n * typed input queue, and queued keystrokes processed back to back are what\n * drove the countries chips into React's #185. The sequence card, each step,\n * the sending card and the preview are memoized and handed only what they\n * show, through handlers that keep their identity; the handlers that wrote\n * from the draft as drawn still do, through `drawn`. A letter now redraws the\n * field it lands in, and the preview when it shows that step's email.\n */\nexport function OutreachSequenceEditor(props: OutreachSequenceEditorProps) {\n const { orgId, orgMount, sequence, settings } = props\n const api = useOutreachApi(orgId)\n const { enqueueSnackbar } = useSnackbar()\n const { data: user } = useUser()\n const uid = user?.uid ?? null\n const mountedHosts = orgMount?.hosts\n const hosts = useMemo(() => mountedHosts ?? [], [mountedHosts])\n const allowedCountries = settings.settings?.allowedCountries\n const orgCountries = useMemo(\n () => allowedCountries ?? ['US'],\n [allowedCountries],\n )\n\n const [draft, setDraft] = useState<OutreachSequenceDraft>(() =>\n sequence\n ? outreachSequenceDraftOf(sequence)\n : emptyOutreachSequenceDraft({\n hostId: hosts.length === 1 ? hosts[0].id : '',\n allowedCountries: orgCountries,\n }),\n )\n const [attempted, setAttempted] = useState(false)\n const [serverIssues, setServerIssues] = useState<OutreachSequenceIssue[]>([])\n const [saving, setSaving] = useState(false)\n // The step whose test-send dialog is open (AGL-3325), by index.\n const [testing, setTesting] = useState<number | null>(null)\n // The draft as last drawn, which the handlers that build on it read.\n const drawn = useRef(draft)\n drawn.current = draft\n\n // A stored sequence the listener updated (a save, a status change) is the\n // new starting point.\n useEffect(() => {\n if (sequence) setDraft(outreachSequenceDraftOf(sequence))\n }, [sequence])\n // A new sequence starts on the organization's countries once they are read.\n const settingsCountries = settings.settings?.allowedCountries.join(',')\n useEffect(() => {\n if (!sequence && settingsCountries) {\n setDraft((previous) => ({\n ...previous,\n settings: {\n ...previous.settings,\n allowedCountries: settingsCountries.split(','),\n },\n }))\n }\n }, [sequence, settingsCountries])\n useEffect(() => {\n if (!sequence && !draft.hostId && hosts.length === 1)\n setDraft((previous) => ({ ...previous, hostId: hosts[0].id }))\n }, [sequence, draft.hostId, hosts])\n\n // A new sequence starts on the member's own mailbox when they have exactly\n // one that is sending.\n const ownSending = props.mailboxes.mailboxes.filter(\n (entry) => entry.connectedByUid === uid && entry.status === 'connected',\n )\n const onlyOwnMailbox = ownSending.length === 1 ? ownSending[0].id : ''\n useEffect(() => {\n if (!sequence && !draft.mailboxId && onlyOwnMailbox)\n setDraft((previous) => ({ ...previous, mailboxId: onlyOwnMailbox }))\n }, [sequence, draft.mailboxId, onlyOwnMailbox])\n\n const templates = useOutreachEmailTemplates(orgId, draft.hostId || null, uid)\n const mailbox =\n props.mailboxes.mailboxes.find((entry) => entry.id === draft.mailboxId) ??\n null\n const sender = useMemo(\n () =>\n mailbox\n ? { name: mailbox.displayName, email: mailbox.sendAs || mailbox.email }\n : null,\n [mailbox],\n )\n const archived = sequence?.status === 'archived'\n /*\n * The org's campaigns, for the picker (AGL-3254): read while the editor\n * is open. A sequence is the organization's record and so is a campaign,\n * so the choice is every campaign in the org, whichever site the\n * sequence sends as.\n */\n const campaigns = useOrgContainerOptions('campaign', orgId, { enabled: true })\n\n const issues = useMemo(() => {\n const judged = [\n ...validateOutreachSequence(draft),\n ...serverIssues,\n ] as OutreachSequenceIssue[]\n return judged.filter(\n (issue) =>\n issue.severity === 'warning' ||\n attempted ||\n serverIssues.includes(issue),\n )\n }, [draft, serverIssues, attempted])\n const issueAt = (path: string) =>\n issues.find((issue) => issue.path === path)?.message\n const stepIssues = useStepIssues(issues, draft.steps.length)\n const listIssue = issueAt('steps')\n const countriesIssue = issues.find((issue) =>\n issue.path.startsWith('settings.allowedCountries'),\n )?.message\n\n // An edit clears what the last save refused. The empty list stays the same\n // list, so an edit with nothing to clear does not change that state.\n const clearServerIssues = useCallback(\n () => setServerIssues((previous) => (previous.length ? [] : previous)),\n [],\n )\n const update = useCallback(\n (next: Partial<OutreachSequenceDraft>) => {\n clearServerIssues()\n setDraft((previous) => ({ ...previous, ...next }))\n },\n [clearServerIssues],\n )\n // Stable, for the memoized countries field: it reads the settings it\n // replaces from the draft it is given rather than from this render's.\n const setCountries = useCallback(\n (next: string[]) => {\n clearServerIssues()\n setDraft((previous) => ({\n ...previous,\n settings: { ...previous.settings, allowedCountries: next },\n }))\n },\n [clearServerIssues],\n )\n const setName = useCallback(\n (event: FieldChange) => update({ name: event.target.value }),\n [update],\n )\n const setHost = useCallback(\n (event: FieldChange) => update({ hostId: event.target.value }),\n [update],\n )\n const setMailbox = useCallback(\n (mailboxId: string) => update({ mailboxId }),\n [update],\n )\n const setCampaigns = useCallback(\n (campaignIds: string[]) => update({ campaignIds }),\n [update],\n )\n const setSettings = useCallback(\n (patch: Partial<SequenceSettings>) =>\n update({ settings: { ...drawn.current.settings, ...patch } }),\n [update],\n )\n const setStep = useCallback(\n (index: number, step: OutreachSequenceStep) =>\n update({\n steps: drawn.current.steps.map((entry, position) =>\n position === index ? step : entry,\n ),\n }),\n [update],\n )\n const moveStep = useCallback(\n (index: number, direction: -1 | 1) => {\n const steps = [...drawn.current.steps]\n const [moved] = steps.splice(index, 1)\n steps.splice(index + direction, 0, moved)\n update({ steps })\n },\n [update],\n )\n const removeStep = useCallback(\n (index: number) =>\n update({\n steps: drawn.current.steps.filter(\n (_entry, position) => position !== index,\n ),\n }),\n [update],\n )\n const addEmail = useCallback(\n () =>\n update({\n steps: [\n ...drawn.current.steps,\n newOutreachEmailStep(drawn.current.steps),\n ],\n }),\n [update],\n )\n const addTask = useCallback(\n (kind: OutreachTaskKind) =>\n update({\n steps: [\n ...drawn.current.steps,\n newOutreachTaskStep(drawn.current.steps, kind),\n ],\n }),\n [update],\n )\n const emailCount = draft.steps.filter((step) => step.kind === 'email').length\n const full = draft.steps.length >= OUTREACH_MAX_STEPS\n const firstEmail = draft.steps.findIndex((entry) => entry.kind === 'email')\n const threadSubject = (index: number) => {\n for (let position = index - 1; position >= 0; position -= 1) {\n const step = draft.steps[position]\n if (step.kind === 'email' && !isInThreadEmailStep(draft.steps, position))\n return step.subject\n }\n return ''\n }\n\n const save = async () => {\n setAttempted(true)\n if (\n validateOutreachSequence(draft).some(\n (issue) => issue.severity === 'error',\n )\n )\n return\n setSaving(true)\n try {\n const answer = await api.saveSequence(sequence?.id ?? null, draft)\n setServerIssues([])\n setAttempted(false)\n enqueueSnackbar(\n answer.created ? 'Sequence created.' : 'Sequence saved.',\n { variant: 'success' },\n )\n props.onSaved(answer.sequence)\n } catch (error) {\n if (error instanceof OutreachRouteError && error.issues.length) {\n setServerIssues(\n error.issues.filter(\n (issue): issue is OutreachSequenceIssue => 'path' in issue,\n ),\n )\n }\n enqueueSnackbar((error as Error).message, {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setSaving(false)\n }\n }\n // The save as last drawn, behind a handler that keeps its identity.\n const drawnSave = useRef(save)\n drawnSave.current = save\n const onSave = useCallback(() => void drawnSave.current(), [])\n\n const siteName = hosts.find((host) => host.id === draft.hostId)?.name ?? ''\n const draftCountries = draft.settings.allowedCountries\n const countryOptions = useMemo(\n () => [...new Set([...orgCountries, ...draftCountries])],\n [orgCountries, draftCountries],\n )\n /*\n * A test sends the step as STORED (AGL-3325): the route reads the saved\n * sequence, so a new one has nothing to send yet and an edited one sends\n * its last save — said on the button and in the dialog rather than found\n * out in the inbox.\n */\n const unsaved =\n sequence !== null &&\n JSON.stringify(draft) !== JSON.stringify(outreachSequenceDraftOf(sequence))\n const sendTestDisabledReason = !sequence\n ? 'Create the sequence to send a test of it.'\n : !draft.mailboxId\n ? 'Choose a mailbox to send the test from.'\n : null\n\n return (\n <Grid container spacing={2}>\n <Grid size={{ xs: 12, md: 7 }}>\n <Stack spacing={2}>\n {archived ? (\n <Alert severity=\"info\">\n This sequence is archived, so it can’t be edited.\n </Alert>\n ) : null}\n <SequenceCard\n orgId={orgId}\n uid={uid}\n name={draft.name}\n hostId={draft.hostId}\n mailboxId={draft.mailboxId}\n campaignIds={draft.campaignIds}\n hosts={hosts}\n mailboxes={props.mailboxes}\n mailboxesPath={props.mailboxesPath}\n campaignOptions={campaigns.options}\n noCampaigns={campaigns.ready && !campaigns.options.length}\n nameIssue={issueAt('name')}\n hostIssue={issueAt('hostId')}\n mailboxIssue={issueAt('mailboxId')}\n campaignsIssue={issueAt('campaignIds')}\n archived={archived}\n saving={saving}\n saveLabel={sequence ? 'Save' : 'Create sequence'}\n onCancel={props.onCancel}\n onSave={onSave}\n onName={setName}\n onHost={setHost}\n onMailbox={setMailbox}\n onCampaigns={setCampaigns}\n />\n\n {listIssue ? <Alert severity=\"error\">{listIssue}</Alert> : null}\n {draft.steps.map((step, index) => {\n const inThread = isInThreadEmailStep(draft.steps, index)\n return (\n <SequenceStepItem\n key={step.id || `step-${index}`}\n step={step}\n index={index}\n count={draft.steps.length}\n firstEmail={firstEmail === index}\n inThread={inThread}\n // Read only by an email sent in the thread, so no other\n // step is redrawn as the subject it replies to is typed.\n threadSubject={inThread ? threadSubject(index) : ''}\n templates={templates.data}\n issues={stepIssues[index]}\n disabled={archived}\n canSendTest={step.kind === 'email' && !archived}\n sendTestDisabledReason={sendTestDisabledReason}\n onStepChange={setStep}\n onStepMove={moveStep}\n onStepRemove={removeStep}\n onStepTest={setTesting}\n />\n )\n })}\n <SequenceAddStep\n emailDisabled={\n archived || full || emailCount >= OUTREACH_MAX_EMAIL_STEPS\n }\n taskDisabled={archived || full}\n onAddEmail={addEmail}\n onAddTask={addTask}\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`Up to ${OUTREACH_MAX_STEPS} steps, ${OUTREACH_MAX_EMAIL_STEPS} of them emails.`}\n </Typography>\n\n <SequenceSendingCard\n settings={draft.settings}\n countryOptions={countryOptions}\n countriesIssue={countriesIssue}\n daysIssue={issueAt('settings.window.days')}\n hoursIssue={issueAt('settings.window')}\n disabled={archived}\n onCountries={setCountries}\n onSettings={setSettings}\n />\n\n </Stack>\n </Grid>\n {sequence && testing !== null ? (\n <OutreachStepTestDialog\n open\n onClose={() => setTesting(null)}\n orgId={orgId}\n sequence={sequence}\n stepIndex={testing}\n contactGroupId={\n sequence.hostId\n ? consentGroupForHost(props.org ?? null, sequence.hostId).groupId\n : ''\n }\n selfEmail={user?.email ?? null}\n unsaved={unsaved}\n api={api}\n />\n ) : null}\n <Grid size={{ xs: 12, md: 5 }}>\n <Box sx={PREVIEW_COLUMN}>\n <MemoSequencePreview\n steps={draft.steps}\n orgSettings={settings.settings}\n orgSettingsStatus={settings.status}\n templates={templates.data}\n sender={sender}\n siteName={siteName}\n />\n </Box>\n </Grid>\n </Grid>\n )\n}\nOutreachSequenceEditor.displayName = 'OutreachSequenceEditor'\n\nexport default OutreachSequenceEditor\n"],"names":["pluginDocsHelp","consentGroupForHost","mdiPlus","CardDisplay","MdiIcon","ContainerPicker","useSnackbar","useOrgContainerOptions","useUser","Alert","Autocomplete","Box","Button","Chip","FormControlLabel","Grid","Menu","MenuItem","Stack","Switch","TextField","Typography","memo","useCallback","useEffect","useMemo","useRef","useState","isInThreadEmailStep","OUTREACH_SEQUENCE_NAME_MAX","validateOutreachSequence","outreachCountryLabel","OUTREACH_MAX_EMAIL_STEPS","OUTREACH_MAX_STEPS","OUTREACH_TASK_KIND_LABELS","OUTREACH_TASK_KINDS","emptyOutreachSequenceDraft","newOutreachEmailStep","newOutreachTaskStep","outreachSequenceDraftOf","OutreachSendWindowFields","OutreachSequenceMailboxPicker","OutreachSequencePreview","OutreachStepCard","OutreachStepTestDialog","OutreachRouteError","useOutreachApi","useOutreachEmailTemplates","stepIssueKey","path","match","exec","field","index","Number","OutreachCountriesField","props","multiple","options","value","getOptionLabel","onChange","_event","next","disabled","renderValue","getItemProps","map","code","key","item","size","label","renderInput","params","error","Boolean","issue","helperText","useStepIssues","issues","count","held","found","Array","from","length","record","undefined","message","current","JSON","stringify","before","entry","MemoTextField","MemoMailboxPicker","MemoContainerPicker","MemoSendWindowFields","MemoSequencePreview","NAME_SLOT_PROPS","htmlInput","maxLength","ADD_STEP_ROW","flexWrap","rowGap","PREVIEW_COLUMN","position","md","top","SequenceSiteField","hosts","select","some","host","id","fullWidth","name","SequenceSaveActions","direction","spacing","onCancel","variant","onClick","saving","onSave","saveLabel","SequenceCard","archived","header","help","anchor","HeaderProps","action","contentGutterX","contentGutterY","onName","nameIssue","slotProps","hostId","hostIssue","onHost","orgId","uid","mailboxes","mailboxesPath","mailboxId","onMailbox","mailboxIssue","kind","campaignOptions","campaignIds","onCampaigns","campaignsIssue","empty","noCampaigns","emptyText","SequenceStepItem","canSendTest","onStepChange","onStepMove","onStepRemove","onStepTest","card","step","onMove","onRemove","onSendTest","SequenceAddStep","onAddTask","taskAnchor","setTaskAnchor","sx","startIcon","fontSize","emailDisabled","onAddEmail","taskDisabled","event","currentTarget","aria-haspopup","anchorEl","open","onClose","SequenceSendingCard","settings","onSettings","setAllowCustomers","allowCustomers","target","checked","setTrackClicks","trackClicks","setCountOpens","countOpens","setListUnsubscribe","listUnsubscribe","setWindow","window","excerpt","countryOptions","allowedCountries","onCountries","countriesIssue","control","color","daysIssue","hoursIssue","OutreachSequenceEditor","orgMount","sequence","api","enqueueSnackbar","data","user","mountedHosts","orgCountries","draft","setDraft","attempted","setAttempted","serverIssues","setServerIssues","setSaving","testing","setTesting","drawn","settingsCountries","join","previous","split","ownSending","filter","connectedByUid","status","onlyOwnMailbox","templates","mailbox","find","sender","displayName","email","sendAs","campaigns","enabled","judged","severity","includes","issueAt","stepIssues","steps","listIssue","startsWith","clearServerIssues","update","setCountries","setName","setHost","setMailbox","setCampaigns","setSettings","patch","setStep","moveStep","moved","splice","removeStep","_entry","addEmail","addTask","emailCount","full","firstEmail","findIndex","threadSubject","subject","save","answer","saveSequence","created","onSaved","allowDuplicate","drawnSave","siteName","draftCountries","Set","unsaved","sendTestDisabledReason","container","xs","ready","inThread","stepIndex","contactGroupId","org","groupId","selfEmail","orgSettings","orgSettingsStatus"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/sequence-editor.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, type ConsolePluginOrgMount } from '@aglyn/aglyn'\nimport { consentGroupForHost } from '@aglyn/aglyn/app-utils/consent-groups'\nimport { mdiPlus } from '@aglyn/shared-data-mdi'\nimport { CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport ContainerPicker, {\n type ContainerPickerProps,\n} from '@aglyn/tenant-feature-instance/components/container-picker'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useOrgContainerOptions, useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Autocomplete,\n Box,\n Button,\n Chip,\n FormControlLabel,\n Grid,\n Menu,\n MenuItem,\n Stack,\n Switch,\n TextField,\n Typography,\n} from '@mui/material'\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n isInThreadEmailStep,\n OUTREACH_SEQUENCE_NAME_MAX,\n validateOutreachSequence,\n} from '../engine/sequence-validation'\nimport { outreachCountryLabel } from '../model/compliance-settings'\nimport {\n OUTREACH_MAX_EMAIL_STEPS,\n OUTREACH_MAX_STEPS,\n OUTREACH_TASK_KIND_LABELS,\n OUTREACH_TASK_KINDS,\n type OutreachSequence,\n type OutreachSequenceStep,\n type OutreachTaskKind,\n} from '../model/outreach.types'\nimport {\n emptyOutreachSequenceDraft,\n newOutreachEmailStep,\n newOutreachTaskStep,\n outreachSequenceDraftOf,\n type OutreachSequenceDraft,\n type OutreachSequenceIssue,\n} from '../model/sequence-draft'\nimport { OutreachSendWindowFields } from './send-window-fields'\nimport { OutreachSequenceMailboxPicker, OutreachSequenceRotationPicker } from './sequence-mailbox-picker'\nimport { OutreachSequencePreview } from './sequence-preview'\nimport {\n OutreachStepCard,\n type OutreachStepCardProps,\n} from './sequence-step-card'\nimport { OutreachStepTestDialog } from './step-test-dialog'\nimport { OutreachRouteError, useOutreachApi } from './use-outreach-api'\nimport { useOutreachEmailTemplates } from './use-outreach-crm'\nimport type { OutreachMailboxesResult } from './use-outreach-mailboxes'\nimport type { OutreachSettingsLoad } from './use-outreach-settings'\n\nexport interface OutreachSequenceEditorProps {\n orgId: string\n orgMount?: ConsolePluginOrgMount\n /** The organization document, for the consent group a test send's person picker searches (AGL-3325). */\n org?: Record<string, unknown> | null\n /** The stored sequence, or `null` for a new one. */\n sequence: OutreachSequence | null\n /** The organization's compliance settings: its countries, and the preview's footer. */\n settings: OutreachSettingsLoad\n /**\n * The organization's mailboxes, from the Mailboxes section's listener:\n * what the picker offers, and who the preview's emails are from.\n */\n mailboxes: OutreachMailboxesResult\n /** The Mailboxes section, where the picker sends a member to connect one. */\n mailboxesPath: string\n onSaved(sequence: OutreachSequence): void\n onCancel?(): void\n}\n\n/** The step a dotted issue path is about, and the field within it. */\nfunction stepIssueKey(path: string): { index: number; field: string } | null {\n const match = /^steps\\.(\\d+)(?:\\.(.+))?$/.exec(path)\n if (!match) return null\n const field = match[2] ?? 'step'\n return { index: Number(match[1]), field: field === 'id' ? 'step' : field }\n}\n\ninterface OutreachCountriesFieldProps {\n options: readonly string[]\n value: readonly string[]\n onChange(next: string[]): void\n issue?: string\n disabled: boolean\n}\n\n/**\n * The countries a sequence sends to, as chips in an Autocomplete.\n *\n * MEMOIZED, AND EVERY PROP IT TAKES IS STABLE WHILE THE COUNTRIES ARE\n * (AGL-3423). A multiple Autocomplete hands its input a new chip array as\n * `startAdornment` on every render, and MUI's `InputBase` copies that into\n * its `FormControl` from a passive effect — a state update after every\n * commit this field takes part in. React 19 counts a commit that leaves such\n * an update pending as a nested update, and keystrokes the browser delivers\n * back to back (a held key, fast typing on a busy page) commit one after\n * another with nothing in between to clear the count: fifty-one of them and\n * the next keystroke's own `setState` throws \"Maximum update depth exceeded\"\n * (minified error #185), which is what typing a step's body reported. Kept\n * out of the editor's other renders, the field commits only when the\n * countries, their options or their issue change.\n */\nconst OutreachCountriesField = memo(function OutreachCountriesField(\n props: OutreachCountriesFieldProps,\n) {\n return (\n <Autocomplete<string, true>\n multiple\n options={props.options}\n value={props.value as string[]}\n getOptionLabel={outreachCountryLabel}\n onChange={(_event, next) => props.onChange(next)}\n disabled={props.disabled}\n renderValue={(value, getItemProps) =>\n value.map((code, index) => {\n const { key, ...item } = getItemProps({ index })\n return (\n <Chip\n key={key}\n size=\"small\"\n label={outreachCountryLabel(code)}\n {...item}\n />\n )\n })\n }\n renderInput={(params) => (\n <TextField\n {...params}\n label=\"Countries\"\n error={Boolean(props.issue)}\n helperText={\n props.issue ??\n 'Among the countries your organization allows. Cold contacts are emailed only in the United States.'\n }\n />\n )}\n />\n )\n})\n\n/** Each step's issues by the field they are about, as its card reads them. */\ntype StepIssues = Partial<Record<string, string>>\n\n/**\n * Each step's issues, the SAME record for a step while what it holds reads\n * the same (AGL-3423), so a step a keystroke did not touch keeps its props.\n */\nfunction useStepIssues(\n issues: readonly OutreachSequenceIssue[],\n count: number,\n): StepIssues[] {\n const held = useRef<Array<{ key: string; value: StepIssues }>>([])\n return useMemo(() => {\n const found: Record<string, string>[] = Array.from(\n { length: count },\n () => ({}),\n )\n for (const issue of issues) {\n const key = stepIssueKey(issue.path)\n const record = key ? found[key.index] : undefined\n if (key && record && !record[key.field])\n record[key.field] = issue.message\n }\n held.current = found.map((value, index) => {\n const key = JSON.stringify(value)\n const before = held.current[index]\n return before?.key === key ? before : { key, value }\n })\n return held.current.map((entry) => entry.value)\n }, [issues, count])\n}\n\n/** A text field that redraws only when what it shows changes (AGL-3423). */\nconst MemoTextField = memo(TextField) as typeof TextField\n\n/*\n * The sections below are drawn from the one draft, and each redraws only\n * when what it shows changes (AGL-3423).\n */\nconst MemoMailboxPicker = memo(OutreachSequenceMailboxPicker)\nconst MemoRotationPicker = memo(OutreachSequenceRotationPicker)\n/** A stable empty rotation, so the picker's props hold still while there is none. */\nconst NO_ROTATION: readonly string[] = []\nconst MemoContainerPicker = memo(ContainerPicker)\nconst MemoSendWindowFields = memo(OutreachSendWindowFields)\nconst MemoSequencePreview = memo(OutreachSequencePreview)\n\ntype FieldChange = { target: { value: string } }\ntype SwitchChange = { target: { checked: boolean } }\ntype SequenceSettings = OutreachSequenceDraft['settings']\n\nconst NAME_SLOT_PROPS = {\n htmlInput: { maxLength: OUTREACH_SEQUENCE_NAME_MAX + 20 },\n}\nconst ADD_STEP_ROW = { flexWrap: 'wrap', rowGap: 1 } as const\nconst PREVIEW_COLUMN = {\n position: { md: 'sticky' },\n top: { md: 16 },\n} as const\n\nconst SequenceSiteField = memo(function SequenceSiteField(props: {\n hosts: ConsolePluginOrgMount['hosts']\n value: string\n issue?: string\n disabled: boolean\n onChange(event: FieldChange): void\n}) {\n const { hosts, value, issue } = props\n return (\n <TextField\n select\n label=\"Site\"\n value={hosts.some((host) => host.id === value) ? value : ''}\n onChange={props.onChange}\n disabled={props.disabled || !hosts.length}\n error={Boolean(issue)}\n helperText={issue ?? 'The site whose contacts this sequence emails.'}\n fullWidth\n >\n {hosts.map((host) => (\n <MenuItem key={host.id} value={host.id}>\n {host.name}\n </MenuItem>\n ))}\n </TextField>\n )\n})\n\n/** The sequence card's header actions: Cancel, and the save of the whole sequence. */\nconst SequenceSaveActions = memo(function SequenceSaveActions(props: {\n saving: boolean\n /** \"Save\" for a stored sequence, \"Create sequence\" for a new one. */\n saveLabel: string\n onCancel?(): void\n onSave(): void\n}) {\n return (\n <Stack direction=\"row\" spacing={1}>\n {props.onCancel ? (\n <Button\n size=\"small\"\n variant=\"text\"\n onClick={props.onCancel}\n disabled={props.saving}\n >\n Cancel\n </Button>\n ) : null}\n <Button\n size=\"small\"\n variant=\"contained\"\n onClick={props.onSave}\n disabled={props.saving}\n >\n {props.saving ? 'Saving…' : props.saveLabel}\n </Button>\n </Stack>\n )\n})\n\ninterface SequenceCardProps {\n orgId: string\n uid: string | null\n name: string\n hostId: string\n mailboxId: string\n /** The mailboxes it rotates through beside its own (AGL-3489). */\n mailboxIds: readonly string[]\n campaignIds: readonly string[]\n hosts: ConsolePluginOrgMount['hosts']\n mailboxes: OutreachMailboxesResult\n mailboxesPath: string\n campaignOptions: ContainerPickerProps['options']\n /** The organization has no campaigns at all. */\n noCampaigns: boolean\n nameIssue?: string\n hostIssue?: string\n mailboxIssue?: string\n rotationIssue?: string\n campaignsIssue?: string\n archived: boolean\n saving: boolean\n saveLabel: string\n onCancel?(): void\n onSave(): void\n onName(event: FieldChange): void\n onHost(event: FieldChange): void\n onMailbox(mailboxId: string): void\n onRotation(mailboxIds: string[]): void\n onCampaigns(campaignIds: string[]): void\n}\n\n/** The sequence's own card: its name, site, mailbox and campaigns. */\nconst SequenceCard = memo(function SequenceCard(props: SequenceCardProps) {\n const { archived } = props\n return (\n <CardDisplay\n header=\"Sequence\"\n help={pluginDocsHelp('sequences', { anchor: '#build-a-sequence' })}\n // The whole sequence (steps and sending rules included) saves\n // from its first card's header, where the console puts a card's\n // actions (AGL-3333).\n HeaderProps={{\n action: archived ? undefined : (\n <SequenceSaveActions\n saving={props.saving}\n saveLabel={props.saveLabel}\n onCancel={props.onCancel}\n onSave={props.onSave}\n />\n ),\n }}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <MemoTextField\n label=\"Name\"\n value={props.name}\n onChange={props.onName}\n disabled={archived}\n error={Boolean(props.nameIssue)}\n helperText={props.nameIssue}\n slotProps={NAME_SLOT_PROPS}\n fullWidth\n />\n <SequenceSiteField\n hosts={props.hosts}\n value={props.hostId}\n issue={props.hostIssue}\n disabled={archived}\n onChange={props.onHost}\n />\n <MemoMailboxPicker\n orgId={props.orgId}\n uid={props.uid}\n mailboxes={props.mailboxes}\n mailboxesPath={props.mailboxesPath}\n value={props.mailboxId}\n onChange={props.onMailbox}\n error={props.mailboxIssue}\n disabled={archived}\n />\n <MemoRotationPicker\n orgId={props.orgId}\n uid={props.uid}\n mailboxes={props.mailboxes}\n mailboxId={props.mailboxId}\n value={props.mailboxIds}\n onChange={props.onRotation}\n error={props.rotationIssue}\n disabled={archived}\n />\n {/*\n The campaigns this sequence is part of (AGL-3254), picked the\n way a form's page picks them. Everyone enrolled joins them,\n and what the sequence produces is reported under them; it\n does not change who is enrolled or what is sent.\n */}\n <MemoContainerPicker\n kind=\"campaign\"\n options={props.campaignOptions}\n value={props.campaignIds}\n onChange={props.onCampaigns}\n label=\"Campaigns\"\n helperText={\n props.campaignsIssue ??\n 'The campaigns this sequence is part of. Everyone enrolled joins them, and its sends, replies, meetings and conversions count on their pages.'\n }\n disabled={archived}\n empty={props.noCampaigns}\n emptyText=\"There are no campaigns yet. Create one from Marketing to file this sequence under it.\"\n />\n </Stack>\n </CardDisplay>\n )\n})\n\ninterface SequenceStepItemProps\n extends Omit<\n OutreachStepCardProps,\n 'onChange' | 'onMove' | 'onRemove' | 'onSendTest'\n > {\n /** Whether the step offers a test send: an email in a sequence that is not archived. */\n canSendTest: boolean\n onStepChange(index: number, step: OutreachSequenceStep): void\n onStepMove(index: number, direction: -1 | 1): void\n onStepRemove(index: number): void\n onStepTest(index: number): void\n}\n\n/**\n * One step's card, bound to its position. Memoized, with handlers that keep\n * their identity, so a keystroke in one step leaves the others undrawn.\n */\nconst SequenceStepItem = memo(function SequenceStepItem(\n props: SequenceStepItemProps,\n) {\n const {\n index,\n canSendTest,\n onStepChange,\n onStepMove,\n onStepRemove,\n onStepTest,\n ...card\n } = props\n const onChange = useCallback(\n (step: OutreachSequenceStep) => onStepChange(index, step),\n [index, onStepChange],\n )\n const onMove = useCallback(\n (direction: -1 | 1) => onStepMove(index, direction),\n [index, onStepMove],\n )\n const onRemove = useCallback(\n () => onStepRemove(index),\n [index, onStepRemove],\n )\n const onSendTest = useCallback(() => onStepTest(index), [index, onStepTest])\n return (\n <OutreachStepCard\n {...card}\n index={index}\n onChange={onChange}\n onMove={onMove}\n onRemove={onRemove}\n onSendTest={canSendTest ? onSendTest : undefined}\n />\n )\n})\n\n/** Adds an email, or a task of a kind picked from its menu. */\nconst SequenceAddStep = memo(function SequenceAddStep(props: {\n emailDisabled: boolean\n taskDisabled: boolean\n onAddEmail(): void\n onAddTask(kind: OutreachTaskKind): void\n}) {\n const { onAddTask } = props\n const [taskAnchor, setTaskAnchor] = useState<HTMLElement | null>(null)\n return (\n <Stack direction=\"row\" spacing={1} sx={ADD_STEP_ROW}>\n <Button\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiPlus.path} fontSize=\"small\" />}\n disabled={props.emailDisabled}\n onClick={props.onAddEmail}\n >\n Add email\n </Button>\n <Button\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiPlus.path} fontSize=\"small\" />}\n disabled={props.taskDisabled}\n onClick={(event) => setTaskAnchor(event.currentTarget)}\n aria-haspopup=\"menu\"\n >\n Add task\n </Button>\n <Menu\n anchorEl={taskAnchor}\n open={Boolean(taskAnchor)}\n onClose={() => setTaskAnchor(null)}\n >\n {OUTREACH_TASK_KINDS.map((kind: OutreachTaskKind) => (\n <MenuItem\n key={kind}\n onClick={() => {\n setTaskAnchor(null)\n onAddTask(kind)\n }}\n >\n {OUTREACH_TASK_KIND_LABELS[kind]}\n </MenuItem>\n ))}\n </Menu>\n </Stack>\n )\n})\n\ninterface SequenceSendingCardProps {\n settings: SequenceSettings\n countryOptions: readonly string[]\n countriesIssue?: string\n daysIssue?: string\n hoursIssue?: string\n disabled: boolean\n onCountries(next: string[]): void\n onSettings(patch: Partial<SequenceSettings>): void\n}\n\n/** Who the sequence sends to, and when: its countries, switches and hours. */\nconst SequenceSendingCard = memo(function SequenceSendingCard(\n props: SequenceSendingCardProps,\n) {\n const { settings, disabled, onSettings } = props\n const setAllowCustomers = useCallback(\n (event: SwitchChange) =>\n onSettings({ allowCustomers: event.target.checked }),\n [onSettings],\n )\n const setTrackClicks = useCallback(\n (event: SwitchChange) => onSettings({ trackClicks: event.target.checked }),\n [onSettings],\n )\n const setCountOpens = useCallback(\n (event: SwitchChange) => onSettings({ countOpens: event.target.checked }),\n [onSettings],\n )\n const setListUnsubscribe = useCallback(\n (event: SwitchChange) =>\n onSettings({ listUnsubscribe: event.target.checked }),\n [onSettings],\n )\n const setWindow = useCallback(\n (window: SequenceSettings['window']) => onSettings({ window }),\n [onSettings],\n )\n return (\n <CardDisplay\n header=\"Who it sends to, and when\"\n help={pluginDocsHelp('sequences', {\n anchor: '#build-a-sequence',\n excerpt:\n 'A sequence sends only to the countries both it and your organization allow, and in its mailbox’s sending hours unless it has its own.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <OutreachCountriesField\n options={props.countryOptions}\n value={settings.allowedCountries}\n onChange={props.onCountries}\n issue={props.countriesIssue}\n disabled={disabled}\n />\n <FormControlLabel\n control={\n <Switch\n checked={settings.allowCustomers}\n onChange={setAllowCustomers}\n disabled={disabled}\n />\n }\n label=\"Include customers\"\n />\n {/*\n * Click tracking (AGL-3239), with its cost stated where it is\n * chosen rather than in a document nobody opens. Off by\n * default: it changes the link a cold recipient sees. The\n * emails stay plain text either way; opens are the separate\n * switch below.\n */}\n <Stack spacing={0}>\n <FormControlLabel\n control={\n <Switch\n checked={settings.trackClicks}\n onChange={setTrackClicks}\n disabled={disabled}\n />\n }\n label=\"Count link clicks\"\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n Links in these emails are replaced with links of ours that\n forward to the same page, so clicks can be counted. The\n recipient sees the replacement, not your address. The\n emails stay plain text.\n </Typography>\n </Stack>\n {/*\n * Open counting (AGL-3395), off by default, its cost stated\n * where it is chosen: an HTML copy with a tracking image is the\n * least one-to-one thing a sequence email can carry, so it is\n * for measuring a slice, not for every sequence.\n */}\n <Stack spacing={0}>\n <FormControlLabel\n control={\n <Switch\n checked={settings.countOpens}\n onChange={setCountOpens}\n disabled={disabled}\n />\n }\n label=\"Count opens\"\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n Each email also goes out as HTML — the same words — with a\n tiny tracking image, so opens can be counted. The plain-text\n version is unchanged. It makes the email look less like one\n written by hand, and some spam filters score HTML with a\n remote image against you, so turn it on to measure a slice\n of your sends rather than for every sequence. Gmail opens\n count; Apple Mail loads every image on arrival, so its loads\n are counted separately.\n </Typography>\n </Stack>\n {/*\n * The mail-client unsubscribe button (AGL-3296), off by\n * default: the header is what makes Apple Mail, Gmail and\n * Outlook present a one-to-one email as a mailing list. The\n * footer's \"reply 'no'\" line is the way out either way.\n */}\n <Stack spacing={0}>\n <FormControlLabel\n control={\n <Switch\n checked={settings.listUnsubscribe}\n onChange={setListUnsubscribe}\n disabled={disabled}\n />\n }\n label=\"Add a mail-client unsubscribe button\"\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n Adds the List-Unsubscribe header, so the recipient’s mail\n app shows its own Unsubscribe button. It’s the easiest way\n out for them, and fewer people mark you as spam when they\n have it, but mail apps then label the email as coming from\n a mailing list. Off, the footer’s “reply ‘no’” line is the\n way out, and it’s always there.\n </Typography>\n </Stack>\n <MemoSendWindowFields\n window={settings.window}\n onChange={setWindow}\n daysIssue={props.daysIssue}\n hoursIssue={props.hoursIssue}\n disabled={disabled}\n />\n </Stack>\n </CardDisplay>\n )\n})\n\n/**\n * The sequence editor (AGL-2980): the name, the site and mailbox, the steps,\n * who it sends to and when, beside a live preview of each email.\n *\n * Every issue the engine's validator finds is shown beside its field — the\n * same validator the save route refuses with — errors once a save was\n * attempted, warnings as soon as they appear. What only the server can\n * judge (whose mailbox, which countries the organization allows, what may\n * no longer change once people are enrolled) comes back from the save and\n * is shown in the same places.\n *\n * ## A keystroke redraws its own field (AGL-3423)\n *\n * The whole sequence is one draft, so every letter typed anywhere is a new\n * draft, and drawing the editor from it inline redrew every field of every\n * step, the settings and the preview with each one: 17 inputs and some 1,150\n * components for one letter in a three-step sequence. That cost is what lets\n * typed input queue, and queued keystrokes processed back to back are what\n * drove the countries chips into React's #185. The sequence card, each step,\n * the sending card and the preview are memoized and handed only what they\n * show, through handlers that keep their identity; the handlers that wrote\n * from the draft as drawn still do, through `drawn`. A letter now redraws the\n * field it lands in, and the preview when it shows that step's email.\n */\nexport function OutreachSequenceEditor(props: OutreachSequenceEditorProps) {\n const { orgId, orgMount, sequence, settings } = props\n const api = useOutreachApi(orgId)\n const { enqueueSnackbar } = useSnackbar()\n const { data: user } = useUser()\n const uid = user?.uid ?? null\n const mountedHosts = orgMount?.hosts\n const hosts = useMemo(() => mountedHosts ?? [], [mountedHosts])\n const allowedCountries = settings.settings?.allowedCountries\n const orgCountries = useMemo(\n () => allowedCountries ?? ['US'],\n [allowedCountries],\n )\n\n const [draft, setDraft] = useState<OutreachSequenceDraft>(() =>\n sequence\n ? outreachSequenceDraftOf(sequence)\n : emptyOutreachSequenceDraft({\n hostId: hosts.length === 1 ? hosts[0].id : '',\n allowedCountries: orgCountries,\n }),\n )\n const [attempted, setAttempted] = useState(false)\n const [serverIssues, setServerIssues] = useState<OutreachSequenceIssue[]>([])\n const [saving, setSaving] = useState(false)\n // The step whose test-send dialog is open (AGL-3325), by index.\n const [testing, setTesting] = useState<number | null>(null)\n // The draft as last drawn, which the handlers that build on it read.\n const drawn = useRef(draft)\n drawn.current = draft\n\n // A stored sequence the listener updated (a save, a status change) is the\n // new starting point.\n useEffect(() => {\n if (sequence) setDraft(outreachSequenceDraftOf(sequence))\n }, [sequence])\n // A new sequence starts on the organization's countries once they are read.\n const settingsCountries = settings.settings?.allowedCountries.join(',')\n useEffect(() => {\n if (!sequence && settingsCountries) {\n setDraft((previous) => ({\n ...previous,\n settings: {\n ...previous.settings,\n allowedCountries: settingsCountries.split(','),\n },\n }))\n }\n }, [sequence, settingsCountries])\n useEffect(() => {\n if (!sequence && !draft.hostId && hosts.length === 1)\n setDraft((previous) => ({ ...previous, hostId: hosts[0].id }))\n }, [sequence, draft.hostId, hosts])\n\n // A new sequence starts on the member's own mailbox when they have exactly\n // one that is sending.\n const ownSending = props.mailboxes.mailboxes.filter(\n (entry) => entry.connectedByUid === uid && entry.status === 'connected',\n )\n const onlyOwnMailbox = ownSending.length === 1 ? ownSending[0].id : ''\n useEffect(() => {\n if (!sequence && !draft.mailboxId && onlyOwnMailbox)\n setDraft((previous) => ({ ...previous, mailboxId: onlyOwnMailbox }))\n }, [sequence, draft.mailboxId, onlyOwnMailbox])\n\n const templates = useOutreachEmailTemplates(orgId, draft.hostId || null, uid)\n const mailbox =\n props.mailboxes.mailboxes.find((entry) => entry.id === draft.mailboxId) ??\n null\n const sender = useMemo(\n () =>\n mailbox\n ? { name: mailbox.displayName, email: mailbox.sendAs || mailbox.email }\n : null,\n [mailbox],\n )\n const archived = sequence?.status === 'archived'\n /*\n * The org's campaigns, for the picker (AGL-3254): read while the editor\n * is open. A sequence is the organization's record and so is a campaign,\n * so the choice is every campaign in the org, whichever site the\n * sequence sends as.\n */\n const campaigns = useOrgContainerOptions('campaign', orgId, { enabled: true })\n\n const issues = useMemo(() => {\n const judged = [\n ...validateOutreachSequence(draft),\n ...serverIssues,\n ] as OutreachSequenceIssue[]\n return judged.filter(\n (issue) =>\n issue.severity === 'warning' ||\n attempted ||\n serverIssues.includes(issue),\n )\n }, [draft, serverIssues, attempted])\n const issueAt = (path: string) =>\n issues.find((issue) => issue.path === path)?.message\n const stepIssues = useStepIssues(issues, draft.steps.length)\n const listIssue = issueAt('steps')\n const countriesIssue = issues.find((issue) =>\n issue.path.startsWith('settings.allowedCountries'),\n )?.message\n\n // An edit clears what the last save refused. The empty list stays the same\n // list, so an edit with nothing to clear does not change that state.\n const clearServerIssues = useCallback(\n () => setServerIssues((previous) => (previous.length ? [] : previous)),\n [],\n )\n const update = useCallback(\n (next: Partial<OutreachSequenceDraft>) => {\n clearServerIssues()\n setDraft((previous) => ({ ...previous, ...next }))\n },\n [clearServerIssues],\n )\n // Stable, for the memoized countries field: it reads the settings it\n // replaces from the draft it is given rather than from this render's.\n const setCountries = useCallback(\n (next: string[]) => {\n clearServerIssues()\n setDraft((previous) => ({\n ...previous,\n settings: { ...previous.settings, allowedCountries: next },\n }))\n },\n [clearServerIssues],\n )\n const setName = useCallback(\n (event: FieldChange) => update({ name: event.target.value }),\n [update],\n )\n const setHost = useCallback(\n (event: FieldChange) => update({ hostId: event.target.value }),\n [update],\n )\n const setMailbox = useCallback(\n (mailboxId: string) =>\n update({\n mailboxId,\n // The sequence's own mailbox is never also one it rotates through.\n mailboxIds: drawn.current.mailboxIds?.filter((id) => id !== mailboxId).length\n ? drawn.current.mailboxIds.filter((id) => id !== mailboxId)\n : undefined,\n }),\n [update],\n )\n const setRotation = useCallback(\n (mailboxIds: string[]) => update({ mailboxIds: mailboxIds.length ? mailboxIds : undefined }),\n [update],\n )\n const setCampaigns = useCallback(\n (campaignIds: string[]) => update({ campaignIds }),\n [update],\n )\n const setSettings = useCallback(\n (patch: Partial<SequenceSettings>) =>\n update({ settings: { ...drawn.current.settings, ...patch } }),\n [update],\n )\n const setStep = useCallback(\n (index: number, step: OutreachSequenceStep) =>\n update({\n steps: drawn.current.steps.map((entry, position) =>\n position === index ? step : entry,\n ),\n }),\n [update],\n )\n const moveStep = useCallback(\n (index: number, direction: -1 | 1) => {\n const steps = [...drawn.current.steps]\n const [moved] = steps.splice(index, 1)\n steps.splice(index + direction, 0, moved)\n update({ steps })\n },\n [update],\n )\n const removeStep = useCallback(\n (index: number) =>\n update({\n steps: drawn.current.steps.filter(\n (_entry, position) => position !== index,\n ),\n }),\n [update],\n )\n const addEmail = useCallback(\n () =>\n update({\n steps: [\n ...drawn.current.steps,\n newOutreachEmailStep(drawn.current.steps),\n ],\n }),\n [update],\n )\n const addTask = useCallback(\n (kind: OutreachTaskKind) =>\n update({\n steps: [\n ...drawn.current.steps,\n newOutreachTaskStep(drawn.current.steps, kind),\n ],\n }),\n [update],\n )\n const emailCount = draft.steps.filter((step) => step.kind === 'email').length\n const full = draft.steps.length >= OUTREACH_MAX_STEPS\n const firstEmail = draft.steps.findIndex((entry) => entry.kind === 'email')\n const threadSubject = (index: number) => {\n for (let position = index - 1; position >= 0; position -= 1) {\n const step = draft.steps[position]\n if (step.kind === 'email' && !isInThreadEmailStep(draft.steps, position))\n return step.subject\n }\n return ''\n }\n\n const save = async () => {\n setAttempted(true)\n if (\n validateOutreachSequence(draft).some(\n (issue) => issue.severity === 'error',\n )\n )\n return\n setSaving(true)\n try {\n const answer = await api.saveSequence(sequence?.id ?? null, draft)\n setServerIssues([])\n setAttempted(false)\n enqueueSnackbar(\n answer.created ? 'Sequence created.' : 'Sequence saved.',\n { variant: 'success' },\n )\n props.onSaved(answer.sequence)\n } catch (error) {\n if (error instanceof OutreachRouteError && error.issues.length) {\n setServerIssues(\n error.issues.filter(\n (issue): issue is OutreachSequenceIssue => 'path' in issue,\n ),\n )\n }\n enqueueSnackbar((error as Error).message, {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setSaving(false)\n }\n }\n // The save as last drawn, behind a handler that keeps its identity.\n const drawnSave = useRef(save)\n drawnSave.current = save\n const onSave = useCallback(() => void drawnSave.current(), [])\n\n const siteName = hosts.find((host) => host.id === draft.hostId)?.name ?? ''\n const draftCountries = draft.settings.allowedCountries\n const countryOptions = useMemo(\n () => [...new Set([...orgCountries, ...draftCountries])],\n [orgCountries, draftCountries],\n )\n /*\n * A test sends the step as STORED (AGL-3325): the route reads the saved\n * sequence, so a new one has nothing to send yet and an edited one sends\n * its last save — said on the button and in the dialog rather than found\n * out in the inbox.\n */\n const unsaved =\n sequence !== null &&\n JSON.stringify(draft) !== JSON.stringify(outreachSequenceDraftOf(sequence))\n const sendTestDisabledReason = !sequence\n ? 'Create the sequence to send a test of it.'\n : !draft.mailboxId\n ? 'Choose a mailbox to send the test from.'\n : null\n\n return (\n <Grid container spacing={2}>\n <Grid size={{ xs: 12, md: 7 }}>\n <Stack spacing={2}>\n {archived ? (\n <Alert severity=\"info\">\n This sequence is archived, so it can’t be edited.\n </Alert>\n ) : null}\n <SequenceCard\n orgId={orgId}\n uid={uid}\n name={draft.name}\n hostId={draft.hostId}\n mailboxId={draft.mailboxId}\n mailboxIds={draft.mailboxIds ?? NO_ROTATION}\n campaignIds={draft.campaignIds}\n hosts={hosts}\n mailboxes={props.mailboxes}\n mailboxesPath={props.mailboxesPath}\n campaignOptions={campaigns.options}\n noCampaigns={campaigns.ready && !campaigns.options.length}\n nameIssue={issueAt('name')}\n hostIssue={issueAt('hostId')}\n mailboxIssue={issueAt('mailboxId')}\n rotationIssue={issueAt('mailboxIds')}\n campaignsIssue={issueAt('campaignIds')}\n archived={archived}\n saving={saving}\n saveLabel={sequence ? 'Save' : 'Create sequence'}\n onCancel={props.onCancel}\n onSave={onSave}\n onName={setName}\n onHost={setHost}\n onMailbox={setMailbox}\n onRotation={setRotation}\n onCampaigns={setCampaigns}\n />\n\n {listIssue ? <Alert severity=\"error\">{listIssue}</Alert> : null}\n {draft.steps.map((step, index) => {\n const inThread = isInThreadEmailStep(draft.steps, index)\n return (\n <SequenceStepItem\n key={step.id || `step-${index}`}\n step={step}\n index={index}\n count={draft.steps.length}\n firstEmail={firstEmail === index}\n inThread={inThread}\n // Read only by an email sent in the thread, so no other\n // step is redrawn as the subject it replies to is typed.\n threadSubject={inThread ? threadSubject(index) : ''}\n templates={templates.data}\n issues={stepIssues[index]}\n disabled={archived}\n canSendTest={step.kind === 'email' && !archived}\n sendTestDisabledReason={sendTestDisabledReason}\n onStepChange={setStep}\n onStepMove={moveStep}\n onStepRemove={removeStep}\n onStepTest={setTesting}\n />\n )\n })}\n <SequenceAddStep\n emailDisabled={\n archived || full || emailCount >= OUTREACH_MAX_EMAIL_STEPS\n }\n taskDisabled={archived || full}\n onAddEmail={addEmail}\n onAddTask={addTask}\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`Up to ${OUTREACH_MAX_STEPS} steps, ${OUTREACH_MAX_EMAIL_STEPS} of them emails.`}\n </Typography>\n\n <SequenceSendingCard\n settings={draft.settings}\n countryOptions={countryOptions}\n countriesIssue={countriesIssue}\n daysIssue={issueAt('settings.window.days')}\n hoursIssue={issueAt('settings.window')}\n disabled={archived}\n onCountries={setCountries}\n onSettings={setSettings}\n />\n\n </Stack>\n </Grid>\n {sequence && testing !== null ? (\n <OutreachStepTestDialog\n open\n onClose={() => setTesting(null)}\n orgId={orgId}\n sequence={sequence}\n stepIndex={testing}\n contactGroupId={\n sequence.hostId\n ? consentGroupForHost(props.org ?? null, sequence.hostId).groupId\n : ''\n }\n selfEmail={user?.email ?? null}\n unsaved={unsaved}\n api={api}\n />\n ) : null}\n <Grid size={{ xs: 12, md: 5 }}>\n <Box sx={PREVIEW_COLUMN}>\n <MemoSequencePreview\n steps={draft.steps}\n orgSettings={settings.settings}\n orgSettingsStatus={settings.status}\n templates={templates.data}\n sender={sender}\n siteName={siteName}\n />\n </Box>\n </Grid>\n </Grid>\n )\n}\nOutreachSequenceEditor.displayName = 'OutreachSequenceEditor'\n\nexport default OutreachSequenceEditor\n"],"names":["pluginDocsHelp","consentGroupForHost","mdiPlus","CardDisplay","MdiIcon","ContainerPicker","useSnackbar","useOrgContainerOptions","useUser","Alert","Autocomplete","Box","Button","Chip","FormControlLabel","Grid","Menu","MenuItem","Stack","Switch","TextField","Typography","memo","useCallback","useEffect","useMemo","useRef","useState","isInThreadEmailStep","OUTREACH_SEQUENCE_NAME_MAX","validateOutreachSequence","outreachCountryLabel","OUTREACH_MAX_EMAIL_STEPS","OUTREACH_MAX_STEPS","OUTREACH_TASK_KIND_LABELS","OUTREACH_TASK_KINDS","emptyOutreachSequenceDraft","newOutreachEmailStep","newOutreachTaskStep","outreachSequenceDraftOf","OutreachSendWindowFields","OutreachSequenceMailboxPicker","OutreachSequenceRotationPicker","OutreachSequencePreview","OutreachStepCard","OutreachStepTestDialog","OutreachRouteError","useOutreachApi","useOutreachEmailTemplates","stepIssueKey","path","match","exec","field","index","Number","OutreachCountriesField","props","multiple","options","value","getOptionLabel","onChange","_event","next","disabled","renderValue","getItemProps","map","code","key","item","size","label","renderInput","params","error","Boolean","issue","helperText","useStepIssues","issues","count","held","found","Array","from","length","record","undefined","message","current","JSON","stringify","before","entry","MemoTextField","MemoMailboxPicker","MemoRotationPicker","NO_ROTATION","MemoContainerPicker","MemoSendWindowFields","MemoSequencePreview","NAME_SLOT_PROPS","htmlInput","maxLength","ADD_STEP_ROW","flexWrap","rowGap","PREVIEW_COLUMN","position","md","top","SequenceSiteField","hosts","select","some","host","id","fullWidth","name","SequenceSaveActions","direction","spacing","onCancel","variant","onClick","saving","onSave","saveLabel","SequenceCard","archived","header","help","anchor","HeaderProps","action","contentGutterX","contentGutterY","onName","nameIssue","slotProps","hostId","hostIssue","onHost","orgId","uid","mailboxes","mailboxesPath","mailboxId","onMailbox","mailboxIssue","mailboxIds","onRotation","rotationIssue","kind","campaignOptions","campaignIds","onCampaigns","campaignsIssue","empty","noCampaigns","emptyText","SequenceStepItem","canSendTest","onStepChange","onStepMove","onStepRemove","onStepTest","card","step","onMove","onRemove","onSendTest","SequenceAddStep","onAddTask","taskAnchor","setTaskAnchor","sx","startIcon","fontSize","emailDisabled","onAddEmail","taskDisabled","event","currentTarget","aria-haspopup","anchorEl","open","onClose","SequenceSendingCard","settings","onSettings","setAllowCustomers","allowCustomers","target","checked","setTrackClicks","trackClicks","setCountOpens","countOpens","setListUnsubscribe","listUnsubscribe","setWindow","window","excerpt","countryOptions","allowedCountries","onCountries","countriesIssue","control","color","daysIssue","hoursIssue","OutreachSequenceEditor","draft","orgMount","sequence","api","enqueueSnackbar","data","user","mountedHosts","orgCountries","setDraft","attempted","setAttempted","serverIssues","setServerIssues","setSaving","testing","setTesting","drawn","settingsCountries","join","previous","split","ownSending","filter","connectedByUid","status","onlyOwnMailbox","templates","mailbox","find","sender","displayName","email","sendAs","campaigns","enabled","judged","severity","includes","issueAt","stepIssues","steps","listIssue","startsWith","clearServerIssues","update","setCountries","setName","setHost","setMailbox","setRotation","setCampaigns","setSettings","patch","setStep","moveStep","moved","splice","removeStep","_entry","addEmail","addTask","emailCount","full","firstEmail","findIndex","threadSubject","subject","save","answer","saveSequence","created","onSaved","allowDuplicate","drawnSave","siteName","draftCountries","Set","unsaved","sendTestDisabledReason","container","xs","ready","inThread","stepIndex","contactGroupId","org","groupId","selfEmail","orgSettings","orgSettingsStatus"],"mappings":"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"}
|
|
@@ -41,4 +41,25 @@ export declare function OutreachSequenceMailboxPicker(props: OutreachSequenceMai
|
|
|
41
41
|
export declare namespace OutreachSequenceMailboxPicker {
|
|
42
42
|
var displayName: string;
|
|
43
43
|
}
|
|
44
|
+
export interface OutreachSequenceRotationPickerProps {
|
|
45
|
+
orgId: string;
|
|
46
|
+
uid: string | null;
|
|
47
|
+
mailboxes: OutreachMailboxesResult;
|
|
48
|
+
/** The sequence's own mailbox, which is never offered here. */
|
|
49
|
+
mailboxId: string;
|
|
50
|
+
value: readonly string[];
|
|
51
|
+
onChange(mailboxIds: string[]): void;
|
|
52
|
+
error?: string;
|
|
53
|
+
disabled?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The other mailboxes a sequence sends from in rotation (AGL-3489): each
|
|
57
|
+
* person enrolled is given one of them or the sequence's own, and all of
|
|
58
|
+
* their emails go from it. Offered once the sequence has a mailbox, from
|
|
59
|
+
* the same mailboxes the member may choose for it.
|
|
60
|
+
*/
|
|
61
|
+
export declare function OutreachSequenceRotationPicker(props: OutreachSequenceRotationPickerProps): import("react").JSX.Element;
|
|
62
|
+
export declare namespace OutreachSequenceRotationPicker {
|
|
63
|
+
var displayName: string;
|
|
64
|
+
}
|
|
44
65
|
export default OutreachSequenceMailboxPicker;
|