Intermediate.tsx 11.6 KB
Newer Older
1
import * as React from 'react';
2
import { Stack, PrimaryButton, Toggle, IStackTokens } from '@fluentui/react';
Lijiao's avatar
Lijiao committed
3
import { TooltipForIntermediate, TableObj, Intermedia, EventMap } from '../../static/interface';
4
import ReactEcharts from 'echarts-for-react';
5
6
7
8
9
10
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';

const stackTokens: IStackTokens = {
    childrenGap: 20
};
11
12

interface IntermediateState {
13
    detailSource: Array<TableObj>;
14
15
16
17
    interSource: object;
    filterSource: Array<TableObj>;
    eachIntermediateNum: number; // trial's intermediate number count
    isLoadconfirmBtn: boolean;
18
    isFilter?: boolean | undefined;
19
    length: number;
20
    clickCounts: number; // user filter intermediate click confirm btn's counts
Lijiao's avatar
Lijiao committed
21
22
    startMediaY: number;
    endMediaY: number;
23
24
25
26
}

interface IntermediateProps {
    source: Array<TableObj>;
27
    whichChart: string;
28
29
30
31
}

class Intermediate extends React.Component<IntermediateProps, IntermediateState> {
    static intervalMediate = 1;
32
33
34
    public pointInput!: HTMLInputElement | null;
    public minValInput!: HTMLInputElement | null;
    public maxValInput!: HTMLInputElement | null;
35
36
37
38

    constructor(props: IntermediateProps) {
        super(props);
        this.state = {
39
            detailSource: [],
40
41
42
43
            interSource: {},
            filterSource: [],
            eachIntermediateNum: 1,
            isLoadconfirmBtn: false,
44
45
            isFilter: false,
            length: 100000,
Lijiao's avatar
Lijiao committed
46
47
48
            clickCounts: 0,
            startMediaY: 0,
            endMediaY: 100
49
50
51
        };
    }

Lijiao's avatar
Lijiao committed
52
    drawIntermediate = (source: Array<TableObj>): void => {
53
        if (source.length > 0) {
54
55
56
57
            this.setState({
                length: source.length,
                detailSource: source
            });
Lijiao's avatar
Lijiao committed
58
            const { startMediaY, endMediaY } = this.state;
59
60
61
62
63
            const trialIntermediate: Array<Intermedia> = [];
            Object.keys(source).map(item => {
                const temp = source[item];
                trialIntermediate.push({
                    name: temp.id,
64
                    trialNum: temp.sequenceId,
65
66
67
68
69
70
                    data: temp.description.intermediate,
                    type: 'line',
                    hyperPara: temp.description.parameters
                });
            });
            // find max intermediate number
71
72
73
            trialIntermediate.sort((a, b) => {
                return b.data.length - a.data.length;
            });
74
            const legend: string[] = [];
75
76
            // max length
            const length = trialIntermediate[0].data.length;
Lijiao's avatar
Lijiao committed
77
            const xAxis: number[] = [];
78
79
80
81
82
83
84
85
86
87
88
            Object.keys(trialIntermediate).map(item => {
                const temp = trialIntermediate[item];
                legend.push(temp.name);
            });
            for (let i = 1; i <= length; i++) {
                xAxis.push(i);
            }
            const option = {
                tooltip: {
                    trigger: 'item',
                    enterable: true,
89
                    position: function(point: number[], data: TooltipForIntermediate): number[] {
90
91
92
93
94
95
                        if (data.dataIndex < length / 2) {
                            return [point[0], 80];
                        } else {
                            return [point[0] - 300, 80];
                        }
                    },
96
                    formatter: function(data: TooltipForIntermediate): React.ReactNode {
97
                        const trialId = data.seriesName;
98
99
                        let parameters = {};
                        let trialNum = 0;
100
101
                        const temp = trialIntermediate.find(key => key.name === trialId);
                        if (temp !== undefined) {
102
103
                            parameters = temp.hyperPara;
                            trialNum = temp.trialNum;
104
                        }
105
106
                        return (
                            '<div class="tooldetailAccuracy">' +
107
108
109
                            '<div>Trial No.: ' +
                            trialNum +
                            '</div>' +
110
111
112
113
114
115
                            '<div>Trial ID: ' +
                            trialId +
                            '</div>' +
                            '<div>Intermediate: ' +
                            data.data +
                            '</div>' +
116
                            '<div>Parameters: ' +
117
                            '<pre>' +
118
                            JSON.stringify(parameters, null, 4) +
119
                            '</pre>' +
120
                            '</div>' +
121
122
                            '</div>'
                        );
123
124
125
126
127
128
129
130
131
                    }
                },
                grid: {
                    left: '5%',
                    top: 40,
                    containLabel: true
                },
                xAxis: {
                    type: 'category',
132
                    // name: '# Intermediate',
133
134
135
136
137
                    boundaryGap: false,
                    data: xAxis
                },
                yAxis: {
                    type: 'value',
138
                    name: 'Metric',
139
                    scale: true
140
                },
Lijiao's avatar
Lijiao committed
141
142
143
144
145
                dataZoom: [
                    {
                        id: 'dataZoomY',
                        type: 'inside',
                        yAxisIndex: [0],
146
                        filterMode: 'none',
Lijiao's avatar
Lijiao committed
147
148
149
150
                        start: startMediaY,
                        end: endMediaY
                    }
                ],
151
152
                series: trialIntermediate
            };
153
154
155
            this.setState({
                interSource: option
            });
156
        } else {
157
158
159
160
161
162
163
164
            const nullData = {
                grid: {
                    left: '5%',
                    top: 40,
                    containLabel: true
                },
                xAxis: {
                    type: 'category',
165
                    boundaryGap: false
166
167
168
                },
                yAxis: {
                    type: 'value',
169
                    name: 'Metric'
170
171
                }
            };
172
            this.setState({ interSource: nullData });
173
        }
174
    };
175
176

