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

Merge pull request #161 from Microsoft/master

merge master
parents aec49771 cbad7acb
......@@ -111,8 +111,8 @@ dev-install:
.PHONY: uninstall
uninstall:
-$(PIP_UNINSTALL) -y nni
-$(PIP_UNINSTALL) -y nnictl
-cd build && $(PIP_UNINSTALL) -y nni
-rm -rf build
-rm -rf $(NNI_PKG_FOLDER)
-rm -f $(BIN_FOLDER)/node
-rm -f $(BIN_FOLDER)/nnictl
......@@ -164,7 +164,18 @@ install-python-modules:
.PHONY: dev-install-python-modules
dev-install-python-modules:
#$(_INFO) Installing Python SDK $(_END)
sed -ie 's/$(NNI_VERSION_TEMPLATE)/$(NNI_VERSION_VALUE)/' setup.py && $(PIP_INSTALL) $(PIP_MODE) -e .
mkdir -p build
ln -sf ../src/sdk/pynni/nni build/nni
ln -sf ../tools/nni_annotation build/nni_annotation
ln -sf ../tools/nni_cmd build/nni_cmd
ln -sf ../tools/nni_trial_tool build/nni_trial_tool
ln -sf ../tools/nni_gpu_tool build/nni_gpu_tool
cp setup.py build/
cp README.md build/
sed -ie 's/$(NNI_VERSION_TEMPLATE)/$(NNI_VERSION_VALUE)/' build/setup.py
sed -ie 's/src\/sdk\/pynni\/nni/nni/g' build/setup.py
sed -ie 's/tools\///g' build/setup.py
cd build && $(PIP_INSTALL) $(PIP_MODE) -e .
.PHONY: install-node-modules
......
......@@ -529,7 +529,15 @@ class PAITrainingService implements TrainingService {
private async statusCheckingLoop(): Promise<void> {
while (!this.stopping) {
await this.updatePaiToken();
try{
await this.updatePaiToken();
}catch(error){
this.log.error(`${error}`);
//only throw error when initlize paiToken first time
if(!this.paiToken) {
throw new Error(error);
}
}
await this.paiJobCollector.retrieveTrialStatus(this.paiToken, this.paiClusterConfig);
const restServer: PAIJobRestServer = component.get(PAIJobRestServer);
if (restServer.getErrorMessage) {
......
......@@ -347,7 +347,7 @@ class HyperoptTuner(Tuner):
for key in vals:
try:
parameter[key] = vals[key][0].item()
except KeyError:
except (KeyError, IndexError):
parameter[key] = None
# remove '_index' from json2parameter and save params-id
......
src/webui/public/icon.png

29.9 KB | W: | H:

src/webui/public/icon.png

2.23 KB | W: | H:

src/webui/public/icon.png
src/webui/public/icon.png
src/webui/public/icon.png
src/webui/public/icon.png
  • 2-up
  • Swipe
  • Onion skin
import * as React from 'react';
import { Input, Button, message } from 'antd';
import axios from 'axios';
import { MANAGER_IP, CONTROLTYPE } from '../static/const';
const { TextArea } = Input;
import '../static/style/control.scss';
interface ExperimentParams {
authorName: string;
experimentName: string;
trialConcurrency: number;
maxExecDuration: number;
maxTrialNum: number;
searchSpace: string;
tuner: {
tunerCommand: string;
tunerCwd: string;
tunerCheckpointDirectory: string;
tunerGpuNum?: number;
};
assessor?: {
assessorCommand: string;
assessorCwd: string;
assessorCheckpointDirectory: string;
assessorGpuNum?: number;
};
}
interface Experiments {
params: ExperimentParams;
id: string;
startTime?: Date;
endTime?: Date;
revision: number;
execDuration: number;
}
interface TrialNumber {
maxExecDuration: number;
trialConcurrency: number;
}
interface ControlState {
addisabled: boolean;
addTrial: string;
updateSearch: string;
trialNum: TrialNumber;
trialMess: string;
updisabled: boolean;
upTrialdis: boolean;
experiment: Experiments;
}
class Control extends React.Component<{}, ControlState> {
public _isMounted = false;
constructor(props: {}) {
super(props);
this.state = {
addisabled: false,
upTrialdis: false,
addTrial: '',
updateSearch: '',
updisabled: false,
trialNum: {
maxExecDuration: 0,
trialConcurrency: 0
},
trialMess: '',
// experiment origin data obj
experiment: {
params: {
authorName: '',
experimentName: '',
trialConcurrency: 0,
maxExecDuration: 0,
maxTrialNum: 0,
searchSpace: '',
tuner: {
tunerCommand: '',
tunerCwd: '',
tunerCheckpointDirectory: '',
}
},
id: '',
revision: 0,
execDuration: 0,
}
};
}
updateTrialNumLoad = () => {
if (this._isMounted) {
this.setState({
upTrialdis: true,
});
}
}
updateTrialNumNormal = () => {
if (this._isMounted) {
this.setState({
upTrialdis: false,
});
}
}
addButtonLoad = () => {
if (this._isMounted) {
this.setState({
addisabled: true
});
}
}
addButtonNormal = () => {
if (this._isMounted) {
this.setState({
addisabled: false,
});
}
}
updateSearchLoad = () => {
if (this._isMounted) {
this.setState({
updisabled: true,
});
}
}
updateSearchNormal = () => {
if (this._isMounted) {
this.setState({
updisabled: false,
});
}
}
getTrialNum = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
if (this._isMounted) {
this.setState({
trialMess: event.target.value
});
}
}
getAddTrialval = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
if (this._isMounted) {
this.setState({
addTrial: event.target.value
});
}
}
updateSearchCon = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
if (this._isMounted) {
this.setState({
updateSearch: event.target.value
});
}
}
// get add trial example
getAddExample = () => {
axios(`${MANAGER_IP}/trial-jobs`, {
method: 'GET'
}).then(res => {
if (res.status === 200 && this._isMounted) {
if (res.data.length !== 0) {
const addTrialExam = JSON.parse(res.data[0].hyperParameters).parameters;
this.setState({
addTrial: JSON.stringify(addTrialExam, null, 4)
});
}
}
});
}
// get update search_space file and experiment
getUpdateExample = () => {
axios(`${MANAGER_IP}/experiment`, {
method: 'GET'
}).then(res => {
if (res.status === 200 && this._isMounted) {
const sespaceExam = JSON.parse(res.data.params.searchSpace);
const trialnum: Array<TrialNumber> = [];
trialnum.push({
maxExecDuration: res.data.params.maxExecDuration,
trialConcurrency: res.data.params.trialConcurrency
});
this.setState(() => ({
updateSearch: JSON.stringify(sespaceExam, null, 4),
trialNum: trialnum[0],
trialMess: JSON.stringify(trialnum[0], null, 4),
experiment: res.data
}));
}
});
}
// update trial number parameters
trialParameterMess = (exper: Experiments, str: string) => {
axios(`${MANAGER_IP}/experiment`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
data: exper,
params: {
update_type: str,
}
}).then(res => {
if (res.status === 200) {
message.success(`Update ${str.toLocaleLowerCase()} successfully`);
this.getUpdateExample();
} else {
message.error(`Update ${str.toLocaleLowerCase()} failed`);
}
});
}
updateTrialMess = () => {
const { trialMess } = this.state;
if (trialMess !== '' || trialMess !== null) {
this.updateTrialNumLoad();
const { experiment } = this.state;
const newExperiment = JSON.parse(JSON.stringify(experiment));
const trialObj = JSON.parse(trialMess);
const orimaxDuration = experiment.params.maxExecDuration;
const oriconTrial = experiment.params.trialConcurrency;
const flagMax = (trialObj.maxExecDuration !== orimaxDuration);
const flagCon = (trialObj.trialConcurrency !== oriconTrial);
if (flagCon && flagMax) {
newExperiment.params.trialConcurrency = trialObj.trialConcurrency;
newExperiment.params.maxExecDuration = trialObj.maxExecDuration;
this.trialParameterMess(newExperiment, CONTROLTYPE[1]);
this.trialParameterMess(newExperiment, CONTROLTYPE[2]);
} else if (flagCon) {
newExperiment.params.trialConcurrency = trialObj.trialConcurrency;
this.trialParameterMess(newExperiment, CONTROLTYPE[1]);
} else if (flagMax) {
newExperiment.params.maxExecDuration = trialObj.maxExecDuration;
this.trialParameterMess(newExperiment, CONTROLTYPE[2]);
} else {
message.info('you have not modified this file');
}
this.updateTrialNumNormal();
} else {
message.error('The text can not be empty');
}
}
userSubmitJob = () => {
const { addTrial } = this.state;
if (addTrial === null || addTrial === '') {
message.error('The text can not be empty');
} else {
this.addButtonLoad();
// new experiment obj
axios(`${MANAGER_IP}/trial-jobs`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
data: addTrial
}).then(res => {
if (res.status === 200) {
message.success('Submit successfully');
} else {
message.error('Submit failed');
}
this.addButtonNormal();
});
}
}
userUpdateSeaspace = () => {
this.updateSearchLoad();
const { updateSearch } = this.state;
if (updateSearch !== '' || updateSearch !== null) {
const { experiment } = this.state;
const newExperiment = JSON.parse(JSON.stringify(experiment));
newExperiment.params.searchSpace = updateSearch;
this.trialParameterMess(newExperiment, CONTROLTYPE[0]);
this.updateSearchNormal();
} else {
message.error('The text can not be empty');
}
}
componentDidMount() {
this._isMounted = true;
this.getAddExample();
this.getUpdateExample();
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
const { addTrial, addisabled, updateSearch, updisabled,
trialMess, upTrialdis
} = this.state;
return (
<div className="user">
<div className="userCon">
<div className="addtrial">
<div className="addtitle">
<span className="line">|</span>
Experiment parameters
</div>
<div className="userInput">
<TextArea
value={trialMess}
autosize={{ minRows: 9 }}
onChange={this.getTrialNum}
/>
</div>
<div className="addBtubox">
<Button
className="userSubmit"
type="primary"
onClick={this.updateTrialMess}
disabled={upTrialdis}
>
Update
</Button>
</div>
</div>
<div className="clear" />
<div className="addtrial">
<div className="addtitle">
<span className="line">|</span>
Add New Trail
</div>
<div className="userInput">
<TextArea
id="userInputJob"
value={addTrial}
autosize={{ minRows: 9 }}
onChange={this.getAddTrialval}
/>
</div>
<div className="addBtubox">
<Button
className="userSubmit"
type="primary"
onClick={this.userSubmitJob}
disabled={addisabled}
>
Submit
</Button>
</div>
</div>
{/* clear float */}
<div className="clear" />
<div className="searchbox">
<div className="updatesear">
<span className="line">|</span>
user update search_space file
</div>
<div className="userInput">
<TextArea
id="InputUpdate"
autosize={{ minRows: 20 }}
value={updateSearch}
onChange={this.updateSearchCon}
/>
</div>
<div className="addBtubox">
<Button
className="buttonbac"
type="primary"
onClick={this.userUpdateSeaspace}
disabled={updisabled}
>
Update
</Button>
</div>
</div>
</div>
</div>
);
}
}
export default Control;
\ No newline at end of file
......@@ -100,7 +100,7 @@ class Overview extends React.Component<{}, OverviewState> {
const endTimenum = sessionData.endTime;
const assessor = sessionData.params.assessor;
const advisor = sessionData.params.advisor;
// default logCollection is true
// default logCollection is true
const logCollection = res.data.params.logCollection;
let expLogCollection: boolean = false;
if (logCollection !== undefined && logCollection !== 'none') {
......@@ -315,6 +315,10 @@ class Overview extends React.Component<{}, OverviewState> {
indexarr.push(items.sequenceId);
});
const accOption = {
grid: {
left: 40,
right: 40
},
tooltip: {
trigger: 'item'
},
......@@ -324,7 +328,7 @@ class Overview extends React.Component<{}, OverviewState> {
data: indexarr
},
yAxis: {
name: 'Default Metric',
name: 'Default metric',
type: 'value',
scale: true,
data: accarr
......@@ -405,7 +409,7 @@ class Overview extends React.Component<{}, OverviewState> {
</Row>
<Row className="overMessage">
{/* status graph */}
<Col span={8} className="prograph overviewBoder">
<Col span={9} className="prograph overviewBoder">
<Title1 text="Status" icon="5.png" />
<Progressed
trialNumber={trialNumber}
......@@ -417,8 +421,8 @@ class Overview extends React.Component<{}, OverviewState> {
/>
</Col>
{/* experiment parameters search space tuner assessor... */}
<Col span={8} className="overviewBoder">
<Title1 text="Search Space" icon="10.png" />
<Col span={7} className="overviewBoder">
<Title1 text="Search space" icon="10.png" />
<Row className="experiment">
<SearchSpace searchSpace={searchSpace} />
</Row>
......@@ -428,7 +432,7 @@ class Overview extends React.Component<{}, OverviewState> {
<Row className="experiment">
{/* the scroll bar all the trial profile in the searchSpace div*/}
<div className="experiment searchSpace">
<TrialPro experiment={experimentAPI} />
<TrialPro experiment={experimentAPI} />
</div>
</Row>
</Col>
......@@ -436,7 +440,7 @@ class Overview extends React.Component<{}, OverviewState> {
<Row className="overGraph">
<Row className="top10bg">
<Col span={4} className="top10Title">
<Title1 text="Top10 Trials" icon="7.png" />
<Title1 text="Top10 trials" icon="7.png" />
</Col>
<Col
span={2}
......@@ -453,22 +457,24 @@ class Overview extends React.Component<{}, OverviewState> {
<Title1 text="Minimal" icon="min.png" bgcolor={titleMinbgcolor} />
</Col>
</Row>
<Col span={8} className="overviewBoder">
<Row className="accuracy">
<Accuracy
accuracyData={accuracyData}
accNodata={accNodata}
height={324}
<Row>
<Col span={8} className="overviewBoder">
<Row className="accuracy">
<Accuracy
accuracyData={accuracyData}
accNodata={accNodata}
height={324}
/>
</Row>
</Col>
<Col span={16} id="succeTable">
<SuccessTable
tableSource={tableData}
logCollection={isLogCollection}
trainingPlatform={trialProfile.trainingServicePlatform}
/>
</Row>
</Col>
<Col span={16} id="succeTable">
<SuccessTable
tableSource={tableData}
logCollection={isLogCollection}
trainingPlatform={trialProfile.trainingServicePlatform}
/>
</Col>
</Col>
</Row>
</Row>
</div>
);
......
......@@ -209,7 +209,7 @@ class SlideBar extends React.Component<{}, SliderState> {
</li>
<li className="tab">
<Link to={'/detail'} activeClassName="high">
Trials Detail
Trials detail
</Link>
</li>
</ul>
......
......@@ -38,21 +38,21 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
public tableList: TableList | null;
private titleOfacc = (
<Title1 text="Default Metric" icon="3.png" />
<Title1 text="Default metric" icon="3.png" />
);
private titleOfhyper = (
<Title1 text="Hyper Parameter" icon="1.png" />
<Title1 text="Hyper-parameter" icon="1.png" />
);
private titleOfDuration = (
<Title1 text="Trial Duration" icon="2.png" />
<Title1 text="Trial duration" icon="2.png" />
);
private titleOfIntermediate = (
<div className="panelTitle">
<Icon type="line-chart" />
<span>Intermediate Result</span>
<span>Intermediate result</span>
</div>
);
......@@ -360,10 +360,10 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
</Tabs>
</div>
{/* trial table list */}
<Title1 text="Trial Jobs" icon="6.png" />
<Title1 text="Trial jobs" icon="6.png" />
<Row className="allList">
<Col span={12}>
<span>show</span>
<span>Show</span>
<Select
className="entry"
onSelect={this.handleEntriesSelect}
......@@ -384,13 +384,13 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
className="tableButton editStyle"
onClick={this.tableList ? this.tableList.addColumn : this.test}
>
AddColumn
Add column
</Button>
</Col>
<Col span={12}>
<Input
type="text"
placeholder="search by Id, Trial No. or Status"
placeholder="Search by id, trial No. or status"
onChange={this.searchTrial}
style={{ width: 230, marginLeft: 6 }}
/>
......
......@@ -28,7 +28,7 @@ class Accuracy extends React.Component<AccuracyProps, {}> {
<ReactEcharts
option={accuracyData}
style={{
width: '100%',
width: '90%',
height: height,
margin: '0 auto',
}}
......
......@@ -27,11 +27,11 @@ class BasicInfo extends React.Component<BasicInfoProps, {}> {
<div>{trialProfile.id}</div>
</Col>
<Col span={8} className="padItem basic">
<p>Start Time</p>
<p>Start time</p>
<div className="nowrap">
{new Date(trialProfile.startTime).toLocaleString('en-US')}
</div>
<p>End Time</p>
<p>End time</p>
<div className="nowrap">
{
trialProfile.endTime
......@@ -43,13 +43,13 @@ class BasicInfo extends React.Component<BasicInfoProps, {}> {
</div>
</Col>
<Col span={8} className="padItem basic">
<p>Log Directory</p>
<p>Log directory</p>
<div className="nowrap">
<Tooltip placement="top" title={trialProfile.logDir}>
{trialProfile.logDir}
</Tooltip>
</div>
<p>TrainingPlatform</p>
<p>Training platform</p>
<div className="nowrap">
{
trialProfile.trainingServicePlatform
......
......@@ -60,6 +60,7 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
const trialConcurrency = experimentFile.params.trialConcurrency;
if (userInputVal !== undefined) {
if (userInputVal === trialConcurrency.toString() || userInputVal === '0') {
message.destroy();
message.info(
`trialConcurrency's value is ${trialConcurrency}, you did not modify it`, 2);
} else {
......@@ -76,6 +77,7 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
}
}).then(res => {
if (res.status === 200) {
message.destroy();
message.success(`Update ${CONTROLTYPE[1].toLocaleLowerCase()}
successfully`);
// rerender trial profile message
......@@ -83,16 +85,16 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
updateFile();
}
})
.catch(error => {
if (error.response.status === 500) {
if (error.response.data.error) {
message.error(error.response.data.error);
} else {
message.error(
`Update ${CONTROLTYPE[1].toLocaleLowerCase()} failed`);
.catch(error => {
if (error.response.status === 500) {
if (error.response.data.error) {
message.error(error.response.data.error);
} else {
message.error(
`Update ${CONTROLTYPE[1].toLocaleLowerCase()} failed`);
}
}
}
});
});
// btn -> edit
this.setState(() => ({
btnName: 'Edit',
......@@ -200,87 +202,85 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
percent={percent}
description={runDuration}
bgclass={status}
maxString={`MaxDuration: ${convertTime(trialProfile.maxDuration)}`}
maxString={`Max duration: ${convertTime(trialProfile.maxDuration)}`}
/>
<ProgressBar
who="TrialNum"
who="Trial numbers"
percent={bar2Percent}
description={bar2.toString()}
bgclass={status}
maxString={`MaxTrialNumber: ${trialProfile.MaxTrialNum}`}
maxString={`Max trial number: ${trialProfile.MaxTrialNum}`}
/>
<Row className="basic colorOfbasic mess">
<Col span={10}>
<p>best metric</p>
<div>{bestAccuracy.toFixed(6)}</div>
</Col>
<Col span={14}>
{/* modify concurrency */}
<p>concurrency</p>
<Row className="inputBox">
<input
type="number"
disabled={isEnable}
onChange={this.getUserTrialConcurrency}
className="concurrencyInput"
ref={(input) => this.conInput = input}
/>
<Button
type="primary"
className="tableButton editStyle"
onClick={this.editTrialConcurrency}
>{btnName}
</Button>
<Button
type="primary"
onClick={this.cancelFunction}
style={{ display: cancelSty, marginLeft: 1 }}
className="tableButton editStyle"
>
Cancel
</Button>
</Row>
</Col>
<p>Best metric</p>
<div>{bestAccuracy.toFixed(6)}</div>
</Row>
<Row className="mess">
<Col span={8}>
<Col span={6}>
<Row className="basic colorOfbasic">
<p>spent</p>
<p>Spent</p>
<div>{convertTime(trialProfile.execDuration)}</div>
</Row>
</Col>
<Col span={9}>
<Col span={6}>
<Row className="basic colorOfbasic">
<p>remaining</p>
<p>Remaining</p>
<div>{remaining}</div>
</Row>
</Col>
<Col span={7}>
<Col span={6}>
<Row className="basic colorOfbasic">
<p>running</p>
<p>Running</p>
<div>{trialNumber.runTrial}</div>
</Row>
</Col>
</Row>
<Row className="mess">
<Col span={8}>
<Col span={6}>
<Row className="basic colorOfbasic">
<p>succeed</p>
<p>Succeeded</p>
<div>{trialNumber.succTrial}</div>
</Row>
</Col>
<Col span={9}>
</Row>
<Row className="mess">
<Col span={6}>
<Row className="basic">
<p>stopped</p>
<p>Stopped</p>
<div>{trialNumber.stopTrial}</div>
</Row>
</Col>
<Col span={7}>
<Col span={6}>
<Row className="basic">
<p>failed</p>
<p>Failed</p>
<div>{trialNumber.failTrial}</div>
</Row>
</Col>
<Col span={12}>
{/* modify concurrency */}
<p>Concurrency</p>
<Row className="inputBox">
<input
type="number"
disabled={isEnable}
onChange={this.getUserTrialConcurrency}
className="concurrencyInput"
ref={(input) => this.conInput = input}
/>
<Button
type="primary"
className="tableButton editStyle"
onClick={this.editTrialConcurrency}
>{btnName}
</Button>
<Button
type="primary"
onClick={this.cancelFunction}
style={{ display: cancelSty, marginLeft: 1 }}
className="tableButton editStyle"
>
Cancel
</Button>
</Row>
</Col>
</Row>
</Row>
);
......
......@@ -22,10 +22,10 @@ class ProgressBar extends React.Component<ProItemProps, {}> {
return (
<div>
<Row className={`probar ${bgclass}`}>
<Col span={6}>
<Col span={8}>
<div className="name">{who}</div>
</Col>
<Col span={17} className="bar">
<Col span={16} className="bar">
<div className="showProgress">
<Progress
percent={percent}
......
......@@ -19,7 +19,7 @@ class SearchSpace extends React.Component<SearchspaceProps, {}> {
<div className="searchSpace">
<MonacoEditor
width="100%"
height="380"
height="361"
language="json"
theme="vs-light"
value={JSON.stringify(searchSpace, null, 2)}
......
......@@ -5,7 +5,7 @@ import DefaultMetric from '../public-child/DefaultMetrc';
import { TableObj } from '../../static/interface';
import { convertDuration } from '../../static/function';
import '../../static/style/tableStatus.css';
import '../../static/style/tableList.scss';
import '../../static/style/openRow.scss';
interface SuccessTableProps {
tableSource: Array<TableObj>;
......@@ -52,11 +52,11 @@ class SuccessTable extends React.Component<SuccessTableProps, {}> {
width: 140,
className: 'tableHead'
}, {
title: 'Id',
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 60,
className: 'tableHead idtitle',
className: 'tableHead leftTitle',
render: (text: string, record: TableObj) => {
return (
<div>{record.id}</div>
......@@ -92,7 +92,7 @@ class SuccessTable extends React.Component<SuccessTableProps, {}> {
);
}
}, {
title: 'Default Metric',
title: 'Default metric',
dataIndex: 'acc',
key: 'acc',
sorter: (a: TableObj, b: TableObj) => {
......
......@@ -42,7 +42,7 @@ class TrialInfo extends React.Component<TrialInfoProps, {}> {
<div className="profile">
<MonacoEditor
width="100%"
height="380"
height="361"
language="json"
theme="vs-light"
value={JSON.stringify(experiment, null, 2)}
......
......@@ -31,13 +31,13 @@ class LogPath extends React.Component<LogpathProps, {}> {
/>
<LogPathChild
eachLogpath={logStr.split(',')[1]}
logName="hdfsLogPath:"
logName="Log on HDFS:"
/>
</div>
:
<LogPathChild
eachLogpath={logStr}
logName="LogPath:"
logName="Log path:"
/>
}
</div>
......
......@@ -13,26 +13,44 @@ interface OpenRowProps {
logCollection: boolean;
}
class OpenRow extends React.Component<OpenRowProps, {}> {
interface OpenRowState {
idList: Array<string>;
}
class OpenRow extends React.Component<OpenRowProps, OpenRowState> {
constructor(props: OpenRowProps) {
super(props);
this.state = {
idList: ['']
};
}
copyParams = (record: TableObj) => {
let params = JSON.stringify(record.description.parameters);
// json format
const params = JSON.stringify(record.description.parameters, null, 4);
if (copy(params)) {
message.destroy();
message.success('Success copy parameters to clipboard in form of python dict !', 3);
const { idList } = this.state;
const copyIdList: Array<string> = idList;
copyIdList[copyIdList.length - 1] = record.id;
this.setState(() => ({
idList: copyIdList
}));
} else {
message.destroy();
message.error('Failed !', 2);
}
}
render() {
const { trainingPlatform, record, logCollection } = this.props;
const { idList } = this.state;
let isClick = false;
let isHasParameters = true;
if (idList.indexOf(record.id) !== -1) { isClick = true; }
if (record.description.parameters.error) {
isHasParameters = false;
}
......@@ -43,53 +61,61 @@ class OpenRow extends React.Component<OpenRowProps, {}> {
?
record.description.logPath
:
'This trial\'s logPath are not available.';
'This trial\'s log path are not available.';
return (
<pre id="description" className="hyperpar">
<Row className="openRowContent">
<Tabs tabPosition="left" className="card">
<TabPane tab="Parameters" key="1">
{
isHasParameters
?
<div>
<JSONTree
hideRoot={true}
shouldExpandNode={() => true} // default expandNode
getItemString={() => (<span />)} // remove the {} items
data={openRowDataSource.parameters}
/>
<Row className="openRowContent hyperpar">
<Tabs tabPosition="left" className="card">
<TabPane tab="Parameters" key="1">
{
isHasParameters
?
<Row id="description">
<Row className="bgHyper">
{
isClick
?
<pre>{JSON.stringify(openRowDataSource.parameters, null, 4)}</pre>
:
<JSONTree
hideRoot={true}
shouldExpandNode={() => true} // default expandNode
getItemString={() => (<span />)} // remove the {} items
data={openRowDataSource.parameters}
/>
}
</Row>
<Row className="copy">
<Button
onClick={this.copyParams.bind(this, record)}
>
Copy as Python
Copy as python
</Button>
</div>
:
<div className="logpath">
<span className="logName">Error: </span>
<span className="error">'This trial's parameters are not available.'</span>
</div>
}
</TabPane>
<TabPane tab="Log" key="2">
{
trainingPlatform !== 'local'
?
<PaiTrialLog
logStr={logPathRow}
id={record.id}
logCollection={logCollection}
/>
:
<TrialLog logStr={logPathRow} id={record.id} />
}
</TabPane>
</Tabs>
</Row>
</pre>
</Row>
</Row>
:
<Row className="logpath">
<span className="logName">Error: </span>
<span className="error">'This trial's parameters are not available.'</span>
</Row>
}
</TabPane>
<TabPane tab="Log" key="2">
{
trainingPlatform !== 'local'
?
<PaiTrialLog
logStr={logPathRow}
id={record.id}
logCollection={logCollection}
/>
:
<TrialLog logStr={logPathRow} id={record.id} />
}
</TabPane>
</Tabs>
</Row >
);
}
}
export default OpenRow;
\ No newline at end of file
export default OpenRow;
......@@ -40,7 +40,7 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
href={`${DOWNLOAD_IP}/trial_${id}.log`}
style={{ marginRight: 10 }}
>
trial stdout
Trial stdout
</a>
<a target="_blank" href={logStr.split(',')[1]}>hdfsLog</a>
</Row>
......@@ -48,11 +48,11 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
<Row>
<LogPathChild
eachLogpath={logStr.split(',')[0]}
logName="trial stdout:"
logName="Trial stdout:"
/>
<LogPathChild
eachLogpath={logStr.split(',')[1]}
logName="hdfsLog:"
logName="Log on HDFS:"
/>
</Row>
}
......
......@@ -20,7 +20,7 @@ class TrialLog extends React.Component<TrialLogProps, {}> {
<div>
<LogPathChild
eachLogpath={logStr}
logName="LogPath:"
logName="Log path:"
/>
</div>
);
......
......@@ -63,8 +63,8 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
},
formatter: function (data: TooltipForAccuracy) {
const result = '<div class="tooldetailAccuracy">' +
'<div>Trial No: ' + data.data[0] + '</div>' +
'<div>Default Metric: ' + data.data[1] + '</div>' +
'<div>Trial No.: ' + data.data[0] + '</div>' +
'<div>Default metric: ' + data.data[1] + '</div>' +
'<div>Parameters: ' +
'<pre>' + JSON.stringify(data.data[2], null, 4) + '</pre>' +
'</div>' +
......@@ -77,7 +77,7 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
type: 'category',
},
yAxis: {
name: 'Default Metric',
name: 'Default metric',
type: 'value',
},
series: [{
......
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