Add colors and move capability to charts

This commit is contained in:
Thomas Nordquist
2019-06-17 18:08:35 +02:00
parent 0f9c2cd36f
commit 8c1c6387c9
13 changed files with 301 additions and 20 deletions

View File

@@ -53,6 +53,7 @@ function Chart(props: Props) {
<br />
{treeNode ? (
<TopicPlot
color={props.parameters.color}
interpolation={props.parameters.interpolation}
range={props.parameters.range ? [props.parameters.range.from, props.parameters.range.to] : undefined}
history={treeNode.messageHistory}

View File

@@ -0,0 +1,71 @@
import * as React from 'react'
import { bindActionCreators } from 'redux'
import { chartActions } from '../../../actions'
import { ChartParameters } from '../../../reducers/Charts'
import { connect } from 'react-redux'
import { Menu, MenuItem } from '@material-ui/core'
import { colors as createColors } from './colors'
function chartParametersForColor(chart: ChartParameters, color?: string) {
return {
color,
topic: chart.topic,
dotPath: chart.dotPath,
}
}
const colors: Array<string> = createColors()
function ColorSettings(props: {
chart: ChartParameters
actions: {
chart: typeof chartActions
}
anchorEl?: Element
open: boolean
close: () => void
}) {
const setColor = React.useCallback(
(color?: string) => props.actions.chart.updateChart(chartParametersForColor(props.chart, color)),
[props.chart]
)
const menuItems = React.useMemo(() => {
return colors.map(color => (
<MenuItem
style={{ minWidth: '8em', minHeight: '36px', backgroundColor: color, textAlign: 'center' }}
key={color}
onClick={() => setColor(color)}
>
{props.chart.color === color ? 'X' : ''}
</MenuItem>
))
}, [colors, props.chart])
return (
<Menu anchorEl={props.anchorEl} open={props.open} onClose={props.close}>
<MenuItem
style={{ minWidth: '8em', minHeight: '36px', textAlign: 'center' }}
key="none"
onClick={() => setColor()}
selected={props.chart.color === undefined}
>
default
</MenuItem>
{menuItems}
</Menu>
)
}
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
export default connect(
undefined,
mapDispatchToProps
)(ColorSettings)

View File

@@ -23,7 +23,7 @@ function InterpolationSettings(props: {
}
anchorEl?: Element
open: boolean
onClose: () => void
close: () => void
}) {
const callbacks = React.useMemo(() => {
const createCurveCallback = (curve: PlotCurveTypes) => () => {
@@ -46,7 +46,7 @@ function InterpolationSettings(props: {
}, [curves, props.chart])
return (
<Menu id="long-menu" anchorEl={props.anchorEl} open={props.open} onClose={props.onClose}>
<Menu anchorEl={props.anchorEl} open={props.open} onClose={props.close}>
{menuItems}
</Menu>
)

View File

@@ -0,0 +1,35 @@
import * as React from 'react'
import { ChartParameters } from '../../../reducers/Charts'
import { Menu, MenuItem, TextField, Typography } from '@material-ui/core'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { chartActions } from '../../../actions'
function MoveUp(props: { actions: { chart: typeof chartActions }; chart: ChartParameters; close: () => void }) {
const moveUp = React.useCallback(() => {
props.actions.chart.moveChartUp({
topic: props.chart.topic,
dotPath: props.chart.dotPath,
})
props.close()
}, [props.chart])
return (
<MenuItem key="size" onClick={moveUp}>
Move up
</MenuItem>
)
}
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
export default connect(
undefined,
mapDispatchToProps
)(MoveUp)

View File

@@ -34,13 +34,7 @@ function RangeSettings(props: {
const setFromHandler = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => setRangeFrom(e.target.value), [])
const setToHandler = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => setRangeTo(e.target.value), [])
return (
<Menu
style={{ textAlign: 'center' }}
id="long-menu"
anchorEl={props.anchorEl}
open={props.open}
onClose={props.onClose}
>
<Menu style={{ textAlign: 'center' }} anchorEl={props.anchorEl} open={props.open} onClose={props.onClose}>
<Typography>Define custom ranges for the Y-Axis</Typography>
<div style={{ padding: '0 16px' }}>
<TextField

View File

@@ -0,0 +1,53 @@
import * as React from 'react'
import { ChartParameters } from '../../../reducers/Charts'
import { Menu, MenuItem, TextField, Typography } from '@material-ui/core'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { chartActions } from '../../../actions'
function Size(props: {
actions: { chart: typeof chartActions }
chart: ChartParameters
anchorEl?: Element
open: boolean
close: () => void
}) {
const setChartWidth = (width?: 'big' | 'medium' | 'small') => () => {
props.actions.chart.updateChart({
width,
topic: props.chart.topic,
dotPath: props.chart.dotPath,
})
props.close()
}
return (
<Menu anchorEl={props.anchorEl} open={props.open} onClose={props.close}>
<MenuItem selected={props.chart.width === undefined} onClick={setChartWidth()}>
auto
</MenuItem>
<MenuItem selected={props.chart.width === 'big'} onClick={setChartWidth('big')}>
100% width
</MenuItem>
<MenuItem selected={props.chart.width === 'medium'} onClick={setChartWidth('medium')}>
50% width
</MenuItem>
<MenuItem selected={props.chart.width === 'small'} onClick={setChartWidth('small')}>
33% width
</MenuItem>
</Menu>
)
}
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
export default connect(
undefined,
mapDispatchToProps
)(Size)

View File

@@ -0,0 +1,46 @@
import {
amber,
orange,
pink,
purple,
deepPurple,
teal,
red,
green,
lime,
indigo,
yellow,
brown,
blueGrey,
} from '@material-ui/core/colors'
export function colors() {
function colorToInt(color: string): [number, number, number] {
const str = color.replace('#', '')
return [parseInt(str.slice(0, 2), 16), parseInt(str.slice(2, 4), 16), parseInt(str.slice(4, 6), 16)]
}
function colorCompare(colorA: string, colorB: string) {
const a = colorToInt(colorA)
const b = colorToInt(colorB)
return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2) + Math.pow(a[2] - b[2], 2))
}
const colors: Array<string> = [
brown,
blueGrey,
amber,
orange,
pink,
purple,
deepPurple,
teal,
red,
green,
lime,
indigo,
yellow,
]
.map(color => [color[200], color[500], color[700]])
.reduce((a, b) => a.concat(b), [])
.sort((a, b) => colorCompare(a, b))
return colors
}

View File

@@ -3,6 +3,9 @@ import InterpolationSettings from './InterpolationSettings'
import { ChartParameters } from '../../../reducers/Charts'
import { Menu, MenuItem } from '@material-ui/core'
import RangeSettings from './RangeSettings'
import Size from './Size'
import MoveUp from './MoveUp'
import ColorSettings from './ColorSettings'
function ChartSettings(props: {
open: boolean
@@ -12,21 +15,37 @@ function ChartSettings(props: {
}) {
const [rangeVisible, setRangeVisible] = React.useState(false)
const [interpolationVisible, setInterpolationVisible] = React.useState(false)
const [sizeVisible, setSizeVisible] = React.useState(false)
const [colorVisible, setColorVisible] = React.useState(false)
const toggleRange = React.useCallback(() => {
if (!rangeVisible && open) {
if (open) {
props.close()
}
setRangeVisible(!rangeVisible)
}, [rangeVisible, open])
const toggleInterpolation = React.useCallback(() => {
if (!interpolationVisible && open) {
if (open) {
props.close()
}
setInterpolationVisible(!interpolationVisible)
}, [interpolationVisible, open])
const toggleSize = React.useCallback(() => {
if (open) {
props.close()
}
setSizeVisible(!sizeVisible)
}, [sizeVisible, open])
const toggleColor = React.useCallback(() => {
if (open) {
props.close()
}
setColorVisible(!colorVisible)
}, [colorVisible, open])
return (
<span>
<Menu id="long-menu" anchorEl={props.anchorEl.current} open={props.open} onClose={props.close}>
@@ -36,14 +55,23 @@ function ChartSettings(props: {
<MenuItem key="interpolation" onClick={toggleInterpolation}>
Curve interpolation
</MenuItem>
<MenuItem key="size" onClick={toggleSize}>
Size
</MenuItem>
<MenuItem key="color" onClick={toggleColor}>
Color
</MenuItem>
<MoveUp chart={props.chart} close={props.close} />
</Menu>
<RangeSettings chart={props.chart} anchorEl={props.anchorEl.current} open={rangeVisible} onClose={toggleRange} />
<InterpolationSettings
chart={props.chart}
anchorEl={props.anchorEl.current}
open={interpolationVisible}
onClose={toggleInterpolation}
close={toggleInterpolation}
/>
<Size chart={props.chart} anchorEl={props.anchorEl.current} open={sizeVisible} close={toggleSize} />
<ColorSettings chart={props.chart} anchorEl={props.anchorEl.current} open={colorVisible} close={toggleColor} />
</span>
)
}

View File

@@ -28,6 +28,19 @@ function spacingForChartCount(count: number): 4 | 6 | 12 {
}
}
function mapWidth(width: 'big' | 'medium' | 'small' | undefined, calculatedSpacing: 4 | 6 | 12): 4 | 6 | 12 {
switch (width) {
case 'big':
return 12
case 'medium':
return 6
case 'small':
return 4
default:
return calculatedSpacing
}
}
function ChartPanel(props: Props) {
const chartsInView = props.charts.count()
@@ -53,7 +66,7 @@ function ChartPanel(props: Props) {
timeout={{ enter: 500, exit: 500 }}
classNames="example"
>
<Grid item xs={spacing}>
<Grid item xs={mapWidth(chartParameters.width, spacing)}>
<Chart parameters={chartParameters} />
</Grid>
</CSSTransition>