UI polishes, file chooser

This commit is contained in:
2026-06-10 14:09:50 +02:00
parent 1f34435893
commit 4544a89443
13 changed files with 357 additions and 115 deletions

View File

@@ -12,7 +12,7 @@ import { asArray, asRecord, formatDateTime, isAuditLockedVersion, isRecord, vers
import { ensureCampaignDraft, getBool, getText, updateNested } from "./utils/draftEditor";
import { useRegisterCampaignUnsavedChanges } from "./context/UnsavedChangesContext";
import FieldValueInput from "./components/FieldValueInput";
import AttachmentRulesOverlay, { type AttachmentRule } from "./components/AttachmentRulesOverlay";
import AttachmentRulesOverlay, { type AttachmentBasePath, type AttachmentRule } from "./components/AttachmentRulesOverlay";
import {
addressesFromValue,
collectCampaignAddressSuggestions,
@@ -46,6 +46,12 @@ export default function RecipientDataPage({ settings, campaignId }: { settings:
const inlineEntries = asArray(entries.inline).map(asRecord);
const source = asRecord(entries.source);
const fieldDefinitions = useMemo(() => getDraftFields(draft), [draft]);
const attachmentSection = asRecord(draft?.attachments);
const attachmentBasePaths = useMemo(() => normalizeAttachmentBasePaths(attachmentSection.base_paths, attachmentSection), [draft?.attachments]);
const individualAttachmentBasePaths = useMemo(() => {
const enabled = attachmentBasePaths.filter((basePath) => basePath.allow_individual);
return enabled.length > 0 ? enabled : attachmentBasePaths;
}, [attachmentBasePaths]);
const addressSuggestions = useMemo(() => collectCampaignAddressSuggestions(draft), [draft]);
const globalRecipientValues: Record<string, MailboxAddress[]> = {
to: addressesFromValue(recipientsSection.to),
@@ -292,6 +298,7 @@ export default function RecipientDataPage({ settings, campaignId }: { settings:
title={`Attachments for recipient ${index + 1}`}
rules={attachments}
disabled={locked}
basePaths={individualAttachmentBasePaths}
onChange={(rules) => updateEntryAttachments(index, rules)}
/>
</td>
@@ -347,6 +354,25 @@ function fallbackRecipientAddress(entry: Record<string, unknown>): MailboxAddres
return direct?.email ? [direct] : [];
}
function normalizeAttachmentBasePaths(value: unknown, attachments: Record<string, unknown>): AttachmentBasePath[] {
if (Array.isArray(value) && value.length > 0) {
return value.filter(isRecord).map((basePath, index) => ({
id: getText(basePath, "id", `base-path-${index + 1}`),
name: getText(basePath, "name", `Base path ${index + 1}`),
source: getText(basePath, "source"),
path: getText(basePath, "path", index === 0 ? getText(attachments, "base_path", ".") : "."),
allow_individual: getBool(basePath, "allow_individual")
}));
}
return [{
id: "base-path-campaign",
name: "Campaign files",
path: getText(attachments, "base_path", "."),
allow_individual: getBool(attachments, "allow_individual", true)
}];
}
function normalizeAttachmentRules(value: unknown): AttachmentRule[] {
if (!Array.isArray(value)) return [];
return value.filter(isRecord).map((rule) => ({ ...rule }));