From bcf0b9f1c44394dbb99a8d4a4ce37f82eb31f965 Mon Sep 17 00:00:00 2001 From: james hadfield Date: Thu, 6 Jun 2024 15:25:19 +1200 Subject: [PATCH 1/3] Don't capture mouse within tip labels Fixes a bug whereby branch hover/click-events didn't work because the tip label captured the mouse, which is very common on tangletrees (because the text starts to the right of the tip and thus always obscures branches). Note that the branch labels already had this setting. --- src/components/tree/phyloTree/labels.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/tree/phyloTree/labels.js b/src/components/tree/phyloTree/labels.js index de9a0e1b2..31fe9db88 100644 --- a/src/components/tree/phyloTree/labels.js +++ b/src/components/tree/phyloTree/labels.js @@ -39,6 +39,7 @@ export const updateTipLabels = function updateTipLabels(dt) { .text((d) => tLFunc(d)) .attr("class", "tipLabel") .style("font-size", fontSize.toString() + "px") + .style("pointer-events", "none") .style("visibility", (d) => (d.visibility === NODE_VISIBLE ? "visible" : "hidden")); }, dt); } From d59dbd5df82cdc2edf4c4ba279b8edd409703109 Mon Sep 17 00:00:00 2001 From: james hadfield Date: Thu, 6 Jun 2024 16:18:51 +1200 Subject: [PATCH 2/3] [tangletrees] fix node-click modal for RHS tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This bug arrived with recent work which lifted the selected node state out of component state and into redux¹, where I forgot to consider tangletrees so that we always ended up retrieving the node (via array index) from the LHS tree. Closes ¹ --- src/components/tree/infoPanels/click.js | 12 +++++++++--- src/components/tree/reactD3Interface/callbacks.js | 4 ++-- src/components/tree/tree.js | 9 ++++++--- src/reducers/controls.ts | 9 +++++++-- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/components/tree/infoPanels/click.js b/src/components/tree/infoPanels/click.js index dc21c7281..7d5b8ef9f 100644 --- a/src/components/tree/infoPanels/click.js +++ b/src/components/tree/infoPanels/click.js @@ -5,6 +5,7 @@ import { numericToCalendar } from "../../../util/dateHelpers"; import { getTraitFromNode, getFullAuthorInfoFromNode, getVaccineFromNode, getAccessionFromNode, getUrlFromNode } from "../../../util/treeMiscHelpers"; import { MutationTable } from "./MutationTable"; +import { lhsTreeId} from "../tree"; export const styles = { container: { @@ -234,16 +235,21 @@ const Trait = ({node, trait, colorings, isTerminal}) => { * A React component to display information about a tree tip in a modal-overlay style * @param {Object} props * @param {Object} props.selectedNode - * @param {Object[]} props.nodes + * @param {Object[]} props.nodesLhsTree + * @param {Object[]|undefined} props.nodesRhsTree * @param {function} props.clearSelectedNode * @param {Object} props.colorings * @param {Object} props.observedMutations * @param {function} props.geneSortFn * @param {function} props.t */ -const NodeClickedPanel = ({selectedNode, nodes, clearSelectedNode, colorings, observedMutations, geneSortFn, t}) => { +const NodeClickedPanel = ({selectedNode, nodesLhsTree, nodesRhsTree, clearSelectedNode, colorings, observedMutations, geneSortFn, t}) => { if (!selectedNode) return null; - const node = nodes[selectedNode.idx]; + const node = (selectedNode.treeId===lhsTreeId ? nodesLhsTree : nodesRhsTree)?.[selectedNode.idx]; + if (!node) { + console.error('Internal error retrieving selected node'); + return null; + } const panelStyle = { ...infoPanelStyles.panel}; panelStyle.maxHeight = "70%"; const isTerminal = !node.hasChildren; diff --git a/src/components/tree/reactD3Interface/callbacks.js b/src/components/tree/reactD3Interface/callbacks.js index 139bfdadc..0ecc3fc85 100644 --- a/src/components/tree/reactD3Interface/callbacks.js +++ b/src/components/tree/reactD3Interface/callbacks.js @@ -24,7 +24,7 @@ export const onTipClick = function onTipClick(d) { /* The order of these two dispatches is important: the reducer handling `SELECT_NODE` must have access to the filtering state _prior_ to these filters being applied */ - this.props.dispatch({type: SELECT_NODE, name: d.n.name, idx: d.n.arrayIdx, isBranch: false}); + this.props.dispatch({type: SELECT_NODE, name: d.n.name, idx: d.n.arrayIdx, isBranch: false, treeId: d.that.id}); this.props.dispatch(applyFilter("add", strainSymbol, [d.n.name])); }; @@ -60,7 +60,7 @@ export const onBranchClick = function onBranchClick(d) { /* if a branch was clicked while holding the shift key, we instead display a node-clicked modal */ if (window.event.shiftKey) { // no need to dispatch a filter action - this.props.dispatch({type: SELECT_NODE, name: d.n.name, idx: d.n.arrayIdx, isBranch: true}) + this.props.dispatch({type: SELECT_NODE, name: d.n.name, idx: d.n.arrayIdx, isBranch: true, treeId: d.that.id}) return; } diff --git a/src/components/tree/tree.js b/src/components/tree/tree.js index f91040fa4..5c358d94f 100644 --- a/src/components/tree/tree.js +++ b/src/components/tree/tree.js @@ -19,6 +19,8 @@ import { untangleTreeToo } from "./tangle/untangling"; import { sortByGeneOrder } from "../../util/treeMiscHelpers"; export const spaceBetweenTrees = 100; +export const lhsTreeId = "LEFT"; +const rhsTreeId = "RIGHT"; class Tree extends React.Component { constructor(props) { @@ -51,7 +53,7 @@ class Tree extends React.Component { setUpAndRenderTreeToo(props, newState) { /* this.setState(newState) will be run sometime after this returns */ /* modifies newState in place */ - newState.treeToo = new PhyloTree(props.treeToo.nodes, "RIGHT", props.treeToo.idxOfInViewRootNode); + newState.treeToo = new PhyloTree(props.treeToo.nodes, rhsTreeId, props.treeToo.idxOfInViewRootNode); if (attemptUntangle) { untangleTreeToo(newState.tree, newState.treeToo); } @@ -61,7 +63,7 @@ class Tree extends React.Component { document.addEventListener('keyup', this.handlekeydownEvent); if (this.props.tree.loaded) { const newState = {}; - newState.tree = new PhyloTree(this.props.tree.nodes, "LEFT", this.props.tree.idxOfInViewRootNode); + newState.tree = new PhyloTree(this.props.tree.nodes, lhsTreeId, this.props.tree.idxOfInViewRootNode); renderTree(this, true, newState.tree, this.props); if (this.props.showTreeToo) { this.setUpAndRenderTreeToo(this.props, newState); /* modifies newState in place */ @@ -209,7 +211,8 @@ class Tree extends React.Component { info.value===action.name); const existingFilterState = existingFilterInfo === undefined ? null : existingFilterInfo.active ? 'active' : 'inactive'; - return {...state, selectedNode: {name: action.name, idx: action.idx, existingFilterState, isBranch: action.isBranch}}; + const selectedNode = {name: action.name, idx: action.idx, existingFilterState, isBranch: action.isBranch, treeId: action.treeId}; + return {...state, selectedNode}; } case types.DESELECT_NODE: { return {...state, selectedNode: null} From b4f5d19d867be6f5687a5cbacb450accc2d34c30 Mon Sep 17 00:00:00 2001 From: james hadfield Date: Mon, 10 Jun 2024 12:03:53 +1200 Subject: [PATCH 3/3] changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f21fe2cf..6252e9a2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # Changelog -## version 2.54.0 - 2024/06/06 +* Fixed a big bug where clicking on tips (and shift-clicking on branches) on the RHS tree in a tanglegram would bring up a modal detailing a node in the LHS tree. ([#1783](https://github.com/nextstrain/auspice/pull/1783)) +* Fixed a small bug where branch labels prevented you from hovering on the branch itself, a situation that was more common in tangletrees. ([#1783](https://github.com/nextstrain/auspice/pull/1783)) + +## version 2.54.0 - 2024/06/06 * Add a link-out to use datasets in Nextclade (this functionality is only enabled when running within the larger nextstrain.org ecosystem.) This builds on functionality introduced in [Nextclade 3.7.0](https://github.com/nextstrain/nextclade/releases/tag/3.7.0) allowing an Auspice dataset to be used as a nextclade dataset so that users can then add new sequences (via drag-and-drop) and see them placed on the tree. ([#1776](https://github.com/nextstrain/auspice/pull/1776))