Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"html2canvas": "^1.4.1",
"i18next": "^23.11.5",
"js-sha256": "^0.11.0",
"jschardet": "^3.1.4",
"jszip": "^3.10.1",
"lodash": "^4.17.21",
"lucide-react": "^0.399.0",
Expand Down
34 changes: 25 additions & 9 deletions frontend/src/modules/core/helpers/files.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import JSZip from "jszip";
import jschardet from "jschardet";

export const FASTA_EXTENSIONS = [".fa", ".mpfa", ".fna", ".fsa", ".fasta"];

Expand Down Expand Up @@ -34,15 +35,30 @@ export const downloadFileFromUrl = (url: string) => {
* @param file - the file to read
* @returns a promise that resolves with the file's text content
*/
export const readFileAsText = (file: Blob): Promise<string> => {
export const readFileAsText = (file: File | Blob): Promise<string> => {
return new Promise((resolve, reject) => {
try {
const reader = new FileReader();
reader.readAsText(file);
reader.onloadend = () => resolve(reader.result as string);
reader.onload = () => {
const arrayBuffer = reader.result as ArrayBuffer;
const uint8Array = new Uint8Array(arrayBuffer);
// Convert Uint8Array to binary string for encoding detection
const binaryString = Array.from(uint8Array)
.map(byte => String.fromCharCode(byte))
.join("");
// Detect encoding as export sources are not deterministic
const detected = jschardet.detect(binaryString);
const encoding = detected.encoding || "UTF-8";
// Decode using TextDecoder with detected encoding
const decoder = new TextDecoder(encoding);
const text = decoder.decode(uint8Array);
resolve(text);
};
reader.onerror = reject;
reader.readAsArrayBuffer(file);
} catch (error) {
console.log(error)
console.log(error);
reject(error);
}
});
};
Expand All @@ -53,7 +69,7 @@ export const readFileAsText = (file: Blob): Promise<string> => {
* @returns a promise that resolves with an array of the files' text content
*/
export const readFilesAsText = (files: File[]): Promise<string[]> => {
const filePromises = files.map((file) => readFileAsText(file));
const filePromises = files.map(file => readFileAsText(file));
return Promise.all(filePromises);
};

Expand Down Expand Up @@ -86,7 +102,7 @@ export const formatData = (
// for bacterial uploads:
// fasta file name contains fasta id
// content contains assembly
fastaSequencesArray.push({fastaId: file.filename.split(".")[0], sequence: file.content});
fastaSequencesArray.push({ fastaId: file.filename.split(".")[0], sequence: file.content });
}
}
return fastaSequencesArray;
Expand All @@ -99,7 +115,7 @@ export const formatData = (
} else {
let rows = Object.values(fileReaderResult)[0].split("\n");
// filter empty lines to prevent empty cells
rows = rows.filter((line) => line !== "");
rows = rows.filter(line => line !== "");
const columns: string[] = rows[0]
.replace(/["'\n]/g, "")
.split(";")
Expand All @@ -118,7 +134,7 @@ export const formatData = (
});
rowData.push(rowObject);
}
return {columns: columns, rows: rowData};
return { columns: columns, rows: rowData };
}
}
};
Expand All @@ -143,7 +159,7 @@ export const collectFastaIdsAndSequences = (fastaSequences: Array<string>) => {
}

if (fastaId) {
fastaSequencesArray.push({fastaId: fastaId, sequence: genome});
fastaSequencesArray.push({ fastaId: fastaId, sequence: genome });
}
}
return fastaSequencesArray;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/modules/core/tests/unit/helpers/files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ describe("FilesHelper", () => {
window.URL.createObjectURL = vi.fn(() => ":object_url:");
// mock methods that are not yet supported by jsdom
const spyOnCreateElement = vi.spyOn(document, "createElement").mockImplementation(() => link);
const spyOnLinkClick = vi.spyOn(link, "click");
const spyOnLinkClick = vi.spyOn(link, "click").mockImplementation(() => {}); // Prevent actual navigation
downloadFile(blob, ":file_name:");

expect(spyOnCreateElement).toHaveBeenCalledOnce();
Expand Down