Duration.tsx 6.04 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
16
17
interface DurationProps {
    source: Array<TableObj>;
}

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

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

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

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

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

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

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

Lijiao's avatar
Lijiao committed
183
    render(): React.ReactNode {
184
        const { durationSource } = this.state;
185
        const onEvents = { dataZoom: this.durationDataZoom };
186

Lijiao's avatar
Lijiao committed
187
188
189
        return (
            <div>
                <ReactEcharts
190
191
                    option={durationSource}
                    style={{ width: '94%', height: 412, margin: '0 auto', marginTop: 15 }}
192
                    theme='nni_theme'
193
                    notMerge={true} // update now
Lijiao's avatar
Lijiao committed
194
                    onEvents={onEvents}
Lijiao's avatar
Lijiao committed
195
196
197
198
                />
            </div>
        );
    }
Lijiao's avatar
Lijiao committed
199

Lijiao's avatar
Lijiao committed
200
    private durationDataZoom = (e: EventMap): void => {
Lijiao's avatar
Lijiao committed
201
202
        if (e.batch !== undefined) {
            this.setState(() => ({
203
204
                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
205
206
            }));
        }
207
    };
Lijiao's avatar
Lijiao committed
208
209
}

210
export default Duration;