Commit 8e1e1c03 authored by Lijiao's avatar Lijiao Committed by fishyds
Browse files

[WebUI] Show version and support download logfile (#485)

* [WebUI]Show version and support download logfile

* Update download style
parent 9ff1f9d4
...@@ -9,19 +9,19 @@ ...@@ -9,19 +9,19 @@
left: 0; left: 0;
top: 0; top: 0;
width: 100%; width: 100%;
height: 80px; height: 56px;
background: #0071BC; background: #0071BC;
border-right: 1px solid #ccc; border-right: 1px solid #ccc;
z-index: 1000; z-index: 1000;
} }
.headerCon{ .headerCon{
min-width: 600px min-width: 1024px;
} }
.content{ .content{
width: 86%; width: 86%;
min-width: 1024px; min-width: 1024px;
margin: 0 auto; margin: 0 auto;
margin-top: 90px; margin-top: 74px;
margin-bottom: 30px; margin-bottom: 30px;
} }
......
...@@ -8,10 +8,11 @@ class App extends React.Component<{}, {}> { ...@@ -8,10 +8,11 @@ class App extends React.Component<{}, {}> {
return ( return (
<Row className="nni"> <Row className="nni">
<Row className="header"> <Row className="header">
<Col span={2} /> <Col span={1} />
<Col className="headerCon" span={22}> <Col className="headerCon" span={22}>
<SlideBar /> <SlideBar />
</Col> </Col>
<Col span={1}/>
</Row> </Row>
<Row className="content"> <Row className="content">
{this.props.children} {this.props.children}
......
import * as React from 'react'; import * as React from 'react';
import axios from 'axios'; import axios from 'axios';
import { Row, Col, Button } from 'antd'; import { Row, Col } from 'antd';
import { MANAGER_IP } from '../static/const'; import { MANAGER_IP } from '../static/const';
import { import {
Experiment, TableObj, Experiment, TableObj,
...@@ -30,10 +30,12 @@ interface OverviewState { ...@@ -30,10 +30,12 @@ interface OverviewState {
option: object; option: object;
noData: string; noData: string;
accuracyData: object; accuracyData: object;
bestAccuracy: string; bestAccuracy: number;
accNodata: string; accNodata: string;
trialNumber: TrialNumber; trialNumber: TrialNumber;
downBool: boolean; isTop10: boolean;
titleMaxbgcolor: string;
titleMinbgcolor?: string;
} }
class Overview extends React.Component<{}, OverviewState> { class Overview extends React.Component<{}, OverviewState> {
...@@ -76,7 +78,7 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -76,7 +78,7 @@ class Overview extends React.Component<{}, OverviewState> {
// accuracy // accuracy
accuracyData: {}, accuracyData: {},
accNodata: '', accNodata: '',
bestAccuracy: '', bestAccuracy: 0,
trialNumber: { trialNumber: {
succTrial: 0, succTrial: 0,
failTrial: 0, failTrial: 0,
...@@ -86,7 +88,8 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -86,7 +88,8 @@ class Overview extends React.Component<{}, OverviewState> {
unknowTrial: 0, unknowTrial: 0,
totalCurrentTrial: 0 totalCurrentTrial: 0
}, },
downBool: false isTop10: true,
titleMaxbgcolor: '#999'
}; };
} }
...@@ -244,6 +247,9 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -244,6 +247,9 @@ class Overview extends React.Component<{}, OverviewState> {
default: default:
} }
}); });
// choose top10 or lowest10
const { isTop10 } = this.state;
if (isTop10 === true) {
topTableData.sort((a: TableObj, b: TableObj) => { topTableData.sort((a: TableObj, b: TableObj) => {
if (a.acc && b.acc) { if (a.acc && b.acc) {
return b.acc - a.acc; return b.acc - a.acc;
...@@ -251,11 +257,27 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -251,11 +257,27 @@ class Overview extends React.Component<{}, OverviewState> {
return NaN; return NaN;
} }
}); });
} else {
topTableData.sort((a: TableObj, b: TableObj) => {
if (a.acc && b.acc) {
return a.acc - b.acc;
} else {
return NaN;
}
});
}
topTableData.length = Math.min(10, topTableData.length); topTableData.length = Math.min(10, topTableData.length);
let bestDefaultMetric = 0;
if (topTableData[0] !== undefined) {
if (topTableData[0].acc !== undefined) {
bestDefaultMetric = topTableData[0].acc;
}
}
if (this._isMounted) { if (this._isMounted) {
this.setState({ this.setState({
tableData: topTableData, tableData: topTableData,
trialNumber: profile trialNumber: profile,
bestAccuracy: bestDefaultMetric
}); });
} }
this.checkStatus(); this.checkStatus();
...@@ -265,64 +287,6 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -265,64 +287,6 @@ class Overview extends React.Component<{}, OverviewState> {
}); });
} }
downExperimentContent = () => {
this.setState(() => ({
downBool: true
}));
axios
.all([
axios.get(`${MANAGER_IP}/experiment`),
axios.get(`${MANAGER_IP}/trial-jobs`),
axios.get(`${MANAGER_IP}/metric-data`)
])
.then(axios.spread((res, res1, res2) => {
if (res.status === 200 && res1.status === 200 && res2.status === 200) {
if (res.data.params.searchSpace) {
res.data.params.searchSpace = JSON.parse(res.data.params.searchSpace);
}
const isEdge = navigator.userAgent.indexOf('Edge') !== -1 ? true : false;
const interResultList = res2.data;
const contentOfExperiment = JSON.stringify(res.data, null, 2);
let trialMessagesArr = res1.data;
Object.keys(trialMessagesArr).map(item => {
// transform hyperparameters as object to show elegantly
trialMessagesArr[item].hyperParameters = JSON.parse(trialMessagesArr[item].hyperParameters);
const trialId = trialMessagesArr[item].id;
// add intermediate result message
trialMessagesArr[item].intermediate = [];
Object.keys(interResultList).map(key => {
const interId = interResultList[key].trialJobId;
if (trialId === interId) {
trialMessagesArr[item].intermediate.push(interResultList[key]);
}
});
});
const trialMessages = JSON.stringify(trialMessagesArr, null, 2);
const aTag = document.createElement('a');
const file = new Blob([contentOfExperiment, trialMessages], { type: 'application/json' });
aTag.download = 'experiment.json';
aTag.href = URL.createObjectURL(file);
aTag.click();
if (!isEdge) {
URL.revokeObjectURL(aTag.href);
}
if (navigator.userAgent.indexOf('Firefox') > -1) {
const downTag = document.createElement('a');
downTag.addEventListener('click', function () {
downTag.download = 'experiment.json';
downTag.href = URL.createObjectURL(file);
});
let eventMouse = document.createEvent('MouseEvents');
eventMouse.initEvent('click', false, false);
downTag.dispatchEvent(eventMouse);
}
this.setState(() => ({
downBool: false
}));
}
}));
}
// trial accuracy graph Default Metric // trial accuracy graph Default Metric
drawPointGraph = () => { drawPointGraph = () => {
...@@ -342,7 +306,6 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -342,7 +306,6 @@ class Overview extends React.Component<{}, OverviewState> {
accarr.push(items.acc); accarr.push(items.acc);
indexarr.push(items.sequenceId); indexarr.push(items.sequenceId);
}); });
const bestAccnum = Math.max(...accarr);
const accOption = { const accOption = {
tooltip: { tooltip: {
trigger: 'item' trigger: 'item'
...@@ -355,6 +318,7 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -355,6 +318,7 @@ class Overview extends React.Component<{}, OverviewState> {
yAxis: { yAxis: {
name: 'Default Metric', name: 'Default Metric',
type: 'value', type: 'value',
scale: true,
data: accarr data: accarr
}, },
series: [{ series: [{
...@@ -370,13 +334,25 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -370,13 +334,25 @@ class Overview extends React.Component<{}, OverviewState> {
}); });
} else { } else {
this.setState({ this.setState({
accNodata: '', accNodata: ''
bestAccuracy: bestAccnum.toFixed(6)
}); });
} }
}); });
} }
clickMaxTop = (event: React.SyntheticEvent<EventTarget>) => {
event.stopPropagation();
// #999 panel active bgcolor; #b3b3b3 as usual
this.setState(() => ({ isTop10: true, titleMaxbgcolor: '#999', titleMinbgcolor: '#b3b3b3' }));
this.showTrials();
}
clickMinTop = (event: React.SyntheticEvent<EventTarget>) => {
event.stopPropagation();
this.setState(() => ({ isTop10: false, titleMaxbgcolor: '#b3b3b3', titleMinbgcolor: '#999' }));
this.showTrials();
}
isOffInterval = () => { isOffInterval = () => {
const { status } = this.state; const { status } = this.state;
switch (status) { switch (status) {
...@@ -407,36 +383,16 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -407,36 +383,16 @@ class Overview extends React.Component<{}, OverviewState> {
render() { render() {
const { const {
trialProfile, trialProfile, searchSpace, tableData, accuracyData,
searchSpace, accNodata, status, errorStr, trialNumber, bestAccuracy,
tableData, titleMaxbgcolor, titleMinbgcolor
accuracyData,
accNodata,
status,
errorStr,
trialNumber,
bestAccuracy,
downBool
} = this.state; } = this.state;
return ( return (
<div className="overview"> <div className="overview">
{/* status and experiment block */} {/* status and experiment block */}
<Row> <Row>
<Row className="exbgcolor"> <Title1 text="Experiment" icon="11.png" />
<Col span={4}><Title1 text="Experiment" icon="11.png" /></Col>
<Col span={4}>
<Button
type="primary"
className="changeBtu download"
onClick={this.downExperimentContent}
disabled={downBool}
>
<span>Download</span>
<img src={require('../static/img/icon/download.png')} alt="icon" />
</Button>
</Col>
</Row>
<BasicInfo trialProfile={trialProfile} status={status} /> <BasicInfo trialProfile={trialProfile} status={status} />
</Row> </Row>
<Row className="overMessage"> <Row className="overMessage">
...@@ -472,8 +428,26 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -472,8 +428,26 @@ class Overview extends React.Component<{}, OverviewState> {
</Col> </Col>
</Row> </Row>
<Row className="overGraph"> <Row className="overGraph">
<Row className="top10bg">
<Col span={4} className="top10Title">
<Title1 text="Top10 Trials" icon="7.png" />
</Col>
<Col
span={2}
className="title"
onClick={this.clickMaxTop}
>
<Title1 text="Maximal" icon="max.png" bgcolor={titleMaxbgcolor} />
</Col>
<Col
span={2}
className="title minTitle"
onClick={this.clickMinTop}
>
<Title1 text="Minimal" icon="min.png" bgcolor={titleMinbgcolor} />
</Col>
</Row>
<Col span={8} className="overviewBoder"> <Col span={8} className="overviewBoder">
<Title1 text="Optimization Progress" icon="3.png" />
<Row className="accuracy"> <Row className="accuracy">
<Accuracy <Accuracy
accuracyData={accuracyData} accuracyData={accuracyData}
...@@ -483,7 +457,6 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -483,7 +457,6 @@ class Overview extends React.Component<{}, OverviewState> {
</Row> </Row>
</Col> </Col>
<Col span={16} id="succeTable"> <Col span={16} id="succeTable">
<Title1 text="Top10 Trials" icon="7.png" />
<SuccessTable tableSource={tableData} /> <SuccessTable tableSource={tableData} />
</Col> </Col>
</Row> </Row>
......
import * as React from 'react'; import * as React from 'react';
import { Link } from 'react-router'; import { Link } from 'react-router';
import axios from 'axios';
import { DOWNLOAD_IP } from '../static/const';
import { Row, Col, Menu, Dropdown, Icon } from 'antd';
import { MANAGER_IP } from '../static/const';
import '../static/style/slideBar.scss'; import '../static/style/slideBar.scss';
import '../static/style/button.scss';
class SlideBar extends React.Component<{}, {}> { interface SliderState {
version: string;
menuVisible: boolean;
}
interface EventPer {
key: string;
}
class SlideBar extends React.Component<{}, SliderState> {
public _isMounted = false;
constructor(props: {}) {
super(props);
this.state = {
version: '',
menuVisible: false
};
}
downExperimentContent = () => {
axios
.all([
axios.get(`${MANAGER_IP}/experiment`),
axios.get(`${MANAGER_IP}/trial-jobs`),
axios.get(`${MANAGER_IP}/metric-data`)
])
.then(axios.spread((res, res1, res2) => {
if (res.status === 200 && res1.status === 200 && res2.status === 200) {
if (res.data.params.searchSpace) {
res.data.params.searchSpace = JSON.parse(res.data.params.searchSpace);
}
const isEdge = navigator.userAgent.indexOf('Edge') !== -1 ? true : false;
const interResultList = res2.data;
const contentOfExperiment = JSON.stringify(res.data, null, 2);
let trialMessagesArr = res1.data;
Object.keys(trialMessagesArr).map(item => {
// transform hyperparameters as object to show elegantly
trialMessagesArr[item].hyperParameters = JSON.parse(trialMessagesArr[item].hyperParameters);
const trialId = trialMessagesArr[item].id;
// add intermediate result message
trialMessagesArr[item].intermediate = [];
Object.keys(interResultList).map(key => {
const interId = interResultList[key].trialJobId;
if (trialId === interId) {
trialMessagesArr[item].intermediate.push(interResultList[key]);
}
});
});
const trialMessages = JSON.stringify(trialMessagesArr, null, 2);
const aTag = document.createElement('a');
const file = new Blob([contentOfExperiment, trialMessages], { type: 'application/json' });
aTag.download = 'experiment.json';
aTag.href = URL.createObjectURL(file);
aTag.click();
if (!isEdge) {
URL.revokeObjectURL(aTag.href);
}
if (navigator.userAgent.indexOf('Firefox') > -1) {
const downTag = document.createElement('a');
downTag.addEventListener('click', function () {
downTag.download = 'experiment.json';
downTag.href = URL.createObjectURL(file);
});
let eventMouse = document.createEvent('MouseEvents');
eventMouse.initEvent('click', false, false);
downTag.dispatchEvent(eventMouse);
}
}
}));
}
downnnimanagerLog = () => {
axios(`${DOWNLOAD_IP}/nnimanager.log`, {
method: 'GET'
})
.then(res => {
if (res.status === 200) {
const nniLogfile = res.data;
const aTag = document.createElement('a');
const isEdge = navigator.userAgent.indexOf('Edge') !== -1 ? true : false;
const file = new Blob([nniLogfile], { type: 'application/json' });
aTag.download = 'nnimanagerLog.json';
aTag.href = URL.createObjectURL(file);
aTag.click();
if (!isEdge) {
URL.revokeObjectURL(aTag.href);
}
if (navigator.userAgent.indexOf('Firefox') > -1) {
const downTag = document.createElement('a');
downTag.addEventListener('click', function () {
downTag.download = 'nnimanagerLog.json';
downTag.href = URL.createObjectURL(file);
});
let eventMouse = document.createEvent('MouseEvents');
eventMouse.initEvent('click', false, false);
downTag.dispatchEvent(eventMouse);
}
}
});
}
downDispatcherlog = () => {
axios(`${DOWNLOAD_IP}/dispatcher.log`, {
method: 'GET'
})
.then(res => {
if (res.status === 200) {
const dispatchLogfile = res.data;
const aTag = document.createElement('a');
const isEdge = navigator.userAgent.indexOf('Edge') !== -1 ? true : false;
const file = new Blob([dispatchLogfile], { type: 'application/json' });
aTag.download = 'dispatcherLog.json';
aTag.href = URL.createObjectURL(file);
aTag.click();
if (!isEdge) {
URL.revokeObjectURL(aTag.href);
}
if (navigator.userAgent.indexOf('Firefox') > -1) {
const downTag = document.createElement('a');
downTag.addEventListener('click', function () {
downTag.download = 'dispatcherLog.json';
downTag.href = URL.createObjectURL(file);
});
let eventMouse = document.createEvent('MouseEvents');
eventMouse.initEvent('click', false, false);
downTag.dispatchEvent(eventMouse);
}
}
});
}
getNNIversion = () => {
axios(`${MANAGER_IP}/version`, {
method: 'GET'
})
.then(res => {
if (res.status === 200 && this._isMounted) {
this.setState({ version: res.data });
}
});
}
handleMenuClick = (e: EventPer) => {
if (this._isMounted) { this.setState({ menuVisible: false }); }
// download experiment related content
switch (e.key) {
case '1':
this.downExperimentContent();
break;
case '2':
this.downnnimanagerLog();
break;
case '3':
this.downDispatcherlog();
break;
default:
}
}
handleVisibleChange = (flag: boolean) => {
this.setState({ menuVisible: flag });
}
componentDidMount() {
this._isMounted = true;
this.getNNIversion();
}
componentWillUnmount() {
this._isMounted = false;
}
render() { render() {
const { version, menuVisible } = this.state;
const menu = (
<Menu onClick={this.handleMenuClick}>
<Menu.Item key="1">Experiment Parameters</Menu.Item>
<Menu.Item key="2">NNImanager Logfile</Menu.Item>
<Menu.Item key="3">Dispatcher Logfile</Menu.Item>
</Menu>
);
return ( return (
<ul className="nav"> <Row className="nav">
<Col span={8}>
<ul className="link">
<li className="logo"> <li className="logo">
<Link to={'/oview'}> <Link to={'/oview'}>
<img src={require('../static/img/logo.png')} style={{ width: 156 }} alt="NNI logo" /> <img src={require('../static/img/logo2.png')} style={{ width: 88 }} alt="NNI logo" />
</Link> </Link>
</li> </li>
<li className="tab"> <li className="tab firstTab">
<Link to={'/oview'} activeClassName="high"> <Link to={'/oview'} activeClassName="high">
Overview Overview
</Link> </Link>
...@@ -23,6 +209,29 @@ class SlideBar extends React.Component<{}, {}> { ...@@ -23,6 +209,29 @@ class SlideBar extends React.Component<{}, {}> {
</Link> </Link>
</li> </li>
</ul> </ul>
</Col>
<Col span={16} className="feedback">
<Dropdown
className="dropdown"
overlay={menu}
onVisibleChange={this.handleVisibleChange}
visible={menuVisible}
>
<a className="ant-dropdown-link" href="#">
Download <Icon type="down" />
</a>
</Dropdown>
<a href="https://github.com/Microsoft/nni/issues/new" target="_blank">
<img
src={require('../static/img/icon/issue.png')}
alt="NNI github issue"
/>
FeedBack
</a>
<span className="version">Version: {version}</span>
</Col>
</Row>
); );
} }
} }
......
...@@ -14,14 +14,10 @@ class BasicInfo extends React.Component<BasicInfoProps, {}> { ...@@ -14,14 +14,10 @@ class BasicInfo extends React.Component<BasicInfoProps, {}> {
constructor(props: BasicInfoProps) { constructor(props: BasicInfoProps) {
super(props); super(props);
} }
render() { render() {
const { trialProfile, const { trialProfile } = this.props;
// status
} = this.props;
return ( return (
<Row className="main"> <Row className="main">
<Col span={8} className="padItem basic"> <Col span={8} className="padItem basic">
......
...@@ -17,7 +17,7 @@ import '../../static/style/probar.scss'; ...@@ -17,7 +17,7 @@ import '../../static/style/probar.scss';
interface ProgressProps { interface ProgressProps {
trialProfile: Experiment; trialProfile: Experiment;
trialNumber: TrialNumber; trialNumber: TrialNumber;
bestAccuracy: string; bestAccuracy: number;
status: string; status: string;
errors: string; errors: string;
updateFile: Function; updateFile: Function;
...@@ -26,25 +26,27 @@ interface ProgressProps { ...@@ -26,25 +26,27 @@ interface ProgressProps {
interface ProgressState { interface ProgressState {
btnName: string; btnName: string;
isEnable: boolean; isEnable: boolean;
userInputVal?: string; // get user input userInputVal: string; // get user input
cancelSty: string; cancelSty: string;
} }
class Progressed extends React.Component<ProgressProps, ProgressState> { class Progressed extends React.Component<ProgressProps, ProgressState> {
public conInput: HTMLInputElement | null; public conInput: HTMLInputElement | null;
public _isMounted = false;
constructor(props: ProgressProps) { constructor(props: ProgressProps) {
super(props); super(props);
this.state = { this.state = {
btnName: 'Edit', btnName: 'Edit',
isEnable: true, isEnable: true,
userInputVal: this.props.trialProfile.runConcurren.toString(),
cancelSty: 'none' cancelSty: 'none'
}; };
} }
editTrialConcurrency = () => { editTrialConcurrency = () => {
const { btnName } = this.state; const { btnName } = this.state;
if (this._isMounted) {
if (btnName === 'Edit') { if (btnName === 'Edit') {
this.setState(() => ({ this.setState(() => ({
isEnable: false, isEnable: false,
...@@ -61,7 +63,7 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -61,7 +63,7 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
const experimentFile = rese.data; const experimentFile = rese.data;
const trialConcurrency = experimentFile.params.trialConcurrency; const trialConcurrency = experimentFile.params.trialConcurrency;
if (userInputVal !== undefined) { if (userInputVal !== undefined) {
if (userInputVal === trialConcurrency.toString() || userInputVal === '') { if (userInputVal === trialConcurrency.toString() || userInputVal === '0') {
message.info( message.info(
`trialConcurrency's value is ${trialConcurrency}, you did not modify it`, 2); `trialConcurrency's value is ${trialConcurrency}, you did not modify it`, 2);
} else { } else {
...@@ -78,7 +80,8 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -78,7 +80,8 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
} }
}).then(res => { }).then(res => {
if (res.status === 200) { if (res.status === 200) {
message.success(`Update ${CONTROLTYPE[1].toLocaleLowerCase()} successfully`); message.success(`Update ${CONTROLTYPE[1].toLocaleLowerCase()}
successfully`);
// rerender trial profile message // rerender trial profile message
const { updateFile } = this.props; const { updateFile } = this.props;
updateFile(); updateFile();
...@@ -105,15 +108,18 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -105,15 +108,18 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
}); });
} }
} }
}
cancelFunction = () => { cancelFunction = () => {
const { trialProfile } = this.props; const { trialProfile } = this.props;
if (this._isMounted) {
this.setState( this.setState(
() => ({ () => ({
btnName: 'Edit', btnName: 'Edit',
isEnable: true, isEnable: true,
cancelSty: 'none', cancelSty: 'none',
})); }));
}
if (this.conInput !== null) { if (this.conInput !== null) {
this.conInput.value = trialProfile.runConcurren.toString(); this.conInput.value = trialProfile.runConcurren.toString();
} }
...@@ -141,6 +147,14 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -141,6 +147,14 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
} }
} }
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
render() { render() {
const { trialProfile, trialNumber, bestAccuracy, status, errors } = this.props; const { trialProfile, trialNumber, bestAccuracy, status, errors } = this.props;
const { isEnable, btnName, cancelSty } = this.state; const { isEnable, btnName, cancelSty } = this.state;
...@@ -164,7 +178,8 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -164,7 +178,8 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
} }
return ( return (
<Row className="progress" id="barBack"> <Row className="progress" id="barBack">
<Row className="basic"> <Row className="basic lineBasic">
<Col span={12}>
<p>Status</p> <p>Status</p>
<div className="status"> <div className="status">
<span className={status}>{status}</span> <span className={status}>{status}</span>
...@@ -182,12 +197,12 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -182,12 +197,12 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
: :
<span /> <span />
} }
</div> </div>
</Row> </Col>
<Col span={12}>
{/* modify concurrency */} {/* modify concurrency */}
<p>Concurrency</p>
<Row className="inputBox"> <Row className="inputBox">
<span className="title">Concurrency:</span>
<input <input
type="number" type="number"
disabled={isEnable} disabled={isEnable}
...@@ -210,6 +225,8 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -210,6 +225,8 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
Cancel Cancel
</Button> </Button>
</Row> </Row>
</Col>
</Row>
<ProgressBar <ProgressBar
who="Duration" who="Duration"
percent={percent} percent={percent}
......
...@@ -19,7 +19,7 @@ class SearchSpace extends React.Component<SearchspaceProps, {}> { ...@@ -19,7 +19,7 @@ class SearchSpace extends React.Component<SearchspaceProps, {}> {
<div className="searchSpace"> <div className="searchSpace">
<MonacoEditor <MonacoEditor
width="100%" width="100%"
height="398" height="380"
language="json" language="json"
theme="vs-light" theme="vs-light"
value={JSON.stringify(searchSpace, null, 2)} value={JSON.stringify(searchSpace, null, 2)}
......
...@@ -3,6 +3,7 @@ import * as React from 'react'; ...@@ -3,6 +3,7 @@ import * as React from 'react';
interface Title1Props { interface Title1Props {
text: string; text: string;
icon: string; icon: string;
bgcolor?: string;
} }
class Title1 extends React.Component<Title1Props, {}> { class Title1 extends React.Component<Title1Props, {}> {
...@@ -12,10 +13,10 @@ class Title1 extends React.Component<Title1Props, {}> { ...@@ -12,10 +13,10 @@ class Title1 extends React.Component<Title1Props, {}> {
} }
render() { render() {
const { text, icon } = this.props; const { text, icon, bgcolor } = this.props;
return ( return (
<div> <div>
<div className="panelTitle"> <div className="panelTitle" style={{backgroundColor: bgcolor}}>
<img src={require(`../../static/img/icon/${icon}`)} alt="icon" /> <img src={require(`../../static/img/icon/${icon}`)} alt="icon" />
<span>{text}</span> <span>{text}</span>
</div> </div>
......
...@@ -29,7 +29,7 @@ class TrialInfo extends React.Component<TrialInfoProps, {}> { ...@@ -29,7 +29,7 @@ class TrialInfo extends React.Component<TrialInfoProps, {}> {
<div className="profile"> <div className="profile">
<MonacoEditor <MonacoEditor
width="100%" width="100%"
height="396" height="380"
language="json" language="json"
theme="vs-light" theme="vs-light"
value={JSON.stringify(showProInfo[0], null, 2)} value={JSON.stringify(showProInfo[0], null, 2)}
......
export const MANAGER_IP = `/api/v1/nni`; export const MANAGER_IP = `/api/v1/nni`;
export const DOWNLOAD_IP = `/logs`;
export const trialJobStatus = [ export const trialJobStatus = [
'UNKNOWN', 'UNKNOWN',
'WAITING', 'WAITING',
......
/* new style */ /* new style */
.overMessage{ .overMessage{
height: 456px; height: 430px;
} }
.overGraph{ .overGraph{
height: 362px; height: 362px;
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
} }
.searchSpace{ .searchSpace{
height: 386px;
line-height: 22px; line-height: 22px;
font-size: 14px; font-size: 14px;
padding: 15px 0; padding: 15px 0;
...@@ -50,28 +49,3 @@ ...@@ -50,28 +49,3 @@
} }
} }
.exbgcolor {
background: #b3b3b3;
.download{
height: 30px;
border: 1px solid #fff;
border-radius: 0;
margin-top: 4px;
background-color: #0071BC;
span{
font-family: 'Segoe';
font-size: 14px;
}
img{
height: 14px;
margin-left: 10px;
margin-top: -6px;
}
}
}
.exbgcolor .download:hover{
border: 1px solid #fff;
}
\ No newline at end of file
$titleBgcolor: #b3b3b3;
.overview .overviewBoder{ .overview .overviewBoder{
height: 100%; height: 100%;
border-right: 2px solid white; border-right: 2px solid white;
} }
.panelTitle{ .panelTitle{
display: block;
width: 100%; width: 100%;
height: 38px; height: 38px;
background: #b3b3b3; background: $titleBgcolor;
img{ img{
height: 22px; height: 22px;
...@@ -24,3 +24,25 @@ ...@@ -24,3 +24,25 @@
line-height: 38px; line-height: 38px;
} }
} }
.top10bg{
background-color: $titleBgcolor;
.top10Title{
width: 160px;
}
.title{
width: 135px;
border-left: 2px solid #fff;
}
.minTitle{
border-right: 2px solid #fff;
}
.title:hover{
cursor: pointer;
}
}
#barBack{ #barBack{
/* status: 'INITIALIZED' | 'EXPERIMENT_RUNNING' | 'ERROR' | 'STOPPING' | 'STOPPED' | 'DONE' */ /* status: 'INITIALIZED' | 'RUNNING' | 'ERROR' | 'STOPPING' | 'STOPPED' | 'DONE' */
.EXPERIMENT_RUNNING, .STOPPING, .INITIALIZED{ .RUNNING, .STOPPING, .INITIALIZED{
/* specific status color */ /* specific status color */
color: #0071bc; color: #0071bc;
.ant-progress-bg { .ant-progress-bg {
......
.progress{ .progress{
margin: 15px 20px; margin: 15px 17px;
.status{ .status{
color: #0573bc; color: #0573bc;
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
margin-top: 5px;
} }
.probar{ .probar{
...@@ -71,24 +72,21 @@ ...@@ -71,24 +72,21 @@
} }
*/ */
.inputBox{ .inputBox{
height: 30px; height: 26px;
margin-top: 8px;
border-bottom: 1px solid #ccc;
padding-bottom: 44px;
.title{
font-size: 14px;
margin-right: 10px;
}
.concurrencyInput{ .concurrencyInput{
width: 25%; width: 25%;
height: 32px; height: 26px;
padding-left: 8px;
outline: none; outline: none;
border: 1px solid #ccc; border: 1px solid #ccc;
} }
.editStyle{ .editStyle{
height: 32px; height: 26px;
padding: 0 9px;
} }
} }
.lineBasic{
padding-bottom: 14px;
border-bottom: 1px solid #ccc;
}
$barHeight: 56px;
.nav{ .nav{
list-style: none; list-style: none;
width: 100%; width: 94%;
height: 80px; height: $barHeight;
li{ margin: 0 auto;
float: left; .tab{
margin-right: 40px;
font-family: 'Segoe'; font-family: 'Segoe';
line-height: $barHeight;
a{ a{
display: block;
padding: 0 10px;
font-size: 18px; font-size: 18px;
color: #b8c7ce; color: #b8c7ce;
text-decoration: none; text-decoration: none;
} }
} }
.firstTab{
margin: 0 32px;
}
.logo{ .logo{
height: 80px; margin-top: 2px;
line-height: 80px; max-width: 128px;
} }
.tab{ }
position: relative;
top: 36px;
line-height: 30px;
.tab a:hover, .tab a.high{
color: white;
border-bottom: 1px solid #fff;
}
.feedback{
text-align: right;
line-height: $barHeight;
font-size: 16px;
color: #fff;
a{
color: #fff;
text-decoration: none;
margin-left: 10px;
}
img{
width: 24px;
margin-right: 8px;
} }
.last{ .version{
margin-right: 0; margin-left: 16px;
} }
} }
.nav li a:hover, .nav a.high{ .link li{
color: white; float: left;
border-bottom: 1px solid white; }
.dropdown{
margin-right: 10px;
} }
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment