Fix legends hanging around

pull/10616/head
Andrew Watkins 2018-04-20 13:54:35 -07:00
parent 4f00cfbba8
commit f6d8a9ea41
7 changed files with 68 additions and 20 deletions

View File

@ -199,6 +199,13 @@ export const setHoverTime = hoverTime => ({
}, },
}) })
export const setActiveCell = activeCellID => ({
type: 'SET_ACTIVE_CELL',
payload: {
activeCellID,
},
})
// Async Action Creators // Async Action Creators
export const getDashboardsAsync = () => async dispatch => { export const getDashboardsAsync = () => async dispatch => {

View File

@ -10,6 +10,7 @@ const initialState = {
isEditMode: false, isEditMode: false,
cellQueryStatus: {queryID: null, status: null}, cellQueryStatus: {queryID: null, status: null},
hoverTime: NULL_HOVER_TIME, hoverTime: NULL_HOVER_TIME,
activeCellID: '',
} }
import { import {
@ -320,6 +321,11 @@ export default function ui(state = initialState, action) {
return {...state, hoverTime} return {...state, hoverTime}
} }
case 'SET_ACTIVE_CELL': {
const {activeCellID} = action.payload
return {...state, activeCellID}
}
} }
return state return state

View File

@ -35,9 +35,7 @@ class Dygraph extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
isHidden: true,
staticLegendHeight: null, staticLegendHeight: null,
isHoveringThisGraph: false,
} }
} }
@ -214,14 +212,11 @@ class Dygraph extends Component {
handleHideLegend = () => { handleHideLegend = () => {
this.props.handleSetHoverTime(NULL_HOVER_TIME) this.props.handleSetHoverTime(NULL_HOVER_TIME)
this.setState({isHidden: true, isHoveringThisGraph: false})
} }
handleShowLegend = e => { handleShowLegend = e => {
const newTime = this.eventToTimestamp(e) const newTime = this.eventToTimestamp(e)
this.props.handleSetHoverTime(newTime) this.props.handleSetHoverTime(newTime)
this.setState({isHidden: false, isHoveringThisGraph: true})
} }
get lineColors() { get lineColors() {
@ -284,8 +279,8 @@ class Dygraph extends Component {
} }
render() { render() {
const {isHidden, staticLegendHeight} = this.state const {staticLegendHeight} = this.state
const {staticLegend, children} = this.props const {staticLegend, children, cellID} = this.props
const nestedGraph = (children && children.length && children[0]) || children const nestedGraph = (children && children.length && children[0]) || children
let dygraphStyle = {...this.props.containerStyle, zIndex: '2'} let dygraphStyle = {...this.props.containerStyle, zIndex: '2'}
if (staticLegend) { if (staticLegend) {
@ -308,7 +303,7 @@ class Dygraph extends Component {
staticLegendHeight={staticLegendHeight} staticLegendHeight={staticLegendHeight}
/> />
<DygraphLegend <DygraphLegend
isHidden={isHidden} cellID={cellID}
dygraph={this.dygraph} dygraph={this.dygraph}
onHide={this.handleHideLegend} onHide={this.handleHideLegend}
onShow={this.handleShowLegend} onShow={this.handleShowLegend}
@ -372,6 +367,7 @@ Dygraph.defaultProps = {
} }
Dygraph.propTypes = { Dygraph.propTypes = {
cellID: string,
handleSetHoverTime: func, handleSetHoverTime: func,
axes: shape({ axes: shape({
y: shape({ y: shape({

View File

@ -1,11 +1,14 @@
import React, {Component} from 'react' import React, {Component} from 'react'
import {connect} from 'react-redux'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import _ from 'lodash' import _ from 'lodash'
import classnames from 'classnames' import classnames from 'classnames'
import uuid from 'uuid' import uuid from 'uuid'
import * as actions from 'src/dashboards/actions'
import {makeLegendStyles, removeMeasurement} from 'shared/graphs/helpers' import {makeLegendStyles, removeMeasurement} from 'shared/graphs/helpers'
import {ErrorHandling} from 'src/shared/decorators/errors' import {ErrorHandling} from 'src/shared/decorators/errors'
import {NO_CELL} from 'src/shared/constants'
@ErrorHandling @ErrorHandling
class DygraphLegend extends Component { class DygraphLegend extends Component {
@ -30,6 +33,7 @@ class DygraphLegend extends Component {
isFilterVisible: false, isFilterVisible: false,
legendStyles: {}, legendStyles: {},
pageX: null, pageX: null,
cellID: null,
} }
} }
@ -43,6 +47,7 @@ class DygraphLegend extends Component {
} }
highlightCallback = _.throttle(e => { highlightCallback = _.throttle(e => {
this.props.setActiveCell(this.props.cellID)
this.setState({pageX: e.pageX}) this.setState({pageX: e.pageX})
this.props.onShow(e) this.props.onShow(e)
}, 60) }, 60)
@ -84,10 +89,15 @@ class DygraphLegend extends Component {
const isMouseHoveringLegend = mouseInLegendY && mouseInLegendX const isMouseHoveringLegend = mouseInLegendY && mouseInLegendX
if (!isMouseHoveringLegend) { if (!isMouseHoveringLegend) {
this.props.onHide() this.handleHide()
} }
} }
handleHide = () => {
this.props.onHide()
this.props.setActiveCell(NO_CELL)
}
handleToggleFilter = () => { handleToggleFilter = () => {
this.setState({ this.setState({
isFilterVisible: !this.state.isFilterVisible, isFilterVisible: !this.state.isFilterVisible,
@ -120,7 +130,7 @@ class DygraphLegend extends Component {
} }
render() { render() {
const {dygraph, onHide, isHidden} = this.props const {dygraph} = this.props
const { const {
pageX, pageX,
@ -140,7 +150,6 @@ class DygraphLegend extends Component {
const ordered = isAscending ? sorted : sorted.reverse() const ordered = isAscending ? sorted : sorted.reverse()
const filtered = ordered.filter(s => s.label.match(filterText)) const filtered = ordered.filter(s => s.label.match(filterText))
const hidden = isHidden ? 'hidden' : ''
const style = makeLegendStyles(dygraph.graphDiv, this.legendNodeRef, pageX) const style = makeLegendStyles(dygraph.graphDiv, this.legendNodeRef, pageX)
const renderSortAlpha = ( const renderSortAlpha = (
@ -174,11 +183,12 @@ class DygraphLegend extends Component {
<div className="sort-btn--bottom">9</div> <div className="sort-btn--bottom">9</div>
</button> </button>
) )
return ( return (
<div <div
className={`dygraph-legend ${hidden}`} className={`dygraph-legend ${this.hidden}`}
ref={el => (this.legendNodeRef = el)} ref={el => (this.legendNodeRef = el)}
onMouseLeave={onHide} onMouseLeave={this.handleHide}
style={style} style={style}
> >
<div className="dygraph-legend--header"> <div className="dygraph-legend--header">
@ -233,15 +243,40 @@ class DygraphLegend extends Component {
</div> </div>
) )
} }
get isVisible() {
const {cellID, activeCellID, isDragging} = this.props
return cellID === activeCellID && !isDragging
}
get hidden() {
if (this.isVisible) {
return ''
}
return 'hidden'
}
} }
const {bool, func, shape} = PropTypes const {bool, func, shape, string} = PropTypes
DygraphLegend.propTypes = { DygraphLegend.propTypes = {
dygraph: shape({}), dygraph: shape({}),
cellID: string.isRequired,
onHide: func.isRequired, onHide: func.isRequired,
onShow: func.isRequired, onShow: func.isRequired,
isHidden: bool.isRequired, isDragging: bool.isRequired,
activeCellID: string.isRequired,
setActiveCell: func.isRequired,
} }
export default DygraphLegend const mapDispatchToProps = {
setActiveCell: actions.setActiveCell,
}
const mapStateToProps = ({dashboardUI}) => ({
activeCellID: dashboardUI.activeCellID,
})
export default connect(mapStateToProps, mapDispatchToProps)(DygraphLegend)

View File

@ -53,6 +53,7 @@ const Layout = (
templates, templates,
timeRange, timeRange,
isEditable, isEditable,
isDragging,
onEditCell, onEditCell,
onCloneCell, onCloneCell,
autoRefresh, autoRefresh,
@ -84,6 +85,7 @@ const Layout = (
inView={cell.inView} inView={cell.inView}
axes={axes} axes={axes}
type={type} type={type}
isDragging={isDragging}
tableOptions={tableOptions} tableOptions={tableOptions}
staticLegend={IS_STATIC_LEGEND(legend)} staticLegend={IS_STATIC_LEGEND(legend)}
cellHeight={h} cellHeight={h}
@ -114,6 +116,7 @@ Layout.contextTypes = {
} }
const propTypes = { const propTypes = {
isDragging: bool,
autoRefresh: number.isRequired, autoRefresh: number.isRequired,
manualRefresh: number, manualRefresh: number,
timeRange: shape({ timeRange: shape({

View File

@ -36,9 +36,9 @@ class LineGraph extends Component {
const { const {
data, data,
axes, axes,
cell,
title, title,
colors, colors,
cellID,
onZoom, onZoom,
queries, queries,
hoverTime, hoverTime,
@ -96,14 +96,14 @@ class LineGraph extends Component {
<div className="dygraph graph--hasYLabel" style={{height: '100%'}}> <div className="dygraph graph--hasYLabel" style={{height: '100%'}}>
{isRefreshing ? <GraphLoadingDots /> : null} {isRefreshing ? <GraphLoadingDots /> : null}
<Dygraph <Dygraph
cell={cell}
axes={axes} axes={axes}
cellID={cellID}
colors={colors} colors={colors}
onZoom={onZoom} onZoom={onZoom}
labels={labels} labels={labels}
hoverTime={hoverTime}
queries={queries} queries={queries}
options={options} options={options}
hoverTime={hoverTime}
timeRange={timeRange} timeRange={timeRange}
isBarGraph={isBarGraph} isBarGraph={isBarGraph}
timeSeries={timeSeries} timeSeries={timeSeries}
@ -157,6 +157,7 @@ LineGraph.defaultProps = {
} }
LineGraph.propTypes = { LineGraph.propTypes = {
cellID: string,
axes: shape({ axes: shape({
y: shape({ y: shape({
bounds: array, bounds: array,
@ -190,7 +191,6 @@ LineGraph.propTypes = {
isInDataExplorer: bool, isInDataExplorer: bool,
setResolution: func, setResolution: func,
cellHeight: number, cellHeight: number,
cell: shape(),
onZoom: func, onZoom: func,
resizeCoords: shape(), resizeCoords: shape(),
queries: arrayOf(shape({}).isRequired).isRequired, queries: arrayOf(shape({}).isRequired).isRequired,

View File

@ -115,6 +115,7 @@ const RefreshingGraph = ({
return ( return (
<RefreshingLineGraph <RefreshingLineGraph
axes={axes} axes={axes}
cellID={cellID}
colors={colors} colors={colors}
onZoom={onZoom} onZoom={onZoom}
queries={queries} queries={queries}