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 {
}
class Duration extends React.Component<DurationProps, DurationState> {
constructor(props: DurationProps) {
super(props);
this.state = {
startDuration: 0, // for record data zoom
endDuration: 100,
durationSource: this.initDuration(this.props.source),
durationSource: this.initDuration(this.props.source)
};
}
initDuration = (source: Array<TableObj>): any => {
......@@ -50,12 +47,15 @@ class Duration extends React.Component<DurationProps, DurationState> {
axisPointer: {
type: 'shadow'
},
formatter: (data: any): React.ReactNode => (
formatter: (data: any): React.ReactNode =>
'<div>' +
'<div>Trial No.: ' + data[0].dataIndex + '</div>' +
'<div>Duration: ' + convertDuration(data[0].data) + '</div>' +
'<div>Trial No.: ' +
data[0].dataIndex +
'</div>' +
'<div>Duration: ' +
convertDuration(data[0].data) +
'</div>' +
'</div>'
),
},
grid: {
bottom: '3%',
......@@ -71,11 +71,11 @@ class Duration extends React.Component<DurationProps, DurationState> {
filterMode: 'empty',
start: 0,
end: 100
},
}
],
xAxis: {
name: 'Time/s',
type: 'value',
type: 'value'
},
yAxis: {
name: 'Trial No.',
......@@ -85,12 +85,14 @@ class Duration extends React.Component<DurationProps, DurationState> {
padding: [0, 0, 0, 30]
}
},
series: [{
series: [
{
type: 'bar',
data: trialTime
}]
};
}
]
};
};
getOption = (dataObj: Runtrial): any => {
const { startDuration, endDuration } = this.state;
......@@ -100,12 +102,15 @@ class Duration extends React.Component<DurationProps, DurationState> {
axisPointer: {
type: 'shadow'
},
formatter: (data: any): React.ReactNode => (
formatter: (data: any): React.ReactNode =>
'<div>' +
'<div>Trial No.: ' + data[0].dataIndex + '</div>' +
'<div>Duration: ' + convertDuration(data[0].data) + '</div>' +
'<div>Trial No.: ' +
data[0].dataIndex +
'</div>' +
'<div>Duration: ' +
convertDuration(data[0].data) +
'</div>' +
'</div>'
),
},
grid: {
bottom: '3%',
......@@ -121,11 +126,11 @@ class Duration extends React.Component<DurationProps, DurationState> {
filterMode: 'empty',
start: startDuration,
end: endDuration
},
}
],
xAxis: {
name: 'Time',
type: 'value',
type: 'value'
},
yAxis: {
name: 'Trial',
......@@ -135,12 +140,14 @@ class Duration extends React.Component<DurationProps, DurationState> {
padding: [0, 0, 0, 30]
}
},
series: [{
series: [
{
type: 'bar',
data: dataObj.trialTime
}]
};
}
]
};
};
drawDurationGraph = (source: Array<TableObj>): void => {
// why this function run two times when props changed?
......@@ -160,7 +167,7 @@ class Duration extends React.Component<DurationProps, DurationState> {
this.setState({
durationSource: this.getOption(trialRun[0])
});
}
};
componentDidMount(): void {
const { source } = this.props;
......@@ -178,13 +185,13 @@ class Duration extends React.Component<DurationProps, DurationState> {
render(): React.ReactNode {
const { durationSource } = this.state;
const onEvents = { 'dataZoom': this.durationDataZoom };
const onEvents = { dataZoom: this.durationDataZoom };
return (
<div>
<ReactEcharts
option={durationSource}
style={{ width: '94%', height: 412, margin: '0 auto', marginTop: 15 }}
theme="my_theme"
theme='my_theme'
notMerge={true} // update now
onEvents={onEvents}
/>
......@@ -195,11 +202,11 @@ class Duration extends React.Component<DurationProps, DurationState> {
private durationDataZoom = (e: EventMap): void => {
if (e.batch !== undefined) {
this.setState(() => ({
startDuration: (e.batch[0].start !== null ? e.batch[0].start : 0),
endDuration: (e.batch[0].end !== null ? e.batch[0].end : 100)
startDuration: e.batch[0].start !== null ? e.batch[0].start : 0,
endDuration: e.batch[0].end !== null ? e.batch[0].end : 100
}));
}
}
};
}
export default Duration;
......@@ -28,7 +28,6 @@ interface IntermediateProps {
}
class Intermediate extends React.Component<IntermediateProps, IntermediateState> {
static intervalMediate = 1;
public pointInput!: HTMLInputElement | null;
public minValInput!: HTMLInputElement | null;
......@@ -68,7 +67,9 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
});
});
// 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[] = [];
// max length
const length = trialIntermediate[0].data.length;
......@@ -84,27 +85,35 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
tooltip: {
trigger: 'item',
enterable: true,
position: function (point: number[], data: TooltipForIntermediate): number[] {
position: function(point: number[], data: TooltipForIntermediate): number[] {
if (data.dataIndex < length / 2) {
return [point[0], 80];
} else {
return [point[0] - 300, 80];
}
},
formatter: function (data: TooltipForIntermediate): React.ReactNode {
formatter: function(data: TooltipForIntermediate): React.ReactNode {
const trialId = data.seriesName;
let obj = {};
const temp = trialIntermediate.find(key => key.name === trialId);
if (temp !== undefined) {
obj = temp.hyperPara;
}
return '<div class="tooldetailAccuracy">' +
'<div>Trial ID: ' + trialId + '</div>' +
'<div>Intermediate: ' + data.data + '</div>' +
return (
'<div class="tooldetailAccuracy">' +
'<div>Trial ID: ' +
trialId +
'</div>' +
'<div>Intermediate: ' +
data.data +
'</div>' +
'<div>Parameters: ' +
'<pre>' + JSON.stringify(obj, null, 4) + '</pre>' +
'<pre>' +
JSON.stringify(obj, null, 4) +
'</pre>' +
'</div>' +
'</div>';
'</div>'
);
}
},
grid: {
......@@ -121,7 +130,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
yAxis: {
type: 'value',
name: 'Metric',
scale: true,
scale: true
},
dataZoom: [
{
......@@ -147,7 +156,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
},
xAxis: {
type: 'category',
boundaryGap: false,
boundaryGap: false
},
yAxis: {
type: 'value',
......@@ -156,7 +165,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
};
this.setState({ interSource: nullData });
}
}
};
// confirm btn function [filter data]
filterLines = (): void => {
......@@ -198,14 +207,14 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
const counts = this.state.clickCounts + 1;
this.setState({ isLoadconfirmBtn: false, clickCounts: counts });
});
}
};
switchTurn = (ev: React.MouseEvent<HTMLElement>, checked?: boolean): void => {
this.setState({ isFilter: checked });
if (checked === false) {
this.drawIntermediate(this.props.source);
}
}
};
componentDidMount(): void {
const { source } = this.props;
......@@ -235,56 +244,47 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
render(): React.ReactNode {
const { interSource, isLoadconfirmBtn, isFilter } = this.state;
const IntermediateEvents = { 'dataZoom': this.intermediateDataZoom };
const IntermediateEvents = { dataZoom: this.intermediateDataZoom };
return (
<div>
{/* style in para.scss */}
<Stack horizontal horizontalAlign="end" tokens={stackTokens} className="meline intermediate">
{
isFilter
?
<Stack horizontal horizontalAlign='end' tokens={stackTokens} className='meline intermediate'>
{isFilter ? (
<div>
<span className="filter-x"># Intermediate result</span>
<span className='filter-x'># Intermediate result</span>
<input
// placeholder="point"
ref={(input): any => this.pointInput = input}
className="strange"
ref={(input): any => (this.pointInput = input)}
className='strange'
/>
<span>Metric range</span>
<input
// placeholder="range"
ref={(input): any => this.minValInput = input}
ref={(input): any => (this.minValInput = input)}
/>
<span className="hyphen">-</span>
<span className='hyphen'>-</span>
<input
// placeholder="range"
ref={(input): any => this.maxValInput = input}
/>
<PrimaryButton
text="Confirm"
onClick={this.filterLines}
disabled={isLoadconfirmBtn}
ref={(input): any => (this.maxValInput = input)}
/>
<PrimaryButton text='Confirm' onClick={this.filterLines} disabled={isLoadconfirmBtn} />
</div>
:
null
}
) : null}
{/* filter message */}
<Stack horizontal className="filter-toggle">
<Stack horizontal className='filter-toggle'>
<span>Filter</span>
<Toggle onChange={this.switchTurn} />
</Stack>
</Stack>
<div className="intermediate-graph">
<div className='intermediate-graph'>
<ReactEcharts
option={interSource}
style={{ width: '100%', height: 400, margin: '0 auto' }}
notMerge={true} // update now
onEvents={IntermediateEvents}
/>
<div className="xAxis"># Intermediate result</div>
<div className='xAxis'># Intermediate result</div>
</div>
</div>
);
......@@ -293,11 +293,11 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
private intermediateDataZoom = (e: EventMap): void => {
if (e.batch !== undefined) {
this.setState(() => ({
startMediaY: (e.batch[0].start !== null ? e.batch[0].start : 0),
endMediaY: (e.batch[0].end !== null ? e.batch[0].end : 100)
startMediaY: e.batch[0].start !== null ? e.batch[0].start : 0,
endMediaY: e.batch[0].end !== null ? e.batch[0].end : 100
}));
}
}
};
}
export default Intermediate;
......@@ -24,7 +24,6 @@ interface ParaProps {
}
class Para extends React.Component<ParaProps, ParaState> {
private paraRef = React.createRef<HTMLDivElement>();
private pcs: any;
......@@ -57,7 +56,7 @@ class Para extends React.Component<ParaProps, ParaState> {
this.renderParallelCoordinates();
});
}
}
};
// select all final keys
updateEntries = (event: React.FormEvent<HTMLDivElement>, item: any): void => {
......@@ -66,7 +65,7 @@ class Para extends React.Component<ParaProps, ParaState> {
this.renderParallelCoordinates();
});
}
}
};
componentDidMount(): void {
this.renderParallelCoordinates();
......@@ -86,8 +85,8 @@ class Para extends React.Component<ParaProps, ParaState> {
const { selectedPercent, noChart } = this.state;
return (
<div className="parameter">
<Stack horizontal className="para-filter" horizontalAlign="end">
<div className='parameter'>
<Stack horizontal className='para-filter' horizontalAlign='end'>
<Dropdown
selectedKey={selectedPercent}
onChange={this.percentNum}
......@@ -95,15 +94,15 @@ class Para extends React.Component<ParaProps, ParaState> {
{ key: '0.01', text: 'Top 1%' },
{ key: '0.05', text: 'Top 5%' },
{ key: '0.2', text: 'Top 20%' },
{ key: '1', text: 'Top 100%' },
{ key: '1', text: 'Top 100%' }
]}
styles={{ dropdown: { width: 120 } }}
className="para-filter-percent"
className='para-filter-percent'
/>
{this.finalKeysDropdown()}
</Stack>
<div className="parcoords" style={this.chartMulineStyle} ref={this.paraRef}/>
{noChart && <div className="nodata">No data</div>}
<div className='parcoords' style={this.chartMulineStyle} ref={this.paraRef} />
{noChart && <div className='nodata'>No data</div>}
</div>
);
}
......@@ -116,18 +115,19 @@ class Para extends React.Component<ParaProps, ParaState> {
const finalKeysDropdown: any = [];
TRIALS.finalKeys().forEach(item => {
finalKeysDropdown.push({
key: item, text: item
key: item,
text: item
});
});
return (
<div>
<span className="para-filter-text para-filter-middle">Metrics</span>
<span className='para-filter-text para-filter-middle'>Metrics</span>
<Dropdown
selectedKey={primaryMetricKey}
options={finalKeysDropdown}
onChange={this.updateEntries}
styles={{ root: { width: 150, display: 'inline-block' } }}
className="para-filter-percent"
className='para-filter-percent'
/>
</div>
);
......@@ -150,13 +150,17 @@ class Para extends React.Component<ParaProps, ParaState> {
let convertedTrials = this.getTrialsAsObjectList(inferredSearchSpace, inferredMetricSpace);
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
for (const [k, v] of inferredSearchSpace.axes) {
dimensions.push([k, {
dimensions.push([
k,
{
type: 'number',
yscale: this.convertToD3Scale(v)
}]);
}
]);
}
for (const [k, v] of inferredMetricSpace.axes) {
const scale = this.convertToD3Scale(v);
......@@ -164,7 +168,7 @@ class Para extends React.Component<ParaProps, ParaState> {
// set color for primary metrics
// `colorScale` is used to produce a color range, while `scale` is to produce a pixel range
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
if (percent != 1) {
const keptTrialNum = Math.max(Math.ceil(convertedTrials.length * percent), 1);
......@@ -182,17 +186,21 @@ class Para extends React.Component<ParaProps, ParaState> {
scale.range([0, 1]); // fake a range to perform invert
const [scaleMin, scaleMax] = scale.domain();
const pivot = scale.invert(0.5);
scale.domain([scaleMin, pivot, scaleMax])
scale
.domain([scaleMin, pivot, scaleMax])
.range(['#90EE90', '#FFC400', '#CA0000'])
.interpolate(d3.interpolateHsl);
};
assignColors(colorScale);
colorDim = k;
}
dimensions.push([k, {
dimensions.push([
k,
{
type: 'number',
yscale: scale
}]);
}
]);
}
if (convertedTrials.length === 0 || dimensions.length <= 1) {
......@@ -203,13 +211,15 @@ class Para extends React.Component<ParaProps, ParaState> {
if (firstRun) {
this.pcs = ParCoords()(this.paraRef.current);
}
this.pcs.data(convertedTrials)
this.pcs
.data(convertedTrials)
.dimensions(dimensions.reduce((obj, entry) => ({ ...obj, [entry[0]]: entry[1] }), {}));
if (firstRun) {
this.pcs.margin(this.innerChartMargins)
this.pcs
.margin(this.innerChartMargins)
.alphaOnBrushed(0.2)
.smoothness(0.1)
.brushMode("1D-axes")
.brushMode('1D-axes')
.reorderable()
.interactive();
}
......@@ -228,7 +238,7 @@ class Para extends React.Component<ParaProps, ParaState> {
return succeededTrials.map(s => {
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 = {};
for (const [k, v] of entries) {
ret[k.fullName] = v;
......@@ -247,20 +257,26 @@ class Para extends React.Component<ParaProps, ParaState> {
private convertToD3Scale(axis: SingleAxis, initRange: boolean = true): any {
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];
};
const padLog = ([x0, x1], k = 0.1): [number, number] => {
const [y0, y1] = padLinear([Math.log(x0), Math.log(x1)], k);
return [Math.exp(y0), Math.exp(y1)];
}
};
let scaleInst: any = undefined;
if (axis.scale === 'ordinal') {
if (axis.nested) {
// 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 {
scaleInst = d3.scalePoint().domain(axis.domain).padding(0.2);
scaleInst = d3
.scalePoint()
.domain(axis.domain)
.padding(0.2);
}
} else if (axis.scale === 'log') {
scaleInst = d3.scaleLog().domain(padLog(axis.domain));
......
......@@ -3,8 +3,17 @@ body {
padding: 0;
width: 100%;
height: 100%;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
font-family:
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
'Roboto',
'Oxygen',
'Ubuntu',
'Cantarell',
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
......@@ -12,7 +21,12 @@ body {
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
font-family:
source-code-pro,
Menlo,
Monaco,
Consolas,
'Courier New',
monospace;
}
......@@ -21,45 +35,134 @@ code {
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, 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 {
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
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 */
article, aside, details, figcaption, figure,
footer, header, hgroup, main, menu, nav, section {
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section {
display: block;
}
/* HTML5 hidden-attribute fix for newer browsers */
*[hidden] {
display: none;
}
ol, ul {
ol,
ul {
list-style: none;
}
blockquote, q {
blockquote,
q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
blockquote::before,
blockquote::after,
q::before,
q::after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
......
......@@ -8,20 +8,18 @@ import './index.css';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
(
<Router>
<App>
<Switch>
<Suspense fallback={null}>
<Route path="/oview" component={Overview} />
<Route path="/detail" component={TrialsDetail} />
<Route path="/" render={(): React.ReactNode => <Redirect to={{ pathname: '/oview' }} />} />
<Route path='/oview' component={Overview} />
<Route path='/detail' component={TrialsDetail} />
<Route path='/' render={(): React.ReactNode => <Redirect to={{ pathname: '/oview' }} />} />
</Suspense>
</Switch>
</App>
</Router>
</Router>,
),
document.getElementById('root')
);
......
......@@ -15,15 +15,11 @@ const trialJobStatus = [
'SYS_CANCELED',
'EARLY_STOPPED'
];
const CONTROLTYPE = [
'SEARCH_SPACE',
'TRIAL_CONCURRENCY',
'MAX_EXEC_DURATION'
];
const CONTROLTYPE = ['SEARCH_SPACE', 'TRIAL_CONCURRENCY', 'MAX_EXEC_DURATION'];
const MONACO = {
readOnly: true,
automaticLayout: true,
scrollBeyondLastLine: false,
scrollBeyondLastLine: false
};
const DRAWEROPTION = {
minimap: { enabled: false },
......@@ -34,8 +30,17 @@ const OPERATION = 'Operation';
// defatult selected column
const COLUMN = ['Trial No.', 'ID', 'Duration', 'Status', 'Default', OPERATION];
// all choice column !dictory final
const COLUMNPro = ['Trial No.', 'ID', 'Start time', 'End time', 'Duration', 'Status',
'Intermediate result', 'Default', OPERATION];
const COLUMNPro = [
'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 SUPPORTED_SEARCH_SPACE_TYPE = [
'choice',
......@@ -53,8 +58,18 @@ const SUPPORTED_SEARCH_SPACE_TYPE = [
];
export {
MANAGER_IP, DOWNLOAD_IP, trialJobStatus, COLUMNPro, WEBUIDOC,
CONTROLTYPE, MONACO, COLUMN, DRAWEROPTION, OPERATION,
METRIC_GROUP_UPDATE_THRESHOLD, METRIC_GROUP_UPDATE_SIZE, CONCURRENCYTOOLTIP,
MANAGER_IP,
DOWNLOAD_IP,
trialJobStatus,
COLUMNPro,
WEBUIDOC,
CONTROLTYPE,
MONACO,
COLUMN,
DRAWEROPTION,
OPERATION,
METRIC_GROUP_UPDATE_THRESHOLD,
METRIC_GROUP_UPDATE_SIZE,
CONCURRENCYTOOLTIP,
SUPPORTED_SEARCH_SPACE_TYPE
};
......@@ -24,7 +24,7 @@ const convertTime = (num: number): string => {
return num / 3600 + 'h';
} else {
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`;
}
};
......@@ -35,7 +35,7 @@ const convertDuration = (num: number): string => {
return '0s';
}
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 result: string[] = [];
if (hour > 0) {
......@@ -60,7 +60,7 @@ function parseMetrics(metricData: string): any {
const isArrayType = (list: any): boolean | undefined => {
return Array.isArray(list);
}
};
// get final result value
// draw Accuracy point graph
......@@ -69,11 +69,11 @@ const getFinalResult = (final?: MetricDataRecord[]): number => {
let showDefault = 0;
if (final) {
acc = parseMetrics(final[final.length - 1].data);
if (typeof (acc) === 'object' && !isArrayType(acc)) {
if (typeof acc === 'object' && !isArrayType(acc)) {
if (acc.default) {
showDefault = acc.default;
}
} else if (typeof (acc) === 'number') {
} else if (typeof acc === 'number') {
showDefault = acc;
} else {
showDefault = NaN;
......@@ -94,7 +94,7 @@ const getFinal = (final?: MetricDataRecord[]): FinalType | undefined => {
if (final) {
showDefault = parseMetrics(final[final.length - 1].data);
if (typeof showDefault === 'number') {
if(!isNaNorInfinity(showDefault)){
if (!isNaNorInfinity(showDefault)) {
return { default: showDefault };
}
} else if (isArrayType(showDefault)) {
......@@ -121,7 +121,7 @@ const intermediateGraphOption = (intermediateArr: number[], id: string): any =>
left: 'center',
textStyle: {
fontSize: 16,
color: '#333',
color: '#333'
}
},
tooltip: {
......@@ -137,11 +137,13 @@ const intermediateGraphOption = (intermediateArr: number[], id: string): any =>
data: intermediateArr,
scale: true
},
series: [{
series: [
{
symbolSize: 6,
type: 'scatter',
data: intermediateArr
}]
}
]
};
};
......@@ -197,7 +199,7 @@ const downFile = (content: string, fileName: string): void => {
}
if (navigator.userAgent.indexOf('Firefox') > -1) {
const downTag = document.createElement('a');
downTag.addEventListener('click', function () {
downTag.addEventListener('click', function() {
downTag.download = fileName;
downTag.href = URL.createObjectURL(file);
});
......@@ -227,7 +229,10 @@ function metricAccuracy(metric: MetricDataRecord): number {
function formatAccuracy(accuracy: number): string {
// 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 {
......@@ -239,8 +244,21 @@ function formatComplexTypeValue(value: any): string | number {
}
export {
convertTime, convertDuration, getFinalResult, getFinal, downFile,
intermediateGraphOption, killJob, filterByStatus, filterDuration,
formatAccuracy, formatTimestamp, metricAccuracy, parseMetrics,
isArrayType, requestAxios, isNaNorInfinity, formatComplexTypeValue
convertTime,
convertDuration,
getFinalResult,
getFinal,
downFile,
intermediateGraphOption,
killJob,
filterByStatus,
filterDuration,
formatAccuracy,
formatTimestamp,
metricAccuracy,
parseMetrics,
isArrayType,
requestAxios,
isNaNorInfinity,
formatComplexTypeValue
};
......@@ -208,8 +208,25 @@ interface EventMap {
}
export {
TableObj, TableRecord, SearchSpace, FinalType, ErrorParameter, Parameters,
AccurPoint, DetailAccurPoint, TooltipForIntermediate, TooltipForAccuracy,
Dimobj, ParaObj, Intermedia, MetricDataRecord, TrialJobInfo, ExperimentParams,
ExperimentProfile, NNIManagerStatus, EventMap, SingleAxis, MultipleAxes
TableObj,
TableRecord,
SearchSpace,
FinalType,
ErrorParameter,
Parameters,
AccurPoint,
DetailAccurPoint,
TooltipForIntermediate,
TooltipForAccuracy,
Dimobj,
ParaObj,
Intermedia,
MetricDataRecord,
TrialJobInfo,
ExperimentParams,
ExperimentProfile,
NNIManagerStatus,
EventMap,
SingleAxis,
MultipleAxes
};
......@@ -87,17 +87,33 @@ class Experiment {
// set initProfile to prevent page broken
const initProfile = {
data: {
"id": "", "revision": 0, "execDuration": 0,
"logDir": "", "nextSequenceId": 0,
"params": {
"authorName": "", "experimentName": "", "trialConcurrency": 0, "maxExecDuration": 0, "maxTrialNum": 0, "searchSpace": "null",
"trainingServicePlatform": "", "tuner": {
"builtinTunerName": "TPE",
"classArgs": { "optimize_mode": "" }, "checkpointDir": ""
id: '',
revision: 0,
execDuration: 0,
logDir: '',
nextSequenceId: 0,
params: {
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": "" },
{ "key": "", "value": "" }]
}, "startTime": 0, "endTime": 0
versionCheck: true,
clusterMetaData: [
{ key: '', value: '' },
{ key: '', value: '' }
]
},
startTime: 0,
endTime: 0
}
};
this.profileField = initProfile.data as any;
......@@ -112,7 +128,7 @@ class Experiment {
get optimizeMode(): string {
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 {
......
......@@ -3,7 +3,7 @@ import { SUPPORTED_SEARCH_SPACE_TYPE } from '../const';
import { formatComplexTypeValue } from '../function';
function fullNameJoin(prefix: string, name: string): string {
return prefix ? (prefix + '/' + name) : name;
return prefix ? prefix + '/' + name : name;
}
class NumericAxis implements SingleAxis {
......@@ -86,17 +86,24 @@ export class SearchSpace implements MultipleAxes {
if (searchSpaceSpec === undefined) {
return;
}
Object.entries(searchSpaceSpec).forEach((item) => {
const key = item[0], spec = item[1] as any;
Object.entries(searchSpaceSpec).forEach(item => {
const key = item[0],
spec = item[1] as any;
if (key === '_name') {
return;
} else if (['choice', 'layer_choice', 'input_choice'].includes(spec._type)) {
// ordinal types
if (spec._value && typeof spec._value[0] === 'object') {
// 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 {
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)) {
this.axes.set(key, new NumericAxis(key, fullName + key, spec._type, spec._value));
......@@ -129,7 +136,10 @@ export class SearchSpace implements MultipleAxes {
}
addingColumns.forEach((value, key) => {
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 {
newSearchSpace.axes.set(key, new SimpleOrdinalAxis(key, key, 'choice', new Set(value).values()));
}
......
import * as JSON5 from 'json5';
import { MetricDataRecord, TrialJobInfo, TableObj, TableRecord, Parameters, FinalType, MultipleAxes, SingleAxis } from '../interface';
import { getFinal, formatAccuracy, metricAccuracy, parseMetrics, isArrayType, isNaNorInfinity, formatComplexTypeValue } from '../function';
import {
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
......@@ -9,14 +26,17 @@ import { getFinal, formatAccuracy, metricAccuracy, parseMetrics, isArrayType, is
* @param prefix Current namespace (to make full name for 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 unexpectedEntries = new Map<string, any>();
for (const [k, v] of Object.entries(paramObj)) {
// prefix can be a good fallback when corresponding item is not found in namespace
const axisKey = space.axes.get(k);
if (prefix && k === '_name')
continue;
if (prefix && k === '_name') continue;
if (axisKey !== undefined) {
if (typeof v === 'object' && v._name !== undefined && axisKey.nested) {
// nested entry
......@@ -93,7 +113,10 @@ class Trial implements TableObj {
if (temp !== undefined) {
if (isArrayType(parseMetrics(temp.data))) {
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;
} else if (typeof parseMetrics(temp.data) === 'number') {
return parseMetrics(temp.data);
......@@ -182,7 +205,7 @@ class Trial implements TableObj {
ret.parameters = getPara;
}
} 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) {
ret.logPath = this.info.logPath;
......@@ -294,7 +317,7 @@ class Trial implements TableObj {
}
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;
if (trialJobInfo.finalMetricData) {
this.final = trialJobInfo.finalMetricData[trialJobInfo.finalMetricData.length - 1];
......@@ -312,7 +335,6 @@ class Trial implements TableObj {
return `${formatAccuracy(val)} (LATEST)`;
} else {
return `${formatAccuracy(val)} (FINAL)`;
}
}
} else {
......@@ -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') {
return (this.accuracy === undefined ? '--' : this.renderNumber(this.accuracy));
return this.accuracy === undefined ? '--' : this.renderNumber(this.accuracy);
} else {
if (this.accuracy !== undefined) {
return this.renderNumber(this.accuracy);
......@@ -335,7 +358,6 @@ class Trial implements TableObj {
return this.renderNumber(metricAccuracy(latest));
}
}
}
}
......
......@@ -11,7 +11,7 @@ function groupMetricsByTrial(metrics: MetricDataRecord[]): Map<string, MetricDat
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
ret.get(metric.trialJobId)!.push(metric);
} else {
ret.set(metric.trialJobId, [ metric ]);
ret.set(metric.trialJobId, [metric]);
}
}
return ret;
......@@ -91,7 +91,7 @@ class TrialManager {
if (succeedTrialsList !== undefined && succeedTrialsList[0] !== undefined) {
return succeedTrialsList[0].finalKeys();
} else {
return ["default"];
return ['default'];
}
}
......@@ -109,7 +109,7 @@ class TrialManager {
['FAILED', 0],
['USER_CANCELED', 0],
['SYS_CANCELED', 0],
['EARLY_STOPPED', 0],
['EARLY_STOPPED', 0]
]);
for (const trial of this.trials.values()) {
if (trial.initialized()) {
......@@ -168,7 +168,6 @@ class TrialManager {
}
private async updateInfo(): Promise<boolean> {
let updated = false;
requestAxios(`${MANAGER_IP}/trial-jobs`)
.then(data => {
......@@ -235,7 +234,11 @@ class TrialManager {
return;
}
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}`)
.then(data => {
const updated = this.doUpdateMetrics(data as any, false);
......
$btnBgcolor: #0071bc;
Button.tableButton{
button.tableButton {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: $btnBgcolor;
border-color: $btnBgcolor;
......@@ -11,17 +11,19 @@ Button.tableButton{
}
/* kill btn style: delete its own hover style */
/* after button click the color not change */
Button.tableButton:hover, Button.tableButton:focus{
button.tableButton:hover,
button.tableButton:focus {
background-color: $btnBgcolor;
border-color: $btnBgcolor;
}
Button.changeBtu{
button.changeBtu {
height: 32px;
}
.ant-input, .ant-select-selection{
.ant-input,
.ant-select-selection {
border-radius: 0 !important;
}
.compare-modal{
.compare-modal {
/* decide modal size */
.ms-Dialog-main{
.ms-Dialog-main {
width: 50%;
min-width: 450px;
}
.ms-Modal-scrollableContent{
.ms-Modal-scrollableContent {
overflow-x: hidden;
}
/* compare-md: table style */
.flex{
.flex {
display: flex;
}
&-table{
&-table {
width: 92%;
margin: 0 auto;
margin-bottom: 20px;
border: 1px solid transparent;
overflow: auto hidden;
color: #333;
tr{
tr {
line-height: 30px;
}
tr:nth-of-type(even){
tr:nth-of-type(even) {
background-color: gainsboro;
}
.column{
.column {
max-width: 124px;
padding-left: 18px;
font-weight: 600;
}
.value{
.value {
max-width: 152px;
padding-right: 18px;
text-align: left;
}
.idList{
.idList {
font-weight: 600;
}
}
/* compare-md: intermediate graph style */
&-intermediate{
&-intermediate {
position: relative;
.compare-yAxis{
.compare-yAxis {
color: #333;
position: absolute;
top: 87%;
......
$color: #f2f2f2;
.formatStr{
.formatStr {
border: 1px solid #8f8f8f;
color: #333;
padding: 5px 10px;
......@@ -7,15 +8,17 @@ $color: #f2f2f2;
}
.format {
.ant-modal-header{
.ant-modal-header {
background-color: $color;
border-bottom: none;
}
.ant-modal-footer{
.ant-modal-footer {
background-color: $color;
border-top: none;
}
.ant-modal-body{
.ant-modal-body {
background-color: $color;
padding: 10px 24px !important;
}
......
.iconButtons{
.iconButtons {
margin-top: 12px;
i{
i {
font-size: 16px;
color: #fff;
}
}
.docIcon{
i{
.docIcon {
i {
font-size: 28px;
}
}
......@@ -23,6 +23,7 @@
/* log drawer download & close button's row */
.buttons {
margin-top: 16px;
.close {
text-align: right;
}
......
.logpath{
.logpath {
margin-left: 10px;
font-size: 14px;
.logName{
color: #268BD2;
.logName {
color: #268bd2;
margin-right: 5px;
}
.logContent{
.logContent {
color: #333;
}
.error{
color: #CB4B16;
.error {
color: #cb4b16;
}
}
.logHref:hover{
.logHref:hover {
color: blue;
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