mirror of
https://github.com/willchen96/mike.git
synced 2026-06-10 20:35:12 +02:00
85 lines
2.5 KiB
TypeScript
85 lines
2.5 KiB
TypeScript
"use client";
|
|
|
|
import ExcelJS from "exceljs";
|
|
import type {
|
|
ColumnConfig,
|
|
Document,
|
|
TabularCell,
|
|
} from "../shared/types";
|
|
import { preprocessCitations } from "./citation-utils";
|
|
|
|
function formatCellForExport(cell: TabularCell | undefined): string {
|
|
if (!cell) return "";
|
|
if (cell.status === "pending" || cell.status === "generating") return "";
|
|
if (cell.status === "error") return "Error";
|
|
const summary = cell.content?.summary;
|
|
if (!summary) return "";
|
|
const { processed } = preprocessCitations(summary);
|
|
return processed
|
|
.replace(/§\d+§/g, "")
|
|
.replace(/\[\[([^\]]+)\]\]/g, "$1")
|
|
.replace(/[ \t]+/g, " ")
|
|
.trim();
|
|
}
|
|
|
|
function sanitizeFilename(name: string): string {
|
|
return (
|
|
name
|
|
.replace(/[\\/:*?"<>|]/g, "")
|
|
.replace(/\s+/g, " ")
|
|
.trim()
|
|
.slice(0, 80) || "Tabular Review"
|
|
);
|
|
}
|
|
|
|
export async function exportTabularReviewToExcel(params: {
|
|
reviewTitle: string;
|
|
columns: ColumnConfig[];
|
|
documents: Document[];
|
|
cells: TabularCell[];
|
|
}) {
|
|
const { reviewTitle, columns, documents, cells } = params;
|
|
|
|
const sortedCols = [...columns].sort((a, b) => a.index - b.index);
|
|
const cellMap = new Map<string, TabularCell>();
|
|
for (const c of cells) cellMap.set(`${c.document_id}:${c.column_index}`, c);
|
|
|
|
const wb = new ExcelJS.Workbook();
|
|
const ws = wb.addWorksheet("Review");
|
|
|
|
ws.columns = [
|
|
{ header: "Document", width: 40 },
|
|
...sortedCols.map((c) => ({ header: c.name, width: 40 })),
|
|
];
|
|
|
|
const headerRow = ws.getRow(1);
|
|
headerRow.font = { bold: true };
|
|
headerRow.alignment = { vertical: "middle" };
|
|
headerRow.fill = {
|
|
type: "pattern",
|
|
pattern: "solid",
|
|
fgColor: { argb: "FFF3F4F6" },
|
|
};
|
|
|
|
for (const doc of documents) {
|
|
const row: string[] = [doc.filename];
|
|
for (const col of sortedCols) {
|
|
row.push(formatCellForExport(cellMap.get(`${doc.id}:${col.index}`)));
|
|
}
|
|
const excelRow = ws.addRow(row);
|
|
excelRow.alignment = { vertical: "top", wrapText: true };
|
|
}
|
|
|
|
const buf = await wb.xlsx.writeBuffer();
|
|
const blob = new Blob([buf], {
|
|
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
});
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement("a");
|
|
a.href = url;
|
|
a.download = `${sanitizeFilename(reviewTitle)}.xlsx`;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
a.remove();
|
|
URL.revokeObjectURL(url);
|
|
}
|