Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
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