Unverified Commit e2d8cc1b authored by Lijiaoa's avatar Lijiaoa Committed by GitHub
Browse files

[webui] format code by eslint and prettier (#2744)



* update

* format as prettier

* fix error

* add stylelint for scss css file

* add arrow-parens rule

* update

* fix lint

* fix conflict
Co-authored-by: default avatarLijiao <15910218274@163.com>
Co-authored-by: default avatarLijiao <Lijiaoa@outlook.com>
Co-authored-by: default avatarLijiao <1425861283@qq.com>
parent 4668fc08
...@@ -23,16 +23,13 @@ interface DurationState { ...@@ -23,16 +23,13 @@ interface DurationState {
} }
class Duration extends React.Component<DurationProps, DurationState> { class Duration extends React.Component<DurationProps, DurationState> {
constructor(props: DurationProps) { constructor(props: DurationProps) {
super(props); super(props);
this.state = { this.state = {
startDuration: 0, // for record data zoom startDuration: 0, // for record data zoom
endDuration: 100, endDuration: 100,
durationSource: this.initDuration(this.props.source), durationSource: this.initDuration(this.props.source)
}; };
} }
initDuration = (source: Array<TableObj>): any => { initDuration = (source: Array<TableObj>): any => {
...@@ -50,12 +47,15 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -50,12 +47,15 @@ class Duration extends React.Component<DurationProps, DurationState> {
axisPointer: { axisPointer: {
type: 'shadow' type: 'shadow'
}, },
formatter: (data: any): React.ReactNode => ( formatter: (data: any): React.ReactNode =>
'<div>' + '<div>' +
'<div>Trial No.: ' + data[0].dataIndex + '</div>' + '<div>Trial No.: ' +
'<div>Duration: ' + convertDuration(data[0].data) + '</div>' + data[0].dataIndex +
'</div>' +
'<div>Duration: ' +
convertDuration(data[0].data) +
'</div>' +
'</div>' '</div>'
),
}, },
grid: { grid: {
bottom: '3%', bottom: '3%',
...@@ -71,11 +71,11 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -71,11 +71,11 @@ class Duration extends React.Component<DurationProps, DurationState> {
filterMode: 'empty', filterMode: 'empty',
start: 0, start: 0,
end: 100 end: 100
}, }
], ],
xAxis: { xAxis: {
name: 'Time/s', name: 'Time/s',
type: 'value', type: 'value'
}, },
yAxis: { yAxis: {
name: 'Trial No.', name: 'Trial No.',
...@@ -85,12 +85,14 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -85,12 +85,14 @@ class Duration extends React.Component<DurationProps, DurationState> {
padding: [0, 0, 0, 30] padding: [0, 0, 0, 30]
} }
}, },
series: [{ series: [
type: 'bar', {
data: trialTime type: 'bar',
}] data: trialTime
}
]
}; };
} };
getOption = (dataObj: Runtrial): any => { getOption = (dataObj: Runtrial): any => {
const { startDuration, endDuration } = this.state; const { startDuration, endDuration } = this.state;
...@@ -100,12 +102,15 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -100,12 +102,15 @@ class Duration extends React.Component<DurationProps, DurationState> {
axisPointer: { axisPointer: {
type: 'shadow' type: 'shadow'
}, },
formatter: (data: any): React.ReactNode => ( formatter: (data: any): React.ReactNode =>
'<div>' + '<div>' +
'<div>Trial No.: ' + data[0].dataIndex + '</div>' + '<div>Trial No.: ' +
'<div>Duration: ' + convertDuration(data[0].data) + '</div>' + data[0].dataIndex +
'</div>' +
'<div>Duration: ' +
convertDuration(data[0].data) +
'</div>' +
'</div>' '</div>'
),
}, },
grid: { grid: {
bottom: '3%', bottom: '3%',
...@@ -121,11 +126,11 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -121,11 +126,11 @@ class Duration extends React.Component<DurationProps, DurationState> {
filterMode: 'empty', filterMode: 'empty',
start: startDuration, start: startDuration,
end: endDuration end: endDuration
}, }
], ],
xAxis: { xAxis: {
name: 'Time', name: 'Time',
type: 'value', type: 'value'
}, },
yAxis: { yAxis: {
name: 'Trial', name: 'Trial',
...@@ -135,12 +140,14 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -135,12 +140,14 @@ class Duration extends React.Component<DurationProps, DurationState> {
padding: [0, 0, 0, 30] padding: [0, 0, 0, 30]
} }
}, },
series: [{ series: [
type: 'bar', {
data: dataObj.trialTime type: 'bar',
}] data: dataObj.trialTime
}
]
}; };
} };
drawDurationGraph = (source: Array<TableObj>): void => { drawDurationGraph = (source: Array<TableObj>): void => {
// why this function run two times when props changed? // why this function run two times when props changed?
...@@ -160,7 +167,7 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -160,7 +167,7 @@ class Duration extends React.Component<DurationProps, DurationState> {
this.setState({ this.setState({
durationSource: this.getOption(trialRun[0]) durationSource: this.getOption(trialRun[0])
}); });
} };
componentDidMount(): void { componentDidMount(): void {
const { source } = this.props; const { source } = this.props;
...@@ -178,13 +185,13 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -178,13 +185,13 @@ class Duration extends React.Component<DurationProps, DurationState> {
render(): React.ReactNode { render(): React.ReactNode {
const { durationSource } = this.state; const { durationSource } = this.state;
const onEvents = { 'dataZoom': this.durationDataZoom }; const onEvents = { dataZoom: this.durationDataZoom };
return ( return (
<div> <div>
<ReactEcharts <ReactEcharts
option={durationSource} option={durationSource}
style={{ width: '94%', height: 412, margin: '0 auto', marginTop: 15 }} style={{ width: '94%', height: 412, margin: '0 auto', marginTop: 15 }}
theme="my_theme" theme='my_theme'
notMerge={true} // update now notMerge={true} // update now
onEvents={onEvents} onEvents={onEvents}
/> />
...@@ -195,11 +202,11 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -195,11 +202,11 @@ class Duration extends React.Component<DurationProps, DurationState> {
private durationDataZoom = (e: EventMap): void => { private durationDataZoom = (e: EventMap): void => {
if (e.batch !== undefined) { if (e.batch !== undefined) {
this.setState(() => ({ this.setState(() => ({
startDuration: (e.batch[0].start !== null ? e.batch[0].start : 0), startDuration: e.batch[0].start !== null ? e.batch[0].start : 0,
endDuration: (e.batch[0].end !== null ? e.batch[0].end : 100) endDuration: e.batch[0].end !== null ? e.batch[0].end : 100
})); }));
} }
} };
} }
export default Duration; export default Duration;
...@@ -28,7 +28,6 @@ interface IntermediateProps { ...@@ -28,7 +28,6 @@ interface IntermediateProps {
} }
class Intermediate extends React.Component<IntermediateProps, IntermediateState> { class Intermediate extends React.Component<IntermediateProps, IntermediateState> {
static intervalMediate = 1; static intervalMediate = 1;
public pointInput!: HTMLInputElement | null; public pointInput!: HTMLInputElement | null;
public minValInput!: HTMLInputElement | null; public minValInput!: HTMLInputElement | null;
...@@ -68,7 +67,9 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -68,7 +67,9 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
}); });
}); });
// find max intermediate number // find max intermediate number
trialIntermediate.sort((a, b) => { return (b.data.length - a.data.length); }); trialIntermediate.sort((a, b) => {
return b.data.length - a.data.length;
});
const legend: string[] = []; const legend: string[] = [];
// max length // max length
const length = trialIntermediate[0].data.length; const length = trialIntermediate[0].data.length;
...@@ -84,27 +85,35 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -84,27 +85,35 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
enterable: true, enterable: true,
position: function (point: number[], data: TooltipForIntermediate): number[] { position: function(point: number[], data: TooltipForIntermediate): number[] {
if (data.dataIndex < length / 2) { if (data.dataIndex < length / 2) {
return [point[0], 80]; return [point[0], 80];
} else { } else {
return [point[0] - 300, 80]; return [point[0] - 300, 80];
} }
}, },
formatter: function (data: TooltipForIntermediate): React.ReactNode { formatter: function(data: TooltipForIntermediate): React.ReactNode {
const trialId = data.seriesName; const trialId = data.seriesName;
let obj = {}; let obj = {};
const temp = trialIntermediate.find(key => key.name === trialId); const temp = trialIntermediate.find(key => key.name === trialId);
if (temp !== undefined) { if (temp !== undefined) {
obj = temp.hyperPara; obj = temp.hyperPara;
} }
return '<div class="tooldetailAccuracy">' + return (
'<div>Trial ID: ' + trialId + '</div>' + '<div class="tooldetailAccuracy">' +
'<div>Intermediate: ' + data.data + '</div>' + '<div>Trial ID: ' +
trialId +
'</div>' +
'<div>Intermediate: ' +
data.data +
'</div>' +
'<div>Parameters: ' + '<div>Parameters: ' +
'<pre>' + JSON.stringify(obj, null, 4) + '</pre>' + '<pre>' +
JSON.stringify(obj, null, 4) +
'</pre>' +
'</div>' + '</div>' +
'</div>'; '</div>'
);
} }
}, },
grid: { grid: {
...@@ -121,7 +130,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -121,7 +130,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
yAxis: { yAxis: {
type: 'value', type: 'value',
name: 'Metric', name: 'Metric',
scale: true, scale: true
}, },
dataZoom: [ dataZoom: [
{ {
...@@ -147,7 +156,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -147,7 +156,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
boundaryGap: false, boundaryGap: false
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
...@@ -156,7 +165,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -156,7 +165,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
}; };
this.setState({ interSource: nullData }); this.setState({ interSource: nullData });
} }
} };
// confirm btn function [filter data] // confirm btn function [filter data]
filterLines = (): void => { filterLines = (): void => {
...@@ -198,14 +207,14 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -198,14 +207,14 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
const counts = this.state.clickCounts + 1; const counts = this.state.clickCounts + 1;
this.setState({ isLoadconfirmBtn: false, clickCounts: counts }); this.setState({ isLoadconfirmBtn: false, clickCounts: counts });
}); });
} };
switchTurn = (ev: React.MouseEvent<HTMLElement>, checked?: boolean): void => { switchTurn = (ev: React.MouseEvent<HTMLElement>, checked?: boolean): void => {
this.setState({ isFilter: checked }); this.setState({ isFilter: checked });
if (checked === false) { if (checked === false) {
this.drawIntermediate(this.props.source); this.drawIntermediate(this.props.source);
} }
} };
componentDidMount(): void { componentDidMount(): void {
const { source } = this.props; const { source } = this.props;
...@@ -235,56 +244,47 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -235,56 +244,47 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
render(): React.ReactNode { render(): React.ReactNode {
const { interSource, isLoadconfirmBtn, isFilter } = this.state; const { interSource, isLoadconfirmBtn, isFilter } = this.state;
const IntermediateEvents = { 'dataZoom': this.intermediateDataZoom }; const IntermediateEvents = { dataZoom: this.intermediateDataZoom };
return ( return (
<div> <div>
{/* style in para.scss */} {/* style in para.scss */}
<Stack horizontal horizontalAlign="end" tokens={stackTokens} className="meline intermediate"> <Stack horizontal horizontalAlign='end' tokens={stackTokens} className='meline intermediate'>
{ {isFilter ? (
isFilter <div>
? <span className='filter-x'># Intermediate result</span>
<div> <input
<span className="filter-x"># Intermediate result</span> // placeholder="point"
<input ref={(input): any => (this.pointInput = input)}
// placeholder="point" className='strange'
ref={(input): any => this.pointInput = input} />
className="strange" <span>Metric range</span>
/> <input
<span>Metric range</span> // placeholder="range"
<input ref={(input): any => (this.minValInput = input)}
// placeholder="range" />
ref={(input): any => this.minValInput = input} <span className='hyphen'>-</span>
/> <input
<span className="hyphen">-</span> // placeholder="range"
<input ref={(input): any => (this.maxValInput = input)}
// placeholder="range" />
ref={(input): any => this.maxValInput = input} <PrimaryButton text='Confirm' onClick={this.filterLines} disabled={isLoadconfirmBtn} />
/> </div>
<PrimaryButton ) : null}
text="Confirm"
onClick={this.filterLines}
disabled={isLoadconfirmBtn}
/>
</div>
:
null
}
{/* filter message */} {/* filter message */}
<Stack horizontal className="filter-toggle"> <Stack horizontal className='filter-toggle'>
<span>Filter</span> <span>Filter</span>
<Toggle onChange={this.switchTurn} /> <Toggle onChange={this.switchTurn} />
</Stack> </Stack>
</Stack> </Stack>
<div className="intermediate-graph"> <div className='intermediate-graph'>
<ReactEcharts <ReactEcharts
option={interSource} option={interSource}
style={{ width: '100%', height: 400, margin: '0 auto' }} style={{ width: '100%', height: 400, margin: '0 auto' }}
notMerge={true} // update now notMerge={true} // update now
onEvents={IntermediateEvents} onEvents={IntermediateEvents}
/> />
<div className="xAxis"># Intermediate result</div> <div className='xAxis'># Intermediate result</div>
</div> </div>
</div> </div>
); );
...@@ -293,11 +293,11 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -293,11 +293,11 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
private intermediateDataZoom = (e: EventMap): void => { private intermediateDataZoom = (e: EventMap): void => {
if (e.batch !== undefined) { if (e.batch !== undefined) {
this.setState(() => ({ this.setState(() => ({
startMediaY: (e.batch[0].start !== null ? e.batch[0].start : 0), startMediaY: e.batch[0].start !== null ? e.batch[0].start : 0,
endMediaY: (e.batch[0].end !== null ? e.batch[0].end : 100) endMediaY: e.batch[0].end !== null ? e.batch[0].end : 100
})); }));
} }
} };
} }
export default Intermediate; export default Intermediate;
...@@ -24,7 +24,6 @@ interface ParaProps { ...@@ -24,7 +24,6 @@ interface ParaProps {
} }
class Para extends React.Component<ParaProps, ParaState> { class Para extends React.Component<ParaProps, ParaState> {
private paraRef = React.createRef<HTMLDivElement>(); private paraRef = React.createRef<HTMLDivElement>();
private pcs: any; private pcs: any;
...@@ -57,7 +56,7 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -57,7 +56,7 @@ class Para extends React.Component<ParaProps, ParaState> {
this.renderParallelCoordinates(); this.renderParallelCoordinates();
}); });
} }
} };
// select all final keys // select all final keys
updateEntries = (event: React.FormEvent<HTMLDivElement>, item: any): void => { updateEntries = (event: React.FormEvent<HTMLDivElement>, item: any): void => {
...@@ -66,7 +65,7 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -66,7 +65,7 @@ class Para extends React.Component<ParaProps, ParaState> {
this.renderParallelCoordinates(); this.renderParallelCoordinates();
}); });
} }
} };
componentDidMount(): void { componentDidMount(): void {
this.renderParallelCoordinates(); this.renderParallelCoordinates();
...@@ -86,8 +85,8 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -86,8 +85,8 @@ class Para extends React.Component<ParaProps, ParaState> {
const { selectedPercent, noChart } = this.state; const { selectedPercent, noChart } = this.state;
return ( return (
<div className="parameter"> <div className='parameter'>
<Stack horizontal className="para-filter" horizontalAlign="end"> <Stack horizontal className='para-filter' horizontalAlign='end'>
<Dropdown <Dropdown
selectedKey={selectedPercent} selectedKey={selectedPercent}
onChange={this.percentNum} onChange={this.percentNum}
...@@ -95,15 +94,15 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -95,15 +94,15 @@ class Para extends React.Component<ParaProps, ParaState> {
{ key: '0.01', text: 'Top 1%' }, { key: '0.01', text: 'Top 1%' },
{ key: '0.05', text: 'Top 5%' }, { key: '0.05', text: 'Top 5%' },
{ key: '0.2', text: 'Top 20%' }, { key: '0.2', text: 'Top 20%' },
{ key: '1', text: 'Top 100%' }, { key: '1', text: 'Top 100%' }
]} ]}
styles={{ dropdown: { width: 120 } }} styles={{ dropdown: { width: 120 } }}
className="para-filter-percent" className='para-filter-percent'
/> />
{this.finalKeysDropdown()} {this.finalKeysDropdown()}
</Stack> </Stack>
<div className="parcoords" style={this.chartMulineStyle} ref={this.paraRef}/> <div className='parcoords' style={this.chartMulineStyle} ref={this.paraRef} />
{noChart && <div className="nodata">No data</div>} {noChart && <div className='nodata'>No data</div>}
</div> </div>
); );
} }
...@@ -116,18 +115,19 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -116,18 +115,19 @@ class Para extends React.Component<ParaProps, ParaState> {
const finalKeysDropdown: any = []; const finalKeysDropdown: any = [];
TRIALS.finalKeys().forEach(item => { TRIALS.finalKeys().forEach(item => {
finalKeysDropdown.push({ finalKeysDropdown.push({
key: item, text: item key: item,
text: item
}); });
}); });
return ( return (
<div> <div>
<span className="para-filter-text para-filter-middle">Metrics</span> <span className='para-filter-text para-filter-middle'>Metrics</span>
<Dropdown <Dropdown
selectedKey={primaryMetricKey} selectedKey={primaryMetricKey}
options={finalKeysDropdown} options={finalKeysDropdown}
onChange={this.updateEntries} onChange={this.updateEntries}
styles={{ root: { width: 150, display: 'inline-block' } }} styles={{ root: { width: 150, display: 'inline-block' } }}
className="para-filter-percent" className='para-filter-percent'
/> />
</div> </div>
); );
...@@ -150,13 +150,17 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -150,13 +150,17 @@ class Para extends React.Component<ParaProps, ParaState> {
let convertedTrials = this.getTrialsAsObjectList(inferredSearchSpace, inferredMetricSpace); let convertedTrials = this.getTrialsAsObjectList(inferredSearchSpace, inferredMetricSpace);
const dimensions: [any, any][] = []; const dimensions: [any, any][] = [];
let colorDim: string | undefined = undefined, colorScale: any = undefined; let colorDim: string | undefined = undefined,
colorScale: any = undefined;
// treat every axis as numeric to fit for brush // treat every axis as numeric to fit for brush
for (const [k, v] of inferredSearchSpace.axes) { for (const [k, v] of inferredSearchSpace.axes) {
dimensions.push([k, { dimensions.push([
type: 'number', k,
yscale: this.convertToD3Scale(v) {
}]); type: 'number',
yscale: this.convertToD3Scale(v)
}
]);
} }
for (const [k, v] of inferredMetricSpace.axes) { for (const [k, v] of inferredMetricSpace.axes) {
const scale = this.convertToD3Scale(v); const scale = this.convertToD3Scale(v);
...@@ -164,7 +168,7 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -164,7 +168,7 @@ class Para extends React.Component<ParaProps, ParaState> {
// set color for primary metrics // set color for primary metrics
// `colorScale` is used to produce a color range, while `scale` is to produce a pixel range // `colorScale` is used to produce a color range, while `scale` is to produce a pixel range
colorScale = this.convertToD3Scale(v, false); colorScale = this.convertToD3Scale(v, false);
convertedTrials.sort((a, b) => EXPERIMENT.optimizeMode === 'minimize' ? a[k] - b[k] : b[k] - a[k]); convertedTrials.sort((a, b) => (EXPERIMENT.optimizeMode === 'minimize' ? a[k] - b[k] : b[k] - a[k]));
// filter top trials // filter top trials
if (percent != 1) { if (percent != 1) {
const keptTrialNum = Math.max(Math.ceil(convertedTrials.length * percent), 1); const keptTrialNum = Math.max(Math.ceil(convertedTrials.length * percent), 1);
...@@ -179,20 +183,24 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -179,20 +183,24 @@ class Para extends React.Component<ParaProps, ParaState> {
// reverse the converted trials to show the top ones upfront // reverse the converted trials to show the top ones upfront
convertedTrials.reverse(); convertedTrials.reverse();
const assignColors = (scale: any): void => { const assignColors = (scale: any): void => {
scale.range([0, 1]); // fake a range to perform invert scale.range([0, 1]); // fake a range to perform invert
const [scaleMin, scaleMax] = scale.domain(); const [scaleMin, scaleMax] = scale.domain();
const pivot = scale.invert(0.5); const pivot = scale.invert(0.5);
scale.domain([scaleMin, pivot, scaleMax]) scale
.domain([scaleMin, pivot, scaleMax])
.range(['#90EE90', '#FFC400', '#CA0000']) .range(['#90EE90', '#FFC400', '#CA0000'])
.interpolate(d3.interpolateHsl); .interpolate(d3.interpolateHsl);
}; };
assignColors(colorScale); assignColors(colorScale);
colorDim = k; colorDim = k;
} }
dimensions.push([k, { dimensions.push([
type: 'number', k,
yscale: scale {
}]); type: 'number',
yscale: scale
}
]);
} }
if (convertedTrials.length === 0 || dimensions.length <= 1) { if (convertedTrials.length === 0 || dimensions.length <= 1) {
...@@ -203,13 +211,15 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -203,13 +211,15 @@ class Para extends React.Component<ParaProps, ParaState> {
if (firstRun) { if (firstRun) {
this.pcs = ParCoords()(this.paraRef.current); this.pcs = ParCoords()(this.paraRef.current);
} }
this.pcs.data(convertedTrials) this.pcs
.data(convertedTrials)
.dimensions(dimensions.reduce((obj, entry) => ({ ...obj, [entry[0]]: entry[1] }), {})); .dimensions(dimensions.reduce((obj, entry) => ({ ...obj, [entry[0]]: entry[1] }), {}));
if (firstRun) { if (firstRun) {
this.pcs.margin(this.innerChartMargins) this.pcs
.margin(this.innerChartMargins)
.alphaOnBrushed(0.2) .alphaOnBrushed(0.2)
.smoothness(0.1) .smoothness(0.1)
.brushMode("1D-axes") .brushMode('1D-axes')
.reorderable() .reorderable()
.interactive(); .interactive();
} }
...@@ -228,7 +238,7 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -228,7 +238,7 @@ class Para extends React.Component<ParaProps, ParaState> {
return succeededTrials.map(s => { return succeededTrials.map(s => {
const entries = Array.from(s.parameters(inferredSearchSpace).entries()); const entries = Array.from(s.parameters(inferredSearchSpace).entries());
entries.push(...(Array.from(s.metrics(inferredMetricSpace).entries()))); entries.push(...Array.from(s.metrics(inferredMetricSpace).entries()));
const ret = {}; const ret = {};
for (const [k, v] of entries) { for (const [k, v] of entries) {
ret[k.fullName] = v; ret[k.fullName] = v;
...@@ -247,20 +257,26 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -247,20 +257,26 @@ class Para extends React.Component<ParaProps, ParaState> {
private convertToD3Scale(axis: SingleAxis, initRange: boolean = true): any { private convertToD3Scale(axis: SingleAxis, initRange: boolean = true): any {
const padLinear = ([x0, x1], k = 0.1): [number, number] => { const padLinear = ([x0, x1], k = 0.1): [number, number] => {
const dx = (x1 - x0) * k / 2; const dx = ((x1 - x0) * k) / 2;
return [x0 - dx, x1 + dx]; return [x0 - dx, x1 + dx];
}; };
const padLog = ([x0, x1], k = 0.1): [number, number] => { const padLog = ([x0, x1], k = 0.1): [number, number] => {
const [y0, y1] = padLinear([Math.log(x0), Math.log(x1)], k); const [y0, y1] = padLinear([Math.log(x0), Math.log(x1)], k);
return [Math.exp(y0), Math.exp(y1)]; return [Math.exp(y0), Math.exp(y1)];
} };
let scaleInst: any = undefined; let scaleInst: any = undefined;
if (axis.scale === 'ordinal') { if (axis.scale === 'ordinal') {
if (axis.nested) { if (axis.nested) {
// TODO: handle nested entries // TODO: handle nested entries
scaleInst = d3.scalePoint().domain(Array.from(axis.domain.keys())).padding(0.2); scaleInst = d3
.scalePoint()
.domain(Array.from(axis.domain.keys()))
.padding(0.2);
} else { } else {
scaleInst = d3.scalePoint().domain(axis.domain).padding(0.2); scaleInst = d3
.scalePoint()
.domain(axis.domain)
.padding(0.2);
} }
} else if (axis.scale === 'log') { } else if (axis.scale === 'log') {
scaleInst = d3.scaleLog().domain(padLog(axis.domain)); scaleInst = d3.scaleLog().domain(padLog(axis.domain));
......
...@@ -2,8 +2,20 @@ import React, { lazy } from 'react'; ...@@ -2,8 +2,20 @@ import React, { lazy } from 'react';
import axios from 'axios'; import axios from 'axios';
import ReactEcharts from 'echarts-for-react'; import ReactEcharts from 'echarts-for-react';
import { import {
Stack, Dropdown, DetailsList, IDetailsListProps, DetailsListLayoutMode, Stack,
PrimaryButton, Modal, IDropdownOption, IColumn, Selection, SelectionMode, IconButton, TooltipHost, IStackTokens Dropdown,
DetailsList,
IDetailsListProps,
DetailsListLayoutMode,
PrimaryButton,
Modal,
IDropdownOption,
IColumn,
Selection,
SelectionMode,
IconButton,
TooltipHost,
IStackTokens
} from '@fluentui/react'; } from '@fluentui/react';
import ReactPaginate from 'react-paginate'; import ReactPaginate from 'react-paginate';
import { LineChart, blocked, copy } from '../buttons/Icon'; import { LineChart, blocked, copy } from '../buttons/Icon';
...@@ -81,7 +93,6 @@ interface TableListState { ...@@ -81,7 +93,6 @@ interface TableListState {
} }
class TableList extends React.Component<TableListProps, TableListState> { class TableList extends React.Component<TableListProps, TableListState> {
public intervalTrialLog = 10; public intervalTrialLog = 10;
public trialId!: string; public trialId!: string;
...@@ -129,17 +140,20 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -129,17 +140,20 @@ class TableList extends React.Component<TableListProps, TableListState> {
currColumn.isSorted = true; currColumn.isSorted = true;
} else { } else {
newCol.isSorted = false; newCol.isSorted = false;
newCol.isSortedDescending = true; newCol.isSortedDescending = true;
} }
}); });
this.setState({ this.setState(
tableColumns: newColumns, {
sortMessage: { field: getColumn.key, isDescend: currColumn.isSortedDescending } tableColumns: newColumns,
}, () => { sortMessage: { field: getColumn.key, isDescend: currColumn.isSortedDescending }
this.updateData(); },
}); () => {
} this.updateData();
}
);
};
AccuracyColumnConfig: any = { AccuracyColumnConfig: any = {
name: 'Default metric', name: 'Default metric',
...@@ -151,9 +165,11 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -151,9 +165,11 @@ class TableList extends React.Component<TableListProps, TableListState> {
isResizable: true, isResizable: true,
data: 'number', data: 'number',
onColumnClick: this.onColumnClick, onColumnClick: this.onColumnClick,
onRender: (item): React.ReactNode => <TooltipHost content={item.formattedLatestAccuracy}> onRender: (item): React.ReactNode => (
<div className="ellipsis">{item.formattedLatestAccuracy}</div> <TooltipHost content={item.formattedLatestAccuracy}>
</TooltipHost> <div className='ellipsis'>{item.formattedLatestAccuracy}</div>
</TooltipHost>
)
}; };
SequenceIdColumnConfig: any = { SequenceIdColumnConfig: any = {
...@@ -164,7 +180,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -164,7 +180,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
maxWidth: 240, maxWidth: 240,
className: 'tableHead', className: 'tableHead',
data: 'number', data: 'number',
onColumnClick: this.onColumnClick, onColumnClick: this.onColumnClick
}; };
IdColumnConfig: any = { IdColumnConfig: any = {
...@@ -188,9 +204,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -188,9 +204,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
isResizable: true, isResizable: true,
data: 'number', data: 'number',
onColumnClick: this.onColumnClick, onColumnClick: this.onColumnClick,
onRender: (record): React.ReactNode => ( onRender: (record): React.ReactNode => <span>{formatTimestamp(record.startTime)}</span>
<span>{formatTimestamp(record.startTime)}</span>
)
}; };
EndTimeColumnConfig: any = { EndTimeColumnConfig: any = {
...@@ -202,9 +216,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -202,9 +216,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
isResizable: true, isResizable: true,
data: 'number', data: 'number',
onColumnClick: this.onColumnClick, onColumnClick: this.onColumnClick,
onRender: (record): React.ReactNode => ( onRender: (record): React.ReactNode => <span>{formatTimestamp(record.endTime, '--')}</span>
<span>{formatTimestamp(record.endTime, '--')}</span>
)
}; };
DurationColumnConfig: any = { DurationColumnConfig: any = {
...@@ -216,9 +228,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -216,9 +228,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
isResizable: true, isResizable: true,
data: 'number', data: 'number',
onColumnClick: this.onColumnClick, onColumnClick: this.onColumnClick,
onRender: (record): React.ReactNode => ( onRender: (record): React.ReactNode => <span className='durationsty'>{convertDuration(record.duration)}</span>
<span className="durationsty">{convertDuration(record.duration)}</span>
)
}; };
StatusColumnConfig: any = { StatusColumnConfig: any = {
...@@ -231,9 +241,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -231,9 +241,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
isResizable: true, isResizable: true,
data: 'string', data: 'string',
onColumnClick: this.onColumnClick, onColumnClick: this.onColumnClick,
onRender: (record): React.ReactNode => ( onRender: (record): React.ReactNode => <span className={`${record.status} commonStyle`}>{record.status}</span>
<span className={`${record.status} commonStyle`}>{record.status}</span>
),
}; };
IntermediateCountColumnConfig: any = { IntermediateCountColumnConfig: any = {
...@@ -245,9 +253,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -245,9 +253,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
isResizable: true, isResizable: true,
data: 'number', data: 'number',
onColumnClick: this.onColumnClick, onColumnClick: this.onColumnClick,
onRender: (record): React.ReactNode => ( onRender: (record): React.ReactNode => <span>{`#${record.intermediateCount}`}</span>
<span>{`#${record.intermediateCount}`}</span>
)
}; };
showIntermediateModal = async (record: TrialJobInfo, event: React.SyntheticEvent<EventTarget>): Promise<void> => { showIntermediateModal = async (record: TrialJobInfo, event: React.SyntheticEvent<EventTarget>): Promise<void> => {
...@@ -273,7 +279,6 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -273,7 +279,6 @@ class TableList extends React.Component<TableListProps, TableListState> {
} }
// intermediateArr just store default val // intermediateArr just store default val
metricDatas.map(item => { metricDatas.map(item => {
if (item.type === 'PERIODICAL') { if (item.type === 'PERIODICAL') {
const temp = parseMetrics(item.data); const temp = parseMetrics(item.data);
if (typeof temp === 'object') { if (typeof temp === 'object') {
...@@ -292,7 +297,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -292,7 +297,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
}); });
} }
this.setState({ modalVisible: true }); this.setState({ modalVisible: true });
} };
// intermediate button click -> intermediate graph for each trial // intermediate button click -> intermediate graph for each trial
// support intermediate is dict // support intermediate is dict
...@@ -329,45 +334,43 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -329,45 +334,43 @@ class TableList extends React.Component<TableListProps, TableListState> {
intermediateOption: intermediate intermediateOption: intermediate
}); });
} }
} };
hideIntermediateModal = (): void => { hideIntermediateModal = (): void => {
this.setState({ this.setState({
modalVisible: false modalVisible: false
}); });
} };
hideShowColumnModal = (): void => { hideShowColumnModal = (): void => {
this.setState(() => ({ isShowColumn: false })); this.setState(() => ({ isShowColumn: false }));
} };
// click add column btn, just show the modal of addcolumn // click add column btn, just show the modal of addcolumn
addColumn = (): void => { addColumn = (): void => {
// show user select check button // show user select check button
this.setState(() => ({ isShowColumn: true })); this.setState(() => ({ isShowColumn: true }));
} };
fillSelectedRowsTostate = (selected: number[] | string[], selectedRows: Array<TableRecord>): void => { fillSelectedRowsTostate = (selected: number[] | string[], selectedRows: Array<TableRecord>): void => {
this.setState({ selectRows: selectedRows, selectedRowKeys: selected }); this.setState({ selectRows: selectedRows, selectedRowKeys: selected });
} };
// open Compare-modal // open Compare-modal
compareBtn = (): void => { compareBtn = (): void => {
const { selectRows } = this.state; const { selectRows } = this.state;
if (selectRows.length === 0) { if (selectRows.length === 0) {
alert('Please select datas you want to compare!'); alert('Please select datas you want to compare!');
} else { } else {
this.setState({ isShowCompareModal: true }); this.setState({ isShowCompareModal: true });
} }
} };
// close Compare-modal // close Compare-modal
hideCompareModal = (): void => { hideCompareModal = (): void => {
// close modal. clear select rows data, clear selected track // close modal. clear select rows data, clear selected track
this.setState({ isShowCompareModal: false, selectedRowKeys: [], selectRows: [] }); this.setState({ isShowCompareModal: false, selectedRowKeys: [], selectRows: [] });
} };
// open customized trial modal // open customized trial modal
private setCustomizedTrial = (trialId: string, event: React.SyntheticEvent<EventTarget>): void => { private setCustomizedTrial = (trialId: string, event: React.SyntheticEvent<EventTarget>): void => {
...@@ -377,21 +380,21 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -377,21 +380,21 @@ class TableList extends React.Component<TableListProps, TableListState> {
isShowCustomizedModal: true, isShowCustomizedModal: true,
copyTrialId: trialId copyTrialId: trialId
}); });
} };
private closeCustomizedTrial = (): void => { private closeCustomizedTrial = (): void => {
this.setState({ this.setState({
isShowCustomizedModal: false, isShowCustomizedModal: false,
copyTrialId: '' copyTrialId: ''
}); });
} };
private onWindowResize = (): void => { private onWindowResize = (): void => {
this.setState(() => ({ this.setState(() => ({
modalIntermediateHeight: window.innerHeight, modalIntermediateHeight: window.innerHeight,
modalIntermediateWidth: window.innerWidth modalIntermediateWidth: window.innerWidth
})); }));
} };
private onRenderRow: IDetailsListProps['onRenderRow'] = props => { private onRenderRow: IDetailsListProps['onRenderRow'] = props => {
if (props) { if (props) {
...@@ -423,8 +426,8 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -423,8 +426,8 @@ class TableList extends React.Component<TableListProps, TableListState> {
} }
// concat trial all final keys and remove dup "default" val, return list // concat trial all final keys and remove dup "default" val, return list
const finalKeysList = TRIALS.finalKeys().filter(item => item !== 'default'); const finalKeysList = TRIALS.finalKeys().filter(item => item !== 'default');
return (COLUMNPro.concat(parameterStr)).concat(finalKeysList); return COLUMNPro.concat(parameterStr).concat(finalKeysList);
} };
// get IColumn[] // get IColumn[]
// when user click [Add Column] need to use the function // when user click [Add Column] need to use the function
...@@ -474,31 +477,29 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -474,31 +477,29 @@ class TableList extends React.Component<TableListProps, TableListState> {
className: 'detail-table', className: 'detail-table',
onRender: (record: any) => { onRender: (record: any) => {
const trialStatus = record.status; const trialStatus = record.status;
const flag: boolean = (trialStatus === 'RUNNING' || trialStatus === 'UNKNOWN') ? false : true; const flag: boolean = trialStatus === 'RUNNING' || trialStatus === 'UNKNOWN' ? false : true;
return ( return (
<Stack className="detail-button" horizontal> <Stack className='detail-button' horizontal>
{/* see intermediate result graph */} {/* see intermediate result graph */}
<PrimaryButton <PrimaryButton
className="detail-button-operation" className='detail-button-operation'
title="Intermediate" title='Intermediate'
onClick={this.showIntermediateModal.bind(this, record)} onClick={this.showIntermediateModal.bind(this, record)}
> >
{LineChart} {LineChart}
</PrimaryButton> </PrimaryButton>
{/* kill job */} {/* kill job */}
{ {flag ? (
flag <PrimaryButton className='detail-button-operation' disabled={true} title='kill'>
? {blocked}
<PrimaryButton className="detail-button-operation" disabled={true} title="kill"> </PrimaryButton>
{blocked} ) : (
</PrimaryButton> <KillJob trial={record} />
: )}
<KillJob trial={record} />
}
{/* Add a new trial-customized trial */} {/* Add a new trial-customized trial */}
<PrimaryButton <PrimaryButton
className="detail-button-operation" className='detail-button-operation'
title="Customized trial" title='Customized trial'
onClick={this.setCustomizedTrial.bind(this, record.id)} onClick={this.setCustomizedTrial.bind(this, record.id)}
disabled={disabledAddCustomizedTrial} disabled={disabledAddCustomizedTrial}
> >
...@@ -506,10 +507,10 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -506,10 +507,10 @@ class TableList extends React.Component<TableListProps, TableListState> {
</PrimaryButton> </PrimaryButton>
</Stack> </Stack>
); );
}, }
}); });
break; break;
case (result): case result:
// remove SEARCH_SPACE title // remove SEARCH_SPACE title
// const realItem = item.replace(' (search space)', ''); // const realItem = item.replace(' (search space)', '');
showColumn.push({ showColumn.push({
...@@ -519,10 +520,8 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -519,10 +520,8 @@ class TableList extends React.Component<TableListProps, TableListState> {
minWidth: 150, minWidth: 150,
onRender: (record: TableRecord) => { onRender: (record: TableRecord) => {
const eachTrial = TRIALS.getTrial(record.id); const eachTrial = TRIALS.getTrial(record.id);
return ( return <span>{eachTrial.description.parameters[item.replace(' (search space)', '')]}</span>;
<span>{eachTrial.description.parameters[item.replace(' (search space)', '')]}</span> }
);
},
}); });
break; break;
default: default:
...@@ -539,7 +538,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -539,7 +538,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
} }
return ( return (
<TooltipHost content={other}> <TooltipHost content={other}>
<div className="ellipsis">{other}</div> <div className='ellipsis'>{other}</div>
</TooltipHost> </TooltipHost>
); );
} }
...@@ -547,7 +546,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -547,7 +546,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
} }
} }
return showColumn; return showColumn;
} };
componentDidMount(): void { componentDidMount(): void {
window.addEventListener('resize', this.onWindowResize); window.addEventListener('resize', this.onWindowResize);
...@@ -555,14 +554,21 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -555,14 +554,21 @@ class TableList extends React.Component<TableListProps, TableListState> {
} }
componentDidUpdate(prevProps: TableListProps): void { componentDidUpdate(prevProps: TableListProps): void {
if (this.props.columnList !== prevProps.columnList || this.props.tableSource !== prevProps.tableSource || prevProps.trialsUpdateBroadcast !== this.props.trialsUpdateBroadcast) { if (
this.props.columnList !== prevProps.columnList ||
this.props.tableSource !== prevProps.tableSource ||
prevProps.trialsUpdateBroadcast !== this.props.trialsUpdateBroadcast
) {
const { columnList } = this.props; const { columnList } = this.props;
this.setState({ this.setState(
tableColumns: this.initTableColumnList(columnList), {
allColumnList: this.getAllColumnKeys() tableColumns: this.initTableColumnList(columnList),
}, () => { allColumnList: this.getAllColumnKeys()
},
() => {
this.updateData(); this.updateData();
}); }
);
} }
} }
...@@ -571,111 +577,153 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -571,111 +577,153 @@ class TableList extends React.Component<TableListProps, TableListState> {
const tableSource: Array<TableRecord> = this.props.tableSource; const tableSource: Array<TableRecord> = this.props.tableSource;
const { offset, perPage, sortMessage } = this.state; const { offset, perPage, sortMessage } = this.state;
if (sortMessage.field !== '') { if (sortMessage.field !== '') {
tableSource.sort(function (a, b): any { tableSource.sort(function(a, b): any {
if (a[sortMessage.field] === undefined || Object.is(a[sortMessage.field], NaN) || Object.is(a[sortMessage.field], Infinity) || Object.is(a[sortMessage.field], -Infinity) || typeof a[sortMessage.field] === 'object' ) { if (
return 1; a[sortMessage.field] === undefined ||
} Object.is(a[sortMessage.field], NaN) ||
if (b[sortMessage.field] === undefined || Object.is(b[sortMessage.field], NaN) || Object.is(b[sortMessage.field], Infinity) || Object.is(b[sortMessage.field], -Infinity) || typeof b[sortMessage.field] === 'object' ) { Object.is(a[sortMessage.field], Infinity) ||
return -1; Object.is(a[sortMessage.field], -Infinity) ||
} typeof a[sortMessage.field] === 'object'
return (sortMessage.isDescend ? a[sortMessage.field] < b[sortMessage.field] : a[sortMessage.field] > b[sortMessage.field]) ? 1 : -1; ) {
}); return 1;
}
if (
b[sortMessage.field] === undefined ||
Object.is(b[sortMessage.field], NaN) ||
Object.is(b[sortMessage.field], Infinity) ||
Object.is(b[sortMessage.field], -Infinity) ||
typeof b[sortMessage.field] === 'object'
) {
return -1;
}
return (sortMessage.isDescend
? a[sortMessage.field] < b[sortMessage.field]
: a[sortMessage.field] > b[sortMessage.field])
? 1
: -1;
});
} }
const tableSlice = tableSource.slice(offset, offset + perPage) const tableSlice = tableSource.slice(offset, offset + perPage);
const curPageCount = Math.ceil(tableSource.length / perPage) const curPageCount = Math.ceil(tableSource.length / perPage);
this.setState({ this.setState({
tablePerPage: tableSlice, tablePerPage: tableSlice,
pageCount: curPageCount, pageCount: curPageCount
}); });
} }
// update data when click the page index of pagination // update data when click the page index of pagination
handlePageClick = (evt: any): void => { handlePageClick = (evt: any): void => {
const selectedPage = evt.selected; const selectedPage = evt.selected;
const offset = selectedPage * this.state.perPage; const offset = selectedPage * this.state.perPage;
this.setState({ this.setState(
currentPage: selectedPage, {
offset: offset currentPage: selectedPage,
}, () => { offset: offset
this.updateData(); },
}); () => {
} this.updateData();
}
);
};
// update per page items when click the dropdown of pagination // update per page items when click the dropdown of pagination
updatePerPage = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption | undefined): void => { updatePerPage = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption | undefined): void => {
const { pageCount } = this.state; const { pageCount } = this.state;
if (item !== undefined) { if (item !== undefined) {
const currentPerPage = item.key === 'all' ? this.props.tableSource.length: Number(item.key) const currentPerPage = item.key === 'all' ? this.props.tableSource.length : Number(item.key);
const currentPageCount = this.props.tableSource.length <= currentPerPage ? 1 : pageCount const currentPageCount = this.props.tableSource.length <= currentPerPage ? 1 : pageCount;
this.setState({ this.setState(
perPage: currentPerPage, {
offset: 0, perPage: currentPerPage,
currentPage: 0, offset: 0,
pageCount: currentPageCount currentPage: 0,
}, () => { pageCount: currentPageCount
this.updateData(); },
}); () => {
this.updateData();
}
);
} }
} };
render(): React.ReactNode { render(): React.ReactNode {
const { intermediateKey, modalIntermediateWidth, modalIntermediateHeight, const {
tableColumns, allColumnList, isShowColumn, modalVisible, intermediateKey,
selectRows, isShowCompareModal, intermediateOtherKeys, modalIntermediateWidth,
isShowCustomizedModal, copyTrialId, intermediateOption, modalIntermediateHeight,
tableColumns,
allColumnList,
isShowColumn,
modalVisible,
selectRows,
isShowCompareModal,
intermediateOtherKeys,
isShowCustomizedModal,
copyTrialId,
intermediateOption,
tablePerPage tablePerPage
} = this.state; } = this.state;
const { columnList } = this.props; const { columnList } = this.props;
const perPageOptions = [ const perPageOptions = [
{ key: '10', text: '10 items per page'}, { key: '10', text: '10 items per page' },
{ key: '20', text: '20 items per page'}, { key: '20', text: '20 items per page' },
{ key: '50', text: '50 items per page'}, { key: '50', text: '50 items per page' },
{ key: 'all', text: 'All items'}, { key: 'all', text: 'All items' }
]; ];
return ( return (
<Stack> <Stack>
<div id="tableList"> <div id='tableList'>
<DetailsList <DetailsList
columns={tableColumns} columns={tableColumns}
items={tablePerPage} items={tablePerPage}
setKey="set" setKey='set'
compact={true} compact={true}
onRenderRow={this.onRenderRow} onRenderRow={this.onRenderRow}
layoutMode={DetailsListLayoutMode.justified} layoutMode={DetailsListLayoutMode.justified}
selectionMode={SelectionMode.multiple} selectionMode={SelectionMode.multiple}
selection={this.getSelectedRows} selection={this.getSelectedRows}
/> />
<Stack horizontal horizontalAlign="end" verticalAlign="baseline" styles={{root:{padding:10}}} tokens={horizontalGapStackTokens}> <Stack
horizontal
horizontalAlign='end'
verticalAlign='baseline'
styles={{ root: { padding: 10 } }}
tokens={horizontalGapStackTokens}
>
<Dropdown <Dropdown
selectedKey={this.state.perPage === this.props.tableSource.length ? 'all':String(this.state.perPage)} selectedKey={
options={perPageOptions} this.state.perPage === this.props.tableSource.length
onChange={this.updatePerPage} ? 'all'
styles={{dropdown: { width: 150}}}/> : String(this.state.perPage)
}
options={perPageOptions}
onChange={this.updatePerPage}
styles={{ dropdown: { width: 150 } }}
/>
<ReactPaginate <ReactPaginate
previousLabel={"<"} previousLabel={'<'}
nextLabel={">"} nextLabel={'>'}
breakLabel={"..."} breakLabel={'...'}
breakClassName={"break"} breakClassName={'break'}
pageCount={this.state.pageCount} pageCount={this.state.pageCount}
marginPagesDisplayed={2} marginPagesDisplayed={2}
pageRangeDisplayed={2} pageRangeDisplayed={2}
onPageChange={this.handlePageClick} onPageChange={this.handlePageClick}
containerClassName={(this.props.tableSource.length == 0 ? "pagination hidden" : "pagination" )} containerClassName={this.props.tableSource.length == 0 ? 'pagination hidden' : 'pagination'}
subContainerClassName={"pages pagination"} subContainerClassName={'pages pagination'}
disableInitialCallback={false} disableInitialCallback={false}
activeClassName={"active"} activeClassName={'active'}
forcePage={this.state.currentPage} forcePage={this.state.currentPage}
/> />
</Stack> </Stack>
</div> </div>
{/* Intermediate Result Modal */} {/* Intermediate Result Modal */}
<Modal <Modal
...@@ -688,31 +736,26 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -688,31 +736,26 @@ class TableList extends React.Component<TableListProps, TableListState> {
<IconButton <IconButton
styles={iconButtonStyles} styles={iconButtonStyles}
iconProps={{ iconName: 'Cancel' }} iconProps={{ iconName: 'Cancel' }}
ariaLabel="Close popup modal" ariaLabel='Close popup modal'
onClick={this.hideIntermediateModal as any} onClick={this.hideIntermediateModal as any}
/> />
</div> </div>
{ {intermediateOtherKeys.length > 1 ? (
intermediateOtherKeys.length > 1 <Stack horizontalAlign='end' className='selectKeys'>
? <Dropdown
<Stack horizontalAlign="end" className="selectKeys"> className='select'
<Dropdown selectedKey={intermediateKey}
className="select" options={intermediateOtherKeys.map((key, item) => {
selectedKey={intermediateKey} return {
options={ key: key,
intermediateOtherKeys.map((key, item) => { text: intermediateOtherKeys[item]
return { };
key: key, text: intermediateOtherKeys[item] })}
}; onChange={this.selectOtherKeys}
}) />
} </Stack>
onChange={this.selectOtherKeys} ) : null}
/> <div className='intermediate-graph'>
</Stack>
:
null
}
<div className="intermediate-graph">
<ReactEcharts <ReactEcharts
option={intermediateOption} option={intermediateOption}
style={{ style={{
...@@ -721,14 +764,13 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -721,14 +764,13 @@ class TableList extends React.Component<TableListProps, TableListState> {
maxHeight: 534, maxHeight: 534,
padding: 20 padding: 20
}} }}
theme="my_theme" theme='my_theme'
/> />
<div className="xAxis">#Intermediate result</div> <div className='xAxis'>#Intermediate result</div>
</div> </div>
</Modal> </Modal>
{/* Add Column Modal */} {/* Add Column Modal */}
{ {isShowColumn && (
isShowColumn &&
<ChangeColumnComponent <ChangeColumnComponent
hideShowColumnDialog={this.hideShowColumnModal} hideShowColumnDialog={this.hideShowColumnModal}
isHideDialog={!isShowColumn} isHideDialog={!isShowColumn}
...@@ -736,7 +778,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -736,7 +778,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
selectedColumn={columnList} selectedColumn={columnList}
changeColumn={this.props.changeColumn} changeColumn={this.props.changeColumn}
/> />
} )}
{/* compare trials based message */} {/* compare trials based message */}
{isShowCompareModal && <Compare compareStacks={selectRows} cancelFunc={this.hideCompareModal} />} {isShowCompareModal && <Compare compareStacks={selectRows} cancelFunc={this.hideCompareModal} />}
{/* clone trial parameters and could submit a customized trial */} {/* clone trial parameters and could submit a customized trial */}
......
body { body {
margin: 0; margin: 0;
padding: 0; padding: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', font-family:
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', -apple-system,
sans-serif; BlinkMacSystemFont,
-webkit-font-smoothing: antialiased; 'Segoe UI',
-moz-osx-font-smoothing: grayscale; 'Roboto',
line-height: 1; 'Oxygen',
'Ubuntu',
'Cantarell',
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
line-height: 1;
} }
code { code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', font-family:
monospace; source-code-pro,
Menlo,
Monaco,
Consolas,
'Courier New',
monospace;
} }
/* http://meyerweb.com/eric/tools/css/reset/ /* http://meyerweb.com/eric/tools/css/reset/
...@@ -21,46 +35,135 @@ code { ...@@ -21,46 +35,135 @@ code {
License: none (public domain) License: none (public domain)
*/ */
html, body, div, span, applet, object, iframe, html,
h1, h2, h3, h4, h5, h6, p, blockquote, pre, body,
a, abbr, acronym, address, big, cite, code, div,
del, dfn, em, img, ins, kbd, q, s, samp, span,
small, strike, strong, sub, sup, tt, var, applet,
b, u, i, center, object,
dl, dt, dd, ol, ul, li, iframe,
fieldset, form, label, legend, h1,
table, caption, tbody, tfoot, thead, tr, th, td, h2,
article, aside, canvas, details, embed, h3,
figure, figcaption, footer, header, hgroup, h4,
main, menu, nav, output, ruby, section, summary, h5,
time, mark, audio, video { h6,
margin: 0; p,
padding: 0; blockquote,
border: 0; pre,
font: inherit; a,
font-size: 100%; abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
main,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font: inherit;
font-size: 100%;
} }
/* HTML5 display-role reset for older browsers */ /* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, article,
footer, header, hgroup, main, menu, nav, section { aside,
display: block; details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section {
display: block;
} }
/* HTML5 hidden-attribute fix for newer browsers */ /* HTML5 hidden-attribute fix for newer browsers */
*[hidden] { *[hidden] {
display: none; display: none;
} }
ol, ul {
list-style: none; ol,
ul {
list-style: none;
} }
blockquote, q {
quotes: none; blockquote,
q {
quotes: none;
} }
blockquote:before, blockquote:after,
q:before, q:after { blockquote::before,
content: ''; blockquote::after,
content: none; q::before,
q::after {
content: '';
content: none;
} }
table { table {
border-collapse: collapse; border-collapse: collapse;
border-spacing: 0; border-spacing: 0;
} }
...@@ -8,21 +8,19 @@ import './index.css'; ...@@ -8,21 +8,19 @@ import './index.css';
import * as serviceWorker from './serviceWorker'; import * as serviceWorker from './serviceWorker';
ReactDOM.render( ReactDOM.render(
(
<Router> <Router>
<App> <App>
<Switch> <Switch>
<Suspense fallback={null}> <Suspense fallback={null}>
<Route path="/oview" component={Overview} /> <Route path='/oview' component={Overview} />
<Route path="/detail" component={TrialsDetail} /> <Route path='/detail' component={TrialsDetail} />
<Route path="/" render={(): React.ReactNode => <Redirect to={{ pathname: '/oview' }} />} /> <Route path='/' render={(): React.ReactNode => <Redirect to={{ pathname: '/oview' }} />} />
</Suspense> </Suspense>
</Switch> </Switch>
</App> </App>
</Router> </Router>,
), document.getElementById('root')
document.getElementById('root')
); );
// If you want your app to work offline and load faster, you can change // If you want your app to work offline and load faster, you can change
......
declare namespace NodeJS { declare namespace NodeJS {
interface ProcessEnv { interface ProcessEnv {
readonly NODE_ENV: 'development' | 'production' | 'test'; readonly NODE_ENV: 'development' | 'production' | 'test';
readonly PUBLIC_URL: string; readonly PUBLIC_URL: string;
} }
} }
declare module '*.bmp' { declare module '*.bmp' {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.gif' { declare module '*.gif' {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.jpg' { declare module '*.jpg' {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.jpeg' { declare module '*.jpeg' {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.png' { declare module '*.png' {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.webp' { declare module '*.webp' {
...@@ -36,25 +36,25 @@ declare module '*.webp' { ...@@ -36,25 +36,25 @@ declare module '*.webp' {
} }
declare module '*.svg' { declare module '*.svg' {
import * as React from 'react'; import * as React from 'react';
export const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>; export const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.module.css' { declare module '*.module.css' {
const classes: { [key: string]: string }; const classes: { [key: string]: string };
export default classes; export default classes;
} }
declare module '*.module.scss' { declare module '*.module.scss' {
const classes: { [key: string]: string }; const classes: { [key: string]: string };
export default classes; export default classes;
} }
declare module '*.module.sass' { declare module '*.module.sass' {
const classes: { [key: string]: string }; const classes: { [key: string]: string };
export default classes; export default classes;
} }
...@@ -15,15 +15,11 @@ const trialJobStatus = [ ...@@ -15,15 +15,11 @@ const trialJobStatus = [
'SYS_CANCELED', 'SYS_CANCELED',
'EARLY_STOPPED' 'EARLY_STOPPED'
]; ];
const CONTROLTYPE = [ const CONTROLTYPE = ['SEARCH_SPACE', 'TRIAL_CONCURRENCY', 'MAX_EXEC_DURATION'];
'SEARCH_SPACE',
'TRIAL_CONCURRENCY',
'MAX_EXEC_DURATION'
];
const MONACO = { const MONACO = {
readOnly: true, readOnly: true,
automaticLayout: true, automaticLayout: true,
scrollBeyondLastLine: false, scrollBeyondLastLine: false
}; };
const DRAWEROPTION = { const DRAWEROPTION = {
minimap: { enabled: false }, minimap: { enabled: false },
...@@ -34,8 +30,17 @@ const OPERATION = 'Operation'; ...@@ -34,8 +30,17 @@ const OPERATION = 'Operation';
// defatult selected column // defatult selected column
const COLUMN = ['Trial No.', 'ID', 'Duration', 'Status', 'Default', OPERATION]; const COLUMN = ['Trial No.', 'ID', 'Duration', 'Status', 'Default', OPERATION];
// all choice column !dictory final // all choice column !dictory final
const COLUMNPro = ['Trial No.', 'ID', 'Start time', 'End time', 'Duration', 'Status', const COLUMNPro = [
'Intermediate result', 'Default', OPERATION]; 'Trial No.',
'ID',
'Start time',
'End time',
'Duration',
'Status',
'Intermediate result',
'Default',
OPERATION
];
const CONCURRENCYTOOLTIP = 'Trial concurrency is the number of trials running concurrently.'; const CONCURRENCYTOOLTIP = 'Trial concurrency is the number of trials running concurrently.';
const SUPPORTED_SEARCH_SPACE_TYPE = [ const SUPPORTED_SEARCH_SPACE_TYPE = [
'choice', 'choice',
...@@ -53,8 +58,18 @@ const SUPPORTED_SEARCH_SPACE_TYPE = [ ...@@ -53,8 +58,18 @@ const SUPPORTED_SEARCH_SPACE_TYPE = [
]; ];
export { export {
MANAGER_IP, DOWNLOAD_IP, trialJobStatus, COLUMNPro, WEBUIDOC, MANAGER_IP,
CONTROLTYPE, MONACO, COLUMN, DRAWEROPTION, OPERATION, DOWNLOAD_IP,
METRIC_GROUP_UPDATE_THRESHOLD, METRIC_GROUP_UPDATE_SIZE, CONCURRENCYTOOLTIP, trialJobStatus,
COLUMNPro,
WEBUIDOC,
CONTROLTYPE,
MONACO,
COLUMN,
DRAWEROPTION,
OPERATION,
METRIC_GROUP_UPDATE_THRESHOLD,
METRIC_GROUP_UPDATE_SIZE,
CONCURRENCYTOOLTIP,
SUPPORTED_SEARCH_SPACE_TYPE SUPPORTED_SEARCH_SPACE_TYPE
}; };
...@@ -24,7 +24,7 @@ const convertTime = (num: number): string => { ...@@ -24,7 +24,7 @@ const convertTime = (num: number): string => {
return num / 3600 + 'h'; return num / 3600 + 'h';
} else { } else {
const hour = Math.floor(num / 3600); const hour = Math.floor(num / 3600);
const min = Math.floor(num / 60 % 60); const min = Math.floor((num / 60) % 60);
return hour > 0 ? `${hour}h ${min}min` : `${min}min`; return hour > 0 ? `${hour}h ${min}min` : `${min}min`;
} }
}; };
...@@ -35,7 +35,7 @@ const convertDuration = (num: number): string => { ...@@ -35,7 +35,7 @@ const convertDuration = (num: number): string => {
return '0s'; return '0s';
} }
const hour = Math.floor(num / 3600); const hour = Math.floor(num / 3600);
const minute = Math.floor(num / 60 % 60); const minute = Math.floor((num / 60) % 60);
const second = Math.floor(num % 60); const second = Math.floor(num % 60);
const result: string[] = []; const result: string[] = [];
if (hour > 0) { if (hour > 0) {
...@@ -60,7 +60,7 @@ function parseMetrics(metricData: string): any { ...@@ -60,7 +60,7 @@ function parseMetrics(metricData: string): any {
const isArrayType = (list: any): boolean | undefined => { const isArrayType = (list: any): boolean | undefined => {
return Array.isArray(list); return Array.isArray(list);
} };
// get final result value // get final result value
// draw Accuracy point graph // draw Accuracy point graph
...@@ -69,11 +69,11 @@ const getFinalResult = (final?: MetricDataRecord[]): number => { ...@@ -69,11 +69,11 @@ const getFinalResult = (final?: MetricDataRecord[]): number => {
let showDefault = 0; let showDefault = 0;
if (final) { if (final) {
acc = parseMetrics(final[final.length - 1].data); acc = parseMetrics(final[final.length - 1].data);
if (typeof (acc) === 'object' && !isArrayType(acc)) { if (typeof acc === 'object' && !isArrayType(acc)) {
if (acc.default) { if (acc.default) {
showDefault = acc.default; showDefault = acc.default;
} }
} else if (typeof (acc) === 'number') { } else if (typeof acc === 'number') {
showDefault = acc; showDefault = acc;
} else { } else {
showDefault = NaN; showDefault = NaN;
...@@ -94,7 +94,7 @@ const getFinal = (final?: MetricDataRecord[]): FinalType | undefined => { ...@@ -94,7 +94,7 @@ const getFinal = (final?: MetricDataRecord[]): FinalType | undefined => {
if (final) { if (final) {
showDefault = parseMetrics(final[final.length - 1].data); showDefault = parseMetrics(final[final.length - 1].data);
if (typeof showDefault === 'number') { if (typeof showDefault === 'number') {
if(!isNaNorInfinity(showDefault)){ if (!isNaNorInfinity(showDefault)) {
return { default: showDefault }; return { default: showDefault };
} }
} else if (isArrayType(showDefault)) { } else if (isArrayType(showDefault)) {
...@@ -121,7 +121,7 @@ const intermediateGraphOption = (intermediateArr: number[], id: string): any => ...@@ -121,7 +121,7 @@ const intermediateGraphOption = (intermediateArr: number[], id: string): any =>
left: 'center', left: 'center',
textStyle: { textStyle: {
fontSize: 16, fontSize: 16,
color: '#333', color: '#333'
} }
}, },
tooltip: { tooltip: {
...@@ -137,11 +137,13 @@ const intermediateGraphOption = (intermediateArr: number[], id: string): any => ...@@ -137,11 +137,13 @@ const intermediateGraphOption = (intermediateArr: number[], id: string): any =>
data: intermediateArr, data: intermediateArr,
scale: true scale: true
}, },
series: [{ series: [
symbolSize: 6, {
type: 'scatter', symbolSize: 6,
data: intermediateArr type: 'scatter',
}] data: intermediateArr
}
]
}; };
}; };
...@@ -159,7 +161,7 @@ const killJob = (key: number, id: string, status: string, updateList?: Function) ...@@ -159,7 +161,7 @@ const killJob = (key: number, id: string, status: string, updateList?: Function)
alert('Cancel the job successfully'); alert('Cancel the job successfully');
// render the table // render the table
if (updateList) { if (updateList) {
updateList(); // FIXME updateList(); // FIXME
} }
} else { } else {
alert('fail to cancel the job'); alert('fail to cancel the job');
...@@ -180,7 +182,7 @@ const filterByStatus = (item: TableObj): boolean => { ...@@ -180,7 +182,7 @@ const filterByStatus = (item: TableObj): boolean => {
return item.status === 'SUCCEEDED'; return item.status === 'SUCCEEDED';
}; };
// a waittiong trial may havn't start time // a waittiong trial may havn't start time
const filterDuration = (item: TableObj): boolean => { const filterDuration = (item: TableObj): boolean => {
return item.status !== 'WAITING'; return item.status !== 'WAITING';
}; };
...@@ -197,7 +199,7 @@ const downFile = (content: string, fileName: string): void => { ...@@ -197,7 +199,7 @@ const downFile = (content: string, fileName: string): void => {
} }
if (navigator.userAgent.indexOf('Firefox') > -1) { if (navigator.userAgent.indexOf('Firefox') > -1) {
const downTag = document.createElement('a'); const downTag = document.createElement('a');
downTag.addEventListener('click', function () { downTag.addEventListener('click', function() {
downTag.download = fileName; downTag.download = fileName;
downTag.href = URL.createObjectURL(file); downTag.href = URL.createObjectURL(file);
}); });
...@@ -227,7 +229,10 @@ function metricAccuracy(metric: MetricDataRecord): number { ...@@ -227,7 +229,10 @@ function metricAccuracy(metric: MetricDataRecord): number {
function formatAccuracy(accuracy: number): string { function formatAccuracy(accuracy: number): string {
// TODO: how to format NaN? // TODO: how to format NaN?
return accuracy.toFixed(6).replace(/0+$/, '').replace(/\.$/, ''); return accuracy
.toFixed(6)
.replace(/0+$/, '')
.replace(/\.$/, '');
} }
function formatComplexTypeValue(value: any): string | number { function formatComplexTypeValue(value: any): string | number {
...@@ -239,8 +244,21 @@ function formatComplexTypeValue(value: any): string | number { ...@@ -239,8 +244,21 @@ function formatComplexTypeValue(value: any): string | number {
} }
export { export {
convertTime, convertDuration, getFinalResult, getFinal, downFile, convertTime,
intermediateGraphOption, killJob, filterByStatus, filterDuration, convertDuration,
formatAccuracy, formatTimestamp, metricAccuracy, parseMetrics, getFinalResult,
isArrayType, requestAxios, isNaNorInfinity, formatComplexTypeValue getFinal,
downFile,
intermediateGraphOption,
killJob,
filterByStatus,
filterDuration,
formatAccuracy,
formatTimestamp,
metricAccuracy,
parseMetrics,
isArrayType,
requestAxios,
isNaNorInfinity,
formatComplexTypeValue
}; };
...@@ -33,7 +33,7 @@ interface TableObj { ...@@ -33,7 +33,7 @@ interface TableObj {
color?: string; color?: string;
startTime?: number; startTime?: number;
endTime?: number; endTime?: number;
parameters(axes: MultipleAxes): Map<SingleAxis, any>; parameters(axes: MultipleAxes): Map<SingleAxis, any>;
metrics(axes: MultipleAxes): Map<SingleAxis, any>; metrics(axes: MultipleAxes): Map<SingleAxis, any>;
} }
...@@ -208,8 +208,25 @@ interface EventMap { ...@@ -208,8 +208,25 @@ interface EventMap {
} }
export { export {
TableObj, TableRecord, SearchSpace, FinalType, ErrorParameter, Parameters, TableObj,
AccurPoint, DetailAccurPoint, TooltipForIntermediate, TooltipForAccuracy, TableRecord,
Dimobj, ParaObj, Intermedia, MetricDataRecord, TrialJobInfo, ExperimentParams, SearchSpace,
ExperimentProfile, NNIManagerStatus, EventMap, SingleAxis, MultipleAxes FinalType,
ErrorParameter,
Parameters,
AccurPoint,
DetailAccurPoint,
TooltipForIntermediate,
TooltipForAccuracy,
Dimobj,
ParaObj,
Intermedia,
MetricDataRecord,
TrialJobInfo,
ExperimentParams,
ExperimentProfile,
NNIManagerStatus,
EventMap,
SingleAxis,
MultipleAxes
}; };
...@@ -87,17 +87,33 @@ class Experiment { ...@@ -87,17 +87,33 @@ class Experiment {
// set initProfile to prevent page broken // set initProfile to prevent page broken
const initProfile = { const initProfile = {
data: { data: {
"id": "", "revision": 0, "execDuration": 0, id: '',
"logDir": "", "nextSequenceId": 0, revision: 0,
"params": { execDuration: 0,
"authorName": "", "experimentName": "", "trialConcurrency": 0, "maxExecDuration": 0, "maxTrialNum": 0, "searchSpace": "null", logDir: '',
"trainingServicePlatform": "", "tuner": { nextSequenceId: 0,
"builtinTunerName": "TPE", params: {
"classArgs": { "optimize_mode": "" }, "checkpointDir": "" authorName: '',
experimentName: '',
trialConcurrency: 0,
maxExecDuration: 0,
maxTrialNum: 0,
searchSpace: 'null',
trainingServicePlatform: '',
tuner: {
builtinTunerName: 'TPE',
// eslint-disable-next-line @typescript-eslint/camelcase
classArgs: { optimize_mode: '' },
checkpointDir: ''
}, },
"versionCheck": true, "clusterMetaData": [{ "key": "", "value": "" }, versionCheck: true,
{ "key": "", "value": "" }] clusterMetaData: [
}, "startTime": 0, "endTime": 0 { key: '', value: '' },
{ key: '', value: '' }
]
},
startTime: 0,
endTime: 0
} }
}; };
this.profileField = initProfile.data as any; this.profileField = initProfile.data as any;
...@@ -112,7 +128,7 @@ class Experiment { ...@@ -112,7 +128,7 @@ class Experiment {
get optimizeMode(): string { get optimizeMode(): string {
const tuner = this.profile.params.tuner; const tuner = this.profile.params.tuner;
return (tuner && tuner.classArgs && tuner.classArgs.optimize_mode) ? tuner.classArgs.optimize_mode : 'unknown'; return tuner && tuner.classArgs && tuner.classArgs.optimize_mode ? tuner.classArgs.optimize_mode : 'unknown';
} }
get trainingServicePlatform(): string { get trainingServicePlatform(): string {
......
...@@ -3,7 +3,7 @@ import { SUPPORTED_SEARCH_SPACE_TYPE } from '../const'; ...@@ -3,7 +3,7 @@ import { SUPPORTED_SEARCH_SPACE_TYPE } from '../const';
import { formatComplexTypeValue } from '../function'; import { formatComplexTypeValue } from '../function';
function fullNameJoin(prefix: string, name: string): string { function fullNameJoin(prefix: string, name: string): string {
return prefix ? (prefix + '/' + name) : name; return prefix ? prefix + '/' + name : name;
} }
class NumericAxis implements SingleAxis { class NumericAxis implements SingleAxis {
...@@ -86,17 +86,24 @@ export class SearchSpace implements MultipleAxes { ...@@ -86,17 +86,24 @@ export class SearchSpace implements MultipleAxes {
if (searchSpaceSpec === undefined) { if (searchSpaceSpec === undefined) {
return; return;
} }
Object.entries(searchSpaceSpec).forEach((item) => { Object.entries(searchSpaceSpec).forEach(item => {
const key = item[0], spec = item[1] as any; const key = item[0],
spec = item[1] as any;
if (key === '_name') { if (key === '_name') {
return; return;
} else if (['choice', 'layer_choice', 'input_choice'].includes(spec._type)) { } else if (['choice', 'layer_choice', 'input_choice'].includes(spec._type)) {
// ordinal types // ordinal types
if (spec._value && typeof spec._value[0] === 'object') { if (spec._value && typeof spec._value[0] === 'object') {
// nested dimension // nested dimension
this.axes.set(key, new NestedOrdinalAxis(key, fullNameJoin(fullName, key), spec._type, spec._value)); this.axes.set(
key,
new NestedOrdinalAxis(key, fullNameJoin(fullName, key), spec._type, spec._value)
);
} else { } else {
this.axes.set(key, new SimpleOrdinalAxis(key, fullNameJoin(fullName, key), spec._type, spec._value)); this.axes.set(
key,
new SimpleOrdinalAxis(key, fullNameJoin(fullName, key), spec._type, spec._value)
);
} }
} else if (SUPPORTED_SEARCH_SPACE_TYPE.includes(spec._type)) { } else if (SUPPORTED_SEARCH_SPACE_TYPE.includes(spec._type)) {
this.axes.set(key, new NumericAxis(key, fullName + key, spec._type, spec._value)); this.axes.set(key, new NumericAxis(key, fullName + key, spec._type, spec._value));
...@@ -129,7 +136,10 @@ export class SearchSpace implements MultipleAxes { ...@@ -129,7 +136,10 @@ export class SearchSpace implements MultipleAxes {
} }
addingColumns.forEach((value, key) => { addingColumns.forEach((value, key) => {
if (value.every(v => typeof v === 'number')) { if (value.every(v => typeof v === 'number')) {
newSearchSpace.axes.set(key, new NumericAxis(key, key, 'uniform', [Math.min(...value), Math.max(...value)])); newSearchSpace.axes.set(
key,
new NumericAxis(key, key, 'uniform', [Math.min(...value), Math.max(...value)])
);
} else { } else {
newSearchSpace.axes.set(key, new SimpleOrdinalAxis(key, key, 'choice', new Set(value).values())); newSearchSpace.axes.set(key, new SimpleOrdinalAxis(key, key, 'choice', new Set(value).values()));
} }
......
import * as JSON5 from 'json5'; import * as JSON5 from 'json5';
import { MetricDataRecord, TrialJobInfo, TableObj, TableRecord, Parameters, FinalType, MultipleAxes, SingleAxis } from '../interface'; import {
import { getFinal, formatAccuracy, metricAccuracy, parseMetrics, isArrayType, isNaNorInfinity, formatComplexTypeValue } from '../function'; MetricDataRecord,
TrialJobInfo,
TableObj,
TableRecord,
Parameters,
FinalType,
MultipleAxes,
SingleAxis
} from '../interface';
import {
getFinal,
formatAccuracy,
metricAccuracy,
parseMetrics,
isArrayType,
isNaNorInfinity,
formatComplexTypeValue
} from '../function';
/** /**
* Get a structured representation of parameters * Get a structured representation of parameters
...@@ -9,14 +26,17 @@ import { getFinal, formatAccuracy, metricAccuracy, parseMetrics, isArrayType, is ...@@ -9,14 +26,17 @@ import { getFinal, formatAccuracy, metricAccuracy, parseMetrics, isArrayType, is
* @param prefix Current namespace (to make full name for unexpected entries) * @param prefix Current namespace (to make full name for unexpected entries)
* @returns Parsed structured parameters and unexpected entries * @returns Parsed structured parameters and unexpected entries
*/ */
function inferTrialParameters(paramObj: object, space: MultipleAxes, prefix: string = ''): [Map<SingleAxis, any>, Map<string, any>] { function inferTrialParameters(
paramObj: object,
space: MultipleAxes,
prefix: string = ''
): [Map<SingleAxis, any>, Map<string, any>] {
const parameters = new Map<SingleAxis, any>(); const parameters = new Map<SingleAxis, any>();
const unexpectedEntries = new Map<string, any>(); const unexpectedEntries = new Map<string, any>();
for (const [k, v] of Object.entries(paramObj)) { for (const [k, v] of Object.entries(paramObj)) {
// prefix can be a good fallback when corresponding item is not found in namespace // prefix can be a good fallback when corresponding item is not found in namespace
const axisKey = space.axes.get(k); const axisKey = space.axes.get(k);
if (prefix && k === '_name') if (prefix && k === '_name') continue;
continue;
if (axisKey !== undefined) { if (axisKey !== undefined) {
if (typeof v === 'object' && v._name !== undefined && axisKey.nested) { if (typeof v === 'object' && v._name !== undefined && axisKey.nested) {
// nested entry // nested entry
...@@ -93,7 +113,10 @@ class Trial implements TableObj { ...@@ -93,7 +113,10 @@ class Trial implements TableObj {
if (temp !== undefined) { if (temp !== undefined) {
if (isArrayType(parseMetrics(temp.data))) { if (isArrayType(parseMetrics(temp.data))) {
return undefined; return undefined;
} else if (typeof parseMetrics(temp.data) === 'object' && parseMetrics(temp.data).hasOwnProperty('default')) { } else if (
typeof parseMetrics(temp.data) === 'object' &&
parseMetrics(temp.data).hasOwnProperty('default')
) {
return parseMetrics(temp.data).default; return parseMetrics(temp.data).default;
} else if (typeof parseMetrics(temp.data) === 'number') { } else if (typeof parseMetrics(temp.data) === 'number') {
return parseMetrics(temp.data); return parseMetrics(temp.data);
...@@ -182,7 +205,7 @@ class Trial implements TableObj { ...@@ -182,7 +205,7 @@ class Trial implements TableObj {
ret.parameters = getPara; ret.parameters = getPara;
} }
} else { } else {
ret.parameters = { error: 'This trial\'s parameters are not available.' }; ret.parameters = { error: "This trial's parameters are not available." };
} }
if (this.info.logPath !== undefined) { if (this.info.logPath !== undefined) {
ret.logPath = this.info.logPath; ret.logPath = this.info.logPath;
...@@ -294,7 +317,7 @@ class Trial implements TableObj { ...@@ -294,7 +317,7 @@ class Trial implements TableObj {
} }
public updateTrialJobInfo(trialJobInfo: TrialJobInfo): boolean { public updateTrialJobInfo(trialJobInfo: TrialJobInfo): boolean {
const same = (this.infoField && this.infoField.status === trialJobInfo.status); const same = this.infoField && this.infoField.status === trialJobInfo.status;
this.infoField = trialJobInfo; this.infoField = trialJobInfo;
if (trialJobInfo.finalMetricData) { if (trialJobInfo.finalMetricData) {
this.final = trialJobInfo.finalMetricData[trialJobInfo.finalMetricData.length - 1]; this.final = trialJobInfo.finalMetricData[trialJobInfo.finalMetricData.length - 1];
...@@ -312,7 +335,6 @@ class Trial implements TableObj { ...@@ -312,7 +335,6 @@ class Trial implements TableObj {
return `${formatAccuracy(val)} (LATEST)`; return `${formatAccuracy(val)} (LATEST)`;
} else { } else {
return `${formatAccuracy(val)} (FINAL)`; return `${formatAccuracy(val)} (FINAL)`;
} }
} }
} else { } else {
...@@ -321,9 +343,10 @@ class Trial implements TableObj { ...@@ -321,9 +343,10 @@ class Trial implements TableObj {
} }
} }
public formatLatestAccuracy(): string { // TODO: this should be private public formatLatestAccuracy(): string {
// TODO: this should be private
if (this.status === 'SUCCEEDED') { if (this.status === 'SUCCEEDED') {
return (this.accuracy === undefined ? '--' : this.renderNumber(this.accuracy)); return this.accuracy === undefined ? '--' : this.renderNumber(this.accuracy);
} else { } else {
if (this.accuracy !== undefined) { if (this.accuracy !== undefined) {
return this.renderNumber(this.accuracy); return this.renderNumber(this.accuracy);
...@@ -335,7 +358,6 @@ class Trial implements TableObj { ...@@ -335,7 +358,6 @@ class Trial implements TableObj {
return this.renderNumber(metricAccuracy(latest)); return this.renderNumber(metricAccuracy(latest));
} }
} }
} }
} }
......
...@@ -11,7 +11,7 @@ function groupMetricsByTrial(metrics: MetricDataRecord[]): Map<string, MetricDat ...@@ -11,7 +11,7 @@ function groupMetricsByTrial(metrics: MetricDataRecord[]): Map<string, MetricDat
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
ret.get(metric.trialJobId)!.push(metric); ret.get(metric.trialJobId)!.push(metric);
} else { } else {
ret.set(metric.trialJobId, [ metric ]); ret.set(metric.trialJobId, [metric]);
} }
} }
return ret; return ret;
...@@ -91,7 +91,7 @@ class TrialManager { ...@@ -91,7 +91,7 @@ class TrialManager {
if (succeedTrialsList !== undefined && succeedTrialsList[0] !== undefined) { if (succeedTrialsList !== undefined && succeedTrialsList[0] !== undefined) {
return succeedTrialsList[0].finalKeys(); return succeedTrialsList[0].finalKeys();
} else { } else {
return ["default"]; return ['default'];
} }
} }
...@@ -109,7 +109,7 @@ class TrialManager { ...@@ -109,7 +109,7 @@ class TrialManager {
['FAILED', 0], ['FAILED', 0],
['USER_CANCELED', 0], ['USER_CANCELED', 0],
['SYS_CANCELED', 0], ['SYS_CANCELED', 0],
['EARLY_STOPPED', 0], ['EARLY_STOPPED', 0]
]); ]);
for (const trial of this.trials.values()) { for (const trial of this.trials.values()) {
if (trial.initialized()) { if (trial.initialized()) {
...@@ -168,7 +168,6 @@ class TrialManager { ...@@ -168,7 +168,6 @@ class TrialManager {
} }
private async updateInfo(): Promise<boolean> { private async updateInfo(): Promise<boolean> {
let updated = false; let updated = false;
requestAxios(`${MANAGER_IP}/trial-jobs`) requestAxios(`${MANAGER_IP}/trial-jobs`)
.then(data => { .then(data => {
...@@ -235,7 +234,11 @@ class TrialManager { ...@@ -235,7 +234,11 @@ class TrialManager {
return; return;
} }
this.doingBatchUpdate = true; this.doingBatchUpdate = true;
for (let i = 0; i < this.maxSequenceId && this.isMetricdataRangeError === false; i += METRIC_GROUP_UPDATE_SIZE) { for (
let i = 0;
i < this.maxSequenceId && this.isMetricdataRangeError === false;
i += METRIC_GROUP_UPDATE_SIZE
) {
requestAxios(`${MANAGER_IP}/metric-data-range/${i}/${i + METRIC_GROUP_UPDATE_SIZE}`) requestAxios(`${MANAGER_IP}/metric-data-range/${i}/${i + METRIC_GROUP_UPDATE_SIZE}`)
.then(data => { .then(data => {
const updated = this.doUpdateMetrics(data as any, false); const updated = this.doUpdateMetrics(data as any, false);
......
$btnBgcolor: #0071bc; $btnBgcolor: #0071bc;
Button.tableButton{ button.tableButton {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: $btnBgcolor; background: $btnBgcolor;
border-color: $btnBgcolor; border-color: $btnBgcolor;
height: 26px; height: 26px;
font-size: 14px; font-size: 14px;
...@@ -11,17 +11,19 @@ Button.tableButton{ ...@@ -11,17 +11,19 @@ Button.tableButton{
} }
/* kill btn style: delete its own hover style */ /* kill btn style: delete its own hover style */
/* after button click the color not change */ /* after button click the color not change */
Button.tableButton:hover, Button.tableButton:focus{ button.tableButton:hover,
button.tableButton:focus {
background-color: $btnBgcolor; background-color: $btnBgcolor;
border-color: $btnBgcolor; border-color: $btnBgcolor;
} }
Button.changeBtu{ button.changeBtu {
height: 32px; height: 32px;
} }
.ant-input, .ant-select-selection{ .ant-input,
.ant-select-selection {
border-radius: 0 !important; border-radius: 0 !important;
} }
.compare-modal{ .compare-modal {
/* decide modal size */ /* decide modal size */
.ms-Dialog-main{ .ms-Dialog-main {
width: 50%; width: 50%;
min-width: 450px; min-width: 450px;
} }
.ms-Modal-scrollableContent{
.ms-Modal-scrollableContent {
overflow-x: hidden; overflow-x: hidden;
} }
/* compare-md: table style */ /* compare-md: table style */
.flex{ .flex {
display: flex; display: flex;
} }
&-table{
&-table {
width: 92%; width: 92%;
margin: 0 auto; margin: 0 auto;
margin-bottom: 20px; margin-bottom: 20px;
border: 1px solid transparent; border: 1px solid transparent;
overflow: auto hidden; overflow: auto hidden;
color: #333; color: #333;
tr{
tr {
line-height: 30px; line-height: 30px;
} }
tr:nth-of-type(even){
tr:nth-of-type(even) {
background-color: gainsboro; background-color: gainsboro;
} }
.column{
.column {
max-width: 124px; max-width: 124px;
padding-left: 18px; padding-left: 18px;
font-weight: 600; font-weight: 600;
} }
.value{
.value {
max-width: 152px; max-width: 152px;
padding-right: 18px; padding-right: 18px;
text-align: left; text-align: left;
} }
.idList{
.idList {
font-weight: 600; font-weight: 600;
} }
} }
/* compare-md: intermediate graph style */ /* compare-md: intermediate graph style */
&-intermediate{ &-intermediate {
position: relative; position: relative;
.compare-yAxis{
.compare-yAxis {
color: #333; color: #333;
position: absolute; position: absolute;
top: 87%; top: 87%;
left: 45%; left: 45%;
} }
} }
} }
\ No newline at end of file
$color: #f2f2f2; $color: #f2f2f2;
.formatStr{
.formatStr {
border: 1px solid #8f8f8f; border: 1px solid #8f8f8f;
color: #333; color: #333;
padding: 5px 10px; padding: 5px 10px;
background-color: #fff; background-color: #fff;
} }
.format { .format {
.ant-modal-header{ .ant-modal-header {
background-color: $color; background-color: $color;
border-bottom: none; border-bottom: none;
} }
.ant-modal-footer{
.ant-modal-footer {
background-color: $color; background-color: $color;
border-top: none; border-top: none;
} }
.ant-modal-body{
.ant-modal-body {
background-color: $color; background-color: $color;
padding: 10px 24px !important; padding: 10px 24px !important;
} }
......
.iconButtons{ .iconButtons {
margin-top: 12px; margin-top: 12px;
i{
i {
font-size: 16px; font-size: 16px;
color: #fff; color: #fff;
} }
} }
.docIcon{ .docIcon {
i{ i {
font-size: 28px; font-size: 28px;
} }
} }
\ No newline at end of file
.download { .download {
button, button,
button:active, button:active,
button:hover { button:hover {
color: #fff; color: #fff;
border: none; border: none;
} }
} }
.log-tab-body { .log-tab-body {
.refresh { .refresh {
margin-left: 10px; margin-left: 10px;
display: none; display: none;
} }
} }
/* office-fabric-ui */ /* office-fabric-ui */
.ms-Panel-main { .ms-Panel-main {
width: 55%; width: 55%;
background: #fff; background: #fff;
} }
/* log drawer download & close button's row */ /* log drawer download & close button's row */
.buttons { .buttons {
margin-top: 16px; margin-top: 16px;
.close {
text-align: right; .close {
} text-align: right;
}
} }
.logpath{ .logpath {
margin-left: 10px; margin-left: 10px;
font-size: 14px; font-size: 14px;
.logName{
color: #268BD2; .logName {
color: #268bd2;
margin-right: 5px; margin-right: 5px;
} }
.logContent{ .logContent {
color: #333; color: #333;
} }
.error{ .error {
color: #CB4B16; color: #cb4b16;
} }
} }
.logHref:hover{ .logHref:hover {
color: blue; color: blue;
text-decoration: underline; text-decoration: underline;
} }
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