Skip to content

Commit

Permalink
Merge pull request #8 from nextstrain/ordered-dataset-selectors
Browse files Browse the repository at this point in the history
Order datasets selectors
  • Loading branch information
trvrb authored Jul 24, 2019
2 parents ff5fc1d + 653355a commit f616c65
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 29 deletions.
49 changes: 32 additions & 17 deletions auspice/server/getDatasetHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,32 +31,47 @@ const decideSourceFromPrefix = (prefix) => {
* "default" one.
*/
const correctPrefixFromAvailable = (source, prefixParts) => {

if (!global.availableDatasets[source]) {
utils.verbose("Cant compare against available datsets as there are none!");
return prefixParts;
}
const prefix = prefixParts.join("/");

/* is there an exact match in the manifest? */
for (let i=0; i<global.availableDatasets[source].length; i++) {
if (global.availableDatasets[source][i].request === prefix) {
utils.verbose("Matches an availible dataset");
return prefixParts;
if (source === "staging" && prefixParts[0] !== "staging") {
prefixParts.unshift("staging");
}

const doesPathExist = (pathToCheck) => {
for (let i=0; i<global.availableDatasets[source].length; i++) {
if (global.availableDatasets[source][i].request === pathToCheck) {
utils.verbose(` ${pathToCheck} Matches an availible dataset`);
return true;
}
}
return false;
};

const removeStagingFromFront = (parts) => {
if (parts[0] === "staging") parts.shift();
return parts;
};

let prefix = prefixParts.join("/");

if (doesPathExist(prefix)) {
return removeStagingFromFront(prefixParts);
}

/* is there a partial match in the manifest? If so, use the
available datasets to return the correct path */
let possibleDatasets = global.availableDatasets[source]
.map((d) => d.request.split("/"));
prefixParts.forEach((part, idx) => {
possibleDatasets = possibleDatasets.filter((dataset) => dataset[idx] === part);
});
if (possibleDatasets.length) {
utils.verbose(`Changing ${prefixParts.join("/")} to ${possibleDatasets[0]}`);
return possibleDatasets[0];
/* if we are here, then the path doesn't match any available datasets exactly */
if (prefix in global.availableDatasets.defaults[source]) {
prefix = `${prefix}/${global.availableDatasets.defaults[source][prefix]}`;
const parts = prefix.split("/");
if (doesPathExist(prefix)) {
return removeStagingFromFront(parts);
}
return correctPrefixFromAvailable(source, parts);
}
utils.verbose("No matches in available datasets for this prefix. Proceeding anyway.");

return prefixParts;
};

Expand Down
35 changes: 23 additions & 12 deletions auspice/server/setAvailableDatasets.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,36 @@ const utils = require("./utils");
* This mimics the behavior of the auspice server around version 1.32.
* Ideally we can find a solution which doesn't use globals.
*/
global.availableDatasets = {};
global.availableDatasets = {defaults: {}};


const convertManifestJsonToAvailableDatasetList = (old) => {
const convertManifestJsonToAvailableDatasetList = (old, pathPrefix=false) => {
const allParts = [];
const defaults = {}; /* holds the defaults, used to complete incomplete paths */
const recurse = (partsSoFar, obj) => {
if (typeof obj === "string") {
// done
allParts.push(partsSoFar);
}
let keys = Object.keys(obj);

/* if there's only one key in the object it's the "name" of the level
in the heirachy, e.g. "category" or "lineage", which we skip over.
Note that for levels with only 1 option there's 2 keys (one is "default") */
if (keys.length === 1) {
obj = obj[keys[0]]; // eslint-disable-line
keys = Object.keys(obj); // skip level
}

const defaultValue = obj.default;
if (!defaultValue) {
return;
}
const orderedKeys = [defaultValue];
defaults[partsSoFar.join("/")] = defaultValue;

const orderedKeys = [];
keys.forEach((k) => {
if (k !== defaultValue && k !== "default") {
if (k !== "default") {
orderedKeys.push(k);
}
});
Expand All @@ -42,9 +50,11 @@ const convertManifestJsonToAvailableDatasetList = (old) => {
});
};

recurse([], old.pathogen);
return allParts
.map((fileParts) => ({request: fileParts.join("/")}));
recurse(pathPrefix ? [pathPrefix] : [], old.pathogen);
return [
allParts.map((fileParts) => ({request: fileParts.join("/")})),
defaults
];
};

/* setAvailableDatasetsFromManifest
Expand All @@ -60,22 +70,23 @@ const setAvailableDatasetsFromManifest = async () => {
try {
let data = await fetch(`http://data.nextstrain.org/manifest_guest.json`)
.then((result) => result.json());
data = convertManifestJsonToAvailableDatasetList(data);
let defaultsForPathCompletion;
[data, defaultsForPathCompletion] = convertManifestJsonToAvailableDatasetList(data);
utils.verbose(`Successfully got manifest for "live"`);
global.availableDatasets.live = data;
global.availableDatasets.defaults.live = defaultsForPathCompletion;
} catch (err) {
utils.warn(`Failed to getch manifest for "live"`);
}
/* STAGING */
try {
let data = await fetch(`http://staging.nextstrain.org/manifest_guest.json`)
.then((result) => result.json());
data = convertManifestJsonToAvailableDatasetList(data);
data.forEach((dataset) => {
dataset.request = `staging/${dataset.request}`;
});
let defaultsForPathCompletion;
[data, defaultsForPathCompletion] = convertManifestJsonToAvailableDatasetList(data, "staging");
utils.verbose(`Successfully got manifest for "staging"`);
global.availableDatasets.staging = data;
global.availableDatasets.defaults.staging = defaultsForPathCompletion;
} catch (err) {
utils.warn(`Failed to fetch manifest for "staging"`);
}
Expand Down

0 comments on commit f616c65

Please sign in to comment.