    // confirm btn function [filter data]
Lijiao's avatar
Lijiao committed
177
    filterLines = (): void => {
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
        const filterSource: Array<TableObj> = [];
        this.setState({ isLoadconfirmBtn: true }, () => {
            const { source } = this.props;
            // get input value
            const pointVal = this.pointInput !== null ? this.pointInput.value : '';
            const minVal = this.minValInput !== null ? this.minValInput.value : '';
            const maxVal = this.maxValInput !== null ? this.maxValInput.value : '';
            // user not input message
            if (pointVal === '' || minVal === '') {
                alert('Please input filter message');
            } else {
                // user not input max value
                const position = JSON.parse(pointVal);
                const min = JSON.parse(minVal);
                if (maxVal === '') {
                    Object.keys(source).map(item => {
                        const temp = source[item];
                        const val = temp.description.intermediate[position - 1];
                        if (val >= min) {
                            filterSource.push(temp);
                        }
                    });
200
                } else {
201
202
203
204
205
206
207
208
                    const max = JSON.parse(maxVal);
                    Object.keys(source).map(item => {
                        const temp = source[item];
                        const val = temp.description.intermediate[position - 1];
                        if (val >= min && val <= max) {
                            filterSource.push(temp);
                        }
                    });
209
                }
210
211
212
213
214
215
                this.setState({ filterSource: filterSource });
                this.drawIntermediate(filterSource);
            }
            const counts = this.state.clickCounts + 1;
            this.setState({ isLoadconfirmBtn: false, clickCounts: counts });
        });
216
    };
217

218
    switchTurn = (ev: React.MouseEvent<HTMLElement>, checked?: boolean): void => {
219
        this.setState({ isFilter: checked });
220
221
222
        if (checked === false) {
            this.drawIntermediate(this.props.source);
        }
223
    };
224

Lijiao's avatar
Lijiao committed
225
    componentDidMount(): void {
226
227
228
229
        const { source } = this.props;
        this.drawIntermediate(source);
    }

230
231
232
    componentDidUpdate(prevProps: IntermediateProps, prevState: any): void {
        if (this.props.source !== prevProps.source || this.state.isFilter !== prevState.isFilter) {
            const { isFilter, filterSource } = this.state;
233
            const { whichChart, source } = this.props;
234

235
            if (whichChart === 'Intermediate result') {
236
237
238
239
240
241
242
243
                if (isFilter === true) {
                    const pointVal = this.pointInput !== null ? this.pointInput.value : '';
                    const minVal = this.minValInput !== null ? this.minValInput.value : '';
                    if (pointVal === '' && minVal === '') {
                        this.drawIntermediate(source);
                    } else {
                        this.drawIntermediate(filterSource);
                    }
244
                } else {
245
                    this.drawIntermediate(source);
246
                }
247
248
249
250
            }
        }
    }

Lijiao's avatar
Lijiao committed
251
    render(): React.ReactNode {
252
        const { interSource, isLoadconfirmBtn, isFilter } = this.state;
253
        const IntermediateEvents = { dataZoom: this.intermediateDataZoom };
254

255
256
257
        return (
            <div>
                {/* style in para.scss */}
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
                <Stack horizontal horizontalAlign='end' tokens={stackTokens} className='meline intermediate'>
                    {isFilter ? (
                        <div>
                            <span className='filter-x'># Intermediate result</span>
                            <input
                                // placeholder="point"
                                ref={(input): any => (this.pointInput = input)}
                                className='strange'
                            />
                            <span>Metric range</span>
                            <input
                                // placeholder="range"
                                ref={(input): any => (this.minValInput = input)}
                            />
                            <span className='hyphen'>-</span>
                            <input
                                // placeholder="range"
                                ref={(input): any => (this.maxValInput = input)}
                            />
                            <PrimaryButton text='Confirm' onClick={this.filterLines} disabled={isLoadconfirmBtn} />
                        </div>
                    ) : null}
Lijiao's avatar
Lijiao committed
280
                    {/* filter message */}
281
                    <Stack horizontal className='filter-toggle'>
282
283
284
285
                        <span>Filter</span>
                        <Toggle onChange={this.switchTurn} />
                    </Stack>
                </Stack>
286
                <div className='intermediate-graph'>
287
288
                    <ReactEcharts
                        option={interSource}
289
                        style={{ width: '100%', height: 400, margin: '0 auto' }}
290
                        notMerge={true} // update now
Lijiao's avatar
Lijiao committed
291
                        onEvents={IntermediateEvents}
292
                    />
293
                    <div className='xAxis'># Intermediate result</div>
294
                </div>
295
296
297
            </div>
        );
    }
Lijiao's avatar
Lijiao committed
298

Lijiao's avatar
Lijiao committed
299
    private intermediateDataZoom = (e: EventMap): void => {
Lijiao's avatar
Lijiao committed
300
301
        if (e.batch !== undefined) {
            this.setState(() => ({
302
303
                startMediaY: e.batch[0].start !== null ? e.batch[0].start : 0,
                endMediaY: e.batch[0].end !== null ? e.batch[0].end : 100
Lijiao's avatar
Lijiao committed
304
305
            }));
        }
306
    };
307
308
}

v-liguo's avatar
v-liguo committed
309
export default Intermediate;