Skip to content
Permalink
premodern
Switch branches/tags
Go to file
* run prettier
2 contributors

Users who have contributed to this file

@mcnuttandrew @benshope
142 lines (131 sloc) 4.44 KB
// Copyright (c) 2016 - 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import React from 'react';
import Sunburst from 'sunburst';
import {EXTENDED_DISCRETE_COLOR_RANGE} from 'theme';
import {LabelSeries} from 'index';
import D3FlareData from '../datasets/d3-flare-example.json';
const LABEL_STYLE = {
fontSize: '8px',
textAnchor: 'middle'
};
/**
* Recursively work backwards from highlighted node to find path of valud nodes
* @param {Object} node - the current node being considered
* @returns {Array} an array of strings describing the key route to the current node
*/
function getKeyPath(node) {
if (!node.parent) {
return ['root'];
}
return [(node.data && node.data.name) || node.name].concat(
getKeyPath(node.parent)
);
}
/**
* Recursively modify data depending on whether or not each cell has been selected by the hover/highlight
* @param {Object} data - the current node being considered
* @param {Object|Boolean} keyPath - a map of keys that are in the highlight path
* if this is false then all nodes are marked as selected
* @returns {Object} Updated tree structure
*/
function updateData(data, keyPath) {
if (data.children) {
data.children.map(child => updateData(child, keyPath));
}
// add a fill to all the uncolored cells
if (!data.hex) {
data.style = {
fill: EXTENDED_DISCRETE_COLOR_RANGE[5]
};
}
data.style = {
...data.style,
fillOpacity: keyPath && !keyPath[data.name] ? 0.2 : 1
};
return data;
}
const decoratedData = updateData(D3FlareData, false);
export default class BasicSunburst extends React.Component {
state = {
pathValue: false,
data: decoratedData,
finalValue: 'SUNBURST',
clicked: false
};
render() {
const {clicked, data, finalValue, pathValue} = this.state;
return (
<div className="basic-sunburst-example-wrapper">
<div>
{clicked ? 'click to unlock selection' : 'click to lock selection'}
</div>
<Sunburst
animation
className="basic-sunburst-example"
hideRootNode
onValueMouseOver={node => {
if (clicked) {
return;
}
const path = getKeyPath(node).reverse();
const pathAsMap = path.reduce((res, row) => {
res[row] = true;
return res;
}, {});
this.setState({
finalValue: path[path.length - 1],
pathValue: path.join(' > '),
data: updateData(decoratedData, pathAsMap)
});
}}
onValueMouseOut={() =>
clicked
? () => {}
: this.setState({
pathValue: false,
finalValue: false,
data: updateData(decoratedData, false)
})
}
onValueClick={() => this.setState({clicked: !clicked})}
style={{
stroke: '#ddd',
strokeOpacity: 0.3,
strokeWidth: '0.5'
}}
colorType="literal"
getSize={d => d.value}
getColor={d => d.hex}
data={data}
height={300}
width={350}
>
{finalValue && (
<LabelSeries
data={[{x: 0, y: 0, label: finalValue, style: LABEL_STYLE}]}
/>
)}
</Sunburst>
<div className="basic-sunburst-example-path-name">{pathValue}</div>
</div>
);
}
}