Skip to content

Commit

Permalink
extends csv function
Browse files Browse the repository at this point in the history
  • Loading branch information
yhabib committed Nov 22, 2024
1 parent 9979071 commit fa8bb37
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 3 deletions.
38 changes: 35 additions & 3 deletions frontend/src/lib/utils/export-to-csv.utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { isNullish } from "@dfinity/utils";

export type Metadata = {
label: string;
value: string;
};

export type CsvHeader<T> = {
id: keyof T;
label: string;
Expand All @@ -8,6 +13,7 @@ export type CsvHeader<T> = {
interface CsvBaseConfig<T> {
data: T[];
headers: CsvHeader<T>[];
metadata?: Metadata[];
}

interface CsvFileConfig<T> extends CsvBaseConfig<T> {
Expand Down Expand Up @@ -39,17 +45,43 @@ const escapeCsvValue = (value: unknown): string => {
return stringValue;
};

export const convertToCsv = <T>({ data, headers }: CsvBaseConfig<T>) => {
export const convertToCsv = <T>({
data,
headers,
metadata = [],
}: CsvBaseConfig<T>) => {
if (headers.length === 0) return "";

const PAD_LEFT_WHEN_METADATA_PRESENT = 2;
const csvRows: string[] = [];
let padLeft = 0;

if (metadata.length > 0) {
const sanitizedMetadata = metadata.map(({ label, value }) => ({
label: escapeCsvValue(label),
value: escapeCsvValue(value),
}));

const metadataRow = sanitizedMetadata
.map(({ label, value }) => `${label},${value}`)
.join("\n");
csvRows.push(metadataRow);

// Add an empty row to separate metadata from data
csvRows.push("");

padLeft = PAD_LEFT_WHEN_METADATA_PRESENT;
}

const emptyPrefix = Array(padLeft).fill("");
const sanitizedHeaders = headers
.map(({ label }) => label)
.map((header) => escapeCsvValue(header));
const csvRows = [sanitizedHeaders.join(",")];
csvRows.push([...emptyPrefix, ...sanitizedHeaders].join(","));

for (const row of data) {
const values = headers.map((header) => escapeCsvValue(row[header.id]));
csvRows.push(values.join(","));
csvRows.push([...emptyPrefix, ...values].join(","));
}

return csvRows.join("\n");
Expand Down
20 changes: 20 additions & 0 deletions frontend/src/tests/lib/utils/export-to-csv.utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,26 @@ describe("Export to Csv", () => {
const expected = 'Full Name,Age\n"Peter\nParker",24\nJane Doe,25';
expect(convertToCsv({ data, headers })).toBe(expected);
});

it("should add metadata to the CSV file", () => {
const data: TestPersonData[] = [{ name: "John", age: 30 }];
const headers: CsvHeader<TestPersonData>[] = [
{ id: "name", label: "name" },
{ id: "age", label: "age" },
];
const metadata = [
{
label: "Title",
value: "This is a test file",
},{
label: 'Export Date',
value: new Date('2021-10-10').toLocaleString()
}
];
const expected = `Title,This is a test file\nExport Date,"10/10/2021, 2:00:00 AM"\n\n,,name,age\n,,John,30`;

expect(convertToCsv({ data, headers, metadata })).toBe(expected);
});
});

describe("downloadCSV", () => {
Expand Down

0 comments on commit fa8bb37

Please sign in to comment.