feat: harden campaign delivery and editing

This commit is contained in:
2026-07-30 14:27:04 +02:00
parent 4a120e8009
commit cd223cbb95
34 changed files with 3370 additions and 165 deletions
@@ -112,10 +112,10 @@ export default function BuiltMessagePreview({
<Button
variant="primary"
disabled={singleMessageSendBusy || Boolean(singleSendDisabledReason)}
title={singleSendDisabledReason || "Send only this built message"}
title={singleSendDisabledReason || "Test, send, or resend only this built message"}
onClick={() => onSendSingle(index)}
>
{singleMessageSendBusy ? "Sending..." : "Send this message..."}
{singleMessageSendBusy ? "Sending..." : "Message actions..."}
</Button>
}
onClose={onClose}
@@ -139,28 +139,15 @@ function singleMessageSendDisabledReason(
return `This message is ${humanize(validationStatus)}.`;
}
const sendStatus = String(row.send_status ?? "not_queued");
const queueStatus = String(row.queue_status ?? "draft");
if (["smtp_accepted", "sent"].includes(sendStatus)) {
return "This message was already accepted by SMTP.";
}
if (["claimed", "sending", "outcome_unknown"].includes(sendStatus)) {
return `This message is in delivery state ${humanize(sendStatus)}.`;
}
if (["failed_temporary", "failed_permanent"].includes(sendStatus)) {
return "Use the explicit retry action for failed messages.";
}
if (sendStatus === "queued" && queueStatus === "queued") return "";
if (
["not_queued", "cancelled"].includes(sendStatus) &&
["draft", "cancelled"].includes(queueStatus)
) {
return "";
}
return `This message cannot be sent from queue ${humanize(queueStatus)} / send ${humanize(sendStatus)}.`;
return "";
}
function builtMessageMetaItems(row: Record<string, unknown>) {
const recipients = asRecord(row.resolved_recipients);
const postboxTargets = asArray(row.resolved_postbox_targets).map(asRecord);
return [
{
label: "i18n:govoplan-campaign.from.3f66052a",
@@ -182,6 +169,23 @@ function builtMessageMetaItems(row: Record<string, unknown>) {
label: "i18n:govoplan-campaign.validation.dd74d182",
value: String(row.validation_status ?? "—")
},
{
label: "Frozen Postbox targets",
value: postboxTargets.length
? postboxTargets
.map((target) => {
const label = String(
target.name ?? target.address ?? target.postbox_id ?? "Postbox"
);
const address = String(target.address ?? "");
const context = target.context_key
? ` [${String(target.context_key)}]`
: "";
return `${label}${address && address !== label ? ` <${address}>` : ""}${context}`;
})
.join(", ")
: null
},
{
label: "i18n:govoplan-campaign.mime_size.c8b9d519",
value: row.eml_size_bytes ? `${String(row.eml_size_bytes)} bytes` : "—"