From 1b85910796a578871d93fcde516b88583af0d4d2 Mon Sep 17 00:00:00 2001 From: Adrian Paul Date: Fri, 27 Nov 2020 15:41:55 -0500 Subject: [PATCH] feat(sunBurst): #2643 dynamic tree --- .../UI/Charts/Sunburst/InfoPanel.tsx | 35 +++++++++++++++++-- .../UI/Charts/Sunburst/Sunburst.tsx | 16 +++++++-- .../UI/Charts/Sunburst/sunburst-d3.jsx | 19 ++++++++++ src/store/sunburstTypes.tsx | 13 +++++++ 4 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/components/UI/Charts/Sunburst/InfoPanel.tsx b/src/components/UI/Charts/Sunburst/InfoPanel.tsx index 36bb79974..a32f8d4f4 100644 --- a/src/components/UI/Charts/Sunburst/InfoPanel.tsx +++ b/src/components/UI/Charts/Sunburst/InfoPanel.tsx @@ -1,6 +1,6 @@ /* eslint-disable react/prop-types */ -import React, { FunctionComponent } from 'react'; -import { Phenotype } from 'store/sunburstTypes'; +import React, { FunctionComponent, ReactText } from 'react'; +import { generatePhenotypeByTitle, Phenotype } from 'store/sunburstTypes'; import { RootState } from 'store/rootState'; import { connect, ConnectedProps } from 'react-redux'; import { addTermToActiveIndex } from 'store/actionCreators/virtualStudies'; @@ -13,6 +13,7 @@ import './sunburst.css'; type OwnProps = { data: Pick; treeData: TreeNode[]; + getSelectedPhenotype: Function; }; type PropsFromRedux = ConnectedProps; @@ -33,7 +34,32 @@ const splitTitle = (title: string) => { }; }; -const InfoPanel: FunctionComponent = ({ data, onClickAddTermToActiveIndex, treeData }) => { +const getPath = (node: string, treeNodes: TreeNode[], path: string[]) => { + const currentNodeText = treeNodes[0].key; + path.push(currentNodeText); + if (node !== currentNodeText) { + getPath(node, treeNodes[0].children, path); + } + return path; +}; + +const generateNodeIdClicked = ( + nodeName: ReactText[], + treeData: TreeNode[], + getSelectedPhenotype: Function, +) => { + const path = getPath(nodeName[0] as string, treeData, []); + const phenotype = generatePhenotypeByTitle(nodeName[0] as string, path.join('-')); + getSelectedPhenotype(phenotype); + return path.join('-'); +}; + +const InfoPanel: FunctionComponent = ({ + data, + onClickAddTermToActiveIndex, + treeData, + getSelectedPhenotype, +}) => { const { title, key, results, exactTagCount } = data; const titleCode = splitTitle(title); @@ -69,6 +95,9 @@ const InfoPanel: FunctionComponent = ({ data, onClickAddTermToActiveIndex expandedKeys={key.split('-')} switcherIcon={
} className={'sunburst-phenotypes-tree'} + onSelect={(node) => + node.length ? generateNodeIdClicked(node, treeData, getSelectedPhenotype) : {} + } />
diff --git a/src/components/UI/Charts/Sunburst/Sunburst.tsx b/src/components/UI/Charts/Sunburst/Sunburst.tsx index 5b4550897..86a05a45f 100644 --- a/src/components/UI/Charts/Sunburst/Sunburst.tsx +++ b/src/components/UI/Charts/Sunburst/Sunburst.tsx @@ -51,6 +51,7 @@ export const hpoTreeTitleFormat = (splitPheno: PhenotypeSplit, currentTerm: stri class Sunburst extends Component { private readonly ref: React.RefObject; + private sunburstUpdate: (id: string) => void; static defaultProps = { depth: 2, width: 300, @@ -60,6 +61,7 @@ class Sunburst extends Component { constructor(props: SunburstProps) { super(props); this.ref = React.createRef(); + this.sunburstUpdate = () => {}; } state = { @@ -77,6 +79,11 @@ class Sunburst extends Component { }); }; + getSelectedPhenotypeFromTree = (phenotype: Phenotype) => { + this.getSelectedPhenotype(phenotype); + this.sunburstUpdate(phenotype.key); + }; + componentDidMount() { const { depth, width, height, tooltipFormatter, centerTextFormatter, data } = this.props; const config = { @@ -84,7 +91,8 @@ class Sunburst extends Component { width, height, }; - sunburstD3(this.ref, data, config, this.getSelectedPhenotype, { + + this.sunburstUpdate = sunburstD3(this.ref, data, config, this.getSelectedPhenotype, { tooltipFormatter, centerTextFormatter, }); @@ -120,7 +128,11 @@ class Sunburst extends Component { ref={this.ref} />
- +
); diff --git a/src/components/UI/Charts/Sunburst/sunburst-d3.jsx b/src/components/UI/Charts/Sunburst/sunburst-d3.jsx index 212db96e7..506bc5ad4 100644 --- a/src/components/UI/Charts/Sunburst/sunburst-d3.jsx +++ b/src/components/UI/Charts/Sunburst/sunburst-d3.jsx @@ -265,6 +265,25 @@ const sunburstD3 = (ref, data, config, getSelectedPhenotype, formatters) => { const textData = p || selectedPhenotype; centerText.text(() => centerTextFormatter(textData.data)).call(wrap); }; + + const findNodeByKey = (key, node, returnNode) => { + if (returnNode) return returnNode; + node.children.forEach((n) => { + if (key.includes(n.data.name)) { + if (key === n.data.key) { + returnNode = n; + } else { + returnNode = findNodeByKey(key, n, returnNode); + } + } + }); + return returnNode; + }; + + return (phenotypeKey) => { + const targetNode = findNodeByKey(phenotypeKey, root); + clicked(targetNode || root); + }; }; export default sunburstD3; diff --git a/src/store/sunburstTypes.tsx b/src/store/sunburstTypes.tsx index 42c50c4d2..899069e0a 100644 --- a/src/store/sunburstTypes.tsx +++ b/src/store/sunburstTypes.tsx @@ -23,3 +23,16 @@ export const generateEmptyPhenotype = () => ({ disabled: true, valueText: '', }); + +export const generatePhenotypeByTitle = (title: string, key: string) => ({ + title: title, + children: [], + results: 0, + exactTagCount: 0, + key: key, + text: '', + name: '', + depth: 0, + disabled: true, + valueText: '', +});