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
92738382
Unverified
Commit
92738382
authored
Oct 21, 2020
by
Lijiaoa
Committed by
GitHub
Oct 21, 2020
Browse files
[webui v1.9 bug bash] fix bugs in v1.9 (#2989)
parent
30d29116
Changes
31
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
526 additions
and
279 deletions
+526
-279
src/webui/src/App.scss
src/webui/src/App.scss
+1
-1
src/webui/src/App.tsx
src/webui/src/App.tsx
+32
-2
src/webui/src/components/Overview.tsx
src/webui/src/components/Overview.tsx
+28
-8
src/webui/src/components/TrialsDetail.tsx
src/webui/src/components/TrialsDetail.tsx
+1
-1
src/webui/src/components/modals/Killjob.tsx
src/webui/src/components/modals/Killjob.tsx
+6
-2
src/webui/src/components/overview/command/Command1.tsx
src/webui/src/components/overview/command/Command1.tsx
+3
-26
src/webui/src/components/overview/command/Command2.tsx
src/webui/src/components/overview/command/Command2.tsx
+60
-0
src/webui/src/components/overview/count/EditExperimentParam.tsx
...bui/src/components/overview/count/EditExperimentParam.tsx
+121
-51
src/webui/src/components/overview/count/ExpDuration.tsx
src/webui/src/components/overview/count/ExpDuration.tsx
+29
-19
src/webui/src/components/overview/count/ExpDurationContext.tsx
...ebui/src/components/overview/count/ExpDurationContext.tsx
+4
-1
src/webui/src/components/overview/count/TrialCount.tsx
src/webui/src/components/overview/count/TrialCount.tsx
+56
-52
src/webui/src/components/overview/count/commonStyle.ts
src/webui/src/components/overview/count/commonStyle.ts
+16
-0
src/webui/src/components/overview/experiment/BasicInfo.tsx
src/webui/src/components/overview/experiment/BasicInfo.tsx
+47
-45
src/webui/src/components/overview/overviewConst.ts
src/webui/src/components/overview/overviewConst.ts
+7
-1
src/webui/src/components/overview/table/SuccessTable.tsx
src/webui/src/components/overview/table/SuccessTable.tsx
+19
-20
src/webui/src/components/public-child/DefaultMetric.tsx
src/webui/src/components/public-child/DefaultMetric.tsx
+1
-1
src/webui/src/components/public-child/config/TrialConfigButton.tsx
.../src/components/public-child/config/TrialConfigButton.tsx
+1
-1
src/webui/src/components/public-child/config/TrialConfigPanel.tsx
...i/src/components/public-child/config/TrialConfigPanel.tsx
+63
-43
src/webui/src/components/trial-detail/TableList.tsx
src/webui/src/components/trial-detail/TableList.tsx
+29
-3
src/webui/src/index.tsx
src/webui/src/index.tsx
+2
-2
No files found.
src/webui/src/App.scss
View file @
92738382
...
...
@@ -53,7 +53,7 @@
.ms-Callout-main
{
p
{
font-weight
:
500
;
color
:
#
333
;
color
:
#
fff
;
}
}
...
...
src/webui/src/App.tsx
View file @
92738382
...
...
@@ -12,6 +12,7 @@ interface AppState {
columnList
:
string
[];
experimentUpdateBroadcast
:
number
;
trialsUpdateBroadcast
:
number
;
maxDurationUnit
:
string
;
metricGraphMode
:
'
max
'
|
'
min
'
;
// tuner's optimize_mode filed
isillegalFinal
:
boolean
;
expWarningMessage
:
string
;
...
...
@@ -26,11 +27,14 @@ export const AppContext = React.createContext({
trialsUpdateBroadcast
:
0
,
metricGraphMode
:
'
max
'
,
bestTrialEntries
:
'
10
'
,
maxDurationUnit
:
'
m
'
,
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
changeColumn
:
(
val
:
string
[])
=>
{},
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
changeMetricGraphMode
:
(
val
:
'
max
'
|
'
min
'
)
=>
{},
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
changeMaxDurationUnit
:
(
val
:
string
)
=>
{},
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
changeEntries
:
(
val
:
string
)
=>
{},
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
updateOverviewPage
:
()
=>
{}
...
...
@@ -47,6 +51,7 @@ class App extends React.Component<{}, AppState> {
experimentUpdateBroadcast
:
0
,
trialsUpdateBroadcast
:
0
,
metricGraphMode
:
'
max
'
,
maxDurationUnit
:
'
m
'
,
isillegalFinal
:
false
,
expWarningMessage
:
''
,
bestTrialEntries
:
'
10
'
,
...
...
@@ -91,6 +96,11 @@ class App extends React.Component<{}, AppState> {
this
.
setState
({
bestTrialEntries
:
entries
});
};
// overview max duration unit
changeMaxDurationUnit
=
(
unit
:
string
):
void
=>
{
this
.
setState
({
maxDurationUnit
:
unit
});
};
updateOverviewPage
=
():
void
=>
{
this
.
setState
(
state
=>
({
experimentUpdateBroadcast
:
state
.
experimentUpdateBroadcast
+
1
...
...
@@ -114,7 +124,8 @@ class App extends React.Component<{}, AppState> {
metricGraphMode
,
isillegalFinal
,
expWarningMessage
,
bestTrialEntries
bestTrialEntries
,
maxDurationUnit
}
=
this
.
state
;
if
(
experimentUpdateBroadcast
===
0
||
trialsUpdateBroadcast
===
0
)
{
return
null
;
// TODO: render a loading page
...
...
@@ -137,7 +148,24 @@ class App extends React.Component<{}, AppState> {
<
Stack
className
=
'contentBox'
>
<
Stack
className
=
'content'
>
{
/* search space & config */
}
<
TrialConfigButton
/>
<
AppContext
.
Provider
value
=
{
{
interval
,
columnList
,
changeColumn
:
this
.
changeColumn
,
experimentUpdateBroadcast
,
trialsUpdateBroadcast
,
metricGraphMode
,
maxDurationUnit
,
changeMaxDurationUnit
:
this
.
changeMaxDurationUnit
,
changeMetricGraphMode
:
this
.
changeMetricGraphMode
,
bestTrialEntries
,
changeEntries
:
this
.
changeEntries
,
updateOverviewPage
:
this
.
updateOverviewPage
}
}
>
<
TrialConfigButton
/>
</
AppContext
.
Provider
>
{
/* if api has error field, show error message */
}
{
errorList
.
map
(
(
item
,
key
)
=>
...
...
@@ -160,6 +188,8 @@ class App extends React.Component<{}, AppState> {
experimentUpdateBroadcast
,
trialsUpdateBroadcast
,
metricGraphMode
,
maxDurationUnit
,
changeMaxDurationUnit
:
this
.
changeMaxDurationUnit
,
changeMetricGraphMode
:
this
.
changeMetricGraphMode
,
bestTrialEntries
,
changeEntries
:
this
.
changeEntries
,
...
...
src/webui/src/components/Overview.tsx
View file @
92738382
...
...
@@ -10,7 +10,8 @@ import { ReBasicInfo } from './overview/experiment/BasicInfo';
import
{
ExpDuration
}
from
'
./overview/count/ExpDuration
'
;
import
{
ExpDurationContext
}
from
'
./overview/count/ExpDurationContext
'
;
import
{
TrialCount
}
from
'
./overview/count/TrialCount
'
;
import
{
Command
}
from
'
./overview/experiment/Command
'
;
import
{
Command1
}
from
'
./overview/command/Command1
'
;
import
{
Command2
}
from
'
./overview/command/Command2
'
;
import
{
TitleContext
}
from
'
./overview/TitleContext
'
;
import
{
itemStyle1
,
itemStyleSucceed
,
itemStyle2
,
entriesOption
}
from
'
./overview/overviewConst
'
;
import
'
../static/style/overview/overview.scss
'
;
...
...
@@ -66,7 +67,13 @@ class Overview extends React.Component<{}, OverviewState> {
return
(
<
AppContext
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
{
const
{
metricGraphMode
,
bestTrialEntries
,
updateOverviewPage
}
=
value
;
const
{
metricGraphMode
,
bestTrialEntries
,
maxDurationUnit
,
updateOverviewPage
,
changeMaxDurationUnit
}
=
value
;
const
maxActive
=
metricGraphMode
===
'
max
'
?
'
active
'
:
''
;
const
minActive
=
metricGraphMode
===
'
min
'
?
'
active
'
:
''
;
return
(
...
...
@@ -88,18 +95,29 @@ class Overview extends React.Component<{}, OverviewState> {
<
Title
/>
</
TitleContext
.
Provider
>
<
ExpDurationContext
.
Provider
value
=
{
{
maxExecDuration
,
execDuration
,
updateOverviewPage
}
}
value
=
{
{
maxExecDuration
,
execDuration
,
updateOverviewPage
,
maxDurationUnit
,
changeMaxDurationUnit
}
}
>
<
ExpDuration
/>
</
ExpDurationContext
.
Provider
>
</
div
>
<
div
className
=
'empty'
/>
<
div
className
=
'trialCount'
>
<
TitleContext
.
Provider
value
=
{
{
text
:
'
Trial numbers
'
,
icon
:
'
NumberSymbol
'
}
}
>
<
Title
/>
</
TitleContext
.
Provider
>
<
ExpDurationContext
.
Provider
value
=
{
{
maxExecDuration
,
execDuration
,
updateOverviewPage
}
}
value
=
{
{
maxExecDuration
,
execDuration
,
updateOverviewPage
,
maxDurationUnit
,
changeMaxDurationUnit
}
}
>
<
TrialCount
/>
</
ExpDurationContext
.
Provider
>
...
...
@@ -114,7 +132,6 @@ class Overview extends React.Component<{}, OverviewState> {
</
TitleContext
.
Provider
>
</
div
>
<
div
className
=
'topTrialTitle'
>
{
/* <Stack horizontal horizontalAlign='space-between'> */
}
<
Stack
horizontal
horizontalAlign
=
'end'
>
<
DefaultButton
onClick
=
{
this
.
clickMaxTop
}
...
...
@@ -152,8 +169,11 @@ class Overview extends React.Component<{}, OverviewState> {
</
Stack
>
<
SuccessTable
trialIds
=
{
bestTrials
.
map
(
trial
=>
trial
.
info
.
id
)
}
/>
</
div
>
<
div
className
=
'overviewCommand'
>
<
Command
/>
<
div
className
=
'overviewCommand1'
>
<
Command1
/>
</
div
>
<
div
className
=
'overviewCommand2'
>
<
Command2
/>
</
div
>
<
div
className
=
'overviewChart'
>
<
Stack
horizontal
>
...
...
src/webui/src/components/TrialsDetail.tsx
View file @
92738382
...
...
@@ -82,7 +82,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
</
Pivot
>
</
div
>
{
/* trial table list */
}
<
div
style
=
{
{
backgroundColor
:
'
#fff
'
}
}
>
<
div
style
=
{
{
backgroundColor
:
'
#fff
'
,
marginTop
:
10
}
}
>
<
TableList
tableSource
=
{
source
}
trialsUpdateBroadcast
=
{
this
.
context
.
trialsUpdateBroadcast
}
...
...
src/webui/src/components/modals/Killjob.tsx
View file @
92738382
...
...
@@ -112,11 +112,15 @@ class KillJob extends React.Component<KillJobProps, KillJobState> {
setInitialFocus
=
{
true
}
>
<
div
className
=
{
styles
.
header
}
>
<
p
className
=
{
styles
.
title
}
>
Kill trial
</
p
>
<
p
className
=
{
styles
.
title
}
style
=
{
{
color
:
'
#333
'
}
}
>
Kill trial
</
p
>
</
div
>
<
div
className
=
{
styles
.
inner
}
>
<
div
>
<
p
className
=
{
styles
.
subtext
}
>
{
prompString
}
</
p
>
<
p
className
=
{
styles
.
subtext
}
style
=
{
{
color
:
'
#333
'
}
}
>
{
prompString
}
</
p
>
</
div
>
</
div
>
<
FocusZone
>
...
...
src/webui/src/components/overview/
experiment
/Command.tsx
→
src/webui/src/components/overview/
command
/Command
1
.tsx
View file @
92738382
import
React
from
'
react
'
;
import
{
TooltipHost
,
Stack
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
'
../../../static/style/overview/command.scss
'
;
export
const
Command
=
():
any
=>
{
const
clusterMetaData
=
EXPERIMENT
.
profile
.
params
.
clusterMetaData
;
export
const
Command1
=
():
any
=>
{
const
tuner
=
EXPERIMENT
.
profile
.
params
.
tuner
;
const
advisor
=
EXPERIMENT
.
profile
.
params
.
advisor
;
const
assessor
=
EXPERIMENT
.
profile
.
params
.
assessor
;
let
title
=
''
;
let
builtinName
=
''
;
let
trialCommand
=
'
unknown
'
;
if
(
tuner
!==
undefined
)
{
title
=
title
.
concat
(
'
Tuner
'
);
if
(
tuner
.
builtinTunerName
!==
undefined
)
{
...
...
@@ -29,35 +26,15 @@ export const Command = (): any => {
builtinName
=
builtinName
.
concat
(
assessor
.
builtinAssessorName
);
}
}
if
(
clusterMetaData
!==
undefined
)
{
for
(
const
item
of
clusterMetaData
)
{
if
(
item
.
key
===
'
command
'
)
{
trialCommand
=
item
.
value
;
}
}
}
return
(
<
div
className
=
'command basic'
>
<
div
className
=
'command1'
>
<
div
>
<
p
>
Training platform
</
p
>
<
div
className
=
'nowrap'
>
{
EXPERIMENT
.
profile
.
params
.
trainingServicePlatform
}
</
div
>
<
p
className
=
'lineMargin'
>
{
title
}
</
p
>
<
div
className
=
'nowrap'
>
{
builtinName
}
</
div
>
</
div
>
<
Stack
className
=
'command2'
>
<
p
>
Log directory
</
p
>
<
div
className
=
'nowrap'
>
<
TooltipHost
content
=
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
className
=
'nowrap'
>
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
</
TooltipHost
>
</
div
>
<
p
className
=
'lineMargin'
>
Trial command
</
p
>
<
div
className
=
'nowrap'
>
<
TooltipHost
content
=
{
trialCommand
||
'
unknown
'
}
className
=
'nowrap'
>
{
trialCommand
||
'
unknown
'
}
</
TooltipHost
>
</
div
>
</
Stack
>
</
div
>
);
};
src/webui/src/components/overview/command/Command2.tsx
0 → 100644
View file @
92738382
import
React
from
'
react
'
;
import
{
TooltipHost
,
DirectionalHint
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
{
TOOLTIP_BACKGROUND_COLOR
}
from
'
../../../static/const
'
;
import
'
../../../static/style/overview/command.scss
'
;
export
const
Command2
=
():
any
=>
{
const
clusterMetaData
=
EXPERIMENT
.
profile
.
params
.
clusterMetaData
;
let
trialCommand
=
'
unknown
'
;
if
(
clusterMetaData
!==
undefined
)
{
for
(
const
item
of
clusterMetaData
)
{
if
(
item
.
key
===
'
command
'
)
{
trialCommand
=
item
.
value
;
}
}
}
return
(
<
div
className
=
'command basic'
>
<
p
>
Log directory
</
p
>
<
div
className
=
'nowrap'
>
<
TooltipHost
content
=
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
className
=
'nowrap'
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
tooltipProps
=
{
{
calloutProps
:
{
styles
:
{
beak
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
beakCurtain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
calloutMain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
}
}
}
}
}
>
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
</
TooltipHost
>
</
div
>
<
p
className
=
'lineMargin'
>
Trial command
</
p
>
<
div
className
=
'nowrap'
>
<
TooltipHost
content
=
{
trialCommand
||
'
unknown
'
}
className
=
'nowrap'
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
tooltipProps
=
{
{
calloutProps
:
{
styles
:
{
beak
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
beakCurtain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
calloutMain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
}
}
}
}
}
>
{
trialCommand
||
'
unknown
'
}
</
TooltipHost
>
</
div
>
</
div
>
);
};
src/webui/src/components/overview/count/EditExperimentParam.tsx
View file @
92738382
import
React
,
{
useState
,
useCallback
,
useContext
}
from
'
react
'
;
import
axios
from
'
axios
'
;
import
{
Dropdown
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
{
AppContext
}
from
'
../../../App
'
;
import
{
EditExpeParamContext
}
from
'
./context
'
;
import
{
MANAGER_IP
}
from
'
../../../static/c
onst
'
;
import
{
convertTimeToSecond
}
from
'
../../../static/
function
'
;
import
{
durationUnit
}
from
'
../overviewC
onst
'
;
import
{
MANAGER_IP
,
MAX_TRIAL_NUMBERS
}
from
'
../../../static/
const
'
;
import
{
Edit
,
CheckMark
,
Cancel
}
from
'
../../buttons/Icon
'
;
import
MessageInfo
from
'
../../modals/MessageInfo
'
;
import
'
../../../static/style/overview/count.scss
'
;
...
...
@@ -28,12 +30,14 @@ export const EditExperimentParam = (): any => {
const
{
title
,
field
,
editType
,
maxExecDuration
,
maxTrialNum
,
trialConcurrency
,
updateOverviewPage
}
=
useContext
(
EditExpeParamContext
);
const
{
maxDurationUnit
,
changeMaxDurationUnit
}
=
useContext
(
AppContext
);
const
[
unit
,
setUnit
]
=
useState
(
maxDurationUnit
);
let
defaultVal
=
''
;
let
editVal
=
''
;
if
(
title
===
'
Max duration
'
)
{
defaultVal
=
maxExecDuration
;
editVal
=
maxExecDuration
;
}
else
if
(
title
===
'
Max trial numbers
'
)
{
}
else
if
(
title
===
MAX_TRIAL_NUMBERS
)
{
defaultVal
=
maxTrialNum
.
toString
();
editVal
=
maxTrialNum
.
toString
();
}
else
{
...
...
@@ -46,32 +50,64 @@ export const EditExperimentParam = (): any => {
setEditValInput
(
event
.
target
.
value
);
}
function
cancelEdit
():
void
{
setEditValInput
(
defaultVal
);
showPencil
();
function
showMessageInfo
(
info
:
string
,
typeInfo
:
string
):
any
{
setInfo
(
info
);
setTypeInfo
(
typeInfo
);
showSucceedInfo
();
setTimeout
(
hideSucceedInfo
,
2000
);
}
function
updateUnit
(
event
:
React
.
FormEvent
<
HTMLDivElement
>
,
item
:
any
):
void
{
if
(
item
!==
undefined
)
{
setUnit
(
item
.
key
);
}
}
async
function
confirmEdit
():
Promise
<
void
>
{
const
isMaxDuration
=
title
===
'
Max duration
'
;
const
newProfile
=
Object
.
assign
({},
EXPERIMENT
.
profile
);
let
beforeParam
=
''
;
if
(
!
isMaxDuration
&&
!
editInputVal
.
match
(
/^
[
1-9
]\d
*$/
))
{
showMessageInfo
(
'
Please enter a positive integer!
'
,
'
error
'
);
return
;
if
(
isMaxDuration
)
{
if
(
!
editInputVal
.
match
(
/^
\d
+
(?=\.{0,1}\d
+$|$
)
/
))
{
showMessageInfo
(
'
Please enter a number!
'
,
'
error
'
);
setEditValInput
(
defaultVal
);
return
;
}
}
else
{
if
(
!
editInputVal
.
match
(
/^
[
1-9
]\d
*$/
))
{
showMessageInfo
(
'
Please enter a positive integer!
'
,
'
error
'
);
setEditValInput
(
defaultVal
);
return
;
}
}
if
(
isMaxDuration
)
{
beforeParam
=
maxExecDuration
;
}
else
if
(
title
===
'
Max trial numbers
'
)
{
}
else
if
(
title
===
MAX_TRIAL_NUMBERS
)
{
beforeParam
=
maxTrialNum
.
toString
();
}
else
{
beforeParam
=
trialConcurrency
.
toString
();
}
if
(
editInputVal
===
beforeParam
)
{
showMessageInfo
(
`Trial
${
field
}
has not changed`
,
'
error
'
);
return
;
if
(
isMaxDuration
)
{
if
(
maxDurationUnit
===
unit
)
{
showMessageInfo
(
`Trial
${
field
}
has not changed`
,
'
error
'
);
return
;
}
}
else
{
showMessageInfo
(
`Trial
${
field
}
has not changed`
,
'
error
'
);
return
;
}
}
if
(
isMaxDuration
)
{
newProfile
.
params
[
field
]
=
convertTimeToSecond
(
editInputVal
);
const
maxDura
=
JSON
.
parse
(
editInputVal
);
if
(
unit
===
'
m
'
)
{
newProfile
.
params
[
field
]
=
maxDura
*
60
;
}
else
if
(
unit
===
'
h
'
)
{
newProfile
.
params
[
field
]
=
maxDura
*
3600
;
}
else
{
newProfile
.
params
[
field
]
=
maxDura
*
24
*
60
*
60
;
}
}
else
{
newProfile
.
params
[
field
]
=
parseInt
(
editInputVal
,
10
);
}
...
...
@@ -82,7 +118,8 @@ export const EditExperimentParam = (): any => {
params
:
{
update_type
:
editType
}
});
if
(
res
.
status
===
200
)
{
showMessageInfo
(
`Successfully updated
${
field
}
`
,
'
success
'
);
showMessageInfo
(
`Successfully updated experiment's
${
field
}
`
,
'
success
'
);
changeMaxDurationUnit
(
unit
);
}
}
catch
(
error
)
{
if
(
error
.
response
&&
error
.
response
.
data
.
error
)
{
...
...
@@ -94,54 +131,87 @@ export const EditExperimentParam = (): any => {
}
else
{
showMessageInfo
(
`Failed to update trial
${
field
}
\nUnknown error`
,
'
error
'
);
}
setEditValInput
(
defaultVal
);
}
showPencil
();
updateOverviewPage
();
}
function
showMessageInfo
(
info
:
string
,
typeInfo
:
string
):
any
{
setInfo
(
info
);
setTypeInfo
(
typeInfo
);
showSucceedInfo
();
setTimeout
(
hideSucceedInfo
,
2000
);
function
cancelEdit
():
void
{
setEditValInput
(
defaultVal
);
showPencil
();
setUnit
(
maxDurationUnit
);
}
function
convertUnit
(
val
:
string
):
string
{
if
(
val
===
'
d
'
)
{
return
'
day
'
;
}
else
if
(
val
===
'
h
'
)
{
return
'
hour
'
;
}
else
if
(
val
===
'
m
'
)
{
return
'
min
'
;
}
else
{
return
val
;
}
}
return
(
<
EditExpeParam
Context
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
{
<
App
Context
.
Consumer
>
{
(
value
s
):
React
.
ReactNode
=>
{
return
(
<
React
.
Fragment
>
<
p
>
{
value
.
title
}
</
p
>
<
div
>
<
input
className
=
{
`
${
value
.
field
}
durationInput`
}
ref
=
{
DurationInputRef
}
disabled
=
{
isShowPencil
?
true
:
false
}
value
=
{
editInputVal
}
onChange
=
{
setInputVal
}
/>
{
isShowPencil
&&
(
<
span
className
=
'edit'
onClick
=
{
hidePencil
}
>
{
Edit
}
</
span
>
)
}
{
!
isShowPencil
&&
(
<
span
className
=
'series'
>
<
span
className
=
'confirm'
onClick
=
{
confirmEdit
}
>
{
CheckMark
}
</
span
>
<
span
className
=
'cancel'
onClick
=
{
cancelEdit
}
>
{
Cancel
}
</
span
>
</
span
>
)
}
<
EditExpeParamContext
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
{
let
editClassName
=
''
;
if
(
value
.
field
===
'
maxExecDuration
'
)
{
editClassName
=
isShowPencil
?
'
noEditDuration
'
:
'
editDuration
'
;
}
return
(
<
React
.
Fragment
>
<
div
className
=
{
`
${
editClassName
}
editparam`
}
>
<
span
>
{
value
.
title
}
</
span
>
<
input
className
=
{
`
${
value
.
field
}
editparam-Input`
}
ref
=
{
DurationInputRef
}
disabled
=
{
isShowPencil
?
true
:
false
}
value
=
{
editInputVal
}
onChange
=
{
setInputVal
}
/>
{
isShowPencil
&&
title
===
'
Max duration
'
&&
(
<
span
>
{
convertUnit
(
values
.
maxDurationUnit
)
}
</
span
>
)
}
{
!
isShowPencil
&&
title
===
'
Max duration
'
&&
(
<
Dropdown
selectedKey
=
{
unit
}
options
=
{
durationUnit
}
className
=
'editparam-dropdown'
onChange
=
{
updateUnit
}
/>
)
}
{
isShowPencil
&&
(
<
span
className
=
'edit'
onClick
=
{
hidePencil
}
>
{
Edit
}
</
span
>
)
}
{
!
isShowPencil
&&
(
<
span
className
=
'series'
>
<
span
className
=
'confirm'
onClick
=
{
confirmEdit
}
>
{
CheckMark
}
</
span
>
<
span
className
=
'cancel'
onClick
=
{
cancelEdit
}
>
{
Cancel
}
</
span
>
</
span
>
)
}
{
isShowSucceedInfo
&&
<
MessageInfo
className
=
'info'
typeInfo
=
{
typeInfo
}
info
=
{
info
}
/>
}
</
div
>
</
React
.
Fragment
>
{
isShowSucceedInfo
&&
(
<
MessageInfo
className
=
'info'
typeInfo
=
{
typeInfo
}
info
=
{
info
}
/>
)
}
</
div
>
</
React
.
Fragment
>
);
}
}
</
EditExpeParamContext
.
Consumer
>
);
}
}
</
EditExpeParam
Context
.
Consumer
>
</
App
Context
.
Consumer
>
);
};
src/webui/src/components/overview/count/ExpDuration.tsx
View file @
92738382
import
React
from
'
react
'
;
import
{
Stack
,
TooltipHost
,
ProgressIndicator
}
from
'
@fluentui/react
'
;
import
{
Stack
,
ProgressIndicator
,
TooltipHost
,
DirectionalHint
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
{
CONTROLTYPE
}
from
'
../../../static/const
'
;
import
{
convertDuration
}
from
'
../../../static/function
'
;
import
{
CONTROLTYPE
,
TOOLTIP_BACKGROUND_COLOR
}
from
'
../../../static/const
'
;
import
{
convertDuration
,
convertTimeAsUnit
}
from
'
../../../static/function
'
;
import
{
EditExperimentParam
}
from
'
./EditExperimentParam
'
;
import
{
ExpDurationContext
}
from
'
./ExpDurationContext
'
;
import
{
EditExpeParamContext
}
from
'
./context
'
;
import
{
durationItem1
,
durationItem2
}
from
'
./commonStyle
'
;
import
'
../../../static/style/overview/count.scss
'
;
const
itemStyle1
:
React
.
CSSProperties
=
{
width
:
'
62%
'
,
height
:
80
};
const
itemStyle2
:
React
.
CSSProperties
=
{
width
:
'
63%
'
,
height
:
80
,
textAlign
:
'
right
'
};
export
const
ExpDuration
=
():
any
=>
(
<
ExpDurationContext
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
{
const
{
maxExecDuration
,
execDuration
,
updateOverviewPage
}
=
value
;
const
{
maxExecDuration
,
execDuration
,
maxDurationUnit
,
updateOverviewPage
}
=
value
;
const
tooltip
=
maxExecDuration
-
execDuration
;
const
maxExecDurationStr
=
convertDuration
(
maxExecDuration
);
const
percent
=
execDuration
/
maxExecDuration
;
const
execDurationStr
=
convertDuration
(
execDuration
);
const
maxExecDurationStr
=
convertTimeAsUnit
(
maxDurationUnit
,
maxExecDuration
).
toString
();
return
(
<
Stack
horizontal
className
=
'ExpDuration'
>
<
div
style
=
{
itemStyle1
}
>
<
TooltipHost
content
=
{
`
${
convertDuration
(
tooltip
)}
remaining`
}
>
<
ProgressIndicator
percentComplete
=
{
percent
}
barHeight
=
{
15
}
/>
<
div
style
=
{
durationItem1
}
>
<
TooltipHost
content
=
{
`
${
convertDuration
(
tooltip
)}
remaining`
}
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
tooltipProps
=
{
{
calloutProps
:
{
styles
:
{
beak
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
beakCurtain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
calloutMain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
}
}
}
}
}
>
<
ProgressIndicator
className
=
{
EXPERIMENT
.
status
}
percentComplete
=
{
percent
}
barHeight
=
{
15
}
/>
</
TooltipHost
>
{
/* execDuration / maxDuration: 20min / 1h */
}
<
div
className
=
'exp-progress'
>
<
span
className
=
{
`
${
EXPERIMENT
.
status
}
bold`
}
>
{
execDurationStr
}
</
span
>
<
span
className
=
'joiner'
>
/
</
span
>
<
span
>
{
`
${
maxExecDurationStr
}
${
maxDurationUnit
}
`
}
</
span
>
</
div
>
</
div
>
<
div
style
=
{
itemStyle2
}
>
<
Stack
horizontal
></
Stack
>
<
div
style
=
{
durationItem2
}
>
<
EditExpeParamContext
.
Provider
value
=
{
{
editType
:
CONTROLTYPE
[
0
],
...
...
src/webui/src/components/overview/count/ExpDurationContext.tsx
View file @
92738382
...
...
@@ -3,5 +3,8 @@ export const ExpDurationContext = React.createContext({
maxExecDuration
:
0
,
execDuration
:
0
,
// eslint-disable-next-line @typescript-eslint/no-empty-function
updateOverviewPage
:
():
void
=>
{}
updateOverviewPage
:
():
void
=>
{},
maxDurationUnit
:
'
m
'
,
// eslint-disable-next-line @typescript-eslint/no-empty-function
changeMaxDurationUnit
:
(
_val
:
'
d
'
|
'
h
'
|
'
m
'
):
void
=>
{}
});
src/webui/src/components/overview/count/TrialCount.tsx
View file @
92738382
import
*
as
React
from
'
react
'
;
import
{
Stack
,
TooltipHost
,
ProgressIndicator
}
from
'
@fluentui/react
'
;
import
{
Stack
,
TooltipHost
,
ProgressIndicator
,
DirectionalHint
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../../static/datamodel
'
;
import
{
CONTROLTYPE
}
from
'
../../../static/const
'
;
import
{
CONTROLTYPE
,
TOOLTIP_BACKGROUND_COLOR
,
MAX_TRIAL_NUMBERS
}
from
'
../../../static/const
'
;
import
{
EditExperimentParam
}
from
'
./EditExperimentParam
'
;
import
{
EditExpeParamContext
}
from
'
./context
'
;
import
{
ExpDurationContext
}
from
'
./ExpDurationContext
'
;
const
itemStyles
:
React
.
CSSProperties
=
{
width
:
'
62%
'
};
const
itemStyle2
:
React
.
CSSProperties
=
{
width
:
'
63%
'
,
textAlign
:
'
right
'
};
const
itemStyle1
:
React
.
CSSProperties
=
{
width
:
'
30%
'
,
height
:
50
};
const
itemRunning
:
React
.
CSSProperties
=
{
width
:
'
42%
'
,
height
:
56
};
import
{
trialCountItem1
,
trialCountItem2
}
from
'
./commonStyle
'
;
export
const
TrialCount
=
():
any
=>
{
const
count
=
TRIALS
.
countStatus
();
...
...
@@ -30,8 +13,9 @@ export const TrialCount = (): any => {
const
stoppedCount
=
count
.
get
(
'
USER_CANCELED
'
)
!
+
count
.
get
(
'
SYS_CANCELED
'
)
!
+
count
.
get
(
'
EARLY_STOPPED
'
)
!
;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const
bar2
=
count
.
get
(
'
RUNNING
'
)
!
+
count
.
get
(
'
SUCCEEDED
'
)
!
+
count
.
get
(
'
FAILED
'
)
!
+
stoppedCount
;
const
maxTrialNum
=
EXPERIMENT
.
profile
.
params
.
maxTrialNum
;
// support type [0, 1], not 98%
const
bar2Percent
=
bar2
/
EXPERIMENT
.
profile
.
params
.
maxTrialNum
;
const
bar2Percent
=
bar2
/
maxTrialNum
;
return
(
<
ExpDurationContext
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
{
...
...
@@ -39,40 +23,36 @@ export const TrialCount = (): any => {
return
(
<
React
.
Fragment
>
<
Stack
horizontal
horizontalAlign
=
'space-between'
className
=
'ExpDuration'
>
<
div
style
=
{
itemStyles
}
>
<
TooltipHost
content
=
{
bar2
.
toString
()
}
>
<
ProgressIndicator
percentComplete
=
{
bar2Percent
}
barHeight
=
{
15
}
/>
<
div
style
=
{
trialCountItem1
}
>
<
TooltipHost
content
=
{
bar2
.
toString
()
}
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
tooltipProps
=
{
{
calloutProps
:
{
styles
:
{
beak
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
beakCurtain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
calloutMain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
}
}
}
}
}
>
<
ProgressIndicator
className
=
{
EXPERIMENT
.
status
}
percentComplete
=
{
bar2Percent
}
barHeight
=
{
15
}
/>
</
TooltipHost
>
<
Stack
horizontal
className
=
'mess'
>
<
div
style
=
{
itemRunning
}
className
=
'basic'
>
<
p
>
Running
</
p
>
<
div
>
{
count
.
get
(
'
RUNNING
'
)
}
</
div
>
</
div
>
<
div
style
=
{
itemStyle1
}
className
=
'basic'
>
<
p
>
Failed
</
p
>
<
div
>
{
count
.
get
(
'
FAILED
'
)
}
</
div
>
</
div
>
<
div
style
=
{
itemStyle1
}
className
=
'basic'
>
<
p
>
Stopped
</
p
>
<
div
>
{
stoppedCount
}
</
div
>
</
div
>
</
Stack
>
<
Stack
horizontal
horizontalAlign
=
'space-between'
className
=
'mess'
>
<
div
style
=
{
itemStyle1
}
className
=
'basic'
>
<
p
>
Succeeded
</
p
>
<
div
>
{
count
.
get
(
'
SUCCEEDED
'
)
}
</
div
>
</
div
>
<
div
style
=
{
itemStyle1
}
className
=
'basic'
>
<
p
>
Waiting
</
p
>
<
div
>
{
count
.
get
(
'
WAITING
'
)
}
</
div
>
</
div
>
</
Stack
>
<
div
className
=
'exp-progress'
>
<
span
className
=
{
`
${
EXPERIMENT
.
status
}
bold`
}
>
{
bar2
}
</
span
>
<
span
className
=
'joiner'
>
/
</
span
>
<
span
>
{
maxTrialNum
}
</
span
>
</
div
>
</
div
>
<
div
style
=
{
itemStyle
2
}
>
<
div
style
=
{
trialCountItem
2
}
>
<
EditExpeParamContext
.
Provider
value
=
{
{
title
:
'
Max trial numbers
'
,
title
:
MAX_TRIAL_NUMBERS
,
field
:
'
maxTrialNum
'
,
editType
:
CONTROLTYPE
[
1
],
maxExecDuration
:
''
,
...
...
@@ -81,7 +61,9 @@ export const TrialCount = (): any => {
updateOverviewPage
}
}
>
<
EditExperimentParam
/>
<
div
className
=
'maxTrialNum'
>
<
EditExperimentParam
/>
</
div
>
</
EditExpeParamContext
.
Provider
>
<
EditExpeParamContext
.
Provider
value
=
{
{
...
...
@@ -99,6 +81,28 @@ export const TrialCount = (): any => {
</
EditExpeParamContext
.
Provider
>
</
div
>
</
Stack
>
<
Stack
horizontal
horizontalAlign
=
'space-between'
className
=
'mess'
>
<
div
className
=
'basic'
>
<
p
>
Running
</
p
>
<
div
>
{
count
.
get
(
'
RUNNING
'
)
}
</
div
>
</
div
>
<
div
className
=
'basic'
>
<
p
>
Succeeded
</
p
>
<
div
>
{
count
.
get
(
'
SUCCEEDED
'
)
}
</
div
>
</
div
>
<
div
className
=
'basic'
>
<
p
>
Stopped
</
p
>
<
div
>
{
stoppedCount
}
</
div
>
</
div
>
<
div
className
=
'basic'
>
<
p
>
Failed
</
p
>
<
div
>
{
count
.
get
(
'
FAILED
'
)
}
</
div
>
</
div
>
<
div
className
=
'basic'
>
<
p
>
Waiting
</
p
>
<
div
>
{
count
.
get
(
'
WAITING
'
)
}
</
div
>
</
div
>
</
Stack
>
</
React
.
Fragment
>
);
}
}
...
...
src/webui/src/components/overview/count/commonStyle.ts
0 → 100644
View file @
92738382
const
durationItem1
:
React
.
CSSProperties
=
{
width
:
'
33%
'
};
const
durationItem2
:
React
.
CSSProperties
=
{
width
:
'
52%
'
,
paddingLeft
:
'
15%
'
};
const
trialCountItem1
:
React
.
CSSProperties
=
{
width
:
'
33%
'
};
const
trialCountItem2
:
React
.
CSSProperties
=
{
width
:
'
52%
'
};
export
{
durationItem1
,
durationItem2
,
trialCountItem1
,
trialCountItem2
};
src/webui/src/components/overview/experiment/BasicInfo.tsx
View file @
92738382
...
...
@@ -24,61 +24,63 @@ export const ReBasicInfo = (): any => {
return
(
<
div
>
<
div
className
=
'basic'
>
<
p
>
ID:
{
EXPERIMENT
.
profile
.
id
}
</
p
>
<
p
>
ID:
<
span
>
{
EXPERIMENT
.
profile
.
id
}
</
span
>
</
p
>
<
div
>
{
EXPERIMENT
.
profile
.
params
.
experimentName
}
</
div
>
</
div
>
<
div
className
=
'basic'
>
<
Stack
className
=
'basic'
>
<
p
>
Status
</
p
>
<
Stack
horizontal
className
=
'status'
>
<
span
className
=
{
`
${
EXPERIMENT
.
status
}
status-text`
}
>
{
EXPERIMENT
.
status
}
</
span
>
{
EXPERIMENT
.
status
===
'
ERROR
'
?
(
<
div
>
<
div
className
=
{
styles
.
buttonArea
}
ref
=
{
ref
}
>
<
IconButton
iconProps
=
{
{
iconName
:
'
info
'
}
}
onClick
=
{
isCalloutVisible
?
onDismiss
:
showCallout
}
/>
</
div
>
{
isCalloutVisible
&&
(
<
Callout
className
=
{
styles
.
callout
}
ariaLabelledBy
=
{
labelId
}
ariaDescribedBy
=
{
descriptionId
}
role
=
'alertdialog'
gapSpace
=
{
0
}
target
=
{
ref
}
onDismiss
=
{
onDismiss
}
setInitialFocus
=
{
true
}
>
<
div
className
=
{
styles
.
header
}
>
<
p
className
=
{
styles
.
title
}
id
=
{
labelId
}
>
Error
</
p
>
</
div
>
<
div
className
=
{
styles
.
inner
}
>
<
p
className
=
{
styles
.
subtext
}
id
=
{
descriptionId
}
>
{
EXPERIMENT
.
error
}
</
p
>
<
div
className
=
{
styles
.
actions
}
>
<
Link
className
=
{
styles
.
link
}
onClick
=
{
ShowLogDrawer
}
>
Learn about
</
Link
>
</
div
>
</
div
>
</
Callout
>
)
}
<
p
>
Status
</
p
>
<
Stack
horizontal
className
=
'status'
>
<
span
className
=
{
`
${
EXPERIMENT
.
status
}
status-text`
}
>
{
EXPERIMENT
.
status
}
</
span
>
{
EXPERIMENT
.
status
===
'
ERROR
'
?
(
<
div
>
<
div
className
=
{
styles
.
buttonArea
}
ref
=
{
ref
}
>
<
IconButton
iconProps
=
{
{
iconName
:
'
info
'
}
}
onClick
=
{
isCalloutVisible
?
onDismiss
:
showCallout
}
/>
</
div
>
)
:
null
}
</
Stack
>
{
isCalloutVisible
&&
(
<
Callout
className
=
{
styles
.
callout
}
ariaLabelledBy
=
{
labelId
}
ariaDescribedBy
=
{
descriptionId
}
role
=
'alertdialog'
gapSpace
=
{
0
}
target
=
{
ref
}
onDismiss
=
{
onDismiss
}
setInitialFocus
=
{
true
}
>
<
div
className
=
{
styles
.
header
}
>
<
p
className
=
{
styles
.
title
}
id
=
{
labelId
}
style
=
{
{
color
:
'
#333
'
}
}
>
Error
</
p
>
</
div
>
<
div
className
=
{
styles
.
inner
}
>
<
p
className
=
{
styles
.
subtext
}
id
=
{
descriptionId
}
style
=
{
{
color
:
'
#333
'
}
}
>
{
EXPERIMENT
.
error
}
</
p
>
<
div
className
=
{
styles
.
actions
}
>
<
Link
className
=
{
styles
.
link
}
onClick
=
{
ShowLogDrawer
}
>
Learn about
</
Link
>
</
div
>
</
div
>
</
Callout
>
)
}
</
div
>
)
:
null
}
</
Stack
>
</
div
>
<
div
className
=
'basic'
>
<
BestMetricContext
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
(
<
Stack
>
<
Stack
className
=
'bestMetric'
>
<
p
>
Best metric
</
p
>
<
div
>
{
isNaN
(
value
.
bestAccuracy
)
?
'
N/A
'
:
value
.
bestAccuracy
.
toFixed
(
6
)
}
</
div
>
<
div
className
=
{
EXPERIMENT
.
status
}
>
{
isNaN
(
value
.
bestAccuracy
)
?
'
N/A
'
:
value
.
bestAccuracy
.
toFixed
(
6
)
}
</
div
>
</
Stack
>
)
}
</
BestMetricContext
.
Consumer
>
...
...
src/webui/src/components/overview/overviewConst.ts
View file @
92738382
...
...
@@ -18,4 +18,10 @@ const entriesOption = [
{
key
:
'
100
'
,
text
:
'
100
'
}
];
export
{
itemStyle1
,
itemStyleSucceed
,
itemStyle2
,
entriesOption
};
const
durationUnit
=
[
{
key
:
'
m
'
,
text
:
'
m
'
},
{
key
:
'
h
'
,
text
:
'
h
'
},
{
key
:
'
d
'
,
text
:
'
d
'
}
];
export
{
itemStyle1
,
itemStyleSucceed
,
itemStyle2
,
entriesOption
,
durationUnit
};
src/webui/src/components/overview/table/SuccessTable.tsx
View file @
92738382
...
...
@@ -70,40 +70,41 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
</
div
>
</
div
>
);
columns
=
[
{
name
:
'
Trial No.
'
,
key
:
'
sequenceId
'
,
fieldName
:
'
sequenceId
'
,
// required!
minWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
maxWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
minWidth
:
5
0
,
maxWidth
:
87
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
<
div
className
=
'succeed-padding'
>
{
item
.
sequenceId
}
</
div
>
},
{
name
:
'
ID
'
,
key
:
'
id
'
,
fieldName
:
'
id
'
,
minWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
maxWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
minWidth
:
5
0
,
maxWidth
:
87
,
isResizable
:
true
,
className
:
'
tableHead leftTitle
'
,
data
:
'
string
'
,
onColumnClick
:
this
.
onColumnClick
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
<
div
className
=
'succeed-padding'
>
{
item
.
id
}
</
div
>
},
{
name
:
'
Duration
'
,
key
:
'
duration
'
,
minWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
maxWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
minWidth
:
6
5
,
maxWidth
:
150
,
isResizable
:
true
,
fieldName
:
'
duration
'
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
(
<
div
className
=
'durationsty'
>
<
div
className
=
'durationsty
succeed-padding
'
>
<
div
>
{
convertDuration
(
item
.
duration
)
}
</
div
>
</
div
>
)
...
...
@@ -111,26 +112,24 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
{
name
:
'
Status
'
,
key
:
'
status
'
,
minWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
maxWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
minWidth
:
80
,
maxWidth
:
150
,
isResizable
:
true
,
fieldName
:
'
status
'
,
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
{
return
<
div
className
=
{
`
${
item
.
status
}
commonStyle`
}
>
{
item
.
status
}
</
div
>
;
}
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
(
<
div
className
=
{
`
${
item
.
status
}
commonStyle
succeed-padding
`
}
>
{
item
.
status
}
</
div
>
)
},
{
name
:
'
Default metric
'
,
key
:
'
accuracy
'
,
fieldName
:
'
accuracy
'
,
minWidth
:
(
window
.
innerWidth
*
0.333
-
200
)
/
5
,
//
maxWidth:
(window.innerWidth * 0.333 - 150) / 5
,
minWidth
:
100
,
maxWidth
:
160
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
{
return
<
DefaultMetric
trialId
=
{
item
.
id
}
/>;
}
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
<
DefaultMetric
trialId
=
{
item
.
id
}
/>
}
];
...
...
src/webui/src/components/public-child/DefaultMetric.tsx
View file @
92738382
...
...
@@ -13,7 +13,7 @@ class DefaultMetric extends React.Component<DefaultMetricProps, {}> {
render
():
React
.
ReactNode
{
const
accuracy
=
TRIALS
.
getTrial
(
this
.
props
.
trialId
).
accuracy
;
return
<
div
>
{
accuracy
!==
undefined
?
formatAccuracy
(
accuracy
)
:
'
--
'
}
</
div
>;
return
<
div
className
=
'succeed-padding'
>
{
accuracy
!==
undefined
?
formatAccuracy
(
accuracy
)
:
'
--
'
}
</
div
>;
}
}
...
...
src/webui/src/components/public-child/config/TrialConfigButton.tsx
View file @
92738382
...
...
@@ -18,8 +18,8 @@ export const TrialConfigButton = (): any => {
return
(
<
React
.
Fragment
>
<
Stack
className
=
'config'
>
<
DefaultButton
text
=
'Config'
onClick
=
{
showTrialConfigpPanel
}
/>
<
DefaultButton
text
=
'Search space'
onClick
=
{
showSearchSpacePanel
}
/>
<
DefaultButton
text
=
'Config'
onClick
=
{
showTrialConfigpPanel
}
/>
</
Stack
>
{
isShowConfigPanel
&&
<
TrialConfigPanel
hideConfigPanel
=
{
hideConfigPanel
}
activeTab
=
{
activeTab
}
/>
}
</
React
.
Fragment
>
...
...
src/webui/src/components/public-child/config/TrialConfigPanel.tsx
View file @
92738382
...
...
@@ -3,7 +3,8 @@ import { Stack, Panel, Pivot, PivotItem, PrimaryButton } from '@fluentui/react';
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
MonacoEditor
from
'
react-monaco-editor
'
;
import
{
MONACO
}
from
'
../../../static/const
'
;
import
{
convertDuration
}
from
'
../../../static/function
'
;
import
{
AppContext
}
from
'
../../../App
'
;
import
{
convertDuration
,
convertTimeAsUnit
}
from
'
../../../static/function
'
;
import
{
prettyStringify
}
from
'
../../../static/json_util
'
;
import
lodash
from
'
lodash
'
;
import
'
../../../static/style/logDrawer.scss
'
;
...
...
@@ -15,6 +16,7 @@ interface LogDrawerProps {
interface
LogDrawerState
{
panelInnerHeight
:
number
;
innerWidth
:
number
;
}
class
TrialConfigPanel
extends
React
.
Component
<
LogDrawerProps
,
LogDrawerState
>
{
...
...
@@ -22,13 +24,15 @@ class TrialConfigPanel extends React.Component<LogDrawerProps, LogDrawerState> {
super
(
props
);
this
.
state
=
{
panelInnerHeight
:
window
.
innerHeight
panelInnerHeight
:
window
.
innerHeight
,
innerWidth
:
window
.
innerWidth
};
}
setLogDrawerHeight
():
void
{
this
.
setState
(()
=>
({
panelInnerHeight
:
window
.
innerHeight
}));
}
// use arrow function for change window size met error: this.setState is not a function
setLogDrawerHeight
=
():
void
=>
{
this
.
setState
(()
=>
({
panelInnerHeight
:
window
.
innerHeight
,
innerWidth
:
window
.
innerWidth
}));
};
async
componentDidMount
():
Promise
<
void
>
{
window
.
addEventListener
(
'
resize
'
,
this
.
setLogDrawerHeight
);
...
...
@@ -40,7 +44,7 @@ class TrialConfigPanel extends React.Component<LogDrawerProps, LogDrawerState> {
render
():
React
.
ReactNode
{
const
{
hideConfigPanel
,
activeTab
}
=
this
.
props
;
const
{
panelInnerHeight
}
=
this
.
state
;
const
{
panelInnerHeight
,
innerWidth
}
=
this
.
state
;
// [marginTop 16px] + [Search space 46px] +
// button[height: 32px, marginTop: 45px, marginBottom: 25px] + [padding-bottom: 20px]
const
monacoEditorHeight
=
panelInnerHeight
-
184
;
...
...
@@ -58,45 +62,61 @@ class TrialConfigPanel extends React.Component<LogDrawerProps, LogDrawerState> {
};
const
profile
=
lodash
.
cloneDeep
(
EXPERIMENT
.
profile
);
profile
.
execDuration
=
convertDuration
(
profile
.
execDuration
);
profile
.
params
.
maxExecDuration
=
convertDuration
(
profile
.
params
.
maxExecDuration
);
const
showProfile
=
JSON
.
stringify
(
profile
,
filter
,
2
);
const
prettyWidth
=
innerWidth
>
1400
?
100
:
60
;
return
(
<
Stack
>
<
Panel
isOpen
=
{
true
}
hasCloseButton
=
{
false
}
isFooterAtBottom
=
{
true
}
isLightDismiss
=
{
true
}
onLightDismissClick
=
{
hideConfigPanel
}
>
<
div
className
=
'log-tab-body'
>
<
Pivot
initialSelectedKey
=
{
activeTab
}
style
=
{
{
minHeight
:
190
,
paddingTop
:
'
16px
'
}
}
>
<
PivotItem
headerText
=
'Search space'
itemKey
=
'search space'
>
<
MonacoEditor
height
=
{
monacoEditorHeight
}
language
=
'json'
theme
=
'vs-light'
value
=
{
prettyStringify
(
EXPERIMENT
.
searchSpace
,
300
,
2
)
}
options
=
{
MONACO
}
/>
</
PivotItem
>
<
PivotItem
headerText
=
'Config'
itemKey
=
'config'
>
<
div
className
=
'profile'
>
<
MonacoEditor
width
=
'100%'
height
=
{
monacoEditorHeight
}
language
=
'json'
theme
=
'vs-light'
value
=
{
showProfile
}
options
=
{
MONACO
}
/>
<
AppContext
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
{
const
unit
=
value
.
maxDurationUnit
;
profile
.
params
.
maxExecDuration
=
`
${
convertTimeAsUnit
(
unit
,
profile
.
params
.
maxExecDuration
)}${
unit
}
`
;
const
showProfile
=
JSON
.
stringify
(
profile
,
filter
,
2
);
return
(
<
Stack
>
<
Panel
isOpen
=
{
true
}
hasCloseButton
=
{
false
}
isFooterAtBottom
=
{
true
}
isLightDismiss
=
{
true
}
onLightDismissClick
=
{
hideConfigPanel
}
>
<
div
className
=
'log-tab-body'
>
<
Pivot
initialSelectedKey
=
{
activeTab
}
style
=
{
{
minHeight
:
190
,
paddingTop
:
'
16px
'
}
}
>
<
PivotItem
headerText
=
'Search space'
itemKey
=
'search space'
>
<
MonacoEditor
height
=
{
monacoEditorHeight
}
language
=
'json'
theme
=
'vs-light'
value
=
{
prettyStringify
(
EXPERIMENT
.
searchSpace
,
prettyWidth
,
2
)
}
options
=
{
MONACO
}
/>
</
PivotItem
>
<
PivotItem
headerText
=
'Config'
itemKey
=
'config'
>
<
div
className
=
'profile'
>
<
MonacoEditor
width
=
'100%'
height
=
{
monacoEditorHeight
}
language
=
'json'
theme
=
'vs-light'
value
=
{
showProfile
}
options
=
{
MONACO
}
/>
</
div
>
</
PivotItem
>
</
Pivot
>
</
div
>
</
PivotItem
>
</
Pivot
>
</
div
>
<
PrimaryButton
text
=
'Close'
className
=
'configClose'
onClick
=
{
hideConfigPanel
}
/>
</
Panel
>
</
Stack
>
<
PrimaryButton
text
=
'Close'
className
=
'configClose'
onClick
=
{
hideConfigPanel
}
/
>
</
Panel
>
</
Stack
>
);
}
}
</
AppContext
.
Consumer
>
);
}
}
...
...
src/webui/src/components/trial-detail/TableList.tsx
View file @
92738382
...
...
@@ -9,10 +9,12 @@ import {
SelectionMode
,
Stack
,
StackItem
,
TooltipHost
TooltipHost
,
DirectionalHint
}
from
'
@fluentui/react
'
;
import
React
from
'
react
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
TOOLTIP_BACKGROUND_COLOR
}
from
'
../../static/const
'
;
import
{
convertDuration
,
formatTimestamp
}
from
'
../../static/function
'
;
import
{
TableObj
}
from
'
../../static/interface
'
;
import
'
../../static/style/search.scss
'
;
...
...
@@ -316,7 +318,19 @@ class TableList extends React.Component<TableListProps, TableListState> {
...((
k
.
startsWith
(
'
metric/
'
)
||
k
.
startsWith
(
'
space/
'
))
&&
{
// show tooltip
onRender
:
(
record
):
React
.
ReactNode
=>
(
<
TooltipHost
content
=
{
record
[
k
]
}
>
<
TooltipHost
content
=
{
record
[
k
]
}
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
tooltipProps
=
{
{
calloutProps
:
{
styles
:
{
beak
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
beakCurtain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
calloutMain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
}
}
}
}
}
>
<
div
className
=
'ellipsis'
>
{
record
[
k
]
}
</
div
>
</
TooltipHost
>
)
...
...
@@ -324,7 +338,19 @@ class TableList extends React.Component<TableListProps, TableListState> {
...(
k
===
'
latestAccuracy
'
&&
{
// FIXME: this is ad-hoc
onRender
:
(
record
):
React
.
ReactNode
=>
(
<
TooltipHost
content
=
{
record
.
_formattedLatestAccuracy
}
>
<
TooltipHost
content
=
{
record
.
_formattedLatestAccuracy
}
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
tooltipProps
=
{
{
calloutProps
:
{
styles
:
{
beak
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
beakCurtain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
calloutMain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
}
}
}
}
}
>
<
div
className
=
'ellipsis'
>
{
record
.
_formattedLatestAccuracy
}
</
div
>
</
TooltipHost
>
)
...
...
src/webui/src/index.tsx
View file @
92738382
import
React
,
{
lazy
,
Suspense
}
from
'
react
'
;
import
ReactDOM
from
'
react-dom
'
;
import
App
from
'
./App
'
;
import
{
BrowserRouter
as
Router
,
Route
,
Switch
,
Redirect
}
from
'
react-router-dom
'
;
import
{
BrowserRouter
as
Router
,
Route
,
Switch
}
from
'
react-router-dom
'
;
const
Overview
=
lazy
(()
=>
import
(
'
./components/Overview
'
));
const
TrialsDetail
=
lazy
(()
=>
import
(
'
./components/TrialsDetail
'
));
import
'
./index.css
'
;
...
...
@@ -19,9 +19,9 @@ ReactDOM.render(
</
div
>
}
>
<
Route
path
=
'/'
component
=
{
Overview
}
exact
/>
<
Route
path
=
'/oview'
component
=
{
Overview
}
/>
<
Route
path
=
'/detail'
component
=
{
TrialsDetail
}
/>
<
Route
path
=
'/'
render
=
{
():
React
.
ReactNode
=>
<
Redirect
to
=
{
{
pathname
:
'
/oview
'
}
}
/>
}
/>
</
Suspense
>
</
Switch
>
</
App
>
...
...
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