Commit c288a16e authored by Lijiao's avatar Lijiao Committed by chicm-ms
Browse files

[WebUI] Show trial log for pai and k8s (#580)

* [WebUI] Show trial log for pai and k8s

* fix lint

* Fix comments
parent d13964dc
...@@ -17,12 +17,17 @@ ...@@ -17,12 +17,17 @@
.headerCon{ .headerCon{
min-width: 1024px; min-width: 1024px;
} }
.contentBox{
width: 100%;
background: #f2f2f2;
}
.content{ .content{
width: 86%; width: 86%;
min-width: 1024px; min-width: 1024px;
margin: 0 auto; margin: 0 auto;
margin-top: 74px; margin-top: 74px;
margin-bottom: 30px; margin-bottom: 30px;
background: #fff;
} }
...@@ -6,18 +6,20 @@ import SlideBar from './components/SlideBar'; ...@@ -6,18 +6,20 @@ import SlideBar from './components/SlideBar';
class App extends React.Component<{}, {}> { class App extends React.Component<{}, {}> {
render() { render() {
return ( return (
<Row className="nni"> <Row className="nni" style={{minHeight: window.innerHeight}}>
<Row className="header"> <Row className="header">
<Col span={1} /> <Col span={1} />
<Col className="headerCon" span={22}> <Col className="headerCon" span={22}>
<SlideBar /> <SlideBar />
</Col> </Col>
<Col span={1}/> <Col span={1} />
</Row> </Row>
<Row className="contentBox">
<Row className="content"> <Row className="content">
{this.props.children} {this.props.children}
</Row> </Row>
</Row> </Row>
</Row>
); );
} }
} }
......
...@@ -215,6 +215,7 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -215,6 +215,7 @@ class Overview extends React.Component<{}, OverviewState> {
case 'USER_CANCELED': case 'USER_CANCELED':
case 'SYS_CANCELED': case 'SYS_CANCELED':
case 'EARLY_STOPPED':
profile.stopTrial += 1; profile.stopTrial += 1;
break; break;
case 'SUCCEEDED': case 'SUCCEEDED':
...@@ -461,7 +462,10 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -461,7 +462,10 @@ class Overview extends React.Component<{}, OverviewState> {
</Row> </Row>
</Col> </Col>
<Col span={16} id="succeTable"> <Col span={16} id="succeTable">
<SuccessTable tableSource={tableData} /> <SuccessTable
tableSource={tableData}
trainingPlatform={trialProfile.trainingServicePlatform}
/>
</Col> </Col>
</Row> </Row>
</div> </div>
......
...@@ -21,6 +21,7 @@ interface TrialDetailState { ...@@ -21,6 +21,7 @@ interface TrialDetailState {
isHasSearch: boolean; isHasSearch: boolean;
experimentStatus: string; experimentStatus: string;
entriesTable: number; entriesTable: number;
experimentPlatform: string;
} }
class TrialsDetail extends React.Component<{}, TrialDetailState> { class TrialsDetail extends React.Component<{}, TrialDetailState> {
...@@ -43,6 +44,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -43,6 +44,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
experimentStatus: '', experimentStatus: '',
entriesTable: 20, entriesTable: 20,
isHasSearch: false, isHasSearch: false,
experimentPlatform: ''
}; };
} }
// trial accuracy graph // trial accuracy graph
...@@ -370,6 +372,26 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -370,6 +372,26 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
alert('TableList component was not properly initialized.'); alert('TableList component was not properly initialized.');
} }
checkExperimentPlatform = () => {
axios(`${MANAGER_IP}/experiment`, {
method: 'GET'
})
.then(res => {
if (res.status === 200) {
const trainingPlatform = res.data.params.trainingServicePlatform !== undefined
?
res.data.params.trainingServicePlatform
:
'';
if (this._isMounted) {
this.setState({
experimentPlatform: trainingPlatform
});
}
}
});
}
componentDidMount() { componentDidMount() {
this._isMounted = true; this._isMounted = true;
...@@ -377,6 +399,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -377,6 +399,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
this.drawPointGraph(); this.drawPointGraph();
this.interTableList = window.setInterval(this.drawTableList, 10000); this.interTableList = window.setInterval(this.drawTableList, 10000);
this.interAccuracy = window.setInterval(this.drawPointGraph, 10000); this.interAccuracy = window.setInterval(this.drawPointGraph, 10000);
this.checkExperimentPlatform();
} }
componentWillUnmount() { componentWillUnmount() {
...@@ -386,7 +409,10 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -386,7 +409,10 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
} }
render() { render() {
const { accSource, accNodata, tableListSource, entriesTable, searchResultSource, isHasSearch } = this.state; const { accSource, accNodata, tableListSource,
entriesTable, searchResultSource, isHasSearch,
experimentPlatform
} = this.state;
const titleOfacc = ( const titleOfacc = (
<Title1 text="Default Metric" icon="3.png" /> <Title1 text="Default Metric" icon="3.png" />
); );
...@@ -463,6 +489,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -463,6 +489,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
updateList={this.drawTableList} updateList={this.drawTableList}
searchResult={searchResultSource} searchResult={searchResultSource}
isHasSearch={isHasSearch} isHasSearch={isHasSearch}
platform={experimentPlatform}
ref={(tabList) => this.tableList = tabList} ref={(tabList) => this.tableList = tabList}
/> />
</div> </div>
......
import * as React from 'react';
import { Row, Button } from 'antd';
import { DOWNLOAD_IP } from '../../static/const';
interface PaiTrialChildProps {
logString: string;
id: string;
showLogModal: Function;
isdisLogbtn?: boolean;
}
class PaiTrialChild extends React.Component<PaiTrialChildProps, {}> {
constructor(props: PaiTrialChildProps) {
super(props);
}
render() {
const { logString, id, showLogModal, isdisLogbtn } = this.props;
return (
<div>
{
logString === ''
?
<div />
:
<Row>
<Row>
<a
target="_blank"
href={`${DOWNLOAD_IP}/trial_${id}.log`}
style={{ marginRight: 10 }}
>
trial stdout
</a>
</Row>
<Row>
<Button
disabled={isdisLogbtn}
type="primary"
className="tableButton"
onClick={showLogModal.bind(this, id)}
>
View
</Button>
</Row>
</Row>
}
</div>
);
}
}
export default PaiTrialChild;
import * as React from 'react';
import { Row, Button } from 'antd';
import { DOWNLOAD_IP } from '../../static/const';
import PaiTrialChild from './PaiTrialChild';
interface PaitrialLogProps {
logStr: string;
id: string;
showLogModal: Function;
trialStatus?: string;
isdisLogbutton?: boolean;
}
class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
constructor(props: PaitrialLogProps) {
super(props);
}
render() {
const { logStr, id, showLogModal,
isdisLogbutton
} = this.props;
const isTwopath = logStr.indexOf(',') !== -1
?
true
:
false;
return (
<div>
<div>
{
isTwopath
?
<Row>
<Row>
<a
target="_blank"
href={`${DOWNLOAD_IP}/trial_${id}.log`}
style={{ marginRight: 10 }}
>
trial stdout
</a>
<a target="_blank" href={logStr.split(',')[1]}>hdfsLog</a>
</Row>
<Row>
<Button
disabled={isdisLogbutton}
type="primary"
className="tableButton"
onClick={showLogModal.bind(this, id)}
>
View
</Button>
</Row>
</Row>
:
<PaiTrialChild
logString={logStr}
id={id}
showLogModal={showLogModal}
isdisLogbtn={isdisLogbutton}
/>
}
</div>
</div>
);
}
}
export default PaitrialLog;
import * as React from 'react';
import LogPathChild from './LogPathChild';
interface TrialLogProps {
logStr: string;
id: string;
}
class TrialLog extends React.Component<TrialLogProps, {}> {
constructor(props: TrialLogProps) {
super(props);
}
render() {
const { logStr } = this.props;
return (
<div>
<LogPathChild
eachLogpath={logStr}
logName="LogPath:"
/>
</div>
);
}
}
export default TrialLog;
import * as React from 'react'; import * as React from 'react';
import { import {
Row, Row, Col, Popover, Button, message
Col,
Popover,
Button,
message
} from 'antd'; } from 'antd';
import axios from 'axios'; import axios from 'axios';
import { MANAGER_IP, CONTROLTYPE } from '../../static/const'; import { MANAGER_IP, CONTROLTYPE } from '../../static/const';
...@@ -92,7 +88,8 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -92,7 +88,8 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
if (error.response.data.error) { if (error.response.data.error) {
message.error(error.response.data.error); message.error(error.response.data.error);
} else { } else {
message.error(`Update ${CONTROLTYPE[1].toLocaleLowerCase()} failed`); message.error(
`Update ${CONTROLTYPE[1].toLocaleLowerCase()} failed`);
} }
} }
}); });
...@@ -179,7 +176,6 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -179,7 +176,6 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
return ( return (
<Row className="progress" id="barBack"> <Row className="progress" id="barBack">
<Row className="basic lineBasic"> <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>
...@@ -198,10 +194,29 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -198,10 +194,29 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
<span /> <span />
} }
</div> </div>
</Row>
<ProgressBar
who="Duration"
percent={percent}
description={runDuration}
bgclass={status}
maxString={`MaxDuration: ${convertTime(trialProfile.maxDuration)}`}
/>
<ProgressBar
who="TrialNum"
percent={bar2Percent}
description={bar2.toString()}
bgclass={status}
maxString={`MaxTrialNumber: ${trialProfile.MaxTrialNum}`}
/>
<Row className="basic colorOfbasic mess">
<Col span={10}>
<p>best metric</p>
<div>{bestAccuracy.toFixed(6)}</div>
</Col> </Col>
<Col span={12}> <Col span={14}>
{/* modify concurrency */} {/* modify concurrency */}
<p>Concurrency</p> <p>concurrency</p>
<Row className="inputBox"> <Row className="inputBox">
<input <input
type="number" type="number"
...@@ -227,24 +242,6 @@ class Progressed extends React.Component<ProgressProps, ProgressState> { ...@@ -227,24 +242,6 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
</Row> </Row>
</Col> </Col>
</Row> </Row>
<ProgressBar
who="Duration"
percent={percent}
description={runDuration}
bgclass={status}
maxString={`MaxDuration: ${convertTime(trialProfile.maxDuration)}`}
/>
<ProgressBar
who="TrialNum"
percent={bar2Percent}
description={bar2.toString()}
bgclass={status}
maxString={`MaxTrialNumber: ${trialProfile.MaxTrialNum}`}
/>
<Row className="basic colorOfbasic mess">
<p>best metric</p>
<div>{bestAccuracy}</div>
</Row>
<Row className="mess"> <Row className="mess">
<Col span={8}> <Col span={8}>
<Row className="basic colorOfbasic"> <Row className="basic colorOfbasic">
......
import * as React from 'react'; import * as React from 'react';
import axios from 'axios';
import JSONTree from 'react-json-tree'; import JSONTree from 'react-json-tree';
import { Table } from 'antd'; import { Row, Modal, Input, Table, Tabs } from 'antd';
const TabPane = Tabs.TabPane;
const { TextArea } = Input;
import { DOWNLOAD_IP } from '../../static/const';
import { TableObj } from '../../static/interface'; import { TableObj } from '../../static/interface';
import { convertDuration } from '../../static/function'; import { convertDuration } from '../../static/function';
import PaiTrialLog from '../logPath/PaiTrialLog';
import TrialLog from '../logPath/TrialLog';
import '../../static/style/tableStatus.css'; import '../../static/style/tableStatus.css';
import LogPath from '../logPath/LogPath'; import '../../static/style/tableList.scss';
interface SuccessTableProps { interface SuccessTableProps {
tableSource: Array<TableObj>; tableSource: Array<TableObj>;
trainingPlatform: string;
} }
class SuccessTable extends React.Component<SuccessTableProps, {}> { interface SuccessTableState {
isShowLogModal: boolean;
logContent: string;
}
class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> {
public _isMounted = false;
constructor(props: SuccessTableProps) { constructor(props: SuccessTableProps) {
super(props); super(props);
this.state = {
isShowLogModal: false,
logContent: ''
};
}
showLogModalOverview = (id: string) => {
axios(`${DOWNLOAD_IP}/trial_${id}.log`, {
method: 'GET'
})
.then(res => {
if (res.status === 200) {
if (this._isMounted) {
this.setState(() => ({
logContent: res.data
}));
}
}
})
.catch(error => {
if (error.response.status === 500) {
if (this._isMounted) {
this.setState(() => ({
logContent: 'failed to get log message'
}));
}
}
});
if (this._isMounted) {
this.setState({
isShowLogModal: true
});
}
}
hideLogModalOverview = () => {
if (this._isMounted) {
this.setState({
isShowLogModal: false,
logContent: '' // close modal, delete data
});
}
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
} }
render() { render() {
const { tableSource } = this.props; const { tableSource, trainingPlatform } = this.props;
const { isShowLogModal, logContent } = this.state;
let bgColor = ''; let bgColor = '';
const columns = [{ const columns = [{
...@@ -114,6 +180,9 @@ class SuccessTable extends React.Component<SuccessTableProps, {}> { ...@@ -114,6 +180,9 @@ class SuccessTable extends React.Component<SuccessTableProps, {}> {
'This trial\'s logPath are not available.'; 'This trial\'s logPath are not available.';
return ( return (
<pre id="description" className="hyperpar"> <pre id="description" className="hyperpar">
<Row className="openRowContent">
<Tabs tabPosition="left" className="card">
<TabPane tab="Parameters" key="1">
{ {
isHasParameters isHasParameters
? ?
...@@ -129,7 +198,22 @@ class SuccessTable extends React.Component<SuccessTableProps, {}> { ...@@ -129,7 +198,22 @@ class SuccessTable extends React.Component<SuccessTableProps, {}> {
<span className="error">'This trial's parameters are not available.'</span> <span className="error">'This trial's parameters are not available.'</span>
</div> </div>
} }
<LogPath logStr={logPathRow}/> </TabPane>
<TabPane tab="Log" key="2">
{
trainingPlatform === 'pai' || trainingPlatform === 'kubeflow'
?
<PaiTrialLog
logStr={logPathRow}
id={record.id}
showLogModal={this.showLogModalOverview}
/>
:
<TrialLog logStr={logPathRow} id={record.id} />
}
</TabPane>
</Tabs>
</Row>
</pre> </pre>
); );
}; };
...@@ -142,6 +226,23 @@ class SuccessTable extends React.Component<SuccessTableProps, {}> { ...@@ -142,6 +226,23 @@ class SuccessTable extends React.Component<SuccessTableProps, {}> {
className="commonTableStyle" className="commonTableStyle"
pagination={false} pagination={false}
/> />
{/* trial log modal */}
<Modal
title="trial log"
visible={isShowLogModal}
onCancel={this.hideLogModalOverview}
footer={null}
destroyOnClose={true}
width="80%"
>
<div id="trialLogContent" style={{ height: window.innerHeight * 0.6 }}>
<TextArea
value={logContent}
disabled={true}
className="logcontent"
/>
</div>
</Modal>
</div> </div>
); );
} }
......
...@@ -2,18 +2,24 @@ import * as React from 'react'; ...@@ -2,18 +2,24 @@ import * as React from 'react';
import axios from 'axios'; import axios from 'axios';
import JSONTree from 'react-json-tree'; import JSONTree from 'react-json-tree';
import ReactEcharts from 'echarts-for-react'; import ReactEcharts from 'echarts-for-react';
import { Row, Table, Button, Popconfirm, Modal, message, Checkbox } from 'antd'; import {
Row, Input, Table, Tabs, Button, Popconfirm, Modal, message, Checkbox
} from 'antd';
const { TextArea } = Input;
const TabPane = Tabs.TabPane;
const CheckboxGroup = Checkbox.Group; const CheckboxGroup = Checkbox.Group;
import { MANAGER_IP, trialJobStatus, COLUMN, COLUMN_INDEX } from '../../static/const'; import { MANAGER_IP, DOWNLOAD_IP, trialJobStatus, COLUMN, COLUMN_INDEX } from '../../static/const';
import { convertDuration } from '../../static/function'; import { convertDuration } from '../../static/function';
import { TableObjFianl, TrialJob } from '../../static/interface'; import { TableObjFianl, TrialJob } from '../../static/interface';
import LogPath from '../logPath/LogPath'; import PaiTrialLog from '../logPath/PaiTrialLog';
import TrialLog from '../logPath/TrialLog';
import '../../static/style/search.scss'; import '../../static/style/search.scss';
require('../../static/style/tableStatus.css'); require('../../static/style/tableStatus.css');
require('../../static/style/logPath.scss'); require('../../static/style/logPath.scss');
require('../../static/style/search.scss'); require('../../static/style/search.scss');
require('../../static/style/table.scss'); require('../../static/style/table.scss');
require('../../static/style/button.scss'); require('../../static/style/button.scss');
require('../../static/style/tableList.scss');
const echarts = require('echarts/lib/echarts'); const echarts = require('echarts/lib/echarts');
require('echarts/lib/chart/line'); require('echarts/lib/chart/line');
require('echarts/lib/component/tooltip'); require('echarts/lib/component/tooltip');
...@@ -28,6 +34,7 @@ interface TableListProps { ...@@ -28,6 +34,7 @@ interface TableListProps {
searchResult: Array<TableObjFianl>; searchResult: Array<TableObjFianl>;
updateList: Function; updateList: Function;
isHasSearch: boolean; isHasSearch: boolean;
platform: string;
} }
interface TableListState { interface TableListState {
...@@ -36,6 +43,8 @@ interface TableListState { ...@@ -36,6 +43,8 @@ interface TableListState {
isObjFinal: boolean; isObjFinal: boolean;
isShowColumn: boolean; isShowColumn: boolean;
columnSelected: Array<string>; // user select columnKeys columnSelected: Array<string>; // user select columnKeys
logModal: boolean;
logMessage: string;
} }
interface ColumnIndex { interface ColumnIndex {
...@@ -46,6 +55,9 @@ interface ColumnIndex { ...@@ -46,6 +55,9 @@ interface ColumnIndex {
class TableList extends React.Component<TableListProps, TableListState> { class TableList extends React.Component<TableListProps, TableListState> {
public _isMounted = false; public _isMounted = false;
public intervalTrialLog = 10;
public _trialId: string;
constructor(props: TableListProps) { constructor(props: TableListProps) {
super(props); super(props);
...@@ -54,7 +66,9 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -54,7 +66,9 @@ class TableList extends React.Component<TableListProps, TableListState> {
modalVisible: false, modalVisible: false,
isObjFinal: false, isObjFinal: false,
isShowColumn: false, isShowColumn: false,
logModal: false,
columnSelected: COLUMN, columnSelected: COLUMN,
logMessage: ''
}; };
} }
...@@ -92,6 +106,51 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -92,6 +106,51 @@ class TableList extends React.Component<TableListProps, TableListState> {
} }
} }
updateTrialLogMessage = (id: string) => {
this._trialId = id;
axios(`${DOWNLOAD_IP}/trial_${this._trialId}.log`, {
method: 'GET'
})
.then(res => {
if (res.status === 200) {
if (this._isMounted) {
this.setState(() => ({
logMessage: res.data
}));
}
}
})
.catch(error => {
if (error.response.status === 500) {
if (this._isMounted) {
this.setState(() => ({
logMessage: 'failed to get log message'
}));
}
}
});
}
showLogModal = (id: string) => {
this.updateTrialLogMessage(id);
this.intervalTrialLog = window.setInterval(this.updateTrialLogMessage.bind(this, this._trialId), 10000);
if (this._isMounted) {
this.setState({
logModal: true
});
}
}
hideLogModal = () => {
window.clearInterval(this.intervalTrialLog);
if (this._isMounted) {
this.setState({
logModal: false,
logMessage: ''
});
}
}
hideShowColumnModal = () => { hideShowColumnModal = () => {
if (this._isMounted) { if (this._isMounted) {
this.setState({ this.setState({
...@@ -235,11 +294,14 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -235,11 +294,14 @@ class TableList extends React.Component<TableListProps, TableListState> {
render() { render() {
const { entries, tableSource, searchResult, isHasSearch } = this.props; const { entries, tableSource, searchResult, isHasSearch, platform } = this.props;
const { intermediateOption, modalVisible, isShowColumn, columnSelected, const { intermediateOption, modalVisible, isShowColumn, columnSelected,
logMessage, logModal
} = this.state; } = this.state;
let showTitle = COLUMN; let showTitle = COLUMN;
let bgColor = '';
const trialJob: Array<TrialJob> = [];
const showColumn: Array<object> = [];
if (tableSource.length >= 1) { if (tableSource.length >= 1) {
const temp = tableSource[0].acc; const temp = tableSource[0].acc;
if (temp !== undefined && typeof temp === 'object') { if (temp !== undefined && typeof temp === 'object') {
...@@ -256,16 +318,12 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -256,16 +318,12 @@ class TableList extends React.Component<TableListProps, TableListState> {
} }
} }
} }
let bgColor = '';
const trialJob: Array<TrialJob> = [];
trialJobStatus.map(item => { trialJobStatus.map(item => {
trialJob.push({ trialJob.push({
text: item, text: item,
value: item value: item
}); });
}); });
const showColumn: Array<object> = [];
Object.keys(columnSelected).map(key => { Object.keys(columnSelected).map(key => {
const item = columnSelected[key]; const item = columnSelected[key];
switch (item) { switch (item) {
...@@ -473,12 +531,20 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -473,12 +531,20 @@ class TableList extends React.Component<TableListProps, TableListState> {
record.description.logPath record.description.logPath
: :
'This trial\'s logPath are not available.'; 'This trial\'s logPath are not available.';
const isdisLogbutton = record.status === 'WAITING'
?
true
:
false;
return ( return (
<pre id="allList" className="hyperpar"> <pre id="allList" className="hyperpar">
<Row className="openRowContent">
<Tabs tabPosition="left" className="card">
<TabPane tab="Parameters" key="1">
{ {
isHasParameters isHasParameters
? ?
< JSONTree <JSONTree
hideRoot={true} hideRoot={true}
shouldExpandNode={() => true} // default expandNode shouldExpandNode={() => true} // default expandNode
getItemString={() => (<span />)} // remove the {} items getItemString={() => (<span />)} // remove the {} items
...@@ -490,7 +556,24 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -490,7 +556,24 @@ class TableList extends React.Component<TableListProps, TableListState> {
<span className="error">'This trial's parameters are not available.'</span> <span className="error">'This trial's parameters are not available.'</span>
</div> </div>
} }
<LogPath logStr={logPathRow} /> </TabPane>
<TabPane tab="Log" key="2">
{
platform === 'pai' || platform === 'kubeflow'
?
<PaiTrialLog
logStr={logPathRow}
id={record.id}
showLogModal={this.showLogModal}
trialStatus={record.status}
isdisLogbutton={isdisLogbutton}
/>
:
<TrialLog logStr={logPathRow} id={record.id} />
}
</TabPane>
</Tabs>
</Row>
</pre> </pre>
); );
}; };
...@@ -523,6 +606,24 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -523,6 +606,24 @@ class TableList extends React.Component<TableListProps, TableListState> {
theme="my_theme" theme="my_theme"
/> />
</Modal> </Modal>
{/* trial log modal */}
<Modal
title="trial log"
visible={logModal}
onCancel={this.hideLogModal}
footer={null}
destroyOnClose={true}
width="80%"
>
<div id="trialLogContent" style={{ height: window.innerHeight * 0.6 }}>
<TextArea
value={logMessage}
disabled={true}
className="logcontent"
/>
</div>
</Modal>
</div> </div>
{/* Add Column Modal */} {/* Add Column Modal */}
<Modal <Modal
...@@ -540,6 +641,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -540,6 +641,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
className="titleColumn" className="titleColumn"
/> />
</Modal> </Modal>
</Row> </Row>
); );
} }
......
#barBack{ #barBack{
/* status: 'INITIALIZED' | 'RUNNING' | 'ERROR' | 'STOPPING' | 'STOPPED' | 'DONE' */ /* status: 'INITIALIZED' | 'RUNNING' | 'ERROR' | 'STOPPING' | 'STOPPED' | 'DONE' */
.RUNNING, .STOPPING, .INITIALIZED{ /* status: 'TUNER_NO_MORE_TRIAL' | 'NO_MORE_TRIAL' */
.RUNNING, .STOPPING, .INITIALIZED, .NO_MORE_TRIAL, .TUNER_NO_MORE_TRIAL{
/* specific status color */ /* specific status color */
color: #0071bc; color: #0071bc;
.ant-progress-bg { .ant-progress-bg {
......
...@@ -73,6 +73,7 @@ ...@@ -73,6 +73,7 @@
*/ */
.inputBox{ .inputBox{
height: 26px; height: 26px;
margin-top: -3px;
.concurrencyInput{ .concurrencyInput{
width: 25%; width: 25%;
height: 26px; height: 26px;
......
$color: #0071bc;
.openRowContent{
.ant-tabs-vertical.ant-tabs-left .ant-tabs-bar .ant-tabs-tab{
text-align: left !important;
}
}
.openRowContent{
.ant-tabs-nav .ant-tabs-tab:hover{
color: $color;
}
}
.openRowContent{
margin-top: 15px;
.card{
.ant-tabs-vertical .ant-tabs-bar .ant-tabs-tab{
margin: 0;
padding: 8px 12px;
}
.ant-tabs-nav .ant-tabs-tab-active{
color: $color;
font-weight: 500;
background: #dedede;
border-left: 3px solid ;
}
.ant-tabs-tabpane{
background: #f2f2f2;
padding: 10px 20px;
}
}
}
.trialLog{
white-space: normal;
color: #212121;
}
#trialLogContent{
.ant-input-disabled{
color: #212121;
background-color: #fff;
cursor: pointer;
border: none;
}
.logcontent{
height: 100%;
}
}
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