@aglyn/plugins-outreach 1.0.0-beta.152 → 1.0.0-beta.153
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 +5 -1
- package/package.json +12 -12
- package/src/lib/components/enroll-dialog.js +142 -32
- package/src/lib/components/enroll-dialog.js.map +1 -1
- package/src/lib/components/enrollments-table.js +37 -8
- package/src/lib/components/enrollments-table.js.map +1 -1
- package/src/lib/components/mailbox-card.d.ts +1 -0
- package/src/lib/components/mailbox-card.js +25 -5
- package/src/lib/components/mailbox-card.js.map +1 -1
- package/src/lib/components/use-outreach-crm.d.ts +20 -1
- package/src/lib/components/use-outreach-crm.js +78 -4
- package/src/lib/components/use-outreach-crm.js.map +1 -1
- package/src/lib/declarations.console-server.js +14 -0
- package/src/lib/declarations.console-server.js.map +1 -1
- package/src/lib/engine/enrollment-state.d.ts +6 -1
- package/src/lib/engine/enrollment-state.js +3 -1
- package/src/lib/engine/enrollment-state.js.map +1 -1
- package/src/lib/enrollment/enroll-people.d.ts +52 -7
- package/src/lib/enrollment/enroll-people.js +109 -12
- package/src/lib/enrollment/enroll-people.js.map +1 -1
- package/src/lib/enrollment/gate-lookups.d.ts +12 -3
- package/src/lib/enrollment/gate-lookups.js +17 -14
- package/src/lib/enrollment/gate-lookups.js.map +1 -1
- package/src/lib/mailboxes/mailbox-api.d.ts +6 -0
- package/src/lib/mailboxes/mailbox-api.js.map +1 -1
- package/src/lib/mailboxes/mailbox-routes.js +11 -0
- package/src/lib/mailboxes/mailbox-routes.js.map +1 -1
- package/src/lib/model/outreach-api.d.ts +39 -8
- package/src/lib/model/outreach-api.js.map +1 -1
- package/src/lib/model/outreach.types.d.ts +28 -3
- package/src/lib/model/outreach.types.js +9 -0
- package/src/lib/model/outreach.types.js.map +1 -1
- package/src/lib/model/stored-records.js +7 -0
- package/src/lib/model/stored-records.js.map +1 -1
- package/src/lib/routes/enroll-routes.js +112 -39
- package/src/lib/routes/enroll-routes.js.map +1 -1
- package/src/lib/routes/preview-routes.js +18 -5
- package/src/lib/routes/preview-routes.js.map +1 -1
- package/src/lib/runtime/lead-records.d.ts +26 -0
- package/src/lib/runtime/lead-records.js +84 -0
- package/src/lib/runtime/lead-records.js.map +1 -0
- package/src/lib/runtime/send-job.js +30 -12
- package/src/lib/runtime/send-job.js.map +1 -1
- package/src/lib/runtime/sync-job.js +11 -3
- package/src/lib/runtime/sync-job.js.map +1 -1
- package/src/lib/runtime/timeline.d.ts +6 -4
- package/src/lib/runtime/timeline.js +3 -7
- package/src/lib/runtime/timeline.js.map +1 -1
- package/src/lib/storage/outreach-records.d.ts +21 -2
- package/src/lib/storage/outreach-records.js +31 -2
- package/src/lib/storage/outreach-records.js.map +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# @aglyn/plugins-outreach
|
|
2
2
|
|
|
3
3
|
Sequences: one-to-one, multi-step email sequences a rep sends from
|
|
4
|
-
their own connected mailbox, logged on the CRM's records.
|
|
4
|
+
their own connected mailbox, logged on the CRM's records. A sequence
|
|
5
|
+
enrolls a contact or a lead (AGL-3234): an enrollment names which record the
|
|
6
|
+
person is, a lead is judged and merged as the contact it would be, and when
|
|
7
|
+
the lead converts its enrollment follows it to the contact through the
|
|
8
|
+
core's lead-conversion seam.
|
|
5
9
|
|
|
6
10
|
> Beta. Published from the Aglyn monorepo under the `beta` dist-tag; APIs can change between beta releases.
|
|
7
11
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/plugins-outreach",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.153",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,17 +25,17 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-data-mdi": "1.0.0-beta.
|
|
30
|
-
"@aglyn/shared-ui-jsx": "1.0.0-beta.
|
|
31
|
-
"@aglyn/shared-ui-next": "1.0.0-beta.
|
|
32
|
-
"@aglyn/shared-ui-snackstack": "1.0.0-beta.
|
|
33
|
-
"@aglyn/shared-util-http": "1.0.0-beta.
|
|
34
|
-
"@aglyn/shared-util-timestamp": "1.0.0-beta.
|
|
35
|
-
"@aglyn/shared-util-tools": "1.0.0-beta.
|
|
36
|
-
"@aglyn/tenant-data-admin": "1.0.0-beta.
|
|
37
|
-
"@aglyn/tenant-feature-instance": "1.0.0-beta.
|
|
38
|
-
"@aglyn/tenant-runtime": "1.0.0-beta.
|
|
28
|
+
"@aglyn/aglyn": "1.0.0-beta.153",
|
|
29
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.153",
|
|
30
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.153",
|
|
31
|
+
"@aglyn/shared-ui-next": "1.0.0-beta.153",
|
|
32
|
+
"@aglyn/shared-ui-snackstack": "1.0.0-beta.153",
|
|
33
|
+
"@aglyn/shared-util-http": "1.0.0-beta.153",
|
|
34
|
+
"@aglyn/shared-util-timestamp": "1.0.0-beta.153",
|
|
35
|
+
"@aglyn/shared-util-tools": "1.0.0-beta.153",
|
|
36
|
+
"@aglyn/tenant-data-admin": "1.0.0-beta.153",
|
|
37
|
+
"@aglyn/tenant-feature-instance": "1.0.0-beta.153",
|
|
38
|
+
"@aglyn/tenant-runtime": "1.0.0-beta.153",
|
|
39
39
|
"@swc/helpers": "0.5.23"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
@@ -23,7 +23,7 @@ import { useMemo, useState } from "react";
|
|
|
23
23
|
import { OUTREACH_ENROLL_BATCH_MAX } from "../model/outreach-api.js";
|
|
24
24
|
import { OUTREACH_ATTESTATION_LABELS, OUTREACH_PERSONAL_LINE_MAX } from "../model/outreach.types.js";
|
|
25
25
|
import { OutreachLoading, OutreachLoadProblem } from "./outreach-ui.js";
|
|
26
|
-
import { useOutreachContactSearch, useOutreachSavedViews } from "./use-outreach-crm.js";
|
|
26
|
+
import { useOutreachContactSearch, useOutreachLeadSearch, useOutreachSavedViews } from "./use-outreach-crm.js";
|
|
27
27
|
const STATUS_LABELS = {
|
|
28
28
|
eligible: 'Eligible',
|
|
29
29
|
needs_confirmation: 'Needs you',
|
|
@@ -59,6 +59,10 @@ const STATUS_COLORS = {
|
|
|
59
59
|
const [viewId, setViewId] = useState('');
|
|
60
60
|
const [text, setText] = useState('');
|
|
61
61
|
const [picked, setPicked] = useState(new Map());
|
|
62
|
+
// The leads picked from the sequence's site (AGL-3234), kept apart from
|
|
63
|
+
// the contacts: the two are different records and the source names which.
|
|
64
|
+
const [leadText, setLeadText] = useState('');
|
|
65
|
+
const [pickedLeads, setPickedLeads] = useState(new Map());
|
|
62
66
|
const [stage, setStage] = useState({
|
|
63
67
|
kind: 'source'
|
|
64
68
|
});
|
|
@@ -72,6 +76,11 @@ const STATUS_COLORS = {
|
|
|
72
76
|
contactGroupId: props.contactGroupId,
|
|
73
77
|
text
|
|
74
78
|
});
|
|
79
|
+
const leadSearch = useOutreachLeadSearch({
|
|
80
|
+
hostId: sequence.hostId,
|
|
81
|
+
text: leadText,
|
|
82
|
+
enabled: props.open && tab === 'leads'
|
|
83
|
+
});
|
|
75
84
|
const reset = ()=>{
|
|
76
85
|
setStage({
|
|
77
86
|
kind: 'source'
|
|
@@ -83,7 +92,9 @@ const STATUS_COLORS = {
|
|
|
83
92
|
const close = ()=>{
|
|
84
93
|
reset();
|
|
85
94
|
setPicked(new Map());
|
|
95
|
+
setPickedLeads(new Map());
|
|
86
96
|
setText('');
|
|
97
|
+
setLeadText('');
|
|
87
98
|
setViewId('');
|
|
88
99
|
props.onClose();
|
|
89
100
|
};
|
|
@@ -95,7 +106,7 @@ const STATUS_COLORS = {
|
|
|
95
106
|
try {
|
|
96
107
|
const answer = await api.previewEnrollment(sequence.id, source);
|
|
97
108
|
setSupplied(Object.fromEntries(answer.people.map((person)=>[
|
|
98
|
-
person.
|
|
109
|
+
person.personId,
|
|
99
110
|
{
|
|
100
111
|
include: person.status !== 'blocked',
|
|
101
112
|
personalLine: '',
|
|
@@ -114,13 +125,13 @@ const STATUS_COLORS = {
|
|
|
114
125
|
}
|
|
115
126
|
};
|
|
116
127
|
const answer = stage.kind === 'preview' || stage.kind === 'enrolling' ? stage.answer : null;
|
|
117
|
-
const ready = useMemo(()=>answer ? answer.people.filter((person)=>outreachPersonReady(person, supplied[person.
|
|
128
|
+
const ready = useMemo(()=>answer ? answer.people.filter((person)=>outreachPersonReady(person, supplied[person.personId])) : [], [
|
|
118
129
|
answer,
|
|
119
130
|
supplied
|
|
120
131
|
]);
|
|
121
132
|
const waiting = answer ? answer.people.filter((person)=>{
|
|
122
|
-
var
|
|
123
|
-
return person.status === 'needs_confirmation' && ((
|
|
133
|
+
var _supplied_person_personId;
|
|
134
|
+
return person.status === 'needs_confirmation' && ((_supplied_person_personId = supplied[person.personId]) == null ? void 0 : _supplied_person_personId.include) && !outreachPersonReady(person, supplied[person.personId]);
|
|
124
135
|
}).length : 0;
|
|
125
136
|
const enroll = async ()=>{
|
|
126
137
|
if (!answer || !ready.length) return;
|
|
@@ -132,12 +143,15 @@ const STATUS_COLORS = {
|
|
|
132
143
|
try {
|
|
133
144
|
const result = await api.enroll(sequence.id, ready.map((person)=>{
|
|
134
145
|
var _ref, _ref1;
|
|
135
|
-
var
|
|
136
|
-
return {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
146
|
+
var _supplied_person_personId, _supplied_person_personId1;
|
|
147
|
+
return _extends({}, person.target === 'lead' && person.leadId ? {
|
|
148
|
+
leadId: person.leadId
|
|
149
|
+
} : {
|
|
150
|
+
contactId: person.contactId
|
|
151
|
+
}, {
|
|
152
|
+
personalLine: (_ref = (_supplied_person_personId = supplied[person.personId]) == null ? void 0 : _supplied_person_personId.personalLine.trim()) != null ? _ref : '',
|
|
153
|
+
attestations: (_ref1 = (_supplied_person_personId1 = supplied[person.personId]) == null ? void 0 : _supplied_person_personId1.attestations) != null ? _ref1 : []
|
|
154
|
+
});
|
|
141
155
|
}));
|
|
142
156
|
setStage({
|
|
143
157
|
kind: 'done',
|
|
@@ -152,32 +166,36 @@ const STATUS_COLORS = {
|
|
|
152
166
|
});
|
|
153
167
|
}
|
|
154
168
|
};
|
|
155
|
-
const supply = (
|
|
156
|
-
[
|
|
169
|
+
const supply = (personId, next)=>setSupplied((previous)=>_extends({}, previous, {
|
|
170
|
+
[personId]: _extends({}, previous[personId], next)
|
|
157
171
|
}));
|
|
158
172
|
const previewEmail = async (person)=>{
|
|
159
173
|
setEmailPreview((previous)=>_extends({}, previous, {
|
|
160
|
-
[person.
|
|
174
|
+
[person.personId]: {
|
|
161
175
|
status: 'loading'
|
|
162
176
|
}
|
|
163
177
|
}));
|
|
164
178
|
try {
|
|
165
179
|
var _ref;
|
|
166
|
-
var
|
|
167
|
-
const result = await api.previewEmail({
|
|
168
|
-
sequenceId: sequence.id
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
180
|
+
var _supplied_person_personId;
|
|
181
|
+
const result = await api.previewEmail(_extends({
|
|
182
|
+
sequenceId: sequence.id
|
|
183
|
+
}, person.target === 'lead' && person.leadId ? {
|
|
184
|
+
leadId: person.leadId
|
|
185
|
+
} : {
|
|
186
|
+
contactId: person.contactId
|
|
187
|
+
}, {
|
|
188
|
+
personalLine: (_ref = (_supplied_person_personId = supplied[person.personId]) == null ? void 0 : _supplied_person_personId.personalLine.trim()) != null ? _ref : ''
|
|
189
|
+
}));
|
|
172
190
|
setEmailPreview((previous)=>_extends({}, previous, {
|
|
173
|
-
[person.
|
|
191
|
+
[person.personId]: {
|
|
174
192
|
status: 'ready',
|
|
175
193
|
answer: result
|
|
176
194
|
}
|
|
177
195
|
}));
|
|
178
196
|
} catch (error) {
|
|
179
197
|
setEmailPreview((previous)=>_extends({}, previous, {
|
|
180
|
-
[person.
|
|
198
|
+
[person.personId]: {
|
|
181
199
|
status: 'failed',
|
|
182
200
|
message: error.message
|
|
183
201
|
}
|
|
@@ -233,6 +251,10 @@ const STATUS_COLORS = {
|
|
|
233
251
|
/*#__PURE__*/ _jsx(Tab, {
|
|
234
252
|
value: "search",
|
|
235
253
|
label: "Search"
|
|
254
|
+
}),
|
|
255
|
+
/*#__PURE__*/ _jsx(Tab, {
|
|
256
|
+
value: "leads",
|
|
257
|
+
label: "Leads"
|
|
236
258
|
})
|
|
237
259
|
]
|
|
238
260
|
}),
|
|
@@ -247,15 +269,93 @@ const STATUS_COLORS = {
|
|
|
247
269
|
label: "Saved Contacts view",
|
|
248
270
|
value: viewId,
|
|
249
271
|
onChange: (event)=>setViewId(event.target.value),
|
|
250
|
-
helperText: `Enrolls up to ${OUTREACH_ENROLL_BATCH_MAX} of the people the view shows at this sequence’s site.`,
|
|
272
|
+
helperText: `Enrolls up to ${OUTREACH_ENROLL_BATCH_MAX} of the people the view shows at this sequence’s site — a Contacts view, or a Leads view of the site’s leads.`,
|
|
251
273
|
fullWidth: true,
|
|
252
274
|
children: views.data.map((view)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
253
275
|
value: view.id,
|
|
254
|
-
children: view.name
|
|
276
|
+
children: view.section === 'leads' ? `${view.name} (Leads)` : view.name
|
|
255
277
|
}, view.id))
|
|
256
278
|
}) : /*#__PURE__*/ _jsx(Alert, {
|
|
257
279
|
severity: "info",
|
|
258
280
|
children: "You have no saved Contacts views to enroll from. Save one in the CRM, or search instead."
|
|
281
|
+
}) : tab === 'leads' ? /*#__PURE__*/ _jsxs(Stack, {
|
|
282
|
+
spacing: 1.5,
|
|
283
|
+
children: [
|
|
284
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
285
|
+
label: "Search leads",
|
|
286
|
+
placeholder: "A name, or an email address",
|
|
287
|
+
value: leadText,
|
|
288
|
+
onChange: (event)=>setLeadText(event.target.value),
|
|
289
|
+
helperText: "The open leads at this sequence’s site. A lead is enrolled as it is, and follows itself to the contact it becomes.",
|
|
290
|
+
fullWidth: true,
|
|
291
|
+
autoFocus: true
|
|
292
|
+
}),
|
|
293
|
+
leadSearch.status === 'loading' ? /*#__PURE__*/ _jsx(OutreachLoading, {
|
|
294
|
+
label: "Reading leads…"
|
|
295
|
+
}) : null,
|
|
296
|
+
leadSearch.status === 'error' || leadSearch.status === 'refused' ? /*#__PURE__*/ _jsx(OutreachLoadProblem, {
|
|
297
|
+
status: leadSearch.status,
|
|
298
|
+
what: "leads",
|
|
299
|
+
message: leadSearch.status === 'refused' ? 'Enrolling reads your CRM’s leads, and your role does not include Manage data.' : 'The leads could not be read. Try again.'
|
|
300
|
+
}) : null,
|
|
301
|
+
leadSearch.status === 'ready' && !leadSearch.idle && !leadSearch.data.length ? /*#__PURE__*/ _jsx(Typography, {
|
|
302
|
+
variant: "body2",
|
|
303
|
+
color: "text.secondary",
|
|
304
|
+
children: "No open leads at this sequence’s site match."
|
|
305
|
+
}) : null,
|
|
306
|
+
leadSearch.data.length ? /*#__PURE__*/ _jsx(List, {
|
|
307
|
+
dense: true,
|
|
308
|
+
"aria-label": "Lead results",
|
|
309
|
+
children: leadSearch.data.map((lead)=>{
|
|
310
|
+
const checked = pickedLeads.has(lead.id);
|
|
311
|
+
return /*#__PURE__*/ _jsx(ListItem, {
|
|
312
|
+
disablePadding: true,
|
|
313
|
+
children: /*#__PURE__*/ _jsxs(ListItemButton, {
|
|
314
|
+
onClick: ()=>setPickedLeads((previous)=>{
|
|
315
|
+
const next = new Map(previous);
|
|
316
|
+
if (checked) next.delete(lead.id);
|
|
317
|
+
else if (next.size < OUTREACH_ENROLL_BATCH_MAX) next.set(lead.id, lead);
|
|
318
|
+
return next;
|
|
319
|
+
}),
|
|
320
|
+
children: [
|
|
321
|
+
/*#__PURE__*/ _jsx(ListItemIcon, {
|
|
322
|
+
children: /*#__PURE__*/ _jsx(Checkbox, {
|
|
323
|
+
edge: "start",
|
|
324
|
+
checked: checked,
|
|
325
|
+
tabIndex: -1,
|
|
326
|
+
disableRipple: true
|
|
327
|
+
})
|
|
328
|
+
}),
|
|
329
|
+
/*#__PURE__*/ _jsx(ListItemText, {
|
|
330
|
+
primary: lead.name || lead.email || lead.id,
|
|
331
|
+
secondary: lead.email
|
|
332
|
+
})
|
|
333
|
+
]
|
|
334
|
+
})
|
|
335
|
+
}, lead.id);
|
|
336
|
+
})
|
|
337
|
+
}) : null,
|
|
338
|
+
pickedLeads.size ? /*#__PURE__*/ _jsx(Stack, {
|
|
339
|
+
direction: "row",
|
|
340
|
+
spacing: 1,
|
|
341
|
+
sx: {
|
|
342
|
+
flexWrap: 'wrap',
|
|
343
|
+
rowGap: 1
|
|
344
|
+
},
|
|
345
|
+
"aria-label": "Picked leads",
|
|
346
|
+
children: [
|
|
347
|
+
...pickedLeads.values()
|
|
348
|
+
].map((lead)=>/*#__PURE__*/ _jsx(Chip, {
|
|
349
|
+
size: "small",
|
|
350
|
+
label: lead.name || lead.email || lead.id,
|
|
351
|
+
onDelete: ()=>setPickedLeads((previous)=>{
|
|
352
|
+
const next = new Map(previous);
|
|
353
|
+
next.delete(lead.id);
|
|
354
|
+
return next;
|
|
355
|
+
})
|
|
356
|
+
}, lead.id))
|
|
357
|
+
}) : null
|
|
358
|
+
]
|
|
259
359
|
}) : /*#__PURE__*/ _jsxs(Stack, {
|
|
260
360
|
spacing: 1.5,
|
|
261
361
|
children: [
|
|
@@ -362,12 +462,12 @@ const STATUS_COLORS = {
|
|
|
362
462
|
"aria-label": "People",
|
|
363
463
|
children: answer.people.map((person)=>/*#__PURE__*/ _jsx(PersonRow, {
|
|
364
464
|
person: person,
|
|
365
|
-
supplied: supplied[person.
|
|
366
|
-
onSupply: (next)=>supply(person.
|
|
367
|
-
emailPreview: emailPreview[person.
|
|
465
|
+
supplied: supplied[person.personId],
|
|
466
|
+
onSupply: (next)=>supply(person.personId, next),
|
|
467
|
+
emailPreview: emailPreview[person.personId],
|
|
368
468
|
onPreviewEmail: ()=>void previewEmail(person),
|
|
369
469
|
disabled: stage.kind === 'enrolling'
|
|
370
|
-
}, person.
|
|
470
|
+
}, person.personId))
|
|
371
471
|
}),
|
|
372
472
|
waiting ? /*#__PURE__*/ _jsx(Typography, {
|
|
373
473
|
variant: "body2",
|
|
@@ -410,10 +510,15 @@ const STATUS_COLORS = {
|
|
|
410
510
|
]
|
|
411
511
|
}) : /*#__PURE__*/ _jsx(Button, {
|
|
412
512
|
variant: "contained",
|
|
413
|
-
disabled: stage.kind === 'previewing' || (tab === 'view' ? !viewId : !picked.size),
|
|
513
|
+
disabled: stage.kind === 'previewing' || (tab === 'view' ? !viewId : tab === 'leads' ? !pickedLeads.size : !picked.size),
|
|
414
514
|
onClick: ()=>void preview(tab === 'view' ? {
|
|
415
515
|
kind: 'view',
|
|
416
516
|
viewId
|
|
517
|
+
} : tab === 'leads' ? {
|
|
518
|
+
kind: 'leads',
|
|
519
|
+
leadIds: [
|
|
520
|
+
...pickedLeads.keys()
|
|
521
|
+
]
|
|
417
522
|
} : {
|
|
418
523
|
kind: 'contacts',
|
|
419
524
|
contactIds: [
|
|
@@ -437,7 +542,7 @@ function PersonRow(props) {
|
|
|
437
542
|
var _ref, _ref1;
|
|
438
543
|
var _props_emailPreview, _props_emailPreview1, _props_emailPreview2;
|
|
439
544
|
const { person, supplied, disabled } = props;
|
|
440
|
-
const name = person.name || person.email || person.
|
|
545
|
+
const name = person.name || person.email || person.personId;
|
|
441
546
|
const line = (_ref = supplied == null ? void 0 : supplied.personalLine) != null ? _ref : '';
|
|
442
547
|
const tooLong = line.trim().length > OUTREACH_PERSONAL_LINE_MAX;
|
|
443
548
|
return /*#__PURE__*/ _jsx(Paper, {
|
|
@@ -486,6 +591,11 @@ function PersonRow(props) {
|
|
|
486
591
|
alignItems: 'center'
|
|
487
592
|
},
|
|
488
593
|
children: [
|
|
594
|
+
person.target === 'lead' ? /*#__PURE__*/ _jsx(Chip, {
|
|
595
|
+
size: "small",
|
|
596
|
+
variant: "outlined",
|
|
597
|
+
label: "Lead"
|
|
598
|
+
}) : null,
|
|
489
599
|
person.cold ? /*#__PURE__*/ _jsx(Chip, {
|
|
490
600
|
size: "small",
|
|
491
601
|
variant: "outlined",
|
|
@@ -636,7 +746,7 @@ function DoneSummary(props) {
|
|
|
636
746
|
children: [
|
|
637
747
|
/*#__PURE__*/ _jsx(Typography, {
|
|
638
748
|
variant: "body2",
|
|
639
|
-
children: (_result_email = result.email) != null ? _result_email : result.
|
|
749
|
+
children: (_result_email = result.email) != null ? _result_email : result.personId
|
|
640
750
|
}),
|
|
641
751
|
result.blocks.map((block)=>/*#__PURE__*/ _jsx(Typography, {
|
|
642
752
|
variant: "body2",
|
|
@@ -644,7 +754,7 @@ function DoneSummary(props) {
|
|
|
644
754
|
children: block.reason
|
|
645
755
|
}, block.code))
|
|
646
756
|
]
|
|
647
|
-
}, result.
|
|
757
|
+
}, result.personId);
|
|
648
758
|
})
|
|
649
759
|
]
|
|
650
760
|
}) : null
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/enroll-dialog.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { HelpTip } from '@aglyn/shared-ui-jsx'\nimport {\n Alert,\n Button,\n Checkbox,\n Chip,\n type ChipProps,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n FormControlLabel,\n FormGroup,\n List,\n ListItem,\n ListItemButton,\n ListItemIcon,\n ListItemText,\n MenuItem,\n Paper,\n Stack,\n Tab,\n Tabs,\n TextField,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@mui/material'\nimport { useMemo, useState } from 'react'\nimport {\n OUTREACH_ENROLL_BATCH_MAX,\n type OutreachEnrollOutcome,\n type OutreachEnrollPreviewPerson,\n type OutreachEnrollPreviewResponse,\n type OutreachEnrollPreviewStatus,\n type OutreachEnrollSource,\n type OutreachPreviewResponse,\n} from '../model/outreach-api'\nimport {\n OUTREACH_ATTESTATION_LABELS,\n OUTREACH_PERSONAL_LINE_MAX,\n type OutreachAttestationKind,\n type OutreachSequence,\n} from '../model/outreach.types'\nimport { OutreachLoading, OutreachLoadProblem } from './outreach-ui'\nimport type { OutreachApi } from './use-outreach-api'\nimport {\n type OutreachContactOption,\n useOutreachContactSearch,\n useOutreachSavedViews,\n} from './use-outreach-crm'\n\nexport interface OutreachEnrollDialogProps {\n open: boolean\n onClose(): void\n orgId: string\n sequence: OutreachSequence\n /** The consent group of the sequence's site: whose names a search shows. */\n contactGroupId: string\n uid: string | null\n api: OutreachApi\n}\n\nconst STATUS_LABELS: Record<OutreachEnrollPreviewStatus, string> = {\n eligible: 'Eligible',\n needs_confirmation: 'Needs you',\n blocked: 'Blocked',\n}\n\nconst STATUS_COLORS: Record<OutreachEnrollPreviewStatus, ChipProps['color']> = {\n eligible: 'success',\n needs_confirmation: 'warning',\n blocked: 'default',\n}\n\n/** What the rep has supplied for one person. */\ninterface Supplied {\n include: boolean\n personalLine: string\n attestations: OutreachAttestationKind[]\n}\n\ntype Stage =\n | { kind: 'source' }\n | { kind: 'previewing' }\n | { kind: 'preview'; answer: OutreachEnrollPreviewResponse }\n | { kind: 'enrolling'; answer: OutreachEnrollPreviewResponse }\n | { kind: 'done'; results: OutreachEnrollOutcome[]; enrolled: number }\n\n/** Whether a person may be sent to Confirm as the rep has left them. */\nexport function outreachPersonReady(\n person: OutreachEnrollPreviewPerson,\n supplied: Supplied | undefined,\n): boolean {\n if (person.status === 'blocked' || !supplied?.include) return false\n const line = supplied.personalLine.trim()\n if (line.length > OUTREACH_PERSONAL_LINE_MAX) return false\n if (person.status === 'eligible') return true\n if (person.requires.personalLine && !line) return false\n return person.requires.attestations.every((kind) =>\n supplied.attestations.includes(kind),\n )\n}\n\n/**\n * Enroll people in a sequence (AGL-2980).\n *\n * The rep picks a saved Contacts view or searches for people, and sees each\n * marked as the gates see them: eligible, blocked with the reason, or\n * waiting on them — for a cold contact, a personal line and the three\n * attestations only they can make, stored on the enrollment with who ticked\n * them and when. Enroll sends only the people who are ready, and the server\n * checks every gate again as it enrolls them.\n */\nexport function OutreachEnrollDialog(props: OutreachEnrollDialogProps) {\n const { orgId, sequence, api } = props\n const theme = useTheme()\n const narrow = useMediaQuery(theme.breakpoints.down('sm'))\n const [tab, setTab] = useState<'view' | 'search'>('view')\n const [viewId, setViewId] = useState('')\n const [text, setText] = useState('')\n const [picked, setPicked] = useState<Map<string, OutreachContactOption>>(\n new Map(),\n )\n const [stage, setStage] = useState<Stage>({ kind: 'source' })\n const [problem, setProblem] = useState<string | null>(null)\n const [supplied, setSupplied] = useState<Record<string, Supplied>>({})\n const [emailPreview, setEmailPreview] = useState<\n Record<\n string,\n | { status: 'loading' }\n | { status: 'ready'; answer: OutreachPreviewResponse }\n | { status: 'failed'; message: string }\n >\n >({})\n\n const views = useOutreachSavedViews(props.open ? orgId : null, props.uid)\n const search = useOutreachContactSearch({\n orgId: props.open && tab === 'search' ? orgId : null,\n hostId: sequence.hostId,\n contactGroupId: props.contactGroupId,\n text,\n })\n\n const reset = () => {\n setStage({ kind: 'source' })\n setProblem(null)\n setSupplied({})\n setEmailPreview({})\n }\n const close = () => {\n reset()\n setPicked(new Map())\n setText('')\n setViewId('')\n props.onClose()\n }\n\n const preview = async (source: OutreachEnrollSource) => {\n setProblem(null)\n setStage({ kind: 'previewing' })\n try {\n const answer = await api.previewEnrollment(sequence.id, source)\n setSupplied(\n Object.fromEntries(\n answer.people.map((person) => [\n person.contactId,\n {\n include: person.status !== 'blocked',\n personalLine: '',\n attestations: [],\n },\n ]),\n ),\n )\n setStage({ kind: 'preview', answer })\n } catch (error) {\n setProblem((error as Error).message)\n setStage({ kind: 'source' })\n }\n }\n\n const answer =\n stage.kind === 'preview' || stage.kind === 'enrolling' ? stage.answer : null\n const ready = useMemo(\n () =>\n answer\n ? answer.people.filter((person) =>\n outreachPersonReady(person, supplied[person.contactId]),\n )\n : [],\n [answer, supplied],\n )\n const waiting = answer\n ? answer.people.filter(\n (person) =>\n person.status === 'needs_confirmation' &&\n supplied[person.contactId]?.include &&\n !outreachPersonReady(person, supplied[person.contactId]),\n ).length\n : 0\n\n const enroll = async () => {\n if (!answer || !ready.length) return\n setProblem(null)\n setStage({ kind: 'enrolling', answer })\n try {\n const result = await api.enroll(\n sequence.id,\n ready.map((person) => ({\n contactId: person.contactId,\n personalLine: supplied[person.contactId]?.personalLine.trim() ?? '',\n attestations: supplied[person.contactId]?.attestations ?? [],\n })),\n )\n setStage({\n kind: 'done',\n results: result.results,\n enrolled: result.enrolled,\n })\n } catch (error) {\n setProblem((error as Error).message)\n setStage({ kind: 'preview', answer })\n }\n }\n\n const supply = (contactId: string, next: Partial<Supplied>) =>\n setSupplied((previous) => ({\n ...previous,\n [contactId]: { ...previous[contactId], ...next } as Supplied,\n }))\n\n const previewEmail = async (person: OutreachEnrollPreviewPerson) => {\n setEmailPreview((previous) => ({\n ...previous,\n [person.contactId]: { status: 'loading' },\n }))\n try {\n const result = await api.previewEmail({\n sequenceId: sequence.id,\n contactId: person.contactId,\n personalLine: supplied[person.contactId]?.personalLine.trim() ?? '',\n })\n setEmailPreview((previous) => ({\n ...previous,\n [person.contactId]: { status: 'ready', answer: result },\n }))\n } catch (error) {\n setEmailPreview((previous) => ({\n ...previous,\n [person.contactId]: {\n status: 'failed',\n message: (error as Error).message,\n },\n }))\n }\n }\n\n const title = `Enroll people in ${sequence.name}`\n\n return (\n <Dialog\n open={props.open}\n onClose={close}\n fullWidth\n maxWidth=\"md\"\n fullScreen={narrow}\n aria-label={title}\n >\n <DialogTitle>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <span>{title}</span>\n <HelpTip {...pluginDocsHelp('sequences', { anchor: '#enroll' })} />\n </Stack>\n </DialogTitle>\n <DialogContent dividers>\n <Stack spacing={2}>\n {problem ? <Alert severity=\"error\">{problem}</Alert> : null}\n\n {stage.kind === 'source' ? (\n <>\n <Tabs\n value={tab}\n onChange={(_event, next) => setTab(next)}\n aria-label=\"Where the people come from\"\n >\n <Tab value=\"view\" label=\"Saved view\" />\n <Tab value=\"search\" label=\"Search\" />\n </Tabs>\n {tab === 'view' ? (\n views.status === 'loading' ? (\n <OutreachLoading label=\"Loading saved views…\" />\n ) : views.status === 'error' || views.status === 'refused' ? (\n <OutreachLoadProblem\n status={views.status}\n what=\"saved views\"\n message={\n views.status === 'refused'\n ? 'Enrolling reads your CRM’s contacts, and your role does not include Manage data.'\n : null\n }\n />\n ) : views.data.length ? (\n <TextField\n select\n label=\"Saved Contacts view\"\n value={viewId}\n onChange={(event) => setViewId(event.target.value)}\n helperText={`Enrolls up to ${OUTREACH_ENROLL_BATCH_MAX} of the people the view shows at this sequence’s site.`}\n fullWidth\n >\n {views.data.map((view) => (\n <MenuItem key={view.id} value={view.id}>\n {view.name}\n </MenuItem>\n ))}\n </TextField>\n ) : (\n <Alert severity=\"info\">\n You have no saved Contacts views to enroll from. Save one in\n the CRM, or search instead.\n </Alert>\n )\n ) : (\n <Stack spacing={1.5}>\n <TextField\n label=\"Search contacts\"\n placeholder=\"A name, or an email address\"\n value={text}\n onChange={(event) => setText(event.target.value)}\n fullWidth\n autoFocus\n />\n {search.status === 'loading' ? (\n <OutreachLoading label=\"Searching…\" />\n ) : null}\n {search.status === 'error' || search.status === 'refused' ? (\n <OutreachLoadProblem\n status={search.status}\n what=\"contacts\"\n message={\n search.status === 'refused'\n ? 'Enrolling reads your CRM’s contacts, and your role does not include Manage data.'\n : 'The search failed. Try again.'\n }\n />\n ) : null}\n {search.status === 'ready' &&\n !search.idle &&\n !search.data.length ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n No contacts at this sequence’s site match.\n </Typography>\n ) : null}\n {search.data.length ? (\n <List dense aria-label=\"Search results\">\n {search.data.map((contact) => {\n const checked = picked.has(contact.id)\n return (\n <ListItem key={contact.id} disablePadding>\n <ListItemButton\n onClick={() =>\n setPicked((previous) => {\n const next = new Map(previous)\n if (checked) next.delete(contact.id)\n else if (\n next.size < OUTREACH_ENROLL_BATCH_MAX\n )\n next.set(contact.id, contact)\n return next\n })\n }\n >\n <ListItemIcon>\n <Checkbox\n edge=\"start\"\n checked={checked}\n tabIndex={-1}\n disableRipple\n />\n </ListItemIcon>\n <ListItemText\n primary={\n contact.name || contact.email || contact.id\n }\n secondary={contact.email}\n />\n </ListItemButton>\n </ListItem>\n )\n })}\n </List>\n ) : null}\n {picked.size ? (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ flexWrap: 'wrap', rowGap: 1 }}\n aria-label=\"Picked\"\n >\n {[...picked.values()].map((contact) => (\n <Chip\n key={contact.id}\n size=\"small\"\n label={contact.name || contact.email || contact.id}\n onDelete={() =>\n setPicked((previous) => {\n const next = new Map(previous)\n next.delete(contact.id)\n return next\n })\n }\n />\n ))}\n </Stack>\n ) : null}\n </Stack>\n )}\n </>\n ) : null}\n\n {stage.kind === 'previewing' ? (\n <OutreachLoading label=\"Checking each person…\" />\n ) : null}\n\n {answer ? (\n <Stack spacing={1.5}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {summary(answer)}\n </Typography>\n {answer.truncated ? (\n <Alert severity=\"info\">\n {`This shows the first ${answer.people.length} of ${answer.total}. Enroll these, then preview again for the rest.`}\n </Alert>\n ) : null}\n <Stack\n spacing={1}\n component=\"ul\"\n sx={{ listStyle: 'none', p: 0, m: 0 }}\n aria-label=\"People\"\n >\n {answer.people.map((person) => (\n <PersonRow\n key={person.contactId}\n person={person}\n supplied={supplied[person.contactId]}\n onSupply={(next) => supply(person.contactId, next)}\n emailPreview={emailPreview[person.contactId]}\n onPreviewEmail={() => void previewEmail(person)}\n disabled={stage.kind === 'enrolling'}\n />\n ))}\n </Stack>\n {waiting ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`${waiting} ${waiting === 1 ? 'person still needs' : 'people still need'} a personal line or a confirmation, and won't be enrolled until they have one.`}\n </Typography>\n ) : null}\n </Stack>\n ) : null}\n\n {stage.kind === 'done' ? (\n <DoneSummary results={stage.results} enrolled={stage.enrolled} />\n ) : null}\n </Stack>\n </DialogContent>\n <DialogActions>\n {stage.kind === 'done' ? (\n <Button variant=\"contained\" onClick={close}>\n Done\n </Button>\n ) : (\n <>\n <Button onClick={close}>Cancel</Button>\n {stage.kind === 'preview' || stage.kind === 'enrolling' ? (\n <>\n <Button onClick={reset} disabled={stage.kind === 'enrolling'}>\n Back\n </Button>\n <Button\n variant=\"contained\"\n disabled={!ready.length || stage.kind === 'enrolling'}\n onClick={() => void enroll()}\n >\n {stage.kind === 'enrolling'\n ? 'Enrolling…'\n : `Enroll ${ready.length} ${ready.length === 1 ? 'person' : 'people'}`}\n </Button>\n </>\n ) : (\n <Button\n variant=\"contained\"\n disabled={\n stage.kind === 'previewing' ||\n (tab === 'view' ? !viewId : !picked.size)\n }\n onClick={() =>\n void preview(\n tab === 'view'\n ? { kind: 'view', viewId }\n : { kind: 'contacts', contactIds: [...picked.keys()] },\n )\n }\n >\n Check people\n </Button>\n )}\n </>\n )}\n </DialogActions>\n </Dialog>\n )\n}\nOutreachEnrollDialog.displayName = 'OutreachEnrollDialog'\n\nfunction summary(answer: OutreachEnrollPreviewResponse): string {\n const count = (status: OutreachEnrollPreviewStatus) =>\n answer.people.filter((person) => person.status === status).length\n return `${count('eligible')} eligible · ${count('needs_confirmation')} need you · ${count('blocked')} blocked`\n}\n\nfunction PersonRow(props: {\n person: OutreachEnrollPreviewPerson\n supplied: Supplied | undefined\n onSupply(next: Partial<Supplied>): void\n emailPreview:\n | { status: 'loading' }\n | { status: 'ready'; answer: OutreachPreviewResponse }\n | { status: 'failed'; message: string }\n | undefined\n onPreviewEmail(): void\n disabled: boolean\n}) {\n const { person, supplied, disabled } = props\n const name = person.name || person.email || person.contactId\n const line = supplied?.personalLine ?? ''\n const tooLong = line.trim().length > OUTREACH_PERSONAL_LINE_MAX\n return (\n <Paper component=\"li\" variant=\"outlined\" sx={{ p: 1.5 }} aria-label={name}>\n <Stack spacing={1}>\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n spacing={1}\n sx={{ alignItems: { sm: 'center' } }}\n >\n <Stack sx={{ flexGrow: 1, minWidth: 0 }}>\n <Typography variant=\"body2\">{name}</Typography>\n {person.email && person.email !== name ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {person.email}\n </Typography>\n ) : null}\n </Stack>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n {person.cold ? (\n <Chip size=\"small\" variant=\"outlined\" label=\"Cold\" />\n ) : null}\n <Chip\n size=\"small\"\n label={STATUS_LABELS[person.status]}\n color={STATUS_COLORS[person.status]}\n />\n </Stack>\n </Stack>\n {person.status === 'blocked' ? (\n <Stack component=\"ul\" spacing={0.5} sx={{ m: 0, pl: 2.5 }}>\n {person.blocks.map((block) => (\n <Typography\n key={block.code}\n component=\"li\"\n variant=\"body2\"\n color=\"text.secondary\"\n >\n {block.reason}\n </Typography>\n ))}\n </Stack>\n ) : (\n <Stack spacing={1}>\n <FormControlLabel\n control={\n <Checkbox\n checked={supplied?.include ?? true}\n onChange={(event) =>\n props.onSupply({ include: event.target.checked })\n }\n disabled={disabled}\n />\n }\n label=\"Enroll this person\"\n />\n {supplied?.include === false ? null : (\n <>\n <TextField\n label={\n person.requires.personalLine\n ? 'Personal line'\n : 'Personal line (optional)'\n }\n placeholder=\"One sentence on why you're writing to this person now.\"\n value={line}\n onChange={(event) =>\n props.onSupply({ personalLine: event.target.value })\n }\n disabled={disabled}\n required={person.requires.personalLine}\n error={tooLong}\n helperText={\n tooLong\n ? `Keep it to one sentence, under ${OUTREACH_PERSONAL_LINE_MAX} characters.`\n : 'Goes where the emails say {{enrollment.personalLine}}.'\n }\n fullWidth\n size=\"small\"\n />\n {person.requires.attestations.length ? (\n <FormGroup aria-label={`What you confirm about ${name}`}>\n {person.requires.attestations.map((kind) => (\n <FormControlLabel\n key={kind}\n control={\n <Checkbox\n checked={\n supplied?.attestations.includes(kind) ?? false\n }\n onChange={(event) =>\n props.onSupply({\n attestations: event.target.checked\n ? [...(supplied?.attestations ?? []), kind]\n : (supplied?.attestations ?? []).filter(\n (entry) => entry !== kind,\n ),\n })\n }\n disabled={disabled}\n />\n }\n label={OUTREACH_ATTESTATION_LABELS[kind]}\n />\n ))}\n </FormGroup>\n ) : null}\n <Stack direction=\"row\">\n <Button\n size=\"small\"\n onClick={props.onPreviewEmail}\n disabled={disabled}\n >\n Preview the first email\n </Button>\n </Stack>\n {props.emailPreview?.status === 'loading' ? (\n <OutreachLoading label=\"Writing the email…\" />\n ) : null}\n {props.emailPreview?.status === 'failed' ? (\n <Alert severity=\"error\">{props.emailPreview.message}</Alert>\n ) : null}\n {props.emailPreview?.status === 'ready' ? (\n props.emailPreview.answer.error ? (\n <Alert severity=\"info\">\n {props.emailPreview.answer.error.message}\n </Alert>\n ) : (\n <Paper\n variant=\"outlined\"\n sx={{ p: 1.5 }}\n aria-label={`First email to ${name}`}\n >\n <Typography variant=\"body2\">{`Subject: ${props.emailPreview.answer.subject}`}</Typography>\n <Typography\n variant=\"body2\"\n sx={{\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n mt: 1,\n }}\n >\n {props.emailPreview.answer.text}\n </Typography>\n </Paper>\n )\n ) : null}\n </>\n )}\n </Stack>\n )}\n </Stack>\n </Paper>\n )\n}\n\nfunction DoneSummary(props: {\n results: OutreachEnrollOutcome[]\n enrolled: number\n}) {\n const refused = props.results.filter(\n (\n result,\n ): result is Extract<OutreachEnrollOutcome, { outcome: 'blocked' }> =>\n result.outcome === 'blocked',\n )\n return (\n <Stack spacing={1.5}>\n <Alert severity={props.enrolled ? 'success' : 'info'}>\n {props.enrolled\n ? `Enrolled ${props.enrolled} ${props.enrolled === 1 ? 'person' : 'people'}. Their first step goes out in the mailbox's sending hours.`\n : 'Nobody was enrolled.'}\n </Alert>\n {refused.length ? (\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">\n Not enrolled, checked again just now:\n </Typography>\n {refused.map((result) => (\n <Stack key={result.contactId} spacing={0.25}>\n <Typography variant=\"body2\">\n {result.email ?? result.contactId}\n </Typography>\n {result.blocks.map((block) => (\n <Typography\n key={block.code}\n variant=\"body2\"\n color=\"text.secondary\"\n >\n {block.reason}\n </Typography>\n ))}\n </Stack>\n ))}\n </Stack>\n ) : null}\n </Stack>\n )\n}\n\nexport default OutreachEnrollDialog\n"],"names":["pluginDocsHelp","HelpTip","Alert","Button","Checkbox","Chip","Dialog","DialogActions","DialogContent","DialogTitle","FormControlLabel","FormGroup","List","ListItem","ListItemButton","ListItemIcon","ListItemText","MenuItem","Paper","Stack","Tab","Tabs","TextField","Typography","useMediaQuery","useTheme","useMemo","useState","OUTREACH_ENROLL_BATCH_MAX","OUTREACH_ATTESTATION_LABELS","OUTREACH_PERSONAL_LINE_MAX","OutreachLoading","OutreachLoadProblem","useOutreachContactSearch","useOutreachSavedViews","STATUS_LABELS","eligible","needs_confirmation","blocked","STATUS_COLORS","outreachPersonReady","person","supplied","status","include","line","personalLine","trim","length","requires","attestations","every","kind","includes","OutreachEnrollDialog","props","orgId","sequence","api","theme","narrow","breakpoints","down","tab","setTab","viewId","setViewId","text","setText","picked","setPicked","Map","stage","setStage","problem","setProblem","setSupplied","emailPreview","setEmailPreview","views","open","uid","search","hostId","contactGroupId","reset","close","onClose","preview","source","answer","previewEnrollment","id","Object","fromEntries","people","map","contactId","error","message","ready","filter","waiting","enroll","result","results","enrolled","supply","next","previous","previewEmail","sequenceId","title","name","fullWidth","maxWidth","fullScreen","aria-label","direction","spacing","sx","alignItems","span","anchor","dividers","severity","value","onChange","_event","label","what","data","select","event","target","helperText","view","placeholder","autoFocus","idle","variant","color","dense","contact","checked","has","disablePadding","onClick","delete","size","set","edge","tabIndex","disableRipple","primary","email","secondary","flexWrap","rowGap","values","onDelete","summary","truncated","total","component","listStyle","p","m","PersonRow","onSupply","onPreviewEmail","disabled","DoneSummary","contactIds","keys","displayName","count","tooLong","xs","sm","flexGrow","minWidth","cold","pl","blocks","block","reason","code","control","required","entry","subject","whiteSpace","wordBreak","mt","refused","outcome"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/enroll-dialog.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { HelpTip } from '@aglyn/shared-ui-jsx'\nimport {\n Alert,\n Button,\n Checkbox,\n Chip,\n type ChipProps,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n FormControlLabel,\n FormGroup,\n List,\n ListItem,\n ListItemButton,\n ListItemIcon,\n ListItemText,\n MenuItem,\n Paper,\n Stack,\n Tab,\n Tabs,\n TextField,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@mui/material'\nimport { useMemo, useState } from 'react'\nimport {\n OUTREACH_ENROLL_BATCH_MAX,\n type OutreachEnrollOutcome,\n type OutreachEnrollPreviewPerson,\n type OutreachEnrollPreviewResponse,\n type OutreachEnrollPreviewStatus,\n type OutreachEnrollSource,\n type OutreachPreviewResponse,\n} from '../model/outreach-api'\nimport {\n OUTREACH_ATTESTATION_LABELS,\n OUTREACH_PERSONAL_LINE_MAX,\n type OutreachAttestationKind,\n type OutreachSequence,\n} from '../model/outreach.types'\nimport { OutreachLoading, OutreachLoadProblem } from './outreach-ui'\nimport type { OutreachApi } from './use-outreach-api'\nimport {\n type OutreachContactOption,\n useOutreachContactSearch,\n useOutreachLeadSearch,\n useOutreachSavedViews,\n} from './use-outreach-crm'\n\nexport interface OutreachEnrollDialogProps {\n open: boolean\n onClose(): void\n orgId: string\n sequence: OutreachSequence\n /** The consent group of the sequence's site: whose names a search shows. */\n contactGroupId: string\n uid: string | null\n api: OutreachApi\n}\n\nconst STATUS_LABELS: Record<OutreachEnrollPreviewStatus, string> = {\n eligible: 'Eligible',\n needs_confirmation: 'Needs you',\n blocked: 'Blocked',\n}\n\nconst STATUS_COLORS: Record<OutreachEnrollPreviewStatus, ChipProps['color']> = {\n eligible: 'success',\n needs_confirmation: 'warning',\n blocked: 'default',\n}\n\n/** What the rep has supplied for one person. */\ninterface Supplied {\n include: boolean\n personalLine: string\n attestations: OutreachAttestationKind[]\n}\n\ntype Stage =\n | { kind: 'source' }\n | { kind: 'previewing' }\n | { kind: 'preview'; answer: OutreachEnrollPreviewResponse }\n | { kind: 'enrolling'; answer: OutreachEnrollPreviewResponse }\n | { kind: 'done'; results: OutreachEnrollOutcome[]; enrolled: number }\n\n/** Whether a person may be sent to Confirm as the rep has left them. */\nexport function outreachPersonReady(\n person: OutreachEnrollPreviewPerson,\n supplied: Supplied | undefined,\n): boolean {\n if (person.status === 'blocked' || !supplied?.include) return false\n const line = supplied.personalLine.trim()\n if (line.length > OUTREACH_PERSONAL_LINE_MAX) return false\n if (person.status === 'eligible') return true\n if (person.requires.personalLine && !line) return false\n return person.requires.attestations.every((kind) =>\n supplied.attestations.includes(kind),\n )\n}\n\n/**\n * Enroll people in a sequence (AGL-2980).\n *\n * The rep picks a saved Contacts view or searches for people, and sees each\n * marked as the gates see them: eligible, blocked with the reason, or\n * waiting on them — for a cold contact, a personal line and the three\n * attestations only they can make, stored on the enrollment with who ticked\n * them and when. Enroll sends only the people who are ready, and the server\n * checks every gate again as it enrolls them.\n */\nexport function OutreachEnrollDialog(props: OutreachEnrollDialogProps) {\n const { orgId, sequence, api } = props\n const theme = useTheme()\n const narrow = useMediaQuery(theme.breakpoints.down('sm'))\n const [tab, setTab] = useState<'view' | 'search' | 'leads'>('view')\n const [viewId, setViewId] = useState('')\n const [text, setText] = useState('')\n const [picked, setPicked] = useState<Map<string, OutreachContactOption>>(\n new Map(),\n )\n // The leads picked from the sequence's site (AGL-3234), kept apart from\n // the contacts: the two are different records and the source names which.\n const [leadText, setLeadText] = useState('')\n const [pickedLeads, setPickedLeads] = useState<Map<string, OutreachContactOption>>(\n new Map(),\n )\n const [stage, setStage] = useState<Stage>({ kind: 'source' })\n const [problem, setProblem] = useState<string | null>(null)\n const [supplied, setSupplied] = useState<Record<string, Supplied>>({})\n const [emailPreview, setEmailPreview] = useState<\n Record<\n string,\n | { status: 'loading' }\n | { status: 'ready'; answer: OutreachPreviewResponse }\n | { status: 'failed'; message: string }\n >\n >({})\n\n const views = useOutreachSavedViews(props.open ? orgId : null, props.uid)\n const search = useOutreachContactSearch({\n orgId: props.open && tab === 'search' ? orgId : null,\n hostId: sequence.hostId,\n contactGroupId: props.contactGroupId,\n text,\n })\n const leadSearch = useOutreachLeadSearch({\n hostId: sequence.hostId,\n text: leadText,\n enabled: props.open && tab === 'leads',\n })\n\n const reset = () => {\n setStage({ kind: 'source' })\n setProblem(null)\n setSupplied({})\n setEmailPreview({})\n }\n const close = () => {\n reset()\n setPicked(new Map())\n setPickedLeads(new Map())\n setText('')\n setLeadText('')\n setViewId('')\n props.onClose()\n }\n\n const preview = async (source: OutreachEnrollSource) => {\n setProblem(null)\n setStage({ kind: 'previewing' })\n try {\n const answer = await api.previewEnrollment(sequence.id, source)\n setSupplied(\n Object.fromEntries(\n answer.people.map((person) => [\n person.personId,\n {\n include: person.status !== 'blocked',\n personalLine: '',\n attestations: [],\n },\n ]),\n ),\n )\n setStage({ kind: 'preview', answer })\n } catch (error) {\n setProblem((error as Error).message)\n setStage({ kind: 'source' })\n }\n }\n\n const answer =\n stage.kind === 'preview' || stage.kind === 'enrolling' ? stage.answer : null\n const ready = useMemo(\n () =>\n answer\n ? answer.people.filter((person) =>\n outreachPersonReady(person, supplied[person.personId]),\n )\n : [],\n [answer, supplied],\n )\n const waiting = answer\n ? answer.people.filter(\n (person) =>\n person.status === 'needs_confirmation' &&\n supplied[person.personId]?.include &&\n !outreachPersonReady(person, supplied[person.personId]),\n ).length\n : 0\n\n const enroll = async () => {\n if (!answer || !ready.length) return\n setProblem(null)\n setStage({ kind: 'enrolling', answer })\n try {\n const result = await api.enroll(\n sequence.id,\n ready.map((person) => ({\n // A contact by id, or a lead by its key (AGL-3234).\n ...(person.target === 'lead' && person.leadId\n ? { leadId: person.leadId }\n : { contactId: person.contactId }),\n personalLine: supplied[person.personId]?.personalLine.trim() ?? '',\n attestations: supplied[person.personId]?.attestations ?? [],\n })),\n )\n setStage({\n kind: 'done',\n results: result.results,\n enrolled: result.enrolled,\n })\n } catch (error) {\n setProblem((error as Error).message)\n setStage({ kind: 'preview', answer })\n }\n }\n\n const supply = (personId: string, next: Partial<Supplied>) =>\n setSupplied((previous) => ({\n ...previous,\n [personId]: { ...previous[personId], ...next } as Supplied,\n }))\n\n const previewEmail = async (person: OutreachEnrollPreviewPerson) => {\n setEmailPreview((previous) => ({\n ...previous,\n [person.personId]: { status: 'loading' },\n }))\n try {\n const result = await api.previewEmail({\n sequenceId: sequence.id,\n ...(person.target === 'lead' && person.leadId\n ? { leadId: person.leadId }\n : { contactId: person.contactId }),\n personalLine: supplied[person.personId]?.personalLine.trim() ?? '',\n })\n setEmailPreview((previous) => ({\n ...previous,\n [person.personId]: { status: 'ready', answer: result },\n }))\n } catch (error) {\n setEmailPreview((previous) => ({\n ...previous,\n [person.personId]: {\n status: 'failed',\n message: (error as Error).message,\n },\n }))\n }\n }\n\n const title = `Enroll people in ${sequence.name}`\n\n return (\n <Dialog\n open={props.open}\n onClose={close}\n fullWidth\n maxWidth=\"md\"\n fullScreen={narrow}\n aria-label={title}\n >\n <DialogTitle>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <span>{title}</span>\n <HelpTip {...pluginDocsHelp('sequences', { anchor: '#enroll' })} />\n </Stack>\n </DialogTitle>\n <DialogContent dividers>\n <Stack spacing={2}>\n {problem ? <Alert severity=\"error\">{problem}</Alert> : null}\n\n {stage.kind === 'source' ? (\n <>\n <Tabs\n value={tab}\n onChange={(_event, next) => setTab(next)}\n aria-label=\"Where the people come from\"\n >\n <Tab value=\"view\" label=\"Saved view\" />\n <Tab value=\"search\" label=\"Search\" />\n <Tab value=\"leads\" label=\"Leads\" />\n </Tabs>\n {tab === 'view' ? (\n views.status === 'loading' ? (\n <OutreachLoading label=\"Loading saved views…\" />\n ) : views.status === 'error' || views.status === 'refused' ? (\n <OutreachLoadProblem\n status={views.status}\n what=\"saved views\"\n message={\n views.status === 'refused'\n ? 'Enrolling reads your CRM’s contacts, and your role does not include Manage data.'\n : null\n }\n />\n ) : views.data.length ? (\n <TextField\n select\n label=\"Saved Contacts view\"\n value={viewId}\n onChange={(event) => setViewId(event.target.value)}\n helperText={`Enrolls up to ${OUTREACH_ENROLL_BATCH_MAX} of the people the view shows at this sequence’s site — a Contacts view, or a Leads view of the site’s leads.`}\n fullWidth\n >\n {views.data.map((view) => (\n <MenuItem key={view.id} value={view.id}>\n {view.section === 'leads' ? `${view.name} (Leads)` : view.name}\n </MenuItem>\n ))}\n </TextField>\n ) : (\n <Alert severity=\"info\">\n You have no saved Contacts views to enroll from. Save one in\n the CRM, or search instead.\n </Alert>\n )\n ) : tab === 'leads' ? (\n <Stack spacing={1.5}>\n <TextField\n label=\"Search leads\"\n placeholder=\"A name, or an email address\"\n value={leadText}\n onChange={(event) => setLeadText(event.target.value)}\n helperText=\"The open leads at this sequence’s site. A lead is enrolled as it is, and follows itself to the contact it becomes.\"\n fullWidth\n autoFocus\n />\n {leadSearch.status === 'loading' ? (\n <OutreachLoading label=\"Reading leads…\" />\n ) : null}\n {leadSearch.status === 'error' || leadSearch.status === 'refused' ? (\n <OutreachLoadProblem\n status={leadSearch.status}\n what=\"leads\"\n message={\n leadSearch.status === 'refused'\n ? 'Enrolling reads your CRM’s leads, and your role does not include Manage data.'\n : 'The leads could not be read. Try again.'\n }\n />\n ) : null}\n {leadSearch.status === 'ready' && !leadSearch.idle && !leadSearch.data.length ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n No open leads at this sequence’s site match.\n </Typography>\n ) : null}\n {leadSearch.data.length ? (\n <List dense aria-label=\"Lead results\">\n {leadSearch.data.map((lead) => {\n const checked = pickedLeads.has(lead.id)\n return (\n <ListItem key={lead.id} disablePadding>\n <ListItemButton\n onClick={() =>\n setPickedLeads((previous) => {\n const next = new Map(previous)\n if (checked) next.delete(lead.id)\n else if (next.size < OUTREACH_ENROLL_BATCH_MAX) next.set(lead.id, lead)\n return next\n })\n }\n >\n <ListItemIcon>\n <Checkbox edge=\"start\" checked={checked} tabIndex={-1} disableRipple />\n </ListItemIcon>\n <ListItemText\n primary={lead.name || lead.email || lead.id}\n secondary={lead.email}\n />\n </ListItemButton>\n </ListItem>\n )\n })}\n </List>\n ) : null}\n {pickedLeads.size ? (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ flexWrap: 'wrap', rowGap: 1 }}\n aria-label=\"Picked leads\"\n >\n {[...pickedLeads.values()].map((lead) => (\n <Chip\n key={lead.id}\n size=\"small\"\n label={lead.name || lead.email || lead.id}\n onDelete={() =>\n setPickedLeads((previous) => {\n const next = new Map(previous)\n next.delete(lead.id)\n return next\n })\n }\n />\n ))}\n </Stack>\n ) : null}\n </Stack>\n ) : (\n <Stack spacing={1.5}>\n <TextField\n label=\"Search contacts\"\n placeholder=\"A name, or an email address\"\n value={text}\n onChange={(event) => setText(event.target.value)}\n fullWidth\n autoFocus\n />\n {search.status === 'loading' ? (\n <OutreachLoading label=\"Searching…\" />\n ) : null}\n {search.status === 'error' || search.status === 'refused' ? (\n <OutreachLoadProblem\n status={search.status}\n what=\"contacts\"\n message={\n search.status === 'refused'\n ? 'Enrolling reads your CRM’s contacts, and your role does not include Manage data.'\n : 'The search failed. Try again.'\n }\n />\n ) : null}\n {search.status === 'ready' &&\n !search.idle &&\n !search.data.length ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n No contacts at this sequence’s site match.\n </Typography>\n ) : null}\n {search.data.length ? (\n <List dense aria-label=\"Search results\">\n {search.data.map((contact) => {\n const checked = picked.has(contact.id)\n return (\n <ListItem key={contact.id} disablePadding>\n <ListItemButton\n onClick={() =>\n setPicked((previous) => {\n const next = new Map(previous)\n if (checked) next.delete(contact.id)\n else if (\n next.size < OUTREACH_ENROLL_BATCH_MAX\n )\n next.set(contact.id, contact)\n return next\n })\n }\n >\n <ListItemIcon>\n <Checkbox\n edge=\"start\"\n checked={checked}\n tabIndex={-1}\n disableRipple\n />\n </ListItemIcon>\n <ListItemText\n primary={\n contact.name || contact.email || contact.id\n }\n secondary={contact.email}\n />\n </ListItemButton>\n </ListItem>\n )\n })}\n </List>\n ) : null}\n {picked.size ? (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ flexWrap: 'wrap', rowGap: 1 }}\n aria-label=\"Picked\"\n >\n {[...picked.values()].map((contact) => (\n <Chip\n key={contact.id}\n size=\"small\"\n label={contact.name || contact.email || contact.id}\n onDelete={() =>\n setPicked((previous) => {\n const next = new Map(previous)\n next.delete(contact.id)\n return next\n })\n }\n />\n ))}\n </Stack>\n ) : null}\n </Stack>\n )}\n </>\n ) : null}\n\n {stage.kind === 'previewing' ? (\n <OutreachLoading label=\"Checking each person…\" />\n ) : null}\n\n {answer ? (\n <Stack spacing={1.5}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {summary(answer)}\n </Typography>\n {answer.truncated ? (\n <Alert severity=\"info\">\n {`This shows the first ${answer.people.length} of ${answer.total}. Enroll these, then preview again for the rest.`}\n </Alert>\n ) : null}\n <Stack\n spacing={1}\n component=\"ul\"\n sx={{ listStyle: 'none', p: 0, m: 0 }}\n aria-label=\"People\"\n >\n {answer.people.map((person) => (\n <PersonRow\n key={person.personId}\n person={person}\n supplied={supplied[person.personId]}\n onSupply={(next) => supply(person.personId, next)}\n emailPreview={emailPreview[person.personId]}\n onPreviewEmail={() => void previewEmail(person)}\n disabled={stage.kind === 'enrolling'}\n />\n ))}\n </Stack>\n {waiting ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`${waiting} ${waiting === 1 ? 'person still needs' : 'people still need'} a personal line or a confirmation, and won't be enrolled until they have one.`}\n </Typography>\n ) : null}\n </Stack>\n ) : null}\n\n {stage.kind === 'done' ? (\n <DoneSummary results={stage.results} enrolled={stage.enrolled} />\n ) : null}\n </Stack>\n </DialogContent>\n <DialogActions>\n {stage.kind === 'done' ? (\n <Button variant=\"contained\" onClick={close}>\n Done\n </Button>\n ) : (\n <>\n <Button onClick={close}>Cancel</Button>\n {stage.kind === 'preview' || stage.kind === 'enrolling' ? (\n <>\n <Button onClick={reset} disabled={stage.kind === 'enrolling'}>\n Back\n </Button>\n <Button\n variant=\"contained\"\n disabled={!ready.length || stage.kind === 'enrolling'}\n onClick={() => void enroll()}\n >\n {stage.kind === 'enrolling'\n ? 'Enrolling…'\n : `Enroll ${ready.length} ${ready.length === 1 ? 'person' : 'people'}`}\n </Button>\n </>\n ) : (\n <Button\n variant=\"contained\"\n disabled={\n stage.kind === 'previewing' ||\n (tab === 'view' ? !viewId : tab === 'leads' ? !pickedLeads.size : !picked.size)\n }\n onClick={() =>\n void preview(\n tab === 'view'\n ? { kind: 'view', viewId }\n : tab === 'leads'\n ? { kind: 'leads', leadIds: [...pickedLeads.keys()] }\n : { kind: 'contacts', contactIds: [...picked.keys()] },\n )\n }\n >\n Check people\n </Button>\n )}\n </>\n )}\n </DialogActions>\n </Dialog>\n )\n}\nOutreachEnrollDialog.displayName = 'OutreachEnrollDialog'\n\nfunction summary(answer: OutreachEnrollPreviewResponse): string {\n const count = (status: OutreachEnrollPreviewStatus) =>\n answer.people.filter((person) => person.status === status).length\n return `${count('eligible')} eligible · ${count('needs_confirmation')} need you · ${count('blocked')} blocked`\n}\n\nfunction PersonRow(props: {\n person: OutreachEnrollPreviewPerson\n supplied: Supplied | undefined\n onSupply(next: Partial<Supplied>): void\n emailPreview:\n | { status: 'loading' }\n | { status: 'ready'; answer: OutreachPreviewResponse }\n | { status: 'failed'; message: string }\n | undefined\n onPreviewEmail(): void\n disabled: boolean\n}) {\n const { person, supplied, disabled } = props\n const name = person.name || person.email || person.personId\n const line = supplied?.personalLine ?? ''\n const tooLong = line.trim().length > OUTREACH_PERSONAL_LINE_MAX\n return (\n <Paper component=\"li\" variant=\"outlined\" sx={{ p: 1.5 }} aria-label={name}>\n <Stack spacing={1}>\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n spacing={1}\n sx={{ alignItems: { sm: 'center' } }}\n >\n <Stack sx={{ flexGrow: 1, minWidth: 0 }}>\n <Typography variant=\"body2\">{name}</Typography>\n {person.email && person.email !== name ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {person.email}\n </Typography>\n ) : null}\n </Stack>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n {person.target === 'lead' ? (\n <Chip size=\"small\" variant=\"outlined\" label=\"Lead\" />\n ) : null}\n {person.cold ? (\n <Chip size=\"small\" variant=\"outlined\" label=\"Cold\" />\n ) : null}\n <Chip\n size=\"small\"\n label={STATUS_LABELS[person.status]}\n color={STATUS_COLORS[person.status]}\n />\n </Stack>\n </Stack>\n {person.status === 'blocked' ? (\n <Stack component=\"ul\" spacing={0.5} sx={{ m: 0, pl: 2.5 }}>\n {person.blocks.map((block) => (\n <Typography\n key={block.code}\n component=\"li\"\n variant=\"body2\"\n color=\"text.secondary\"\n >\n {block.reason}\n </Typography>\n ))}\n </Stack>\n ) : (\n <Stack spacing={1}>\n <FormControlLabel\n control={\n <Checkbox\n checked={supplied?.include ?? true}\n onChange={(event) =>\n props.onSupply({ include: event.target.checked })\n }\n disabled={disabled}\n />\n }\n label=\"Enroll this person\"\n />\n {supplied?.include === false ? null : (\n <>\n <TextField\n label={\n person.requires.personalLine\n ? 'Personal line'\n : 'Personal line (optional)'\n }\n placeholder=\"One sentence on why you're writing to this person now.\"\n value={line}\n onChange={(event) =>\n props.onSupply({ personalLine: event.target.value })\n }\n disabled={disabled}\n required={person.requires.personalLine}\n error={tooLong}\n helperText={\n tooLong\n ? `Keep it to one sentence, under ${OUTREACH_PERSONAL_LINE_MAX} characters.`\n : 'Goes where the emails say {{enrollment.personalLine}}.'\n }\n fullWidth\n size=\"small\"\n />\n {person.requires.attestations.length ? (\n <FormGroup aria-label={`What you confirm about ${name}`}>\n {person.requires.attestations.map((kind) => (\n <FormControlLabel\n key={kind}\n control={\n <Checkbox\n checked={\n supplied?.attestations.includes(kind) ?? false\n }\n onChange={(event) =>\n props.onSupply({\n attestations: event.target.checked\n ? [...(supplied?.attestations ?? []), kind]\n : (supplied?.attestations ?? []).filter(\n (entry) => entry !== kind,\n ),\n })\n }\n disabled={disabled}\n />\n }\n label={OUTREACH_ATTESTATION_LABELS[kind]}\n />\n ))}\n </FormGroup>\n ) : null}\n <Stack direction=\"row\">\n <Button\n size=\"small\"\n onClick={props.onPreviewEmail}\n disabled={disabled}\n >\n Preview the first email\n </Button>\n </Stack>\n {props.emailPreview?.status === 'loading' ? (\n <OutreachLoading label=\"Writing the email…\" />\n ) : null}\n {props.emailPreview?.status === 'failed' ? (\n <Alert severity=\"error\">{props.emailPreview.message}</Alert>\n ) : null}\n {props.emailPreview?.status === 'ready' ? (\n props.emailPreview.answer.error ? (\n <Alert severity=\"info\">\n {props.emailPreview.answer.error.message}\n </Alert>\n ) : (\n <Paper\n variant=\"outlined\"\n sx={{ p: 1.5 }}\n aria-label={`First email to ${name}`}\n >\n <Typography variant=\"body2\">{`Subject: ${props.emailPreview.answer.subject}`}</Typography>\n <Typography\n variant=\"body2\"\n sx={{\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n mt: 1,\n }}\n >\n {props.emailPreview.answer.text}\n </Typography>\n </Paper>\n )\n ) : null}\n </>\n )}\n </Stack>\n )}\n </Stack>\n </Paper>\n )\n}\n\nfunction DoneSummary(props: {\n results: OutreachEnrollOutcome[]\n enrolled: number\n}) {\n const refused = props.results.filter(\n (\n result,\n ): result is Extract<OutreachEnrollOutcome, { outcome: 'blocked' }> =>\n result.outcome === 'blocked',\n )\n return (\n <Stack spacing={1.5}>\n <Alert severity={props.enrolled ? 'success' : 'info'}>\n {props.enrolled\n ? `Enrolled ${props.enrolled} ${props.enrolled === 1 ? 'person' : 'people'}. Their first step goes out in the mailbox's sending hours.`\n : 'Nobody was enrolled.'}\n </Alert>\n {refused.length ? (\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">\n Not enrolled, checked again just now:\n </Typography>\n {refused.map((result) => (\n <Stack key={result.personId} spacing={0.25}>\n <Typography variant=\"body2\">\n {result.email ?? result.personId}\n </Typography>\n {result.blocks.map((block) => (\n <Typography\n key={block.code}\n variant=\"body2\"\n color=\"text.secondary\"\n >\n {block.reason}\n </Typography>\n ))}\n </Stack>\n ))}\n </Stack>\n ) : null}\n </Stack>\n )\n}\n\nexport default OutreachEnrollDialog\n"],"names":["pluginDocsHelp","HelpTip","Alert","Button","Checkbox","Chip","Dialog","DialogActions","DialogContent","DialogTitle","FormControlLabel","FormGroup","List","ListItem","ListItemButton","ListItemIcon","ListItemText","MenuItem","Paper","Stack","Tab","Tabs","TextField","Typography","useMediaQuery","useTheme","useMemo","useState","OUTREACH_ENROLL_BATCH_MAX","OUTREACH_ATTESTATION_LABELS","OUTREACH_PERSONAL_LINE_MAX","OutreachLoading","OutreachLoadProblem","useOutreachContactSearch","useOutreachLeadSearch","useOutreachSavedViews","STATUS_LABELS","eligible","needs_confirmation","blocked","STATUS_COLORS","outreachPersonReady","person","supplied","status","include","line","personalLine","trim","length","requires","attestations","every","kind","includes","OutreachEnrollDialog","props","orgId","sequence","api","theme","narrow","breakpoints","down","tab","setTab","viewId","setViewId","text","setText","picked","setPicked","Map","leadText","setLeadText","pickedLeads","setPickedLeads","stage","setStage","problem","setProblem","setSupplied","emailPreview","setEmailPreview","views","open","uid","search","hostId","contactGroupId","leadSearch","enabled","reset","close","onClose","preview","source","answer","previewEnrollment","id","Object","fromEntries","people","map","personId","error","message","ready","filter","waiting","enroll","result","target","leadId","contactId","results","enrolled","supply","next","previous","previewEmail","sequenceId","title","name","fullWidth","maxWidth","fullScreen","aria-label","direction","spacing","sx","alignItems","span","anchor","dividers","severity","value","onChange","_event","label","what","data","select","event","helperText","view","section","placeholder","autoFocus","idle","variant","color","dense","lead","checked","has","disablePadding","onClick","delete","size","set","edge","tabIndex","disableRipple","primary","email","secondary","flexWrap","rowGap","values","onDelete","contact","summary","truncated","total","component","listStyle","p","m","PersonRow","onSupply","onPreviewEmail","disabled","DoneSummary","leadIds","keys","contactIds","displayName","count","tooLong","xs","sm","flexGrow","minWidth","cold","pl","blocks","block","reason","code","control","required","entry","subject","whiteSpace","wordBreak","mt","refused","outcome"],"mappings":"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"}
|