Skip to content

Commit

Permalink
feat: add i18n for headers of exported HTML
Browse files Browse the repository at this point in the history
Fixes #24
  • Loading branch information
prinsss committed Jun 16, 2024
1 parent 1c7f970 commit 59ca0fe
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 14 deletions.
11 changes: 11 additions & 0 deletions src/components/modals/export-data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,22 @@ export function ExportDataModal<T>({ title, table, show, onClose }: ExportDataMo
setCurrentProgress(allRecords.length);
}

// Prepare header translations for the exported data.
const headerTranslations = table
.getAllColumns()
.reduce<Record<string, string>>((acc, column) => {
const key = column.columnDef.meta?.exportKey || column.id;
const header = column.columnDef.meta?.exportHeader || column.id;
acc[key] = t(header as TranslationKey);
return acc;
}, {});

// Convert data to selected format and download it.
await exportData(
allRecords,
selectedFormat,
`twitter-${title}-${Date.now()}.${selectedFormat.toLowerCase()}`,
headerTranslations,
);
setLoading(false);
};
Expand Down
39 changes: 25 additions & 14 deletions src/utils/exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,18 @@ export function saveFile(filename: string, content: string, prependBOM: boolean

/**
* Export data and download as a file.
*
* @param data Data list to export.
* @param format Export format. (JSON, HTML, CSV)
* @param filename Filename to save.
* @param translations Translations for headers.
*/
export async function exportData(data: DataType[], format: ExportFormatType, filename: string) {
export async function exportData(
data: DataType[],
format: ExportFormatType,
filename: string,
translations: Record<string, string>,
) {
try {
let content = '';
let prependBOM = false;
Expand All @@ -51,7 +61,7 @@ export async function exportData(data: DataType[], format: ExportFormatType, fil
content = await jsonExporter(data);
break;
case EXPORT_FORMAT.HTML:
content = await htmlExporter(data);
content = await htmlExporter(data, translations);
break;
case EXPORT_FORMAT.CSV:
prependBOM = true;
Expand All @@ -68,16 +78,17 @@ export async function jsonExporter(data: DataType[]) {
return JSON.stringify(data, undefined, ' ');
}

export async function htmlExporter(data: DataType[]) {
export async function htmlExporter(data: DataType[], translations: Record<string, string>) {
const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');

const headers = Object.keys(data[0] ?? {});
// The keys of the first row are translated and used as headers.
const exportKeys = Object.keys(data[0] ?? {});
const headerRow = document.createElement('tr');
for (const header of headers) {
for (const exportKey of exportKeys) {
const th = document.createElement('th');
th.textContent = header;
th.textContent = translations[exportKey] ?? exportKey;
headerRow.appendChild(th);
}

Expand All @@ -87,17 +98,17 @@ export async function htmlExporter(data: DataType[]) {

for (const row of data) {
const tr = document.createElement('tr');
for (const header of headers) {
for (const exportKey of exportKeys) {
const td = document.createElement('td');
const value = row[header];
const value = row[exportKey];

if (header === 'profile_image_url' || header === 'profile_banner_url') {
if (exportKey === 'profile_image_url' || exportKey === 'profile_banner_url') {
const img = document.createElement('img');
img.src = value;
img.width = 50;
td.innerHTML = '';
td.appendChild(img);
} else if (header === 'media') {
} else if (exportKey === 'media') {
if (value?.length > 0) {
for (const media of value) {
const img = document.createElement('img');
Expand All @@ -111,13 +122,13 @@ export async function htmlExporter(data: DataType[]) {
td.appendChild(link);
}
}
} else if (header === 'full_text' || header === 'description') {
} else if (exportKey === 'full_text' || exportKey === 'description') {
const p = document.createElement('p');
p.innerHTML = value;
p.style.whiteSpace = 'pre-wrap';
p.style.maxWidth = '640px';
td.appendChild(p);
} else if (header === 'metadata') {
} else if (exportKey === 'metadata') {
const details = document.createElement('details');
const summary = document.createElement('summary');
summary.textContent = 'Expand';
Expand All @@ -126,14 +137,14 @@ export async function htmlExporter(data: DataType[]) {
pre.textContent = JSON.stringify(value, undefined, ' ');
details.appendChild(pre);
td.appendChild(details);
} else if (header === 'url') {
} else if (exportKey === 'url') {
const link = document.createElement('a');
link.href = value;
link.target = '_blank';
link.textContent = value;
td.appendChild(link);
} else {
td.textContent = typeof value === 'string' ? value : JSON.stringify(row[header]);
td.textContent = typeof value === 'string' ? value : JSON.stringify(row[exportKey]);
}

tr.appendChild(td);
Expand Down

0 comments on commit 59ca0fe

Please sign in to comment.