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
b40e3db7
Commit
b40e3db7
authored
Dec 01, 2020
by
quzha
Browse files
Merge branch 'master' of github.com:Microsoft/nni into dev-retiarii
parents
efa4e31c
95f731e4
Changes
226
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
454 additions
and
295 deletions
+454
-295
ts/webui/src/components/overview/command/Command1.tsx
ts/webui/src/components/overview/command/Command1.tsx
+15
-10
ts/webui/src/components/overview/count/EditExperimentParam.tsx
...bui/src/components/overview/count/EditExperimentParam.tsx
+3
-3
ts/webui/src/components/overview/count/ExpDuration.tsx
ts/webui/src/components/overview/count/ExpDuration.tsx
+7
-3
ts/webui/src/components/overview/count/TrialCount.tsx
ts/webui/src/components/overview/count/TrialCount.tsx
+5
-5
ts/webui/src/components/overview/count/commonStyle.ts
ts/webui/src/components/overview/count/commonStyle.ts
+8
-9
ts/webui/src/components/overview/experiment/BasicInfo.tsx
ts/webui/src/components/overview/experiment/BasicInfo.tsx
+66
-68
ts/webui/src/components/overview/table/Details.tsx
ts/webui/src/components/overview/table/Details.tsx
+0
-37
ts/webui/src/components/overview/table/SuccessTable.tsx
ts/webui/src/components/overview/table/SuccessTable.tsx
+127
-62
ts/webui/src/components/public-child/MonacoEditor.tsx
ts/webui/src/components/public-child/MonacoEditor.tsx
+2
-2
ts/webui/src/components/slideNav/IconButtonTemplet.tsx
ts/webui/src/components/slideNav/IconButtonTemplet.tsx
+29
-0
ts/webui/src/components/slideNav/SlideNavBtns.tsx
ts/webui/src/components/slideNav/SlideNavBtns.tsx
+40
-0
ts/webui/src/components/slideNav/TrialConfigPanel.tsx
ts/webui/src/components/slideNav/TrialConfigPanel.tsx
+35
-33
ts/webui/src/components/trial-detail/TableList.tsx
ts/webui/src/components/trial-detail/TableList.tsx
+4
-33
ts/webui/src/static/function.ts
ts/webui/src/static/function.ts
+34
-1
ts/webui/src/static/interface.ts
ts/webui/src/static/interface.ts
+9
-2
ts/webui/src/static/model/trial.ts
ts/webui/src/static/model/trial.ts
+3
-3
ts/webui/src/static/model/trialmanager.ts
ts/webui/src/static/model/trialmanager.ts
+3
-3
ts/webui/src/static/style/common.scss
ts/webui/src/static/style/common.scss
+5
-0
ts/webui/src/static/style/logDrawer.scss
ts/webui/src/static/style/logDrawer.scss
+43
-9
ts/webui/src/static/style/overview/count.scss
ts/webui/src/static/style/overview/count.scss
+16
-12
No files found.
ts/webui/src/components/overview/command/Command1.tsx
View file @
b40e3db7
...
...
@@ -6,24 +6,29 @@ export const Command1 = (): any => {
const
tuner
=
EXPERIMENT
.
profile
.
params
.
tuner
;
const
advisor
=
EXPERIMENT
.
profile
.
params
.
advisor
;
const
assessor
=
EXPERIMENT
.
profile
.
params
.
assessor
;
le
t
title
=
''
;
le
t
builtinName
=
''
;
cons
t
title
:
string
[]
=
[]
;
cons
t
builtinName
:
string
[]
=
[]
;
if
(
tuner
!==
undefined
)
{
title
=
title
.
concat
(
'
Tuner
'
);
title
.
push
(
'
Tuner
'
);
if
(
tuner
.
builtinTunerName
!==
undefined
)
{
builtinName
=
builtinName
.
concat
(
tuner
.
builtinTunerName
);
builtinName
.
push
(
tuner
.
builtinTunerName
);
}
}
if
(
advisor
!==
undefined
)
{
title
=
title
.
concat
(
'
/ Asses
sor
'
);
title
.
push
(
'
Advi
sor
'
);
if
(
advisor
.
builtinAdvisorName
!==
undefined
)
{
builtinName
=
builtinName
.
concat
(
advisor
.
builtinAdvisorName
);
builtinName
.
push
(
advisor
.
builtinAdvisorName
);
}
if
(
advisor
.
className
!==
undefined
)
{
builtinName
.
push
(
advisor
.
className
);
}
}
if
(
assessor
!==
undefined
)
{
title
=
title
.
concat
(
'
/ Addvi
sor
'
);
title
.
push
(
'
Asses
sor
'
);
if
(
assessor
.
builtinAssessorName
!==
undefined
)
{
builtinName
=
builtinName
.
concat
(
assessor
.
builtinAssessorName
);
builtinName
.
push
(
assessor
.
builtinAssessorName
);
}
}
...
...
@@ -32,8 +37,8 @@ export const Command1 = (): any => {
<
div
>
<
p
className
=
'command'
>
Training platform
</
p
>
<
div
className
=
'nowrap'
>
{
EXPERIMENT
.
profile
.
params
.
trainingServicePlatform
}
</
div
>
<
p
className
=
'lineMargin'
>
{
title
}
</
p
>
<
div
className
=
'nowrap'
>
{
builtinName
}
</
div
>
<
p
className
=
'lineMargin'
>
{
title
.
join
(
'
/
'
)
}
</
p
>
<
div
className
=
'nowrap'
>
{
builtinName
.
join
(
'
/
'
)
}
</
div
>
</
div
>
</
div
>
);
...
...
ts/webui/src/components/overview/count/EditExperimentParam.tsx
View file @
b40e3db7
...
...
@@ -188,16 +188,16 @@ export const EditExperimentParam = (): any => {
/>
)
}
{
isShowPencil
&&
(
<
span
className
=
'edit'
onClick
=
{
hidePencil
}
>
<
span
className
=
'edit
cursor
'
onClick
=
{
hidePencil
}
>
{
Edit
}
</
span
>
)
}
{
!
isShowPencil
&&
(
<
span
className
=
'series'
>
<
span
className
=
'confirm'
onClick
=
{
confirmEdit
}
>
<
span
className
=
'confirm
cursor
'
onClick
=
{
confirmEdit
}
>
{
CheckMark
}
</
span
>
<
span
className
=
'cancel'
onClick
=
{
cancelEdit
}
>
<
span
className
=
'cancel
cursor
'
onClick
=
{
cancelEdit
}
>
{
Cancel
}
</
span
>
</
span
>
...
...
ts/webui/src/components/overview/count/ExpDuration.tsx
View file @
b40e3db7
...
...
@@ -6,7 +6,7 @@ import { convertDuration, convertTimeAsUnit } from '../../../static/function';
import
{
EditExperimentParam
}
from
'
./EditExperimentParam
'
;
import
{
ExpDurationContext
}
from
'
./ExpDurationContext
'
;
import
{
EditExpeParamContext
}
from
'
./context
'
;
import
{
durationItem1
,
durationItem2
}
from
'
./commonStyle
'
;
import
{
leftProgress
,
durationItem2
,
progressHeight
}
from
'
./commonStyle
'
;
import
'
../../../static/style/overview/count.scss
'
;
export
const
ExpDuration
=
():
any
=>
(
...
...
@@ -19,7 +19,7 @@ export const ExpDuration = (): any => (
const
maxExecDurationStr
=
convertTimeAsUnit
(
maxDurationUnit
,
maxExecDuration
).
toString
();
return
(
<
Stack
horizontal
className
=
'ExpDuration'
>
<
div
style
=
{
durationItem1
}
>
<
div
style
=
{
leftProgress
}
>
<
TooltipHost
content
=
{
`
${
convertDuration
(
tooltip
)}
remaining`
}
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
...
...
@@ -33,7 +33,11 @@ export const ExpDuration = (): any => (
}
}
}
>
<
ProgressIndicator
className
=
{
EXPERIMENT
.
status
}
percentComplete
=
{
percent
}
barHeight
=
{
15
}
/>
<
ProgressIndicator
className
=
{
EXPERIMENT
.
status
}
percentComplete
=
{
percent
}
barHeight
=
{
progressHeight
}
/>
</
TooltipHost
>
{
/* execDuration / maxDuration: 20min / 1h */
}
<
div
className
=
'exp-progress'
>
...
...
ts/webui/src/components/overview/count/TrialCount.tsx
View file @
b40e3db7
...
...
@@ -5,7 +5,7 @@ import { CONTROLTYPE, TOOLTIP_BACKGROUND_COLOR, MAX_TRIAL_NUMBERS } from '../../
import
{
EditExperimentParam
}
from
'
./EditExperimentParam
'
;
import
{
EditExpeParamContext
}
from
'
./context
'
;
import
{
ExpDurationContext
}
from
'
./ExpDurationContext
'
;
import
{
trialCountItem1
,
trialCountItem2
}
from
'
./commonStyle
'
;
import
{
leftProgress
,
trialCountItem2
,
progressHeight
}
from
'
./commonStyle
'
;
export
const
TrialCount
=
():
any
=>
{
const
count
=
TRIALS
.
countStatus
();
...
...
@@ -23,9 +23,9 @@ export const TrialCount = (): any => {
return
(
<
React
.
Fragment
>
<
Stack
horizontal
horizontalAlign
=
'space-between'
className
=
'ExpDuration'
>
<
div
style
=
{
trialCountItem1
}
>
<
div
style
=
{
leftProgress
}
>
<
TooltipHost
content
=
{
bar2
.
toString
()
}
content
=
{
`
${
bar2
.
toString
()}
trials`
}
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
tooltipProps
=
{
{
calloutProps
:
{
...
...
@@ -40,7 +40,7 @@ export const TrialCount = (): any => {
<
ProgressIndicator
className
=
{
EXPERIMENT
.
status
}
percentComplete
=
{
bar2Percent
}
barHeight
=
{
15
}
barHeight
=
{
progressHeight
}
/>
</
TooltipHost
>
<
div
className
=
'exp-progress'
>
...
...
@@ -81,7 +81,7 @@ export const TrialCount = (): any => {
</
EditExpeParamContext
.
Provider
>
</
div
>
</
Stack
>
<
Stack
horizontal
horizontalAlign
=
'space-between'
className
=
'
mes
s'
>
<
Stack
horizontal
horizontalAlign
=
'space-between'
className
=
'
trialStatu
s'
>
<
div
className
=
'basic'
>
<
p
>
Running
</
p
>
<
div
>
{
count
.
get
(
'
RUNNING
'
)
}
</
div
>
...
...
ts/webui/src/components/overview/count/commonStyle.ts
View file @
b40e3db7
const
durationItem1
:
React
.
CSSProperties
=
{
width
:
'
33%
'
const
leftProgress
:
React
.
CSSProperties
=
{
width
:
'
33%
'
,
position
:
'
relative
'
,
top
:
6
};
const
durationItem2
:
React
.
CSSProperties
=
{
width
:
'
5
2
%
'
,
width
:
'
5
1.5
%
'
,
paddingLeft
:
'
15%
'
};
const
trialCountItem1
:
React
.
CSSProperties
=
{
width
:
'
33%
'
};
const
trialCountItem2
:
React
.
CSSProperties
=
{
width
:
'
5
2
%
'
width
:
'
5
1.5
%
'
};
export
{
durationItem1
,
durationItem2
,
trialCountItem
1
,
trialCountItem2
};
const
progressHeight
=
8
;
export
{
leftProgress
,
durationItem2
,
trialCountItem
2
,
progressHeight
};
ts/webui/src/components/overview/experiment/BasicInfo.tsx
View file @
b40e3db7
...
...
@@ -23,11 +23,12 @@ export const ReBasicInfo = (): any => {
return
(
<
div
>
<
Stack
horizontal
horizontalAlign
=
'space-between'
className
=
'mess'
>
<
div
className
=
'basic'
>
<
p
>
ID:
<
span
>
{
EXPERIMENT
.
profile
.
id
}
</
span
>
</
p
>
<
div
>
{
EXPERIMENT
.
profile
.
params
.
experimentName
}
</
div
>
<
p
>
Name
</
p
>
<
div
className
=
'nowrap'
>
{
EXPERIMENT
.
profile
.
params
.
experimentName
}
</
div
>
<
p
className
=
'margin'
>
ID
</
p
>
<
div
className
=
'nowrap'
>
{
EXPERIMENT
.
profile
.
id
}
</
div
>
</
div
>
<
div
className
=
'basic'
>
<
p
>
Status
</
p
>
...
...
@@ -53,12 +54,12 @@ export const ReBasicInfo = (): any => {
setInitialFocus
=
{
true
}
>
<
div
className
=
{
styles
.
header
}
>
<
p
className
=
{
styles
.
title
}
id
=
{
labelId
}
style
=
{
{
color
:
'
#333
'
}
}
>
<
p
className
=
{
`
${
styles
.
title
}
color`
}
id
=
{
labelId
}
>
Error
</
p
>
</
div
>
<
div
className
=
{
styles
.
inner
}
>
<
p
className
=
{
styles
.
subtext
}
id
=
{
descriptionId
}
style
=
{
{
color
:
'
#333
'
}
}
>
<
p
className
=
{
`
${
styles
.
subtext
}
color`
}
id
=
{
descriptionId
}
>
{
EXPERIMENT
.
error
}
</
p
>
<
div
className
=
{
styles
.
actions
}
>
...
...
@@ -72,12 +73,10 @@ export const ReBasicInfo = (): any => {
</
div
>
)
:
null
}
</
Stack
>
</
div
>
<
div
className
=
'basic'
>
<
BestMetricContext
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
(
<
Stack
className
=
'bestMetric'
>
<
p
>
Best metric
</
p
>
<
p
className
=
'margin'
>
Best metric
</
p
>
<
div
className
=
{
EXPERIMENT
.
status
}
>
{
isNaN
(
value
.
bestAccuracy
)
?
'
N/A
'
:
value
.
bestAccuracy
.
toFixed
(
6
)
}
</
div
>
...
...
@@ -88,11 +87,10 @@ export const ReBasicInfo = (): any => {
<
div
className
=
'basic'
>
<
p
>
Start time
</
p
>
<
div
className
=
'nowrap'
>
{
formatTimestamp
(
EXPERIMENT
.
profile
.
startTime
)
}
</
div
>
</
div
>
<
div
className
=
'basic'
>
<
p
>
End time
</
p
>
<
p
className
=
'margin'
>
End time
</
p
>
<
div
className
=
'nowrap'
>
{
formatTimestamp
(
EXPERIMENT
.
profile
.
endTime
)
}
</
div
>
</
div
>
</
Stack
>
{
/* learn about click -> default active key is dispatcher. */
}
{
isShowLogDrawer
?
<
LogDrawer
closeDrawer
=
{
closeLogDrawer
}
activeTab
=
'dispatcher'
/>
:
null
}
</
div
>
...
...
ts/webui/src/components/overview/table/Details.tsx
deleted
100644 → 0
View file @
efa4e31c
import
*
as
React
from
'
react
'
;
import
{
DetailsRow
,
IDetailsRowBaseProps
}
from
'
@fluentui/react
'
;
import
OpenRow
from
'
../../public-child/OpenRow
'
;
interface
DetailsProps
{
detailsProps
:
IDetailsRowBaseProps
;
}
interface
DetailsState
{
isExpand
:
boolean
;
}
class
Details
extends
React
.
Component
<
DetailsProps
,
DetailsState
>
{
constructor
(
props
:
DetailsProps
)
{
super
(
props
);
this
.
state
=
{
isExpand
:
false
};
}
render
():
React
.
ReactNode
{
const
{
detailsProps
}
=
this
.
props
;
const
{
isExpand
}
=
this
.
state
;
return
(
<
div
>
<
div
onClick
=
{
():
void
=>
{
this
.
setState
(()
=>
({
isExpand
:
!
isExpand
}));
}
}
>
<
DetailsRow
{
...
detailsProps
}
/>
</
div
>
{
isExpand
&&
<
OpenRow
trialId
=
{
detailsProps
.
item
.
id
}
/>
}
</
div
>
);
}
}
export
default
Details
;
ts/webui/src/components/overview/table/SuccessTable.tsx
View file @
b40e3db7
import
*
as
React
from
'
react
'
;
import
{
DetailsList
,
IDetailsListProps
,
IColumn
}
from
'
@fluentui/react
'
;
import
{
DetailsList
,
IDetailsListProps
,
IColumn
,
Icon
,
DetailsRow
,
IRenderFunction
,
IDetailsHeaderProps
,
Sticky
,
StickyPositionType
,
ScrollablePane
,
ScrollbarVisibility
}
from
'
@fluentui/react
'
;
import
DefaultMetric
from
'
../../public-child/DefaultMetric
'
;
import
Details
from
'
.
/Details
'
;
import
{
convertDuration
}
from
'
../../../static/function
'
;
import
OpenRow
from
'
.
./../public-child/OpenRow
'
;
import
{
convertDuration
,
copyAndSort
}
from
'
../../../static/function
'
;
import
{
TRIALS
}
from
'
../../../static/datamodel
'
;
import
{
SortInfo
}
from
'
../../../static/interface
'
;
import
{
DETAILTABS
}
from
'
../../stateless-component/NNItabs
'
;
import
'
../../../static/style/succTable.scss
'
;
import
'
../../../static/style/tableStatus.css
'
;
...
...
@@ -11,12 +24,15 @@ import '../../../static/style/openRow.scss';
interface
SuccessTableProps
{
trialIds
:
string
[];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
updateOverviewPage
:
()
=>
void
;
}
interface
SuccessTableState
{
columns
:
IColumn
[];
source
:
Array
<
any
>
;
innerWidth
:
number
;
expandRowIdList
:
Set
<
string
>
;
sortInfo
:
SortInfo
;
}
class
SuccessTable
extends
React
.
Component
<
SuccessTableProps
,
SuccessTableState
>
{
...
...
@@ -25,18 +41,42 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
this
.
state
=
{
columns
:
this
.
columns
,
source
:
TRIALS
.
table
(
this
.
props
.
trialIds
),
innerWidth
:
window
.
innerWidth
sortInfo
:
{
field
:
''
,
isDescend
:
false
},
expandRowIdList
:
new
Set
()
// store expanded row's trial id
};
}
private
onRenderRow
:
IDetailsListProps
[
'
onRenderRow
'
]
=
props
=>
{
if
(
props
)
{
return
<
Details
detailsProps
=
{
props
}
/>;
componentDidUpdate
(
prevProps
:
SuccessTableProps
):
void
{
if
(
this
.
props
.
trialIds
!==
prevProps
.
trialIds
)
{
const
{
trialIds
}
=
this
.
props
;
this
.
setState
(()
=>
({
source
:
TRIALS
.
table
(
trialIds
)
}));
}
}
render
():
React
.
ReactNode
{
const
{
columns
,
source
,
sortInfo
}
=
this
.
state
;
const
keepSortedSource
=
copyAndSort
(
source
,
sortInfo
.
field
,
sortInfo
.
isDescend
);
const
isNoneData
=
source
.
length
===
0
?
true
:
false
;
return
(
<
div
id
=
'succTable'
>
<
ScrollablePane
className
=
'scrollPanel'
scrollbarVisibility
=
{
ScrollbarVisibility
.
auto
}
>
<
DetailsList
columns
=
{
columns
}
items
=
{
keepSortedSource
}
setKey
=
'set'
compact
=
{
true
}
onRenderRow
=
{
this
.
onRenderRow
}
onRenderDetailsHeader
=
{
this
.
onRenderDetailsHeader
}
selectionMode
=
{
0
}
// close selector function
className
=
'succTable'
/>
</
ScrollablePane
>
{
isNoneData
&&
<
div
className
=
'succTable-tooltip'
>
{
this
.
tooltipStr
}
</
div
>
}
</
div
>
);
}
return
null
;
};
onColumnClick
=
(
ev
:
React
.
MouseEvent
<
HTMLElement
>
,
getColumn
:
IColumn
):
void
=>
{
private
onColumnClick
=
(
_
ev
:
React
.
MouseEvent
<
HTMLElement
>
,
getColumn
:
IColumn
):
void
=>
{
const
{
columns
,
source
}
=
this
.
state
;
const
newColumns
:
IColumn
[]
=
columns
.
slice
();
const
currColumn
:
IColumn
=
newColumns
.
filter
(
item
=>
getColumn
.
key
===
item
.
key
)[
0
];
...
...
@@ -50,32 +90,51 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
}
});
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const
newItems
=
this
.
copyAndSort
(
source
,
currColumn
.
fieldName
!
,
currColumn
.
isSortedDescending
);
const
newItems
=
copyAndSort
(
source
,
currColumn
.
fieldName
!
,
currColumn
.
isSortedDescending
);
this
.
setState
({
columns
:
newColumns
,
source
:
newItems
source
:
newItems
,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
sortInfo
:
{
field
:
currColumn
.
fieldName
!
,
isDescend
:
currColumn
.
isSortedDescending
}
});
};
private
copyAndSort
<
T
>
(
items
:
T
[],
columnKey
:
string
,
isSortedDescending
?:
boolean
):
T
[]
{
const
key
=
columnKey
as
keyof
T
;
return
items
.
slice
(
0
).
sort
((
a
:
T
,
b
:
T
)
=>
((
isSortedDescending
?
a
[
key
]
<
b
[
key
]
:
a
[
key
]
>
b
[
key
])
?
1
:
-
1
));
}
tooltipStr
=
(
private
tooltipStr
=
(
<
React
.
Fragment
>
The experiment is running, please wait for the final metric patiently. You could also find status of trial
job with
<
span
>
{
DETAILTABS
}
</
span
>
button.
</
React
.
Fragment
>
);
columns
=
[
private
columns
=
[
{
key
:
'
_expand
'
,
name
:
''
,
onRender
:
(
item
:
any
):
any
=>
(
<
Icon
aria
-
hidden
=
{
true
}
iconName
=
'ChevronRight'
styles
=
{
{
root
:
{
transition
:
'
all 0.2s
'
,
transform
:
`rotate(
${
this
.
state
.
expandRowIdList
.
has
(
item
.
id
)
?
90
:
0
}
deg)`
}
}
}
className
=
'cursor'
onClick
=
{
this
.
expandTrialId
.
bind
(
this
,
Event
,
item
.
id
)
}
/>
),
fieldName
:
'
expand
'
,
isResizable
:
false
,
minWidth
:
20
,
maxWidth
:
20
},
{
name
:
'
Trial No.
'
,
key
:
'
sequenceId
'
,
fieldName
:
'
sequenceId
'
,
// required!
minWidth
:
5
0
,
maxWidth
:
87
,
minWidth
:
6
0
,
maxWidth
:
100
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
...
...
@@ -85,8 +144,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
name
:
'
ID
'
,
key
:
'
id
'
,
fieldName
:
'
id
'
,
minWidth
:
5
0
,
maxWidth
:
8
7
,
minWidth
:
6
0
,
maxWidth
:
11
8
,
isResizable
:
true
,
className
:
'
tableHead leftTitle
'
,
data
:
'
string
'
,
...
...
@@ -96,8 +155,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
{
name
:
'
Duration
'
,
key
:
'
duration
'
,
minWidth
:
6
5
,
maxWidth
:
1
50
,
minWidth
:
8
5
,
maxWidth
:
1
66
,
isResizable
:
true
,
fieldName
:
'
duration
'
,
data
:
'
number
'
,
...
...
@@ -111,8 +170,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
{
name
:
'
Status
'
,
key
:
'
status
'
,
minWidth
:
8
0
,
maxWidth
:
1
5
0
,
minWidth
:
9
8
,
maxWidth
:
1
6
0
,
isResizable
:
true
,
fieldName
:
'
status
'
,
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
(
...
...
@@ -124,7 +183,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
key
:
'
accuracy
'
,
fieldName
:
'
accuracy
'
,
minWidth
:
100
,
maxWidth
:
16
0
,
maxWidth
:
16
6
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
...
...
@@ -132,43 +191,49 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
}
];
setInnerWidth
=
():
void
=>
{
this
.
setState
(()
=>
({
innerWidth
:
window
.
innerWidth
}));
};
componentDidMount
():
void
{
window
.
addEventListener
(
'
resize
'
,
this
.
setInnerWidth
);
}
componentWillUnmount
():
void
{
window
.
removeEventListener
(
'
resize
'
,
this
.
setInnerWidth
);
}
componentDidUpdate
(
prevProps
:
SuccessTableProps
):
void
{
if
(
this
.
props
.
trialIds
!==
prevProps
.
trialIds
)
{
const
{
trialIds
}
=
this
.
props
;
this
.
setState
(()
=>
({
source
:
TRIALS
.
table
(
trialIds
)
}));
}
private
onRenderDetailsHeader
:
IRenderFunction
<
IDetailsHeaderProps
>
=
(
props
,
defaultRender
)
=>
{
if
(
!
props
)
{
return
null
;
}
return
(
<
Sticky
stickyPosition
=
{
StickyPositionType
.
Header
}
isScrollSynced
>
{
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
defaultRender
!
({
...
props
})
}
</
Sticky
>
);
};
render
():
React
.
ReactNode
{
const
{
columns
,
source
}
=
this
.
state
;
const
isNoneData
=
source
.
length
===
0
?
true
:
false
;
private
onRenderRow
:
IDetailsListProps
[
'
onRenderRow
'
]
=
props
=>
{
const
{
expandRowIdList
}
=
this
.
state
;
if
(
props
)
{
return
(
<
div
id
=
'succTable'
>
<
DetailsList
columns
=
{
columns
}
items
=
{
source
}
setKey
=
'set'
compact
=
{
true
}
onRenderRow
=
{
this
.
onRenderRow
}
selectionMode
=
{
0
}
// close selector function
className
=
'succTable'
/>
{
isNoneData
&&
<
div
className
=
'succTable-tooltip'
>
{
this
.
tooltipStr
}
</
div
>
}
<
div
>
<
div
>
<
DetailsRow
{
...
props
}
/>
</
div
>
{
Array
.
from
(
expandRowIdList
).
map
(
item
=>
item
===
props
.
item
.
id
&&
<
OpenRow
key
=
{
item
}
trialId
=
{
item
}
/>
)
}
</
div
>
);
}
return
null
;
};
private
expandTrialId
=
(
_event
:
any
,
id
:
string
):
void
=>
{
const
{
expandRowIdList
}
=
this
.
state
;
const
{
updateOverviewPage
}
=
this
.
props
;
const
copyExpandList
=
expandRowIdList
;
if
(
copyExpandList
.
has
(
id
))
{
copyExpandList
.
delete
(
id
);
}
else
{
copyExpandList
.
add
(
id
);
}
this
.
setState
(()
=>
({
expandRowIdList
:
copyExpandList
}));
updateOverviewPage
();
};
}
export
default
SuccessTable
;
ts/webui/src/components/public-child/MonacoEditor.tsx
View file @
b40e3db7
...
...
@@ -27,7 +27,7 @@ class MonacoHTML extends React.Component<MonacoEditorProps, {}> {
render
():
React
.
ReactNode
{
const
{
content
,
loading
,
height
}
=
this
.
props
;
return
(
<
div
className
=
'just-for-log'
>
<
React
.
Fragment
>
{
loading
?
(
<
Spinner
label
=
'Wait, wait...'
...
...
@@ -46,7 +46,7 @@ class MonacoHTML extends React.Component<MonacoEditorProps, {}> {
)
:
(
<
MonacoEditor
width
=
'100%'
height
=
{
height
}
language
=
'json'
value
=
{
content
}
options
=
{
DRAWEROPTION
}
/>
)
}
</
div
>
</
React
.
Fragment
>
);
}
}
...
...
ts/webui/src/components/slideNav/IconButtonTemplet.tsx
0 → 100644
View file @
b40e3db7
import
React
from
'
react
'
;
import
{
DefaultButton
,
Icon
}
from
'
@fluentui/react
'
;
interface
ButtonProps
{
icon
:
string
;
btuName
:
string
;
event
:
any
;
}
class
IconButtonTemplet
extends
React
.
Component
<
ButtonProps
,
{}
>
{
constructor
(
props
:
ButtonProps
)
{
super
(
props
);
}
render
():
React
.
ReactNode
{
const
{
icon
,
btuName
,
event
}
=
this
.
props
;
return
(
<
div
className
=
'container'
>
<
DefaultButton
className
=
'icon'
>
<
Icon
iconName
=
{
icon
}
/>
</
DefaultButton
>
<
DefaultButton
className
=
'integralBtn'
onClick
=
{
event
}
>
<
Icon
iconName
=
{
icon
}
/>
<
span
className
=
'margin'
>
{
btuName
}
</
span
>
</
DefaultButton
>
</
div
>
);
}
}
export
default
IconButtonTemplet
;
ts/webui/src/components/
public-child/config/TrialConfigButton
.tsx
→
ts/webui/src/components/
slideNav/SlideNavBtns
.tsx
View file @
b40e3db7
import
React
,
{
useState
,
useCallback
}
from
'
react
'
;
import
{
DefaultButton
,
Stack
}
from
'
@fluentui/react
'
;
import
{
Stack
}
from
'
@fluentui/react
'
;
import
TrialConfigPanel
from
'
./TrialConfigPanel
'
;
import
'
../../../static/style/overview/config.scss
'
;
import
LogPanel
from
'
../modals/LogPanel
'
;
import
IconButtonTemplate
from
'
./IconButtonTemplet
'
;
import
'
../../static/style/overview/panel.scss
'
;
export
const
TrialConfigButton
=
():
any
=>
{
export
const
SlideNavBtns
=
():
any
=>
{
const
[
isShowConfigPanel
,
setShowConfigPanle
]
=
useState
(
false
);
const
[
activeTab
,
setActiveTab
]
=
useState
(
'
1
'
);
const
[
isShowLogPanel
,
setShowLogPanel
]
=
useState
(
false
);
const
[
panelName
,
setPanelName
]
=
useState
(
''
);
const
hideConfigPanel
=
useCallback
(()
=>
setShowConfigPanle
(
false
),
[]);
const
showTrialConfigpPanel
=
useCallback
(()
=>
{
setShowConfigPanle
(
true
);
set
ActiveTab
(
'
config
'
);
set
PanelName
(
'
config
'
);
},
[]);
const
showSearchSpacePanel
=
useCallback
(()
=>
{
setShowConfigPanle
(
true
);
setActiveTab
(
'
search space
'
);
setPanelName
(
'
search space
'
);
},
[]);
const
showLogPanel
=
useCallback
(()
=>
{
setShowLogPanel
(
true
);
},
[]);
const
hideLogPanel
=
useCallback
(()
=>
{
setShowLogPanel
(
false
);
},
[]);
return
(
// right side nav buttons
<
React
.
Fragment
>
<
Stack
className
=
'config'
>
<
DefaultButton
text
=
'Search space'
onClick
=
{
showSearchSpacePanel
}
/>
<
DefaultButton
text
=
'Config'
onClick
=
{
showTrialConfigpPanel
}
/>
<
IconButtonTemplate
icon
=
'DocumentSearch'
btuName
=
'Search space'
event
=
{
showSearchSpacePanel
}
/>
<
IconButtonTemplate
icon
=
'Archive'
btuName
=
'Config'
event
=
{
showTrialConfigpPanel
}
/>
<
IconButtonTemplate
icon
=
'FilePDB'
btuName
=
'Log files'
event
=
{
showLogPanel
}
/>
</
Stack
>
{
isShowConfigPanel
&&
<
TrialConfigPanel
hideConfigPanel
=
{
hideConfigPanel
}
activeTab
=
{
activeTab
}
/>
}
{
isShowConfigPanel
&&
<
TrialConfigPanel
panelName
=
{
panelName
}
hideConfigPanel
=
{
hideConfigPanel
}
/>
}
{
/* the panel for dispatcher & nnimanager log message */
}
{
isShowLogPanel
&&
<
LogPanel
closeDrawer
=
{
hideLogPanel
}
/>
}
</
React
.
Fragment
>
);
};
ts/webui/src/components/
public-child/config
/TrialConfigPanel.tsx
→
ts/webui/src/components/
slideNav
/TrialConfigPanel.tsx
View file @
b40e3db7
import
*
as
React
from
'
react
'
;
import
{
Stack
,
Panel
,
Pivot
,
PivotItem
,
PrimaryButton
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../
../
static/datamodel
'
;
import
{
Stack
,
Panel
,
PrimaryButton
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../static/datamodel
'
;
import
MonacoEditor
from
'
react-monaco-editor
'
;
import
{
MONACO
}
from
'
../../
../
static/const
'
;
import
{
AppContext
}
from
'
../../
../
App
'
;
import
{
convertDuration
,
convertTimeAsUnit
}
from
'
../../
../
static/function
'
;
import
{
prettyStringify
}
from
'
../../
../
static/json_util
'
;
import
{
MONACO
}
from
'
../../static/const
'
;
import
{
AppContext
}
from
'
../../App
'
;
import
{
convertDuration
,
convertTimeAsUnit
,
caclMonacoEditorHeight
}
from
'
../../static/function
'
;
import
{
prettyStringify
}
from
'
../../static/json_util
'
;
import
lodash
from
'
lodash
'
;
import
'
../../
../
static/style/logDrawer.scss
'
;
import
'
../../static/style/logDrawer.scss
'
;
interface
LogDrawerProps
{
hideConfigPanel
:
()
=>
void
;
activeTab
?
:
string
;
panelName
:
string
;
}
interface
LogDrawerState
{
...
...
@@ -19,6 +19,12 @@ interface LogDrawerState {
innerWidth
:
number
;
}
/**
* search space
* config
* model
*/
class
TrialConfigPanel
extends
React
.
Component
<
LogDrawerProps
,
LogDrawerState
>
{
constructor
(
props
:
LogDrawerProps
)
{
super
(
props
);
...
...
@@ -43,11 +49,9 @@ class TrialConfigPanel extends React.Component<LogDrawerProps, LogDrawerState> {
}
render
():
React
.
ReactNode
{
const
{
hideConfigPanel
,
activeTab
}
=
this
.
props
;
const
{
hideConfigPanel
,
panelName
}
=
this
.
props
;
const
{
panelInnerHeight
,
innerWidth
}
=
this
.
state
;
// [marginTop 16px] + [Search space 46px] +
// button[height: 32px, marginTop: 45px, marginBottom: 25px] + [padding-bottom: 20px]
const
monacoEditorHeight
=
panelInnerHeight
-
184
;
const
monacoEditorHeight
=
caclMonacoEditorHeight
(
panelInnerHeight
);
const
blacklist
=
[
'
id
'
,
'
logDir
'
,
...
...
@@ -83,12 +87,10 @@ class TrialConfigPanel extends React.Component<LogDrawerProps, LogDrawerState> {
isLightDismiss
=
{
true
}
onLightDismissClick
=
{
hideConfigPanel
}
>
<
div
className
=
'log-tab-body'
>
<
Pivot
initialSelectedKey
=
{
activeTab
}
style
=
{
{
minHeight
:
190
,
paddingTop
:
'
16px
'
}
}
>
<
PivotItem
headerText
=
'Search space'
itemKey
=
'search space'
>
<
div
className
=
'panel'
>
{
panelName
===
'
search space
'
?
(
<
div
>
<
div
className
=
'panelName'
>
Search space
</
div
>
<
MonacoEditor
height
=
{
monacoEditorHeight
}
language
=
'json'
...
...
@@ -96,9 +98,10 @@ class TrialConfigPanel extends React.Component<LogDrawerProps, LogDrawerState> {
value
=
{
prettyStringify
(
EXPERIMENT
.
searchSpace
,
prettyWidth
,
2
)
}
options
=
{
MONACO
}
/>
</
P
iv
otItem
>
<
PivotItem
headerText
=
'Config'
itemKey
=
'config'
>
</
d
iv
>
)
:
(
<
div
className
=
'profile'
>
<
div
className
=
'panelName'
>
Config
</
div
>
<
MonacoEditor
width
=
'100%'
height
=
{
monacoEditorHeight
}
...
...
@@ -108,10 +111,9 @@ class TrialConfigPanel extends React.Component<LogDrawerProps, LogDrawerState> {
options
=
{
MONACO
}
/>
</
div
>
</
PivotItem
>
</
Pivot
>
</
div
>
)
}
<
PrimaryButton
text
=
'Close'
className
=
'configClose'
onClick
=
{
hideConfigPanel
}
/>
</
div
>
</
Panel
>
</
Stack
>
);
...
...
ts/webui/src/components/trial-detail/TableList.tsx
View file @
b40e3db7
...
...
@@ -15,8 +15,8 @@ import {
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
{
convertDuration
,
formatTimestamp
,
copyAndSort
}
from
'
../../static/function
'
;
import
{
TableObj
,
SortInfo
}
from
'
../../static/interface
'
;
import
'
../../static/style/search.scss
'
;
import
'
../../static/style/tableStatus.css
'
;
import
'
../../static/style/logPath.scss
'
;
...
...
@@ -56,36 +56,6 @@ const searchOptionLiterals = {
const
defaultDisplayedColumns
=
[
'
sequenceId
'
,
'
id
'
,
'
duration
'
,
'
status
'
,
'
latestAccuracy
'
];
interface
SortInfo
{
field
:
string
;
isDescend
?:
boolean
;
}
function
_copyAndSort
<
T
>
(
items
:
T
[],
columnKey
:
string
,
isSortedDescending
?:
boolean
):
any
{
const
key
=
columnKey
as
keyof
T
;
return
items
.
slice
(
0
).
sort
(
function
(
a
:
T
,
b
:
T
):
any
{
if
(
a
[
key
]
===
undefined
||
Object
.
is
(
a
[
key
],
NaN
)
||
Object
.
is
(
a
[
key
],
Infinity
)
||
Object
.
is
(
a
[
key
],
-
Infinity
)
||
typeof
a
[
key
]
===
'
object
'
)
{
return
1
;
}
if
(
b
[
key
]
===
undefined
||
Object
.
is
(
b
[
key
],
NaN
)
||
Object
.
is
(
b
[
key
],
Infinity
)
||
Object
.
is
(
b
[
key
],
-
Infinity
)
||
typeof
b
[
key
]
===
'
object
'
)
{
return
-
1
;
}
return
(
isSortedDescending
?
a
[
key
]
<
b
[
key
]
:
a
[
key
]
>
b
[
key
])
?
1
:
-
1
;
});
}
function
_inferColumnTitle
(
columnKey
:
string
):
string
{
if
(
columnKey
===
'
sequenceId
'
)
{
return
'
Trial No.
'
;
...
...
@@ -238,7 +208,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
const
{
sortInfo
}
=
this
.
state
;
if
(
sortInfo
.
field
!==
''
)
{
return
_
copyAndSort
(
items
,
sortInfo
.
field
,
sortInfo
.
isDescend
);
return
copyAndSort
(
items
,
sortInfo
.
field
,
sortInfo
.
isDescend
);
}
else
{
return
items
;
}
...
...
@@ -255,6 +225,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
<
Icon
aria
-
hidden
=
{
true
}
iconName
=
'ChevronRight'
className
=
'cursor'
styles
=
{
{
root
:
{
transition
:
'
all 0.2s
'
,
...
...
ts/webui/src/static/function.ts
View file @
b40e3db7
...
...
@@ -262,6 +262,37 @@ function formatComplexTypeValue(value: any): string | number {
}
}
function
caclMonacoEditorHeight
(
height
):
number
{
// [Search space 56px] + [marginBottom 18px] +
// button[height: 32px, marginTop: 45px, marginBottom: 7px]
// panel own padding-bottom: 20px;
return
height
-
178
;
}
function
copyAndSort
<
T
>
(
items
:
T
[],
columnKey
:
string
,
isSortedDescending
?:
boolean
):
any
{
const
key
=
columnKey
as
keyof
T
;
return
items
.
slice
(
0
).
sort
(
function
(
a
:
T
,
b
:
T
):
any
{
if
(
a
[
key
]
===
undefined
||
Object
.
is
(
a
[
key
],
NaN
)
||
Object
.
is
(
a
[
key
],
Infinity
)
||
Object
.
is
(
a
[
key
],
-
Infinity
)
||
typeof
a
[
key
]
===
'
object
'
)
{
return
1
;
}
if
(
b
[
key
]
===
undefined
||
Object
.
is
(
b
[
key
],
NaN
)
||
Object
.
is
(
b
[
key
],
Infinity
)
||
Object
.
is
(
b
[
key
],
-
Infinity
)
||
typeof
b
[
key
]
===
'
object
'
)
{
return
-
1
;
}
return
(
isSortedDescending
?
a
[
key
]
<
b
[
key
]
:
a
[
key
]
>
b
[
key
])
?
1
:
-
1
;
});
}
export
{
convertTime
,
convertDuration
,
...
...
@@ -280,5 +311,7 @@ export {
isArrayType
,
requestAxios
,
isNaNorInfinity
,
formatComplexTypeValue
formatComplexTypeValue
,
caclMonacoEditorHeight
,
copyAndSort
};
ts/webui/src/static/interface.ts
View file @
b40e3db7
...
...
@@ -131,7 +131,7 @@ interface MetricDataRecord {
}
interface
TrialJobInfo
{
i
d
:
string
;
trialJobI
d
:
string
;
sequenceId
:
number
;
status
:
string
;
startTime
?:
number
;
...
...
@@ -212,6 +212,12 @@ interface EventMap {
[
key
:
string
]:
()
=>
void
;
}
// table column sort
interface
SortInfo
{
field
:
string
;
isDescend
?:
boolean
;
}
export
{
TableObj
,
TableRecord
,
...
...
@@ -233,5 +239,6 @@ export {
NNIManagerStatus
,
EventMap
,
SingleAxis
,
MultipleAxes
MultipleAxes
,
SortInfo
};
ts/webui/src/static/model/trial.ts
View file @
b40e3db7
...
...
@@ -144,9 +144,9 @@ class Trial implements TableObj {
}
return
{
key
:
this
.
info
.
i
d
,
key
:
this
.
info
.
trialJobI
d
,
sequenceId
:
this
.
info
.
sequenceId
,
id
:
this
.
info
.
i
d
,
id
:
this
.
info
.
trialJobI
d
,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
startTime
:
this
.
info
.
startTime
!
,
endTime
:
this
.
info
.
endTime
,
...
...
@@ -169,7 +169,7 @@ class Trial implements TableObj {
}
get
id
():
string
{
return
this
.
info
.
i
d
;
return
this
.
info
.
trialJobI
d
;
}
get
duration
():
number
{
...
...
ts/webui/src/static/model/trialmanager.ts
View file @
b40e3db7
...
...
@@ -172,11 +172,11 @@ class TrialManager {
requestAxios
(
`
${
MANAGER_IP
}
/trial-jobs`
)
.
then
(
data
=>
{
for
(
const
trialInfo
of
data
as
TrialJobInfo
[])
{
if
(
this
.
trials
.
has
(
trialInfo
.
i
d
))
{
if
(
this
.
trials
.
has
(
trialInfo
.
trialJobI
d
))
{
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
updated
=
this
.
trials
.
get
(
trialInfo
.
i
d
)
!
.
updateTrialJobInfo
(
trialInfo
)
||
updated
;
updated
=
this
.
trials
.
get
(
trialInfo
.
trialJobI
d
)
!
.
updateTrialJobInfo
(
trialInfo
)
||
updated
;
}
else
{
this
.
trials
.
set
(
trialInfo
.
i
d
,
new
Trial
(
trialInfo
,
undefined
));
this
.
trials
.
set
(
trialInfo
.
trialJobI
d
,
new
Trial
(
trialInfo
,
undefined
));
updated
=
true
;
}
this
.
maxSequenceId
=
Math
.
max
(
this
.
maxSequenceId
,
trialInfo
.
sequenceId
);
...
...
ts/webui/src/static/style/common.scss
0 → 100644
View file @
b40e3db7
.cursor
{
&
:hover
,
&
i
:hover
{
cursor
:
pointer
;
}
}
\ No newline at end of file
ts/webui/src/static/style/logDrawer.scss
View file @
b40e3db7
$buttonsMarginTop
:
45px
;
$buttonsMarginBottom
:
7px
;
$navBarHeight
:
56px
;
$navBarMarginBottom
:
18px
;
.download
{
button
,
button
:active
,
...
...
@@ -7,22 +12,51 @@
}
}
.log-tab-body
{
.refresh
{
margin-left
:
10px
;
display
:
none
;
}
}
/* office-fabric-ui */
.ms-Panel-main
{
width
:
55%
;
background
:
#fff
;
.ms-Panel-content
{
padding
:
0
;
}
.ms-Pivot
{
line-height
:
56px
;
padding
:
0
38px
;
background
:
#f2f2f2
;
.ms-Pivot-linkContent
:hover
{
border-bottom
:
2px
solid
#ccc
;
}
.is-selected
{
.ms-Pivot-linkContent
:hover
{
border
:
none
;
}
}
}
}
.panel
{
padding
:
0
38px
;
}
// for log panel editor
.logMargin
{
margin-top
:
20px
;
}
.panelName
{
line-height
:
$navBarHeight
;
font-size
:
14px
;
margin-bottom
:
$navBarMarginBottom
;
font-weight
:
500
;
}
/* log drawer download & close button's row */
.buttons
{
margin
-top
:
16px
;
margin
:
$buttonsMarginTop
0
$buttonsMarginBottom
0
;
.close
{
text-align
:
right
;
...
...
@@ -30,5 +64,5 @@
}
.configClose
{
margin
:
45px
0
25px
0
;
margin
:
$buttonsMarginTop
0
$buttonsMarginBottom
0
;
}
ts/webui/src/static/style/overview/count.scss
View file @
b40e3db7
$seriesIconMargin
:
8
px
;
$seriesIconMargin
:
10
px
;
.ExpDuration
{
margin-top
:
28px
;
span
:hover
{
cursor
:
pointer
;
}
margin-top
:
20px
;
.maxTrialNum
{
margin-bottom
:
10px
;
...
...
@@ -13,7 +9,7 @@ $seriesIconMargin: 8px;
}
.exp-progress
{
margin-top
:
1
0
px
;
margin-top
:
1
6
px
;
.bold
{
font-weight
:
500
;
...
...
@@ -57,17 +53,17 @@ $seriesIconMargin: 8px;
}
&
-dropdown
{
width
:
48
px
;
width
:
65
px
;
display
:
inline-block
;
position
:
relative
;
top
:
13px
;
left
:
4px
;
margin-right
:
3px
;
}
}
.ExpDuration
.series
.confirm
{
margin
:
0
6px
;
.ms-Dropdown-title
{
padding-right
:
0
;
}
}
}
.series
{
...
...
@@ -114,4 +110,12 @@ $seriesIconMargin: 8px;
.basic
p
{
margin-top
:
0
;
}
p
.margin
{
margin-top
:
20px
;
}
}
.trialStatus
{
margin-top
:
8px
;
}
Prev
1
…
7
8
9
10
11
12
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