auspice
Version:
Web app for visualizing pathogen evolution
65 lines (58 loc) • 2.31 kB
text/typescript
import { errorNotification, successNotification } from "../notifications";
import { fileTypeIsCSVLike, fileTypeIsJson } from "./constants";
import { handleCsvLikeDroppedFile } from "./parseCsv";
import { handleNodeDataJsonFile } from "./parseNodeDataJson";
import { updateMetadata, SUCCESS } from "../updateMetadata/updateMetadata";
import { AppDispatch, RootState } from "../../store";
import { NewMetadata } from "../updateMetadata/updateMetadata.types"
/**
* A thunk to handle dropped files and take the appropriate action.
* Exported for use by auspice.us
*/
export const handleFilesDropped = (files: FileList) => async (dispatch: AppDispatch, getState: () => RootState): Promise<void> => {
const { tree, treeToo } = getState();
const nodeNames = _collectNodeNames(tree, treeToo);
for (const file of files) {
try {
let newMetadata: NewMetadata;
if (fileTypeIsCSVLike(file)) {
newMetadata = await handleCsvLikeDroppedFile(file, nodeNames);
} else if (fileTypeIsJson(file)) {
newMetadata = await handleNodeDataJsonFile(file, nodeNames);
} else {
// console.error("[internal logic error] unhandled file type");
dispatch(errorNotification({
message: `Parsing of '${file.name}' failed`,
details: `Unhandled file type`,
}))
continue;
}
const result = dispatch(updateMetadata(newMetadata));
if (result===SUCCESS) {
dispatch(successNotification({
message: `Adding metadata from ${file.name}`,
details: `n = ${Object.keys(newMetadata.attributes).length} fields(s)`,
}));
} else {
throw Error(result);
}
} catch (err) {
console.error(err)
dispatch(errorNotification({
message: `Parsing of '${file.name}' failed`,
details: err instanceof Error ? err.message : String(err),
}))
}
}
};
export default handleFilesDropped;
/**
* Return a set of all node names found across both trees
*/
function _collectNodeNames(tree: RootState['tree'], treeToo: RootState['treeToo']): Set<string> {
const names = new Set(tree.nodes.map((n) => n.name)); // can be internal nodes
if (Array.isArray(treeToo.nodes)) {
treeToo.nodes.forEach((node) => names.add(node.name));
}
return names;
}