import React from 'react'; import { withContentRect } from 'react-measure' import { filter, range, map, pipe } from 'rambda'; import { ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Brush, Label } from 'recharts'; import Job from './Job'; import { maxTime, minTime } from '../ganttUtils'; import theme from '../theme'; class Gannt extends React.PureComponent { constructor(props) { super(props); this.state = { startTime: minTime(props.data), endTime: maxTime(props.data) }; } render() { const { data, measureRef, contentRect: { bounds: dimensions } } = this.props; const { startTime } = this.state; const endTime = this.state.endTime === startTime ? startTime + 1 : this.state.endTime; const scopeData = map(processorData => pipe( filter(datum => (datum.startTime >= startTime || (datum.startTime < startTime && datum.endTime >= startTime) ) && datum.startTime <= endTime ), map(datum => { let newDatum = datum; if (newDatum.startTime < startTime) { newDatum = { ...newDatum, startTime, formerStartTime: newDatum.startTime }; } if (newDatum.endTime > endTime) { newDatum = { ...newDatum, endTime, formerEndTime: newDatum.endTime }; } return newDatum; }) )(processorData), data ); const processors = range(1, data.length + 1); const scopeMinTime = minTime(scopeData); const scopeMaxTime = maxTime(scopeData); const ticksCountX = scopeMinTime + scopeMaxTime; const width = Math.max(theme.gantt.maxWidth, dimensions.width); const height = 100 + 1.75 * theme.gantt.job.height * processors.length; const horizontalGuideLines = map( i => theme.gantt.margin.top + i * 1.75 * theme.gantt.job.height - i * 10, range(0, processors.length) ); return ( <div ref={measureRef}> <ScatterChart width={width} height={height} data={data[0]} margin={theme.gantt.margin}> <CartesianGrid stroke={theme.gantt.grid.stroke} strokeDasharray="5 5" horizontalPoints={horizontalGuideLines} /> <XAxis type="number" dataKey="startTime" interval={0} domain={[scopeMinTime, scopeMaxTime]} tickCount={ticksCountX} allowDecimals={false} > <Label offset={-30} position="insideBottom">Time</Label> </XAxis> <YAxis type="number" dataKey="processor" interval={0} name="processor" allowDecimals={false} domain={[0.5, processors.length + 0.5]} ticks={processors} > <Label position="insideLeft" angle={-90}>Workers</Label> </YAxis> <Brush dataKey="startTime" y={height - theme.gantt.brush.height - 10} height={theme.gantt.brush.height} stroke={theme.gantt.brush.stroke} onChange={({ startIndex, endIndex }) => this.setState({ startTime: startIndex + 1, endTime: endIndex + 1 }) } /> {scopeData.map((processorData, i) => ( <Scatter key={i} data={processorData} shape={<Job />} /> ))} </ScatterChart> </div> ); } } export default withContentRect('bounds')(Gannt);