Workflow UI redesign - first draft
This commit is contained in:
@@ -7,6 +7,8 @@ import PageTitle from "../../components/PageTitle";
|
||||
import LoadingFrame from "../../components/LoadingFrame";
|
||||
import LockedVersionNotice from "./components/LockedVersionNotice";
|
||||
import VersionLine from "./components/VersionLine";
|
||||
import ReviewWorkflowCards from "./components/ReviewWorkflowCards";
|
||||
import MessagePreviewOverlay, { type MessagePreviewAttachment } from "./components/MessagePreviewOverlay";
|
||||
import Card from "../../components/Card";
|
||||
import MetricCard from "../../components/MetricCard";
|
||||
import StatusBadge from "../../components/StatusBadge";
|
||||
@@ -157,6 +159,15 @@ export default function SendDataPage({ settings, campaignId }: { settings: ApiSe
|
||||
<MetricCard label="Failed" value={cards?.failed ?? "—"} tone="danger" detail="SMTP failures" />
|
||||
</div>
|
||||
|
||||
<ReviewWorkflowCards
|
||||
settings={settings}
|
||||
version={version}
|
||||
summary={data.summary}
|
||||
loading={loading}
|
||||
reload={reload}
|
||||
setError={setError}
|
||||
/>
|
||||
|
||||
<Card title="Mock delivery test" collapsible actions={<span className="muted small-note">Temporary sandbox. It never uses the real SMTP/IMAP server and never marks this version sent.</span>}>
|
||||
<div className="button-row compact-actions">
|
||||
<Button onClick={() => void runMockFlow(false, false)} disabled={!version || loading || mockBusy}>{mockBusy ? "Working…" : "Review mock steps"}</Button>
|
||||
@@ -254,22 +265,7 @@ export default function SendDataPage({ settings, campaignId }: { settings: ApiSe
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{selectedMockMessage && (
|
||||
<div className="mock-message-detail">
|
||||
<div className="subsection-heading split">
|
||||
<h3>{selectedMockMessage.subject || "Mock message"}</h3>
|
||||
<Button onClick={() => setSelectedMockMessage(null)}>Close details</Button>
|
||||
</div>
|
||||
<div className="detail-grid">
|
||||
<div><span className="muted small-note">From</span><strong>{selectedMockMessage.from_header || selectedMockMessage.envelope_from || "—"}</strong></div>
|
||||
<div><span className="muted small-note">To</span><strong>{selectedMockMessage.to_header || (selectedMockMessage.envelope_recipients || []).join(", ") || "—"}</strong></div>
|
||||
<div><span className="muted small-note">Size</span><strong>{selectedMockMessage.size_bytes || 0} bytes</strong></div>
|
||||
<div><span className="muted small-note">Folder</span><strong>{selectedMockMessage.folder || "—"}</strong></div>
|
||||
</div>
|
||||
{selectedMockMessage.body_preview && <pre className="mock-message-preview">{selectedMockMessage.body_preview}</pre>}
|
||||
{selectedMockMessage.raw_eml && <details><summary>Raw MIME</summary><pre className="mock-message-raw">{selectedMockMessage.raw_eml}</pre></details>}
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
@@ -343,6 +339,21 @@ export default function SendDataPage({ settings, campaignId }: { settings: ApiSe
|
||||
</p>
|
||||
</Card>
|
||||
</LoadingFrame>
|
||||
{selectedMockMessage && (
|
||||
<MessagePreviewOverlay
|
||||
title="Captured mock mail"
|
||||
subject={selectedMockMessage.subject || "Mock message"}
|
||||
bodyMode="text"
|
||||
text={selectedMockMessage.body_preview || ""}
|
||||
recipientLabel={selectedMockMessage.kind === "imap_append" ? "Mock IMAP append" : "Mock SMTP delivery"}
|
||||
recipientNote={selectedMockMessage.created_at ? new Date(selectedMockMessage.created_at).toLocaleString() : undefined}
|
||||
metaItems={mockMessageMetaItems(selectedMockMessage)}
|
||||
attachments={mockMessageAttachments(selectedMockMessage)}
|
||||
raw={selectedMockMessage.raw_eml}
|
||||
rawLabel="Raw MIME"
|
||||
onClose={() => setSelectedMockMessage(null)}
|
||||
/>
|
||||
)}
|
||||
<ConfirmDialog
|
||||
open={sendConfirmOpen}
|
||||
title="Send this version now?"
|
||||
@@ -359,3 +370,23 @@ export default function SendDataPage({ settings, campaignId }: { settings: ApiSe
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function mockMessageMetaItems(message: MockMailboxMessage) {
|
||||
return [
|
||||
{ label: "From", value: message.from_header || message.envelope_from || "—" },
|
||||
{ label: "To", value: message.to_header || message.envelope_recipients?.join(", ") || "—" },
|
||||
{ label: "Kind", value: message.kind || "—" },
|
||||
{ label: "Folder", value: message.folder || "—" },
|
||||
{ label: "Message-ID", value: message.message_id || "—" },
|
||||
{ label: "Size", value: `${message.size_bytes || 0} bytes` }
|
||||
];
|
||||
}
|
||||
|
||||
function mockMessageAttachments(message: MockMailboxMessage): MessagePreviewAttachment[] {
|
||||
return (message.attachments ?? []).map((attachment, index) => ({
|
||||
filename: attachment.filename || `Attachment ${index + 1}`,
|
||||
contentType: attachment.content_type || undefined,
|
||||
sizeBytes: attachment.size_bytes ?? undefined
|
||||
}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user