chore: sync GovOPlaN module split state
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, type ReactNode } from "react";
|
||||
import { useState } from "react";
|
||||
import type { ApiSettings, AuthInfo } from "../../types";
|
||||
import { Button } from "@govoplan/core-webui";
|
||||
import { Card } from "@govoplan/core-webui";
|
||||
@@ -6,6 +6,8 @@ import { FormField } from "@govoplan/core-webui";
|
||||
import { DismissibleAlert } from "@govoplan/core-webui";
|
||||
import { PageTitle } from "@govoplan/core-webui";
|
||||
import { LoadingFrame } from "@govoplan/core-webui";
|
||||
import { PolicyRow } from "@govoplan/core-webui";
|
||||
import { PolicyTable } from "@govoplan/core-webui";
|
||||
import LockedVersionNotice from "./components/LockedVersionNotice";
|
||||
import CampaignAccessCard from "./components/CampaignAccessCard";
|
||||
import VersionLine from "./components/VersionLine";
|
||||
@@ -44,10 +46,10 @@ export default function GlobalSettingsPage({ settings, auth, campaignId, view =
|
||||
reload,
|
||||
setError,
|
||||
currentStep: isPolicyView ? "policies" : "global-settings",
|
||||
unsavedTitle: isPolicyView ? "Unsaved campaign policy changes" : "Unsaved campaign settings",
|
||||
unsavedMessage: isPolicyView
|
||||
? "Campaign policies have unsaved changes. Save them before leaving, or discard them and continue."
|
||||
: "Campaign settings have unsaved changes. Save them before leaving, or discard them and continue.",
|
||||
unsavedTitle: isPolicyView ? "i18n:govoplan-campaign.unsaved_campaign_policy_changes.181f3426" : "i18n:govoplan-campaign.unsaved_campaign_settings.0555d713",
|
||||
unsavedMessage: isPolicyView ?
|
||||
"i18n:govoplan-campaign.campaign_policies_have_unsaved_changes_save_them.7b07827f" :
|
||||
"i18n:govoplan-campaign.campaign_settings_have_unsaved_changes_save_them.c1c5f65f",
|
||||
extraPayload: () => ({ editor_state: editorState }),
|
||||
onLoaded: (loadedVersion) => setEditorState(cloneJson(loadedVersion.editor_state ?? {})),
|
||||
onSaved: (savedVersion) => setEditorState(cloneJson(savedVersion.editor_state ?? editorState))
|
||||
@@ -61,7 +63,7 @@ export default function GlobalSettingsPage({ settings, auth, campaignId, view =
|
||||
const optIns = asRecord(editorState.opt_ins);
|
||||
const canReadRetentionPolicy = hasScope(auth, "admin:policies:read");
|
||||
const canWriteRetentionPolicy = hasScope(auth, "admin:policies:write");
|
||||
const pageTitle = isPolicyView ? "Campaign policies" : "Campaign settings";
|
||||
const pageTitle = isPolicyView ? "i18n:govoplan-campaign.campaign_policies.0b5de1f5" : "i18n:govoplan-campaign.campaign_settings.efffec26";
|
||||
|
||||
function patchEditor(path: string[], value: unknown) {
|
||||
if (locked) return;
|
||||
@@ -77,171 +79,185 @@ export default function GlobalSettingsPage({ settings, auth, campaignId, view =
|
||||
<VersionLine version={version} versions={data.versions} status={saveState} />
|
||||
</div>
|
||||
<div className="button-row compact-actions">
|
||||
<Button onClick={reload} disabled={loading}>Reload</Button>
|
||||
<Button variant="primary" onClick={() => saveDraft("manual")} disabled={!dirty || locked || !draft}>{dirty ? "Save now" : "Saved"}</Button>
|
||||
<Button onClick={reload} disabled={loading}>i18n:govoplan-campaign.reload.cce71553</Button>
|
||||
<Button variant="primary" onClick={() => saveDraft("manual")} disabled={!dirty || locked || !draft}>{dirty ? "i18n:govoplan-campaign.save_now.3989b7c0" : "i18n:govoplan-campaign.saved.c0ae8f6e"}</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{error && <DismissibleAlert tone="danger" resetKey={error} floating>{error}</DismissibleAlert>}
|
||||
{localError && <DismissibleAlert tone="danger" resetKey={localError} floating>{localError}</DismissibleAlert>}
|
||||
{locked && <LockedVersionNotice settings={settings} campaignId={campaignId} version={version} currentVersionId={data.campaign?.current_version_id} reload={reload} message="This page is read-only for the selected version." />}
|
||||
{locked && <LockedVersionNotice settings={settings} campaignId={campaignId} version={version} currentVersionId={data.campaign?.current_version_id} reload={reload} message="i18n:govoplan-campaign.this_page_is_read_only_for_the_selected_version.dacf5743" />}
|
||||
|
||||
<LoadingFrame loading={loading || !draft} label="Loading campaign draft…">
|
||||
{isPolicyView ? (
|
||||
<>
|
||||
{canReadRetentionPolicy && (
|
||||
<RetentionPolicyEditor
|
||||
settings={settings}
|
||||
scopeType="campaign"
|
||||
scopeId={campaignId}
|
||||
title="Campaign retention policy"
|
||||
description="Campaign-level retention limits applied after system, tenant and owner policy. Blank values inherit."
|
||||
canWrite={canWriteRetentionPolicy}
|
||||
locked={locked}
|
||||
/>
|
||||
)}
|
||||
<LoadingFrame loading={loading || !draft} label="i18n:govoplan-campaign.loading_campaign_draft.1cf47e50">
|
||||
{isPolicyView ?
|
||||
<>
|
||||
{canReadRetentionPolicy &&
|
||||
<RetentionPolicyEditor
|
||||
settings={settings}
|
||||
scopeType="campaign"
|
||||
scopeId={campaignId}
|
||||
title="i18n:govoplan-campaign.campaign_retention_policy.fcc9897c"
|
||||
description="i18n:govoplan-campaign.campaign_level_retention_limits_applied_after_sy.e1a5fd45"
|
||||
canWrite={canWriteRetentionPolicy}
|
||||
locked={locked} />
|
||||
|
||||
}
|
||||
|
||||
<div className="dashboard-grid below-grid">
|
||||
<Card title="Validation policy" collapsible>
|
||||
<PolicyTable>
|
||||
<Card title="i18n:govoplan-campaign.validation_policy.57dcc756" collapsible>
|
||||
<PolicyTable className="campaign-policy-table" rowClassName="campaign-policy-row" headerClassName="campaign-policy-row-header" fieldLabel="i18n:govoplan-campaign.policy.bb9cf141" settingLabel="i18n:govoplan-campaign.setting.fb449f71" effectiveLabel="i18n:govoplan-campaign.effective_behavior.3daa11c2" showEffectiveColumn>
|
||||
<PolicyRow
|
||||
label="Missing required attachment"
|
||||
note="Required attachment rule found no matching file."
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "missing_required_attachment", "ask")} disabled={locked} onChange={(value) => patch(["validation_policy", "missing_required_attachment"], value)} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "missing_required_attachment", "ask"))}
|
||||
/>
|
||||
className="campaign-policy-row"
|
||||
labelClassName="campaign-policy-label"
|
||||
controlClassName="campaign-policy-control"
|
||||
effectiveClassName="campaign-policy-effective-note"
|
||||
label="i18n:govoplan-campaign.missing_required_attachment.a8aa73e0"
|
||||
note="i18n:govoplan-campaign.required_attachment_rule_found_no_matching_file.d947b52b"
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "missing_required_attachment", "ask")} disabled={locked} onChange={(value) => patch(["validation_policy", "missing_required_attachment"], value)} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "missing_required_attachment", "ask"))} />
|
||||
|
||||
<PolicyRow
|
||||
label="Missing optional attachment"
|
||||
note="Optional attachment rule found no matching file."
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "missing_optional_attachment", "warn")} disabled={locked} onChange={(value) => patch(["validation_policy", "missing_optional_attachment"], value)} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "missing_optional_attachment", "warn"))}
|
||||
/>
|
||||
className="campaign-policy-row"
|
||||
labelClassName="campaign-policy-label"
|
||||
controlClassName="campaign-policy-control"
|
||||
effectiveClassName="campaign-policy-effective-note"
|
||||
label="i18n:govoplan-campaign.missing_optional_attachment.36640fa6"
|
||||
note="i18n:govoplan-campaign.optional_attachment_rule_found_no_matching_file.709a2a13"
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "missing_optional_attachment", "warn")} disabled={locked} onChange={(value) => patch(["validation_policy", "missing_optional_attachment"], value)} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "missing_optional_attachment", "warn"))} />
|
||||
|
||||
<PolicyRow
|
||||
label="Ambiguous attachment match"
|
||||
note="Attachment rule matched more files than expected."
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "ambiguous_attachment_match", "ask")} disabled={locked} onChange={(value) => patch(["validation_policy", "ambiguous_attachment_match"], value)} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "ambiguous_attachment_match", "ask"))}
|
||||
/>
|
||||
className="campaign-policy-row"
|
||||
labelClassName="campaign-policy-label"
|
||||
controlClassName="campaign-policy-control"
|
||||
effectiveClassName="campaign-policy-effective-note"
|
||||
label="i18n:govoplan-campaign.ambiguous_attachment_match.8043ddfa"
|
||||
note="i18n:govoplan-campaign.attachment_rule_matched_more_files_than_expected.3e2110e8"
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "ambiguous_attachment_match", "ask")} disabled={locked} onChange={(value) => patch(["validation_policy", "ambiguous_attachment_match"], value)} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "ambiguous_attachment_match", "ask"))} />
|
||||
|
||||
<PolicyRow
|
||||
label="Unsent attachment file"
|
||||
note="A watched attachment directory contains files that were not selected."
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "unsent_attachment_files", "warn")} disabled={locked} onChange={(value) => patch(["validation_policy", "unsent_attachment_files"], value)} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "unsent_attachment_files", "warn"))}
|
||||
/>
|
||||
className="campaign-policy-row"
|
||||
labelClassName="campaign-policy-label"
|
||||
controlClassName="campaign-policy-control"
|
||||
effectiveClassName="campaign-policy-effective-note"
|
||||
label="i18n:govoplan-campaign.unsent_attachment_file.a25263ce"
|
||||
note="i18n:govoplan-campaign.a_watched_attachment_directory_contains_files_th.03f58a42"
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "unsent_attachment_files", "warn")} disabled={locked} onChange={(value) => patch(["validation_policy", "unsent_attachment_files"], value)} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "unsent_attachment_files", "warn"))} />
|
||||
|
||||
<PolicyRow
|
||||
label="Missing email address"
|
||||
note="The effective recipient list has no To address."
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "missing_email", "block")} disabled={locked} onChange={(value) => patch(["validation_policy", "missing_email"], value)} options={["block", "drop"]} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "missing_email", "block"))}
|
||||
/>
|
||||
className="campaign-policy-row"
|
||||
labelClassName="campaign-policy-label"
|
||||
controlClassName="campaign-policy-control"
|
||||
effectiveClassName="campaign-policy-effective-note"
|
||||
label="i18n:govoplan-campaign.missing_email_address.2a94b6d8"
|
||||
note="i18n:govoplan-campaign.the_effective_recipient_list_has_no_to_address.df4e24f7"
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "missing_email", "block")} disabled={locked} onChange={(value) => patch(["validation_policy", "missing_email"], value)} options={["block", "drop"]} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "missing_email", "block"))} />
|
||||
|
||||
<PolicyRow
|
||||
label="Template error"
|
||||
note="A selected template body contains unresolved placeholders."
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "template_error", "block")} disabled={locked} onChange={(value) => patch(["validation_policy", "template_error"], value)} options={["block", "drop"]} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "template_error", "block"))}
|
||||
/>
|
||||
className="campaign-policy-row"
|
||||
labelClassName="campaign-policy-label"
|
||||
controlClassName="campaign-policy-control"
|
||||
effectiveClassName="campaign-policy-effective-note"
|
||||
label="i18n:govoplan-campaign.template_error.50b92586"
|
||||
note="i18n:govoplan-campaign.a_selected_template_body_contains_unresolved_pla.d061acad"
|
||||
control={<PolicySelectControl value={getText(validationPolicy, "template_error", "block")} disabled={locked} onChange={(value) => patch(["validation_policy", "template_error"], value)} options={["block", "drop"]} />}
|
||||
effective={behaviorSummary(getText(validationPolicy, "template_error", "block"))} />
|
||||
|
||||
<PolicyRow
|
||||
label="Ignore empty fields"
|
||||
note="Controls how missing placeholder values are rendered."
|
||||
control={<ToggleSwitch label="Enabled" checked={getBool(validationPolicy, "ignore_empty_fields")} disabled={locked} onChange={(checked) => patch(["validation_policy", "ignore_empty_fields"], checked)} />}
|
||||
effective={getBool(validationPolicy, "ignore_empty_fields") ? "Missing values render as empty text." : "Missing values remain visible and can trigger template errors."}
|
||||
/>
|
||||
className="campaign-policy-row"
|
||||
labelClassName="campaign-policy-label"
|
||||
controlClassName="campaign-policy-control"
|
||||
effectiveClassName="campaign-policy-effective-note"
|
||||
label="i18n:govoplan-campaign.ignore_empty_fields.1ffcdc5d"
|
||||
note="i18n:govoplan-campaign.controls_how_missing_placeholder_values_are_rend.c1ad492a"
|
||||
control={<ToggleSwitch label="i18n:govoplan-campaign.enabled.df174a3f" checked={getBool(validationPolicy, "ignore_empty_fields")} disabled={locked} onChange={(checked) => patch(["validation_policy", "ignore_empty_fields"], checked)} />}
|
||||
effective={getBool(validationPolicy, "ignore_empty_fields") ? "i18n:govoplan-campaign.missing_values_render_as_empty_text.0a6bce45" : "i18n:govoplan-campaign.missing_values_remain_visible_and_can_trigger_te.31464ee2"} />
|
||||
|
||||
</PolicyTable>
|
||||
</Card>
|
||||
|
||||
<Card title="Attachment policy" collapsible>
|
||||
<PolicyTable>
|
||||
<Card title="i18n:govoplan-campaign.attachment_policy.2fd471d4" collapsible>
|
||||
<PolicyTable className="campaign-policy-table" rowClassName="campaign-policy-row" headerClassName="campaign-policy-row-header" fieldLabel="i18n:govoplan-campaign.policy.bb9cf141" settingLabel="i18n:govoplan-campaign.setting.fb449f71" effectiveLabel="i18n:govoplan-campaign.effective_behavior.3daa11c2" showEffectiveColumn>
|
||||
<PolicyRow
|
||||
label="Default missing behavior"
|
||||
note="Used by attachment rules that do not override missing-file behavior."
|
||||
control={<PolicySelectControl value={getText(attachments, "missing_behavior", "ask")} disabled={locked} onChange={(value) => patch(["attachments", "missing_behavior"], value)} />}
|
||||
effective={behaviorSummary(getText(attachments, "missing_behavior", "ask"))}
|
||||
/>
|
||||
className="campaign-policy-row"
|
||||
labelClassName="campaign-policy-label"
|
||||
controlClassName="campaign-policy-control"
|
||||
effectiveClassName="campaign-policy-effective-note"
|
||||
label="i18n:govoplan-campaign.default_missing_behavior.ffbd9cd7"
|
||||
note="i18n:govoplan-campaign.used_by_attachment_rules_that_do_not_override_mi.ab8bc0d5"
|
||||
control={<PolicySelectControl value={getText(attachments, "missing_behavior", "ask")} disabled={locked} onChange={(value) => patch(["attachments", "missing_behavior"], value)} />}
|
||||
effective={behaviorSummary(getText(attachments, "missing_behavior", "ask"))} />
|
||||
|
||||
<PolicyRow
|
||||
label="Default ambiguous behavior"
|
||||
note="Used by attachment rules that do not override ambiguous-match behavior."
|
||||
control={<PolicySelectControl value={getText(attachments, "ambiguous_behavior", "ask")} disabled={locked} onChange={(value) => patch(["attachments", "ambiguous_behavior"], value)} />}
|
||||
effective={behaviorSummary(getText(attachments, "ambiguous_behavior", "ask"))}
|
||||
/>
|
||||
className="campaign-policy-row"
|
||||
labelClassName="campaign-policy-label"
|
||||
controlClassName="campaign-policy-control"
|
||||
effectiveClassName="campaign-policy-effective-note"
|
||||
label="i18n:govoplan-campaign.default_ambiguous_behavior.878b9345"
|
||||
note="i18n:govoplan-campaign.used_by_attachment_rules_that_do_not_override_am.c31b4e9f"
|
||||
control={<PolicySelectControl value={getText(attachments, "ambiguous_behavior", "ask")} disabled={locked} onChange={(value) => patch(["attachments", "ambiguous_behavior"], value)} />}
|
||||
effective={behaviorSummary(getText(attachments, "ambiguous_behavior", "ask"))} />
|
||||
|
||||
<PolicyRow
|
||||
label="Send without attachments"
|
||||
note="Campaign-wide fallback when no attachment is available."
|
||||
control={<ToggleSwitch label="Allowed" checked={getBool(attachments, "send_without_attachments", true)} disabled={locked} onChange={(checked) => patch(["attachments", "send_without_attachments"], checked)} />}
|
||||
effective={getBool(attachments, "send_without_attachments", true) ? "Messages may be sent when attachment rules allow it." : "Missing attachment coverage blocks sending."}
|
||||
/>
|
||||
className="campaign-policy-row"
|
||||
labelClassName="campaign-policy-label"
|
||||
controlClassName="campaign-policy-control"
|
||||
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={<ToggleSwitch label="i18n:govoplan-campaign.allowed.77c7b490" checked={getBool(attachments, "send_without_attachments", true)} disabled={locked} onChange={(checked) => 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"} />
|
||||
|
||||
</PolicyTable>
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
</> :
|
||||
|
||||
<>
|
||||
{data.campaign && <CampaignAccessCard settings={settings} campaign={data.campaign} onChanged={reload} onError={setError} />}
|
||||
|
||||
<div className="dashboard-grid below-grid">
|
||||
<Card title="Delivery defaults" collapsible>
|
||||
<Card title="i18n:govoplan-campaign.delivery_defaults.33cc3b97" collapsible>
|
||||
<div className="form-grid compact responsive-form-grid">
|
||||
<FormField label="Messages per minute"><input type="number" min={1} value={getNumber(rateLimit, "messages_per_minute", 5)} disabled={locked} onChange={(event) => patch(["delivery", "rate_limit", "messages_per_minute"], Number(event.target.value || 1))} /></FormField>
|
||||
<FormField label="Concurrency"><input type="number" min={1} value={getNumber(rateLimit, "concurrency", 1)} disabled={locked} onChange={(event) => patch(["delivery", "rate_limit", "concurrency"], Number(event.target.value || 1))} /></FormField>
|
||||
<FormField label="Max attempts"><input type="number" min={1} value={getNumber(retry, "max_attempts", 3)} disabled={locked} onChange={(event) => patch(["delivery", "retry", "max_attempts"], Number(event.target.value || 1))} /></FormField>
|
||||
<ToggleSwitch label="Status tracking" checked={getBool(statusTracking, "enabled", true)} disabled={locked} onChange={(checked) => patch(["status_tracking", "enabled"], checked)} />
|
||||
<FormField label="i18n:govoplan-campaign.messages_per_minute.bea49348"><input type="number" min={1} value={getNumber(rateLimit, "messages_per_minute", 5)} disabled={locked} onChange={(event) => patch(["delivery", "rate_limit", "messages_per_minute"], Number(event.target.value || 1))} /></FormField>
|
||||
<FormField label="i18n:govoplan-campaign.concurrency.2ec390bf"><input type="number" min={1} value={getNumber(rateLimit, "concurrency", 1)} disabled={locked} onChange={(event) => patch(["delivery", "rate_limit", "concurrency"], Number(event.target.value || 1))} /></FormField>
|
||||
<FormField label="i18n:govoplan-campaign.max_attempts.f684fef4"><input type="number" min={1} value={getNumber(retry, "max_attempts", 3)} disabled={locked} onChange={(event) => patch(["delivery", "retry", "max_attempts"], Number(event.target.value || 1))} /></FormField>
|
||||
<ToggleSwitch label="i18n:govoplan-campaign.status_tracking.15f61f88" checked={getBool(statusTracking, "enabled", true)} disabled={locked} onChange={(checked) => patch(["status_tracking", "enabled"], checked)} />
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card title="Opt-ins and local assistance" collapsible>
|
||||
<Card title="i18n:govoplan-campaign.opt_ins_and_local_assistance.d0d23635" collapsible>
|
||||
<div className="toggle-grid">
|
||||
<ToggleSwitch label="Suggest addresses from this campaign" checked={getBool(optIns, "campaign_address_suggestions", true)} disabled={locked} onChange={(checked) => patchEditor(["opt_ins", "campaign_address_suggestions"], checked)} />
|
||||
<ToggleSwitch label="Remember newly used addresses" checked={getBool(optIns, "remember_used_addresses")} disabled={locked} onChange={(checked) => patchEditor(["opt_ins", "remember_used_addresses"], checked)} />
|
||||
<ToggleSwitch label="Show guided warnings while editing" checked={getBool(optIns, "inline_guidance", true)} disabled={locked} onChange={(checked) => patchEditor(["opt_ins", "inline_guidance"], checked)} />
|
||||
<ToggleSwitch label="i18n:govoplan-campaign.suggest_addresses_from_this_campaign.5ebe2aea" checked={getBool(optIns, "campaign_address_suggestions", true)} disabled={locked} onChange={(checked) => patchEditor(["opt_ins", "campaign_address_suggestions"], checked)} />
|
||||
<ToggleSwitch label="i18n:govoplan-campaign.remember_newly_used_addresses.aebe8adb" checked={getBool(optIns, "remember_used_addresses")} disabled={locked} onChange={(checked) => patchEditor(["opt_ins", "remember_used_addresses"], checked)} />
|
||||
<ToggleSwitch label="i18n:govoplan-campaign.show_guided_warnings_while_editing.bc5dba85" checked={getBool(optIns, "inline_guidance", true)} disabled={locked} onChange={(checked) => patchEditor(["opt_ins", "inline_guidance"], checked)} />
|
||||
</div>
|
||||
<p className="muted small-note">These opt-ins are stored in the draft editor metadata for now. A later backend patch can make address-book storage tenant/user aware.</p>
|
||||
<p className="muted small-note">i18n:govoplan-campaign.these_opt_ins_are_stored_in_the_draft_editor_met.dc6ffbfd</p>
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
}
|
||||
</LoadingFrame>
|
||||
</div>
|
||||
);
|
||||
</div>);
|
||||
|
||||
}
|
||||
|
||||
function PolicyTable({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<div className="campaign-policy-table policy-table">
|
||||
<div className="campaign-policy-row policy-row campaign-policy-row-header policy-row-header">
|
||||
<span>Policy</span>
|
||||
<span>Setting</span>
|
||||
<span>Effective behavior</span>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function PolicyRow({ label, note, control, effective }: { label: string; note: string; control: ReactNode; effective: string }) {
|
||||
return (
|
||||
<div className="campaign-policy-row policy-row">
|
||||
<div className="campaign-policy-label policy-field-label">
|
||||
<strong>{label}</strong>
|
||||
<small>{note}</small>
|
||||
</div>
|
||||
<div className="campaign-policy-control policy-control">{control}</div>
|
||||
<p className="muted small-note campaign-policy-effective-note policy-effective-note">{effective}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function PolicySelectControl({ value, disabled, onChange, options = behaviorOptions }: { value: string; disabled?: boolean; onChange: (value: string) => void; options?: string[] }) {
|
||||
function PolicySelectControl({ value, disabled, onChange, options = behaviorOptions }: {value: string;disabled?: boolean;onChange: (value: string) => void;options?: string[];}) {
|
||||
return (
|
||||
<select value={value} disabled={disabled} onChange={(event) => onChange(event.target.value)}>
|
||||
{options.map((option) => <option key={option} value={option}>{option}</option>)}
|
||||
</select>
|
||||
);
|
||||
</select>);
|
||||
|
||||
}
|
||||
|
||||
function behaviorSummary(value: string): string {
|
||||
if (value === "block") return "Blocks the affected message.";
|
||||
if (value === "ask") return "Marks the message for review.";
|
||||
if (value === "drop") return "Excludes the affected message.";
|
||||
if (value === "continue") return "Continues without a review issue.";
|
||||
if (value === "warn") return "Keeps sending possible with a warning.";
|
||||
return "Uses the configured behavior.";
|
||||
if (value === "block") return "i18n:govoplan-campaign.blocks_the_affected_message.0157342a";
|
||||
if (value === "ask") return "i18n:govoplan-campaign.marks_the_message_for_review.d63beb24";
|
||||
if (value === "drop") return "i18n:govoplan-campaign.excludes_the_affected_message.73be963f";
|
||||
if (value === "continue") return "i18n:govoplan-campaign.continues_without_a_review_issue.99ab0684";
|
||||
if (value === "warn") return "i18n:govoplan-campaign.keeps_sending_possible_with_a_warning.66c84a54";
|
||||
return "i18n:govoplan-campaign.uses_the_configured_behavior.ea6e82a3";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user