diff --git a/webui/src/features/campaigns/AttachmentsDataPage.tsx b/webui/src/features/campaigns/AttachmentsDataPage.tsx index f75c57b..d850820 100644 --- a/webui/src/features/campaigns/AttachmentsDataPage.tsx +++ b/webui/src/features/campaigns/AttachmentsDataPage.tsx @@ -6,6 +6,7 @@ import { Button } from "@govoplan/core-webui"; import { Card } from "@govoplan/core-webui"; import { PageTitle } from "@govoplan/core-webui"; import { LoadingFrame } from "@govoplan/core-webui"; +import { MetricCard } from "@govoplan/core-webui"; import LockedVersionNotice from "./components/LockedVersionNotice"; import VersionLine from "./components/VersionLine"; import { ToggleSwitch } from "@govoplan/core-webui"; @@ -40,7 +41,7 @@ export default function AttachmentsDataPage({ settings, campaignId }: {settings: const [zipNameEditorIndex, setZipNameEditorIndex] = useState(null); const version = data.currentVersion; const locked = isAuditLockedVersion(version, data.campaign?.current_version_id); - const { draft, setDraft, displayDraft, dirty, saveState, localError, patch, markDirty, saveDraft } = useCampaignDraftEditor({ + const { draft, setDraft, displayDraft, dirty, saveState, localError, patch, markDirty, discardDraft, saveDraft } = useCampaignDraftEditor({ settings, campaignId, version, @@ -238,7 +239,7 @@ export default function AttachmentsDataPage({ settings, campaignId }: {settings:
{filesModuleInstalled && } - +
@@ -249,6 +250,13 @@ export default function AttachmentsDataPage({ settings, campaignId }: {settings: <> +
+ + + + +
+
{zipArchiveNameValidation.message} } -

i18n:govoplan-campaign.archive_names_support_recipient_and_campaign_fie.d5b1b2d1

@@ -319,20 +326,6 @@ export default function AttachmentsDataPage({ settings, campaignId }: {settings: - -
-
i18n:govoplan-campaign.base_paths.edf35a97
{basePaths.length}
-
i18n:govoplan-campaign.global_attachments.438263a1
direct: {globalSummary.direct} i18n:govoplan-campaign.rules.e5d36074 {globalSummary.rules}
-
i18n:govoplan-campaign.per_recipient_patterns.53da30da
{individualRulesCount}
-
i18n:govoplan-campaign.upload_support.1c54931c
{managedFilesAvailable ? "i18n:govoplan-campaign.connected_through_files.95007112" : "i18n:govoplan-campaign.manual_paths.8e20627a"}
-
-

{managedFilesAvailable ? - "i18n:govoplan-campaign.files_are_managed_in_the_top_level_files_module_.4b370222" : - filesModuleInstalled ? - "i18n:govoplan-campaign.managed_file_browsing_is_unavailable_use_manual_.782867fe" : - "i18n:govoplan-campaign.the_files_module_is_not_installed_use_manual_pat.49abc725"}

-
- @@ -450,6 +443,19 @@ function zipArchiveColumns({ disabled, archives, invalidNameIndexes, onEditName, render: (archive, index) => patchArchive(index, { password_enabled: checked })} />, value: (archive) => archive.password_enabled ? "protected" : "none" }, + { + id: "method", header: "ZIP mode", width: 280, sortable: true, filterable: true, + columnType: "from-list", list: { options: [{ value: "aes", label: "AES" }, { value: "zip_standard", label: "Win-compatible" }] }, + render: (archive, index) => + patchArchive(index, { method: checked ? "zip_standard" : "aes" })} />, + + value: (archive) => archive.method + }, { id: "password_field", header: "i18n:govoplan-campaign.password_field.a1fc8a1c", width: 230, sortable: true, filterable: true, columnType: "from-list", list: { options: [{ value: "", label: "i18n:govoplan-campaign.no_field.1fe00ed4" }, ...passwordFields.map((field) => ({ value: field.name, label: field.label || field.name }))] }, diff --git a/webui/src/features/campaigns/GlobalSettingsPage.tsx b/webui/src/features/campaigns/GlobalSettingsPage.tsx index ab26555..cfb2e0c 100644 --- a/webui/src/features/campaigns/GlobalSettingsPage.tsx +++ b/webui/src/features/campaigns/GlobalSettingsPage.tsx @@ -38,7 +38,7 @@ export default function GlobalSettingsPage({ settings, auth, campaignId, view = const version = data.currentVersion; const locked = isAuditLockedVersion(version, data.campaign?.current_version_id); - const { draft, displayDraft, dirty, saveState, localError, patch, markDirty, saveDraft } = useCampaignDraftEditor({ + const { draft, displayDraft, dirty, saveState, localError, patch, markDirty, discardDraft, saveDraft } = useCampaignDraftEditor({ settings, campaignId, version, @@ -71,6 +71,11 @@ export default function GlobalSettingsPage({ settings, auth, campaignId, view = markDirty(); } + function patchSendWithoutAttachmentsBehavior(value: string) { + patch(["attachments", "send_without_attachments_behavior"], value); + patch(["attachments", "send_without_attachments"], value !== "block"); + } + return (
@@ -79,7 +84,7 @@ export default function GlobalSettingsPage({ settings, auth, campaignId, view =
- +
@@ -208,8 +213,8 @@ export default function GlobalSettingsPage({ settings, auth, campaignId, view = effectiveClassName="campaign-policy-effective-note" label="i18n:govoplan-campaign.send_without_attachments.ead6d030" note="i18n:govoplan-campaign.campaign_wide_fallback_when_no_attachment_is_ava.84ffa0bc" - control={ patch(["attachments", "send_without_attachments"], checked)} />} - effective={getBool(attachments, "send_without_attachments", true) ? "i18n:govoplan-campaign.messages_may_be_sent_when_attachment_rules_allow.e6bf1aed" : "i18n:govoplan-campaign.missing_attachment_coverage_blocks_sending.05ff02a1"} /> + control={} + effective={behaviorSummary(sendWithoutAttachmentsBehavior(attachments))} /> @@ -261,3 +266,9 @@ function behaviorSummary(value: string): string { if (value === "warn") return "i18n:govoplan-campaign.keeps_sending_possible_with_a_warning.66c84a54"; return "i18n:govoplan-campaign.uses_the_configured_behavior.ea6e82a3"; } + +function sendWithoutAttachmentsBehavior(attachments: Record): string { + const configured = getText(attachments, "send_without_attachments_behavior"); + if (behaviorOptions.includes(configured)) return configured; + return getBool(attachments, "send_without_attachments", true) ? "continue" : "block"; +} diff --git a/webui/src/features/campaigns/utils/draftEditor.ts b/webui/src/features/campaigns/utils/draftEditor.ts index 15f51d7..fdb20fd 100644 --- a/webui/src/features/campaigns/utils/draftEditor.ts +++ b/webui/src/features/campaigns/utils/draftEditor.ts @@ -22,15 +22,21 @@ export function ensureCampaignDraft(version: CampaignVersionDetail | null): Reco raw.server = isRecord(raw.server) ? raw.server : {}; raw.recipients = isRecord(raw.recipients) ? raw.recipients : {}; raw.template = isRecord(raw.template) ? raw.template : { subject: "", text: "" }; + const sourceAttachments = asRecord(raw.attachments); raw.attachments = { base_path: ".", allow_individual: false, send_without_attachments: true, + send_without_attachments_behavior: "continue", global: [], missing_behavior: "ask", ambiguous_behavior: "ask", - ...asRecord(raw.attachments) + ...sourceAttachments }; + const normalizedAttachments = asRecord(raw.attachments); + if (sourceAttachments.send_without_attachments_behavior === undefined) { + normalizedAttachments.send_without_attachments_behavior = getBool(normalizedAttachments, "send_without_attachments", true) ? "continue" : "block"; + } raw.entries = isRecord(raw.entries) ? raw.entries : { inline: [] }; raw.validation_policy = { unsent_attachment_files: "warn",