Add colors and move capability to charts
This commit is contained in:
@@ -106,6 +106,18 @@ export const removeChart = (chartParameters: ChartParameters) => async (
|
|||||||
dispatch(saveCharts())
|
dispatch(saveCharts())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const moveChartUp = (parameters: { topic: string; dotPath?: string }) => async (
|
||||||
|
dispatch: Dispatch<any>,
|
||||||
|
getState: () => AppState
|
||||||
|
) => {
|
||||||
|
dispatch({
|
||||||
|
topic: parameters.topic,
|
||||||
|
dotPath: parameters.dotPath,
|
||||||
|
type: ActionTypes.CHARTS_MOVE_UP,
|
||||||
|
})
|
||||||
|
dispatch(saveCharts())
|
||||||
|
}
|
||||||
|
|
||||||
export const setCharts = (charts: Array<ChartParameters>): Action => {
|
export const setCharts = (charts: Array<ChartParameters>): Action => {
|
||||||
return {
|
return {
|
||||||
charts,
|
charts,
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ function Chart(props: Props) {
|
|||||||
<br />
|
<br />
|
||||||
{treeNode ? (
|
{treeNode ? (
|
||||||
<TopicPlot
|
<TopicPlot
|
||||||
|
color={props.parameters.color}
|
||||||
interpolation={props.parameters.interpolation}
|
interpolation={props.parameters.interpolation}
|
||||||
range={props.parameters.range ? [props.parameters.range.from, props.parameters.range.to] : undefined}
|
range={props.parameters.range ? [props.parameters.range.from, props.parameters.range.to] : undefined}
|
||||||
history={treeNode.messageHistory}
|
history={treeNode.messageHistory}
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -23,7 +23,7 @@ function InterpolationSettings(props: {
|
|||||||
}
|
}
|
||||||
anchorEl?: Element
|
anchorEl?: Element
|
||||||
open: boolean
|
open: boolean
|
||||||
onClose: () => void
|
close: () => void
|
||||||
}) {
|
}) {
|
||||||
const callbacks = React.useMemo(() => {
|
const callbacks = React.useMemo(() => {
|
||||||
const createCurveCallback = (curve: PlotCurveTypes) => () => {
|
const createCurveCallback = (curve: PlotCurveTypes) => () => {
|
||||||
@@ -46,7 +46,7 @@ function InterpolationSettings(props: {
|
|||||||
}, [curves, props.chart])
|
}, [curves, props.chart])
|
||||||
|
|
||||||
return (
|
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}
|
{menuItems}
|
||||||
</Menu>
|
</Menu>
|
||||||
)
|
)
|
||||||
|
|||||||
35
app/src/components/ChartPanel/ChartSettings/MoveUp.tsx
Normal file
35
app/src/components/ChartPanel/ChartSettings/MoveUp.tsx
Normal 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)
|
||||||
@@ -34,13 +34,7 @@ function RangeSettings(props: {
|
|||||||
const setFromHandler = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => setRangeFrom(e.target.value), [])
|
const setFromHandler = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => setRangeFrom(e.target.value), [])
|
||||||
const setToHandler = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => setRangeTo(e.target.value), [])
|
const setToHandler = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => setRangeTo(e.target.value), [])
|
||||||
return (
|
return (
|
||||||
<Menu
|
<Menu style={{ textAlign: 'center' }} anchorEl={props.anchorEl} open={props.open} onClose={props.onClose}>
|
||||||
style={{ textAlign: 'center' }}
|
|
||||||
id="long-menu"
|
|
||||||
anchorEl={props.anchorEl}
|
|
||||||
open={props.open}
|
|
||||||
onClose={props.onClose}
|
|
||||||
>
|
|
||||||
<Typography>Define custom ranges for the Y-Axis</Typography>
|
<Typography>Define custom ranges for the Y-Axis</Typography>
|
||||||
<div style={{ padding: '0 16px' }}>
|
<div style={{ padding: '0 16px' }}>
|
||||||
<TextField
|
<TextField
|
||||||
|
|||||||
53
app/src/components/ChartPanel/ChartSettings/Size.tsx
Normal file
53
app/src/components/ChartPanel/ChartSettings/Size.tsx
Normal 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)
|
||||||
46
app/src/components/ChartPanel/ChartSettings/colors.ts
Normal file
46
app/src/components/ChartPanel/ChartSettings/colors.ts
Normal 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
|
||||||
|
}
|
||||||
@@ -3,6 +3,9 @@ import InterpolationSettings from './InterpolationSettings'
|
|||||||
import { ChartParameters } from '../../../reducers/Charts'
|
import { ChartParameters } from '../../../reducers/Charts'
|
||||||
import { Menu, MenuItem } from '@material-ui/core'
|
import { Menu, MenuItem } from '@material-ui/core'
|
||||||
import RangeSettings from './RangeSettings'
|
import RangeSettings from './RangeSettings'
|
||||||
|
import Size from './Size'
|
||||||
|
import MoveUp from './MoveUp'
|
||||||
|
import ColorSettings from './ColorSettings'
|
||||||
|
|
||||||
function ChartSettings(props: {
|
function ChartSettings(props: {
|
||||||
open: boolean
|
open: boolean
|
||||||
@@ -12,21 +15,37 @@ function ChartSettings(props: {
|
|||||||
}) {
|
}) {
|
||||||
const [rangeVisible, setRangeVisible] = React.useState(false)
|
const [rangeVisible, setRangeVisible] = React.useState(false)
|
||||||
const [interpolationVisible, setInterpolationVisible] = 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(() => {
|
const toggleRange = React.useCallback(() => {
|
||||||
if (!rangeVisible && open) {
|
if (open) {
|
||||||
props.close()
|
props.close()
|
||||||
}
|
}
|
||||||
setRangeVisible(!rangeVisible)
|
setRangeVisible(!rangeVisible)
|
||||||
}, [rangeVisible, open])
|
}, [rangeVisible, open])
|
||||||
|
|
||||||
const toggleInterpolation = React.useCallback(() => {
|
const toggleInterpolation = React.useCallback(() => {
|
||||||
if (!interpolationVisible && open) {
|
if (open) {
|
||||||
props.close()
|
props.close()
|
||||||
}
|
}
|
||||||
setInterpolationVisible(!interpolationVisible)
|
setInterpolationVisible(!interpolationVisible)
|
||||||
}, [interpolationVisible, open])
|
}, [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 (
|
return (
|
||||||
<span>
|
<span>
|
||||||
<Menu id="long-menu" anchorEl={props.anchorEl.current} open={props.open} onClose={props.close}>
|
<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}>
|
<MenuItem key="interpolation" onClick={toggleInterpolation}>
|
||||||
Curve interpolation
|
Curve interpolation
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem key="size" onClick={toggleSize}>
|
||||||
|
Size
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem key="color" onClick={toggleColor}>
|
||||||
|
Color
|
||||||
|
</MenuItem>
|
||||||
|
<MoveUp chart={props.chart} close={props.close} />
|
||||||
</Menu>
|
</Menu>
|
||||||
<RangeSettings chart={props.chart} anchorEl={props.anchorEl.current} open={rangeVisible} onClose={toggleRange} />
|
<RangeSettings chart={props.chart} anchorEl={props.anchorEl.current} open={rangeVisible} onClose={toggleRange} />
|
||||||
<InterpolationSettings
|
<InterpolationSettings
|
||||||
chart={props.chart}
|
chart={props.chart}
|
||||||
anchorEl={props.anchorEl.current}
|
anchorEl={props.anchorEl.current}
|
||||||
open={interpolationVisible}
|
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>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
function ChartPanel(props: Props) {
|
||||||
const chartsInView = props.charts.count()
|
const chartsInView = props.charts.count()
|
||||||
|
|
||||||
@@ -53,7 +66,7 @@ function ChartPanel(props: Props) {
|
|||||||
timeout={{ enter: 500, exit: 500 }}
|
timeout={{ enter: 500, exit: 500 }}
|
||||||
classNames="example"
|
classNames="example"
|
||||||
>
|
>
|
||||||
<Grid item xs={spacing}>
|
<Grid item xs={mapWidth(chartParameters.width, spacing)}>
|
||||||
<Chart parameters={chartParameters} />
|
<Chart parameters={chartParameters} />
|
||||||
</Grid>
|
</Grid>
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ interface Props {
|
|||||||
theme: Theme
|
theme: Theme
|
||||||
interpolation?: PlotCurveTypes
|
interpolation?: PlotCurveTypes
|
||||||
range?: [number?, number?]
|
range?: [number?, number?]
|
||||||
|
color?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapCurveType(type: PlotCurveTypes | undefined) {
|
function mapCurveType(type: PlotCurveTypes | undefined) {
|
||||||
@@ -58,6 +59,12 @@ export default withTheme((props: Props) => {
|
|||||||
? [props.range[0] || calculatedDomain[0], props.range[1] || calculatedDomain[1]]
|
? [props.range[0] || calculatedDomain[0], props.range[1] || calculatedDomain[1]]
|
||||||
: calculatedDomain
|
: calculatedDomain
|
||||||
|
|
||||||
|
let color: string =
|
||||||
|
props.theme.palette.type === 'light' ? props.theme.palette.secondary.dark : props.theme.palette.primary.light
|
||||||
|
if (props.color) {
|
||||||
|
color = props.color
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ height: '150px', overflow: 'hidden' }}>
|
<div style={{ height: '150px', overflow: 'hidden' }}>
|
||||||
<XYPlot width={width} height={180} yDomain={yDomain}>
|
<XYPlot width={width} height={180} yDomain={yDomain}>
|
||||||
@@ -65,11 +72,7 @@ export default withTheme((props: Props) => {
|
|||||||
<XAxis />
|
<XAxis />
|
||||||
<YAxis width={45} tickFormat={(num: number) => abbreviate(num)} />
|
<YAxis width={45} tickFormat={(num: number) => abbreviate(num)} />
|
||||||
<LineMarkSeries
|
<LineMarkSeries
|
||||||
color={
|
color={color}
|
||||||
props.theme.palette.type === 'light'
|
|
||||||
? props.theme.palette.secondary.dark
|
|
||||||
: props.theme.palette.primary.light
|
|
||||||
}
|
|
||||||
onValueMouseOver={showTooltip}
|
onValueMouseOver={showTooltip}
|
||||||
onValueMouseOut={hideTooltip}
|
onValueMouseOut={hideTooltip}
|
||||||
size={3}
|
size={3}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ interface Props {
|
|||||||
dotPath?: string
|
dotPath?: string
|
||||||
interpolation?: PlotCurveTypes
|
interpolation?: PlotCurveTypes
|
||||||
range?: [number?, number?]
|
range?: [number?, number?]
|
||||||
|
color?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeToHistory(history: q.MessageHistory) {
|
function nodeToHistory(history: q.MessageHistory) {
|
||||||
@@ -41,7 +42,7 @@ function nodeDotPathToHistory(history: q.MessageHistory, dotPath: string) {
|
|||||||
|
|
||||||
function render(props: Props) {
|
function render(props: Props) {
|
||||||
const data = props.dotPath ? nodeDotPathToHistory(props.history, props.dotPath) : nodeToHistory(props.history)
|
const data = props.dotPath ? nodeDotPathToHistory(props.history, props.dotPath) : nodeToHistory(props.history)
|
||||||
return <PlotHistory range={props.range} interpolation={props.interpolation} data={data} />
|
return <PlotHistory color={props.color} range={props.range} interpolation={props.interpolation} data={data} />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default render
|
export default render
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Action } from 'redux'
|
import { Action } from 'redux'
|
||||||
import { createReducer } from './lib'
|
import { createReducer } from './lib'
|
||||||
import { Record, List } from 'immutable'
|
import { Record, List } from 'immutable'
|
||||||
|
import MoveUp from '../components/ChartPanel/ChartSettings/MoveUp'
|
||||||
|
|
||||||
export type PlotCurveTypes = 'curve' | 'linear' | 'cubic_basis_spline' | 'step_after' | 'step_before'
|
export type PlotCurveTypes = 'curve' | 'linear' | 'cubic_basis_spline' | 'step_after' | 'step_before'
|
||||||
|
|
||||||
@@ -12,6 +13,8 @@ export interface ChartParameters {
|
|||||||
from?: number
|
from?: number
|
||||||
to?: number
|
to?: number
|
||||||
}
|
}
|
||||||
|
width?: 'big' | 'medium' | 'small'
|
||||||
|
color?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChartsStateModel {
|
export interface ChartsStateModel {
|
||||||
@@ -20,13 +23,14 @@ export interface ChartsStateModel {
|
|||||||
|
|
||||||
export type ChartsState = Record<ChartsStateModel>
|
export type ChartsState = Record<ChartsStateModel>
|
||||||
|
|
||||||
export type Action = AddChart | RemoveChart | SetCharts | UpdateChart
|
export type Action = AddChart | RemoveChart | SetCharts | UpdateChart | MoveUp
|
||||||
|
|
||||||
export enum ActionTypes {
|
export enum ActionTypes {
|
||||||
CHARTS_ADD = 'CHARTS_ADD',
|
CHARTS_ADD = 'CHARTS_ADD',
|
||||||
CHARTS_REMOVE = 'CHARTS_REMOVE',
|
CHARTS_REMOVE = 'CHARTS_REMOVE',
|
||||||
CHARTS_SET = 'CHARTS_SET',
|
CHARTS_SET = 'CHARTS_SET',
|
||||||
CHARTS_UPDATE = 'CHARTS_UPDATE',
|
CHARTS_UPDATE = 'CHARTS_UPDATE',
|
||||||
|
CHARTS_MOVE_UP = 'CHARTS_MOVE_UP',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddChart {
|
export interface AddChart {
|
||||||
@@ -34,6 +38,12 @@ export interface AddChart {
|
|||||||
chart: ChartParameters
|
chart: ChartParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MoveUp {
|
||||||
|
type: ActionTypes.CHARTS_ADD
|
||||||
|
topic: string
|
||||||
|
dotPath?: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface UpdateChart {
|
export interface UpdateChart {
|
||||||
type: ActionTypes.CHARTS_ADD
|
type: ActionTypes.CHARTS_ADD
|
||||||
topic: string
|
topic: string
|
||||||
@@ -60,12 +70,26 @@ export const chartsReducer = createReducer(initialState(), {
|
|||||||
CHARTS_REMOVE: removeChart,
|
CHARTS_REMOVE: removeChart,
|
||||||
CHARTS_SET: setCharts,
|
CHARTS_SET: setCharts,
|
||||||
CHARTS_UPDATE: updateChart,
|
CHARTS_UPDATE: updateChart,
|
||||||
|
CHARTS_MOVE_UP: moveUp,
|
||||||
})
|
})
|
||||||
|
|
||||||
function addChart(state: ChartsState, action: AddChart) {
|
function addChart(state: ChartsState, action: AddChart) {
|
||||||
return state.set('charts', state.get('charts').push(action.chart))
|
return state.set('charts', state.get('charts').push(action.chart))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function moveUp(state: ChartsState, action: MoveUp) {
|
||||||
|
const charts = state.get('charts')
|
||||||
|
const idx = charts.findIndex(chart => chart.topic === action.topic && chart.dotPath === action.dotPath)
|
||||||
|
const item = charts.get(idx)
|
||||||
|
const previousItem = charts.get(idx - 1)
|
||||||
|
|
||||||
|
if (idx === 0 || !item || !previousItem) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newlyOrderedCharts = charts.set(idx - 1, item).set(idx, previousItem)
|
||||||
|
return state.set('charts', newlyOrderedCharts)
|
||||||
|
}
|
||||||
|
|
||||||
function updateChart(state: ChartsState, action: UpdateChart) {
|
function updateChart(state: ChartsState, action: UpdateChart) {
|
||||||
const charts = state.get('charts')
|
const charts = state.get('charts')
|
||||||
const chartIdx = charts.findIndex(chart => chart.topic === action.topic && chart.dotPath === action.dotPath)
|
const chartIdx = charts.findIndex(chart => chart.topic === action.topic && chart.dotPath === action.dotPath)
|
||||||
|
|||||||
Reference in New Issue
Block a user