Implement archive and unarchive functionality for proformas, including UI dialogs and logic for handling draft proformas.

This commit is contained in:
David Arranz 2026-07-29 18:23:57 +02:00
parent eb8cbd97f2
commit 1e0aadbfc6
17 changed files with 279 additions and 65 deletions

View File

@ -8,6 +8,7 @@
- Archived proformas remain available through `GET /proformas/:id`. - Archived proformas remain available through `GET /proformas/:id`.
- Deleted proformas remain excluded from every flow. - Deleted proformas remain excluded from every flow.
- Numbering is never reused and `document_series.next_number` is untouched. - Numbering is never reused and `document_series.next_number` is untouched.
- Archived `draft` proformas can be deleted directly without unarchiving.
## Endpoints ## Endpoints

View File

@ -155,3 +155,4 @@ Si devuelve filas:
- una proforma creada nace con `archived_at = NULL` - una proforma creada nace con `archived_at = NULL`
- el archivado posterior no altera `status` - el archivado posterior no altera `status`
- una proforma `draft` archivada puede borrarse sin desarchivarse antes

View File

@ -10,8 +10,9 @@ Definir el borrado funcional de proformas sin romper trazabilidad ni numeracion.
- `sent`, `approved`, `rejected` e `issued` devuelven conflicto - `sent`, `approved`, `rejected` e `issued` devuelven conflicto
- `rejected` no se borra; queda reservado para una futura operacion de archivado - `rejected` no se borra; queda reservado para una futura operacion de archivado
- el borrado es logico mediante `deleted_at` - el borrado es logico mediante `deleted_at`
- las proformas archivadas no se exponen para borrado en UI V1 - el borrado de `draft` no depende de `archived_at`
- si una proforma draft esta archivada, debe desarchivarse antes de borrarla - una proforma `draft` archivada puede borrarse directamente
- una proforma `rejected` archivada no puede borrarse
- la numeracion no se reutiliza - la numeracion no se reutiliza
- no se decrementa `document_series.next_number` - no se decrementa `document_series.next_number`
- no se borran fisicamente `proforma_items` ni `proforma_taxes` - no se borran fisicamente `proforma_items` ni `proforma_taxes`
@ -38,5 +39,6 @@ Definir el borrado funcional de proformas sin romper trazabilidad ni numeracion.
## UI ## UI
- la accion `Eliminar` solo debe mostrarse para proformas `draft` - la accion `Eliminar` solo debe mostrarse para proformas `draft`
- en la vista de archivadas, `Eliminar` tambien debe mostrarse para `draft`
- la confirmacion debe advertir que la referencia no se reutilizara - la confirmacion debe advertir que la referencia no se reutilizara
- en esta fase la accion solo esta disponible en el listado - en esta fase la accion esta disponible en el listado activo y en archivadas para `draft`

View File

@ -170,6 +170,7 @@ Preparar el esquema fisico para separar:
- `DELETE /proformas/:proforma_id` vuelve a estar operativo sobre persistencia V2 - `DELETE /proformas/:proforma_id` vuelve a estar operativo sobre persistencia V2
- el borrado es logico mediante `deleted_at` - el borrado es logico mediante `deleted_at`
- el archivado es logico mediante `archived_at` - el archivado es logico mediante `archived_at`
- el borrado de `draft` no depende de `archived_at`
- solo `draft` puede borrarse - solo `draft` puede borrarse
- `rejected` sigue fuera del alcance y queda reservado para archivado futuro - `rejected` sigue fuera del alcance y queda reservado para archivado futuro
- la validacion de borrado comprueba tambien `linked_invoice_id` y `issued_invoices.source_proforma_id` - la validacion de borrado comprueba tambien `linked_invoice_id` y `issued_invoices.source_proforma_id`

View File

@ -7,3 +7,8 @@ SELECT id, proforma_reference, status, archived_at, deleted_at
FROM proformas FROM proformas
WHERE archived_at IS NOT NULL WHERE archived_at IS NOT NULL
AND deleted_at IS NOT NULL; AND deleted_at IS NOT NULL;
SELECT id, proforma_reference, status, archived_at, deleted_at
FROM proformas
WHERE deleted_at IS NOT NULL
AND status <> 'draft';

