Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chart improvements #989

Merged
merged 25 commits into from
Oct 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
898efcb
Extract rendering of dashboard display icons into own component
bjoernricks Oct 1, 2018
ba002c3
Resort methods in DataDisplay
bjoernricks Oct 1, 2018
3bdb9d7
No need to put hasSvg into the DataDisplay state
bjoernricks Oct 1, 2018
ddd7416
Allow to toggle the Legend in children of DataDisplay
bjoernricks Oct 2, 2018
4423392
Use DataDisplay icons prop as render props
bjoernricks Oct 2, 2018
32cfade
Add a chartState to DataDisplay
bjoernricks Oct 2, 2018
b16d763
Move MENU_PLACEHOLDER_WIDTH to a new js module
bjoernricks Oct 2, 2018
377f808
Add a default shouldUpdate implementation for charts
bjoernricks Oct 2, 2018
49d243f
Use new shouldUpdate for Line, Donut and Bar chart
bjoernricks Oct 2, 2018
1c72750
Fix indentation
bjoernricks Oct 2, 2018
b483e9e
Use showLegend prop to toggle displaying chart Legends
bjoernricks Oct 2, 2018
8062970
Fix calculating the Bar chart width with Legend displayed
bjoernricks Oct 2, 2018
36ed925
Deactivate toggle legend buttons for charts without legends
bjoernricks Oct 2, 2018
b67033e
Move LineChart proptypes to the bottom
bjoernricks Oct 2, 2018
bc3271a
Rename displayLegend into showLegend
bjoernricks Oct 2, 2018
f49f80a
Don't crash if svg ref isn't set in LineChart
bjoernricks Oct 2, 2018
bf2d14a
Use shouldUpdate func at ScheduleChart
bjoernricks Oct 2, 2018
1dc6076
Avoid crashing DataDisplay on svg download
bjoernricks Oct 2, 2018
041ead1
Fix displaying the svg download icon
bjoernricks Oct 2, 2018
c01917f
Disable svg downloads for data table displays
bjoernricks Oct 2, 2018
274deff
Allow to toggle legends of different charts
bjoernricks Oct 2, 2018
db73eef
Fix LineChart update
bjoernricks Oct 2, 2018
741028d
Update shouldUpdate to consider showLegend prop
bjoernricks Oct 2, 2018
9ae37ac
Allow to toggle 2d/3d donut view
bjoernricks Oct 2, 2018
ed66c95
Rename chart state to child state
bjoernricks Oct 2, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions gsa/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,9 @@ set (GSA_JS_SRC_FILES
${GSA_SRC_DIR}/src/web/components/chart/tooltip.js
${GSA_SRC_DIR}/src/web/components/chart/topology.js
${GSA_SRC_DIR}/src/web/components/chart/utils/arc.js
${GSA_SRC_DIR}/src/web/components/chart/utils/constants.js
${GSA_SRC_DIR}/src/web/components/chart/utils/path.js
${GSA_SRC_DIR}/src/web/components/chart/utils/update.js
${GSA_SRC_DIR}/src/web/components/chart/wordcloud.js
${GSA_SRC_DIR}/src/web/components/comment/comment.js
${GSA_SRC_DIR}/src/web/components/dashboard/controls.js
Expand All @@ -219,6 +221,7 @@ set (GSA_JS_SRC_FILES
${GSA_SRC_DIR}/src/web/components/dashboard/display/cvss/cvsstabledisplay.js
${GSA_SRC_DIR}/src/web/components/dashboard/display/cvss/cvsstransform.js
${GSA_SRC_DIR}/src/web/components/dashboard/display/datadisplay.js
${GSA_SRC_DIR}/src/web/components/dashboard/display/datadisplayicons.js
${GSA_SRC_DIR}/src/web/components/dashboard/display/datatable.js
${GSA_SRC_DIR}/src/web/components/dashboard/display/datatabledisplay.js
${GSA_SRC_DIR}/src/web/components/dashboard/display/display.js
Expand Down
78 changes: 55 additions & 23 deletions gsa/src/web/components/chart/bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,13 @@ import {scaleBand, scaleLinear} from 'd3-scale';
import {shorten} from 'gmp/utils/string';
import {isDefined} from 'gmp/utils/identity';

import {
MENU_PLACEHOLDER_WIDTH,
} from 'web/components/dashboard/display/datadisplay';

import Layout from 'web/components/layout/layout';

import PropTypes from 'web/utils/proptypes';

import {MENU_PLACEHOLDER_WIDTH} from './utils/constants';
import {shouldUpdate} from './utils/update';

import Axis from './axis';
import Group from './group';
import Legend from './legend';
Expand Down Expand Up @@ -67,16 +66,58 @@ const tickFormat = val => {

class BarChart extends React.Component {

shouldComponentUpdate(nextProps) {
return this.props.width !== nextProps.width ||
this.props.height !== nextProps.height ||
this.props.data !== nextProps.data;
constructor(...args) {
super(...args);

this.legendRef = React.createRef();

this.state = {
width: this.getWidth(),
};
}

shouldComponentUpdate(nextProps, nextState) {
return shouldUpdate(nextProps, this.props) ||
nextState.width !== this.state.width;
}

componentDidMount() {
this.update();
}

componentDidUpdate() {
this.update();
}

update() {
const width = this.getWidth();
if (width !== this.state.width) {
this.setState({width});
}
}

getWidth() {
let {width} = this.props;
const {current: legend} = this.legendRef;

width = width - MENU_PLACEHOLDER_WIDTH;

if (legend !== null) {
const {width: legendWidth} = legend.getBoundingClientRect();
width = width - legendWidth - LEGEND_MARGIN;
}

if (width < MIN_WIDTH) {
width = MIN_WIDTH;
}

return width;
}

render() {
const {
data = [],
displayLegend = true,
showLegend = true,
height,
xLabel = '',
yLabel = '',
Expand All @@ -85,16 +126,7 @@ class BarChart extends React.Component {
onDataClick,
onLegendItemClick,
} = this.props;
let {width} = this.props;

if (this.legend) {
const {width: legendWidth} = this.legend.getBoundingClientRect();
width = width - legendWidth - LEGEND_MARGIN;
}

if (width < MIN_WIDTH) {
width = MIN_WIDTH;
}
const {width} = this.state;

const xValues = data.map(d => d.x);
const yValues = data.map(d => d.y);
Expand All @@ -108,7 +140,7 @@ class BarChart extends React.Component {
const marginLeft = horizontal ? margin.left +
Math.min(MAX_LABEL_LENGTH, maxLabelLength) * 4 : margin.left;

const maxWidth = width - marginLeft - margin.right - MENU_PLACEHOLDER_WIDTH;
const maxWidth = width - marginLeft - margin.right;
let maxHeight = height - margin.top - margin.bottom;

if (isDefined(xLabel)) {
Expand Down Expand Up @@ -195,9 +227,9 @@ class BarChart extends React.Component {
))}
</Group>
</Svg>
{displayLegend && data.length > 0 &&
{showLegend && data.length > 0 &&
<Legend
innerRef={ref => this.legend = ref}
innerRef={this.legendRef}
data={data}
onItemClick={onLegendItemClick}
/>
Expand Down Expand Up @@ -226,9 +258,9 @@ BarChart.propTypes = {
color: PropTypes.toString.isRequired,
toolTip: PropTypes.elementOrString,
})).isRequired,
displayLegend: PropTypes.bool,
height: PropTypes.number.isRequired,
horizontal: PropTypes.bool,
showLegend: PropTypes.bool,
svgRef: PropTypes.ref,
width: PropTypes.number.isRequired,
xLabel: PropTypes.toString,
Expand Down
16 changes: 7 additions & 9 deletions gsa/src/web/components/chart/donut.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ import {setRef} from 'web/utils/render';
import Theme from 'web/utils/theme';

import arc from './utils/arc';

import {
MENU_PLACEHOLDER_WIDTH,
} from 'web/components/dashboard/display/datadisplay';
import {MENU_PLACEHOLDER_WIDTH} from './utils/constants';
import {shouldUpdate} from './utils/update';

import Layout from 'web/components/layout/layout';

Expand Down Expand Up @@ -152,9 +150,7 @@ class DonutChart extends React.Component {
}

shouldComponentUpdate(nextProps, nextState) {
return nextProps.data !== this.props.data ||
nextProps.width !== this.props.width ||
nextProps.height !== this.props.height ||
return shouldUpdate(nextProps, this.props) ||
nextState.width !== this.state.width ||
nextProps.show3d !== this.props.show3d;
}
Expand All @@ -165,7 +161,7 @@ class DonutChart extends React.Component {
if (width !== this.state.width) {
this.setState({width});
}
this.separateLabels();
this.separateLabels();
}

componentDidUpdate() {
Expand Down Expand Up @@ -241,6 +237,7 @@ class DonutChart extends React.Component {
height,
svgRef,
show3d = true,
showLegend = true,
onDataClick,
onLegendItemClick,
} = this.props;
Expand Down Expand Up @@ -339,7 +336,7 @@ class DonutChart extends React.Component {
/>
}
</Svg>
{data.length > 0 &&
{data.length > 0 && showLegend &&
<Legend
data={data}
innerRef={this.legendRef}
Expand All @@ -356,6 +353,7 @@ DonutChart.propTypes = {
height: PropTypes.number.isRequired,
innerRadius: PropTypes.number,
show3d: PropTypes.bool,
showLegend: PropTypes.bool,
svgRef: PropTypes.ref,
width: PropTypes.number.isRequired,
onDataClick: PropTypes.func,
Expand Down
101 changes: 55 additions & 46 deletions gsa/src/web/components/chart/line.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,15 @@ import {isDefined} from 'gmp/utils/identity';

import date from 'gmp/models/date';

import {
MENU_PLACEHOLDER_WIDTH,
} from 'web/components/dashboard/display/datadisplay';

import Layout from 'web/components/layout/layout';

import PropTypes from 'web/utils/proptypes';
import Theme from 'web/utils/theme';
import {setRef} from 'web/utils/render';

import {MENU_PLACEHOLDER_WIDTH} from './utils/constants';
import {shouldUpdate} from './utils/update';

import Legend, {Item, Label, Line as LegendLine} from './legend';
import Axis from './axis';
import Svg from './svg';
Expand Down Expand Up @@ -156,29 +155,6 @@ CrossY2.propTypes = crossPropTypes;

class LineChart extends React.Component {

static propTypes = {
data: PropTypes.arrayOf(PropTypes.shape({
x: PropTypes.oneOfType([
PropTypes.number,
PropTypes.date,
]).isRequired,
y: PropTypes.number.isRequired,
y2: PropTypes.number.isRequired,
})),
displayLegend: PropTypes.bool,
height: PropTypes.number.isRequired,
numTicks: PropTypes.number,
svgRef: PropTypes.ref,
timeline: PropTypes.bool,
width: PropTypes.number.isRequired,
xAxisLabel: PropTypes.toString,
y2AxisLabel: PropTypes.toString,
y2Line: lineDataPropType,
yAxisLabel: PropTypes.toString,
yLine: lineDataPropType,
onRangeSelected: PropTypes.func,
};

constructor(...args) {
super(...args);

Expand All @@ -194,23 +170,20 @@ class LineChart extends React.Component {

this.state = {
displayInfo: false,
...this.update(),
...this.stateFromWidth(this.getWidth()),
};
}

componentDidUpdate() {

this.setState(this.update());
this.update();
}

componentDidMount() {
this.setState(this.update());
this.update();
}

shouldComponentUpdate(nextProps, nextState) {
return nextProps.data !== this.props.data ||
nextProps.width !== this.props.width ||
nextProps.height !== this.props.height ||
return shouldUpdate(nextProps, this.props) ||
nextState.width !== this.state.width ||
nextState.rangeX !== this.state.rangeX ||
nextState.infoX !== this.state.infoX ||
Expand All @@ -228,6 +201,10 @@ class LineChart extends React.Component {
}

handleMouseMove(event) {
if (!this.svg) {
return;
}

const box = this.svg.getBoundingClientRect();
const mouseX = event.clientX - box.left -
margin.left - 1;
Expand Down Expand Up @@ -305,29 +282,37 @@ class LineChart extends React.Component {
}

getWidth() {
const {width} = this.props;
let {width} = this.props;
const {current: legend} = this.legendRef;

if (legend === null) {
return width;
width = width - MENU_PLACEHOLDER_WIDTH;

if (legend !== null) {
const {width: legendWidth} = legend.getBoundingClientRect();
width = width - legendWidth - LEGEND_MARGIN;
}

if (width < MIN_WIDTH) {
width = MIN_WIDTH;
}

const {width: legendWidth} = legend.getBoundingClientRect();
return width - legendWidth - LEGEND_MARGIN - MENU_PLACEHOLDER_WIDTH;
return width;
}

update() {
const width = this.getWidth();
if (width !== this.state.width) {
this.setState(this.stateFromWidth(width));
}
}

stateFromWidth(width) {
const {
data = [],
height,
timeline = false,
} = this.props;

let width = this.getWidth();
if (width < MIN_WIDTH) {
width = MIN_WIDTH;
}

const maxWidth = width - margin.left - margin.right;
const maxHeight = height - margin.top - margin.bottom;

Expand Down Expand Up @@ -550,7 +535,7 @@ class LineChart extends React.Component {
} = this.state;
const {
data = [],
displayLegend = true,
showLegend = true,
svgRef,
xAxisLabel,
yAxisLabel,
Expand Down Expand Up @@ -664,7 +649,7 @@ class LineChart extends React.Component {
{this.renderRange()}
</Group>
</Svg>
{hasLines && displayLegend &&
{hasLines && showLegend &&
<Legend
innerRef={this.legendRef}
data={[yLine, y2Line]}
Expand All @@ -688,6 +673,30 @@ class LineChart extends React.Component {
}
}

LineChart.propTypes = {
data: PropTypes.arrayOf(PropTypes.shape({
x: PropTypes.oneOfType([
PropTypes.number,
PropTypes.date,
]).isRequired,
y: PropTypes.number.isRequired,
y2: PropTypes.number.isRequired,
})),
height: PropTypes.number.isRequired,
numTicks: PropTypes.number,
showLegend: PropTypes.bool,
svgRef: PropTypes.ref,
timeline: PropTypes.bool,
width: PropTypes.number.isRequired,
xAxisLabel: PropTypes.toString,
y2AxisLabel: PropTypes.toString,
y2Line: lineDataPropType,
yAxisLabel: PropTypes.toString,
yLine: lineDataPropType,
onRangeSelected: PropTypes.func,
};


export default LineChart;

// vim: set ts=2 sw=2 tw=80:
Loading