Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
OpenDAS
nni
Commits
d90433da
Unverified
Commit
d90433da
authored
May 12, 2020
by
SparkSnail
Committed by
GitHub
May 12, 2020
Browse files
Merge pull request #246 from microsoft/master
merge master
parents
1e511829
bf7daa8f
Changes
35
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
238 additions
and
170 deletions
+238
-170
src/webui/src/components/Modals/Killjob.tsx
src/webui/src/components/Modals/Killjob.tsx
+2
-2
src/webui/src/components/Overview.tsx
src/webui/src/components/Overview.tsx
+44
-16
src/webui/src/components/TrialsDetail.tsx
src/webui/src/components/TrialsDetail.tsx
+46
-45
src/webui/src/components/overview/BasicInfo.tsx
src/webui/src/components/overview/BasicInfo.tsx
+6
-0
src/webui/src/components/overview/Title1.tsx
src/webui/src/components/overview/Title1.tsx
+4
-4
src/webui/src/components/public-child/OpenRow.tsx
src/webui/src/components/public-child/OpenRow.tsx
+0
-20
src/webui/src/components/trial-detail/TableList.tsx
src/webui/src/components/trial-detail/TableList.tsx
+26
-28
src/webui/src/static/const.ts
src/webui/src/static/const.ts
+6
-3
src/webui/src/static/interface.ts
src/webui/src/static/interface.ts
+6
-2
src/webui/src/static/model/experiment.ts
src/webui/src/static/model/experiment.ts
+0
-4
src/webui/src/static/model/trial.ts
src/webui/src/static/model/trial.ts
+7
-5
src/webui/src/static/model/trialmanager.ts
src/webui/src/static/model/trialmanager.ts
+86
-18
src/webui/src/static/style/overview.scss
src/webui/src/static/style/overview.scss
+0
-1
src/webui/src/static/style/overviewTitle.scss
src/webui/src/static/style/overviewTitle.scss
+3
-10
src/webui/src/static/style/trialsDetail.scss
src/webui/src/static/style/trialsDetail.scss
+2
-12
No files found.
src/webui/src/components/Modals/Killjob.tsx
View file @
d90433da
...
@@ -77,7 +77,7 @@ class KillJob extends React.Component<KillJobProps, KillJobState> {
...
@@ -77,7 +77,7 @@ class KillJob extends React.Component<KillJobProps, KillJobState> {
onKill
=
():
void
=>
{
onKill
=
():
void
=>
{
this
.
setState
({
isCalloutVisible
:
false
},
()
=>
{
this
.
setState
({
isCalloutVisible
:
false
},
()
=>
{
const
{
trial
}
=
this
.
props
;
const
{
trial
}
=
this
.
props
;
killJob
(
trial
.
key
,
trial
.
i
d
,
trial
.
status
);
killJob
(
trial
.
key
,
trial
.
jobI
d
,
trial
.
status
);
});
});
}
}
...
@@ -127,4 +127,4 @@ class KillJob extends React.Component<KillJobProps, KillJobState> {
...
@@ -127,4 +127,4 @@ class KillJob extends React.Component<KillJobProps, KillJobState> {
}
}
}
}
export
default
KillJob
;
export
default
KillJob
;
\ No newline at end of file
src/webui/src/components/Overview.tsx
View file @
d90433da
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Stack
,
IStackTokens
}
from
'
office-ui-fabric-react
'
;
import
{
Stack
,
IStackTokens
,
Dropdown
}
from
'
office-ui-fabric-react
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../static/datamodel
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../static/datamodel
'
;
import
{
Trial
}
from
'
../static/model/trial
'
;
import
{
Trial
}
from
'
../static/model/trial
'
;
import
Title1
from
'
./overview/Title1
'
;
import
Title1
from
'
./overview/Title1
'
;
...
@@ -16,7 +16,9 @@ interface OverviewProps {
...
@@ -16,7 +16,9 @@ interface OverviewProps {
experimentUpdateBroadcast
:
number
;
experimentUpdateBroadcast
:
number
;
trialsUpdateBroadcast
:
number
;
trialsUpdateBroadcast
:
number
;
metricGraphMode
:
'
max
'
|
'
min
'
;
metricGraphMode
:
'
max
'
|
'
min
'
;
bestTrialEntries
:
string
;
changeMetricGraphMode
:
(
val
:
'
max
'
|
'
min
'
)
=>
void
;
changeMetricGraphMode
:
(
val
:
'
max
'
|
'
min
'
)
=>
void
;
changeEntries
:
(
entries
:
string
)
=>
void
;
}
}
interface
OverviewState
{
interface
OverviewState
{
...
@@ -38,6 +40,7 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
...
@@ -38,6 +40,7 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
changeMetricGraphMode
(
'
max
'
);
changeMetricGraphMode
(
'
max
'
);
}
}
clickMinTop
=
(
event
:
React
.
SyntheticEvent
<
EventTarget
>
):
void
=>
{
clickMinTop
=
(
event
:
React
.
SyntheticEvent
<
EventTarget
>
):
void
=>
{
event
.
stopPropagation
();
event
.
stopPropagation
();
const
{
changeMetricGraphMode
}
=
this
.
props
;
const
{
changeMetricGraphMode
}
=
this
.
props
;
...
@@ -48,9 +51,16 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
...
@@ -48,9 +51,16 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
this
.
setState
({
trialConcurrency
:
val
});
this
.
setState
({
trialConcurrency
:
val
});
}
}
// updateEntries = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption | undefined): void => {
updateEntries
=
(
event
:
React
.
FormEvent
<
HTMLDivElement
>
,
item
:
any
):
void
=>
{
if
(
item
!==
undefined
)
{
this
.
props
.
changeEntries
(
item
.
key
);
}
}
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
const
{
trialConcurrency
}
=
this
.
state
;
const
{
trialConcurrency
}
=
this
.
state
;
const
{
experimentUpdateBroadcast
,
metricGraphMode
}
=
this
.
props
;
const
{
experimentUpdateBroadcast
,
metricGraphMode
,
bestTrialEntries
}
=
this
.
props
;
const
searchSpace
=
this
.
convertSearchSpace
();
const
searchSpace
=
this
.
convertSearchSpace
();
const
bestTrials
=
this
.
findBestTrials
();
const
bestTrials
=
this
.
findBestTrials
();
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...
@@ -58,23 +68,31 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
...
@@ -58,23 +68,31 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
const
accuracyGraphData
=
this
.
generateAccuracyGraph
(
bestTrials
);
const
accuracyGraphData
=
this
.
generateAccuracyGraph
(
bestTrials
);
const
noDataMessage
=
bestTrials
.
length
>
0
?
''
:
'
No data
'
;
const
noDataMessage
=
bestTrials
.
length
>
0
?
''
:
'
No data
'
;
const
titleMaxbgcolor
=
(
metricGraphMode
===
'
max
'
?
'
#
999
'
:
'
#b3b3b3
'
);
const
titleMaxbgcolor
=
(
metricGraphMode
===
'
max
'
?
'
#
333
'
:
'
#b3b3b3
'
);
const
titleMinbgcolor
=
(
metricGraphMode
===
'
min
'
?
'
#
999
'
:
'
#b3b3b3
'
);
const
titleMinbgcolor
=
(
metricGraphMode
===
'
min
'
?
'
#
333
'
:
'
#b3b3b3
'
);
const
stackTokens
:
IStackTokens
=
{
const
stackTokens
:
IStackTokens
=
{
childrenGap
:
30
,
childrenGap
:
30
,
};
};
const
entriesOption
=
[
{
key
:
'
10
'
,
text
:
'
Display top 10 trials
'
},
{
key
:
'
20
'
,
text
:
'
Display top 20 trials
'
},
{
key
:
'
30
'
,
text
:
'
Display top 30 trials
'
},
{
key
:
'
50
'
,
text
:
'
Display top 50 trials
'
},
{
key
:
'
100
'
,
text
:
'
Display top 100 trials
'
}
];
return
(
return
(
<
div
className
=
"overview"
>
<
div
className
=
"overview"
>
{
/* status and experiment block */
}
{
/* status and experiment block */
}
<
Stack
>
<
Stack
className
=
"bottomDiv bgNNI"
>
<
Title1
text
=
"Experiment"
icon
=
"11.png"
/>
<
Title1
text
=
"Experiment"
icon
=
"11.png"
/>
<
BasicInfo
experimentUpdateBroadcast
=
{
experimentUpdateBroadcast
}
/>
<
BasicInfo
experimentUpdateBroadcast
=
{
experimentUpdateBroadcast
}
/>
</
Stack
>
</
Stack
>
<
Stack
horizontal
className
=
"overMessage"
>
<
Stack
horizontal
className
=
"overMessage
bottomDiv
"
>
{
/* status block */
}
{
/* status block */
}
<
Stack
.
Item
grow
className
=
"prograph
overviewBoder cc
"
>
<
Stack
.
Item
grow
className
=
"prograph
bgNNI borderRight
"
>
<
Title1
text
=
"Status"
icon
=
"5.png"
/>
<
Title1
text
=
"Status"
icon
=
"5.png"
/>
<
Progressed
<
Progressed
bestAccuracy
=
{
bestAccuracy
}
bestAccuracy
=
{
bestAccuracy
}
...
@@ -84,13 +102,14 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
...
@@ -84,13 +102,14 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
/>
/>
</
Stack
.
Item
>
</
Stack
.
Item
>
{
/* experiment parameters search space tuner assessor... */
}
{
/* experiment parameters search space tuner assessor... */
}
<
Stack
.
Item
grow
styles
=
{
{
root
:
{
width
:
450
}}
}
className
=
"overviewBoder"
>
<
Stack
.
Item
grow
styles
=
{
{
root
:
{
width
:
450
}}
}
className
=
"overviewBoder
borderRight bgNNI
"
>
<
Title1
text
=
"Search space"
icon
=
"10.png"
/>
<
Title1
text
=
"Search space"
icon
=
"10.png"
/>
<
Stack
className
=
"experiment"
>
<
Stack
className
=
"experiment"
>
<
SearchSpace
searchSpace
=
{
searchSpace
}
/>
<
SearchSpace
searchSpace
=
{
searchSpace
}
/>
</
Stack
>
</
Stack
>
</
Stack
.
Item
>
</
Stack
.
Item
>
<
Stack
.
Item
grow
styles
=
{
{
root
:
{
width
:
450
}}
}
>
{
/* <Stack.Item grow styles={{root: {width: 450}}} className="bgNNI"> */
}
<
Stack
.
Item
grow
styles
=
{
{
root
:
{
width
:
450
}}
}
className
=
"bgNNI"
>
<
Title1
text
=
"Config"
icon
=
"4.png"
/>
<
Title1
text
=
"Config"
icon
=
"4.png"
/>
<
Stack
className
=
"experiment"
>
<
Stack
className
=
"experiment"
>
{
/* the scroll bar all the trial profile in the searchSpace div*/
}
{
/* the scroll bar all the trial profile in the searchSpace div*/
}
...
@@ -104,19 +123,27 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
...
@@ -104,19 +123,27 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
</
Stack
.
Item
>
</
Stack
.
Item
>
</
Stack
>
</
Stack
>
<
Stack
>
<
Stack
style
=
{
{
backgroundColor
:
'
#fff
'
}
}
>
<
Stack
horizontal
className
=
"top10bg"
>
<
Stack
horizontal
className
=
"top10bg"
style
=
{
{
position
:
'
relative
'
}
}
>
<
div
<
div
className
=
"title"
className
=
"title"
onClick
=
{
this
.
clickMaxTop
}
onClick
=
{
this
.
clickMaxTop
}
>
>
<
Title1
text
=
"Top
10
Maximal trials"
icon
=
"max.png"
bgc
olor
=
{
titleMaxbgcolor
}
/>
<
Title1
text
=
"Top Maximal trials"
icon
=
"max.png"
fontC
olor
=
{
titleMaxbgcolor
}
/>
</
div
>
</
div
>
<
div
<
div
className
=
"title minTitle"
className
=
"title minTitle"
onClick
=
{
this
.
clickMinTop
}
onClick
=
{
this
.
clickMinTop
}
>
>
<
Title1
text
=
"Top10 Minimal trials"
icon
=
"min.png"
bgcolor
=
{
titleMinbgcolor
}
/>
<
Title1
text
=
"Top Minimal trials"
icon
=
"min.png"
fontColor
=
{
titleMinbgcolor
}
/>
</
div
>
<
div
style
=
{
{
position
:
'
absolute
'
,
right
:
52
,
top
:
6
}
}
>
<
Dropdown
selectedKey
=
{
bestTrialEntries
}
options
=
{
entriesOption
}
onChange
=
{
this
.
updateEntries
}
styles
=
{
{
root
:
{
width
:
170
}
}
}
/>
</
div
>
</
div
>
</
Stack
>
</
Stack
>
<
Stack
horizontal
tokens
=
{
stackTokens
}
>
<
Stack
horizontal
tokens
=
{
stackTokens
}
>
...
@@ -128,7 +155,7 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
...
@@ -128,7 +155,7 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
/>
/>
</
div
>
</
div
>
<
div
style
=
{
{
width
:
'
60%
'
}
}
>
<
div
style
=
{
{
width
:
'
60%
'
}
}
>
<
SuccessTable
trialIds
=
{
bestTrials
.
map
(
trial
=>
trial
.
info
.
id
)
}
/>
<
SuccessTable
trialIds
=
{
bestTrials
.
map
(
trial
=>
trial
.
info
.
id
)
}
/>
</
div
>
</
div
>
</
Stack
>
</
Stack
>
</
Stack
>
</
Stack
>
...
@@ -155,10 +182,11 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
...
@@ -155,10 +182,11 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
private
findBestTrials
():
Trial
[]
{
private
findBestTrials
():
Trial
[]
{
const
bestTrials
=
TRIALS
.
sort
();
const
bestTrials
=
TRIALS
.
sort
();
const
{
bestTrialEntries
}
=
this
.
props
;
if
(
this
.
props
.
metricGraphMode
===
'
max
'
)
{
if
(
this
.
props
.
metricGraphMode
===
'
max
'
)
{
bestTrials
.
reverse
().
splice
(
10
);
bestTrials
.
reverse
().
splice
(
JSON
.
parse
(
bestTrialEntries
)
);
}
else
{
}
else
{
bestTrials
.
splice
(
10
);
bestTrials
.
splice
(
JSON
.
parse
(
bestTrialEntries
)
);
}
}
return
bestTrials
;
return
bestTrials
;
}
}
...
...
src/webui/src/components/TrialsDetail.tsx
View file @
d90433da
...
@@ -142,53 +142,54 @@ class TrialsDetail extends React.Component<TrialsDetailProps, TrialDetailState>
...
@@ -142,53 +142,54 @@ class TrialsDetail extends React.Component<TrialsDetailProps, TrialDetailState>
</
Pivot
>
</
Pivot
>
</
div
>
</
div
>
{
/* trial table list */
}
{
/* trial table list */
}
<
Stack
horizontal
className
=
"panelTitle"
>
<
div
style
=
{
{
backgroundColor
:
'
#fff
'
}
}
>
<
span
style
=
{
{
marginRight
:
12
}
}
>
{
tableListIcon
}
</
span
>
<
Stack
horizontal
className
=
"panelTitle"
style
=
{
{
marginTop
:
10
}
}
>
<
span
>
Trial jobs
</
span
>
<
span
style
=
{
{
marginRight
:
12
}
}
>
{
tableListIcon
}
</
span
>
</
Stack
>
<
span
>
Trial jobs
</
span
>
<
Stack
horizontal
className
=
"allList"
>
</
Stack
>
<
StackItem
grow
=
{
50
}
>
<
Stack
horizontal
className
=
"allList"
>
<
DefaultButton
<
StackItem
grow
=
{
50
}
>
text
=
"Compare"
className
=
"allList-compare"
// use child-component tableList's function, the function is in child-component.
onClick
=
{
():
void
=>
{
if
(
this
.
tableList
)
{
this
.
tableList
.
compareBtn
();
}
}
}
/>
</
StackItem
>
<
StackItem
grow
=
{
50
}
>
<
Stack
horizontal
horizontalAlign
=
"end"
className
=
"allList"
>
<
DefaultButton
<
DefaultButton
className
=
"allList-button-gap"
text
=
"Compare"
text
=
"Add column"
className
=
"allList-compare"
onClick
=
{
():
void
=>
{
if
(
this
.
tableList
)
{
this
.
tableList
.
addColumn
();
}
}
}
// use child-component tableList's function, the function is in child-component.
onClick
=
{
():
void
=>
{
if
(
this
.
tableList
)
{
this
.
tableList
.
compareBtn
();
}
}
}
/>
/>
<
Dropdown
</
StackItem
>
selectedKey
=
{
searchType
}
<
StackItem
grow
=
{
50
}
>
options
=
{
searchOptions
}
<
Stack
horizontal
horizontalAlign
=
"end"
className
=
"allList"
>
onChange
=
{
this
.
updateSearchFilterType
}
<
DefaultButton
styles
=
{
{
root
:
{
width
:
150
}
}
}
className
=
"allList-button-gap"
/>
text
=
"Add column"
<
input
onClick
=
{
():
void
=>
{
if
(
this
.
tableList
)
{
this
.
tableList
.
addColumn
();
}
}
}
type
=
"text"
/>
className
=
"allList-search-input"
<
Dropdown
placeholder
=
{
`Search by
${
this
.
state
.
searchType
}
`
}
selectedKey
=
{
searchType
}
onChange
=
{
this
.
searchTrial
}
options
=
{
searchOptions
}
style
=
{
{
width
:
230
}
}
onChange
=
{
this
.
updateSearchFilterType
}
ref
=
{
(
text
):
any
=>
(
this
.
searchInput
)
=
text
}
styles
=
{
{
root
:
{
width
:
150
}
}
}
/>
/>
</
Stack
>
<
input
type
=
"text"
</
StackItem
>
className
=
"allList-search-input"
</
Stack
>
placeholder
=
{
`Search by
${
this
.
state
.
searchType
}
`
}
<
TableList
onChange
=
{
this
.
searchTrial
}
pageSize
=
{
tablePageSize
}
style
=
{
{
width
:
230
}
}
tableSource
=
{
source
.
map
(
trial
=>
trial
.
tableRecord
)
}
ref
=
{
(
text
):
any
=>
(
this
.
searchInput
)
=
text
}
columnList
=
{
columnList
}
/>
changeColumn
=
{
changeColumn
}
</
Stack
>
trialsUpdateBroadcast
=
{
this
.
props
.
trialsUpdateBroadcast
}
</
StackItem
>
// TODO: change any to specific type
</
Stack
>
ref
=
{
(
tabList
):
any
=>
this
.
tableList
=
tabList
}
<
TableList
/>
pageSize
=
{
tablePageSize
}
tableSource
=
{
source
.
map
(
trial
=>
trial
.
tableRecord
)
}
columnList
=
{
columnList
}
changeColumn
=
{
changeColumn
}
trialsUpdateBroadcast
=
{
this
.
props
.
trialsUpdateBroadcast
}
// TODO: change any to specific type
ref
=
{
(
tabList
):
any
=>
this
.
tableList
=
tabList
}
/>
</
div
>
</
div
>
</
div
>
);
);
}
}
...
...
src/webui/src/components/overview/BasicInfo.tsx
View file @
d90433da
...
@@ -22,12 +22,16 @@ class BasicInfo extends React.Component<BasicInfoProps, {}> {
...
@@ -22,12 +22,16 @@ class BasicInfo extends React.Component<BasicInfoProps, {}> {
<
Stack
.
Item
grow
=
{
3
}
className
=
"padItem basic"
>
<
Stack
.
Item
grow
=
{
3
}
className
=
"padItem basic"
>
<
p
>
Name
</
p
>
<
p
>
Name
</
p
>
<
div
>
{
EXPERIMENT
.
profile
.
params
.
experimentName
}
</
div
>
<
div
>
{
EXPERIMENT
.
profile
.
params
.
experimentName
}
</
div
>
</
Stack
.
Item
>
<
Stack
.
Item
grow
=
{
3
}
className
=
"padItem basic"
>
<
p
>
ID
</
p
>
<
p
>
ID
</
p
>
<
div
>
{
EXPERIMENT
.
profile
.
id
}
</
div
>
<
div
>
{
EXPERIMENT
.
profile
.
id
}
</
div
>
</
Stack
.
Item
>
</
Stack
.
Item
>
<
Stack
.
Item
grow
=
{
3
}
className
=
"padItem basic"
>
<
Stack
.
Item
grow
=
{
3
}
className
=
"padItem basic"
>
<
p
>
Start time
</
p
>
<
p
>
Start time
</
p
>
<
div
className
=
"nowrap"
>
{
formatTimestamp
(
EXPERIMENT
.
profile
.
startTime
)
}
</
div
>
<
div
className
=
"nowrap"
>
{
formatTimestamp
(
EXPERIMENT
.
profile
.
startTime
)
}
</
div
>
</
Stack
.
Item
>
<
Stack
.
Item
grow
=
{
3
}
className
=
"padItem basic"
>
<
p
>
End time
</
p
>
<
p
>
End time
</
p
>
<
div
className
=
"nowrap"
>
{
formatTimestamp
(
EXPERIMENT
.
profile
.
endTime
)
}
</
div
>
<
div
className
=
"nowrap"
>
{
formatTimestamp
(
EXPERIMENT
.
profile
.
endTime
)
}
</
div
>
</
Stack
.
Item
>
</
Stack
.
Item
>
...
@@ -45,6 +49,8 @@ class BasicInfo extends React.Component<BasicInfoProps, {}> {
...
@@ -45,6 +49,8 @@ class BasicInfo extends React.Component<BasicInfoProps, {}> {
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
</
TooltipHost
>
</
TooltipHost
>
</
div
>
</
div
>
</
Stack
.
Item
>
<
Stack
.
Item
className
=
"padItem basic"
>
<
p
>
Training platform
</
p
>
<
p
>
Training platform
</
p
>
<
div
className
=
"nowrap"
>
{
EXPERIMENT
.
profile
.
params
.
trainingServicePlatform
}
</
div
>
<
div
className
=
"nowrap"
>
{
EXPERIMENT
.
profile
.
params
.
trainingServicePlatform
}
</
div
>
</
Stack
.
Item
>
</
Stack
.
Item
>
...
...
src/webui/src/components/overview/Title1.tsx
View file @
d90433da
...
@@ -4,7 +4,7 @@ import '../../static/style/overviewTitle.scss';
...
@@ -4,7 +4,7 @@ import '../../static/style/overviewTitle.scss';
interface
Title1Props
{
interface
Title1Props
{
text
:
string
;
text
:
string
;
icon
?:
string
;
icon
?:
string
;
bgc
olor
?:
string
;
fontC
olor
?:
string
;
}
}
class
Title1
extends
React
.
Component
<
Title1Props
,
{}
>
{
class
Title1
extends
React
.
Component
<
Title1Props
,
{}
>
{
...
@@ -14,11 +14,11 @@ class Title1 extends React.Component<Title1Props, {}> {
...
@@ -14,11 +14,11 @@ class Title1 extends React.Component<Title1Props, {}> {
}
}
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
const
{
text
,
icon
,
bgc
olor
}
=
this
.
props
;
const
{
text
,
icon
,
fontC
olor
}
=
this
.
props
;
return
(
return
(
<
Stack
horizontal
className
=
"panelTitle"
style
=
{
{
backgroundColor
:
bgcolor
}
}
>
<
Stack
horizontal
className
=
"panelTitle"
>
<
img
src
=
{
require
(
`../../static/img/icon/
${
icon
}
`
)
}
alt
=
"icon"
/>
<
img
src
=
{
require
(
`../../static/img/icon/
${
icon
}
`
)
}
alt
=
"icon"
/>
<
span
>
{
text
}
</
span
>
<
span
style
=
{
{
color
:
fontColor
}
}
>
{
text
}
</
span
>
</
Stack
>
</
Stack
>
);
);
}
}
...
...
src/webui/src/components/public-child/OpenRow.tsx
View file @
d90433da
...
@@ -3,7 +3,6 @@ import * as copy from 'copy-to-clipboard';
...
@@ -3,7 +3,6 @@ import * as copy from 'copy-to-clipboard';
import
{
Stack
,
PrimaryButton
,
Pivot
,
PivotItem
}
from
'
office-ui-fabric-react
'
;
import
{
Stack
,
PrimaryButton
,
Pivot
,
PivotItem
}
from
'
office-ui-fabric-react
'
;
import
{
Trial
}
from
'
../../static/model/trial
'
;
import
{
Trial
}
from
'
../../static/model/trial
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
MANAGER_IP
}
from
'
../../static/const
'
;
import
JSONTree
from
'
react-json-tree
'
;
import
JSONTree
from
'
react-json-tree
'
;
import
PaiTrialLog
from
'
../public-child/PaiTrialLog
'
;
import
PaiTrialLog
from
'
../public-child/PaiTrialLog
'
;
import
TrialLog
from
'
../public-child/TrialLog
'
;
import
TrialLog
from
'
../public-child/TrialLog
'
;
...
@@ -60,31 +59,12 @@ class OpenRow extends React.Component<OpenRowProps, OpenRowState> {
...
@@ -60,31 +59,12 @@ class OpenRow extends React.Component<OpenRowProps, OpenRowState> {
const
{
isHidenInfo
,
typeInfo
,
info
}
=
this
.
state
;
const
{
isHidenInfo
,
typeInfo
,
info
}
=
this
.
state
;
const
trialId
=
this
.
props
.
trialId
;
const
trialId
=
this
.
props
.
trialId
;
const
trial
=
TRIALS
.
getTrial
(
trialId
);
const
trial
=
TRIALS
.
getTrial
(
trialId
);
const
trialLink
:
string
=
`
${
MANAGER_IP
}
/trial-jobs/
${
trialId
}
`
;
const
logPathRow
=
trial
.
info
.
logPath
||
'
This trial
\'
s log path is not available.
'
;
const
logPathRow
=
trial
.
info
.
logPath
||
'
This trial
\'
s log path is not available.
'
;
const
multiProgress
=
trial
.
info
.
hyperParameters
===
undefined
?
0
:
trial
.
info
.
hyperParameters
.
length
;
return
(
return
(
<
Stack
className
=
"openRow"
>
<
Stack
className
=
"openRow"
>
<
Stack
className
=
"openRowContent"
>
<
Stack
className
=
"openRowContent"
>
<
Pivot
>
<
Pivot
>
<
PivotItem
headerText
=
"Parameters"
key
=
"1"
itemIcon
=
"TestParameter"
>
<
PivotItem
headerText
=
"Parameters"
key
=
"1"
itemIcon
=
"TestParameter"
>
{
EXPERIMENT
.
multiPhase
?
<
Stack
className
=
"link"
>
{
`
Trails for multiphase experiment will return a set of parameters,
we are listing the latest parameter in webportal.
For the entire parameter set, please refer to the following "
`
}
<
a
href
=
{
trialLink
}
rel
=
"noopener noreferrer"
target
=
"_blank"
>
{
trialLink
}
</
a
>
{
`".`
}
<
div
>
Current Phase:
{
multiProgress
}
.
</
div
>
</
Stack
>
:
null
}
{
{
trial
.
info
.
hyperParameters
!==
undefined
trial
.
info
.
hyperParameters
!==
undefined
?
?
...
...
src/webui/src/components/trial-detail/TableList.tsx
View file @
d90433da
...
@@ -9,7 +9,7 @@ import { LineChart, blocked, copy } from '../Buttons/Icon';
...
@@ -9,7 +9,7 @@ import { LineChart, blocked, copy } from '../Buttons/Icon';
import
{
MANAGER_IP
,
COLUMNPro
}
from
'
../../static/const
'
;
import
{
MANAGER_IP
,
COLUMNPro
}
from
'
../../static/const
'
;
import
{
convertDuration
,
formatTimestamp
,
intermediateGraphOption
,
parseMetrics
}
from
'
../../static/function
'
;
import
{
convertDuration
,
formatTimestamp
,
intermediateGraphOption
,
parseMetrics
}
from
'
../../static/function
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
TableRecord
}
from
'
../../static/interface
'
;
import
{
TableRecord
,
TrialJobInfo
}
from
'
../../static/interface
'
;
import
Details
from
'
../overview/Details
'
;
import
Details
from
'
../overview/Details
'
;
import
ChangeColumnComponent
from
'
../Modals/ChangeColumnComponent
'
;
import
ChangeColumnComponent
from
'
../Modals/ChangeColumnComponent
'
;
import
Compare
from
'
../Modals/Compare
'
;
import
Compare
from
'
../Modals/Compare
'
;
...
@@ -231,18 +231,23 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -231,18 +231,23 @@ class TableList extends React.Component<TableListProps, TableListState> {
)
)
};
};
showIntermediateModal
=
async
(
id
:
string
,
event
:
React
.
SyntheticEvent
<
EventTarget
>
):
Promise
<
void
>
=>
{
showIntermediateModal
=
async
(
record
:
TrialJobInfo
,
event
:
React
.
SyntheticEvent
<
EventTarget
>
):
Promise
<
void
>
=>
{
event
.
preventDefault
();
event
.
preventDefault
();
event
.
stopPropagation
();
event
.
stopPropagation
();
const
res
=
await
axios
.
get
(
`
${
MANAGER_IP
}
/metric-data/
${
i
d
}
`
);
const
res
=
await
axios
.
get
(
`
${
MANAGER_IP
}
/metric-data/
${
record
.
jobI
d
}
`
);
if
(
res
.
status
===
200
)
{
if
(
res
.
status
===
200
)
{
const
intermediateArr
:
number
[]
=
[];
const
intermediateArr
:
number
[]
=
[];
// support intermediate result is dict because the last intermediate result is
// support intermediate result is dict because the last intermediate result is
// final result in a succeed trial, it may be a dict.
// final result in a succeed trial, it may be a dict.
// get intermediate result dict keys array
// get intermediate result dict keys array
const
{
intermediateKey
}
=
this
.
state
;
const
{
intermediateKey
}
=
this
.
state
;
const
otherkeys
:
string
[]
=
[
];
const
otherkeys
:
string
[]
=
[];
if
(
res
.
data
.
length
!==
0
)
{
// One trial job may contains multiple parameter id
// only show current trial's metric data
const
metricDatas
=
res
.
data
.
filter
(
item
=>
{
return
item
.
parameterId
==
record
.
parameterId
;
});
if
(
metricDatas
.
length
!==
0
)
{
// just add type=number keys
// just add type=number keys
const
intermediateMetrics
=
parseMetrics
(
res
.
data
[
0
].
data
);
const
intermediateMetrics
=
parseMetrics
(
res
.
data
[
0
].
data
);
for
(
const
key
in
intermediateMetrics
)
{
for
(
const
key
in
intermediateMetrics
)
{
...
@@ -252,9 +257,10 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -252,9 +257,10 @@ class TableList extends React.Component<TableListProps, TableListState> {
}
}
}
}
// intermediateArr just store default val
// intermediateArr just store default val
Object
.
keys
(
res
.
data
).
map
(
item
=>
{
metricDatas
.
map
(
item
=>
{
if
(
res
.
data
[
item
].
type
===
'
PERIODICAL
'
)
{
const
temp
=
parseMetrics
(
res
.
data
[
item
].
data
);
if
(
item
.
type
===
'
PERIODICAL
'
)
{
const
temp
=
parseMetrics
(
item
.
data
);
if
(
typeof
temp
===
'
object
'
)
{
if
(
typeof
temp
===
'
object
'
)
{
intermediateArr
.
push
(
temp
[
intermediateKey
]);
intermediateArr
.
push
(
temp
[
intermediateKey
]);
}
else
{
}
else
{
...
@@ -262,12 +268,12 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -262,12 +268,12 @@ class TableList extends React.Component<TableListProps, TableListState> {
}
}
}
}
});
});
const
intermediate
=
intermediateGraphOption
(
intermediateArr
,
id
);
const
intermediate
=
intermediateGraphOption
(
intermediateArr
,
record
.
id
);
this
.
setState
({
this
.
setState
({
intermediateData
:
res
.
data
,
// store origin intermediate data for a trial
intermediateData
:
res
.
data
,
// store origin intermediate data for a trial
intermediateOption
:
intermediate
,
intermediateOption
:
intermediate
,
intermediateOtherKeys
:
otherkeys
,
intermediateOtherKeys
:
otherkeys
,
intermediateId
:
id
intermediateId
:
record
.
id
});
});
}
}
this
.
setState
({
modalVisible
:
true
});
this
.
setState
({
modalVisible
:
true
});
...
@@ -426,8 +432,6 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -426,8 +432,6 @@ class TableList extends React.Component<TableListProps, TableListState> {
// when user click [Add Column] need to use the function
// when user click [Add Column] need to use the function
private
initTableColumnList
=
(
columnList
:
string
[]):
IColumn
[]
=>
{
private
initTableColumnList
=
(
columnList
:
string
[]):
IColumn
[]
=>
{
// const { columnList } = this.props;
// const { columnList } = this.props;
// [supportCustomizedTrial: true]
const
supportCustomizedTrial
=
(
EXPERIMENT
.
multiPhase
===
true
)
?
false
:
true
;
const
disabledAddCustomizedTrial
=
[
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
].
includes
(
EXPERIMENT
.
status
);
const
disabledAddCustomizedTrial
=
[
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
].
includes
(
EXPERIMENT
.
status
);
const
showColumn
:
IColumn
[]
=
[];
const
showColumn
:
IColumn
[]
=
[];
for
(
const
item
of
columnList
)
{
for
(
const
item
of
columnList
)
{
...
@@ -479,7 +483,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -479,7 +483,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
<
PrimaryButton
<
PrimaryButton
className
=
"detail-button-operation"
className
=
"detail-button-operation"
title
=
"Intermediate"
title
=
"Intermediate"
onClick
=
{
this
.
showIntermediateModal
.
bind
(
this
,
record
.
id
)
}
onClick
=
{
this
.
showIntermediateModal
.
bind
(
this
,
record
)
}
>
>
{
LineChart
}
{
LineChart
}
</
PrimaryButton
>
</
PrimaryButton
>
...
@@ -494,20 +498,14 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -494,20 +498,14 @@ class TableList extends React.Component<TableListProps, TableListState> {
<
KillJob
trial
=
{
record
}
/>
<
KillJob
trial
=
{
record
}
/>
}
}
{
/* Add a new trial-customized trial */
}
{
/* Add a new trial-customized trial */
}
{
<
PrimaryButton
supportCustomizedTrial
className
=
"detail-button-operation"
?
title
=
"Customized trial"
<
PrimaryButton
onClick
=
{
this
.
setCustomizedTrial
.
bind
(
this
,
record
.
id
)
}
className
=
"detail-button-operation"
disabled
=
{
disabledAddCustomizedTrial
}
title
=
"Customized trial"
>
onClick
=
{
this
.
setCustomizedTrial
.
bind
(
this
,
record
.
id
)
}
{
copy
}
disabled
=
{
disabledAddCustomizedTrial
}
</
PrimaryButton
>
>
{
copy
}
</
PrimaryButton
>
:
null
}
</
Stack
>
</
Stack
>
);
);
},
},
...
@@ -659,4 +657,4 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -659,4 +657,4 @@ class TableList extends React.Component<TableListProps, TableListState> {
}
}
}
}
export
default
TableList
;
export
default
TableList
;
\ No newline at end of file
src/webui/src/static/const.ts
View file @
d90433da
...
@@ -2,7 +2,10 @@
...
@@ -2,7 +2,10 @@
const
METRIC_GROUP_UPDATE_THRESHOLD
=
100
;
const
METRIC_GROUP_UPDATE_THRESHOLD
=
100
;
const
METRIC_GROUP_UPDATE_SIZE
=
20
;
const
METRIC_GROUP_UPDATE_SIZE
=
20
;
const
MANAGER_IP
=
`/api/v1/nni`
;
let
MANAGER_IP
=
`/api/v1/nni`
;
if
(
process
.
env
.
NODE_ENV
==
"
development
"
)
{
MANAGER_IP
=
`//
${
window
.
location
.
hostname
}
:8080`
+
MANAGER_IP
;
}
const
DOWNLOAD_IP
=
`/logs`
;
const
DOWNLOAD_IP
=
`/logs`
;
const
WEBUIDOC
=
'
https://nni.readthedocs.io/en/latest/Tutorial/WebUI.html
'
;
const
WEBUIDOC
=
'
https://nni.readthedocs.io/en/latest/Tutorial/WebUI.html
'
;
const
trialJobStatus
=
[
const
trialJobStatus
=
[
...
@@ -34,8 +37,8 @@ const OPERATION = 'Operation';
...
@@ -34,8 +37,8 @@ const OPERATION = 'Operation';
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
=
[
'
Trial No.
'
,
'
ID
'
,
'
Start Time
'
,
'
End Time
'
,
'
Duration
'
,
'
Status
'
,
'
Intermediate result
'
,
'
Default
'
,
OPERATION
];
'
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.
'
;
export
{
export
{
MANAGER_IP
,
DOWNLOAD_IP
,
trialJobStatus
,
COLUMNPro
,
WEBUIDOC
,
MANAGER_IP
,
DOWNLOAD_IP
,
trialJobStatus
,
COLUMNPro
,
WEBUIDOC
,
...
...
src/webui/src/static/interface.ts
View file @
d90433da
...
@@ -18,6 +18,8 @@ interface TableRecord {
...
@@ -18,6 +18,8 @@ interface TableRecord {
startTime
:
number
;
startTime
:
number
;
endTime
?:
number
;
endTime
?:
number
;
id
:
string
;
id
:
string
;
jobId
:
string
;
parameterId
:
string
;
duration
:
number
;
duration
:
number
;
status
:
string
;
status
:
string
;
intermediateCount
:
number
;
intermediateCount
:
number
;
...
@@ -99,6 +101,7 @@ interface Intermedia {
...
@@ -99,6 +101,7 @@ interface Intermedia {
interface
MetricDataRecord
{
interface
MetricDataRecord
{
timestamp
:
number
;
timestamp
:
number
;
trialJobId
:
string
;
trialJobId
:
string
;
trialId
:
string
;
parameterId
:
string
;
parameterId
:
string
;
type
:
string
;
type
:
string
;
sequence
:
number
;
sequence
:
number
;
...
@@ -107,6 +110,8 @@ interface MetricDataRecord {
...
@@ -107,6 +110,8 @@ interface MetricDataRecord {
interface
TrialJobInfo
{
interface
TrialJobInfo
{
id
:
string
;
id
:
string
;
jobId
:
string
;
parameterId
:
string
;
sequenceId
:
number
;
sequenceId
:
number
;
status
:
string
;
status
:
string
;
startTime
?:
number
;
startTime
?:
number
;
...
@@ -126,7 +131,6 @@ interface ExperimentParams {
...
@@ -126,7 +131,6 @@ interface ExperimentParams {
maxTrialNum
:
number
;
maxTrialNum
:
number
;
searchSpace
:
string
;
searchSpace
:
string
;
trainingServicePlatform
:
string
;
trainingServicePlatform
:
string
;
multiPhase
?:
boolean
;
multiThread
?:
boolean
;
multiThread
?:
boolean
;
versionCheck
?:
boolean
;
versionCheck
?:
boolean
;
logCollection
?:
string
;
logCollection
?:
string
;
...
@@ -189,4 +193,4 @@ export {
...
@@ -189,4 +193,4 @@ export {
AccurPoint
,
DetailAccurPoint
,
TooltipForIntermediate
,
TooltipForAccuracy
,
AccurPoint
,
DetailAccurPoint
,
TooltipForIntermediate
,
TooltipForAccuracy
,
Dimobj
,
ParaObj
,
Intermedia
,
MetricDataRecord
,
TrialJobInfo
,
ExperimentParams
,
Dimobj
,
ParaObj
,
Intermedia
,
MetricDataRecord
,
TrialJobInfo
,
ExperimentParams
,
ExperimentProfile
,
NNIManagerStatus
,
EventMap
ExperimentProfile
,
NNIManagerStatus
,
EventMap
};
};
\ No newline at end of file
src/webui/src/static/model/experiment.ts
View file @
d90433da
...
@@ -66,10 +66,6 @@ class Experiment {
...
@@ -66,10 +66,6 @@ class Experiment {
return
!!
(
this
.
profile
.
params
.
logCollection
&&
this
.
profile
.
params
.
logCollection
!==
'
none
'
);
return
!!
(
this
.
profile
.
params
.
logCollection
&&
this
.
profile
.
params
.
logCollection
!==
'
none
'
);
}
}
get
multiPhase
():
boolean
{
return
!!
(
this
.
profile
.
params
.
multiPhase
);
}
get
status
():
string
{
get
status
():
string
{
if
(
!
this
.
statusField
)
{
if
(
!
this
.
statusField
)
{
throw
Error
(
'
Experiment status not initialized
'
);
throw
Error
(
'
Experiment status not initialized
'
);
...
...
src/webui/src/static/model/trial.ts
View file @
d90433da
...
@@ -4,7 +4,7 @@ import { getFinal, formatAccuracy, metricAccuracy, parseMetrics, isArrayType } f
...
@@ -4,7 +4,7 @@ import { getFinal, formatAccuracy, metricAccuracy, parseMetrics, isArrayType } f
class
Trial
implements
TableObj
{
class
Trial
implements
TableObj
{
private
metricsInitialized
:
boolean
=
false
;
private
metricsInitialized
:
boolean
=
false
;
private
infoField
:
TrialJobInfo
|
undefined
;
private
infoField
:
TrialJobInfo
|
undefined
;
private
intermediates
:
(
MetricDataRecord
|
undefined
)[]
=
[
];
private
intermediates
:
(
MetricDataRecord
|
undefined
)[]
=
[];
public
final
:
MetricDataRecord
|
undefined
;
public
final
:
MetricDataRecord
|
undefined
;
private
finalAcc
:
number
|
undefined
;
private
finalAcc
:
number
|
undefined
;
...
@@ -29,7 +29,7 @@ class Trial implements TableObj {
...
@@ -29,7 +29,7 @@ class Trial implements TableObj {
}
}
get
intermediateMetrics
():
MetricDataRecord
[]
{
get
intermediateMetrics
():
MetricDataRecord
[]
{
const
ret
:
MetricDataRecord
[]
=
[
];
const
ret
:
MetricDataRecord
[]
=
[];
for
(
let
i
=
0
;
i
<
this
.
intermediates
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
this
.
intermediates
.
length
;
i
++
)
{
if
(
this
.
intermediates
[
i
])
{
if
(
this
.
intermediates
[
i
])
{
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...
@@ -80,6 +80,8 @@ class Trial implements TableObj {
...
@@ -80,6 +80,8 @@ class Trial implements TableObj {
key
:
this
.
info
.
id
,
key
:
this
.
info
.
id
,
sequenceId
:
this
.
info
.
sequenceId
,
sequenceId
:
this
.
info
.
sequenceId
,
id
:
this
.
info
.
id
,
id
:
this
.
info
.
id
,
jobId
:
this
.
info
.
jobId
,
parameterId
:
this
.
info
.
parameterId
,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
startTime
:
this
.
info
.
startTime
!
,
startTime
:
this
.
info
.
startTime
!
,
endTime
:
this
.
info
.
endTime
,
endTime
:
this
.
info
.
endTime
,
...
@@ -122,8 +124,8 @@ class Trial implements TableObj {
...
@@ -122,8 +124,8 @@ class Trial implements TableObj {
get
description
():
Parameters
{
get
description
():
Parameters
{
const
ret
:
Parameters
=
{
const
ret
:
Parameters
=
{
parameters
:
{
},
parameters
:
{},
intermediate
:
[
],
intermediate
:
[],
multiProgress
:
1
multiProgress
:
1
};
};
const
tempHyper
=
this
.
info
.
hyperParameters
;
const
tempHyper
=
this
.
info
.
hyperParameters
;
...
@@ -142,7 +144,7 @@ class Trial implements TableObj {
...
@@ -142,7 +144,7 @@ class Trial implements TableObj {
ret
.
logPath
=
this
.
info
.
logPath
;
ret
.
logPath
=
this
.
info
.
logPath
;
}
}
const
mediate
:
number
[]
=
[
];
const
mediate
:
number
[]
=
[];
for
(
const
items
of
this
.
intermediateMetrics
)
{
for
(
const
items
of
this
.
intermediateMetrics
)
{
if
(
typeof
parseMetrics
(
items
.
data
)
===
'
object
'
)
{
if
(
typeof
parseMetrics
(
items
.
data
)
===
'
object
'
)
{
mediate
.
push
(
parseMetrics
(
items
.
data
).
default
);
mediate
.
push
(
parseMetrics
(
items
.
data
).
default
);
...
...
src/webui/src/static/model/trialmanager.ts
View file @
d90433da
...
@@ -6,13 +6,29 @@ import { Trial } from './trial';
...
@@ -6,13 +6,29 @@ import { Trial } from './trial';
function
groupMetricsByTrial
(
metrics
:
MetricDataRecord
[]):
Map
<
string
,
MetricDataRecord
[]
>
{
function
groupMetricsByTrial
(
metrics
:
MetricDataRecord
[]):
Map
<
string
,
MetricDataRecord
[]
>
{
const
ret
=
new
Map
<
string
,
MetricDataRecord
[]
>
();
const
ret
=
new
Map
<
string
,
MetricDataRecord
[]
>
();
for
(
const
metric
of
metrics
)
{
for
(
const
metric
of
metrics
)
{
if
(
ret
.
has
(
metric
.
trialJobId
))
{
const
trialId
=
`
${
metric
.
trialJobId
}
-
${
metric
.
parameterId
}
`
;
metric
.
trialId
=
trialId
;
if
(
ret
.
has
(
trialId
))
{
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
ret
.
get
(
metric
.
trial
Job
Id
)
!
.
push
(
metric
);
ret
.
get
(
trialId
)
!
.
push
(
metric
);
}
else
{
}
else
{
ret
.
set
(
metric
.
trial
Job
Id
,
[
metric
]);
ret
.
set
(
trialId
,
[
metric
]);
}
}
}
}
// to compatiable with multi-trial in same job, fix offset of sequence
ret
.
forEach
((
trialMetrics
)
=>
{
let
minSequenceNumber
=
Number
.
POSITIVE_INFINITY
;
trialMetrics
.
map
((
item
)
=>
{
if
(
item
.
sequence
<
minSequenceNumber
&&
item
.
type
!==
"
FINAL
"
)
{
minSequenceNumber
=
item
.
sequence
;
}
});
trialMetrics
.
map
((
item
)
=>
{
if
(
item
.
type
!==
"
FINAL
"
)
{
item
.
sequence
-=
minSequenceNumber
;
}
});
});
return
ret
;
return
ret
;
}
}
...
@@ -31,7 +47,7 @@ class TrialManager {
...
@@ -31,7 +47,7 @@ class TrialManager {
}
}
public
async
update
(
lastTime
?:
boolean
):
Promise
<
boolean
>
{
public
async
update
(
lastTime
?:
boolean
):
Promise
<
boolean
>
{
const
[
infoUpdated
,
metricUpdated
]
=
await
Promise
.
all
([
this
.
updateInfo
(),
this
.
updateMetrics
(
lastTime
)
]);
const
[
infoUpdated
,
metricUpdated
]
=
await
Promise
.
all
([
this
.
updateInfo
(),
this
.
updateMetrics
(
lastTime
)]);
return
infoUpdated
||
metricUpdated
;
return
infoUpdated
||
metricUpdated
;
}
}
...
@@ -71,14 +87,14 @@ class TrialManager {
...
@@ -71,14 +87,14 @@ class TrialManager {
public
countStatus
():
Map
<
string
,
number
>
{
public
countStatus
():
Map
<
string
,
number
>
{
const
cnt
=
new
Map
<
string
,
number
>
([
const
cnt
=
new
Map
<
string
,
number
>
([
[
'
UNKNOWN
'
,
0
],
[
'
UNKNOWN
'
,
0
],
[
'
WAITING
'
,
0
],
[
'
WAITING
'
,
0
],
[
'
RUNNING
'
,
0
],
[
'
RUNNING
'
,
0
],
[
'
SUCCEEDED
'
,
0
],
[
'
SUCCEEDED
'
,
0
],
[
'
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
())
{
...
@@ -89,19 +105,71 @@ class TrialManager {
...
@@ -89,19 +105,71 @@ class TrialManager {
return
cnt
;
return
cnt
;
}
}
public
static
expandJobsToTrials
(
jobs
:
TrialJobInfo
[]):
TrialJobInfo
[]
{
const
trials
:
TrialJobInfo
[]
=
[];
for
(
const
jobInfo
of
jobs
as
TrialJobInfo
[])
{
if
(
jobInfo
.
hyperParameters
)
{
let
trial
:
TrialJobInfo
|
undefined
;
let
lastTrial
:
TrialJobInfo
|
undefined
;
for
(
let
i
=
0
;
i
<
jobInfo
.
hyperParameters
.
length
;
i
++
)
{
const
hyperParameters
=
jobInfo
.
hyperParameters
[
i
]
const
hpObject
=
JSON
.
parse
(
hyperParameters
);
const
parameterId
=
hpObject
[
"
parameter_id
"
];
trial
=
{
id
:
`
${
jobInfo
.
id
}
-
${
parameterId
}
`
,
jobId
:
jobInfo
.
id
,
parameterId
:
parameterId
,
sequenceId
:
parameterId
,
status
:
"
SUCCEEDED
"
,
startTime
:
jobInfo
.
startTime
,
endTime
:
jobInfo
.
startTime
,
hyperParameters
:
[
hyperParameters
],
logPath
:
jobInfo
.
logPath
,
stderrPath
:
jobInfo
.
stderrPath
,
};
if
(
jobInfo
.
finalMetricData
)
{
for
(
const
metricData
of
jobInfo
.
finalMetricData
)
{
if
(
metricData
.
parameterId
==
parameterId
)
{
trial
.
finalMetricData
=
[
metricData
];
trial
.
endTime
=
metricData
.
timestamp
;
break
;
}
}
}
if
(
lastTrial
)
{
trial
.
startTime
=
lastTrial
.
endTime
;
}
else
{
trial
.
startTime
=
jobInfo
.
startTime
;
}
lastTrial
=
trial
;
trials
.
push
(
trial
);
}
if
(
lastTrial
!==
undefined
)
{
lastTrial
.
status
=
jobInfo
.
status
;
lastTrial
.
endTime
=
jobInfo
.
endTime
;
}
}
else
{
trials
.
push
(
jobInfo
);
}
}
return
trials
;
}
private
async
updateInfo
():
Promise
<
boolean
>
{
private
async
updateInfo
():
Promise
<
boolean
>
{
const
response
=
await
axios
.
get
(
`
${
MANAGER_IP
}
/trial-jobs`
);
const
response
=
await
axios
.
get
(
`
${
MANAGER_IP
}
/trial-jobs`
);
let
updated
=
false
;
let
updated
=
false
;
if
(
response
.
status
===
200
)
{
if
(
response
.
status
===
200
)
{
for
(
const
info
of
response
.
data
as
TrialJobInfo
[])
{
const
newTrials
=
TrialManager
.
expandJobsToTrials
(
response
.
data
);
if
(
this
.
trials
.
has
(
info
.
id
))
{
for
(
const
trialInfo
of
newTrials
as
TrialJobInfo
[])
{
if
(
this
.
trials
.
has
(
trialInfo
.
id
))
{
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
updated
=
this
.
trials
.
get
(
i
nfo
.
id
)
!
.
updateTrialJobInfo
(
i
nfo
)
||
updated
;
updated
=
this
.
trials
.
get
(
trialI
nfo
.
id
)
!
.
updateTrialJobInfo
(
trialI
nfo
)
||
updated
;
}
else
{
}
else
{
this
.
trials
.
set
(
i
nfo
.
id
,
new
Trial
(
i
nfo
,
undefined
));
this
.
trials
.
set
(
trialI
nfo
.
id
,
new
Trial
(
trialI
nfo
,
undefined
));
updated
=
true
;
updated
=
true
;
}
}
this
.
maxSequenceId
=
Math
.
max
(
this
.
maxSequenceId
,
i
nfo
.
sequenceId
);
this
.
maxSequenceId
=
Math
.
max
(
this
.
maxSequenceId
,
trialI
nfo
.
sequenceId
);
}
}
this
.
infoInitialized
=
true
;
this
.
infoInitialized
=
true
;
}
}
...
@@ -146,7 +214,7 @@ class TrialManager {
...
@@ -146,7 +214,7 @@ class TrialManager {
private
doUpdateMetrics
(
allMetrics
:
MetricDataRecord
[],
latestOnly
:
boolean
):
boolean
{
private
doUpdateMetrics
(
allMetrics
:
MetricDataRecord
[],
latestOnly
:
boolean
):
boolean
{
let
updated
=
false
;
let
updated
=
false
;
for
(
const
[
trialId
,
metrics
]
of
groupMetricsByTrial
(
allMetrics
).
entries
())
{
for
(
const
[
trialId
,
metrics
]
of
groupMetricsByTrial
(
allMetrics
).
entries
())
{
if
(
this
.
trials
.
has
(
trialId
))
{
if
(
this
.
trials
.
has
(
trialId
))
{
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const
trial
=
this
.
trials
.
get
(
trialId
)
!
;
const
trial
=
this
.
trials
.
get
(
trialId
)
!
;
...
...
src/webui/src/static/style/overview.scss
View file @
d90433da
...
@@ -25,7 +25,6 @@
...
@@ -25,7 +25,6 @@
padding
:
15px
0
;
padding
:
15px
0
;
color
:
#212121
;
color
:
#212121
;
width
:
95%
;
width
:
95%
;
margin
:
0
auto
;
}
}
.nowrap
{
.nowrap
{
...
...
src/webui/src/static/style/overviewTitle.scss
View file @
d90433da
$titleBgcolor
:
#b3b3b3
;
$iconPaddingVal
:
14px
;
$iconPaddingVal
:
14px
;
.overview
.overviewBoder
{
height
:
100%
;
border-right
:
2px
solid
white
;
}
.panelTitle
{
.panelTitle
{
font-family
:
'Segoe UI'
,
Tahoma
,
Geneva
,
Verdana
,
sans-serif
;
font-family
:
'Segoe UI'
,
Tahoma
,
Geneva
,
Verdana
,
sans-serif
;
width
:
100%
;
width
:
100%
;
height
:
38px
;
height
:
38px
;
padding
:
0
$iconPaddingVal
;
padding
:
4px
$iconPaddingVal
;
b
ackground
:
$titleBgcolor
;
b
ox-sizing
:
border-box
;
img
{
img
{
height
:
22px
;
height
:
22px
;
/* (38 - 22 ) / 2 */
/* (38 - 22 ) / 2 */
...
@@ -40,7 +34,6 @@ $iconPaddingVal: 14px;
...
@@ -40,7 +34,6 @@ $iconPaddingVal: 14px;
}
}
.top10bg
{
.top10bg
{
background-color
:
$titleBgcolor
;
.top10Title
{
.top10Title
{
width
:
160px
;
width
:
160px
;
...
...
src/webui/src/static/style/trialsDetail.scss
View file @
d90433da
$bg
:
#b3b3b3
;
#tabsty
{
#tabsty
{
background-color
:
#fff
;
.ms-Pivot
{
.ms-Pivot
{
.ms-Button
{
.ms-Button
{
padding
:
0
;
padding
:
0
;
...
@@ -7,13 +7,6 @@ $bg: #b3b3b3;
...
@@ -7,13 +7,6 @@ $bg: #b3b3b3;
margin-right
:
0
;
margin-right
:
0
;
border-right
:
2px
solid
#fff
;
border-right
:
2px
solid
#fff
;
transition
:
0
.3s
;
transition
:
0
.3s
;
&
:hover
{
background-color
:
$bg
;
}
.ms-Button-flexContainer
{
background-color
:
$bg
;
}
}
}
.
ms-Pivot-link
:
:
before
{
.
ms-Pivot-link
:
:
before
{
...
@@ -45,10 +38,7 @@ $bg: #b3b3b3;
...
@@ -45,10 +38,7 @@ $bg: #b3b3b3;
/* graph, title total height */
/* graph, title total height */
width
:
100%
;
width
:
100%
;
height
:
500px
;
height
:
500px
;
/* graph all title bg*/
.ms-FocusZone
{
background-color
:
$bg
;
}
.graph
{
.graph
{
height
:
432px
;
height
:
432px
;
margin
:
0
auto
;
margin
:
0
auto
;
...
...
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment