diff --git a/src/actions/recomputeReduxState.js b/src/actions/recomputeReduxState.js
index 4cf121d96..da06f6a62 100644
--- a/src/actions/recomputeReduxState.js
+++ b/src/actions/recomputeReduxState.js
@@ -16,7 +16,7 @@ import { computeMatrixFromRawData } from "../util/processFrequencies";
import { applyInViewNodesToTree } from "../actions/tree";
import { isColorByGenotype, decodeColorByGenotype } from "../util/getGenotype";
import { getTraitFromNode, getDivFromNode } from "../util/treeMiscHelpers";
-
+import { collectAvailableTipLabelOptions } from "../components/controls/choose-tip-label";
export const doesColorByHaveConfidence = (controlsState, colorBy) =>
controlsState.coloringsPresentOnTreeWithConfidence.has(colorBy);
@@ -71,6 +71,9 @@ const modifyStateViaURLQuery = (state, query) => {
if (query.p && state.canTogglePanelLayout && (query.p === "full" || query.p === "grid")) {
state["panelLayout"] = query.p;
}
+ if (query.tl) {
+ state["tipLabelKey"] = query.tl;
+ }
if (query.d) {
const proposed = query.d.split(",");
state.panelsToDisplay = state.panelsAvailable.filter((n) => proposed.indexOf(n) !== -1);
@@ -169,6 +172,7 @@ const restoreQueryableStateToDefaults = (state) => {
state["panelLayout"] = calcBrowserDimensionsInitialState().width > twoColumnBreakpoint ? "grid" : "full";
state.panelsToDisplay = state.panelsAvailable.slice();
+ state.tipLabelKey = strainSymbol;
// console.log("state now", state);
return state;
};
@@ -478,6 +482,12 @@ const checkAndCorrectErrorsInState = (state, metadata, query, tree, viewingNarra
state.defaults.selectedBranchLabel = "none";
}
+ /* check tip label is valid. We use the function which generates the options for the dropdown here */
+ if (!collectAvailableTipLabelOptions(metadata.colorings).map((o) => o.value).includes(state.tipLabelKey)) {
+ console.error("Can't set selected tip label to ", state.tipLabelKey);
+ state.tipLabelKey = strainSymbol;
+ }
+
/* temporalConfidence */
if (shouldDisplayTemporalConfidence(state.temporalConfidence.exists, state.distanceMeasure, state.layout)) {
state.temporalConfidence.display = true;
diff --git a/src/actions/types.js b/src/actions/types.js
index 5bef4fb19..2b1775149 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -53,3 +53,4 @@ export const TOGGLE_LEGEND = "TOGGLE_LEGEND";
export const TOGGLE_TRANSMISSION_LINES = "TOGGLE_TRANSMISSION_LINES";
export const CACHE_JSONS = "CACHE_JSONS";
export const SET_ROOT_SEQUENCE = "SET_ROOT_SEQUENCE";
+export const CHANGE_TIP_LABEL_KEY = "CHANGE_TIP_LABEL_KEY";
diff --git a/src/components/controls/choose-tip-label.js b/src/components/controls/choose-tip-label.js
new file mode 100644
index 000000000..e37e77388
--- /dev/null
+++ b/src/components/controls/choose-tip-label.js
@@ -0,0 +1,66 @@
+import React from "react";
+import { connect } from "react-redux";
+import Select from "react-select/lib/Select";
+import { withTranslation } from 'react-i18next';
+import { CHANGE_TIP_LABEL_KEY } from "../../actions/types";
+import { SidebarSubtitle } from "./styles";
+import { controlsWidth, strainSymbol } from "../../util/globals";
+
+@connect((state) => ({
+ selected: state.controls.tipLabelKey,
+ options: collectAvailableTipLabelOptions(state.metadata.colorings)
+}))
+class ChooseTipLabel extends React.Component {
+ constructor(props) {
+ super(props);
+ this.change = (value) => {this.props.dispatch({type: CHANGE_TIP_LABEL_KEY, key: value.value});};
+ }
+ render() {
+ const { t } = this.props;
+ return (
+
+
+ {t("sidebar:Tip Labels")}
+
+
+
+
+
+ );
+ }
+}
+
+const WithTranslation = withTranslation()(ChooseTipLabel);
+export default WithTranslation;
+
+/**
+ * collect available tip labellings -- currently this is based on the available
+ * colorings but we ignore genotype (this could be implemented in the future,
+ * but it's not straightforward)
+ */
+export function collectAvailableTipLabelOptions(colorings) {
+ return [
+ {value: strainSymbol, label: "Sample Name"},
+ ...Object.entries(colorings)
+ .filter((keyValue) => keyValue[0] !== 'gt')
+ .map(([key, value]) => {
+ return {value: key, label: value.title};
+ })
+ ];
+}
+
+/**
+ * Find the currently selected option.
+ *