Files
periscope/frontend/src/lib/report-export.ts
T
micheleandCursor e4fd6c3849 Ship Sprint 0 CAD foundations so findings, KiCad hierarchy, BOM match, eval, and optional PCB ingest have a stable contract.
Extend Finding with rule_id/net/pins, flatten multi-sheet .kicad_sch, flag MPN mismatches, score simple_project, and parse .kicad_pcb without running layout DRC.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-10 21:54:37 +02:00

67 lines
1.8 KiB
TypeScript

import * as XLSX from "xlsx";
import type { DesignGraph, Finding, ValidationReport } from "./types";
import { sortFindings } from "./utils";
const HEADER = [
"Designator",
"MPN",
"ID",
"Severity",
"Title",
"Description",
"Recommendation",
"Source",
"Net",
"Pins",
"Rule",
];
// Column widths (in characters), aligned with HEADER order.
const COL_WIDTHS = [12, 20, 12, 10, 44, 60, 50, 24, 16, 16, 14];
// Fold the datasheet reference + page number into a single cell, mirroring the
// finding card's reference button + "Automated check" tag logic.
function formatSource(f: Finding): string {
if (f.source && f.source !== "review") return "Automated check";
const ds = f.source_designator || f.designator;
return `${ds} datasheet` + (f.source_page ? ` p.${f.source_page}` : "");
}
function slugify(name: string): string {
return name.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "report";
}
/**
* Build and download the validation report as an .xlsx workbook (client-side).
* One "Findings" sheet, one row per finding, sorted ERROR -> WARNING -> INFO.
*/
export function exportReportToExcel(
report: ValidationReport,
graph: DesignGraph,
projectName?: string,
): void {
const rows = sortFindings(report.findings).map((f) => [
f.designator,
f.mpn || graph.components[f.designator]?.mpn || "",
f.finding_id ?? "",
f.status,
f.finding,
f.why ?? "",
f.recommendation ?? "",
formatSource(f),
f.net ?? "",
(f.pins ?? []).join(", "),
f.rule_id ?? "",
]);
const ws = XLSX.utils.aoa_to_sheet([HEADER, ...rows]);
ws["!cols"] = COL_WIDTHS.map((wch) => ({ wch }));
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Findings");
const filename = `${slugify(projectName || report.project || "report")}-findings.xlsx`;
XLSX.writeFile(wb, filename);
}