View File

@ -24,7 +24,7 @@ export class ProformaDeleter implements IProformaDeleter {
id: UniqueID; id: UniqueID;
transaction: unknown; transaction: unknown;
}): Promise<Result<void, Error>> { }): Promise<Result<void, Error>> {
const proformaResult = await this.deps.repository.getByIdInCompany( const proformaResult = await this.deps.repository.getByIdIncludingArchivedInCompany(
params.companyId, params.companyId,
params.id, params.id,
params.transaction params.transaction

View File

@ -99,6 +99,9 @@
"archive": { "archive": {
"confirm_title": "Archive proforma", "confirm_title": "Archive proforma",
"confirm_description": "The proforma will be hidden from the main list but kept for historical lookup.", "confirm_description": "The proforma will be hidden from the main list but kept for historical lookup.",
"confirm": "Archive",
"cancel": "Cancel",
"submitting": "Archiving...",
"success_title": "Proforma archived", "success_title": "Proforma archived",
"success_description": "The proforma was archived successfully.", "success_description": "The proforma was archived successfully.",
"error_title": "The proforma could not be archived", "error_title": "The proforma could not be archived",
@ -108,6 +111,9 @@
"unarchive": { "unarchive": {
"confirm_title": "Unarchive proforma", "confirm_title": "Unarchive proforma",
"confirm_description": "The proforma will appear again in the main list.", "confirm_description": "The proforma will appear again in the main list.",
"confirm": "Unarchive",
"cancel": "Cancel",
"submitting": "Unarchiving...",
"success_title": "Proforma unarchived", "success_title": "Proforma unarchived",
"success_description": "The proforma was unarchived successfully.", "success_description": "The proforma was unarchived successfully.",
"error_title": "The proforma could not be unarchived", "error_title": "The proforma could not be unarchived",
@ -130,9 +136,12 @@
"delete_proforma_dialog": { "delete_proforma_dialog": {
"single_title": "Delete proforma", "single_title": "Delete proforma",
"single_description": "This proforma will be deleted. Its reference will not be reused.", "single_description": "This proforma will be deleted. Its reference will not be reused.",
"archived_single_title": "Delete archived proforma",
"archived_single_description": "The draft proforma will be deleted. Its reference will not be reused.",
"multiple_title": "Delete proformas", "multiple_title": "Delete proformas",
"multiple_description": "{{count}} draft proformas will be deleted. Their references will not be reused.", "multiple_description": "{{count}} draft proformas will be deleted. Their references will not be reused.",
"warning": "This action does not delete issued invoices and does not reuse numbering.", "warning": "This action does not delete issued invoices and does not reuse numbering.",
"archived_warning": "This action does not physically erase its data, but it will no longer be available in operational lists.",
"confirm_delete": "Confirm deletion", "confirm_delete": "Confirm deletion",
"deleting": "Deleting...", "deleting": "Deleting...",
"cancel": "Cancel", "cancel": "Cancel",

View File

@ -99,6 +99,9 @@
"archive": { "archive": {
"confirm_title": "Archivar proforma", "confirm_title": "Archivar proforma",
"confirm_description": "La proforma se ocultará del listado principal, pero seguirá conservada para consulta histórica.", "confirm_description": "La proforma se ocultará del listado principal, pero seguirá conservada para consulta histórica.",
"confirm": "Archivar",
"cancel": "Cancelar",
"submitting": "Archivando...",
"success_title": "Proforma archivada", "success_title": "Proforma archivada",
"success_description": "La proforma se ha archivado correctamente.", "success_description": "La proforma se ha archivado correctamente.",
"error_title": "No se pudo archivar la proforma", "error_title": "No se pudo archivar la proforma",
@ -108,6 +111,9 @@
"unarchive": { "unarchive": {
"confirm_title": "Desarchivar proforma", "confirm_title": "Desarchivar proforma",
"confirm_description": "La proforma volverá a aparecer en el listado principal.", "confirm_description": "La proforma volverá a aparecer en el listado principal.",
"confirm": "Desarchivar",
"cancel": "Cancelar",
"submitting": "Desarchivando...",
"success_title": "Proforma desarchivada", "success_title": "Proforma desarchivada",
"success_description": "La proforma se ha desarchivado correctamente.", "success_description": "La proforma se ha desarchivado correctamente.",
"error_title": "No se pudo desarchivar la proforma", "error_title": "No se pudo desarchivar la proforma",
@ -131,9 +137,12 @@
"delete_proforma_dialog": { "delete_proforma_dialog": {
"single_title": "Eliminar proforma", "single_title": "Eliminar proforma",
"single_description": "Se eliminará la proforma. Su referencia no se reutilizará.", "single_description": "Se eliminará la proforma. Su referencia no se reutilizará.",
"archived_single_title": "Eliminar proforma archivada",
"archived_single_description": "Se eliminará la proforma en borrador. Su referencia no se reutilizará.",
"multiple_title": "Eliminar proformas", "multiple_title": "Eliminar proformas",
"multiple_description": "Se eliminarán {{count}} proformas draft. Sus referencias no se reutilizarán.", "multiple_description": "Se eliminarán {{count}} proformas draft. Sus referencias no se reutilizarán.",
"warning": "Esta acción no elimina facturas emitidas ni reutiliza numeración.", "warning": "Esta acción no elimina facturas emitidas ni reutiliza numeración.",
"archived_warning": "Esta acción no borra físicamente sus datos, pero dejará de estar disponible en los listados operativos.",
"confirm_delete": "Confirmar eliminación", "confirm_delete": "Confirmar eliminación",
"deleting": "Eliminando...", "deleting": "Eliminando...",
"cancel": "Cancelar", "cancel": "Cancelar",

View File

@ -1,4 +1,5 @@
export interface DeleteProformaTarget { export interface DeleteProformaTarget {
id: string; id: string;
reference?: string; reference?: string;
isArchived?: boolean;
} }

View File

@ -34,9 +34,20 @@ export const DeleteProformaDialog = ({
const total = targets.length; const total = targets.length;
const isSingle = total === 1; const isSingle = total === 1;
const firstTarget = targets[0]; const firstTarget = targets[0];
const isArchivedContext = targets.some((target) => target.isArchived);
const titleKey = isArchivedContext
? "proformas.delete_proforma_dialog.archived_single_title"
: "proformas.delete_proforma_dialog.single_title";
const descriptionKey = isArchivedContext
? "proformas.delete_proforma_dialog.archived_single_description"
: "proformas.delete_proforma_dialog.single_description";
const warningKey = isArchivedContext
? "proformas.delete_proforma_dialog.archived_warning"
: "proformas.delete_proforma_dialog.warning";
const title = isSingle const title = isSingle
? t("proformas.delete_proforma_dialog.single_title", { ? t(titleKey, {
reference: getTargetLabel(firstTarget), reference: getTargetLabel(firstTarget),
}) })
: t("proformas.delete_proforma_dialog.multiple_title", { : t("proformas.delete_proforma_dialog.multiple_title", {
@ -44,7 +55,7 @@ export const DeleteProformaDialog = ({
}); });
const description = isSingle const description = isSingle
? t("proformas.delete_proforma_dialog.single_description") ? t(descriptionKey)
: t("proformas.delete_proforma_dialog.multiple_description", { : t("proformas.delete_proforma_dialog.multiple_description", {
count: total, count: total,
}); });
@ -64,7 +75,7 @@ export const DeleteProformaDialog = ({
</AlertDialogHeader> </AlertDialogHeader>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
{t("proformas.delete_proforma_dialog.warning")} {t(warningKey)}
</p> </p>
{total > 1 ? ( {total > 1 ? (

View File

@ -12,4 +12,5 @@ export const prepareDeleteProformaTargets = (
const mapToDeleteProformaTarget = (proforma: Proforma | ProformaListRow): DeleteProformaTarget => ({ const mapToDeleteProformaTarget = (proforma: Proforma | ProformaListRow): DeleteProformaTarget => ({
id: proforma.id, id: proforma.id,
reference: proforma.reference, reference: proforma.reference,
isArchived: proforma.isArchived,
}); });

View File

@ -1,6 +1,6 @@
import { showErrorToast, showSuccessToast } from "@repo/rdx-ui/helpers"; import { showErrorToast, showSuccessToast } from "@repo/rdx-ui/helpers";
import type { RightPanelMode } from "@repo/rdx-ui/hooks"; import type { RightPanelMode } from "@repo/rdx-ui/hooks";
import { useCallback } from "react"; import { useCallback, useState } from "react";
import { useSearchParams } from "react-router-dom"; import { useSearchParams } from "react-router-dom";
import { useTranslation } from "../../../i18n"; import { useTranslation } from "../../../i18n";
@ -46,73 +46,99 @@ export const useListProformasPageController = () => {
initialOpen: proformaId !== "", initialOpen: proformaId !== "",
}); });
const handleArchive = useCallback( const [archiveTarget, setArchiveTarget] = useState<ProformaListRow | null>(null);
async (proforma: ProformaListRow) => { const [unarchiveTarget, setUnarchiveTarget] = useState<ProformaListRow | null>(null);
const confirmed = window.confirm(
`${t("proformas.archive.confirm_title")}\n\n${t("proformas.archive.confirm_description")}` const openArchiveDialog = useCallback((proforma: ProformaListRow) => {
setArchiveTarget(proforma);
}, []);
const closeArchiveDialog = useCallback(() => {
if (archiveMutation.isPending) return;
setArchiveTarget(null);
}, [archiveMutation.isPending]);
const confirmArchive = useCallback(async () => {
if (!archiveTarget) {
return;
}
try {
await archiveMutation.mutateAsync({ proformaId: archiveTarget.id });
showSuccessToast(
t("proformas.archive.success_title"),
t("proformas.archive.success_description")
); );
setArchiveTarget(null);
if (!confirmed) return; } catch (error: unknown) {
const status = (error as { status?: number } | undefined)?.status;
try { showErrorToast(
await archiveMutation.mutateAsync({ proformaId: proforma.id }); t("proformas.archive.error_title"),
showSuccessToast( status === 409
t("proformas.archive.success_title"), ? t("proformas.archive.error_conflict_message")
t("proformas.archive.success_description") : t("proformas.archive.error_unknown_message")
);
} catch (error: unknown) {
console.error(error);
const status = (error as { status?: number } | undefined)?.status;
showErrorToast(
t("proformas.archive.error_title"),
status === 409
? t("proformas.archive.error_conflict_message")
: t("proformas.archive.error_unknown_message")
);
}
},
[archiveMutation, t]
);
const handleUnarchive = useCallback(
async (proforma: ProformaListRow) => {
const confirmed = window.confirm(
`${t("proformas.unarchive.confirm_title")}\n\n${t("proformas.unarchive.confirm_description")}`
); );
}
}, [archiveMutation, archiveTarget, t]);
if (!confirmed) return; const openUnarchiveDialog = useCallback((proforma: ProformaListRow) => {
setUnarchiveTarget(proforma);
}, []);
try { const closeUnarchiveDialog = useCallback(() => {
await unarchiveMutation.mutateAsync({ proformaId: proforma.id }); if (unarchiveMutation.isPending) return;
showSuccessToast( setUnarchiveTarget(null);
t("proformas.unarchive.success_title"), }, [unarchiveMutation.isPending]);
t("proformas.unarchive.success_description")
); const confirmUnarchive = useCallback(async () => {
} catch (error: unknown) { if (!unarchiveTarget) {
const status = (error as { status?: number } | undefined)?.status; return;
showErrorToast( }
t("proformas.unarchive.error_title"),
status === 409 try {
? t("proformas.unarchive.error_conflict_message") await unarchiveMutation.mutateAsync({ proformaId: unarchiveTarget.id });
: t("proformas.unarchive.error_unknown_message") showSuccessToast(
); t("proformas.unarchive.success_title"),
} t("proformas.unarchive.success_description")
}, );
[t, unarchiveMutation] setUnarchiveTarget(null);
); } catch (error: unknown) {
const status = (error as { status?: number } | undefined)?.status;
showErrorToast(
t("proformas.unarchive.error_title"),
status === 409
? t("proformas.unarchive.error_conflict_message")
: t("proformas.unarchive.error_unknown_message")
);
}
}, [t, unarchiveMutation, unarchiveTarget]);
return { return {
listCtrl, listCtrl,
panelCtrl, panelCtrl,
archiveDialogCtrl: {
open: archiveTarget !== null,
target: archiveTarget,
isSubmitting: archiveMutation.isPending,
openDialog: openArchiveDialog,
closeDialog: closeArchiveDialog,
confirmArchive,
},
deleteDialogCtrl, deleteDialogCtrl,
issueDialogCtrl, issueDialogCtrl,
changeStatusDialogCtrl, changeStatusDialogCtrl,
unarchiveDialogCtrl: {
open: unarchiveTarget !== null,
target: unarchiveTarget,
isSubmitting: unarchiveMutation.isPending,
openDialog: openUnarchiveDialog,
closeDialog: closeUnarchiveDialog,
confirmUnarchive,
},
downloadPDFCtrl, downloadPDFCtrl,
handleArchive,
handleDownloadPDF, handleDownloadPDF,
handleUnarchive,
pdfDownloadingId: downloadPDFCtrl.loadingId, pdfDownloadingId: downloadPDFCtrl.loadingId,
isPDFDownloading: downloadPDFCtrl.isLoading, isPDFDownloading: downloadPDFCtrl.isLoading,
}; };

View File

@ -457,7 +457,7 @@ export function useProformasGridColumns(
</TooltipProvider> </TooltipProvider>
{/* Eliminar */} {/* Eliminar */}
{isDraft && !proforma.isArchived && actionHandlers.onDeleteClick && ( {isDraft && actionHandlers.onDeleteClick && (
<TooltipProvider> <TooltipProvider>
<Tooltip> <Tooltip>
<TooltipTrigger <TooltipTrigger

View File

@ -0,0 +1,60 @@
import {
AlertDialog,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
Button,
Spinner,
} from "@repo/shadcn-ui/components";
import { useTranslation } from "../../../../i18n";
import type { ProformaListRow } from "../../../shared";
interface ArchiveProformaDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
target: ProformaListRow | null;
isSubmitting: boolean;
onConfirm: () => void;
}
export const ArchiveProformaDialog = ({
open,
onOpenChange,
target,
isSubmitting,
onConfirm,
}: ArchiveProformaDialogProps) => {
const { t } = useTranslation();
return (
<AlertDialog onOpenChange={onOpenChange} open={open}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{t("proformas.archive.confirm_title")}</AlertDialogTitle>
<AlertDialogDescription>
{t("proformas.archive.confirm_description")}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<Button disabled={isSubmitting} onClick={() => onOpenChange(false)} variant="outline">
{t("proformas.archive.cancel")}
</Button>
<Button disabled={isSubmitting || !target} onClick={onConfirm}>
{isSubmitting ? (
<>
<Spinner aria-hidden className="mr-2 size-4" />
{t("proformas.archive.submitting")}
</>
) : (
t("proformas.archive.confirm")
)}
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
};

View File

@ -1 +1,3 @@
export * from "./archive-proforma-dialog";
export * from "./proforma-status-badge"; export * from "./proforma-status-badge";
export * from "./unarchive-proforma-dialog";

View File

@ -0,0 +1,60 @@
import {
AlertDialog,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
Button,
Spinner,
} from "@repo/shadcn-ui/components";
import { useTranslation } from "../../../../i18n";
import type { ProformaListRow } from "../../../shared";
interface UnarchiveProformaDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
target: ProformaListRow | null;
isSubmitting: boolean;
onConfirm: () => void;
}
export const UnarchiveProformaDialog = ({
open,
onOpenChange,
target,
isSubmitting,
onConfirm,
}: UnarchiveProformaDialogProps) => {
const { t } = useTranslation();
return (
<AlertDialog onOpenChange={onOpenChange} open={open}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{t("proformas.unarchive.confirm_title")}</AlertDialogTitle>
<AlertDialogDescription>
{t("proformas.unarchive.confirm_description")}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<Button disabled={isSubmitting} onClick={() => onOpenChange(false)} variant="outline">
{t("proformas.unarchive.cancel")}
</Button>
<Button disabled={isSubmitting || !target} onClick={onConfirm}>
{isSubmitting ? (
<>
<Spinner aria-hidden className="mr-2 size-4" />
{t("proformas.unarchive.submitting")}
</>
) : (
t("proformas.unarchive.confirm")
)}
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
};

View File

@ -34,6 +34,7 @@ import { prepareIssueProformaTarget } from "../../../issue-proforma/utils";
import type { ProformaListRow } from "../../../shared"; import type { ProformaListRow } from "../../../shared";
import { useListProformasPageController } from "../../controllers"; import { useListProformasPageController } from "../../controllers";
import { ProformaSummaryPanel, ProformasGrid, useProformasGridColumns } from "../blocks"; import { ProformaSummaryPanel, ProformasGrid, useProformasGridColumns } from "../blocks";
import { ArchiveProformaDialog, UnarchiveProformaDialog } from "../components";
import { ProformaStatusBadge } from "../components"; import { ProformaStatusBadge } from "../components";
export const ListProformasPage = () => { export const ListProformasPage = () => {
@ -50,9 +51,9 @@ export const ListProformasPage = () => {
deleteDialogCtrl, deleteDialogCtrl,
issueDialogCtrl, issueDialogCtrl,
changeStatusDialogCtrl, changeStatusDialogCtrl,
handleArchive, archiveDialogCtrl,
handleDownloadPDF, handleDownloadPDF,
handleUnarchive, unarchiveDialogCtrl,
isPDFDownloading: isPdfDownloading, isPDFDownloading: isPdfDownloading,
pdfDownloadingId, pdfDownloadingId,
} = useListProformasPageController(); } = useListProformasPageController();
@ -70,12 +71,12 @@ export const ListProformasPage = () => {
onEditClick: (proforma) => handleEditClick(proforma.id), onEditClick: (proforma) => handleEditClick(proforma.id),
onIssueClick: (proformaRow) => onIssueClick: (proformaRow) =>
issueDialogCtrl.openDialog(prepareIssueProformaTarget(proformaRow)), issueDialogCtrl.openDialog(prepareIssueProformaTarget(proformaRow)),
onArchiveClick: handleArchive, onArchiveClick: archiveDialogCtrl.openDialog,
onDeleteClick: (proformaRow: ProformaListRow) => onDeleteClick: (proformaRow: ProformaListRow) =>
deleteDialogCtrl.openDialog(prepareDeleteProformaTargets(proformaRow)), deleteDialogCtrl.openDialog(prepareDeleteProformaTargets(proformaRow)),
onChangeStatusClick: (proforma) => onChangeStatusClick: (proforma) =>
changeStatusDialogCtrl.openDialog(prepareChangeProformaStatusTargets(proforma)), changeStatusDialogCtrl.openDialog(prepareChangeProformaStatusTargets(proforma)),
onUnarchiveClick: handleUnarchive, onUnarchiveClick: unarchiveDialogCtrl.openDialog,
onDownloadPdf: handleDownloadPDF, onDownloadPdf: handleDownloadPDF,
pdfDownloadingId, pdfDownloadingId,
@ -360,6 +361,30 @@ export const ListProformasPage = () => {
open={deleteDialogCtrl.open} open={deleteDialogCtrl.open}
targets={deleteDialogCtrl.targets} targets={deleteDialogCtrl.targets}
/> />
<ArchiveProformaDialog
isSubmitting={archiveDialogCtrl.isSubmitting}
onConfirm={archiveDialogCtrl.confirmArchive}
onOpenChange={(open) => {
if (!open) {
archiveDialogCtrl.closeDialog();
}
}}
open={archiveDialogCtrl.open}
target={archiveDialogCtrl.target}
/>
<UnarchiveProformaDialog
isSubmitting={unarchiveDialogCtrl.isSubmitting}
onConfirm={unarchiveDialogCtrl.confirmUnarchive}
onOpenChange={(open) => {
if (!open) {
unarchiveDialogCtrl.closeDialog();
}
}}
open={unarchiveDialogCtrl.open}
target={unarchiveDialogCtrl.target}
/>
</> </>
</div> </div>
); );