@aglyn/plugins-outreach 1.0.0-beta.143
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/LICENSE +201 -0
- package/README.md +93 -0
- package/package.json +52 -0
- package/src/index.d.ts +22 -0
- package/src/index.js +29 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/compliance-section.d.ts +20 -0
- package/src/lib/components/compliance-section.js +291 -0
- package/src/lib/components/compliance-section.js.map +1 -0
- package/src/lib/components/enroll-dialog.d.ts +36 -0
- package/src/lib/components/enroll-dialog.js +656 -0
- package/src/lib/components/enroll-dialog.js.map +1 -0
- package/src/lib/components/enrollments-table.d.ts +28 -0
- package/src/lib/components/enrollments-table.js +375 -0
- package/src/lib/components/enrollments-table.js.map +1 -0
- package/src/lib/components/mailbox-card.d.ts +46 -0
- package/src/lib/components/mailbox-card.js +517 -0
- package/src/lib/components/mailbox-card.js.map +1 -0
- package/src/lib/components/mailboxes-section.d.ts +24 -0
- package/src/lib/components/mailboxes-section.js +258 -0
- package/src/lib/components/mailboxes-section.js.map +1 -0
- package/src/lib/components/outreach-console-page.d.ts +17 -0
- package/src/lib/components/outreach-console-page.js +81 -0
- package/src/lib/components/outreach-console-page.js.map +1 -0
- package/src/lib/components/outreach-console-sections.d.ts +43 -0
- package/src/lib/components/outreach-console-sections.js +55 -0
- package/src/lib/components/outreach-console-sections.js.map +1 -0
- package/src/lib/components/outreach-ui.d.ts +51 -0
- package/src/lib/components/outreach-ui.js +171 -0
- package/src/lib/components/outreach-ui.js.map +1 -0
- package/src/lib/components/send-window-fields.d.ts +25 -0
- package/src/lib/components/send-window-fields.js +178 -0
- package/src/lib/components/send-window-fields.js.map +1 -0
- package/src/lib/components/sequence-detail.d.ts +54 -0
- package/src/lib/components/sequence-detail.js +435 -0
- package/src/lib/components/sequence-detail.js.map +1 -0
- package/src/lib/components/sequence-editor.d.ts +37 -0
- package/src/lib/components/sequence-editor.js +485 -0
- package/src/lib/components/sequence-editor.js.map +1 -0
- package/src/lib/components/sequence-mailbox-picker.d.ts +44 -0
- package/src/lib/components/sequence-mailbox-picker.js +137 -0
- package/src/lib/components/sequence-mailbox-picker.js.map +1 -0
- package/src/lib/components/sequence-preview.d.ts +27 -0
- package/src/lib/components/sequence-preview.js +146 -0
- package/src/lib/components/sequence-preview.js.map +1 -0
- package/src/lib/components/sequence-step-card.d.ts +31 -0
- package/src/lib/components/sequence-step-card.js +326 -0
- package/src/lib/components/sequence-step-card.js.map +1 -0
- package/src/lib/components/sequences-section.d.ts +40 -0
- package/src/lib/components/sequences-section.js +310 -0
- package/src/lib/components/sequences-section.js.map +1 -0
- package/src/lib/components/use-outreach-api.d.ts +38 -0
- package/src/lib/components/use-outreach-api.js +139 -0
- package/src/lib/components/use-outreach-api.js.map +1 -0
- package/src/lib/components/use-outreach-crm.d.ts +50 -0
- package/src/lib/components/use-outreach-crm.js +200 -0
- package/src/lib/components/use-outreach-crm.js.map +1 -0
- package/src/lib/components/use-outreach-data.d.ts +55 -0
- package/src/lib/components/use-outreach-data.js +199 -0
- package/src/lib/components/use-outreach-data.js.map +1 -0
- package/src/lib/components/use-outreach-mailbox-api.d.ts +30 -0
- package/src/lib/components/use-outreach-mailbox-api.js +101 -0
- package/src/lib/components/use-outreach-mailbox-api.js.map +1 -0
- package/src/lib/components/use-outreach-mailboxes.d.ts +22 -0
- package/src/lib/components/use-outreach-mailboxes.js +68 -0
- package/src/lib/components/use-outreach-mailboxes.js.map +1 -0
- package/src/lib/components/use-outreach-settings.d.ts +17 -0
- package/src/lib/components/use-outreach-settings.js +64 -0
- package/src/lib/components/use-outreach-settings.js.map +1 -0
- package/src/lib/constants/api-routes.d.ts +68 -0
- package/src/lib/constants/api-routes.js +57 -0
- package/src/lib/constants/api-routes.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +46 -0
- package/src/lib/constants/bundle-common.js +55 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/constants/runtime-jobs.d.ts +24 -0
- package/src/lib/constants/runtime-jobs.js +24 -0
- package/src/lib/constants/runtime-jobs.js.map +1 -0
- package/src/lib/declarations.console-server.d.ts +38 -0
- package/src/lib/declarations.console-server.js +99 -0
- package/src/lib/declarations.console-server.js.map +1 -0
- package/src/lib/engine/compose.d.ts +86 -0
- package/src/lib/engine/compose.js +212 -0
- package/src/lib/engine/compose.js.map +1 -0
- package/src/lib/engine/delivery-status.d.ts +53 -0
- package/src/lib/engine/delivery-status.js +184 -0
- package/src/lib/engine/delivery-status.js.map +1 -0
- package/src/lib/engine/do-not-contact.d.ts +18 -0
- package/src/lib/engine/do-not-contact.js +34 -0
- package/src/lib/engine/do-not-contact.js.map +1 -0
- package/src/lib/engine/enrollment-state.d.ts +156 -0
- package/src/lib/engine/enrollment-state.js +303 -0
- package/src/lib/engine/enrollment-state.js.map +1 -0
- package/src/lib/engine/gates.d.ts +125 -0
- package/src/lib/engine/gates.js +232 -0
- package/src/lib/engine/gates.js.map +1 -0
- package/src/lib/engine/index.d.ts +28 -0
- package/src/lib/engine/index.js +33 -0
- package/src/lib/engine/index.js.map +1 -0
- package/src/lib/engine/mailbox-health.d.ts +49 -0
- package/src/lib/engine/mailbox-health.js +83 -0
- package/src/lib/engine/mailbox-health.js.map +1 -0
- package/src/lib/engine/opt-out-intent.d.ts +41 -0
- package/src/lib/engine/opt-out-intent.js +220 -0
- package/src/lib/engine/opt-out-intent.js.map +1 -0
- package/src/lib/engine/recipient-country.d.ts +41 -0
- package/src/lib/engine/recipient-country.js +171 -0
- package/src/lib/engine/recipient-country.js.map +1 -0
- package/src/lib/engine/schedule.d.ts +70 -0
- package/src/lib/engine/schedule.js +115 -0
- package/src/lib/engine/schedule.js.map +1 -0
- package/src/lib/engine/sending-capacity.d.ts +96 -0
- package/src/lib/engine/sending-capacity.js +172 -0
- package/src/lib/engine/sending-capacity.js.map +1 -0
- package/src/lib/engine/sequence-validation.d.ts +90 -0
- package/src/lib/engine/sequence-validation.js +291 -0
- package/src/lib/engine/sequence-validation.js.map +1 -0
- package/src/lib/engine/thread-classification.d.ts +78 -0
- package/src/lib/engine/thread-classification.js +224 -0
- package/src/lib/engine/thread-classification.js.map +1 -0
- package/src/lib/engine/thread-message.d.ts +80 -0
- package/src/lib/engine/thread-message.js +143 -0
- package/src/lib/engine/thread-message.js.map +1 -0
- package/src/lib/enrollment/enroll-people.d.ts +81 -0
- package/src/lib/enrollment/enroll-people.js +250 -0
- package/src/lib/enrollment/enroll-people.js.map +1 -0
- package/src/lib/enrollment/gate-lookups.d.ts +32 -0
- package/src/lib/enrollment/gate-lookups.js +154 -0
- package/src/lib/enrollment/gate-lookups.js.map +1 -0
- package/src/lib/mailboxes/mailbox-api.d.ts +126 -0
- package/src/lib/mailboxes/mailbox-api.js +66 -0
- package/src/lib/mailboxes/mailbox-api.js.map +1 -0
- package/src/lib/mailboxes/mailbox-credentials.d.ts +95 -0
- package/src/lib/mailboxes/mailbox-credentials.js +102 -0
- package/src/lib/mailboxes/mailbox-credentials.js.map +1 -0
- package/src/lib/mailboxes/mailbox-erasure.d.ts +69 -0
- package/src/lib/mailboxes/mailbox-erasure.js +148 -0
- package/src/lib/mailboxes/mailbox-erasure.js.map +1 -0
- package/src/lib/mailboxes/mailbox-gate.d.ts +75 -0
- package/src/lib/mailboxes/mailbox-gate.js +98 -0
- package/src/lib/mailboxes/mailbox-gate.js.map +1 -0
- package/src/lib/mailboxes/mailbox-revoke.d.ts +59 -0
- package/src/lib/mailboxes/mailbox-revoke.js +41 -0
- package/src/lib/mailboxes/mailbox-revoke.js.map +1 -0
- package/src/lib/mailboxes/mailbox-routes.d.ts +119 -0
- package/src/lib/mailboxes/mailbox-routes.js +605 -0
- package/src/lib/mailboxes/mailbox-routes.js.map +1 -0
- package/src/lib/mailboxes/mailbox-settings.d.ts +110 -0
- package/src/lib/mailboxes/mailbox-settings.js +212 -0
- package/src/lib/mailboxes/mailbox-settings.js.map +1 -0
- package/src/lib/mailboxes/mailbox-transport.d.ts +64 -0
- package/src/lib/mailboxes/mailbox-transport.js +94 -0
- package/src/lib/mailboxes/mailbox-transport.js.map +1 -0
- package/src/lib/mailboxes/oauth-redirect.d.ts +41 -0
- package/src/lib/mailboxes/oauth-redirect.js +63 -0
- package/src/lib/mailboxes/oauth-redirect.js.map +1 -0
- package/src/lib/mailboxes/oauth-state.d.ts +152 -0
- package/src/lib/mailboxes/oauth-state.js +212 -0
- package/src/lib/mailboxes/oauth-state.js.map +1 -0
- package/src/lib/mailboxes/outreach-config.d.ts +64 -0
- package/src/lib/mailboxes/outreach-config.js +77 -0
- package/src/lib/mailboxes/outreach-config.js.map +1 -0
- package/src/lib/mailboxes/register-mailbox-routes.d.ts +47 -0
- package/src/lib/mailboxes/register-mailbox-routes.js +135 -0
- package/src/lib/mailboxes/register-mailbox-routes.js.map +1 -0
- package/src/lib/model/compliance-settings.d.ts +78 -0
- package/src/lib/model/compliance-settings.js +155 -0
- package/src/lib/model/compliance-settings.js.map +1 -0
- package/src/lib/model/outreach-api.d.ts +210 -0
- package/src/lib/model/outreach-api.js +28 -0
- package/src/lib/model/outreach-api.js.map +1 -0
- package/src/lib/model/outreach.types.d.ts +563 -0
- package/src/lib/model/outreach.types.js +225 -0
- package/src/lib/model/outreach.types.js.map +1 -0
- package/src/lib/model/sequence-draft.d.ts +84 -0
- package/src/lib/model/sequence-draft.js +239 -0
- package/src/lib/model/sequence-draft.js.map +1 -0
- package/src/lib/model/step-preview.d.ts +45 -0
- package/src/lib/model/step-preview.js +98 -0
- package/src/lib/model/step-preview.js.map +1 -0
- package/src/lib/model/stored-records.d.ts +23 -0
- package/src/lib/model/stored-records.js +84 -0
- package/src/lib/model/stored-records.js.map +1 -0
- package/src/lib/plugin.d.ts +46 -0
- package/src/lib/plugin.js +86 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/routes/enroll-routes.d.ts +64 -0
- package/src/lib/routes/enroll-routes.js +350 -0
- package/src/lib/routes/enroll-routes.js.map +1 -0
- package/src/lib/routes/enrollment-routes.d.ts +19 -0
- package/src/lib/routes/enrollment-routes.js +171 -0
- package/src/lib/routes/enrollment-routes.js.map +1 -0
- package/src/lib/routes/platform-deps.d.ts +51 -0
- package/src/lib/routes/platform-deps.js +66 -0
- package/src/lib/routes/platform-deps.js.map +1 -0
- package/src/lib/routes/preview-routes.d.ts +33 -0
- package/src/lib/routes/preview-routes.js +117 -0
- package/src/lib/routes/preview-routes.js.map +1 -0
- package/src/lib/routes/register-routes.d.ts +22 -0
- package/src/lib/routes/register-routes.js +92 -0
- package/src/lib/routes/register-routes.js.map +1 -0
- package/src/lib/routes/route-deps.d.ts +49 -0
- package/src/lib/routes/route-deps.js +27 -0
- package/src/lib/routes/route-deps.js.map +1 -0
- package/src/lib/routes/route-gate.d.ts +94 -0
- package/src/lib/routes/route-gate.js +87 -0
- package/src/lib/routes/route-gate.js.map +1 -0
- package/src/lib/routes/route-http.d.ts +32 -0
- package/src/lib/routes/route-http.js +62 -0
- package/src/lib/routes/route-http.js.map +1 -0
- package/src/lib/routes/sequence-routes.d.ts +32 -0
- package/src/lib/routes/sequence-routes.js +359 -0
- package/src/lib/routes/sequence-routes.js.map +1 -0
- package/src/lib/routes/settings-routes.d.ts +30 -0
- package/src/lib/routes/settings-routes.js +73 -0
- package/src/lib/routes/settings-routes.js.map +1 -0
- package/src/lib/runtime/enrollment-events.d.ts +86 -0
- package/src/lib/runtime/enrollment-events.js +141 -0
- package/src/lib/runtime/enrollment-events.js.map +1 -0
- package/src/lib/runtime/fixtures/fake-gmail.d.ts +121 -0
- package/src/lib/runtime/fixtures/fake-gmail.js +312 -0
- package/src/lib/runtime/fixtures/fake-gmail.js.map +1 -0
- package/src/lib/runtime/mailbox-health-store.d.ts +47 -0
- package/src/lib/runtime/mailbox-health-store.js +168 -0
- package/src/lib/runtime/mailbox-health-store.js.map +1 -0
- package/src/lib/runtime/person-erasure.d.ts +39 -0
- package/src/lib/runtime/person-erasure.js +57 -0
- package/src/lib/runtime/person-erasure.js.map +1 -0
- package/src/lib/runtime/platform-runtime-deps.d.ts +29 -0
- package/src/lib/runtime/platform-runtime-deps.js +98 -0
- package/src/lib/runtime/platform-runtime-deps.js.map +1 -0
- package/src/lib/runtime/runtime-deps.d.ts +77 -0
- package/src/lib/runtime/runtime-deps.js +18 -0
- package/src/lib/runtime/runtime-deps.js.map +1 -0
- package/src/lib/runtime/send-job.d.ts +42 -0
- package/src/lib/runtime/send-job.js +780 -0
- package/src/lib/runtime/send-job.js.map +1 -0
- package/src/lib/runtime/sync-job.d.ts +41 -0
- package/src/lib/runtime/sync-job.js +480 -0
- package/src/lib/runtime/sync-job.js.map +1 -0
- package/src/lib/runtime/timeline.d.ts +67 -0
- package/src/lib/runtime/timeline.js +93 -0
- package/src/lib/runtime/timeline.js.map +1 -0
- package/src/lib/runtime/unsubscribe-link.d.ts +75 -0
- package/src/lib/runtime/unsubscribe-link.js +121 -0
- package/src/lib/runtime/unsubscribe-link.js.map +1 -0
- package/src/lib/runtime/unsubscribe-route.d.ts +24 -0
- package/src/lib/runtime/unsubscribe-route.js +103 -0
- package/src/lib/runtime/unsubscribe-route.js.map +1 -0
- package/src/lib/server.d.ts +53 -0
- package/src/lib/server.js +94 -0
- package/src/lib/server.js.map +1 -0
- package/src/lib/storage/compliance-settings-store.d.ts +44 -0
- package/src/lib/storage/compliance-settings-store.js +78 -0
- package/src/lib/storage/compliance-settings-store.js.map +1 -0
- package/src/lib/storage/do-not-contact-store.d.ts +60 -0
- package/src/lib/storage/do-not-contact-store.js +168 -0
- package/src/lib/storage/do-not-contact-store.js.map +1 -0
- package/src/lib/storage/outreach-records.d.ts +33 -0
- package/src/lib/storage/outreach-records.js +35 -0
- package/src/lib/storage/outreach-records.js.map +1 -0
- package/src/lib/subprocessors.d.ts +48 -0
- package/src/lib/subprocessors.js +70 -0
- package/src/lib/subprocessors.js.map +1 -0
- package/src/lib/transport/gmail-client.d.ts +145 -0
- package/src/lib/transport/gmail-client.js +229 -0
- package/src/lib/transport/gmail-client.js.map +1 -0
- package/src/lib/transport/gmail-errors.d.ts +84 -0
- package/src/lib/transport/gmail-errors.js +138 -0
- package/src/lib/transport/gmail-errors.js.map +1 -0
- package/src/lib/transport/google-oauth.d.ts +138 -0
- package/src/lib/transport/google-oauth.js +247 -0
- package/src/lib/transport/google-oauth.js.map +1 -0
- package/src/lib/transport/http.d.ts +53 -0
- package/src/lib/transport/http.js +79 -0
- package/src/lib/transport/http.js.map +1 -0
- package/src/lib/transport/rfc5322.d.ts +116 -0
- package/src/lib/transport/rfc5322.js +330 -0
- package/src/lib/transport/rfc5322.js.map +1 -0
- package/src/lib/transport/send-message.d.ts +69 -0
- package/src/lib/transport/send-message.js +77 -0
- package/src/lib/transport/send-message.js.map +1 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
18
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
19
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
20
|
+
import { pluginDocsHelp } from "@aglyn/aglyn";
|
|
21
|
+
import { mdiPlus } from "@aglyn/shared-data-mdi";
|
|
22
|
+
import { CardDisplay, MdiIcon } from "@aglyn/shared-ui-jsx";
|
|
23
|
+
import { useSnackbar } from "@aglyn/shared-ui-snackstack";
|
|
24
|
+
import { useUser } from "@aglyn/tenant-feature-instance";
|
|
25
|
+
import { Alert, Autocomplete, Box, Button, Chip, FormControlLabel, Grid, Menu, MenuItem, Stack, Switch, TextField, Typography } from "@mui/material";
|
|
26
|
+
import { useEffect, useMemo, useState } from "react";
|
|
27
|
+
import { isInThreadEmailStep, OUTREACH_SEQUENCE_NAME_MAX, validateOutreachSequence } from "../engine/sequence-validation.js";
|
|
28
|
+
import { outreachCountryLabel } from "../model/compliance-settings.js";
|
|
29
|
+
import { OUTREACH_MAX_EMAIL_STEPS, OUTREACH_MAX_STEPS, OUTREACH_TASK_KIND_LABELS, OUTREACH_TASK_KINDS } from "../model/outreach.types.js";
|
|
30
|
+
import { emptyOutreachSequenceDraft, newOutreachEmailStep, newOutreachTaskStep, outreachSequenceDraftOf } from "../model/sequence-draft.js";
|
|
31
|
+
import { OutreachSendWindowFields } from "./send-window-fields.js";
|
|
32
|
+
import { OutreachSequenceMailboxPicker } from "./sequence-mailbox-picker.js";
|
|
33
|
+
import { OutreachSequencePreview } from "./sequence-preview.js";
|
|
34
|
+
import { OutreachStepCard } from "./sequence-step-card.js";
|
|
35
|
+
import { OutreachRouteError, useOutreachApi } from "./use-outreach-api.js";
|
|
36
|
+
import { useOutreachEmailTemplates } from "./use-outreach-crm.js";
|
|
37
|
+
/** The step a dotted issue path is about, and the field within it. */ function stepIssueKey(path) {
|
|
38
|
+
var _match_;
|
|
39
|
+
const match = /^steps\.(\d+)(?:\.(.+))?$/.exec(path);
|
|
40
|
+
if (!match) return null;
|
|
41
|
+
const field = (_match_ = match[2]) != null ? _match_ : 'step';
|
|
42
|
+
return {
|
|
43
|
+
index: Number(match[1]),
|
|
44
|
+
field: field === 'id' ? 'step' : field
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The sequence editor (AGL-2980): the name, the site and mailbox, the steps,
|
|
49
|
+
* who it sends to and when, beside a live preview of each email.
|
|
50
|
+
*
|
|
51
|
+
* Every issue the engine's validator finds is shown beside its field — the
|
|
52
|
+
* same validator the save route refuses with — errors once a save was
|
|
53
|
+
* attempted, warnings as soon as they appear. What only the server can
|
|
54
|
+
* judge (whose mailbox, which countries the organization allows, what may
|
|
55
|
+
* no longer change once people are enrolled) comes back from the save and
|
|
56
|
+
* is shown in the same places.
|
|
57
|
+
*/ export function OutreachSequenceEditor(props) {
|
|
58
|
+
var _ref, _ref1, _props_mailboxes_mailboxes_find, _ref2, _issueAt;
|
|
59
|
+
var _settings_settings, _settings_settings1, _issues_find, _hosts_find;
|
|
60
|
+
const { orgId, orgMount, sequence, settings } = props;
|
|
61
|
+
const api = useOutreachApi(orgId);
|
|
62
|
+
const { enqueueSnackbar } = useSnackbar();
|
|
63
|
+
const { data: user } = useUser();
|
|
64
|
+
const uid = (_ref = user == null ? void 0 : user.uid) != null ? _ref : null;
|
|
65
|
+
const mountedHosts = orgMount == null ? void 0 : orgMount.hosts;
|
|
66
|
+
const hosts = useMemo(()=>mountedHosts != null ? mountedHosts : [], [
|
|
67
|
+
mountedHosts
|
|
68
|
+
]);
|
|
69
|
+
const orgCountries = (_ref1 = (_settings_settings = settings.settings) == null ? void 0 : _settings_settings.allowedCountries) != null ? _ref1 : [
|
|
70
|
+
'US'
|
|
71
|
+
];
|
|
72
|
+
const [draft, setDraft] = useState(()=>sequence ? outreachSequenceDraftOf(sequence) : emptyOutreachSequenceDraft({
|
|
73
|
+
hostId: hosts.length === 1 ? hosts[0].id : '',
|
|
74
|
+
allowedCountries: orgCountries
|
|
75
|
+
}));
|
|
76
|
+
const [attempted, setAttempted] = useState(false);
|
|
77
|
+
const [serverIssues, setServerIssues] = useState([]);
|
|
78
|
+
const [saving, setSaving] = useState(false);
|
|
79
|
+
const [taskAnchor, setTaskAnchor] = useState(null);
|
|
80
|
+
// A stored sequence the listener updated (a save, a status change) is the
|
|
81
|
+
// new starting point.
|
|
82
|
+
useEffect(()=>{
|
|
83
|
+
if (sequence) setDraft(outreachSequenceDraftOf(sequence));
|
|
84
|
+
}, [
|
|
85
|
+
sequence
|
|
86
|
+
]);
|
|
87
|
+
// A new sequence starts on the organization's countries once they are read.
|
|
88
|
+
const settingsCountries = (_settings_settings1 = settings.settings) == null ? void 0 : _settings_settings1.allowedCountries.join(',');
|
|
89
|
+
useEffect(()=>{
|
|
90
|
+
if (!sequence && settingsCountries) {
|
|
91
|
+
setDraft((previous)=>_extends({}, previous, {
|
|
92
|
+
settings: _extends({}, previous.settings, {
|
|
93
|
+
allowedCountries: settingsCountries.split(',')
|
|
94
|
+
})
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
}, [
|
|
98
|
+
sequence,
|
|
99
|
+
settingsCountries
|
|
100
|
+
]);
|
|
101
|
+
useEffect(()=>{
|
|
102
|
+
if (!sequence && !draft.hostId && hosts.length === 1) setDraft((previous)=>_extends({}, previous, {
|
|
103
|
+
hostId: hosts[0].id
|
|
104
|
+
}));
|
|
105
|
+
}, [
|
|
106
|
+
sequence,
|
|
107
|
+
draft.hostId,
|
|
108
|
+
hosts
|
|
109
|
+
]);
|
|
110
|
+
// A new sequence starts on the member's own mailbox when they have exactly
|
|
111
|
+
// one that is sending.
|
|
112
|
+
const ownSending = props.mailboxes.mailboxes.filter((entry)=>entry.connectedByUid === uid && entry.status === 'connected');
|
|
113
|
+
const onlyOwnMailbox = ownSending.length === 1 ? ownSending[0].id : '';
|
|
114
|
+
useEffect(()=>{
|
|
115
|
+
if (!sequence && !draft.mailboxId && onlyOwnMailbox) setDraft((previous)=>_extends({}, previous, {
|
|
116
|
+
mailboxId: onlyOwnMailbox
|
|
117
|
+
}));
|
|
118
|
+
}, [
|
|
119
|
+
sequence,
|
|
120
|
+
draft.mailboxId,
|
|
121
|
+
onlyOwnMailbox
|
|
122
|
+
]);
|
|
123
|
+
const templates = useOutreachEmailTemplates(orgId, draft.hostId || null, uid);
|
|
124
|
+
const mailbox = (_props_mailboxes_mailboxes_find = props.mailboxes.mailboxes.find((entry)=>entry.id === draft.mailboxId)) != null ? _props_mailboxes_mailboxes_find : null;
|
|
125
|
+
const archived = (sequence == null ? void 0 : sequence.status) === 'archived';
|
|
126
|
+
const issues = useMemo(()=>{
|
|
127
|
+
const judged = [
|
|
128
|
+
...validateOutreachSequence(draft),
|
|
129
|
+
...serverIssues
|
|
130
|
+
];
|
|
131
|
+
return judged.filter((issue)=>issue.severity === 'warning' || attempted || serverIssues.includes(issue));
|
|
132
|
+
}, [
|
|
133
|
+
draft,
|
|
134
|
+
serverIssues,
|
|
135
|
+
attempted
|
|
136
|
+
]);
|
|
137
|
+
const issueAt = (path)=>{
|
|
138
|
+
var _issues_find;
|
|
139
|
+
return (_issues_find = issues.find((issue)=>issue.path === path)) == null ? void 0 : _issues_find.message;
|
|
140
|
+
};
|
|
141
|
+
const stepIssues = (index)=>{
|
|
142
|
+
const found = {};
|
|
143
|
+
for (const issue of issues){
|
|
144
|
+
const key = stepIssueKey(issue.path);
|
|
145
|
+
if ((key == null ? void 0 : key.index) === index && !found[key.field]) found[key.field] = issue.message;
|
|
146
|
+
}
|
|
147
|
+
return found;
|
|
148
|
+
};
|
|
149
|
+
const listIssue = issueAt('steps');
|
|
150
|
+
const countriesIssue = (_issues_find = issues.find((issue)=>issue.path.startsWith('settings.allowedCountries'))) == null ? void 0 : _issues_find.message;
|
|
151
|
+
const update = (next)=>{
|
|
152
|
+
setServerIssues([]);
|
|
153
|
+
setDraft((previous)=>_extends({}, previous, next));
|
|
154
|
+
};
|
|
155
|
+
const setStep = (index, step)=>update({
|
|
156
|
+
steps: draft.steps.map((entry, position)=>position === index ? step : entry)
|
|
157
|
+
});
|
|
158
|
+
const moveStep = (index, direction)=>{
|
|
159
|
+
const steps = [
|
|
160
|
+
...draft.steps
|
|
161
|
+
];
|
|
162
|
+
const [moved] = steps.splice(index, 1);
|
|
163
|
+
steps.splice(index + direction, 0, moved);
|
|
164
|
+
update({
|
|
165
|
+
steps
|
|
166
|
+
});
|
|
167
|
+
};
|
|
168
|
+
const emailCount = draft.steps.filter((step)=>step.kind === 'email').length;
|
|
169
|
+
const full = draft.steps.length >= OUTREACH_MAX_STEPS;
|
|
170
|
+
const threadSubject = (index)=>{
|
|
171
|
+
for(let position = index - 1; position >= 0; position -= 1){
|
|
172
|
+
const step = draft.steps[position];
|
|
173
|
+
if (step.kind === 'email' && !isInThreadEmailStep(draft.steps, position)) return step.subject;
|
|
174
|
+
}
|
|
175
|
+
return '';
|
|
176
|
+
};
|
|
177
|
+
const save = async ()=>{
|
|
178
|
+
setAttempted(true);
|
|
179
|
+
if (validateOutreachSequence(draft).some((issue)=>issue.severity === 'error')) return;
|
|
180
|
+
setSaving(true);
|
|
181
|
+
try {
|
|
182
|
+
var _ref;
|
|
183
|
+
const answer = await api.saveSequence((_ref = sequence == null ? void 0 : sequence.id) != null ? _ref : null, draft);
|
|
184
|
+
setServerIssues([]);
|
|
185
|
+
setAttempted(false);
|
|
186
|
+
enqueueSnackbar(answer.created ? 'Sequence created.' : 'Sequence saved.', {
|
|
187
|
+
variant: 'success'
|
|
188
|
+
});
|
|
189
|
+
props.onSaved(answer.sequence);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
if (error instanceof OutreachRouteError && error.issues.length) {
|
|
192
|
+
setServerIssues(error.issues.filter((issue)=>'path' in issue));
|
|
193
|
+
}
|
|
194
|
+
enqueueSnackbar(error.message, {
|
|
195
|
+
variant: 'error',
|
|
196
|
+
allowDuplicate: true
|
|
197
|
+
});
|
|
198
|
+
} finally{
|
|
199
|
+
setSaving(false);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
const siteName = (_ref2 = (_hosts_find = hosts.find((host)=>host.id === draft.hostId)) == null ? void 0 : _hosts_find.name) != null ? _ref2 : '';
|
|
203
|
+
const countryOptions = [
|
|
204
|
+
...new Set([
|
|
205
|
+
...orgCountries,
|
|
206
|
+
...draft.settings.allowedCountries
|
|
207
|
+
])
|
|
208
|
+
];
|
|
209
|
+
return /*#__PURE__*/ _jsxs(Grid, {
|
|
210
|
+
container: true,
|
|
211
|
+
spacing: 2,
|
|
212
|
+
children: [
|
|
213
|
+
/*#__PURE__*/ _jsx(Grid, {
|
|
214
|
+
size: {
|
|
215
|
+
xs: 12,
|
|
216
|
+
md: 7
|
|
217
|
+
},
|
|
218
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
219
|
+
spacing: 2,
|
|
220
|
+
children: [
|
|
221
|
+
archived ? /*#__PURE__*/ _jsx(Alert, {
|
|
222
|
+
severity: "info",
|
|
223
|
+
children: "This sequence is archived, so it can’t be edited."
|
|
224
|
+
}) : null,
|
|
225
|
+
/*#__PURE__*/ _jsx(CardDisplay, {
|
|
226
|
+
header: "Sequence",
|
|
227
|
+
help: pluginDocsHelp('sequences', {
|
|
228
|
+
anchor: '#build-a-sequence'
|
|
229
|
+
}),
|
|
230
|
+
contentGutterX: true,
|
|
231
|
+
contentGutterY: true,
|
|
232
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
233
|
+
spacing: 2,
|
|
234
|
+
children: [
|
|
235
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
236
|
+
label: "Name",
|
|
237
|
+
value: draft.name,
|
|
238
|
+
onChange: (event)=>update({
|
|
239
|
+
name: event.target.value
|
|
240
|
+
}),
|
|
241
|
+
disabled: archived,
|
|
242
|
+
error: Boolean(issueAt('name')),
|
|
243
|
+
helperText: issueAt('name'),
|
|
244
|
+
slotProps: {
|
|
245
|
+
htmlInput: {
|
|
246
|
+
maxLength: OUTREACH_SEQUENCE_NAME_MAX + 20
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
fullWidth: true
|
|
250
|
+
}),
|
|
251
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
252
|
+
select: true,
|
|
253
|
+
label: "Site",
|
|
254
|
+
value: hosts.some((host)=>host.id === draft.hostId) ? draft.hostId : '',
|
|
255
|
+
onChange: (event)=>update({
|
|
256
|
+
hostId: event.target.value
|
|
257
|
+
}),
|
|
258
|
+
disabled: archived || !hosts.length,
|
|
259
|
+
error: Boolean(issueAt('hostId')),
|
|
260
|
+
helperText: (_issueAt = issueAt('hostId')) != null ? _issueAt : 'The site whose contacts this sequence emails.',
|
|
261
|
+
fullWidth: true,
|
|
262
|
+
children: hosts.map((host)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
263
|
+
value: host.id,
|
|
264
|
+
children: host.name
|
|
265
|
+
}, host.id))
|
|
266
|
+
}),
|
|
267
|
+
/*#__PURE__*/ _jsx(OutreachSequenceMailboxPicker, {
|
|
268
|
+
orgId: orgId,
|
|
269
|
+
uid: uid,
|
|
270
|
+
mailboxes: props.mailboxes,
|
|
271
|
+
mailboxesPath: props.mailboxesPath,
|
|
272
|
+
value: draft.mailboxId,
|
|
273
|
+
onChange: (mailboxId)=>update({
|
|
274
|
+
mailboxId
|
|
275
|
+
}),
|
|
276
|
+
error: issueAt('mailboxId'),
|
|
277
|
+
disabled: archived
|
|
278
|
+
})
|
|
279
|
+
]
|
|
280
|
+
})
|
|
281
|
+
}),
|
|
282
|
+
listIssue ? /*#__PURE__*/ _jsx(Alert, {
|
|
283
|
+
severity: "error",
|
|
284
|
+
children: listIssue
|
|
285
|
+
}) : null,
|
|
286
|
+
draft.steps.map((step, index)=>/*#__PURE__*/ _jsx(OutreachStepCard, {
|
|
287
|
+
step: step,
|
|
288
|
+
index: index,
|
|
289
|
+
count: draft.steps.length,
|
|
290
|
+
firstEmail: draft.steps.findIndex((entry)=>entry.kind === 'email') === index,
|
|
291
|
+
inThread: isInThreadEmailStep(draft.steps, index),
|
|
292
|
+
threadSubject: threadSubject(index),
|
|
293
|
+
templates: templates.data,
|
|
294
|
+
issues: stepIssues(index),
|
|
295
|
+
disabled: archived,
|
|
296
|
+
onChange: (next)=>setStep(index, next),
|
|
297
|
+
onMove: (direction)=>moveStep(index, direction),
|
|
298
|
+
onRemove: ()=>update({
|
|
299
|
+
steps: draft.steps.filter((_entry, position)=>position !== index)
|
|
300
|
+
})
|
|
301
|
+
}, step.id || `step-${index}`)),
|
|
302
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
303
|
+
direction: "row",
|
|
304
|
+
spacing: 1,
|
|
305
|
+
sx: {
|
|
306
|
+
flexWrap: 'wrap',
|
|
307
|
+
rowGap: 1
|
|
308
|
+
},
|
|
309
|
+
children: [
|
|
310
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
311
|
+
variant: "outlined",
|
|
312
|
+
startIcon: /*#__PURE__*/ _jsx(MdiIcon, {
|
|
313
|
+
path: mdiPlus.path,
|
|
314
|
+
fontSize: "small"
|
|
315
|
+
}),
|
|
316
|
+
disabled: archived || full || emailCount >= OUTREACH_MAX_EMAIL_STEPS,
|
|
317
|
+
onClick: ()=>update({
|
|
318
|
+
steps: [
|
|
319
|
+
...draft.steps,
|
|
320
|
+
newOutreachEmailStep(draft.steps)
|
|
321
|
+
]
|
|
322
|
+
}),
|
|
323
|
+
children: "Add email"
|
|
324
|
+
}),
|
|
325
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
326
|
+
variant: "outlined",
|
|
327
|
+
startIcon: /*#__PURE__*/ _jsx(MdiIcon, {
|
|
328
|
+
path: mdiPlus.path,
|
|
329
|
+
fontSize: "small"
|
|
330
|
+
}),
|
|
331
|
+
disabled: archived || full,
|
|
332
|
+
onClick: (event)=>setTaskAnchor(event.currentTarget),
|
|
333
|
+
"aria-haspopup": "menu",
|
|
334
|
+
children: "Add task"
|
|
335
|
+
}),
|
|
336
|
+
/*#__PURE__*/ _jsx(Menu, {
|
|
337
|
+
anchorEl: taskAnchor,
|
|
338
|
+
open: Boolean(taskAnchor),
|
|
339
|
+
onClose: ()=>setTaskAnchor(null),
|
|
340
|
+
children: OUTREACH_TASK_KINDS.map((kind)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
341
|
+
onClick: ()=>{
|
|
342
|
+
setTaskAnchor(null);
|
|
343
|
+
update({
|
|
344
|
+
steps: [
|
|
345
|
+
...draft.steps,
|
|
346
|
+
newOutreachTaskStep(draft.steps, kind)
|
|
347
|
+
]
|
|
348
|
+
});
|
|
349
|
+
},
|
|
350
|
+
children: OUTREACH_TASK_KIND_LABELS[kind]
|
|
351
|
+
}, kind))
|
|
352
|
+
})
|
|
353
|
+
]
|
|
354
|
+
}),
|
|
355
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
356
|
+
variant: "caption",
|
|
357
|
+
color: "text.secondary",
|
|
358
|
+
children: `Up to ${OUTREACH_MAX_STEPS} steps, ${OUTREACH_MAX_EMAIL_STEPS} of them emails.`
|
|
359
|
+
}),
|
|
360
|
+
/*#__PURE__*/ _jsx(CardDisplay, {
|
|
361
|
+
header: "Who it sends to, and when",
|
|
362
|
+
help: pluginDocsHelp('sequences', {
|
|
363
|
+
anchor: '#build-a-sequence',
|
|
364
|
+
excerpt: '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.'
|
|
365
|
+
}),
|
|
366
|
+
contentGutterX: true,
|
|
367
|
+
contentGutterY: true,
|
|
368
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
369
|
+
spacing: 2,
|
|
370
|
+
children: [
|
|
371
|
+
/*#__PURE__*/ _jsx(Autocomplete, {
|
|
372
|
+
multiple: true,
|
|
373
|
+
options: countryOptions,
|
|
374
|
+
value: draft.settings.allowedCountries,
|
|
375
|
+
getOptionLabel: outreachCountryLabel,
|
|
376
|
+
onChange: (_event, next)=>update({
|
|
377
|
+
settings: _extends({}, draft.settings, {
|
|
378
|
+
allowedCountries: next
|
|
379
|
+
})
|
|
380
|
+
}),
|
|
381
|
+
disabled: archived,
|
|
382
|
+
renderValue: (value, getItemProps)=>value.map((code, index)=>{
|
|
383
|
+
const _getItemProps = getItemProps({
|
|
384
|
+
index
|
|
385
|
+
}), { key } = _getItemProps, item = _object_without_properties_loose(_getItemProps, [
|
|
386
|
+
"key"
|
|
387
|
+
]);
|
|
388
|
+
return /*#__PURE__*/ _jsx(Chip, _extends({
|
|
389
|
+
size: "small",
|
|
390
|
+
label: outreachCountryLabel(code)
|
|
391
|
+
}, item), key);
|
|
392
|
+
}),
|
|
393
|
+
renderInput: (params)=>/*#__PURE__*/ _jsx(TextField, _extends({}, params, {
|
|
394
|
+
label: "Countries",
|
|
395
|
+
error: Boolean(countriesIssue),
|
|
396
|
+
helperText: countriesIssue != null ? countriesIssue : 'Among the countries your organization allows. Cold contacts are emailed only in the United States.'
|
|
397
|
+
}))
|
|
398
|
+
}),
|
|
399
|
+
/*#__PURE__*/ _jsx(FormControlLabel, {
|
|
400
|
+
control: /*#__PURE__*/ _jsx(Switch, {
|
|
401
|
+
checked: draft.settings.allowCustomers,
|
|
402
|
+
onChange: (event)=>update({
|
|
403
|
+
settings: _extends({}, draft.settings, {
|
|
404
|
+
allowCustomers: event.target.checked
|
|
405
|
+
})
|
|
406
|
+
}),
|
|
407
|
+
disabled: archived
|
|
408
|
+
}),
|
|
409
|
+
label: "Include customers"
|
|
410
|
+
}),
|
|
411
|
+
/*#__PURE__*/ _jsx(OutreachSendWindowFields, {
|
|
412
|
+
window: draft.settings.window,
|
|
413
|
+
onChange: (window)=>update({
|
|
414
|
+
settings: _extends({}, draft.settings, {
|
|
415
|
+
window
|
|
416
|
+
})
|
|
417
|
+
}),
|
|
418
|
+
daysIssue: issueAt('settings.window.days'),
|
|
419
|
+
hoursIssue: issueAt('settings.window'),
|
|
420
|
+
disabled: archived
|
|
421
|
+
})
|
|
422
|
+
]
|
|
423
|
+
})
|
|
424
|
+
}),
|
|
425
|
+
archived ? null : /*#__PURE__*/ _jsxs(Stack, {
|
|
426
|
+
direction: {
|
|
427
|
+
xs: 'column',
|
|
428
|
+
sm: 'row'
|
|
429
|
+
},
|
|
430
|
+
spacing: 1,
|
|
431
|
+
sx: {
|
|
432
|
+
justifyContent: 'flex-end'
|
|
433
|
+
},
|
|
434
|
+
children: [
|
|
435
|
+
props.onCancel ? /*#__PURE__*/ _jsx(Button, {
|
|
436
|
+
variant: "text",
|
|
437
|
+
onClick: props.onCancel,
|
|
438
|
+
disabled: saving,
|
|
439
|
+
children: "Cancel"
|
|
440
|
+
}) : null,
|
|
441
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
442
|
+
variant: "contained",
|
|
443
|
+
onClick: ()=>void save(),
|
|
444
|
+
disabled: saving,
|
|
445
|
+
children: saving ? 'Saving…' : sequence ? 'Save' : 'Create sequence'
|
|
446
|
+
})
|
|
447
|
+
]
|
|
448
|
+
})
|
|
449
|
+
]
|
|
450
|
+
})
|
|
451
|
+
}),
|
|
452
|
+
/*#__PURE__*/ _jsx(Grid, {
|
|
453
|
+
size: {
|
|
454
|
+
xs: 12,
|
|
455
|
+
md: 5
|
|
456
|
+
},
|
|
457
|
+
children: /*#__PURE__*/ _jsx(Box, {
|
|
458
|
+
sx: {
|
|
459
|
+
position: {
|
|
460
|
+
md: 'sticky'
|
|
461
|
+
},
|
|
462
|
+
top: {
|
|
463
|
+
md: 16
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
children: /*#__PURE__*/ _jsx(OutreachSequencePreview, {
|
|
467
|
+
steps: draft.steps,
|
|
468
|
+
orgSettings: settings.settings,
|
|
469
|
+
orgSettingsStatus: settings.status,
|
|
470
|
+
templates: templates.data,
|
|
471
|
+
sender: mailbox ? {
|
|
472
|
+
name: mailbox.displayName,
|
|
473
|
+
email: mailbox.sendAs || mailbox.email
|
|
474
|
+
} : null,
|
|
475
|
+
siteName: siteName
|
|
476
|
+
})
|
|
477
|
+
})
|
|
478
|
+
})
|
|
479
|
+
]
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
OutreachSequenceEditor.displayName = 'OutreachSequenceEditor';
|
|
483
|
+
export default OutreachSequenceEditor;
|
|
484
|
+
|
|
485
|
+
//# sourceMappingURL=sequence-editor.js.map
|
|
@@ -0,0 +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 { mdiPlus } from '@aglyn/shared-data-mdi'\nimport { CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { 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 { useEffect, useMemo, 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 { OutreachStepCard } from './sequence-step-card'\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 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\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 */\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 orgCountries = settings.settings?.allowedCountries ?? ['US']\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 const [taskAnchor, setTaskAnchor] = useState<HTMLElement | null>(null)\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 archived = sequence?.status === 'archived'\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 = (index: number) => {\n const found: Record<string, string> = {}\n for (const issue of issues) {\n const key = stepIssueKey(issue.path)\n if (key?.index === index && !found[key.field])\n found[key.field] = issue.message\n }\n return found\n }\n const listIssue = issueAt('steps')\n const countriesIssue = issues.find((issue) =>\n issue.path.startsWith('settings.allowedCountries'),\n )?.message\n\n const update = (next: Partial<OutreachSequenceDraft>) => {\n setServerIssues([])\n setDraft((previous) => ({ ...previous, ...next }))\n }\n const setStep = (index: number, step: OutreachSequenceStep) =>\n update({\n steps: draft.steps.map((entry, position) =>\n position === index ? step : entry,\n ),\n })\n const moveStep = (index: number, direction: -1 | 1) => {\n const steps = [...draft.steps]\n const [moved] = steps.splice(index, 1)\n steps.splice(index + direction, 0, moved)\n update({ steps })\n }\n const emailCount = draft.steps.filter((step) => step.kind === 'email').length\n const full = draft.steps.length >= OUTREACH_MAX_STEPS\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\n const siteName = hosts.find((host) => host.id === draft.hostId)?.name ?? ''\n const countryOptions = [\n ...new Set([...orgCountries, ...draft.settings.allowedCountries]),\n ]\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 <CardDisplay\n header=\"Sequence\"\n help={pluginDocsHelp('sequences', { anchor: '#build-a-sequence' })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <TextField\n label=\"Name\"\n value={draft.name}\n onChange={(event) => update({ name: event.target.value })}\n disabled={archived}\n error={Boolean(issueAt('name'))}\n helperText={issueAt('name')}\n slotProps={{\n htmlInput: { maxLength: OUTREACH_SEQUENCE_NAME_MAX + 20 },\n }}\n fullWidth\n />\n <TextField\n select\n label=\"Site\"\n value={\n hosts.some((host) => host.id === draft.hostId)\n ? draft.hostId\n : ''\n }\n onChange={(event) => update({ hostId: event.target.value })}\n disabled={archived || !hosts.length}\n error={Boolean(issueAt('hostId'))}\n helperText={\n issueAt('hostId') ??\n 'The site whose contacts this sequence emails.'\n }\n fullWidth\n >\n {hosts.map((host) => (\n <MenuItem key={host.id} value={host.id}>\n {host.name}\n </MenuItem>\n ))}\n </TextField>\n <OutreachSequenceMailboxPicker\n orgId={orgId}\n uid={uid}\n mailboxes={props.mailboxes}\n mailboxesPath={props.mailboxesPath}\n value={draft.mailboxId}\n onChange={(mailboxId) => update({ mailboxId })}\n error={issueAt('mailboxId')}\n disabled={archived}\n />\n </Stack>\n </CardDisplay>\n\n {listIssue ? <Alert severity=\"error\">{listIssue}</Alert> : null}\n {draft.steps.map((step, index) => (\n <OutreachStepCard\n key={step.id || `step-${index}`}\n step={step}\n index={index}\n count={draft.steps.length}\n firstEmail={\n draft.steps.findIndex((entry) => entry.kind === 'email') ===\n index\n }\n inThread={isInThreadEmailStep(draft.steps, index)}\n threadSubject={threadSubject(index)}\n templates={templates.data}\n issues={stepIssues(index)}\n disabled={archived}\n onChange={(next) => setStep(index, next)}\n onMove={(direction) => moveStep(index, direction)}\n onRemove={() =>\n update({\n steps: draft.steps.filter(\n (_entry, position) => position !== index,\n ),\n })\n }\n />\n ))}\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ flexWrap: 'wrap', rowGap: 1 }}\n >\n <Button\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiPlus.path} fontSize=\"small\" />}\n disabled={\n archived || full || emailCount >= OUTREACH_MAX_EMAIL_STEPS\n }\n onClick={() =>\n update({\n steps: [...draft.steps, newOutreachEmailStep(draft.steps)],\n })\n }\n >\n Add email\n </Button>\n <Button\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiPlus.path} fontSize=\"small\" />}\n disabled={archived || full}\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 update({\n steps: [\n ...draft.steps,\n newOutreachTaskStep(draft.steps, kind),\n ],\n })\n }}\n >\n {OUTREACH_TASK_KIND_LABELS[kind]}\n </MenuItem>\n ))}\n </Menu>\n </Stack>\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 <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 <Autocomplete<string, true>\n multiple\n options={countryOptions}\n value={draft.settings.allowedCountries}\n getOptionLabel={outreachCountryLabel}\n onChange={(_event, next) =>\n update({\n settings: { ...draft.settings, allowedCountries: next },\n })\n }\n disabled={archived}\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(countriesIssue)}\n helperText={\n countriesIssue ??\n 'Among the countries your organization allows. Cold contacts are emailed only in the United States.'\n }\n />\n )}\n />\n <FormControlLabel\n control={\n <Switch\n checked={draft.settings.allowCustomers}\n onChange={(event) =>\n update({\n settings: {\n ...draft.settings,\n allowCustomers: event.target.checked,\n },\n })\n }\n disabled={archived}\n />\n }\n label=\"Include customers\"\n />\n <OutreachSendWindowFields\n window={draft.settings.window}\n onChange={(window) =>\n update({ settings: { ...draft.settings, window } })\n }\n daysIssue={issueAt('settings.window.days')}\n hoursIssue={issueAt('settings.window')}\n disabled={archived}\n />\n </Stack>\n </CardDisplay>\n\n {archived ? null : (\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n spacing={1}\n sx={{ justifyContent: 'flex-end' }}\n >\n {props.onCancel ? (\n <Button\n variant=\"text\"\n onClick={props.onCancel}\n disabled={saving}\n >\n Cancel\n </Button>\n ) : null}\n <Button\n variant=\"contained\"\n onClick={() => void save()}\n disabled={saving}\n >\n {saving ? 'Saving…' : sequence ? 'Save' : 'Create sequence'}\n </Button>\n </Stack>\n )}\n </Stack>\n </Grid>\n <Grid size={{ xs: 12, md: 5 }}>\n <Box sx={{ position: { md: 'sticky' }, top: { md: 16 } }}>\n <OutreachSequencePreview\n steps={draft.steps}\n orgSettings={settings.settings}\n orgSettingsStatus={settings.status}\n templates={templates.data}\n sender={\n mailbox\n ? {\n name: mailbox.displayName,\n email: mailbox.sendAs || mailbox.email,\n }\n : null\n }\n siteName={siteName}\n />\n </Box>\n </Grid>\n </Grid>\n )\n}\nOutreachSequenceEditor.displayName = 'OutreachSequenceEditor'\n\nexport default OutreachSequenceEditor\n"],"names":["pluginDocsHelp","mdiPlus","CardDisplay","MdiIcon","useSnackbar","useUser","Alert","Autocomplete","Box","Button","Chip","FormControlLabel","Grid","Menu","MenuItem","Stack","Switch","TextField","Typography","useEffect","useMemo","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","OutreachRouteError","useOutreachApi","useOutreachEmailTemplates","stepIssueKey","path","match","exec","field","index","Number","OutreachSequenceEditor","props","issueAt","settings","issues","hosts","orgId","orgMount","sequence","api","enqueueSnackbar","data","user","uid","mountedHosts","orgCountries","allowedCountries","draft","setDraft","hostId","length","id","attempted","setAttempted","serverIssues","setServerIssues","saving","setSaving","taskAnchor","setTaskAnchor","settingsCountries","join","previous","split","ownSending","mailboxes","filter","entry","connectedByUid","status","onlyOwnMailbox","mailboxId","templates","mailbox","find","archived","judged","issue","severity","includes","message","stepIssues","found","key","listIssue","countriesIssue","startsWith","update","next","setStep","step","steps","map","position","moveStep","direction","moved","splice","emailCount","kind","full","threadSubject","subject","save","some","answer","saveSequence","created","variant","onSaved","error","allowDuplicate","siteName","host","name","countryOptions","Set","container","spacing","size","xs","md","header","help","anchor","contentGutterX","contentGutterY","label","value","onChange","event","target","disabled","Boolean","helperText","slotProps","htmlInput","maxLength","fullWidth","select","mailboxesPath","count","firstEmail","findIndex","inThread","onMove","onRemove","_entry","sx","flexWrap","rowGap","startIcon","fontSize","onClick","currentTarget","aria-haspopup","anchorEl","open","onClose","color","excerpt","multiple","options","getOptionLabel","_event","renderValue","getItemProps","code","item","renderInput","params","control","checked","allowCustomers","window","daysIssue","hoursIssue","sm","justifyContent","onCancel","top","orgSettings","orgSettingsStatus","sender","displayName","email","sendAs"],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { OutreachMailbox } from '../model/outreach.types';
|
|
2
|
+
import type { OutreachMailboxesResult } from './use-outreach-mailboxes';
|
|
3
|
+
export interface OutreachSequenceMailboxPickerProps {
|
|
4
|
+
orgId: string;
|
|
5
|
+
/** The member choosing, whose own mailboxes are offered. */
|
|
6
|
+
uid: string | null;
|
|
7
|
+
/** The organization's mailboxes, from the Mailboxes section's own listener. */
|
|
8
|
+
mailboxes: OutreachMailboxesResult;
|
|
9
|
+
/** The Mailboxes section, where a mailbox is connected, resumed or reconnected. */
|
|
10
|
+
mailboxesPath: string;
|
|
11
|
+
value: string;
|
|
12
|
+
onChange(mailboxId: string): void;
|
|
13
|
+
error?: string;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** A mailbox as its line in the menu reads: who mail is from, and any status that stops it sending. */
|
|
17
|
+
export declare function outreachMailboxOptionLabel(mailbox: OutreachMailbox): string;
|
|
18
|
+
/**
|
|
19
|
+
* The mailboxes a member may choose for a sequence: their own, or every
|
|
20
|
+
* one for an organization owner or admin — the two the save route lets
|
|
21
|
+
* send from a mailbox — never a disconnected one. The mailbox a sequence
|
|
22
|
+
* already names stays in the list whoever connected it, so the field never
|
|
23
|
+
* reads as empty.
|
|
24
|
+
*/
|
|
25
|
+
export declare function outreachOfferedMailboxes(mailboxes: readonly OutreachMailbox[], input: {
|
|
26
|
+
uid: string | null;
|
|
27
|
+
canManageAll: boolean;
|
|
28
|
+
value: string;
|
|
29
|
+
}): OutreachMailbox[];
|
|
30
|
+
/**
|
|
31
|
+
* The mailbox a sequence sends from (AGL-2980), chosen from the Mailboxes
|
|
32
|
+
* section's own listener and route (AGL-2978).
|
|
33
|
+
*
|
|
34
|
+
* Whether the member may choose a colleague's mailbox is the mailbox
|
|
35
|
+
* routes' answer (`availability().canManageAll`); until it arrives, or when
|
|
36
|
+
* it cannot be had, the member is offered their own, which is always
|
|
37
|
+
* allowed. A chosen mailbox that is paused or waiting to be reconnected can
|
|
38
|
+
* hold a draft, and the field says what activating will need.
|
|
39
|
+
*/
|
|
40
|
+
export declare function OutreachSequenceMailboxPicker(props: OutreachSequenceMailboxPickerProps): import("react").JSX.Element;
|
|
41
|
+
export declare namespace OutreachSequenceMailboxPicker {
|
|
42
|
+
var displayName: string;
|
|
43
|
+
}
|
|
44
|
+
export default OutreachSequenceMailboxPicker;
|