Skip to content

Commit

Permalink
Change how closing a tip modal modifies filters
Browse files Browse the repository at this point in the history
Clicking on a tip activates a modal and activates the corresponding
strain filter. Previously clearing the modal would always inactivate the
filter. In the absence of any filtering this behaviour is not bad, but
when already filtering to a set of strains then it's counter-intuitive
because we inactivate a filter that was active.

The new behaviour restores the filtering state of the strain before the
modal was opened. Specifically,
* If the tip was already filtered, opening and closing the modal doesn't
  change the filters.
* If the tip was filtered but inactive, opening the modal activates it
  and closing the modal returns it to the inactive state.
* If the tip wasn't filtered (active or inactive) then opening the modal
  makes it an active filter and closing the modal removes the filter
  entirely.

Closes #1701
  • Loading branch information
jameshadfield committed Feb 5, 2024
1 parent 9790c56 commit cedd2ac
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 3 deletions.
12 changes: 11 additions & 1 deletion src/components/tree/reactD3Interface/callbacks.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export const onTipHover = function onTipHover(d) {
export const onTipClick = function onTipClick(d) {
if (d.visibility !== NODE_VISIBLE) return;
if (this.props.narrativeMode) return;
/* 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});
this.props.dispatch(applyFilter("add", strainSymbol, [d.n.name]));
};
Expand Down Expand Up @@ -119,7 +122,14 @@ export const onTipLeave = function onTipLeave(d) {
/* clearSelectedNode when clicking to remove the node-selected modal */
export const clearSelectedNode = function clearSelectedNode(selectedNode, isTerminal) {
if (isTerminal) {
this.props.dispatch(applyFilter("inactivate", strainSymbol, [selectedNode.name]));
/* perform the filtering action (if necessary) that will restore the
filtering state of the node prior to the selection */
if (!selectedNode.existingFilterState) {
this.props.dispatch(applyFilter("remove", strainSymbol, [selectedNode.name]));
} else if (selectedNode.existingFilterState==='inactive') {
this.props.dispatch(applyFilter("inactivate", strainSymbol, [selectedNode.name]));
}
/* else the filter was already active, so leave it unchanged */
}
this.props.dispatch({type: DESELECT_NODE});
};
7 changes: 5 additions & 2 deletions src/reducers/controls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,11 @@ const Controls = (state: ControlsState = getDefaultControlsState(), action): Con
geoResolution: action.data
});

case types.SELECT_NODE: {
return {...state, selectedNode: {name: action.name, idx: action.idx}};
case types.SELECT_NODE: {
const existingFilterInfo = (state.filters?.[strainSymbol]||[]).find((info) => info.value===action.name);
const existingFilterState = existingFilterInfo === undefined ? null :
existingFilterInfo.active ? 'active' : 'inactive';
return {...state, selectedNode: {name: action.name, idx: action.idx, existingFilterState}};
}
case types.DESELECT_NODE: {
return {...state, selectedNode: null}
Expand Down

0 comments on commit cedd2ac

Please sign in to comment.