"vscode:/vscode.git/clone" did not exist on "19f058ec9e9149e9c04bec5e598c7ef6724f5042"
Unverified Commit f0a2d396 authored by SparkSnail's avatar SparkSnail Committed by GitHub
Browse files

Merge pull request #150 from Microsoft/master

merge master
parents 080ae00d 0330333c
...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json ...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json
#choice: true, false #choice: true, false
useAnnotation: false useAnnotation: false
tuner: tuner:
#choice: TPE, Random, Anneal, Evolution, BatchTuner #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner
#SMAC (SMAC should be installed through nnictl) #SMAC (SMAC should be installed through nnictl)
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
......
...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json ...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json
#choice: true, false #choice: true, false
useAnnotation: false useAnnotation: false
tuner: tuner:
#choice: TPE, Random, Anneal, Evolution, BatchTuner #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner
#SMAC (SMAC should be installed through nnictl) #SMAC (SMAC should be installed through nnictl)
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
......
...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json ...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json
#choice: true, false #choice: true, false
useAnnotation: false useAnnotation: false
tuner: tuner:
#choice: TPE, Random, Anneal, Evolution, BatchTuner #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner
#SMAC (SMAC should be installed through nnictl) #SMAC (SMAC should be installed through nnictl)
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
......
...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json ...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json
#choice: true, false #choice: true, false
useAnnotation: false useAnnotation: false
tuner: tuner:
#choice: TPE, Random, Anneal, Evolution #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
#choice: maximize, minimize #choice: maximize, minimize
......
...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json ...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json
#choice: true, false #choice: true, false
useAnnotation: false useAnnotation: false
tuner: tuner:
#choice: TPE, Random, Anneal, Evolution #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
#choice: maximize, minimize #choice: maximize, minimize
......
...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json ...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json
#choice: true, false #choice: true, false
useAnnotation: false useAnnotation: false
tuner: tuner:
#choice: TPE, Random, Anneal, Evolution, BatchTuner #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner
#SMAC (SMAC should be installed through nnictl) #SMAC (SMAC should be installed through nnictl)
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
......
...@@ -5,7 +5,7 @@ The Network Morphism is a build-in Tuner using network morphism techniques to se ...@@ -5,7 +5,7 @@ The Network Morphism is a build-in Tuner using network morphism techniques to se
### 1. Training framework support ### 1. Training framework support
The network morphism now is framework-based, and we have not implemented the framework-free methods. The training frameworks which we have supported yet are Pytorch and Keras. If you get familiar with the intermediate JSON format, you can build your own model in your own training framework. In the future, we will change to intermediate format from JSON to ONNX in order to get a [standard intermediate representation spec](https://github.com/onnx/onnx/blob/master/docs/IR.md). The network morphism now is framework-based, and we have not implemented the framework-free methods. The training frameworks which we have supported yet are PyTorch and Keras. If you get familiar with the intermediate JSON format, you can build your own model in your own training framework. In the future, we will change to intermediate format from JSON to ONNX in order to get a [standard intermediate representation spec](https://github.com/onnx/onnx/blob/master/docs/IR.md).
### 2. Install the requirements ### 2. Install the requirements
......
...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json ...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json
#choice: true, false #choice: true, false
useAnnotation: false useAnnotation: false
tuner: tuner:
#choice: TPE, Random, Anneal, Evolution #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
#choice: maximize, minimize #choice: maximize, minimize
......
...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json ...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json
#choice: true, false #choice: true, false
useAnnotation: false useAnnotation: false
tuner: tuner:
#choice: TPE, Random, Anneal, Evolution, BatchTuner #choice: TPE, Random, Anneal, Evolution, BatchTuner,MetisTuner
#SMAC (SMAC should be installed through nnictl) #SMAC (SMAC should be installed through nnictl)
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
......
...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json ...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json
#choice: true, false #choice: true, false
useAnnotation: false useAnnotation: false
tuner: tuner:
#choice: TPE, Random, Anneal, Evolution #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
#choice: maximize, minimize #choice: maximize, minimize
......
...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json ...@@ -9,7 +9,7 @@ searchSpacePath: search_space.json
#choice: true, false #choice: true, false
useAnnotation: false useAnnotation: false
tuner: tuner:
#choice: TPE, Random, Anneal, Evolution, BatchTuner #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner
#SMAC (SMAC should be installed through nnictl) #SMAC (SMAC should be installed through nnictl)
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
......
...@@ -103,7 +103,7 @@ class LocalTrainingService implements TrainingService { ...@@ -103,7 +103,7 @@ class LocalTrainingService implements TrainingService {
protected log: Logger; protected log: Logger;
protected localTrailConfig?: TrialConfig; protected localTrailConfig?: TrialConfig;
private isMultiPhase: boolean = false; private isMultiPhase: boolean = false;
private streams: Array<ts.Stream>; protected jobStreamMap: Map<string, ts.Stream>;
constructor() { constructor() {
this.eventEmitter = new EventEmitter(); this.eventEmitter = new EventEmitter();
...@@ -113,7 +113,7 @@ class LocalTrainingService implements TrainingService { ...@@ -113,7 +113,7 @@ class LocalTrainingService implements TrainingService {
this.stopping = false; this.stopping = false;
this.log = getLogger(); this.log = getLogger();
this.trialSequenceId = -1; this.trialSequenceId = -1;
this.streams = new Array<ts.Stream>(); this.jobStreamMap = new Map<string, ts.Stream>();
this.log.info('Construct local machine training service.'); this.log.info('Construct local machine training service.');
} }
...@@ -307,14 +307,24 @@ class LocalTrainingService implements TrainingService { ...@@ -307,14 +307,24 @@ class LocalTrainingService implements TrainingService {
public cleanUp(): Promise<void> { public cleanUp(): Promise<void> {
this.log.info('Stopping local machine training service...'); this.log.info('Stopping local machine training service...');
this.stopping = true; this.stopping = true;
for (const stream of this.streams) { for (const stream of this.jobStreamMap.values()) {
stream.destroy(); stream.destroy();
} }
return Promise.resolve(); return Promise.resolve();
} }
protected onTrialJobStatusChanged(trialJob: TrialJobDetail, oldStatus: TrialJobStatus): void { protected onTrialJobStatusChanged(trialJob: TrialJobDetail, oldStatus: TrialJobStatus): void {
//abstract //if job is not running, destory job stream
if(['SUCCEEDED', 'FAILED', 'USER_CANCELED', 'SYS_CANCELED', 'EARLY_STOPPED'].includes(trialJob.status)) {
if(this.jobStreamMap.has(trialJob.id)) {
const stream = this.jobStreamMap.get(trialJob.id);
if(!stream) {
throw new Error(`Could not find stream in trial ${trialJob.id}`);
}
stream.destroy();
this.jobStreamMap.delete(trialJob.id);
}
}
} }
protected getEnvironmentVariables(trialJobDetail: TrialJobDetail, _: {}): { key: string; value: string }[] { protected getEnvironmentVariables(trialJobDetail: TrialJobDetail, _: {}): { key: string; value: string }[] {
...@@ -396,7 +406,8 @@ class LocalTrainingService implements TrainingService { ...@@ -396,7 +406,8 @@ class LocalTrainingService implements TrainingService {
buffer = remain; buffer = remain;
} }
}); });
this.streams.push(stream);
this.jobStreamMap.set(trialJobDetail.id, stream);
} }
private async runHostJob(form: HostJobApplicationForm): Promise<TrialJobDetail> { private async runHostJob(form: HostJobApplicationForm): Promise<TrialJobDetail> {
......
...@@ -78,6 +78,7 @@ class LocalTrainingServiceForGPU extends LocalTrainingService { ...@@ -78,6 +78,7 @@ class LocalTrainingServiceForGPU extends LocalTrainingService {
} }
protected onTrialJobStatusChanged(trialJob: LocalTrialJobDetailForGPU, oldStatus: TrialJobStatus): void { protected onTrialJobStatusChanged(trialJob: LocalTrialJobDetailForGPU, oldStatus: TrialJobStatus): void {
super.onTrialJobStatusChanged(trialJob, oldStatus);
if (trialJob.gpuIndices !== undefined && trialJob.gpuIndices.length !== 0 && this.gpuScheduler !== undefined) { if (trialJob.gpuIndices !== undefined && trialJob.gpuIndices.length !== 0 && this.gpuScheduler !== undefined) {
if (oldStatus === 'RUNNING' && trialJob.status !== 'RUNNING') { if (oldStatus === 'RUNNING' && trialJob.status !== 'RUNNING') {
for (const index of trialJob.gpuIndices) { for (const index of trialJob.gpuIndices) {
......
...@@ -33,6 +33,8 @@ interface OverviewState { ...@@ -33,6 +33,8 @@ interface OverviewState {
isTop10: boolean; isTop10: boolean;
titleMaxbgcolor: string; titleMaxbgcolor: string;
titleMinbgcolor?: string; titleMinbgcolor?: string;
// trial stdout is content(false) or link(true)
isLogCollection: boolean;
} }
class Overview extends React.Component<{}, OverviewState> { class Overview extends React.Component<{}, OverviewState> {
...@@ -76,7 +78,8 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -76,7 +78,8 @@ class Overview extends React.Component<{}, OverviewState> {
totalCurrentTrial: 0 totalCurrentTrial: 0
}, },
isTop10: true, isTop10: true,
titleMaxbgcolor: '#999' titleMaxbgcolor: '#999',
isLogCollection: false
}; };
} }
...@@ -95,6 +98,12 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -95,6 +98,12 @@ class Overview extends React.Component<{}, OverviewState> {
const endTimenum = sessionData.endTime; const endTimenum = sessionData.endTime;
const assessor = sessionData.params.assessor; const assessor = sessionData.params.assessor;
const advisor = sessionData.params.advisor; const advisor = sessionData.params.advisor;
// default logCollection is true
const logCollection = res.data.params.logCollection;
let expLogCollection: boolean = false;
if (logCollection !== undefined && logCollection !== 'none') {
expLogCollection = true;
}
trialPro.push({ trialPro.push({
id: sessionData.id, id: sessionData.id,
author: sessionData.params.authorName, author: sessionData.params.authorName,
...@@ -111,7 +120,8 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -111,7 +120,8 @@ class Overview extends React.Component<{}, OverviewState> {
tuner: sessionData.params.tuner, tuner: sessionData.params.tuner,
assessor: assessor ? assessor : undefined, assessor: assessor ? assessor : undefined,
advisor: advisor ? advisor : undefined, advisor: advisor ? advisor : undefined,
clusterMetaData: clusterMetaData ? clusterMetaData : undefined clusterMetaData: clusterMetaData ? clusterMetaData : undefined,
logCollection: logCollection
}); });
// search space format loguniform max and min // search space format loguniform max and min
const temp = sessionData.params.searchSpace; const temp = sessionData.params.searchSpace;
...@@ -134,7 +144,8 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -134,7 +144,8 @@ class Overview extends React.Component<{}, OverviewState> {
if (this._isMounted) { if (this._isMounted) {
this.setState({ this.setState({
trialProfile: trialPro[0], trialProfile: trialPro[0],
searchSpace: searchSpace searchSpace: searchSpace,
isLogCollection: expLogCollection
}); });
} }
} }
...@@ -379,7 +390,7 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -379,7 +390,7 @@ class Overview extends React.Component<{}, OverviewState> {
const { const {
trialProfile, searchSpace, tableData, accuracyData, trialProfile, searchSpace, tableData, accuracyData,
accNodata, status, errorStr, trialNumber, bestAccuracy, accNodata, status, errorStr, trialNumber, bestAccuracy,
titleMaxbgcolor, titleMinbgcolor titleMaxbgcolor, titleMinbgcolor, isLogCollection
} = this.state; } = this.state;
return ( return (
...@@ -410,7 +421,7 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -410,7 +421,7 @@ class Overview extends React.Component<{}, OverviewState> {
</Row> </Row>
</Col> </Col>
<Col span={8} className="overviewBoder"> <Col span={8} className="overviewBoder">
<Title1 text="Trial Profile" icon="4.png" /> <Title1 text="Profile" icon="4.png" />
<Row className="experiment"> <Row className="experiment">
{/* the scroll bar all the trial profile in the searchSpace div*/} {/* the scroll bar all the trial profile in the searchSpace div*/}
<div className="experiment searchSpace"> <div className="experiment searchSpace">
...@@ -453,6 +464,7 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -453,6 +464,7 @@ class Overview extends React.Component<{}, OverviewState> {
<Col span={16} id="succeTable"> <Col span={16} id="succeTable">
<SuccessTable <SuccessTable
tableSource={tableData} tableSource={tableData}
logCollection={isLogCollection}
trainingPlatform={trialProfile.trainingServicePlatform} trainingPlatform={trialProfile.trainingServicePlatform}
/> />
</Col> </Col>
......
...@@ -21,8 +21,9 @@ interface TrialDetailState { ...@@ -21,8 +21,9 @@ interface TrialDetailState {
searchResultSource: Array<TableObj>; searchResultSource: Array<TableObj>;
isHasSearch: boolean; isHasSearch: boolean;
experimentStatus: string; experimentStatus: string;
entriesTable: number;
experimentPlatform: string; experimentPlatform: string;
experimentLogCollection: boolean;
entriesTable: number;
searchSpace: string; searchSpace: string;
defaultMetric?: Array<number>; defaultMetric?: Array<number>;
} }
...@@ -49,7 +50,6 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -49,7 +50,6 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
); );
private titleOfIntermediate = ( private titleOfIntermediate = (
// <Title1 text="Intermediate Result" icon="intermediate.png" />
<div className="panelTitle"> <div className="panelTitle">
<Icon type="line-chart" /> <Icon type="line-chart" />
<span>Intermediate Result</span> <span>Intermediate Result</span>
...@@ -65,9 +65,10 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -65,9 +65,10 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
tableListSource: [], tableListSource: [],
searchResultSource: [], searchResultSource: [],
experimentStatus: '', experimentStatus: '',
experimentPlatform: '',
experimentLogCollection: false,
entriesTable: 20, entriesTable: 20,
isHasSearch: false, isHasSearch: false,
experimentPlatform: '',
searchSpace: '', searchSpace: '',
defaultMetric: [0, 1] defaultMetric: [0, 1]
}; };
...@@ -279,6 +280,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -279,6 +280,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
alert('TableList component was not properly initialized.'); alert('TableList component was not properly initialized.');
} }
// get and set logCollection val
checkExperimentPlatform = () => { checkExperimentPlatform = () => {
axios(`${MANAGER_IP}/experiment`, { axios(`${MANAGER_IP}/experiment`, {
method: 'GET' method: 'GET'
...@@ -290,10 +292,17 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -290,10 +292,17 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
res.data.params.trainingServicePlatform res.data.params.trainingServicePlatform
: :
''; '';
// default logCollection is true
const logCollection = res.data.params.logCollection;
let expLogCollection: boolean = false;
if (logCollection !== undefined && logCollection !== 'none') {
expLogCollection = true;
}
if (this._isMounted) { if (this._isMounted) {
this.setState({ this.setState({
experimentPlatform: trainingPlatform, experimentPlatform: trainingPlatform,
searchSpace: res.data.params.searchSpace searchSpace: res.data.params.searchSpace,
experimentLogCollection: expLogCollection
}); });
} }
} }
...@@ -318,7 +327,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -318,7 +327,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
const { const {
tableListSource, searchResultSource, isHasSearch, tableListSource, searchResultSource, isHasSearch,
entriesTable, experimentPlatform, searchSpace, entriesTable, experimentPlatform, searchSpace,
defaultMetric defaultMetric, experimentLogCollection
} = this.state; } = this.state;
const source = isHasSearch ? searchResultSource : tableListSource; const source = isHasSearch ? searchResultSource : tableListSource;
return ( return (
...@@ -392,8 +401,9 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -392,8 +401,9 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
<TableList <TableList
entries={entriesTable} entries={entriesTable}
tableSource={source} tableSource={source}
updateList={this.getDetailSource}
platform={experimentPlatform} platform={experimentPlatform}
updateList={this.getDetailSource}
logCollection={experimentLogCollection}
ref={(tabList) => this.tableList = tabList} ref={(tabList) => this.tableList = tabList}
/> />
</div> </div>
......
import * as React from 'react'; import * as React from 'react';
import axios from 'axios'; import { Table } from 'antd';
import { Modal, Input, Table } from 'antd';
const { TextArea } = Input;
import OpenRow from '../public-child/OpenRow'; import OpenRow from '../public-child/OpenRow';
import DefaultMetric from '../public-child/DefaultMetrc'; import DefaultMetric from '../public-child/DefaultMetrc';
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 '../../static/style/tableStatus.css'; import '../../static/style/tableStatus.css';
...@@ -13,72 +10,25 @@ import '../../static/style/tableList.scss'; ...@@ -13,72 +10,25 @@ import '../../static/style/tableList.scss';
interface SuccessTableProps { interface SuccessTableProps {
tableSource: Array<TableObj>; tableSource: Array<TableObj>;
trainingPlatform: string; trainingPlatform: string;
logCollection: boolean;
} }
interface SuccessTableState { class SuccessTable extends React.Component<SuccessTableProps, {}> {
isShowLogModal: boolean;
logContent: string;
}
class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> {
public _isMounted = false; 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
});
}
} }
openRow = (record: TableObj) => { openRow = (record: TableObj) => {
const { trainingPlatform } = this.props; const { trainingPlatform, logCollection } = this.props;
return ( return (
<OpenRow <OpenRow
showLogModalOverview={this.showLogModalOverview}
trainingPlatform={trainingPlatform} trainingPlatform={trainingPlatform}
record={record} record={record}
logCollection={logCollection}
/> />
); );
} }
...@@ -93,7 +43,6 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> ...@@ -93,7 +43,6 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
render() { render() {
const { tableSource } = this.props; const { tableSource } = this.props;
const { isShowLogModal, logContent } = this.state;
let bgColor = ''; let bgColor = '';
const columns = [{ const columns = [{
...@@ -168,25 +117,9 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> ...@@ -168,25 +117,9 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
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 >
); );
} }
} }
export default SuccessTable; export default SuccessTable;
...@@ -22,6 +22,7 @@ class TrialInfo extends React.Component<TrialInfoProps, {}> { ...@@ -22,6 +22,7 @@ class TrialInfo extends React.Component<TrialInfoProps, {}> {
trialConcurrency: tiralProInfo.runConcurren, trialConcurrency: tiralProInfo.runConcurren,
tuner: tiralProInfo.tuner, tuner: tiralProInfo.tuner,
assessor: tiralProInfo.assessor ? tiralProInfo.assessor : undefined, assessor: tiralProInfo.assessor ? tiralProInfo.assessor : undefined,
logCollection: tiralProInfo.logCollection ? tiralProInfo.logCollection : undefined,
advisor: tiralProInfo.advisor ? tiralProInfo.advisor : undefined, advisor: tiralProInfo.advisor ? tiralProInfo.advisor : undefined,
clusterMetaData: tiralProInfo.clusterMetaData ? tiralProInfo.clusterMetaData : undefined clusterMetaData: tiralProInfo.clusterMetaData ? tiralProInfo.clusterMetaData : undefined
}); });
......
...@@ -19,7 +19,7 @@ class DefaultMetric extends React.Component<DefaultMetricProps, {}> { ...@@ -19,7 +19,7 @@ class DefaultMetric extends React.Component<DefaultMetricProps, {}> {
accuracy = record.acc.default; accuracy = record.acc.default;
} }
let wei = 0; let wei = 0;
if (accuracy) { if (accuracy !== undefined) {
if (accuracy.toString().indexOf('.') !== -1) { if (accuracy.toString().indexOf('.') !== -1) {
wei = accuracy.toString().length - accuracy.toString().indexOf('.') - 1; wei = accuracy.toString().length - accuracy.toString().indexOf('.') - 1;
} }
...@@ -27,7 +27,7 @@ class DefaultMetric extends React.Component<DefaultMetricProps, {}> { ...@@ -27,7 +27,7 @@ class DefaultMetric extends React.Component<DefaultMetricProps, {}> {
return ( return (
<div> <div>
{ {
record.acc && record.acc.default record.acc !== undefined && record.acc.default !== undefined
? ?
wei > 6 wei > 6
? ?
......
import * as React from 'react';
import { TableObj } from '../../static/interface';
interface IntermediateValProps {
record: TableObj;
}
class IntermediateVal extends React.Component<IntermediateValProps, {}> {
constructor(props: IntermediateValProps) {
super(props);
}
render() {
const { record } = this.props;
const interArr = record.description.intermediate;
const status = record.status;
let lastVal;
let wei = 0;
if (interArr !== undefined) {
lastVal = interArr[interArr.length - 1];
}
let result: string = JSON.stringify(lastVal);
if (lastVal !== undefined) {
if (lastVal.toString().indexOf('.') !== -1) {
wei = lastVal.toString().length - lastVal.toString().indexOf('.') - 1;
if (wei > 6) {
result = `${lastVal.toFixed(6)}`;
}
if (status === 'SUCCEEDED') {
result = `${lastVal.toFixed(6)} (FINAL)`;
} else {
result = `${lastVal.toFixed(6)} (LATEST)`;
}
}
} else {
result = '--';
}
return (
<div>{result}</div>
);
}
}
export default IntermediateVal;
...@@ -17,19 +17,15 @@ class LogPathChild extends React.Component<LogpathChildProps, {}> { ...@@ -17,19 +17,15 @@ class LogPathChild extends React.Component<LogpathChildProps, {}> {
const isLink = /^http/gi.test(eachLogpath); const isLink = /^http/gi.test(eachLogpath);
return ( return (
<div> <div className="logpath">
<span className="logName">{logName}</span>
{ {
isLink isLink
? ?
<div className="logpath">
<span className="logName">{logName}</span>
<a className="logContent logHref" href={eachLogpath} target="_blank">{eachLogpath}</a> <a className="logContent logHref" href={eachLogpath} target="_blank">{eachLogpath}</a>
</div>
: :
<div className="logpath">
<span className="logName">{logName}</span>
<span className="logContent">{eachLogpath}</span> <span className="logContent">{eachLogpath}</span>
</div>
} }
</div> </div>
); );
......
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