@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,517 @@
|
|
|
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 { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
|
+
import { pluginDocsHelp } from "@aglyn/aglyn";
|
|
20
|
+
import { CardDisplay, useConfirmationContext } from "@aglyn/shared-ui-jsx";
|
|
21
|
+
import { useSnackbar } from "@aglyn/shared-ui-snackstack";
|
|
22
|
+
import { Alert, Autocomplete, Box, Button, Chip, FormHelperText, MenuItem, Stack, TextField, ToggleButton, ToggleButtonGroup, Typography } from "@mui/material";
|
|
23
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
24
|
+
import { formatMinuteOfDay, isValidTimezone, OUTREACH_DEFAULT_WINDOW, OUTREACH_MAILBOX_STATUS_LABELS, OUTREACH_MAX_DAILY_CAP, OUTREACH_RAMP_STEPS, OUTREACH_WEEKDAY_LABELS, outreachEffectiveDailyCap, summarizeMailboxHealth, validateDailyCap, validateDisplayName, validateSendWindow } from "../mailboxes/mailbox-settings.js";
|
|
25
|
+
/**
|
|
26
|
+
* What the card says about a mailbox that paused ITSELF (AGL-2981): the
|
|
27
|
+
* engine's own sentence, when it paused, and — after a complaint — the day
|
|
28
|
+
* resuming stops being premature. Nothing sends from it until a member
|
|
29
|
+
* resumes it.
|
|
30
|
+
*/ export function autoPauseSentence(mailbox) {
|
|
31
|
+
const pause = mailbox.autoPause;
|
|
32
|
+
if (!pause) return '';
|
|
33
|
+
const day = (atMs)=>{
|
|
34
|
+
try {
|
|
35
|
+
return new Intl.DateTimeFormat('en-US', {
|
|
36
|
+
dateStyle: 'medium',
|
|
37
|
+
timeZone: mailbox.timezone
|
|
38
|
+
}).format(atMs);
|
|
39
|
+
} catch (unused) {
|
|
40
|
+
return new Intl.DateTimeFormat('en-US', {
|
|
41
|
+
dateStyle: 'medium',
|
|
42
|
+
timeZone: 'UTC'
|
|
43
|
+
}).format(atMs);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const until = typeof pause.untilMs === 'number' ? ` Wait until ${day(pause.untilMs)} before resuming it.` : '';
|
|
47
|
+
return `Sequences paused this mailbox on ${day(pause.atMs)}. ${pause.message}${until} Nothing sends from it until it is resumed.`;
|
|
48
|
+
}
|
|
49
|
+
/** Accessible names of the card's actions, spelled once for the specs. */ export const MAILBOX_ACTION_LABELS = {
|
|
50
|
+
save: 'Save settings',
|
|
51
|
+
pause: 'Pause',
|
|
52
|
+
resume: 'Resume',
|
|
53
|
+
test: 'Send a test to myself',
|
|
54
|
+
disconnect: 'Disconnect',
|
|
55
|
+
reconnect: 'Reconnect'
|
|
56
|
+
};
|
|
57
|
+
const WEEKDAY_NAMES = [
|
|
58
|
+
'Sunday',
|
|
59
|
+
'Monday',
|
|
60
|
+
'Tuesday',
|
|
61
|
+
'Wednesday',
|
|
62
|
+
'Thursday',
|
|
63
|
+
'Friday',
|
|
64
|
+
'Saturday'
|
|
65
|
+
];
|
|
66
|
+
const STATUS_COLOR = {
|
|
67
|
+
connected: 'success',
|
|
68
|
+
paused: 'default',
|
|
69
|
+
reconnect_required: 'warning',
|
|
70
|
+
disconnected: 'error'
|
|
71
|
+
};
|
|
72
|
+
/** Every half hour of the day, and midnight at its end. */ const MINUTE_OPTIONS = Array.from({
|
|
73
|
+
length: 49
|
|
74
|
+
}, (_, index)=>index * 30);
|
|
75
|
+
/** The zones this runtime knows, the mailbox's own included whatever it is. */ function timezoneOptions(current) {
|
|
76
|
+
var _ref;
|
|
77
|
+
const supported = (_ref = Intl.supportedValuesOf == null ? void 0 : Intl.supportedValuesOf.call(Intl, 'timeZone')) != null ? _ref : [];
|
|
78
|
+
const zones = supported.length ? supported : [
|
|
79
|
+
'UTC'
|
|
80
|
+
];
|
|
81
|
+
return zones.includes(current) ? zones : [
|
|
82
|
+
current,
|
|
83
|
+
...zones
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
/** The ramp, as the cap's helper text reads it. */ const RAMP_SENTENCE = `Warm-up: ${OUTREACH_RAMP_STEPS.map((step, index)=>`week ${step.week}${index === OUTREACH_RAMP_STEPS.length - 1 ? '+' : ''}: ${step.limit}`).join(' · ')} a day, never above the cap.`;
|
|
87
|
+
const draftOf = (mailbox)=>{
|
|
88
|
+
var _mailbox_sendAs, _mailbox_displayName, _mailbox_dailyCap, _mailbox_window, _mailbox_timezone;
|
|
89
|
+
return {
|
|
90
|
+
sendAs: (_mailbox_sendAs = mailbox.sendAs) != null ? _mailbox_sendAs : mailbox.email,
|
|
91
|
+
displayName: (_mailbox_displayName = mailbox.displayName) != null ? _mailbox_displayName : '',
|
|
92
|
+
dailyCap: String((_mailbox_dailyCap = mailbox.dailyCap) != null ? _mailbox_dailyCap : ''),
|
|
93
|
+
window: (_mailbox_window = mailbox.window) != null ? _mailbox_window : OUTREACH_DEFAULT_WINDOW,
|
|
94
|
+
timezone: (_mailbox_timezone = mailbox.timezone) != null ? _mailbox_timezone : 'UTC'
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* One connected mailbox (AGL-2978): its account and status, its last seven
|
|
99
|
+
* days, its settings, and pause, test and disconnect.
|
|
100
|
+
*
|
|
101
|
+
* Every control is offered only where the route will allow it: the settings
|
|
102
|
+
* form and pause and disconnect to the member who connected the mailbox or an
|
|
103
|
+
* org owner or admin, and the test and the reconnect to its member alone,
|
|
104
|
+
* because both act in that member's own Google account.
|
|
105
|
+
*/ export function MailboxCard(props) {
|
|
106
|
+
var _OUTREACH_MAILBOX_STATUS_LABELS_mailbox_status, _STATUS_COLOR_mailbox_status;
|
|
107
|
+
var _mailbox_sendAsOptions;
|
|
108
|
+
const { mailbox, isMine, canManage, api, onReconnect, reconnecting = false, nowMs = Date.now() } = props;
|
|
109
|
+
const { enqueueSnackbar } = useSnackbar();
|
|
110
|
+
const { confirm } = useConfirmationContext();
|
|
111
|
+
const [draft, setDraft] = useState(()=>draftOf(mailbox));
|
|
112
|
+
const [saving, setSaving] = useState(false);
|
|
113
|
+
const [saveError, setSaveError] = useState(null);
|
|
114
|
+
const [busy, setBusy] = useState(null);
|
|
115
|
+
// A save here, a change made from another tab, or a reconnect rewrites the
|
|
116
|
+
// stored settings; the form follows them, unless the member has unsaved
|
|
117
|
+
// edits of their own, which are never thrown away.
|
|
118
|
+
const stored = useMemo(()=>draftOf(mailbox), [
|
|
119
|
+
mailbox
|
|
120
|
+
]);
|
|
121
|
+
const storedKey = JSON.stringify(stored);
|
|
122
|
+
const seededFrom = useRef(storedKey);
|
|
123
|
+
const dirty = JSON.stringify(draft) !== storedKey;
|
|
124
|
+
useEffect(()=>{
|
|
125
|
+
if (seededFrom.current === storedKey) return;
|
|
126
|
+
const previous = seededFrom.current;
|
|
127
|
+
seededFrom.current = storedKey;
|
|
128
|
+
setDraft((current)=>JSON.stringify(current) === previous ? stored : current);
|
|
129
|
+
}, [
|
|
130
|
+
storedKey,
|
|
131
|
+
stored
|
|
132
|
+
]);
|
|
133
|
+
const health = summarizeMailboxHealth(mailbox.health, mailbox.timezone, nowMs);
|
|
134
|
+
const needsReconnect = mailbox.status === 'reconnect_required' || mailbox.status === 'disconnected';
|
|
135
|
+
const capCheck = validateDailyCap(draft.dailyCap === '' ? Number.NaN : Number(draft.dailyCap));
|
|
136
|
+
const windowCheck = validateSendWindow(draft.window);
|
|
137
|
+
const nameCheck = validateDisplayName(draft.displayName);
|
|
138
|
+
const timezoneValid = isValidTimezone(draft.timezone);
|
|
139
|
+
const invalid = typeof capCheck !== 'number' || !('days' in windowCheck) || typeof nameCheck !== 'string' || !timezoneValid;
|
|
140
|
+
const todayLimit = outreachEffectiveDailyCap({
|
|
141
|
+
dailyCap: typeof capCheck === 'number' ? capCheck : mailbox.dailyCap,
|
|
142
|
+
rampStartedAtMs: mailbox.rampStartedAtMs,
|
|
143
|
+
timezone: timezoneValid ? draft.timezone : mailbox.timezone
|
|
144
|
+
}, nowMs);
|
|
145
|
+
const save = async ()=>{
|
|
146
|
+
setSaving(true);
|
|
147
|
+
setSaveError(null);
|
|
148
|
+
try {
|
|
149
|
+
await api.saveSettings(_extends({
|
|
150
|
+
mailboxId: mailbox.id
|
|
151
|
+
}, draft.sendAs !== stored.sendAs ? {
|
|
152
|
+
sendAs: draft.sendAs
|
|
153
|
+
} : {}, draft.displayName !== stored.displayName ? {
|
|
154
|
+
displayName: draft.displayName
|
|
155
|
+
} : {}, draft.dailyCap !== stored.dailyCap ? {
|
|
156
|
+
dailyCap: Number(draft.dailyCap)
|
|
157
|
+
} : {}, JSON.stringify(draft.window) !== JSON.stringify(stored.window) ? {
|
|
158
|
+
window: draft.window
|
|
159
|
+
} : {}, draft.timezone !== stored.timezone ? {
|
|
160
|
+
timezone: draft.timezone
|
|
161
|
+
} : {}));
|
|
162
|
+
enqueueSnackbar('Mailbox settings saved', {
|
|
163
|
+
variant: 'success'
|
|
164
|
+
});
|
|
165
|
+
} catch (error) {
|
|
166
|
+
setSaveError(error.message);
|
|
167
|
+
} finally{
|
|
168
|
+
setSaving(false);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
const togglePaused = async ()=>{
|
|
172
|
+
const paused = mailbox.status !== 'paused';
|
|
173
|
+
setBusy('status');
|
|
174
|
+
try {
|
|
175
|
+
await api.setPaused(mailbox.id, paused);
|
|
176
|
+
enqueueSnackbar(paused ? 'Mailbox paused' : 'Mailbox resumed', {
|
|
177
|
+
variant: 'success'
|
|
178
|
+
});
|
|
179
|
+
} catch (error) {
|
|
180
|
+
enqueueSnackbar(error.message, {
|
|
181
|
+
variant: 'error',
|
|
182
|
+
allowDuplicate: true
|
|
183
|
+
});
|
|
184
|
+
} finally{
|
|
185
|
+
setBusy(null);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const sendTest = async ()=>{
|
|
189
|
+
setBusy('test');
|
|
190
|
+
try {
|
|
191
|
+
const sent = await api.sendTest(mailbox.id);
|
|
192
|
+
enqueueSnackbar(`Test sent to ${sent.sentTo}. Check your inbox.`, {
|
|
193
|
+
variant: 'success'
|
|
194
|
+
});
|
|
195
|
+
} catch (error) {
|
|
196
|
+
enqueueSnackbar(error.message, {
|
|
197
|
+
variant: 'error',
|
|
198
|
+
allowDuplicate: true
|
|
199
|
+
});
|
|
200
|
+
} finally{
|
|
201
|
+
setBusy(null);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const disconnect = async ()=>{
|
|
205
|
+
const confirmed = await confirm({
|
|
206
|
+
title: 'Disconnect this mailbox?',
|
|
207
|
+
description: 'Disconnecting deletes the access stored for this mailbox and asks Google to revoke it. ' + 'Nothing is sent from it again unless it is connected again.',
|
|
208
|
+
confirmationText: MAILBOX_ACTION_LABELS.disconnect,
|
|
209
|
+
confirmationButtonProps: {
|
|
210
|
+
color: 'error'
|
|
211
|
+
}
|
|
212
|
+
}).then(()=>true).catch(()=>false);
|
|
213
|
+
if (!confirmed) return;
|
|
214
|
+
setBusy('disconnect');
|
|
215
|
+
try {
|
|
216
|
+
const { revocation } = await api.disconnect(mailbox.id);
|
|
217
|
+
if (revocation === 'failed') {
|
|
218
|
+
enqueueSnackbar('Mailbox disconnected, but Google could not confirm the access was revoked. ' + 'Remove it from the Google Account’s third-party connections to be sure.', {
|
|
219
|
+
variant: 'warning',
|
|
220
|
+
persist: true
|
|
221
|
+
});
|
|
222
|
+
} else if (revocation === 'kept-for-other-mailbox') {
|
|
223
|
+
enqueueSnackbar('Mailbox disconnected. Google access stays in place for another connected mailbox on the same account.', {
|
|
224
|
+
variant: 'success'
|
|
225
|
+
});
|
|
226
|
+
} else {
|
|
227
|
+
enqueueSnackbar('Mailbox disconnected', {
|
|
228
|
+
variant: 'success'
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
} catch (error) {
|
|
232
|
+
enqueueSnackbar(error.message, {
|
|
233
|
+
variant: 'error',
|
|
234
|
+
allowDuplicate: true
|
|
235
|
+
});
|
|
236
|
+
setBusy(null);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const sendAsLabel = (email)=>{
|
|
240
|
+
var _mailbox_sendAsOptions;
|
|
241
|
+
const option = (_mailbox_sendAsOptions = mailbox.sendAsOptions) == null ? void 0 : _mailbox_sendAsOptions.find((entry)=>entry.email === email);
|
|
242
|
+
return (option == null ? void 0 : option.displayName) ? `${option.displayName} <${option.email}>` : email;
|
|
243
|
+
};
|
|
244
|
+
return /*#__PURE__*/ _jsx(CardDisplay, {
|
|
245
|
+
header: mailbox.email,
|
|
246
|
+
subheader: isMine ? 'Your mailbox' : 'A teammate’s mailbox',
|
|
247
|
+
help: pluginDocsHelp('sequences', {
|
|
248
|
+
anchor: '#connect-a-mailbox'
|
|
249
|
+
}),
|
|
250
|
+
contentGutterX: true,
|
|
251
|
+
contentGutterY: true,
|
|
252
|
+
HeaderProps: {
|
|
253
|
+
action: /*#__PURE__*/ _jsx(Chip, {
|
|
254
|
+
size: "small",
|
|
255
|
+
label: (_OUTREACH_MAILBOX_STATUS_LABELS_mailbox_status = OUTREACH_MAILBOX_STATUS_LABELS[mailbox.status]) != null ? _OUTREACH_MAILBOX_STATUS_LABELS_mailbox_status : mailbox.status,
|
|
256
|
+
color: (_STATUS_COLOR_mailbox_status = STATUS_COLOR[mailbox.status]) != null ? _STATUS_COLOR_mailbox_status : 'default'
|
|
257
|
+
})
|
|
258
|
+
},
|
|
259
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
260
|
+
spacing: 2,
|
|
261
|
+
children: [
|
|
262
|
+
needsReconnect ? /*#__PURE__*/ _jsx(Alert, {
|
|
263
|
+
severity: "warning",
|
|
264
|
+
action: isMine ? /*#__PURE__*/ _jsx(Button, {
|
|
265
|
+
color: "inherit",
|
|
266
|
+
size: "small",
|
|
267
|
+
disabled: reconnecting,
|
|
268
|
+
onClick: onReconnect,
|
|
269
|
+
children: MAILBOX_ACTION_LABELS.reconnect
|
|
270
|
+
}) : undefined,
|
|
271
|
+
children: `${mailbox.status === 'disconnected' ? 'This mailbox was disconnected.' : 'Google stopped accepting this mailbox’s connection.'} ${isMine ? 'Nothing sends from it until you connect it again.' : 'Only the member who connected it can reconnect it.'}`
|
|
272
|
+
}) : null,
|
|
273
|
+
mailbox.status === 'paused' && mailbox.autoPause ? /*#__PURE__*/ _jsx(Alert, {
|
|
274
|
+
severity: "error",
|
|
275
|
+
role: "alert",
|
|
276
|
+
children: autoPauseSentence(mailbox)
|
|
277
|
+
}) : null,
|
|
278
|
+
/*#__PURE__*/ _jsxs(Box, {
|
|
279
|
+
children: [
|
|
280
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
281
|
+
variant: "subtitle2",
|
|
282
|
+
children: "Last 7 days"
|
|
283
|
+
}),
|
|
284
|
+
health.hasSent ? null : /*#__PURE__*/ _jsx(Typography, {
|
|
285
|
+
variant: "body2",
|
|
286
|
+
color: "text.secondary",
|
|
287
|
+
children: "No sends yet"
|
|
288
|
+
}),
|
|
289
|
+
/*#__PURE__*/ _jsx(Stack, {
|
|
290
|
+
direction: "row",
|
|
291
|
+
spacing: 3,
|
|
292
|
+
sx: {
|
|
293
|
+
mt: 0.5
|
|
294
|
+
},
|
|
295
|
+
children: [
|
|
296
|
+
[
|
|
297
|
+
'Sent',
|
|
298
|
+
health.sent
|
|
299
|
+
],
|
|
300
|
+
[
|
|
301
|
+
'Bounces',
|
|
302
|
+
health.bounces
|
|
303
|
+
],
|
|
304
|
+
[
|
|
305
|
+
'Replies',
|
|
306
|
+
health.replies
|
|
307
|
+
]
|
|
308
|
+
].map(([label, value])=>/*#__PURE__*/ _jsxs(Box, {
|
|
309
|
+
"aria-label": `${label} in the last 7 days`,
|
|
310
|
+
children: [
|
|
311
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
312
|
+
variant: "h6",
|
|
313
|
+
component: "p",
|
|
314
|
+
children: value
|
|
315
|
+
}),
|
|
316
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
317
|
+
variant: "caption",
|
|
318
|
+
color: "text.secondary",
|
|
319
|
+
children: label
|
|
320
|
+
})
|
|
321
|
+
]
|
|
322
|
+
}, label))
|
|
323
|
+
})
|
|
324
|
+
]
|
|
325
|
+
}),
|
|
326
|
+
canManage ? /*#__PURE__*/ _jsxs(Stack, {
|
|
327
|
+
spacing: 2,
|
|
328
|
+
component: "form",
|
|
329
|
+
onSubmit: (event)=>event.preventDefault(),
|
|
330
|
+
children: [
|
|
331
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
332
|
+
select: true,
|
|
333
|
+
size: "small",
|
|
334
|
+
label: "Send as",
|
|
335
|
+
value: draft.sendAs,
|
|
336
|
+
onChange: (event)=>setDraft(_extends({}, draft, {
|
|
337
|
+
sendAs: event.target.value
|
|
338
|
+
})),
|
|
339
|
+
helperText: "Addresses Gmail has verified for this account.",
|
|
340
|
+
children: (((_mailbox_sendAsOptions = mailbox.sendAsOptions) == null ? void 0 : _mailbox_sendAsOptions.length) ? mailbox.sendAsOptions : [
|
|
341
|
+
{
|
|
342
|
+
email: mailbox.sendAs
|
|
343
|
+
}
|
|
344
|
+
]).map((option)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
345
|
+
value: option.email,
|
|
346
|
+
children: sendAsLabel(option.email)
|
|
347
|
+
}, option.email))
|
|
348
|
+
}),
|
|
349
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
350
|
+
size: "small",
|
|
351
|
+
label: "Display name",
|
|
352
|
+
value: draft.displayName,
|
|
353
|
+
onChange: (event)=>setDraft(_extends({}, draft, {
|
|
354
|
+
displayName: event.target.value
|
|
355
|
+
})),
|
|
356
|
+
error: typeof nameCheck !== 'string',
|
|
357
|
+
helperText: typeof nameCheck !== 'string' ? nameCheck.message : 'The name recipients see beside the address.'
|
|
358
|
+
}),
|
|
359
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
360
|
+
size: "small",
|
|
361
|
+
type: "number",
|
|
362
|
+
label: "Daily cap",
|
|
363
|
+
value: draft.dailyCap,
|
|
364
|
+
onChange: (event)=>setDraft(_extends({}, draft, {
|
|
365
|
+
dailyCap: event.target.value
|
|
366
|
+
})),
|
|
367
|
+
error: typeof capCheck !== 'number',
|
|
368
|
+
slotProps: {
|
|
369
|
+
htmlInput: {
|
|
370
|
+
min: 1,
|
|
371
|
+
max: OUTREACH_MAX_DAILY_CAP,
|
|
372
|
+
step: 1
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
helperText: typeof capCheck !== 'number' ? capCheck.message : `${RAMP_SENTENCE} Today’s limit: ${todayLimit}.`
|
|
376
|
+
}),
|
|
377
|
+
/*#__PURE__*/ _jsxs(Box, {
|
|
378
|
+
children: [
|
|
379
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
380
|
+
variant: "subtitle2",
|
|
381
|
+
gutterBottom: true,
|
|
382
|
+
children: "Sending window"
|
|
383
|
+
}),
|
|
384
|
+
/*#__PURE__*/ _jsx(ToggleButtonGroup, {
|
|
385
|
+
size: "small",
|
|
386
|
+
"aria-label": "Sending days",
|
|
387
|
+
value: draft.window.days,
|
|
388
|
+
onChange: (_event, days)=>setDraft(_extends({}, draft, {
|
|
389
|
+
window: _extends({}, draft.window, {
|
|
390
|
+
days: [
|
|
391
|
+
...days
|
|
392
|
+
].sort((a, b)=>a - b)
|
|
393
|
+
})
|
|
394
|
+
})),
|
|
395
|
+
children: OUTREACH_WEEKDAY_LABELS.map((label, day)=>/*#__PURE__*/ _jsx(ToggleButton, {
|
|
396
|
+
value: day,
|
|
397
|
+
"aria-label": WEEKDAY_NAMES[day],
|
|
398
|
+
children: label
|
|
399
|
+
}, label))
|
|
400
|
+
}),
|
|
401
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
402
|
+
direction: {
|
|
403
|
+
xs: 'column',
|
|
404
|
+
sm: 'row'
|
|
405
|
+
},
|
|
406
|
+
spacing: 2,
|
|
407
|
+
sx: {
|
|
408
|
+
mt: 2
|
|
409
|
+
},
|
|
410
|
+
children: [
|
|
411
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
412
|
+
select: true,
|
|
413
|
+
size: "small",
|
|
414
|
+
label: "From",
|
|
415
|
+
value: draft.window.startMinute,
|
|
416
|
+
onChange: (event)=>setDraft(_extends({}, draft, {
|
|
417
|
+
window: _extends({}, draft.window, {
|
|
418
|
+
startMinute: Number(event.target.value)
|
|
419
|
+
})
|
|
420
|
+
})),
|
|
421
|
+
children: MINUTE_OPTIONS.slice(0, -1).map((minute)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
422
|
+
value: minute,
|
|
423
|
+
children: formatMinuteOfDay(minute)
|
|
424
|
+
}, minute))
|
|
425
|
+
}),
|
|
426
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
427
|
+
select: true,
|
|
428
|
+
size: "small",
|
|
429
|
+
label: "Until",
|
|
430
|
+
value: draft.window.endMinute,
|
|
431
|
+
onChange: (event)=>setDraft(_extends({}, draft, {
|
|
432
|
+
window: _extends({}, draft.window, {
|
|
433
|
+
endMinute: Number(event.target.value)
|
|
434
|
+
})
|
|
435
|
+
})),
|
|
436
|
+
children: MINUTE_OPTIONS.slice(1).map((minute)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
437
|
+
value: minute,
|
|
438
|
+
children: formatMinuteOfDay(minute)
|
|
439
|
+
}, minute))
|
|
440
|
+
}),
|
|
441
|
+
/*#__PURE__*/ _jsx(Autocomplete, {
|
|
442
|
+
size: "small",
|
|
443
|
+
disableClearable: true,
|
|
444
|
+
options: timezoneOptions(mailbox.timezone),
|
|
445
|
+
value: draft.timezone,
|
|
446
|
+
onChange: (_event, timezone)=>setDraft(_extends({}, draft, {
|
|
447
|
+
timezone: timezone != null ? timezone : draft.timezone
|
|
448
|
+
})),
|
|
449
|
+
sx: {
|
|
450
|
+
minWidth: 240
|
|
451
|
+
},
|
|
452
|
+
renderInput: (params)=>/*#__PURE__*/ _jsx(TextField, _extends({}, params, {
|
|
453
|
+
label: "Timezone"
|
|
454
|
+
}))
|
|
455
|
+
})
|
|
456
|
+
]
|
|
457
|
+
}),
|
|
458
|
+
'days' in windowCheck ? null : /*#__PURE__*/ _jsx(FormHelperText, {
|
|
459
|
+
error: true,
|
|
460
|
+
children: windowCheck.message
|
|
461
|
+
})
|
|
462
|
+
]
|
|
463
|
+
}),
|
|
464
|
+
saveError ? /*#__PURE__*/ _jsx(FormHelperText, {
|
|
465
|
+
error: true,
|
|
466
|
+
children: saveError
|
|
467
|
+
}) : null,
|
|
468
|
+
/*#__PURE__*/ _jsx(Box, {
|
|
469
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
470
|
+
variant: "contained",
|
|
471
|
+
disabled: !dirty || invalid || saving,
|
|
472
|
+
onClick: ()=>void save(),
|
|
473
|
+
children: MAILBOX_ACTION_LABELS.save
|
|
474
|
+
})
|
|
475
|
+
})
|
|
476
|
+
]
|
|
477
|
+
}) : /*#__PURE__*/ _jsx(Typography, {
|
|
478
|
+
variant: "body2",
|
|
479
|
+
color: "text.secondary",
|
|
480
|
+
children: `Sends as ${sendAsLabel(stored.sendAs)}, at most ${stored.dailyCap} a day, ` + `${stored.window.days.map((day)=>OUTREACH_WEEKDAY_LABELS[day]).join(', ')} ` + `${formatMinuteOfDay(stored.window.startMinute)}–${formatMinuteOfDay(stored.window.endMinute)} ` + `(${stored.timezone}).`
|
|
481
|
+
}),
|
|
482
|
+
canManage || isMine ? /*#__PURE__*/ _jsxs(Stack, {
|
|
483
|
+
direction: "row",
|
|
484
|
+
spacing: 1,
|
|
485
|
+
useFlexGap: true,
|
|
486
|
+
sx: {
|
|
487
|
+
flexWrap: 'wrap'
|
|
488
|
+
},
|
|
489
|
+
children: [
|
|
490
|
+
canManage && !needsReconnect ? /*#__PURE__*/ _jsx(Button, {
|
|
491
|
+
variant: "outlined",
|
|
492
|
+
disabled: busy !== null,
|
|
493
|
+
onClick: ()=>void togglePaused(),
|
|
494
|
+
children: mailbox.status === 'paused' ? MAILBOX_ACTION_LABELS.resume : MAILBOX_ACTION_LABELS.pause
|
|
495
|
+
}) : null,
|
|
496
|
+
isMine && !needsReconnect ? /*#__PURE__*/ _jsx(Button, {
|
|
497
|
+
variant: "outlined",
|
|
498
|
+
disabled: busy !== null,
|
|
499
|
+
onClick: ()=>void sendTest(),
|
|
500
|
+
children: MAILBOX_ACTION_LABELS.test
|
|
501
|
+
}) : null,
|
|
502
|
+
canManage ? /*#__PURE__*/ _jsx(Button, {
|
|
503
|
+
color: "error",
|
|
504
|
+
disabled: busy !== null,
|
|
505
|
+
onClick: ()=>void disconnect(),
|
|
506
|
+
children: MAILBOX_ACTION_LABELS.disconnect
|
|
507
|
+
}) : null
|
|
508
|
+
]
|
|
509
|
+
}) : null
|
|
510
|
+
]
|
|
511
|
+
})
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
MailboxCard.displayName = 'MailboxCard';
|
|
515
|
+
export default MailboxCard;
|
|
516
|
+
|
|
517
|
+
//# sourceMappingURL=mailbox-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/mailbox-card.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { CardDisplay, useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Alert,\n Autocomplete,\n Box,\n Button,\n Chip,\n FormHelperText,\n MenuItem,\n Stack,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport {\n formatMinuteOfDay,\n isValidTimezone,\n OUTREACH_DEFAULT_WINDOW,\n OUTREACH_MAILBOX_STATUS_LABELS,\n OUTREACH_MAX_DAILY_CAP,\n OUTREACH_RAMP_STEPS,\n OUTREACH_WEEKDAY_LABELS,\n outreachEffectiveDailyCap,\n summarizeMailboxHealth,\n validateDailyCap,\n validateDisplayName,\n validateSendWindow,\n} from '../mailboxes/mailbox-settings'\nimport type {\n OutreachMailbox,\n OutreachMailboxStatus,\n OutreachSendWindow,\n} from '../model/outreach.types'\nimport type { OutreachMailboxApi } from './use-outreach-mailbox-api'\n\nexport interface MailboxCardProps {\n mailbox: OutreachMailbox\n /** The viewer is the member who connected it. */\n isMine: boolean\n /** The viewer may change, pause and disconnect it: its member, or an org owner or admin. */\n canManage: boolean\n api: OutreachMailboxApi\n /** Starts a new Google connect, for a mailbox that needs reconnecting. */\n onReconnect(): void\n /** True while that connect is on its way to Google. */\n reconnecting?: boolean\n /** The clock the health window and today's limit are read on. */\n nowMs?: number\n}\n\n/**\n * What the card says about a mailbox that paused ITSELF (AGL-2981): the\n * engine's own sentence, when it paused, and — after a complaint — the day\n * resuming stops being premature. Nothing sends from it until a member\n * resumes it.\n */\nexport function autoPauseSentence(mailbox: Pick<OutreachMailbox, 'autoPause' | 'timezone'>): string {\n const pause = mailbox.autoPause\n if (!pause) return ''\n const day = (atMs: number) => {\n try {\n return new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeZone: mailbox.timezone }).format(atMs)\n } catch {\n return new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeZone: 'UTC' }).format(atMs)\n }\n }\n const until = typeof pause.untilMs === 'number' ? ` Wait until ${day(pause.untilMs)} before resuming it.` : ''\n return `Sequences paused this mailbox on ${day(pause.atMs)}. ${pause.message}${until} Nothing sends from it until it is resumed.`\n}\n\n/** Accessible names of the card's actions, spelled once for the specs. */\nexport const MAILBOX_ACTION_LABELS = {\n save: 'Save settings',\n pause: 'Pause',\n resume: 'Resume',\n test: 'Send a test to myself',\n disconnect: 'Disconnect',\n reconnect: 'Reconnect',\n} as const\n\nconst WEEKDAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']\n\nconst STATUS_COLOR: Record<OutreachMailboxStatus, 'success' | 'default' | 'warning' | 'error'> = {\n connected: 'success',\n paused: 'default',\n reconnect_required: 'warning',\n disconnected: 'error',\n}\n\n/** Every half hour of the day, and midnight at its end. */\nconst MINUTE_OPTIONS = Array.from({ length: 49 }, (_, index) => index * 30)\n\n/** The zones this runtime knows, the mailbox's own included whatever it is. */\nfunction timezoneOptions(current: string): string[] {\n const supported = (Intl as { supportedValuesOf?: (key: string) => string[] }).supportedValuesOf?.('timeZone') ?? []\n const zones = supported.length ? supported : ['UTC']\n return zones.includes(current) ? zones : [current, ...zones]\n}\n\n/** The ramp, as the cap's helper text reads it. */\nconst RAMP_SENTENCE = `Warm-up: ${OUTREACH_RAMP_STEPS.map((step, index) =>\n `week ${step.week}${index === OUTREACH_RAMP_STEPS.length - 1 ? '+' : ''}: ${step.limit}`,\n).join(' · ')} a day, never above the cap.`\n\ninterface Draft {\n sendAs: string\n displayName: string\n dailyCap: string\n window: OutreachSendWindow\n timezone: string\n}\n\nconst draftOf = (mailbox: OutreachMailbox): Draft => ({\n sendAs: mailbox.sendAs ?? mailbox.email,\n displayName: mailbox.displayName ?? '',\n dailyCap: String(mailbox.dailyCap ?? ''),\n window: mailbox.window ?? OUTREACH_DEFAULT_WINDOW,\n timezone: mailbox.timezone ?? 'UTC',\n})\n\n/**\n * One connected mailbox (AGL-2978): its account and status, its last seven\n * days, its settings, and pause, test and disconnect.\n *\n * Every control is offered only where the route will allow it: the settings\n * form and pause and disconnect to the member who connected the mailbox or an\n * org owner or admin, and the test and the reconnect to its member alone,\n * because both act in that member's own Google account.\n */\nexport function MailboxCard(props: MailboxCardProps) {\n const { mailbox, isMine, canManage, api, onReconnect, reconnecting = false, nowMs = Date.now() } = props\n const { enqueueSnackbar } = useSnackbar()\n const { confirm } = useConfirmationContext()\n const [draft, setDraft] = useState<Draft>(() => draftOf(mailbox))\n const [saving, setSaving] = useState(false)\n const [saveError, setSaveError] = useState<string | null>(null)\n const [busy, setBusy] = useState<'status' | 'test' | 'disconnect' | null>(null)\n\n // A save here, a change made from another tab, or a reconnect rewrites the\n // stored settings; the form follows them, unless the member has unsaved\n // edits of their own, which are never thrown away.\n const stored = useMemo(() => draftOf(mailbox), [mailbox])\n const storedKey = JSON.stringify(stored)\n const seededFrom = useRef(storedKey)\n const dirty = JSON.stringify(draft) !== storedKey\n useEffect(() => {\n if (seededFrom.current === storedKey) return\n const previous = seededFrom.current\n seededFrom.current = storedKey\n setDraft((current) => (JSON.stringify(current) === previous ? stored : current))\n }, [storedKey, stored])\n\n const health = summarizeMailboxHealth(mailbox.health, mailbox.timezone, nowMs)\n const needsReconnect = mailbox.status === 'reconnect_required' || mailbox.status === 'disconnected'\n const capCheck = validateDailyCap(draft.dailyCap === '' ? Number.NaN : Number(draft.dailyCap))\n const windowCheck = validateSendWindow(draft.window)\n const nameCheck = validateDisplayName(draft.displayName)\n const timezoneValid = isValidTimezone(draft.timezone)\n const invalid =\n typeof capCheck !== 'number' || !('days' in windowCheck) || typeof nameCheck !== 'string' || !timezoneValid\n const todayLimit = outreachEffectiveDailyCap(\n {\n dailyCap: typeof capCheck === 'number' ? capCheck : mailbox.dailyCap,\n rampStartedAtMs: mailbox.rampStartedAtMs,\n timezone: timezoneValid ? draft.timezone : mailbox.timezone,\n },\n nowMs,\n )\n\n const save = async () => {\n setSaving(true)\n setSaveError(null)\n try {\n await api.saveSettings({\n mailboxId: mailbox.id,\n ...(draft.sendAs !== stored.sendAs ? { sendAs: draft.sendAs } : {}),\n ...(draft.displayName !== stored.displayName ? { displayName: draft.displayName } : {}),\n ...(draft.dailyCap !== stored.dailyCap ? { dailyCap: Number(draft.dailyCap) } : {}),\n ...(JSON.stringify(draft.window) !== JSON.stringify(stored.window) ? { window: draft.window } : {}),\n ...(draft.timezone !== stored.timezone ? { timezone: draft.timezone } : {}),\n })\n enqueueSnackbar('Mailbox settings saved', { variant: 'success' })\n } catch (error) {\n setSaveError((error as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n const togglePaused = async () => {\n const paused = mailbox.status !== 'paused'\n setBusy('status')\n try {\n await api.setPaused(mailbox.id, paused)\n enqueueSnackbar(paused ? 'Mailbox paused' : 'Mailbox resumed', { variant: 'success' })\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n } finally {\n setBusy(null)\n }\n }\n\n const sendTest = async () => {\n setBusy('test')\n try {\n const sent = await api.sendTest(mailbox.id)\n enqueueSnackbar(`Test sent to ${sent.sentTo}. Check your inbox.`, { variant: 'success' })\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n } finally {\n setBusy(null)\n }\n }\n\n const disconnect = async () => {\n const confirmed = await confirm({\n title: 'Disconnect this mailbox?',\n description:\n 'Disconnecting deletes the access stored for this mailbox and asks Google to revoke it. ' +\n 'Nothing is sent from it again unless it is connected again.',\n confirmationText: MAILBOX_ACTION_LABELS.disconnect,\n confirmationButtonProps: { color: 'error' },\n })\n .then(() => true)\n .catch(() => false)\n if (!confirmed) return\n setBusy('disconnect')\n try {\n const { revocation } = await api.disconnect(mailbox.id)\n if (revocation === 'failed') {\n enqueueSnackbar(\n 'Mailbox disconnected, but Google could not confirm the access was revoked. ' +\n 'Remove it from the Google Account’s third-party connections to be sure.',\n { variant: 'warning', persist: true },\n )\n } else if (revocation === 'kept-for-other-mailbox') {\n enqueueSnackbar(\n 'Mailbox disconnected. Google access stays in place for another connected mailbox on the same account.',\n { variant: 'success' },\n )\n } else {\n enqueueSnackbar('Mailbox disconnected', { variant: 'success' })\n }\n } catch (error) {\n enqueueSnackbar((error as Error).message, { variant: 'error', allowDuplicate: true })\n setBusy(null)\n }\n }\n\n const sendAsLabel = (email: string) => {\n const option = mailbox.sendAsOptions?.find((entry) => entry.email === email)\n return option?.displayName ? `${option.displayName} <${option.email}>` : email\n }\n\n return (\n <CardDisplay\n header={mailbox.email}\n subheader={isMine ? 'Your mailbox' : 'A teammate’s mailbox'}\n help={pluginDocsHelp('sequences', { anchor: '#connect-a-mailbox' })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n action: (\n <Chip\n size=\"small\"\n label={OUTREACH_MAILBOX_STATUS_LABELS[mailbox.status] ?? mailbox.status}\n color={STATUS_COLOR[mailbox.status] ?? 'default'}\n />\n ),\n }}\n >\n <Stack spacing={2}>\n {needsReconnect ? (\n <Alert\n severity=\"warning\"\n action={\n isMine ? (\n <Button color=\"inherit\" size=\"small\" disabled={reconnecting} onClick={onReconnect}>\n {MAILBOX_ACTION_LABELS.reconnect}\n </Button>\n ) : undefined\n }\n >\n {`${\n mailbox.status === 'disconnected'\n ? 'This mailbox was disconnected.'\n : 'Google stopped accepting this mailbox’s connection.'\n } ${\n isMine\n ? 'Nothing sends from it until you connect it again.'\n : 'Only the member who connected it can reconnect it.'\n }`}\n </Alert>\n ) : null}\n {mailbox.status === 'paused' && mailbox.autoPause ? (\n <Alert severity=\"error\" role=\"alert\">\n {autoPauseSentence(mailbox)}\n </Alert>\n ) : null}\n\n <Box>\n <Typography variant=\"subtitle2\">Last 7 days</Typography>\n {health.hasSent ? null : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n No sends yet\n </Typography>\n )}\n <Stack direction=\"row\" spacing={3} sx={{ mt: 0.5 }}>\n {[\n ['Sent', health.sent],\n ['Bounces', health.bounces],\n ['Replies', health.replies],\n ].map(([label, value]) => (\n <Box key={label as string} aria-label={`${label} in the last 7 days`}>\n <Typography variant=\"h6\" component=\"p\">\n {value}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {label}\n </Typography>\n </Box>\n ))}\n </Stack>\n </Box>\n\n {canManage ? (\n <Stack spacing={2} component=\"form\" onSubmit={(event) => event.preventDefault()}>\n <TextField\n select\n size=\"small\"\n label=\"Send as\"\n value={draft.sendAs}\n onChange={(event) => setDraft({ ...draft, sendAs: event.target.value })}\n helperText=\"Addresses Gmail has verified for this account.\"\n >\n {(mailbox.sendAsOptions?.length ? mailbox.sendAsOptions : [{ email: mailbox.sendAs }]).map((option) => (\n <MenuItem key={option.email} value={option.email}>\n {sendAsLabel(option.email)}\n </MenuItem>\n ))}\n </TextField>\n <TextField\n size=\"small\"\n label=\"Display name\"\n value={draft.displayName}\n onChange={(event) => setDraft({ ...draft, displayName: event.target.value })}\n error={typeof nameCheck !== 'string'}\n helperText={typeof nameCheck !== 'string' ? nameCheck.message : 'The name recipients see beside the address.'}\n />\n <TextField\n size=\"small\"\n type=\"number\"\n label=\"Daily cap\"\n value={draft.dailyCap}\n onChange={(event) => setDraft({ ...draft, dailyCap: event.target.value })}\n error={typeof capCheck !== 'number'}\n slotProps={{ htmlInput: { min: 1, max: OUTREACH_MAX_DAILY_CAP, step: 1 } }}\n helperText={\n typeof capCheck !== 'number'\n ? capCheck.message\n : `${RAMP_SENTENCE} Today’s limit: ${todayLimit}.`\n }\n />\n <Box>\n <Typography variant=\"subtitle2\" gutterBottom>\n Sending window\n </Typography>\n <ToggleButtonGroup\n size=\"small\"\n aria-label=\"Sending days\"\n value={draft.window.days}\n onChange={(_event, days: number[]) =>\n setDraft({ ...draft, window: { ...draft.window, days: [...days].sort((a, b) => a - b) } })\n }\n >\n {OUTREACH_WEEKDAY_LABELS.map((label, day) => (\n <ToggleButton key={label} value={day} aria-label={WEEKDAY_NAMES[day]}>\n {label}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} sx={{ mt: 2 }}>\n <TextField\n select\n size=\"small\"\n label=\"From\"\n value={draft.window.startMinute}\n onChange={(event) =>\n setDraft({ ...draft, window: { ...draft.window, startMinute: Number(event.target.value) } })\n }\n >\n {MINUTE_OPTIONS.slice(0, -1).map((minute) => (\n <MenuItem key={minute} value={minute}>\n {formatMinuteOfDay(minute)}\n </MenuItem>\n ))}\n </TextField>\n <TextField\n select\n size=\"small\"\n label=\"Until\"\n value={draft.window.endMinute}\n onChange={(event) =>\n setDraft({ ...draft, window: { ...draft.window, endMinute: Number(event.target.value) } })\n }\n >\n {MINUTE_OPTIONS.slice(1).map((minute) => (\n <MenuItem key={minute} value={minute}>\n {formatMinuteOfDay(minute)}\n </MenuItem>\n ))}\n </TextField>\n <Autocomplete\n size=\"small\"\n disableClearable\n options={timezoneOptions(mailbox.timezone)}\n value={draft.timezone}\n onChange={(_event, timezone) => setDraft({ ...draft, timezone: timezone ?? draft.timezone })}\n sx={{ minWidth: 240 }}\n renderInput={(params) => <TextField {...params} label=\"Timezone\" />}\n />\n </Stack>\n {'days' in windowCheck ? null : <FormHelperText error>{windowCheck.message}</FormHelperText>}\n </Box>\n {saveError ? <FormHelperText error>{saveError}</FormHelperText> : null}\n <Box>\n <Button variant=\"contained\" disabled={!dirty || invalid || saving} onClick={() => void save()}>\n {MAILBOX_ACTION_LABELS.save}\n </Button>\n </Box>\n </Stack>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Sends as ${sendAsLabel(stored.sendAs)}, at most ${stored.dailyCap} a day, ` +\n `${stored.window.days.map((day) => OUTREACH_WEEKDAY_LABELS[day]).join(', ')} ` +\n `${formatMinuteOfDay(stored.window.startMinute)}–${formatMinuteOfDay(stored.window.endMinute)} ` +\n `(${stored.timezone}).`}\n </Typography>\n )}\n\n {canManage || isMine ? (\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ flexWrap: 'wrap' }}>\n {canManage && !needsReconnect ? (\n <Button variant=\"outlined\" disabled={busy !== null} onClick={() => void togglePaused()}>\n {mailbox.status === 'paused' ? MAILBOX_ACTION_LABELS.resume : MAILBOX_ACTION_LABELS.pause}\n </Button>\n ) : null}\n {isMine && !needsReconnect ? (\n <Button variant=\"outlined\" disabled={busy !== null} onClick={() => void sendTest()}>\n {MAILBOX_ACTION_LABELS.test}\n </Button>\n ) : null}\n {canManage ? (\n <Button color=\"error\" disabled={busy !== null} onClick={() => void disconnect()}>\n {MAILBOX_ACTION_LABELS.disconnect}\n </Button>\n ) : null}\n </Stack>\n ) : null}\n </Stack>\n </CardDisplay>\n )\n}\nMailboxCard.displayName = 'MailboxCard'\n\nexport default MailboxCard\n"],"names":["pluginDocsHelp","CardDisplay","useConfirmationContext","useSnackbar","Alert","Autocomplete","Box","Button","Chip","FormHelperText","MenuItem","Stack","TextField","ToggleButton","ToggleButtonGroup","Typography","useEffect","useMemo","useRef","useState","formatMinuteOfDay","isValidTimezone","OUTREACH_DEFAULT_WINDOW","OUTREACH_MAILBOX_STATUS_LABELS","OUTREACH_MAX_DAILY_CAP","OUTREACH_RAMP_STEPS","OUTREACH_WEEKDAY_LABELS","outreachEffectiveDailyCap","summarizeMailboxHealth","validateDailyCap","validateDisplayName","validateSendWindow","autoPauseSentence","mailbox","pause","autoPause","day","atMs","Intl","DateTimeFormat","dateStyle","timeZone","timezone","format","until","untilMs","message","MAILBOX_ACTION_LABELS","save","resume","test","disconnect","reconnect","WEEKDAY_NAMES","STATUS_COLOR","connected","paused","reconnect_required","disconnected","MINUTE_OPTIONS","Array","from","length","_","index","timezoneOptions","current","supported","supportedValuesOf","zones","includes","RAMP_SENTENCE","map","step","week","limit","join","draftOf","sendAs","email","displayName","dailyCap","String","window","MailboxCard","props","isMine","canManage","api","onReconnect","reconnecting","nowMs","Date","now","enqueueSnackbar","confirm","draft","setDraft","saving","setSaving","saveError","setSaveError","busy","setBusy","stored","storedKey","JSON","stringify","seededFrom","dirty","previous","health","needsReconnect","status","capCheck","Number","NaN","windowCheck","nameCheck","timezoneValid","invalid","todayLimit","rampStartedAtMs","saveSettings","mailboxId","id","variant","error","togglePaused","setPaused","allowDuplicate","sendTest","sent","sentTo","confirmed","title","description","confirmationText","confirmationButtonProps","color","then","catch","revocation","persist","sendAsLabel","option","sendAsOptions","find","entry","header","subheader","help","anchor","contentGutterX","contentGutterY","HeaderProps","action","size","label","spacing","severity","disabled","onClick","undefined","role","hasSent","direction","sx","mt","bounces","replies","value","aria-label","component","onSubmit","event","preventDefault","select","onChange","target","helperText","type","slotProps","htmlInput","min","max","gutterBottom","days","_event","sort","a","b","xs","sm","startMinute","slice","minute","endMinute","disableClearable","options","minWidth","renderInput","params","useFlexGap","flexWrap"],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface OutreachMailboxesSectionProps {
|
|
2
|
+
/** The organization the hub is mounted under; `null` until the shell knows it. */
|
|
3
|
+
orgId: string | null;
|
|
4
|
+
/** Sends the browser to Google's consent screen. A test seam; the page's own location by default. */
|
|
5
|
+
navigate?: (url: string) => void;
|
|
6
|
+
}
|
|
7
|
+
/** The connect button's accessible name, spelled once for the specs. */
|
|
8
|
+
export declare const CONNECT_WITH_GOOGLE_LABEL = "Connect with Google";
|
|
9
|
+
/**
|
|
10
|
+
* The Mailboxes section (AGL-2978): the organization's connected Google
|
|
11
|
+
* mailboxes, and the connect that adds one.
|
|
12
|
+
*
|
|
13
|
+
* A connect leaves the console for Google's consent screen and comes back
|
|
14
|
+
* here through the callback route, which puts the authorization code in this
|
|
15
|
+
* page's URL fragment. The section reads the fragment once, takes it out of
|
|
16
|
+
* the address bar before anything else, and finishes the connect with the
|
|
17
|
+
* member's own session — the step that refuses a connect started by anyone
|
|
18
|
+
* else.
|
|
19
|
+
*/
|
|
20
|
+
export declare function OutreachMailboxesSection(props: OutreachMailboxesSectionProps): import("react").JSX.Element;
|
|
21
|
+
export declare namespace OutreachMailboxesSection {
|
|
22
|
+
var displayName: string;
|
|
23
|
+
}
|
|
24
|
+
export default OutreachMailboxesSection;
|