refactor(campaign-ui): separate IMAP append settings

This commit is contained in:
2026-07-20 20:08:58 +02:00
parent c71fa3dc64
commit 0c4f198802

View File

@@ -1,5 +1,5 @@
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { MailServerSettingsPanel, addressesFromValue, hasMailImapSettings, mailImapSettingsPayload, mailNumberOrDefault, mailNumberOrNull, mailServerSecurityOptions, mailSmtpSettingsPayload, mailTransportCredentialsPayloadFromRecords, usePlatformModuleInstalled, usePlatformUiCapability, type MailProfilesUiCapability, type MailServerConnectionTestResult, type MailServerCredentialSettings, type MailServerFolderLookupResult, type MailServerImapSettings, type MailServerSmtpSettings } from "@govoplan/core-webui"; import { MailServerFolderLookupResultView, MailServerSettingsPanel, ToggleSwitch, addressesFromValue, hasMailImapSettings, mailImapSettingsPayload, mailNumberOrDefault, mailNumberOrNull, mailServerSecurityOptions, mailSmtpSettingsPayload, mailTransportCredentialsPayloadFromRecords, usePlatformModuleInstalled, usePlatformUiCapability, type MailProfilesUiCapability, type MailServerConnectionTestResult, type MailServerCredentialSettings, type MailServerFolderLookupResult, type MailServerImapSettings, type MailServerSmtpSettings } from "@govoplan/core-webui";
import type { ApiSettings } from "../../types"; import type { ApiSettings } from "../../types";
import { Button } from "@govoplan/core-webui"; import { Button } from "@govoplan/core-webui";
import { Card } from "@govoplan/core-webui"; import { Card } from "@govoplan/core-webui";
@@ -59,7 +59,7 @@ export default function MailSettingsPage({ settings, campaignId, view = "setting
const version = data.currentVersion; const version = data.currentVersion;
const locked = isAuditLockedVersion(version, data.campaign?.current_version_id); const locked = isAuditLockedVersion(version, data.campaign?.current_version_id);
const { draft, displayDraft, dirty, saveState, localError, setLocalError, patch, saveDraft } = useCampaignDraftEditor({ const { draft, displayDraft, dirty, saveState, localError, setLocalError, patch, discardDraft, saveDraft } = useCampaignDraftEditor({
settings, settings,
campaignId, campaignId,
version, version,
@@ -98,6 +98,7 @@ export default function MailSettingsPage({ settings, campaignId, view = "setting
const imapCredentialDisabled = locked || inlineMailSettingsBlocked || imapUnavailable || usingMailProfile && imapCredentialsInherited; const imapCredentialDisabled = locked || inlineMailSettingsBlocked || imapUnavailable || usingMailProfile && imapCredentialsInherited;
const imapDisabled = locked || inlineMailSettingsBlocked || imapUnavailable; const imapDisabled = locked || inlineMailSettingsBlocked || imapUnavailable;
const imapAppendEnabled = getBool(imapAppend, "enabled"); const imapAppendEnabled = getBool(imapAppend, "enabled");
const imapAppendFolder = getText(imapAppend, "folder", getText(imap, "sent_folder", "auto"));
const appendTargetFolderDisabled = imapDisabled || !imapAppendEnabled; const appendTargetFolderDisabled = imapDisabled || !imapAppendEnabled;
const inlinePolicyMessages = useMemo(() => { const inlinePolicyMessages = useMemo(() => {
const validateMailPolicy = mailProfilesUi?.validateMailPolicy; const validateMailPolicy = mailProfilesUi?.validateMailPolicy;
@@ -393,7 +394,7 @@ export default function MailSettingsPage({ settings, campaignId, view = "setting
<VersionLine version={version} versions={data.versions} status={saveState} /> <VersionLine version={version} versions={data.versions} status={saveState} />
</div> </div>
<div className="button-row compact-actions"> <div className="button-row compact-actions">
<Button onClick={reload} disabled={loading}>i18n:govoplan-campaign.reload.cce71553</Button> <Button onClick={() => void discardDraft()} disabled={loading}>Discard</Button>
{!isPolicyView && <Button variant="primary" onClick={() => saveDraft("manual")} disabled={!dirty || locked || !draft || inlineMailSettingsBlocked}>{dirty ? "i18n:govoplan-campaign.save_now.3989b7c0" : "i18n:govoplan-campaign.saved.c0ae8f6e"}</Button>} {!isPolicyView && <Button variant="primary" onClick={() => saveDraft("manual")} disabled={!dirty || locked || !draft || inlineMailSettingsBlocked}>{dirty ? "i18n:govoplan-campaign.save_now.3989b7c0" : "i18n:govoplan-campaign.saved.c0ae8f6e"}</Button>}
</div> </div>
</div> </div>
@@ -464,6 +465,33 @@ export default function MailSettingsPage({ settings, campaignId, view = "setting
</Card> </Card>
} }
{!isPolicyView &&
<Card title="i18n:govoplan-campaign.imap_append.8c0d9e96" collapsible>
<div className="form-grid compact responsive-form-grid mail-server-form-grid">
<div className="mail-server-field-span mail-server-toggle-row mail-server-plain-toggle-row">
<ToggleSwitch
label="i18n:govoplan-campaign.append_successful_messages_to_sent_via_imap.dbd1b1d8"
checked={imapAppendEnabled}
disabled={imapDisabled}
onChange={(checked) => patch(["delivery", "imap_append_sent", "enabled"], checked)} />
</div>
<FormField label="i18n:govoplan-core.append_target_folder.0aaacc0c" help="i18n:govoplan-core.folder_for_sent_message_copies_leave_as_auto_unl.a62586e9">
<div className="field-with-action mail-server-folder-field">
<input
value={imapAppendFolder}
disabled={appendTargetFolderDisabled}
onChange={(event) => patch(["delivery", "imap_append_sent", "folder"], event.target.value)}
placeholder="i18n:govoplan-core.auto.0d612c12" />
<Button type="button" variant="primary" onClick={() => void runFolderLookup()} disabled={appendTargetFolderDisabled || mailActionState === "folders"}>
{mailActionState === "folders" ? "i18n:govoplan-core.looking_up.5fc6d2a2" : "i18n:govoplan-core.folders.c603ab65"}
</Button>
</div>
</FormField>
<MailServerFolderLookupResultView result={folderResult} disabled={appendTargetFolderDisabled} onUseDetected={useDetectedSentFolder} floatingFailures />
</div>
</Card>
}
{!isPolicyView && {!isPolicyView &&
<Card title="i18n:govoplan-campaign.mail_server_settings.6db620b0" collapsible> <Card title="i18n:govoplan-campaign.mail_server_settings.6db620b0" collapsible>
{inlinePolicyMessages.length > 0 && {inlinePolicyMessages.length > 0 &&
@@ -489,25 +517,13 @@ export default function MailSettingsPage({ settings, campaignId, view = "setting
imapCredentialDisabled={imapCredentialDisabled} imapCredentialDisabled={imapCredentialDisabled}
imapPasswordSaved={Boolean(usingMailProfile && imapCredentialsInherited && selectedProfile?.imap_password_configured)} imapPasswordSaved={Boolean(usingMailProfile && imapCredentialsInherited && selectedProfile?.imap_password_configured)}
imapActionDisabled={imapDisabled || !mailModuleInstalled} imapActionDisabled={imapDisabled || !mailModuleInstalled}
append={{
enabled: imapAppendEnabled,
folder: getText(imapAppend, "folder", getText(imap, "sent_folder", "auto")),
disabled: imapDisabled,
folderDisabled: appendTargetFolderDisabled,
onEnabledChange: (checked) => patch(["delivery", "imap_append_sent", "enabled"], checked),
onFolderChange: (folder) => patch(["delivery", "imap_append_sent", "folder"], folder)
}}
smtpTestLabel={usingMailProfile ? "i18n:govoplan-campaign.test_profile_smtp.884a0e66" : "i18n:govoplan-campaign.test_smtp_login.a1359755"} smtpTestLabel={usingMailProfile ? "i18n:govoplan-campaign.test_profile_smtp.884a0e66" : "i18n:govoplan-campaign.test_smtp_login.a1359755"}
imapTestLabel={usingMailProfile ? "i18n:govoplan-campaign.test_profile_imap.e1cec0e0" : "i18n:govoplan-campaign.test_imap_login.c32e316e"} imapTestLabel={usingMailProfile ? "i18n:govoplan-campaign.test_profile_imap.e1cec0e0" : "i18n:govoplan-campaign.test_imap_login.c32e316e"}
busyAction={mailActionState} busyAction={mailActionState}
onTestSmtp={runSmtpTest} onTestSmtp={runSmtpTest}
onTestImap={runImapTest} onTestImap={runImapTest}
onLookupFolders={runFolderLookup}
smtpTestResult={smtpTestResult} smtpTestResult={smtpTestResult}
imapTestResult={imapTestResult} imapTestResult={imapTestResult}
folderLookupResult={folderResult}
onUseDetectedFolder={useDetectedSentFolder}
useDetectedFolderDisabled={appendTargetFolderDisabled}
floatingResults /> floatingResults />
</Card> </Card>