Duration.tsx 6.13 KB
Newer Older
Lijiao's avatar
Lijiao committed
1
2
import * as React from 'react';
import ReactEcharts from 'echarts-for-react';
3
import { TableObj, EventMap } from '../../static/interface';
4
import { filterDuration, convertDuration } from '../../static/function';
5
6
7
import 'echarts/lib/chart/bar';
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
Lijiao's avatar
Lijiao committed
8
9

interface Runtrial {
10
    trialId: string[];
Lijiao's avatar
Lijiao committed
11
    trialTime: number[];
Lijiao's avatar
Lijiao committed
12
13
}

14
15
interface DurationProps {
    source: Array<TableObj>;
16
    whichChart: string;
17
18
}

Lijiao's avatar
Lijiao committed
19
interface DurationState {
Lijiao's avatar
Lijiao committed
20
21
    startDuration: number; // for record data zoom
    endDuration: number;
22
    durationSource: {};
Lijiao's avatar
Lijiao committed
23
24
}

25
26
27
class Duration extends React.Component<DurationProps, DurationState> {
    constructor(props: DurationProps) {
        super(props);
Lijiao's avatar
Lijiao committed
28
        this.state = {
Lijiao's avatar
Lijiao committed
29
30
            startDuration: 0, // for record data zoom
            endDuration: 100,
31
            durationSource: this.initDuration(this.props.source)
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
        };
    }

    initDuration = (source: Array<TableObj>): any => {
        const trialId: number[] = [];
        const trialTime: number[] = [];
        const trialJobs = source.filter(filterDuration);

        trialJobs.forEach(item => {
            trialId.push(item.sequenceId);
            trialTime.push(item.duration);
        });
        return {
            tooltip: {
                trigger: 'axis',
                axisPointer: {
                    type: 'shadow'
49
                },
50
                formatter: (data: any): React.ReactNode =>
51
                    '<div>' +
52
53
54
55
56
57
                    '<div>Trial No.: ' +
                    data[0].dataIndex +
                    '</div>' +
                    '<div>Duration: ' +
                    convertDuration(data[0].data) +
                    '</div>' +
58
                    '</div>'
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
            },
            grid: {
                bottom: '3%',
                containLabel: true,
                left: '1%',
                right: '5%'
            },
            dataZoom: [
                {
                    id: 'dataZoomY',
                    type: 'inside',
                    yAxisIndex: [0],
                    filterMode: 'empty',
                    start: 0,
                    end: 100
74
                }
75
76
77
            ],
            xAxis: {
                name: 'Time/s',
78
                type: 'value'
79
80
81
82
83
84
85
86
87
            },
            yAxis: {
                name: 'Trial No.',
                type: 'category',
                data: trialId,
                nameTextStyle: {
                    padding: [0, 0, 0, 30]
                }
            },
88
89
90
91
92
93
            series: [
                {
                    type: 'bar',
                    data: trialTime
                }
            ]
94
        };
95
    };
96

Lijiao's avatar
Lijiao committed
97
    getOption = (dataObj: Runtrial): any => {
Lijiao's avatar
Lijiao committed
98
        const { startDuration, endDuration } = this.state;
99
        return {
Lijiao's avatar
Lijiao committed
100
101
102
103
            tooltip: {
                trigger: 'axis',
                axisPointer: {
                    type: 'shadow'
104
                },
105
                formatter: (data: any): React.ReactNode =>
106
                    '<div>' +
107
108
109
110
111
112
                    '<div>Trial No.: ' +
                    data[0].dataIndex +
                    '</div>' +
                    '<div>Duration: ' +
                    convertDuration(data[0].data) +
                    '</div>' +
113
                    '</div>'
Lijiao's avatar
Lijiao committed
114
115
116
117
118
            },
            grid: {
                bottom: '3%',
                containLabel: true,
                left: '1%',
119
                right: '5%'
Lijiao's avatar
Lijiao committed
120
            },
Lijiao's avatar
Lijiao committed
121
122
123
124
125
126
127
128
            dataZoom: [
                {
                    id: 'dataZoomY',
                    type: 'inside',
                    yAxisIndex: [0],
                    filterMode: 'empty',
                    start: startDuration,
                    end: endDuration
129
                }
Lijiao's avatar
Lijiao committed
130
            ],
Lijiao's avatar
Lijiao committed
131
132
            xAxis: {
                name: 'Time',
133
                type: 'value'
Lijiao's avatar
Lijiao committed
134
135
136
137
            },
            yAxis: {
                name: 'Trial',
                type: 'category',
138
139
140
141
                data: dataObj.trialId,
                nameTextStyle: {
                    padding: [0, 0, 0, 30]
                }
Lijiao's avatar
Lijiao committed
142
            },
143
144
145
146
147
148
            series: [
                {
                    type: 'bar',
                    data: dataObj.trialTime
                }
            ]
Lijiao's avatar
Lijiao committed
149
        };
150
    };
Lijiao's avatar
Lijiao committed
151

152
    drawDurationGraph = (source: Array<TableObj>): void => {
153
        // why this function run two times when props changed?
154
        const trialId: string[] = [];
Lijiao's avatar
Lijiao committed
155
        const trialTime: number[] = [];
156
        const trialRun: Runtrial[] = [];
157
        const trialJobs = source.filter(filterDuration);
158
159
        Object.keys(trialJobs).map(item => {
            const temp = trialJobs[item];
160
161
            trialId.push(temp.sequenceId);
            trialTime.push(temp.duration);
162
163
164
165
166
        });
        trialRun.push({
            trialId: trialId,
            trialTime: trialTime
        });
167
168
169
        this.setState({
            durationSource: this.getOption(trialRun[0])
        });
170
    };
171
172
173
174
175
176

    componentDidMount(): void {
        const { source } = this.props;
        this.drawDurationGraph(source);
    }

177
178
179
    componentDidUpdate(prevProps: DurationProps): void {
        // add this if to prevent endless loop
        if (this.props.source !== prevProps.source) {
180
            if (this.props.whichChart === 'Duration') {
181
                this.drawDurationGraph(this.props.source);
182
183
184
185
            }
        }
    }

Lijiao's avatar
Lijiao committed
186
    render(): React.ReactNode {
187
        const { durationSource } = this.state;
188
        const onEvents = { dataZoom: this.durationDataZoom };
Lijiao's avatar
Lijiao committed
189
190
191
        return (
            <div>
                <ReactEcharts
192
193
                    option={durationSource}
                    style={{ width: '94%', height: 412, margin: '0 auto', marginTop: 15 }}
194
                    theme='my_theme'
195
                    notMerge={true} // update now
Lijiao's avatar
Lijiao committed
196
                    onEvents={onEvents}
Lijiao's avatar
Lijiao committed
197
198
199
200
                />
            </div>
        );
    }
Lijiao's avatar
Lijiao committed
201

Lijiao's avatar
Lijiao committed
202
    private durationDataZoom = (e: EventMap): void => {
Lijiao's avatar
Lijiao committed
203
204
        if (e.batch !== undefined) {
            this.setState(() => ({
205
206
                startDuration: e.batch[0].start !== null ? e.batch[0].start : 0,
                endDuration: e.batch[0].end !== null ? e.batch[0].end : 100
Lijiao's avatar
Lijiao committed
207
208
            }));
        }
209
    };
Lijiao's avatar
Lijiao committed
210
211
}

212
export default Duration;