diff --git a/deployment/pypi/README.md b/deployment/pypi/README.md index da3f2bea2c..da888698a1 100644 --- a/deployment/pypi/README.md +++ b/deployment/pypi/README.md @@ -25,4 +25,4 @@ make ```bash make upload ``` -You may need to input the account and password of htts://pypi.org during this process. \ No newline at end of file +You may need to input the account and password of https://pypi.org during this process. diff --git a/src/webui/src/components/Overview.tsx b/src/webui/src/components/Overview.tsx index 55f91f952a..7386052308 100644 --- a/src/webui/src/components/Overview.tsx +++ b/src/webui/src/components/Overview.tsx @@ -296,6 +296,7 @@ class Overview extends React.Component<{}, OverviewState> { if (res.data.params.searchSpace) { res.data.params.searchSpace = JSON.parse(res.data.params.searchSpace); } + const isEdge = navigator.userAgent.indexOf('Edge') !== -1 ? true : false; const interResultList = res2.data; const contentOfExperiment = JSON.stringify(res.data, null, 2); let trialMessagesArr = res1.data; @@ -315,14 +316,16 @@ class Overview extends React.Component<{}, OverviewState> { const trialMessages = JSON.stringify(trialMessagesArr, null, 2); const aTag = document.createElement('a'); const file = new Blob([contentOfExperiment, trialMessages], { type: 'application/json' }); - aTag.download = 'experiment.txt'; + aTag.download = 'experiment.json'; aTag.href = URL.createObjectURL(file); aTag.click(); - URL.revokeObjectURL(aTag.href); + if (!isEdge) { + URL.revokeObjectURL(aTag.href); + } if (navigator.userAgent.indexOf('Firefox') > -1) { const downTag = document.createElement('a'); downTag.addEventListener('click', function () { - downTag.download = 'experiment.txt'; + downTag.download = 'experiment.json'; downTag.href = URL.createObjectURL(file); }); let eventMouse = document.createEvent('MouseEvents'); @@ -336,7 +339,7 @@ class Overview extends React.Component<{}, OverviewState> { })); } - // trial accuracy graph + // trial accuracy graph Default Metric drawPointGraph = () => { const { tableData } = this.state; @@ -366,7 +369,7 @@ class Overview extends React.Component<{}, OverviewState> { data: indexarr }, yAxis: { - name: 'Accuracy', + name: 'Default Metric', type: 'value', data: accarr }, diff --git a/src/webui/src/components/TrialsDetail.tsx b/src/webui/src/components/TrialsDetail.tsx index 5dc70ea247..477df4d4aa 100644 --- a/src/webui/src/components/TrialsDetail.tsx +++ b/src/webui/src/components/TrialsDetail.tsx @@ -3,7 +3,7 @@ import axios from 'axios'; import { MANAGER_IP } from '../static/const'; import { Row, Col, Button, Tabs, Input } from 'antd'; const Search = Input.Search; -import { TableObj, Parameters, AccurPoint } from '../static/interface'; +import { TableObj, Parameters, DetailAccurPoint, TooltipForAccuracy, } from '../static/interface'; import Accuracy from './overview/Accuracy'; import Duration from './trial-detail/Duration'; import Title1 from './overview/Title1'; @@ -42,11 +42,12 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { .then(res => { if (res.status === 200 && this._isMounted) { const accData = res.data; - const accSource: Array = []; + const accSource: Array = []; Object.keys(accData).map(item => { if (accData[item].status === 'SUCCEEDED' && accData[item].finalMetricData) { let acc; let tableAcc; + let searchSpace: object = {}; if (accData[item].finalMetricData) { acc = JSON.parse(accData[item].finalMetricData.data); if (typeof (acc) === 'object') { @@ -57,42 +58,62 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { tableAcc = acc; } } + if (accData[item].hyperParameters) { + searchSpace = JSON.parse(accData[item].hyperParameters).parameters; + } accSource.push({ acc: tableAcc, - index: accData[item].sequenceId + index: accData[item].sequenceId, + searchSpace: JSON.stringify(searchSpace) }); } }); - const accarr: Array = []; - const indexarr: Array = []; + const resultList: Array[] = []; Object.keys(accSource).map(item => { const items = accSource[item]; - accarr.push(items.acc); - indexarr.push(items.index); + let temp: Array; + temp = [items.index, items.acc, JSON.parse(items.searchSpace)]; + resultList.push(temp); }); const allAcuracy = { tooltip: { - trigger: 'item' + trigger: 'item', + enterable: true, + position: function (point: Array, data: TooltipForAccuracy) { + if (data.data[0] < resultList.length / 2) { + return [point[0], 10]; + } else { + return [point[0] - 300, 10]; + } + }, + formatter: function (data: TooltipForAccuracy) { + const result = '
' + + '
Trial No: ' + data.data[0] + '
' + + '
Default Metrc: ' + data.data[1] + '
' + + '
Parameters: ' + + '
' + JSON.stringify(data.data[2], null, 4) + '
' + + '
' + + '
'; + return result; + } }, xAxis: { name: 'Trial', type: 'category', - data: indexarr }, yAxis: { - name: 'Accuracy', + name: 'Default Metric', type: 'value', - data: accarr }, series: [{ symbolSize: 6, type: 'scatter', - data: accarr + data: resultList }] }; this.setState({ accSource: allAcuracy }, () => { - if (accarr.length === 0) { + if (resultList.length === 0) { this.setState({ accNodata: 'No data' }); @@ -250,8 +271,9 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { accSource, accNodata, tableListSource } = this.state; + const titleOfacc = ( - + ); const titleOfhyper = ( diff --git a/src/webui/src/components/overview/SuccessTable.tsx b/src/webui/src/components/overview/SuccessTable.tsx index b85057298b..245e1c4150 100644 --- a/src/webui/src/components/overview/SuccessTable.tsx +++ b/src/webui/src/components/overview/SuccessTable.tsx @@ -42,6 +42,7 @@ class SuccessTable extends React.Component { dataIndex: 'duration', key: 'duration', width: 140, + sorter: (a: TableObj, b: TableObj) => (a.duration as number) - (b.duration as number), render: (text: string, record: TableObj) => { let duration; if (record.duration) { @@ -69,6 +70,7 @@ class SuccessTable extends React.Component { title: 'Default Metric', dataIndex: 'acc', key: 'acc', + sorter: (a: TableObj, b: TableObj) => (a.acc as number) - (b.acc as number), render: (text: string, record: TableObj) => { const accuracy = record.acc; let wei = 0; diff --git a/src/webui/src/components/trial-detail/TableList.tsx b/src/webui/src/components/trial-detail/TableList.tsx index c7cd0bf782..9e3ccd7a4c 100644 --- a/src/webui/src/components/trial-detail/TableList.tsx +++ b/src/webui/src/components/trial-detail/TableList.tsx @@ -130,7 +130,11 @@ class TableList extends React.Component { }) .catch(error => { if (error.response.status === 500) { - message.error('500 error, fail to cancel the job'); + if (error.response.data.error) { + message.error(error.response.data.error); + } else { + message.error('500 error, fail to cancel the job'); + } } }); } diff --git a/src/webui/src/static/interface.ts b/src/webui/src/static/interface.ts index 03441a123f..4faf16e8d6 100644 --- a/src/webui/src/static/interface.ts +++ b/src/webui/src/static/interface.ts @@ -42,6 +42,16 @@ interface AccurPoint { index: number; } +interface DetailAccurPoint { + acc: number; + index: number; + searchSpace: string; +} + +interface TooltipForAccuracy { + data: Array; +} + interface TrialNumber { succTrial: number; failTrial: number; @@ -82,5 +92,6 @@ interface VisualMapValue { export {TableObj, Parameters, Experiment, AccurPoint, TrialNumber, TrialJob, + DetailAccurPoint, TooltipForAccuracy, HoverName, ParaObj, VisualMapValue, Dimobj }; \ No newline at end of file diff --git a/src/webui/src/static/style/trialsDetail.scss b/src/webui/src/static/style/trialsDetail.scss index 44e6070fdc..6dc3e93f9e 100644 --- a/src/webui/src/static/style/trialsDetail.scss +++ b/src/webui/src/static/style/trialsDetail.scss @@ -17,8 +17,7 @@ background-color: #999; span{ color: #fff; - font-size: 18px; - font-family: 'Segoe'; + font-weight: normal; } } } @@ -52,4 +51,18 @@ .commonTableStyle{ overflow: hidden; } -} \ No newline at end of file +} + +.tooldetailAccuracy{ + user-select: text; + min-width: 245px; + max-width: 350px; + max-height: 350px; + padding: 10px 10px; + white-space: normal; + overflow: auto; + pre{ + overflow: inherit; + margin-bottom: 10px; + } +}