wip: ops admin panel + migration sync + crud/rbac phase-5 snapshot
Working-tree checkpoint of in-progress work carried across prior sessions on the feat/crud-rbac branch, committed so it lands on the remote alongside the CI changes. - Operaciones admin panel: apps/api/src/ops (ingest upload, backup / restore / re-import jobs) wired into app.module + RBAC abilities, and the apps/web/src/app/operaciones page. docker-compose gets INGEST_DIR / BACKUP_DIR volumes; .gitignore excludes migration/ingest + backups. - migration/sync.py plus transform_*.py / run_all / config / dbenv / blob_extract adjustments for the additive sync path. - crud/rbac phase-5 web bits: AppShell, api/labels/types libs, globals. - schema.prisma + PLAN/RESUME doc updates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -266,6 +266,48 @@ export function bankSourceLabel(source: string | null | undefined): string {
|
||||
return BANK_SOURCE_LABELS[source] ?? source;
|
||||
}
|
||||
|
||||
// ----- DB operations (admin) -----
|
||||
|
||||
export const OPS_KIND_LABELS: Record<string, string> = {
|
||||
BACKUP: "Respaldo",
|
||||
RESTORE: "Restauración",
|
||||
REIMPORT: "Reimportación",
|
||||
SYNC: "Sincronización",
|
||||
};
|
||||
|
||||
export const OPS_STATUS_LABELS: Record<string, string> = {
|
||||
RUNNING: "En curso",
|
||||
SUCCESS: "Completado",
|
||||
FAILED: "Con error",
|
||||
};
|
||||
|
||||
/** Bytes → human size (KB/MB/GB), es-MX formatting. */
|
||||
export function formatBytes(bytes: number | null | undefined): string {
|
||||
if (bytes === null || bytes === undefined) return "—";
|
||||
if (bytes < 1024) return `${bytes} B`;
|
||||
const units = ["KB", "MB", "GB"];
|
||||
let n = bytes / 1024;
|
||||
let i = 0;
|
||||
while (n >= 1024 && i < units.length - 1) {
|
||||
n /= 1024;
|
||||
i++;
|
||||
}
|
||||
return `${n.toLocaleString("es-MX", { maximumFractionDigits: 1 })} ${units[i]}`;
|
||||
}
|
||||
|
||||
export function formatDateTime(iso: string | null | undefined): string {
|
||||
if (!iso) return "—";
|
||||
const d = new Date(iso);
|
||||
if (Number.isNaN(d.getTime())) return "—";
|
||||
return d.toLocaleString("es-MX", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
}
|
||||
|
||||
export const MONTH_NAMES = [
|
||||
"Enero",
|
||||
"Febrero",
|
||||
|
||||
Reference in New Issue
Block a user