Skip to content

Commit

Permalink
Load sidecar files when changing narrative datasets
Browse files Browse the repository at this point in the history
This complements the previous commit to allow narrative slide-changes to
change datasets by querying the cache set up at narrative load.
Appropriate sidecar files are also loaded, and we ensure that
sidecar data from the previous dataset is not displayed.

This work is based upon PR #1312 by eharkins.

Co-authored-by: eharkins <[email protected]>
  • Loading branch information
eharkins authored and jameshadfield committed Aug 11, 2021
1 parent c190057 commit b312077
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 43 deletions.
72 changes: 33 additions & 39 deletions src/actions/navigation.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import queryString from "query-string";
import { createStateFromQueryOrJSONs } from "./recomputeReduxState";
import { PAGE_CHANGE, URL_QUERY_CHANGE_WITH_COMPUTED_STATE } from "./types";
import { PAGE_CHANGE, URL_QUERY_CHANGE_WITH_COMPUTED_STATE, SET_ROOT_SEQUENCE } from "./types";
import { getDatasetNamesFromUrl } from "./loadData";
import { errorNotification } from "./notifications";

/* Given a URL, what "page" should be displayed?
* "page" means the main app, splash page, status page etc
Expand All @@ -26,26 +27,39 @@ export const chooseDisplayComponentFromURL = (url) => {
};

/*
* All the Fetch Promises are created before first render. When trying the cache we `await`.
* `datasets` is populated with `Dataset()` instances for each dataset in a narrative.
* Each instance contains promises to represent the main and sidecar datafiles.
* If the Fetch is not finished, this will wait for it to end. Subsequent awaits will immediately return the result.
* For the landing dataset, no problem either because await on a value just returns the value.
*/
const tryCacheThenFetch = async (mainTreeName, secondTreeName, state) => {
// console.log("tryCacheThenFetch", mainTreeName, mainTreeName);

if (!state.jsonCache || !state.jsonCache.jsons) {
throw new Error("Cache not present");
}
const cache = state.jsonCache.jsons;
if (!cache[mainTreeName] || !cache[mainTreeName].main) {
throw new Error(`${mainTreeName} not in cache.`);
const updateNarrativeDataset = async (dispatch, datasets, narrativeBlocks, path, query) => {
try {
const [mainTreeName, secondTreeName] = getDatasetNamesFromUrl(path);
const mainDataset = datasets[mainTreeName];
const secondDataset = datasets[secondTreeName];
const mainJson = await mainDataset.main;
const secondJson = secondDataset ? (await secondDataset.main) : false;
dispatch({
type: URL_QUERY_CHANGE_WITH_COMPUTED_STATE,
...createStateFromQueryOrJSONs({
json: mainJson,
secondTreeDataset: secondJson,
mainTreeName,
secondTreeName,
narrativeBlocks,
query,
dispatch
}),
pushState: true,
query
});
mainDataset.loadSidecars(dispatch);
} catch (err) {
dispatch(errorNotification({
message: `Error loading the datasets for this narrative slide`,
details: `Please contact the author of this narrative!`
}));
console.error(err);
}
const mainJson = await cache[mainTreeName].main;
const secondJson = cache[secondTreeName] ? await cache[secondTreeName].main : undefined;
return {json: mainJson, secondJson};

// todo: sidecar files. These are in cache. Turn `tryCacheThenFetch`
// into an async generator?
};

/* changes the state of the page and (perhaps) the dataset displayed.
Expand Down Expand Up @@ -95,26 +109,7 @@ export const changePage = ({
});
} else if (changeDatasetOnly) {
/* Case 2 (see docstring): the path (dataset) has changed but the we want to remain on the current page and update state with the new dataset */
const [mainTreeName, secondTreeName] = getDatasetNamesFromUrl(path);
tryCacheThenFetch(mainTreeName, secondTreeName, oldState)
.then(({json, secondJson}) => {
const newState = createStateFromQueryOrJSONs({
json,
secondTreeDataset: secondJson || false,
mainTreeName,
secondTreeName: secondTreeName || false,
narrativeBlocks: oldState.narrative.blocks,
query,
dispatch
});
// same dispatch as case 1 but the state comes from a JSON
dispatch({
type: URL_QUERY_CHANGE_WITH_COMPUTED_STATE,
...newState,
pushState: push,
query
});
});
updateNarrativeDataset(dispatch, oldState.jsonCache.jsons, oldState.narrative.blocks, path, query);
} else {
/* Case 3 (see docstring): the path (dataset) has changed and we want to change pages and set a new state according to the path */
dispatch({
Expand All @@ -136,4 +131,3 @@ export const goTo404 = (errorMessage) => ({
errorMessage,
pushState: true
});

3 changes: 3 additions & 0 deletions src/actions/recomputeReduxState.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { calcBrowserDimensionsInitialState } from "../reducers/browserDimensions
import { getIdxMatchingLabel, calculateVisiblityAndBranchThickness } from "../util/treeVisibilityHelpers";
import { constructVisibleTipLookupBetweenTrees } from "../util/treeTangleHelpers";
import { getDefaultControlsState, shouldDisplayTemporalConfidence } from "../reducers/controls";
import { getDefaultFrequenciesState } from "../reducers/frequencies";
import { countTraitsAcrossTree, calcTotalTipsInTree } from "../util/treeCountingHelpers";
import { calcEntropyInView } from "../util/entropy";
import { treeJsonToState } from "../util/treeJsonProcessing";
Expand Down Expand Up @@ -747,6 +748,8 @@ export const createStateFromQueryOrJSONs = ({
metadata = createMetadataStateFromJSON(json);
/* entropy state */
entropy = entropyCreateState(metadata.genomeAnnotations);
/* ensure default frequencies state */
frequencies = getDefaultFrequenciesState();
/* new tree state(s) */
tree = treeJsonToState(json.tree);
tree.debug = "LEFT";
Expand Down
10 changes: 6 additions & 4 deletions src/reducers/frequencies.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import * as types from "../actions/types";

/* TODO: initial data should simply be {loaded: false} */
const frequencies = (state = {
export const getDefaultFrequenciesState = () => ({
loaded: false,
data: undefined,
pivots: undefined,
matrix: undefined,
projection_pivot: undefined,
version: 0
}, action) => {
});

/* TODO: initial data should simply be {loaded: false} */
const frequencies = (state = getDefaultFrequenciesState(), action) => {
switch (action.type) {
case types.URL_QUERY_CHANGE_WITH_COMPUTED_STATE: // fallthrough
case types.LOAD_FREQUENCIES:
Expand All @@ -17,7 +19,7 @@ const frequencies = (state = {
return Object.assign({}, state, {loaded: true, matrix: action.matrix, version: state.version + 1});
}
case types.DATA_INVALID: {
return {loaded: false, data: undefined, pivots: undefined, matrix: undefined, projection_pivot: undefined, version: 0};
return getDefaultFrequenciesState();
}
default:
return state;
Expand Down

0 comments on commit b312077

Please sign in to comment.