diff --git a/cli/server/handleGenomeDbs.js b/cli/server/handleGenomeDbs.js index 105f1a48a..b07ec6ef7 100644 --- a/cli/server/handleGenomeDbs.js +++ b/cli/server/handleGenomeDbs.js @@ -1,10 +1,8 @@ const fs = require('fs'); const path = require("path"); -const through = require('through2'); const {PassThrough} = require('stream'); const Engine = require('nedb'); const fasta = require('bionode-fasta'); -const bodyParser = require('body-parser'); const { promisify } = require('util'); @@ -35,7 +33,7 @@ const fetchRecords = (ids, dbPath) => if (err) { console.log('EE'); reject(err); - } else if (docs.length == 0) { + } else if (docs.length === 0) { console.log("No record found!"); resolve(docs); } else { @@ -54,11 +52,11 @@ const fetchRecords = (ids, dbPath) => const getGenomeDB = (datasetsPath) => { return async (req, res) => { // eslint-disable-line consistent-return try { - let prefix = req.body.prefix - .replace(/^\//, '') - .replace(/\/$/, '') - .split("/") - .join("_"); + const prefix = req.body.prefix + .replace(/^\//, '') + .replace(/\/$/, '') + .split("/") + .join("_"); const dbPath = datasetsPath + '/genomeDbs/' + prefix + '.db'; if (!req.body.ids || req.body.ids.length === 0) { res.setHeader('Content-Type', 'application/json'); @@ -70,8 +68,8 @@ const getGenomeDB = (datasetsPath) => { return; } res.setHeader('Content-Type', 'text/plain'); - var db = await fetchRecords(req.body.ids, dbPath); - db.forEach(v=> { + const db = await fetchRecords(req.body.ids, dbPath); + db.forEach((v) => { const wrappedSeq = v.seq.match(/.{1,80}/g).join('\n') + '\n'; res.write('>' + v.id + '\n'); res.write(wrappedSeq); @@ -83,27 +81,6 @@ const getGenomeDB = (datasetsPath) => { }; }; -/** - @param {string} path Path to datasetDir so we can create database if corresponding fasta - files exists for aupsice input JSON file -*/ -const prepareDbs = async (path) => { - try { - const files = await readdir(path); - const v2Files = files.filter((file) => ( - file.endsWith(".fasta") - )); - v2Files.forEach((v) => { - makeDB(path, path + '/' + v); - }); - - - } catch (err) { - // utils.warn(`Couldn't collect available dataset files (path searched: ${path})`); - // utils.verbose(err); - } -}; - /** @param {string} dbRoot Path to directory where genome database should be saved @param {string} fastaPath Path to fasta file to use as input to create database @@ -129,7 +106,7 @@ const makeDB = (dbRoot, fastaPath) => new Promise((resolve, reject) => { let rc = 0; processRecord.on('data', (rec) => { - obj = JSON.parse(rec); + const obj = JSON.parse(rec); const outrec = {id: obj.id, seq: obj.seq, source: fastaPath}; db.insert(outrec); rc++; @@ -149,6 +126,28 @@ const makeDB = (dbRoot, fastaPath) => new Promise((resolve, reject) => { .pipe(processRecord); }); + +/** + @param {string} path Path to datasetDir so we can create database if corresponding fasta + files exists for aupsice input JSON file +*/ +const prepareDbs = async (localPath) => { + try { + const files = await readdir(localPath); + const v2Files = files.filter((file) => ( + file.endsWith(".fasta") + )); + v2Files.forEach((v) => { + makeDB(localPath, localPath + '/' + v); + }); + + + } catch (err) { + // utils.warn(`Couldn't collect available dataset files (path searched: ${locaPath})`); + // utils.verbose(err); + } +}; + module.exports = { fetchRecords, getDbPath, diff --git a/cli/server/parseNarrative.js b/cli/server/parseNarrative.js index a132e3201..c7843d185 100644 --- a/cli/server/parseNarrative.js +++ b/cli/server/parseNarrative.js @@ -60,7 +60,7 @@ const makeFrontMatterBlock = (frontMatter) => { markdown.push(`#### License: ${license}`); } } - + const block = new Proxy({}, blockProxyHandler); block.url = frontMatter.dataset; block.contents = markdown.join("\n"); diff --git a/docs-src/website/siteConfig.js b/docs-src/website/siteConfig.js index 36e4fe4f0..04428abe5 100644 --- a/docs-src/website/siteConfig.js +++ b/docs-src/website/siteConfig.js @@ -17,7 +17,7 @@ const siteConfig = { // Header links in the top nav bar headerLinks: [ - {doc: 'introduction/overview', label: 'Docs'}, + {doc: 'introduction/overview', label: 'Docs'} // {doc: 'tutorial/overview', label: 'Tutorial'} ], diff --git a/docs/js/scrollSpy.js b/docs/js/scrollSpy.js index 0632e6c33..484a5d6f5 100755 --- a/docs/js/scrollSpy.js +++ b/docs/js/scrollSpy.js @@ -18,7 +18,7 @@ // throttle return; } - timer = setTimeout(function() { + timer = setTimeout(function () { timer = null; let activeNavFound = false; const headings = findHeadings(); // toc nav anchors @@ -48,7 +48,7 @@ } else { console.error('Can not find header element', { id: next, - heading, + heading }); } } @@ -68,9 +68,9 @@ document.addEventListener('scroll', onScroll); document.addEventListener('resize', onScroll); - document.addEventListener('DOMContentLoaded', function() { + document.addEventListener('DOMContentLoaded', function () { // Cache the headings once the page has fully loaded. headingsCache = findHeadings(); onScroll(); }); -})(); +}()); diff --git a/src/components/download/downloadModal.js b/src/components/download/downloadModal.js index 4e8a33aff..87041e1bf 100644 --- a/src/components/download/downloadModal.js +++ b/src/components/download/downloadModal.js @@ -138,17 +138,17 @@ class DownloadModal extends React.Component { } formatPublications(pubs) { return ( - + - + ))} + + ); } getFilePrefix() { @@ -233,21 +233,21 @@ class DownloadModal extends React.Component { const buttonTextStyle = Object.assign({}, materialButton, {backgroundColor: "rgba(0,0,0,0)", paddingLeft: "10px", color: "white", minWidth: "300px", textAlign: "left" }); const buttonLabelStyle = { fontStyle: "italic", fontSize: "14px", color: "lightgray" }; return ( -
+
- {buttons.map((data) => ( + {buttons.map((data) => (
- {data[2]} - -
- + {data[2]} + +
+ +
-
- ))} -
+ ))}
+
); } dismissModal() { @@ -279,42 +279,42 @@ class DownloadModal extends React.Component { const meta = this.props.metadata; return ( -
+
stopProp(e)}> -

+

({t("click outside this box to return to the app")}) -

+

-
- {meta.title} ({t("last updated")} {meta.updated}) -
+
+ {meta.title} ({t("last updated")} {meta.updated}) +
-
- {this.createSummaryWrapper()} -
-
- {" " + t("A full list of sequence authors is available via the TSV files below")} -
- {getAcknowledgments({}, {preamble: {fontWeight: 300}, acknowledgments: {fontWeight: 300}})} +
+ {this.createSummaryWrapper()} +
+
+ {" " + t("A full list of sequence authors is available via the TSV files below")} +
+ {getAcknowledgments({}, {preamble: {fontWeight: 300}, acknowledgments: {fontWeight: 300}})} -
- {t("Data usage policy")} -
- {t("Data usage part 1") + " " + t("Data usage part 2")} +
+ {t("Data usage policy")} +
+ {t("Data usage part 1") + " " + t("Data usage part 2")} -
- {t("Please cite the authors who contributed genomic data (where relevant), as well as")+":"} -
- {this.formatPublications(this.getRelevantPublications())} +
+ {t("Please cite the authors who contributed genomic data (where relevant), as well as")+":"} +
+ {this.formatPublications(this.getRelevantPublications())} -
- {t("Download data")}: -
- {this.downloadButtons()} +
+ {t("Download data")}: +
+ {this.downloadButtons()} -
+
); } } diff --git a/src/reducers/controls.js b/src/reducers/controls.js index b5378b678..d5c12e3d8 100644 --- a/src/reducers/controls.js +++ b/src/reducers/controls.js @@ -12,7 +12,7 @@ import { calcBrowserDimensionsInitialState } from "./browserDimensions"; import { doesColorByHaveConfidence } from "../actions/recomputeReduxState"; /* defaultState is a fn so that we can re-create it -at any time, e.g. if we want to revert things (e.g. on dataset change) + at any time, e.g. if we want to revert things (e.g. on dataset change) */ export const getDefaultControlsState = () => { const defaults = { @@ -93,170 +93,170 @@ export const shouldDisplayTemporalConfidence = (exists, distMeasure, layout) => const Controls = (state = getDefaultControlsState(), action) => { switch (action.type) { - case types.URL_QUERY_CHANGE_WITH_COMPUTED_STATE: /* fallthrough */ - case types.CLEAN_START: - return action.controls; - case types.SET_AVAILABLE: - return Object.assign({}, state, {available: action.data}); - case types.BRANCH_MOUSEENTER: - return Object.assign({}, state, { - selectedBranch: action.data - }); - case types.BRANCH_MOUSELEAVE: - return Object.assign({}, state, { - selectedBranch: null - }); - case types.NODE_MOUSEENTER: - return Object.assign({}, state, { - selectedNode: action.data - }); - case types.NODE_MOUSELEAVE: - return Object.assign({}, state, { - selectedNode: null - }); - case types.CHANGE_BRANCH_LABEL: - return Object.assign({}, state, {selectedBranchLabel: action.value}); - case types.CHANGE_LAYOUT: - return Object.assign({}, state, { - layout: action.data, - /* temporal confidence can only be displayed for rectangular trees */ - temporalConfidence: Object.assign({}, state.temporalConfidence, { - display: shouldDisplayTemporalConfidence(state.temporalConfidence.exists, state.distanceMeasure, action.data), - on: false}) - }); - case types.CHANGE_DISTANCE_MEASURE: - const updatesToState = { - distanceMeasure: action.data, - branchLengthsToDisplay: state.branchLengthsToDisplay - }; - if (shouldDisplayTemporalConfidence(state.temporalConfidence.exists, action.data, state.layout)) { - updatesToState.temporalConfidence = Object.assign({}, state.temporalConfidence, {display: true}); - } else { - updatesToState.temporalConfidence = Object.assign({}, state.temporalConfidence, {display: false, on: false}); + case types.URL_QUERY_CHANGE_WITH_COMPUTED_STATE: /* fallthrough */ + case types.CLEAN_START: + return action.controls; + case types.SET_AVAILABLE: + return Object.assign({}, state, {available: action.data}); + case types.BRANCH_MOUSEENTER: + return Object.assign({}, state, { + selectedBranch: action.data + }); + case types.BRANCH_MOUSELEAVE: + return Object.assign({}, state, { + selectedBranch: null + }); + case types.NODE_MOUSEENTER: + return Object.assign({}, state, { + selectedNode: action.data + }); + case types.NODE_MOUSELEAVE: + return Object.assign({}, state, { + selectedNode: null + }); + case types.CHANGE_BRANCH_LABEL: + return Object.assign({}, state, {selectedBranchLabel: action.value}); + case types.CHANGE_LAYOUT: + return Object.assign({}, state, { + layout: action.data, + /* temporal confidence can only be displayed for rectangular trees */ + temporalConfidence: Object.assign({}, state.temporalConfidence, { + display: shouldDisplayTemporalConfidence(state.temporalConfidence.exists, state.distanceMeasure, action.data), + on: false}) + }); + case types.CHANGE_DISTANCE_MEASURE: + const updatesToState = { + distanceMeasure: action.data, + branchLengthsToDisplay: state.branchLengthsToDisplay + }; + if (shouldDisplayTemporalConfidence(state.temporalConfidence.exists, action.data, state.layout)) { + updatesToState.temporalConfidence = Object.assign({}, state.temporalConfidence, {display: true}); + } else { + updatesToState.temporalConfidence = Object.assign({}, state.temporalConfidence, {display: false, on: false}); + } + return Object.assign({}, state, updatesToState); + case types.CHANGE_DATES_VISIBILITY_THICKNESS: { + const newDates = {quickdraw: action.quickdraw}; + if (action.dateMin) { + newDates.dateMin = action.dateMin; + newDates.dateMinNumeric = action.dateMinNumeric; + } + if (action.dateMax) { + newDates.dateMax = action.dateMax; + newDates.dateMaxNumeric = action.dateMaxNumeric; + } + return Object.assign({}, state, newDates); } - return Object.assign({}, state, updatesToState); - case types.CHANGE_DATES_VISIBILITY_THICKNESS: { - const newDates = {quickdraw: action.quickdraw}; - if (action.dateMin) { - newDates.dateMin = action.dateMin; - newDates.dateMinNumeric = action.dateMinNumeric; + case types.CHANGE_ABSOLUTE_DATE_MIN: + return Object.assign({}, state, { + absoluteDateMin: action.data, + absoluteDateMinNumeric: calendarToNumeric(action.data) + }); + case types.CHANGE_ABSOLUTE_DATE_MAX: + return Object.assign({}, state, { + absoluteDateMax: action.data, + absoluteDateMaxNumeric: calendarToNumeric(action.data) + }); + case types.CHANGE_ANIMATION_TIME: + return Object.assign({}, state, { + mapAnimationDurationInMilliseconds: action.data + }); + case types.CHANGE_ANIMATION_CUMULATIVE: + return Object.assign({}, state, { + mapAnimationCumulative: action.data + }); + case types.CHANGE_ANIMATION_LOOP: + return Object.assign({}, state, { + mapAnimationShouldLoop: action.data + }); + case types.MAP_ANIMATION_PLAY_PAUSE_BUTTON: + return Object.assign({}, state, { + quickdraw: action.data !== "Play", + animationPlayPauseButton: action.data + }); + case types.CHANGE_ANIMATION_START: + return Object.assign({}, state, { + mapAnimationStartDate: action.data + }); + case types.CHANGE_PANEL_LAYOUT: + return Object.assign({}, state, { + panelLayout: action.data + }); + case types.TREE_TOO_DATA: + return action.controls; + case types.TOGGLE_PANEL_DISPLAY: + return Object.assign({}, state, { + panelsToDisplay: action.panelsToDisplay, + panelLayout: action.panelLayout, + canTogglePanelLayout: action.panelsToDisplay.indexOf("tree") !== -1 && action.panelsToDisplay.indexOf("map") !== -1 + }); + case types.NEW_COLORS: { + const newState = Object.assign({}, state, { + colorBy: action.colorBy, + colorScale: action.colorScale, + colorByConfidence: doesColorByHaveConfidence(state, action.colorBy) + }); + return newState; } - if (action.dateMax) { - newDates.dateMax = action.dateMax; - newDates.dateMaxNumeric = action.dateMaxNumeric; - } - return Object.assign({}, state, newDates); - } - case types.CHANGE_ABSOLUTE_DATE_MIN: - return Object.assign({}, state, { - absoluteDateMin: action.data, - absoluteDateMinNumeric: calendarToNumeric(action.data) - }); - case types.CHANGE_ABSOLUTE_DATE_MAX: - return Object.assign({}, state, { - absoluteDateMax: action.data, - absoluteDateMaxNumeric: calendarToNumeric(action.data) - }); - case types.CHANGE_ANIMATION_TIME: - return Object.assign({}, state, { - mapAnimationDurationInMilliseconds: action.data - }); - case types.CHANGE_ANIMATION_CUMULATIVE: - return Object.assign({}, state, { - mapAnimationCumulative: action.data - }); - case types.CHANGE_ANIMATION_LOOP: - return Object.assign({}, state, { - mapAnimationShouldLoop: action.data - }); - case types.MAP_ANIMATION_PLAY_PAUSE_BUTTON: - return Object.assign({}, state, { - quickdraw: action.data !== "Play", - animationPlayPauseButton: action.data - }); - case types.CHANGE_ANIMATION_START: - return Object.assign({}, state, { - mapAnimationStartDate: action.data - }); - case types.CHANGE_PANEL_LAYOUT: - return Object.assign({}, state, { - panelLayout: action.data - }); - case types.TREE_TOO_DATA: - return action.controls; - case types.TOGGLE_PANEL_DISPLAY: - return Object.assign({}, state, { - panelsToDisplay: action.panelsToDisplay, - panelLayout: action.panelLayout, - canTogglePanelLayout: action.panelsToDisplay.indexOf("tree") !== -1 && action.panelsToDisplay.indexOf("map") !== -1 - }); - case types.NEW_COLORS: { - const newState = Object.assign({}, state, { - colorBy: action.colorBy, - colorScale: action.colorScale, - colorByConfidence: doesColorByHaveConfidence(state, action.colorBy) - }); - return newState; - } - case types.CHANGE_GEO_RESOLUTION: - return Object.assign({}, state, { - geoResolution: action.data - }); - case types.APPLY_FILTER: { + case types.CHANGE_GEO_RESOLUTION: + return Object.assign({}, state, { + geoResolution: action.data + }); + case types.APPLY_FILTER: { // values arrive as array - const filters = Object.assign({}, state.filters, {}); - filters[action.trait] = action.values; - return Object.assign({}, state, { - filters - }); - } - case types.TOGGLE_MUT_TYPE: - return Object.assign({}, state, { - mutType: action.data - }); - case types.TOGGLE_TEMPORAL_CONF: - return Object.assign({}, state, { - temporalConfidence: Object.assign({}, state.temporalConfidence, { - on: !state.temporalConfidence.on - }) - }); - case types.TRIGGER_DOWNLOAD_MODAL: - return Object.assign({}, state, { - showDownload: true - }); - case types.DISMISS_DOWNLOAD_MODAL: - return Object.assign({}, state, { - showDownload: false - }); - case types.REMOVE_TREE_TOO: - return Object.assign({}, state, { - showTreeToo: undefined, - showTangle: false, - canTogglePanelLayout: state.panelsAvailable.indexOf("map") !== -1, - panelsToDisplay: state.panelsAvailable.slice() - }); - case types.TOGGLE_TANGLE: - if (state.showTreeToo) { - return Object.assign({}, state, {showTangle: !state.showTangle}); - } - return state; - case types.TOGGLE_SIDEBAR: - return Object.assign({}, state, {sidebarOpen: action.value}); - case types.TOGGLE_LEGEND: - return Object.assign({}, state, {legendOpen: action.value}); - case types.ADD_COLOR_BYS: - for (const colorBy of Object.keys(action.newColorings)) { - state.coloringsPresentOnTree.add(colorBy); + const filters = Object.assign({}, state.filters, {}); + filters[action.trait] = action.values; + return Object.assign({}, state, { + filters + }); } - return Object.assign({}, state, {coloringsPresentOnTree: state.coloringsPresentOnTree}); - case types.TOGGLE_TRANSMISSION_LINES: - return Object.assign({}, state, {showTransmissionLines: action.data}); - case 'GRID_FILTERED': - return Object.assign({}, state, {gridFiltered: action.data}); - case 'GENOME_AVAILBLE': - return Object.assign({}, state, {isGenomeAvailable: action.data}); - default: - return state; + case types.TOGGLE_MUT_TYPE: + return Object.assign({}, state, { + mutType: action.data + }); + case types.TOGGLE_TEMPORAL_CONF: + return Object.assign({}, state, { + temporalConfidence: Object.assign({}, state.temporalConfidence, { + on: !state.temporalConfidence.on + }) + }); + case types.TRIGGER_DOWNLOAD_MODAL: + return Object.assign({}, state, { + showDownload: true + }); + case types.DISMISS_DOWNLOAD_MODAL: + return Object.assign({}, state, { + showDownload: false + }); + case types.REMOVE_TREE_TOO: + return Object.assign({}, state, { + showTreeToo: undefined, + showTangle: false, + canTogglePanelLayout: state.panelsAvailable.indexOf("map") !== -1, + panelsToDisplay: state.panelsAvailable.slice() + }); + case types.TOGGLE_TANGLE: + if (state.showTreeToo) { + return Object.assign({}, state, {showTangle: !state.showTangle}); + } + return state; + case types.TOGGLE_SIDEBAR: + return Object.assign({}, state, {sidebarOpen: action.value}); + case types.TOGGLE_LEGEND: + return Object.assign({}, state, {legendOpen: action.value}); + case types.ADD_COLOR_BYS: + for (const colorBy of Object.keys(action.newColorings)) { + state.coloringsPresentOnTree.add(colorBy); + } + return Object.assign({}, state, {coloringsPresentOnTree: state.coloringsPresentOnTree}); + case types.TOGGLE_TRANSMISSION_LINES: + return Object.assign({}, state, {showTransmissionLines: action.data}); + case 'GRID_FILTERED': + return Object.assign({}, state, {gridFiltered: action.data}); + case 'GENOME_AVAILBLE': + return Object.assign({}, state, {isGenomeAvailable: action.data}); + default: + return state; } }; @@ -264,7 +264,7 @@ export default Controls; function getInitialSidebarState() { /* The following "hack" was present when `sidebarOpen` wasn't URL customisable. It can be removed - from here once the GISAID URLs (iFrames) are updated */ + from here once the GISAID URLs (iFrames) are updated */ if (window.location.pathname.includes("gisaid")) { return {sidebarOpen: false, setDefault: true}; }