diff --git a/src/lib/datasets.js b/src/lib/datasets.js index 6b00280..e4fc65f 100644 --- a/src/lib/datasets.js +++ b/src/lib/datasets.js @@ -1,6 +1,7 @@ import groupBy from "lodash/groupBy"; import { Popover } from "antd"; import Primer from "../bits/Primer"; +import { formatTaxon } from "./utils"; export const PRIMER_GROUPINGS = ["Taxa_group", "Phylum", "Order", "Family", "Genus", "Final_ID"]; @@ -23,7 +24,7 @@ const taxaRecGroup = (arr, groupings, pathStr) => { const baseRecord = { title: isSpeciesLevel ? - {k.split("_").join(" ")}{" "} + {formatTaxon(k)}{" "} ) }> @@ -54,12 +55,15 @@ const buildLeafKey = (rec) => `root-${PRIMER_GROUPINGS.map((g) => rec[g]).join(" export const createDataset = (records) => { const tree = taxaRecGroup(records, PRIMER_GROUPINGS, "root"); - const primers = new Set(records.map((x) => x["Primer_name"])); + const primers = new Set(records.map((rec) => rec["Primer_name"])); const recordsWithKey = records.map((rec) => ({ ...rec, key: buildLeafKey(rec) })); + const recordsByKey = Object.fromEntries(recordsWithKey.map((rec) => [rec.key, rec])); + return { tree, primers: Array.from(primers), records: recordsWithKey, - recordsByKey: Object.fromEntries(recordsWithKey.map((rec) => [rec.key, rec])), + recordsByKey, + recordsByFinalID: Object.fromEntries(recordsWithKey.map((rec) => [rec["FinalID"], rec])), }; }; diff --git a/src/lib/utils.js b/src/lib/utils.js index e17328a..1325e3b 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -7,3 +7,13 @@ export const pluralize = (word, count) => { if (count !== 1) return `${word}s`; return word; }; + +export const formatTaxon = (finalID) => { + const parts = finalID.split("_"); + if (parts.length === 1) { + // Not a latin name + return <>{finalID}; + } + return {parts.join(" ")}{parts.at(-1) === "sp" ? "." : ""}; +}; + diff --git a/src/steps/DiscoverStep.js b/src/steps/DiscoverStep.js index a5d81a6..12286c2 100644 --- a/src/steps/DiscoverStep.js +++ b/src/steps/DiscoverStep.js @@ -16,14 +16,76 @@ import { Space, Spin, Tabs, - Tag, Tree, Typography } from "antd"; import { ArrowLeftOutlined, ArrowRightOutlined, SearchOutlined } from "@ant-design/icons"; import Primer from "../bits/Primer"; -import { pluralize } from "../lib/utils"; +import { formatTaxon, pluralize } from "../lib/utils"; + + +const ResultsTabs = ({ results }) => ( + { + const { nPrimers, results: npResults } = res; + + const nRes = npResults.length; + + return { + label: + {nPrimers} {pluralize("Primer", nPrimers)}: {(res.coverage * 100).toFixed(1)}% + {nRes > 1 ? <>{" "}({nRes} sets) : null} + , + key: `tab-${nPrimers}-primers`, + children: ( +
+
+ {npResults.map((r, j) => { + const newTaxa = (i < results.length - 1) + ? Array.from(difference(r.coveredTaxa, results[i + 1].results[0].coveredTaxa)) + : null; + + return ( + + +
+ Primers:
+ {Array.from(r.primers).map((p) => )} +
+
+ Taxa: {r.coveredTaxa.size} + {newTaxa + ?
+ + Adds {newTaxa.length} new {" "} + {pluralize("taxon", newTaxa.length)}{" "} + vs. with {results[i + 1].nPrimers}{" "} + {pluralize("primer", results[i + 1].nPrimers)} + + <> + {newTaxa.map((t, ti) => <> + {formatTaxon(t)} + {ti < newTaxa.length - 1 ? ", " : ""} + )} + +
+ : null} +
+
+
+ ); + })} +
+
+ ), + }; + })}/> +); const DiscoverStep = ({ visible, dataset, onBack, onFinish }) => { const worker = useRef(null); @@ -75,6 +137,7 @@ const DiscoverStep = ({ visible, dataset, onBack, onFinish }) => { const onCheck = useCallback((keys) => { setCheckedKeys(keys); + setProgress(0); }, []); const onExpand = useCallback((keys, e) => { @@ -99,11 +162,7 @@ const DiscoverStep = ({ visible, dataset, onBack, onFinish }) => { }, [dataset]); const deselectAll = useCallback(() => setCheckedKeys([]), []); - /** @type React.ReactNode */ - const selectedNode = useMemo( - () => {checkedLeaves.length} entries selected, - [checkedLeaves], - ); + const nCheckedLeaves = checkedLeaves.length; useEffect(() => { if (!dataset) return; @@ -142,7 +201,7 @@ const DiscoverStep = ({ visible, dataset, onBack, onFinish }) => { searching.current = true; }, [dataset, worker, checkedLeaves, nPrimers]); - if (!visible) return ; + if (!visible) return ; // noinspection JSCheckFunctionSignatures return <> @@ -152,7 +211,9 @@ const DiscoverStep = ({ visible, dataset, onBack, onFinish }) => { - {selectedNode} + + {checkedLeaves.length} entries selected + {
@@ -210,74 +271,9 @@ const DiscoverStep = ({ visible, dataset, onBack, onFinish }) => { /> )} {searching.current && ( - - )} - {!!results && ( - { - const { nPrimers, results: npResults } = res; - - const nRes = npResults.length; - - return { - label: - {nPrimers} {pluralize("Primer", nPrimers)}: {(res.coverage * 100).toFixed(1)}% - {nRes > 1 ? <>{" "}({nRes} sets) : null} - , - key: `tab-${nPrimers}-primers`, - children: ( -
-
- {npResults.map((r, j) => { - const newTaxa = (i < results.length - 1) - ? Array.from(difference( - r.coveredTaxa, - results[i + 1].results[0].coveredTaxa - )) - : null; - - return ( - - -
- Primers:
- {Array.from(r.primers).map((p) => ( - - ))} -
-
- Taxa: {r.coveredTaxa.size} - {newTaxa - ? <> -
- - {newTaxa.length}{" "} - new {pluralize( - "taxon", - newTaxa.length, - )}{" "} - vs. {results[i + 1].nPrimers} primers - {newTaxa.length < 8 - ? `: ${newTaxa.join(", ")}` - : null} - - - : null} -
-
-
- ); - })} -
-
- ), - }; - })} /> + )} + {!!results && } @@ -291,7 +287,7 @@ const DiscoverStep = ({ visible, dataset, onBack, onFinish }) => { > - {selectedNode} + {nCheckedLeaves} entries selected @@ -306,16 +302,16 @@ const DiscoverStep = ({ visible, dataset, onBack, onFinish }) => { /> - + - +