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
                enterable: true,
105
                formatter: (data: any): React.ReactNode =>
106
107
108
109
110
                    `<div class="tooldetailAccuracy">
                        <div>Trial No.: ${data[0].dataIndex}</div>
                        <div>Duration: ${convertDuration(data[0].data)}</div>
                    </div>
                    `
Lijiao's avatar
Lijiao committed
111
112
113
114
115
            },
            grid: {
                bottom: '3%',
                containLabel: true,
                left: '1%',
116
                right: '5%'
Lijiao's avatar
Lijiao committed
117
            },
Lijiao's avatar
Lijiao committed
118
119
120
121
122
123
124
125
            dataZoom: [
                {
                    id: 'dataZoomY',
                    type: 'inside',
                    yAxisIndex: [0],
                    filterMode: 'empty',
                    start: startDuration,
                    end: endDuration
126
                }
Lijiao's avatar
Lijiao committed
127
            ],
Lijiao's avatar
Lijiao committed
128
129
            xAxis: {
                name: 'Time',
130
                type: 'value'
Lijiao's avatar
Lijiao committed
131
132
133
134
            },
            yAxis: {
                name: 'Trial',
                type: 'category',
135
136
137
138
                data: dataObj.trialId,
                nameTextStyle: {
                    padding: [0, 0, 0, 30]
                }
Lijiao's avatar
Lijiao committed
139
            },
140
141
142
143
144
145
            series: [
                {
                    type: 'bar',
                    data: dataObj.trialTime
                }
            ]
Lijiao's avatar
Lijiao committed
146
        };
147
    };
Lijiao's avatar
Lijiao committed
148

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

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

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

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

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

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

208
export default Duration;