Unverified Commit cb25d66e authored by SparkSnail's avatar SparkSnail Committed by GitHub
Browse files

Merge pull request #190 from microsoft/master

merge master
parents 9fb25ccc 7ee86e1d
configspace @ f389e1d0
Subproject commit f389e1d0a72564f7f1fd4d86039e5f393a45a058
This file is placed here by pip to indicate the source was put
here by pip.
Once this package is successfully installed this source code will be
deleted (unless you remove this file).
ConfigSpace==0.4.7 ConfigSpace==0.4.7
statsmodels==0.9.0 statsmodels==0.10.0
\ No newline at end of file \ No newline at end of file
.nni{ .nni{
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #212121; color: #212121;
font-size: 14px; font-size: 14px;
background: #f2f2f2; background: #f2f2f2;
......
import * as React from 'react';
import axios from 'axios';
import { downFile } from '../../static/function';
import { Drawer, Tabs, Row, Col, Button } from 'antd';
import { MANAGER_IP, DRAWEROPTION } from '../../static/const';
import MonacoEditor from 'react-monaco-editor';
const { TabPane } = Tabs;
import '../../static/style/logDrawer.scss';
interface ExpDrawerProps {
isVisble: boolean;
closeExpDrawer: () => void;
}
interface ExpDrawerState {
experiment: string;
}
class ExperimentDrawer extends React.Component<ExpDrawerProps, ExpDrawerState> {
public _isCompareMount: boolean;
constructor(props: ExpDrawerProps) {
super(props);
this.state = {
experiment: ''
};
}
getExperimentContent = () => {
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);
}
let trialMessagesArr = res1.data;
const interResultList = res2.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 result = {
experimentParameters: res.data,
trialMessage: trialMessagesArr
};
if (this._isCompareMount === true) {
this.setState(() => ({ experiment: JSON.stringify(result, null, 4) }));
}
}
}));
}
downExperimentParameters = () => {
const { experiment } = this.state;
downFile(experiment, 'experiment.json');
}
componentDidMount() {
this._isCompareMount = true;
this.getExperimentContent();
}
componentWillReceiveProps(nextProps: ExpDrawerProps) {
const { isVisble } = nextProps;
if (isVisble === true) {
this.getExperimentContent();
}
}
componentWillUnmount() {
this._isCompareMount = false;
}
render() {
const { isVisble, closeExpDrawer } = this.props;
const { experiment } = this.state;
const heights: number = window.innerHeight - 48;
return (
<Row className="logDrawer">
<Drawer
// title="Log Message"
placement="right"
closable={false}
destroyOnClose={true}
onClose={closeExpDrawer}
visible={isVisble}
width="54%"
height={heights}
>
<div className="card-container log-tab-body" style={{ height: heights }}>
<Tabs type="card">
<TabPane tab="Experiment Parameters" key="Experiment">
<div className="just-for-log">
<MonacoEditor
width="100%"
height={heights * 0.9}
language="json"
value={experiment}
options={DRAWEROPTION}
/>
</div>
<Row className="buttons">
<Col span={12}>
<Button
type="primary"
onClick={this.downExperimentParameters}
>
Download
</Button>
</Col>
<Col span={12} className="close">
<Button
type="default"
onClick={closeExpDrawer}
>
Close
</Button>
</Col>
</Row>
</TabPane>
</Tabs>
</div>
</Drawer>
</Row>
);
}
}
export default ExperimentDrawer;
import * as React from 'react';
import axios from 'axios';
import { Drawer, Tabs, Row, Col, Button, Icon } from 'antd';
import { DOWNLOAD_IP } from '../../static/const';
import { downFile } from '../../static/function';
const { TabPane } = Tabs;
import MonacoHTML from '../public-child/MonacoEditor';
import '../../static/style/logDrawer.scss';
interface LogDrawerProps {
isVisble: boolean;
closeDrawer: () => void;
activeTab?: string;
}
interface LogDrawerState {
nniManagerLogStr: string;
dispatcherLogStr: string;
isLoading: boolean;
isLoadispatcher: boolean;
}
class LogDrawer extends React.Component<LogDrawerProps, LogDrawerState> {
public _isLogDrawer: boolean;
constructor(props: LogDrawerProps) {
super(props);
this.state = {
nniManagerLogStr: 'nnimanager',
dispatcherLogStr: 'dispatcher',
isLoading: false,
isLoadispatcher: false
};
}
getNNImanagerLogmessage = () => {
if (this._isLogDrawer === true) {
this.setState({ isLoading: true }, () => {
axios(`${DOWNLOAD_IP}/nnimanager.log`, {
method: 'GET'
})
.then(res => {
if (res.status === 200) {
setTimeout(() => { this.setNNImanager(res.data); }, 300);
}
});
});
}
}
setDispatcher = (value: string) => {
if (this._isLogDrawer === true) {
this.setState(() => ({ isLoadispatcher: false, dispatcherLogStr: value }));
}
}
setNNImanager = (val: string) => {
if (this._isLogDrawer === true) {
this.setState(() => ({ isLoading: false, nniManagerLogStr: val }));
}
}
getdispatcherLogmessage = () => {
if (this._isLogDrawer === true) {
this.setState({ isLoadispatcher: true }, () => {
axios(`${DOWNLOAD_IP}/dispatcher.log`, {
method: 'GET'
})
.then(res => {
if (res.status === 200) {
setTimeout(() => { this.setDispatcher(res.data); }, 300);
}
});
});
}
}
downloadNNImanager = () => {
const { nniManagerLogStr } = this.state;
downFile(nniManagerLogStr, 'nnimanager.log');
}
downloadDispatcher = () => {
const { dispatcherLogStr } = this.state;
downFile(dispatcherLogStr, 'dispatcher.log');
}
dispatcherHTML = () => {
return (
<div>
<span>Dispatcher Log</span>
<span className="refresh" onClick={this.getdispatcherLogmessage}>
<Icon type="sync" />
</span>
</div>
);
}
nnimanagerHTML = () => {
return (
<div>
<span>NNImanager Log</span>
<span className="refresh" onClick={this.getNNImanagerLogmessage}><Icon type="sync" /></span>
</div>
);
}
componentDidMount() {
this._isLogDrawer = true;
this.getNNImanagerLogmessage();
this.getdispatcherLogmessage();
}
componentWillReceiveProps(nextProps: LogDrawerProps) {
const { isVisble, activeTab } = nextProps;
if (isVisble === true) {
if (activeTab === 'nnimanager') {
this.getNNImanagerLogmessage();
}
if (activeTab === 'dispatcher') {
this.getdispatcherLogmessage();
}
}
}
componentWillUnmount() {
this._isLogDrawer = false;
}
render() {
const { isVisble, closeDrawer, activeTab } = this.props;
const { nniManagerLogStr, dispatcherLogStr, isLoadispatcher, isLoading } = this.state;
const heights: number = window.innerHeight - 48; // padding top and bottom
return (
<Row>
<Drawer
placement="right"
closable={false}
destroyOnClose={true}
onClose={closeDrawer}
visible={isVisble}
width="76%"
height={heights}
// className="logDrawer"
>
<div className="card-container log-tab-body" style={{ height: heights }}>
<Tabs type="card" defaultActiveKey={activeTab}>
{/* <Tabs type="card" onTabClick={this.selectwhichLog} defaultActiveKey={activeTab}> */}
{/* <TabPane tab="Dispatcher Log" key="dispatcher"> */}
<TabPane tab={this.dispatcherHTML()} key="dispatcher">
<div>
<MonacoHTML content={dispatcherLogStr} loading={isLoadispatcher} />
</div>
<Row className="buttons">
<Col span={12}>
<Button
type="primary"
onClick={this.downloadDispatcher}
>
Download
</Button>
</Col>
<Col span={12} className="close">
<Button
type="default"
onClick={closeDrawer}
>
Close
</Button>
</Col>
</Row>
</TabPane>
<TabPane tab={this.nnimanagerHTML()} key="nnimanager">
{/* <TabPane tab="NNImanager Log" key="nnimanager"> */}
<div>
<MonacoHTML content={nniManagerLogStr} loading={isLoading} />
</div>
<Row className="buttons">
<Col span={12} className="download">
<Button
type="primary"
onClick={this.downloadNNImanager}
>
Download
</Button>
</Col>
<Col span={12} className="close">
<Button
type="default"
onClick={closeDrawer}
>
Close
</Button>
</Col>
</Row>
</TabPane>
</Tabs>
</div>
</Drawer>
</Row>
);
}
}
export default LogDrawer;
...@@ -3,10 +3,11 @@ import { Link } from 'react-router'; ...@@ -3,10 +3,11 @@ import { Link } from 'react-router';
import axios from 'axios'; import axios from 'axios';
import { MANAGER_IP } from '../static/const'; import { MANAGER_IP } from '../static/const';
import MediaQuery from 'react-responsive'; import MediaQuery from 'react-responsive';
import { DOWNLOAD_IP } from '../static/const';
import { Row, Col, Menu, Dropdown, Icon, Select, Button } from 'antd'; import { Row, Col, Menu, Dropdown, Icon, Select, Button } from 'antd';
const { SubMenu } = Menu; const { SubMenu } = Menu;
const { Option } = Select; const { Option } = Select;
import LogDrawer from './Modal/LogDrawer';
import ExperimentDrawer from './Modal/ExperimentDrawer';
import '../static/style/slideBar.scss'; import '../static/style/slideBar.scss';
import '../static/style/button.scss'; import '../static/style/button.scss';
...@@ -15,6 +16,9 @@ interface SliderState { ...@@ -15,6 +16,9 @@ interface SliderState {
menuVisible: boolean; menuVisible: boolean;
navBarVisible: boolean; navBarVisible: boolean;
isdisabledFresh: boolean; isdisabledFresh: boolean;
isvisibleLogDrawer: boolean;
isvisibleExperimentDrawer: boolean;
activeKey: string;
} }
interface SliderProps { interface SliderProps {
...@@ -38,124 +42,13 @@ class SlideBar extends React.Component<SliderProps, SliderState> { ...@@ -38,124 +42,13 @@ class SlideBar extends React.Component<SliderProps, SliderState> {
version: '', version: '',
menuVisible: false, menuVisible: false,
navBarVisible: false, navBarVisible: false,
isdisabledFresh: false isdisabledFresh: false,
isvisibleLogDrawer: false, // download button (nnimanager·dispatcher) click -> drawer
isvisibleExperimentDrawer: false,
activeKey: 'dispatcher'
}; };
} }
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;
let trialMessagesArr = res1.data;
const interResultList = res2.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 result = {
experimentParameters: res.data,
trialMessage: trialMessagesArr
};
const aTag = document.createElement('a');
const file = new Blob([JSON.stringify(result, null, 4)], { 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.log';
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.log';
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.log';
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.log';
downTag.href = URL.createObjectURL(file);
});
let eventMouse = document.createEvent('MouseEvents');
eventMouse.initEvent('click', false, false);
downTag.dispatchEvent(eventMouse);
}
}
});
}
getNNIversion = () => { getNNIversion = () => {
axios(`${MANAGER_IP}/version`, { axios(`${MANAGER_IP}/version`, {
method: 'GET' method: 'GET'
...@@ -170,17 +63,23 @@ class SlideBar extends React.Component<SliderProps, SliderState> { ...@@ -170,17 +63,23 @@ class SlideBar extends React.Component<SliderProps, SliderState> {
handleMenuClick = (e: EventPer) => { handleMenuClick = (e: EventPer) => {
if (this._isMounted) { this.setState({ menuVisible: false }); } if (this._isMounted) { this.setState({ menuVisible: false }); }
switch (e.key) { switch (e.key) {
// download experiment related content // to see & download experiment parameters
case '1': case '1':
this.downExperimentContent(); if (this._isMounted === true) {
this.setState(() => ({ isvisibleExperimentDrawer: true }));
}
break; break;
// download nnimanager log file // to see & download nnimanager log
case '2': case '2':
this.downnnimanagerLog(); if (this._isMounted === true) {
this.setState(() => ({ activeKey: 'nnimanager', isvisibleLogDrawer: true }));
}
break; break;
// download dispatcher log file // to see & download dispatcher log
case '3': case '3':
this.downDispatcherlog(); if (this._isMounted === true) {
this.setState(() => ({ isvisibleLogDrawer: true, activeKey: 'dispatcher' }));
}
break; break;
case 'close': case 'close':
case '10': case '10':
...@@ -285,6 +184,20 @@ class SlideBar extends React.Component<SliderProps, SliderState> { ...@@ -285,6 +184,20 @@ class SlideBar extends React.Component<SliderProps, SliderState> {
} }
} }
// close log drawer (nnimanager.dispatcher)
closeLogDrawer = () => {
if (this._isMounted === true) {
this.setState(() => ({ isvisibleLogDrawer: false, activeKey: '' }));
}
}
// close download experiment parameters drawer
closeExpDrawer = () => {
if (this._isMounted === true) {
this.setState(() => ({ isvisibleExperimentDrawer: false }));
}
}
componentDidMount() { componentDidMount() {
this._isMounted = true; this._isMounted = true;
this.getNNIversion(); this.getNNIversion();
...@@ -295,79 +208,91 @@ class SlideBar extends React.Component<SliderProps, SliderState> { ...@@ -295,79 +208,91 @@ class SlideBar extends React.Component<SliderProps, SliderState> {
} }
render() { render() {
const { version, menuVisible } = this.state; const { version, menuVisible, isvisibleLogDrawer, activeKey, isvisibleExperimentDrawer } = this.state;
const feed = `https://github.com/Microsoft/nni/issues/new?labels=${version}`; const feed = `https://github.com/Microsoft/nni/issues/new?labels=${version}`;
return ( return (
<Row> <Row>
<Col span={18}> <Row>
<MediaQuery query="(min-width: 1299px)"> <Col span={18}>
<Row className="nav"> <MediaQuery query="(min-width: 1299px)">
<ul className="link"> <Row className="nav">
<li className="logo"> <ul className="link">
<li className="logo">
<Link to={'/oview'}>
<img
src={require('../static/img/logo2.png')}
style={{ width: 88 }}
alt="NNI logo"
/>
</Link>
</li>
<li className="tab firstTab">
<Link to={'/oview'} activeClassName="high">
Overview
</Link>
</li>
<li className="tab">
<Link to={'/detail'} activeClassName="high">
Trials detail
</Link>
</li>
<li className="feedback">
<Dropdown
className="dropdown"
overlay={this.menu()}
onVisibleChange={this.handleVisibleChange}
visible={menuVisible}
trigger={['click']}
>
<a className="ant-dropdown-link" href="#">
Download <Icon type="down" />
</a>
</Dropdown>
<a href={feed} target="_blank">
<img
src={require('../static/img/icon/issue.png')}
alt="NNI github issue"
/>
Feedback
</a>
<span className="version">Version: {version}</span>
</li>
</ul>
</Row>
</MediaQuery>
</Col>
<Col span={18}>
<MediaQuery query="(max-width: 1299px)">
<Row className="little">
<Col span={1} className="menu">
<Dropdown overlay={this.navigationBar()} trigger={['click']}>
<Icon type="unordered-list" className="more" />
</Dropdown>
</Col>
<Col span={14} className="logo">
<Link to={'/oview'}> <Link to={'/oview'}>
<img <img
src={require('../static/img/logo2.png')} src={require('../static/img/logo2.png')}
style={{ width: 88 }} style={{ width: 80 }}
alt="NNI logo" alt="NNI logo"
/> />
</Link> </Link>
</li> </Col>
<li className="tab firstTab"> </Row>
<Link to={'/oview'} activeClassName="high"> </MediaQuery>
Overview </Col>
</Link> <Col span={3}> {this.select()} </Col>
</li> </Row>
<li className="tab"> {/* the drawer for dispatcher & nnimanager log message */}
<Link to={'/detail'} activeClassName="high"> <LogDrawer
Trials detail isVisble={isvisibleLogDrawer}
</Link> closeDrawer={this.closeLogDrawer}
</li> activeTab={activeKey}
<li className="feedback"> />
<Dropdown <ExperimentDrawer
className="dropdown" isVisble={isvisibleExperimentDrawer}
overlay={this.menu()} closeExpDrawer={this.closeExpDrawer}
onVisibleChange={this.handleVisibleChange} />
visible={menuVisible}
trigger={['click']}
>
<a className="ant-dropdown-link" href="#">
Download <Icon type="down" />
</a>
</Dropdown>
<a href={feed} target="_blank">
<img
src={require('../static/img/icon/issue.png')}
alt="NNI github issue"
/>
Feedback
</a>
<span className="version">Version: {version}</span>
</li>
</ul>
</Row>
</MediaQuery>
</Col>
<Col span={18}>
<MediaQuery query="(max-width: 1299px)">
<Row className="little">
<Col span={1} className="menu">
<Dropdown overlay={this.navigationBar()} trigger={['click']}>
<Icon type="unordered-list" className="more" />
</Dropdown>
</Col>
<Col span={14} className="logo">
<Link to={'/oview'}>
<img
src={require('../static/img/logo2.png')}
style={{ width: 80 }}
alt="NNI logo"
/>
</Link>
</Col>
</Row>
</MediaQuery>
</Col>
<Col span={3}> {this.select()} </Col>
</Row> </Row>
); );
} }
......
...@@ -7,6 +7,7 @@ import { MANAGER_IP, CONTROLTYPE } from '../../static/const'; ...@@ -7,6 +7,7 @@ import { MANAGER_IP, CONTROLTYPE } from '../../static/const';
import { Experiment, TrialNumber } from '../../static/interface'; import { Experiment, TrialNumber } from '../../static/interface';
import { convertTime } from '../../static/function'; import { convertTime } from '../../static/function';
import ProgressBar from './ProgressItem'; import ProgressBar from './ProgressItem';
import LogDrawer from '../Modal/LogDrawer';
import '../../static/style/progress.scss'; import '../../static/style/progress.scss';
import '../../static/style/probar.scss'; import '../../static/style/probar.scss';
...@@ -24,6 +25,7 @@ interface ProgressState { ...@@ -24,6 +25,7 @@ interface ProgressState {
isEnable: boolean; isEnable: boolean;
userInputVal: string; // get user input userInputVal: string; // get user input
cancelSty: string; cancelSty: string;
isShowLogDrawer: boolean;
} }
class Progressed extends React.Component<ProgressProps, ProgressState> { class Progressed extends React.Component<ProgressProps, ProgressState> {
...@@ -36,7 +38,8 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -36,7 +38,8 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
btnName: 'Edit', btnName: 'Edit',
isEnable: true, isEnable: true,
userInputVal: this.props.trialProfile.runConcurren.toString(), userInputVal: this.props.trialProfile.runConcurren.toString(),
cancelSty: 'none' cancelSty: 'none',
isShowLogDrawer: false
}; };
} }
...@@ -139,6 +142,18 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -139,6 +142,18 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
} }
} }
isShowDrawer = () => {
if (this._isMounted === true) {
this.setState(() => ({ isShowLogDrawer: true }));
}
}
closeDrawer = () => {
if (this._isMounted === true) {
this.setState(() => ({ isShowLogDrawer: false }));
}
}
componentWillReceiveProps() { componentWillReceiveProps() {
const { trialProfile } = this.props; const { trialProfile } = this.props;
if (this.conInput !== null) { if (this.conInput !== null) {
...@@ -156,7 +171,7 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -156,7 +171,7 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
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, isShowLogDrawer } = this.state;
const bar2 = trialNumber.totalCurrentTrial - trialNumber.waitTrial - trialNumber.unknowTrial; const bar2 = trialNumber.totalCurrentTrial - trialNumber.waitTrial - trialNumber.unknowTrial;
const bar2Percent = (bar2 / trialProfile.MaxTrialNum) * 100; const bar2Percent = (bar2 / trialProfile.MaxTrialNum) * 100;
const percent = (trialProfile.execDuration / trialProfile.maxDuration) * 100; const percent = (trialProfile.execDuration / trialProfile.maxDuration) * 100;
...@@ -173,6 +188,7 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -173,6 +188,7 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
errorContent = ( errorContent = (
<div className="errors"> <div className="errors">
{errors} {errors}
<div><a href="#" onClick={this.isShowDrawer}>Learn about</a></div>
</div> </div>
); );
} }
...@@ -282,8 +298,13 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -282,8 +298,13 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
<div>{trialNumber.failTrial}</div> <div>{trialNumber.failTrial}</div>
</Row> </Row>
</Col> </Col>
</Row> </Row>
{/* learn about click -> default active key is dispatcher. */}
<LogDrawer
isVisble={isShowLogDrawer}
closeDrawer={this.closeDrawer}
activeTab="dispatcher"
/>
</Row> </Row>
); );
} }
......
import * as React from 'react';
import { Spin } from 'antd';
import { DRAWEROPTION } from '../../static/const';
import MonacoEditor from 'react-monaco-editor';
interface MonacoEditorProps {
content: string;
loading: boolean;
}
class MonacoHTML extends React.Component<MonacoEditorProps, {}> {
public _isMonacoMount: boolean;
constructor(props: MonacoEditorProps) {
super(props);
}
componentDidMount() {
this._isMonacoMount = true;
}
componentWillUnmount() {
this._isMonacoMount = false;
}
render() {
const { content, loading } = this.props;
const heights: number = window.innerHeight - 48;
return (
<div className="just-for-log">
<Spin
// tip="Loading..."
style={{ width: '100%', height: heights * 0.9 }}
spinning={loading}
>
<MonacoEditor
width="100%"
height={heights * 0.9}
language="json"
value={content}
options={DRAWEROPTION}
/>
</Spin>
</div>
);
}
}
export default MonacoHTML;
...@@ -19,6 +19,11 @@ const MONACO = { ...@@ -19,6 +19,11 @@ const MONACO = {
readOnly: true, readOnly: true,
automaticLayout: true automaticLayout: true
}; };
const DRAWEROPTION = {
minimap: { enabled: false },
readOnly: true,
automaticLayout: true
};
const COLUMN_INDEX = [ const COLUMN_INDEX = [
{ {
name: 'Trial No.', name: 'Trial No.',
...@@ -52,5 +57,5 @@ const COLUMN_INDEX = [ ...@@ -52,5 +57,5 @@ const COLUMN_INDEX = [
const COLUMN = ['Trial No.', 'ID', 'Duration', 'Status', 'Default', 'Operation', 'Intermediate result']; const COLUMN = ['Trial No.', 'ID', 'Duration', 'Status', 'Default', 'Operation', 'Intermediate result'];
export { export {
MANAGER_IP, DOWNLOAD_IP, trialJobStatus, MANAGER_IP, DOWNLOAD_IP, trialJobStatus,
CONTROLTYPE, MONACO, COLUMN, COLUMN_INDEX CONTROLTYPE, MONACO, COLUMN, COLUMN_INDEX, DRAWEROPTION
}; };
...@@ -138,7 +138,29 @@ const filterDuration = (item: TableObj) => { ...@@ -138,7 +138,29 @@ const filterDuration = (item: TableObj) => {
return item.status !== 'WAITING'; return item.status !== 'WAITING';
}; };
const downFile = (content: string, fileName: string) => {
const aTag = document.createElement('a');
const isEdge = navigator.userAgent.indexOf('Edge') !== -1 ? true : false;
const file = new Blob([content], { type: 'application/json' });
aTag.download = fileName;
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 = fileName;
downTag.href = URL.createObjectURL(file);
});
let eventMouse = document.createEvent('MouseEvents');
eventMouse.initEvent('click', false, false);
downTag.dispatchEvent(eventMouse);
}
};
export { export {
convertTime, convertDuration, getFinalResult, getFinal, convertTime, convertDuration, getFinalResult, getFinal, downFile,
intermediateGraphOption, killJob, filterByStatus, filterDuration intermediateGraphOption, killJob, filterByStatus, filterDuration
}; };
$btnBgcolor: #0071bc; $btnBgcolor: #0071bc;
Button.tableButton{ Button.tableButton{
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: $btnBgcolor; background: $btnBgcolor;
border-color: $btnBgcolor; border-color: $btnBgcolor;
height: 26px; height: 26px;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
.column{ .column{
max-width: 124px; max-width: 124px;
padding-left: 18px; padding-left: 18px;
font-weight: 700; font-weight: 600;
} }
.value{ .value{
max-width: 152px; max-width: 152px;
...@@ -20,6 +20,6 @@ ...@@ -20,6 +20,6 @@
text-align: left; text-align: left;
} }
.idList{ .idList{
font-weight: 700; font-weight: 600;
} }
} }
...@@ -55,7 +55,7 @@ div.addtitle{ ...@@ -55,7 +55,7 @@ div.addtitle{
font-size: 20px; font-size: 20px;
} }
.line{ .line{
font-weight: bold; font-weight: 600;
color: rgb(60,141,188); color: rgb(60,141,188);
padding-right: 20px; padding-right: 20px;
} }
......
.card-container > .ant-tabs-card > .ant-tabs-content {
margin-top: -16px;
}
.card-container > .ant-tabs-card > .ant-tabs-content > .ant-tabs-tabpane {
background: #fff;
padding: 16px;
}
.card-container > .ant-tabs-card > .ant-tabs-bar {
border-color: #fff;
}
.card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab {
border-color: transparent;
background: transparent;
}
.card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active {
border-color: #fff;
background: #fff;
}
.logContainer{
height: 100%;
}
.buttons{
margin-top: 15px;
.close{
text-align: right;
}
}
/*
.logDrawer{
width: 100%;
.ant-drawer-body{
box-sizing: border-box;
-webkit-box-sizing: border-box;
}
}
*/
.ant-drawer-body{
background: #333;
}
.card-container > .ant-tabs-card > .ant-tabs-bar{
border: none;
}
.card-container > .ant-tabs-card > .ant-tabs-content > .ant-tabs-tabpane{
background-color: #333;
}
.close{
Button, Button:active, Button:hover{
background-color: #212121;
color: #fff;
border: none;
}
}
.download{
Button, Button:active, Button:hover{
background-color: #2772be;
color: #fff;
border: none;
}
}
.log-tab-body > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active{
background-color: #1e1e1e;
color: #fff;
border: none;
}
.log-tab-body .ant-tabs-nav .ant-tabs-tab:hover, .log-tab-body .ant-tabs-nav .ant-tabs-tab{
color: #fff;
border: none;
}
.ant-tabs.ant-tabs-card>.ant-tabs-bar .ant-tabs-tab{
border: none;
}
.log-tab-body{
.refresh{
margin-left: 10px;
display: none;
}
.ant-tabs-tab-active{
.refresh{
transition: 0.3s;
display: inline-block;
}
.refresh:hover{
transform: scale(1.2);
}
}
}
.just-for-log{
.monaco-editor{
.line-numbers{
color: #fff;
}
.current-line ~ .line-numbers{
color: #FFFAF0;
}
}
.view-lines{
background-color: #1e1e1e;
.mtk1{
color: #fff;
}
}
.margin-view-overlays{
background-color: #1e1e1e;
}
}
...@@ -22,7 +22,7 @@ $bgColor: #f2f2f2; ...@@ -22,7 +22,7 @@ $bgColor: #f2f2f2;
} }
.ant-tabs-nav .ant-tabs-tab-active{ .ant-tabs-nav .ant-tabs-tab-active{
color: $color; color: $color;
font-weight: 500; font-weight: 600;
background: #dedede; background: #dedede;
border-left: 3px solid ; border-left: 3px solid ;
} }
......
...@@ -5,6 +5,7 @@ $titleBgcolor: #b3b3b3; ...@@ -5,6 +5,7 @@ $titleBgcolor: #b3b3b3;
} }
.panelTitle{ .panelTitle{
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
width: 100%; width: 100%;
height: 38px; height: 38px;
background: $titleBgcolor; background: $titleBgcolor;
...@@ -17,8 +18,7 @@ $titleBgcolor: #b3b3b3; ...@@ -17,8 +18,7 @@ $titleBgcolor: #b3b3b3;
span{ span{
font-size: 18px; font-size: 18px;
font-weight: bold; font-weight: 600;
font-family: 'Segoe';
color: #333; color: #333;
line-height: 38px; line-height: 38px;
margin-left: 14px; margin-left: 14px;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
.status{ .status{
color: #0573bc; color: #0573bc;
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: 600;
margin-top: 5px; margin-top: 5px;
} }
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
.basic{ .basic{
line-height: 24px; line-height: 24px;
font-family: 'Segoe'; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
p{ p{
font-size: 14px; font-size: 14px;
color: #212121; color: #212121;
......
...@@ -10,8 +10,8 @@ $drowHoverBgColor: #e2e2e2; ...@@ -10,8 +10,8 @@ $drowHoverBgColor: #e2e2e2;
margin: 0 auto; margin: 0 auto;
position: relative; position: relative;
.tab{ .tab{
font-family: 'Segoe';
line-height: $barHeight; line-height: $barHeight;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
a{ a{
font-size: 18px; font-size: 18px;
color: #b8c7ce; color: #b8c7ce;
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
} }
/* add the brother selector to increase the priority */ /* add the brother selector to increase the priority */
#succeTable .commonTableStyle, #tableList .commonTableStyle { #succeTable .commonTableStyle, #tableList .commonTableStyle {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
tr{ tr{
text-align: center; text-align: center;
color:#212121; color:#212121;
......
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