Progress.tsx 7.78 KB
Newer Older
Lijiao's avatar
Lijiao committed
1
import * as React from 'react';
2
import { Row, Col, Popover, message } from 'antd';
3
import axios from 'axios';
4
5
import { MANAGER_IP } from '../../static/const';
import { EXPERIMENT, TRIALS } from '../../static/datamodel';
Lijiao's avatar
Lijiao committed
6
import { convertTime } from '../../static/function';
7
import ConcurrencyInput from './NumInput';
Lijiao's avatar
Lijiao committed
8
import ProgressBar from './ProgressItem';
v-liguo's avatar
v-liguo committed
9
import LogDrawer from '../Modal/LogDrawer';
Lijiao's avatar
Lijiao committed
10
import '../../static/style/progress.scss';
11
import '../../static/style/probar.scss';
Lijiao's avatar
Lijiao committed
12
13

interface ProgressProps {
14
    concurrency: number;
15
    bestAccuracy: number;
16
    changeConcurrency: (val: number) => void;
17
    experimentUpdateBroadcast: number;
Lijiao's avatar
Lijiao committed
18
19
}

20
interface ProgressState {
v-liguo's avatar
v-liguo committed
21
    isShowLogDrawer: boolean;
22
23
24
}

class Progressed extends React.Component<ProgressProps, ProgressState> {
Lijiao's avatar
Lijiao committed
25
26
    constructor(props: ProgressProps) {
        super(props);
27
        this.state = {
v-liguo's avatar
v-liguo committed
28
            isShowLogDrawer: false
29
30
31
        };
    }

32
33
34
35
    editTrialConcurrency = async (userInput: string) => {
        if (!userInput.match(/^[1-9]\d*$/)) {
            message.error('Please enter a positive integer!', 2);
            return;
36
        }
37
38
39
40
        const newConcurrency = parseInt(userInput, 10);
        if (newConcurrency === this.props.concurrency) {
            message.info(`Trial concurrency has not changed`, 2);
            return;
41
42
        }

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
        const newProfile = Object.assign({}, EXPERIMENT.profile);
        newProfile.params.trialConcurrency = newConcurrency;

        // rest api, modify trial concurrency value
        try {
            const res = await axios.put(`${MANAGER_IP}/experiment`, newProfile, {
                params: { update_type: 'TRIAL_CONCURRENCY' }
            });
            if (res.status === 200) {
                message.success(`Successfully updated trial concurrency`);
                // NOTE: should we do this earlier in favor of poor networks?
                this.props.changeConcurrency(newConcurrency);
            }
        } catch (error) {
            if (error.response && error.response.data.error) {
                message.error(`Failed to update trial concurrency\n${error.response.data.error}`);
            } else if (error.response) {
                message.error(`Failed to update trial concurrency\nServer responsed ${error.response.status}`);
            } else if (error.message) {
                message.error(`Failed to update trial concurrency\n${error.message}`);
            } else {
                message.error(`Failed to update trial concurrency\nUnknown error`);
65
66
67
68
            }
        }
    }

v-liguo's avatar
v-liguo committed
69
    isShowDrawer = () => {
70
        this.setState({ isShowLogDrawer: true });
v-liguo's avatar
v-liguo committed
71
72
73
    }

    closeDrawer = () => {
74
        this.setState({ isShowLogDrawer: false });
v-liguo's avatar
v-liguo committed
75
76
    }

77
78
79
    render() {
        const { bestAccuracy } = this.props;
        const { isShowLogDrawer } = this.state;
Lijiao's avatar
Lijiao committed
80

81
82
83
        const count = TRIALS.countStatus();
        const stoppedCount = count.get('USER_CANCELED')! + count.get('SYS_CANCELED')! + count.get('EARLY_STOPPED')!;
        const bar2 = count.get('RUNNING')! + count.get('SUCCEEDED')! + count.get('FAILED')! + stoppedCount;
84

85
86
87
88
        const bar2Percent = (bar2 / EXPERIMENT.profile.params.maxTrialNum) * 100;
        const percent = (EXPERIMENT.profile.execDuration / EXPERIMENT.profile.params.maxExecDuration) * 100;
        const remaining = convertTime(EXPERIMENT.profile.params.maxExecDuration - EXPERIMENT.profile.execDuration);
        const maxDuration = convertTime(EXPERIMENT.profile.params.maxExecDuration);
89
        const maxTrialNum = EXPERIMENT.profile.params.maxTrialNum;
90
        const execDuration = convertTime(EXPERIMENT.profile.execDuration);
91

92
        let errorContent;
93
        if (EXPERIMENT.error) {
94
95
            errorContent = (
                <div className="errors">
96
                    {EXPERIMENT.error}
v-liguo's avatar
v-liguo committed
97
                    <div><a href="#" onClick={this.isShowDrawer}>Learn about</a></div>
98
99
100
                </div>
            );
        }
Lijiao's avatar
Lijiao committed
101
        return (
102
            <Row className="progress" id="barBack">
103
                <Row className="basic lineBasic">
104
105
                    <p>Status</p>
                    <div className="status">
106
                        <span className={EXPERIMENT.status}>{EXPERIMENT.status}</span>
107
                        {
108
                            EXPERIMENT.status === 'ERROR'
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
                                ?
                                <Popover
                                    placement="rightTop"
                                    content={errorContent}
                                    title="Error"
                                    trigger="hover"
                                >
                                    <span className="errorBtn">i</span>
                                </Popover>
                                :
                                <span />
                        }
                    </div>
                </Row>
                <ProgressBar
                    who="Duration"
                    percent={percent}
126
127
128
                    description={execDuration}
                    bgclass={EXPERIMENT.status}
                    maxString={`Max duration: ${maxDuration}`}
129
130
                />
                <ProgressBar
Lijiao's avatar
Lijiao committed
131
                    who="Trial numbers"
132
133
                    percent={bar2Percent}
                    description={bar2.toString()}
134
135
                    bgclass={EXPERIMENT.status}
                    maxString={`Max trial number: ${maxTrialNum}`}
136
137
                />
                <Row className="basic colorOfbasic mess">
Lijiao's avatar
Lijiao committed
138
                    <p>Best metric</p>
139
                    <div>{isNaN(bestAccuracy) ? 'N/A' : bestAccuracy.toFixed(6)}</div>
140
                </Row>
Lijiao's avatar
Lijiao committed
141
                <Row className="mess">
Lijiao's avatar
Lijiao committed
142
                    <Col span={6}>
Lijiao's avatar
Lijiao committed
143
                        <Row className="basic colorOfbasic">
Lijiao's avatar
Lijiao committed
144
                            <p>Spent</p>
145
                            <div>{execDuration}</div>
Lijiao's avatar
Lijiao committed
146
147
                        </Row>
                    </Col>
Lijiao's avatar
Lijiao committed
148
                    <Col span={6}>
Lijiao's avatar
Lijiao committed
149
                        <Row className="basic colorOfbasic">
Lijiao's avatar
Lijiao committed
150
                            <p>Remaining</p>
151
                            <div className="time">{remaining}</div>
Lijiao's avatar
Lijiao committed
152
153
                        </Row>
                    </Col>
Lijiao's avatar
Lijiao committed
154
155
156
                    <Col span={12}>
                        {/* modify concurrency */}
                        <p>Concurrency</p>
157
                        <ConcurrencyInput value={this.props.concurrency} updateValue={this.editTrialConcurrency} />
Lijiao's avatar
Lijiao committed
158
                    </Col>
Lijiao's avatar
Lijiao committed
159
                </Row>
160
161
162
163
                <Row className="mess">
                    <Col span={6}>
                        <Row className="basic colorOfbasic">
                            <p>Running</p>
164
                            <div>{count.get('RUNNING')}</div>
165
166
167
168
169
                        </Row>
                    </Col>
                    <Col span={6}>
                        <Row className="basic colorOfbasic">
                            <p>Succeeded</p>
170
                            <div>{count.get('SUCCEEDED')}</div>
171
172
173
174
175
                        </Row>
                    </Col>
                    <Col span={6}>
                        <Row className="basic">
                            <p>Stopped</p>
176
                            <div>{stoppedCount}</div>
177
178
179
180
181
                        </Row>
                    </Col>
                    <Col span={6}>
                        <Row className="basic">
                            <p>Failed</p>
182
                            <div>{count.get('FAILED')}</div>
183
184
185
                        </Row>
                    </Col>
                </Row>
v-liguo's avatar
v-liguo committed
186
                {/* learn about click -> default active key is dispatcher. */}
187
188
189
190
191
192
                {isShowLogDrawer ? (
                    <LogDrawer
                        closeDrawer={this.closeDrawer}
                        activeTab="dispatcher"
                    />
                ) : null}
Lijiao's avatar
Lijiao committed
193
194
195
196
197
            </Row>
        );
    }
}

198
export default Progressed;