import { useState } from "react"; import type { ApiSettings } from "../../../types"; import { Button } from "@govoplan/core-webui"; import { ConfirmDialog } from "@govoplan/core-webui"; import { DismissibleAlert } from "@govoplan/core-webui"; import { forkCampaignVersion, lockCampaignVersionPermanently, unlockCampaignVersionUserLock, unlockCampaignVersionValidation, type CampaignVersionDetail, type CampaignVersionListItem } from "../../../api/campaigns"; import { canUnlockValidationVersion, formatDateTime, isFinalLockedVersion, isHistoricalCampaignVersion, isPermanentUserLockedVersion, isTemporaryUserLockedVersion } from "../utils/campaignView"; type LockedVersionNoticeProps = { settings: ApiSettings; campaignId: string; version: CampaignVersionDetail | CampaignVersionListItem | null; currentVersionId?: string | null; reload: () => Promise; message?: string; }; type ConfirmAction = "unlock-validation" | "unlock-user" | "permanent" | null; export default function LockedVersionNotice({ settings, campaignId, version, currentVersionId, reload, message }: LockedVersionNoticeProps) { const [busy, setBusy] = useState(false); const [localError, setLocalError] = useState(""); const [localMessage, setLocalMessage] = useState(""); const [confirmAction, setConfirmAction] = useState(null); const historicalVersion = isHistoricalCampaignVersion(version, currentVersionId); const validationLock = !historicalVersion && canUnlockValidationVersion(version); const temporaryUserLock = !historicalVersion && isTemporaryUserLockedVersion(version); const permanentUserLock = isPermanentUserLockedVersion(version); const finalLock = isFinalLockedVersion(version); const canCreateEditableCopy = !historicalVersion && (permanentUserLock || finalLock); const presentation = lockPresentation(version, { historicalVersion, validationLock, temporaryUserLock, permanentUserLock, finalLock }); async function runAction(action: Exclude) { if (!version || busy) return; setBusy(true); setLocalError(""); setLocalMessage(""); try { if (action === "unlock-validation") { await unlockCampaignVersionValidation(settings, campaignId, version.id); setLocalMessage("i18n:govoplan-campaign.validation_lock_removed_validation_build_and_gen.ea26975f"); } else if (action === "unlock-user") { await unlockCampaignVersionUserLock(settings, campaignId, version.id); setLocalMessage("i18n:govoplan-campaign.temporary_user_lock_removed_the_version_is_edita.0ca4c587"); } else { await lockCampaignVersionPermanently(settings, campaignId, version.id); setLocalMessage("i18n:govoplan-campaign.version_permanently_locked_future_changes_requir.fd718a84"); } await reload(); } catch (err) { setLocalError(err instanceof Error ? err.message : String(err)); } finally { setBusy(false); } } async function createEditableCopy() { if (!version || busy) return; setBusy(true); setLocalError(""); setLocalMessage(""); try { const result = await forkCampaignVersion(settings, campaignId, version.id, { current_flow: "manual", current_step: version.current_step ?? null }); setLocalMessage(`Created editable version #${result.version.version_number}.`); await reload(); } catch (err) { setLocalError(err instanceof Error ? err.message : String(err)); } finally { setBusy(false); } } return (
{presentation.title}{" "} {presentation.description} {message && {message}} {presentation.info && {presentation.info}} {localMessage && {localMessage}} {localError && {localError}}
{validationLock && } {temporaryUserLock && <> } {canCreateEditableCopy && }
setConfirmAction(null)} onConfirm={() => { const action = confirmAction; setConfirmAction(null); if (action) void runAction(action); }} />
); } type LockFlags = { historicalVersion: boolean; validationLock: boolean; temporaryUserLock: boolean; permanentUserLock: boolean; finalLock: boolean; }; function lockPresentation( version: CampaignVersionDetail | CampaignVersionListItem | null, flags: LockFlags) : {kind: string;title: string;description: string;info: string;} { if (flags.historicalVersion) { return { kind: "historical", title: "i18n:govoplan-campaign.historical_version.adac5dba", description: "i18n:govoplan-campaign.this_version_is_review_only_only_the_campaign_s_.9e68f6a0", info: `Version #${version?.version_number ?? "—"}.` }; } if (flags.temporaryUserLock) { return { kind: "temporary-user", title: "i18n:govoplan-campaign.temporarily_locked_version.696f85e3", description: "i18n:govoplan-campaign.campaign_data_is_read_only_but_an_authorized_use.f2e513b1", info: version?.user_locked_at ? `Locked ${formatDateTime(version.user_locked_at)}.` : "" }; } if (flags.permanentUserLock) { return { kind: "permanent-user", title: "i18n:govoplan-campaign.permanently_locked_version.248c2eeb", description: "i18n:govoplan-campaign.this_user_requested_snapshot_cannot_be_unlocked_.9e91210c", info: version?.user_locked_at || version?.published_at ? `Locked ${formatDateTime(version.user_locked_at ?? version.published_at)}.` : "" }; } if (flags.validationLock) { return { kind: "validation", title: "i18n:govoplan-campaign.temporarily_locked_after_validation.c558ce56", description: "i18n:govoplan-campaign.this_protects_the_validated_build_input_unlockin.ed890772", info: version?.locked_at ? `Validated ${formatDateTime(version.locked_at)}.` : "" }; } if (flags.finalLock) { return { kind: "delivery", title: "i18n:govoplan-campaign.permanently_locked_delivery_snapshot.c3670daa", description: "i18n:govoplan-campaign.delivery_has_started_or_the_version_is_in_a_fina.571e86ed", info: version?.locked_at ? `Locked ${formatDateTime(version.locked_at)}.` : "" }; } return { kind: "other", title: "i18n:govoplan-campaign.locked_version.e755b179", description: "i18n:govoplan-campaign.this_version_is_read_only_create_an_editable_cop.9e0afd29", info: version?.locked_at ? `Locked ${formatDateTime(version.locked_at)}.` : "" }; } function confirmDialogTitle(action: ConfirmAction): string { if (action === "unlock-validation") return "i18n:govoplan-campaign.unlock_validation.e3066247"; if (action === "unlock-user") return "i18n:govoplan-campaign.unlock_temporary_lock.8a3ad468"; if (action === "permanent") return "i18n:govoplan-campaign.lock_permanently.24d5b74d"; return "i18n:govoplan-campaign.confirm_action.50649c5c"; } function confirmDialogMessage(action: ConfirmAction): string { if (action === "unlock-validation") { return "i18n:govoplan-campaign.this_makes_the_version_editable_and_clears_valid.89a6cd1b"; } if (action === "unlock-user") { return "i18n:govoplan-campaign.this_removes_the_reversible_user_lock_campaign_d.fcf8cb1d"; } if (action === "permanent") { return "i18n:govoplan-campaign.this_lock_cannot_be_removed_by_any_role_the_vers.3054b076"; } return "i18n:govoplan-campaign.continue.4e6302ed"; } function confirmDialogLabel(action: ConfirmAction): string { if (action === "unlock-validation") return "i18n:govoplan-campaign.unlock_validation.f01952b6"; if (action === "unlock-user") return "i18n:govoplan-campaign.unlock.1526a17e"; if (action === "permanent") return "i18n:govoplan-campaign.lock_permanently.cc0ce9e7"; return "i18n:govoplan-campaign.confirm.04a21221"; }