Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
OpenDAS
nni
Commits
c7187946
Commit
c7187946
authored
Feb 10, 2020
by
Lijiao
Committed by
GitHub
Feb 10, 2020
Browse files
Use office-fabric-ui components (#1964)
parent
fdfff50d
Changes
90
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1226 additions
and
1050 deletions
+1226
-1050
src/webui/src/components/overview/BasicInfo.tsx
src/webui/src/components/overview/BasicInfo.tsx
+23
-11
src/webui/src/components/overview/Details.tsx
src/webui/src/components/overview/Details.tsx
+36
-0
src/webui/src/components/overview/NumInput.tsx
src/webui/src/components/overview/NumInput.tsx
+15
-24
src/webui/src/components/overview/Progress.tsx
src/webui/src/components/overview/Progress.tsx
+188
-87
src/webui/src/components/overview/ProgressItem.tsx
src/webui/src/components/overview/ProgressItem.tsx
+16
-22
src/webui/src/components/overview/SearchSpace.tsx
src/webui/src/components/overview/SearchSpace.tsx
+0
-1
src/webui/src/components/overview/SuccessTable.tsx
src/webui/src/components/overview/SuccessTable.tsx
+110
-61
src/webui/src/components/overview/Title1.tsx
src/webui/src/components/overview/Title1.tsx
+6
-7
src/webui/src/components/overview/TrialProfile.tsx
src/webui/src/components/overview/TrialProfile.tsx
+0
-1
src/webui/src/components/public-child/DefaultMetric.tsx
src/webui/src/components/public-child/DefaultMetric.tsx
+0
-0
src/webui/src/components/public-child/LogPath.tsx
src/webui/src/components/public-child/LogPath.tsx
+0
-48
src/webui/src/components/public-child/MonacoEditor.tsx
src/webui/src/components/public-child/MonacoEditor.tsx
+30
-16
src/webui/src/components/public-child/OpenRow.tsx
src/webui/src/components/public-child/OpenRow.tsx
+96
-111
src/webui/src/components/public-child/PaiTrialChild.tsx
src/webui/src/components/public-child/PaiTrialChild.tsx
+2
-3
src/webui/src/components/public-child/PaiTrialLog.tsx
src/webui/src/components/public-child/PaiTrialLog.tsx
+6
-7
src/webui/src/components/trial-detail/DefaultMetricPoint.tsx
src/webui/src/components/trial-detail/DefaultMetricPoint.tsx
+93
-93
src/webui/src/components/trial-detail/Duration.tsx
src/webui/src/components/trial-detail/Duration.tsx
+86
-17
src/webui/src/components/trial-detail/Intermediate.tsx
src/webui/src/components/trial-detail/Intermediate.tsx
+32
-74
src/webui/src/components/trial-detail/Para.tsx
src/webui/src/components/trial-detail/Para.tsx
+90
-103
src/webui/src/components/trial-detail/TableList.tsx
src/webui/src/components/trial-detail/TableList.tsx
+397
-364
No files found.
src/webui/src/components/overview/BasicInfo.tsx
View file @
c7187946
import
{
Col
,
Row
,
Tooltip
}
from
'
antd
'
;
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Stack
,
TooltipHost
,
getId
}
from
'
office-ui-fabric-react
'
;
import
{
EXPERIMENT
}
from
'
../../static/datamodel
'
;
import
{
EXPERIMENT
}
from
'
../../static/datamodel
'
;
import
{
formatTimestamp
}
from
'
../../static/function
'
;
import
{
formatTimestamp
}
from
'
../../static/function
'
;
...
@@ -8,36 +8,48 @@ interface BasicInfoProps {
...
@@ -8,36 +8,48 @@ interface BasicInfoProps {
}
}
class
BasicInfo
extends
React
.
Component
<
BasicInfoProps
,
{}
>
{
class
BasicInfo
extends
React
.
Component
<
BasicInfoProps
,
{}
>
{
// Use getId() to ensure that the ID is unique on the page.
// (It's also okay to use a plain string without getId() and manually ensure uniqueness.)
// for tooltip user the log directory
private
_hostId
:
string
=
getId
(
'
tooltipHost
'
);
constructor
(
props
:
BasicInfoProps
)
{
constructor
(
props
:
BasicInfoProps
)
{
super
(
props
);
super
(
props
);
}
}
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
return
(
return
(
<
Row
className
=
"main"
>
<
Stack
horizontal
horizontalAlign
=
"space-between"
className
=
"main"
>
<
Col
span
=
{
8
}
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
>
<
p
>
ID
</
p
>
<
p
>
ID
</
p
>
<
div
>
{
EXPERIMENT
.
profile
.
id
}
</
div
>
<
div
>
{
EXPERIMENT
.
profile
.
id
}
</
div
>
</
Col
>
</
Stack
.
Item
>
<
Col
span
=
{
8
}
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
>
<
p
>
End time
</
p
>
<
p
>
End time
</
p
>
<
div
className
=
"nowrap"
>
{
formatTimestamp
(
EXPERIMENT
.
profile
.
endTime
)
}
</
div
>
<
div
className
=
"nowrap"
>
{
formatTimestamp
(
EXPERIMENT
.
profile
.
endTime
)
}
</
div
>
</
Col
>
</
Stack
.
Item
>
<
Col
span
=
{
8
}
className
=
"padItem basic"
>
<
Stack
.
Item
className
=
"padItem basic"
>
<
p
>
Log directory
</
p
>
<
p
>
Log directory
</
p
>
<
div
className
=
"nowrap"
>
<
div
className
=
"nowrap"
>
<
Tooltip
placement
=
"top"
title
=
{
EXPERIMENT
.
profile
.
logDir
||
''
}
>
<
TooltipHost
// Tooltip message content
content
=
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
id
=
{
this
.
_hostId
}
calloutProps
=
{
{
gapSpace
:
0
}
}
styles
=
{
{
root
:
{
display
:
'
inline-block
'
}
}
}
>
{
/* show logDir */
}
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
</
Tooltip
>
</
Tooltip
Host
>
</
div
>
</
div
>
<
p
>
Training platform
</
p
>
<
p
>
Training platform
</
p
>
<
div
className
=
"nowrap"
>
{
EXPERIMENT
.
profile
.
params
.
trainingServicePlatform
}
</
div
>
<
div
className
=
"nowrap"
>
{
EXPERIMENT
.
profile
.
params
.
trainingServicePlatform
}
</
div
>
</
Col
>
</
Stack
.
Item
>
</
Row
>
</
Stack
>
);
);
}
}
}
}
...
...
src/webui/src/components/overview/Details.tsx
0 → 100644
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
{
DetailsRow
,
IDetailsRowBaseProps
}
from
'
office-ui-fabric-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
;
\ No newline at end of file
src/webui/src/components/overview/NumInput.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Button
,
Row
}
from
'
antd
'
;
import
{
Stack
,
Primary
Button
}
from
'
office-ui-fabric-react
'
;
interface
ConcurrencyInputProps
{
interface
ConcurrencyInputProps
{
value
:
number
;
value
:
number
;
...
@@ -36,47 +36,38 @@ class ConcurrencyInput extends React.Component<ConcurrencyInputProps, Concurrenc
...
@@ -36,47 +36,38 @@ class ConcurrencyInput extends React.Component<ConcurrencyInputProps, Concurrenc
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
if
(
this
.
state
.
editting
)
{
if
(
this
.
state
.
editting
)
{
return
(
return
(
<
Row
className
=
"inputBox"
>
<
Stack
horizontal
className
=
"inputBox"
>
<
input
<
input
type
=
"number"
type
=
"number"
className
=
"concurrencyInput"
className
=
"concurrencyInput"
defaultValue
=
{
this
.
props
.
value
.
toString
()
}
defaultValue
=
{
this
.
props
.
value
.
toString
()
}
ref
=
{
this
.
input
}
ref
=
{
this
.
input
}
/>
/>
<
Button
<
PrimaryButton
type
=
"primary"
text
=
"Save"
className
=
"tableButton editStyle"
onClick
=
{
this
.
save
}
onClick
=
{
this
.
save
}
>
/>
Save
<
PrimaryButton
</
Button
>
text
=
"Cancel"
<
Button
type
=
"primary"
onClick
=
{
this
.
cancel
}
style
=
{
{
display
:
'
inline-block
'
,
marginLeft
:
1
}
}
style
=
{
{
display
:
'
inline-block
'
,
marginLeft
:
1
}
}
className
=
"tableButton editStyle"
onClick
=
{
this
.
cancel
}
>
/>
Cancel
</
Stack
>
</
Button
>
</
Row
>
);
);
}
else
{
}
else
{
return
(
return
(
<
Row
className
=
"inputBox"
>
<
Stack
horizontal
className
=
"inputBox"
>
<
input
<
input
type
=
"number"
type
=
"number"
className
=
"concurrencyInput"
className
=
"concurrencyInput"
disabled
=
{
true
}
disabled
=
{
true
}
value
=
{
this
.
props
.
value
}
value
=
{
this
.
props
.
value
}
/>
/>
<
Button
<
PrimaryButton
type
=
"primary"
text
=
"Edit"
className
=
"tableButton editStyle"
onClick
=
{
this
.
edit
}
onClick
=
{
this
.
edit
}
>
/>
Edit
</
Stack
>
</
Button
>
</
Row
>
);
);
}
}
}
}
...
...
src/webui/src/components/overview/Progress.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Row
,
Col
,
Popover
,
message
}
from
'
antd
'
;
import
{
Stack
,
Callout
,
Link
,
IconButton
,
FontWeights
,
mergeStyleSets
,
getId
,
getTheme
,
StackItem
}
from
'
office-ui-fabric-react
'
;
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
;
import
{
MANAGER_IP
}
from
'
../../static/const
'
;
import
{
MANAGER_IP
}
from
'
../../static/const
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
convertTime
}
from
'
../../static/function
'
;
import
{
convertTime
}
from
'
../../static/function
'
;
import
ConcurrencyInput
from
'
./NumInput
'
;
import
ConcurrencyInput
from
'
./NumInput
'
;
import
ProgressBar
from
'
./ProgressItem
'
;
import
ProgressBar
from
'
./ProgressItem
'
;
import
LogDrawer
from
'
../Modal/LogDrawer
'
;
import
LogDrawer
from
'
../Modals/LogDrawer
'
;
import
MessageInfo
from
'
../Modals/MessageInfo
'
;
import
'
../../static/style/progress.scss
'
;
import
'
../../static/style/progress.scss
'
;
import
'
../../static/style/probar.scss
'
;
import
'
../../static/style/probar.scss
'
;
interface
ProgressProps
{
interface
ProgressProps
{
concurrency
:
number
;
concurrency
:
number
;
bestAccuracy
:
number
;
bestAccuracy
:
number
;
...
@@ -19,24 +19,106 @@ interface ProgressProps {
...
@@ -19,24 +19,106 @@ interface ProgressProps {
interface
ProgressState
{
interface
ProgressState
{
isShowLogDrawer
:
boolean
;
isShowLogDrawer
:
boolean
;
isCalloutVisible
?:
boolean
;
isShowSucceedInfo
:
boolean
;
info
:
string
;
typeInfo
:
string
;
}
}
const
itemStyles
:
React
.
CSSProperties
=
{
height
:
50
,
width
:
100
};
const
theme
=
getTheme
();
const
styles
=
mergeStyleSets
({
buttonArea
:
{
verticalAlign
:
'
top
'
,
display
:
'
inline-block
'
,
textAlign
:
'
center
'
,
// margin: '0 100px',
minWidth
:
30
,
height
:
30
},
callout
:
{
maxWidth
:
300
},
header
:
{
padding
:
'
18px 24px 12px
'
},
title
:
[
theme
.
fonts
.
xLarge
,
{
margin
:
0
,
color
:
theme
.
palette
.
neutralPrimary
,
fontWeight
:
FontWeights
.
semilight
}
],
inner
:
{
height
:
'
100%
'
,
padding
:
'
0 24px 20px
'
},
actions
:
{
position
:
'
relative
'
,
marginTop
:
20
,
width
:
'
100%
'
,
whiteSpace
:
'
nowrap
'
},
subtext
:
[
theme
.
fonts
.
small
,
{
margin
:
0
,
color
:
theme
.
palette
.
neutralPrimary
,
fontWeight
:
FontWeights
.
semilight
}
],
link
:
[
theme
.
fonts
.
medium
,
{
color
:
theme
.
palette
.
neutralPrimary
}
]
});
class
Progressed
extends
React
.
Component
<
ProgressProps
,
ProgressState
>
{
class
Progressed
extends
React
.
Component
<
ProgressProps
,
ProgressState
>
{
private
menuButtonElement
!
:
HTMLDivElement
|
null
;
private
labelId
:
string
=
getId
(
'
callout-label
'
);
private
descriptionId
:
string
=
getId
(
'
callout-description
'
);
constructor
(
props
:
ProgressProps
)
{
constructor
(
props
:
ProgressProps
)
{
super
(
props
);
super
(
props
);
this
.
state
=
{
this
.
state
=
{
isShowLogDrawer
:
false
isShowLogDrawer
:
false
,
isCalloutVisible
:
false
,
isShowSucceedInfo
:
false
,
info
:
''
,
typeInfo
:
'
success
'
};
};
}
}
hideSucceedInfo
=
():
void
=>
{
this
.
setState
(()
=>
({
isShowSucceedInfo
:
false
}));
}
/**
* info: message content
* typeInfo: message type: success | error...
* continuousTime: show time, 2000ms
*/
showMessageInfo
=
(
info
:
string
,
typeInfo
:
string
):
void
=>
{
this
.
setState
(()
=>
({
info
,
typeInfo
,
isShowSucceedInfo
:
true
}));
setTimeout
(
this
.
hideSucceedInfo
,
2000
);
}
editTrialConcurrency
=
async
(
userInput
:
string
):
Promise
<
void
>
=>
{
editTrialConcurrency
=
async
(
userInput
:
string
):
Promise
<
void
>
=>
{
if
(
!
userInput
.
match
(
/^
[
1-9
]\d
*$/
))
{
if
(
!
userInput
.
match
(
/^
[
1-9
]\d
*$/
))
{
message
.
error
(
'
Please enter a positive integer!
'
,
2
);
this
.
showMessageInfo
(
'
Please enter a positive integer!
'
,
'
error
'
);
return
;
return
;
}
}
const
newConcurrency
=
parseInt
(
userInput
,
10
);
const
newConcurrency
=
parseInt
(
userInput
,
10
);
if
(
newConcurrency
===
this
.
props
.
concurrency
)
{
if
(
newConcurrency
===
this
.
props
.
concurrency
)
{
m
essage
.
i
nfo
(
`
Trial concurrency has not changed
`
,
2
);
this
.
showM
essage
I
nfo
(
'
Trial concurrency has not changed
'
,
'
error
'
);
return
;
return
;
}
}
...
@@ -50,19 +132,19 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
...
@@ -50,19 +132,19 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
params
:
{
update_type
:
'
TRIAL_CONCURRENCY
'
}
params
:
{
update_type
:
'
TRIAL_CONCURRENCY
'
}
});
});
if
(
res
.
status
===
200
)
{
if
(
res
.
status
===
200
)
{
message
.
success
(
`
Successfully updated trial concurrency
`
);
this
.
showMessageInfo
(
'
Successfully updated trial concurrency
'
,
'
success
'
);
// NOTE: should we do this earlier in favor of poor networks?
// NOTE: should we do this earlier in favor of poor networks?
this
.
props
.
changeConcurrency
(
newConcurrency
);
this
.
props
.
changeConcurrency
(
newConcurrency
);
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
if
(
error
.
response
&&
error
.
response
.
data
.
error
)
{
if
(
error
.
response
&&
error
.
response
.
data
.
error
)
{
message
.
error
(
`Failed to update trial concurrency\n
${
error
.
response
.
data
.
error
}
`
);
this
.
showMessageInfo
(
`Failed to update trial concurrency\n
${
error
.
response
.
data
.
error
}
`
,
'
error
'
);
}
else
if
(
error
.
response
)
{
}
else
if
(
error
.
response
)
{
message
.
error
(
`Failed to update trial concurrency\nServer responsed
${
error
.
response
.
status
}
`
);
this
.
showMessageInfo
(
`Failed to update trial concurrency\nServer responsed
${
error
.
response
.
status
}
`
,
'
error
'
);
}
else
if
(
error
.
message
)
{
}
else
if
(
error
.
message
)
{
message
.
error
(
`Failed to update trial concurrency\n
${
error
.
message
}
`
);
this
.
showMessageInfo
(
`Failed to update trial concurrency\n
${
error
.
message
}
`
,
'
error
'
);
}
else
{
}
else
{
message
.
error
(
`Failed to update trial concurrency\nUnknown error`
);
this
.
showMessageInfo
(
`Failed to update trial concurrency\nUnknown error`
,
'
error
'
);
}
}
}
}
}
}
...
@@ -75,55 +157,79 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
...
@@ -75,55 +157,79 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
this
.
setState
({
isShowLogDrawer
:
false
});
this
.
setState
({
isShowLogDrawer
:
false
});
}
}
onDismiss
=
():
void
=>
{
this
.
setState
({
isCalloutVisible
:
false
});
}
onShow
=
():
void
=>
{
this
.
setState
({
isCalloutVisible
:
true
});
}
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
const
{
bestAccuracy
}
=
this
.
props
;
const
{
bestAccuracy
}
=
this
.
props
;
const
{
isShowLogDrawer
}
=
this
.
state
;
const
{
isShowLogDrawer
,
isCalloutVisible
,
isShowSucceedInfo
,
info
,
typeInfo
}
=
this
.
state
;
const
count
=
TRIALS
.
countStatus
();
const
count
=
TRIALS
.
countStatus
();
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const
stoppedCount
=
count
.
get
(
'
USER_CANCELED
'
)
!
+
count
.
get
(
'
SYS_CANCELED
'
)
!
+
count
.
get
(
'
EARLY_STOPPED
'
)
!
;
const
stoppedCount
=
count
.
get
(
'
USER_CANCELED
'
)
!
+
count
.
get
(
'
SYS_CANCELED
'
)
!
+
count
.
get
(
'
EARLY_STOPPED
'
)
!
;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const
bar2
=
count
.
get
(
'
RUNNING
'
)
!
+
count
.
get
(
'
SUCCEEDED
'
)
!
+
count
.
get
(
'
FAILED
'
)
!
+
stoppedCount
;
const
bar2
=
count
.
get
(
'
RUNNING
'
)
!
+
count
.
get
(
'
SUCCEEDED
'
)
!
+
count
.
get
(
'
FAILED
'
)
!
+
stoppedCount
;
// support type [0, 1], not 98%
const
bar2Percent
=
(
bar2
/
EXPERIMENT
.
profile
.
params
.
maxTrialNum
)
*
100
;
const
bar2Percent
=
bar2
/
EXPERIMENT
.
profile
.
params
.
maxTrialNum
;
const
percent
=
(
EXPERIMENT
.
profile
.
execDuration
/
EXPERIMENT
.
profile
.
params
.
maxExecDuration
)
*
100
;
const
percent
=
EXPERIMENT
.
profile
.
execDuration
/
EXPERIMENT
.
profile
.
params
.
maxExecDuration
;
const
remaining
=
convertTime
(
EXPERIMENT
.
profile
.
params
.
maxExecDuration
-
EXPERIMENT
.
profile
.
execDuration
);
const
remaining
=
convertTime
(
EXPERIMENT
.
profile
.
params
.
maxExecDuration
-
EXPERIMENT
.
profile
.
execDuration
);
const
maxDuration
=
convertTime
(
EXPERIMENT
.
profile
.
params
.
maxExecDuration
);
const
maxDuration
=
convertTime
(
EXPERIMENT
.
profile
.
params
.
maxExecDuration
);
const
maxTrialNum
=
EXPERIMENT
.
profile
.
params
.
maxTrialNum
;
const
maxTrialNum
=
EXPERIMENT
.
profile
.
params
.
maxTrialNum
;
const
execDuration
=
convertTime
(
EXPERIMENT
.
profile
.
execDuration
);
const
execDuration
=
convertTime
(
EXPERIMENT
.
profile
.
execDuration
);
let
errorContent
;
if
(
EXPERIMENT
.
error
)
{
errorContent
=
(
<
div
className
=
"errors"
>
{
EXPERIMENT
.
error
}
<
div
><
a
href
=
"#"
onClick
=
{
this
.
isShowDrawer
}
>
Learn about
</
a
></
div
>
</
div
>
);
}
return
(
return
(
<
Row
className
=
"progress"
id
=
"barBack"
>
<
Stack
className
=
"progress"
id
=
"barBack"
>
<
Row
className
=
"basic lineBasic"
>
<
Stack
className
=
"basic lineBasic"
>
<
p
>
Status
</
p
>
<
p
>
Status
</
p
>
<
div
className
=
"status"
>
<
Stack
horizontal
className
=
"status"
>
<
span
className
=
{
EXPERIMENT
.
status
}
>
{
EXPERIMENT
.
status
}
</
span
>
<
span
className
=
{
`
${
EXPERIMENT
.
status
}
status-text`
}
>
{
EXPERIMENT
.
status
}
</
span
>
{
{
EXPERIMENT
.
status
===
'
ERROR
'
EXPERIMENT
.
status
===
'
ERROR
'
?
?
<
Popover
<
div
>
placement
=
"rightTop"
<
div
className
=
{
styles
.
buttonArea
}
ref
=
{
(
val
):
any
=>
this
.
menuButtonElement
=
val
}
>
content
=
{
errorContent
}
<
IconButton
title
=
"Error"
iconProps
=
{
{
iconName
:
'
info
'
}
}
trigger
=
"hover"
onClick
=
{
isCalloutVisible
?
this
.
onDismiss
:
this
.
onShow
}
>
/>
<
span
className
=
"errorBtn"
>
i
</
span
>
</
div
>
</
Popover
>
{
isCalloutVisible
&&
(
<
Callout
className
=
{
styles
.
callout
}
ariaLabelledBy
=
{
this
.
labelId
}
ariaDescribedBy
=
{
this
.
descriptionId
}
role
=
"alertdialog"
gapSpace
=
{
0
}
target
=
{
this
.
menuButtonElement
}
onDismiss
=
{
this
.
onDismiss
}
setInitialFocus
=
{
true
}
>
<
div
className
=
{
styles
.
header
}
>
<
p
className
=
{
styles
.
title
}
id
=
{
this
.
labelId
}
>
Error
</
p
>
</
div
>
<
div
className
=
{
styles
.
inner
}
>
<
p
className
=
{
styles
.
subtext
}
id
=
{
this
.
descriptionId
}
>
{
EXPERIMENT
.
error
}
</
p
>
<
div
className
=
{
styles
.
actions
}
>
<
Link
className
=
{
styles
.
link
}
onClick
=
{
this
.
isShowDrawer
}
>
Learn about
</
Link
>
</
div
>
</
div
>
</
Callout
>
)
}
</
div
>
:
:
<
span
/>
null
}
}
</
div
>
</
Stack
>
</
Row
>
</
Stack
>
<
ProgressBar
<
ProgressBar
who
=
"Duration"
who
=
"Duration"
percent
=
{
percent
}
percent
=
{
percent
}
...
@@ -138,55 +244,49 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
...
@@ -138,55 +244,49 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
bgclass
=
{
EXPERIMENT
.
status
}
bgclass
=
{
EXPERIMENT
.
status
}
maxString
=
{
`Max trial number:
${
maxTrialNum
}
`
}
maxString
=
{
`Max trial number:
${
maxTrialNum
}
`
}
/>
/>
<
Row
className
=
"basic colorOfbasic mess"
>
<
Stack
className
=
"basic colorOfbasic mess"
horizontal
>
<
p
>
Best metric
</
p
>
<
StackItem
grow
=
{
50
}
>
<
div
>
{
isNaN
(
bestAccuracy
)
?
'
N/A
'
:
bestAccuracy
.
toFixed
(
6
)
}
</
div
>
<
p
>
Best metric
</
p
>
</
Row
>
<
div
>
{
isNaN
(
bestAccuracy
)
?
'
N/A
'
:
bestAccuracy
.
toFixed
(
6
)
}
</
div
>
<
Row
className
=
"mess"
>
</
StackItem
>
<
Col
span
=
{
6
}
>
<
StackItem
>
<
Row
className
=
"basic colorOfbasic"
>
{
isShowSucceedInfo
&&
<
MessageInfo
className
=
"info"
typeInfo
=
{
typeInfo
}
info
=
{
info
}
/>
}
<
p
>
Spent
</
p
>
</
StackItem
>
<
div
>
{
execDuration
}
</
div
>
</
Stack
>
</
Row
>
<
Stack
horizontal
horizontalAlign
=
"space-between"
className
=
"mess"
>
</
Col
>
<
span
style
=
{
itemStyles
}
className
=
"basic colorOfbasic"
>
<
Col
span
=
{
6
}
>
<
p
>
Spent
</
p
>
<
Row
className
=
"basic colorOfbasic"
>
<
div
>
{
execDuration
}
</
div
>
<
p
>
Remaining
</
p
>
</
span
>
<
div
className
=
"time"
>
{
remaining
}
</
div
>
<
span
style
=
{
itemStyles
}
className
=
"basic colorOfbasic"
>
</
Row
>
<
p
>
Remaining
</
p
>
</
Col
>
<
div
className
=
"time"
>
{
remaining
}
</
div
>
<
Col
span
=
{
12
}
>
</
span
>
<
span
style
=
{
itemStyles
}
>
{
/* modify concurrency */
}
{
/* modify concurrency */
}
<
p
>
Concurrency
</
p
>
<
p
>
Concurrency
</
p
>
<
ConcurrencyInput
value
=
{
this
.
props
.
concurrency
}
updateValue
=
{
this
.
editTrialConcurrency
}
/>
<
ConcurrencyInput
value
=
{
this
.
props
.
concurrency
}
updateValue
=
{
this
.
editTrialConcurrency
}
/>
</
Col
>
</
span
>
</
Row
>
<
span
style
=
{
itemStyles
}
className
=
"basic colorOfbasic"
></
span
>
<
Row
className
=
"mess"
>
</
Stack
>
<
Col
span
=
{
6
}
>
<
Stack
horizontal
horizontalAlign
=
"space-between"
className
=
"mess"
>
<
Row
className
=
"basic colorOfbasic"
>
<
div
style
=
{
itemStyles
}
className
=
"basic colorOfbasic"
>
<
p
>
Running
</
p
>
<
p
>
Running
</
p
>
<
div
>
{
count
.
get
(
'
RUNNING
'
)
}
</
div
>
<
div
>
{
count
.
get
(
'
RUNNING
'
)
}
</
div
>
</
Row
>
</
div
>
</
Col
>
<
div
style
=
{
itemStyles
}
className
=
"basic colorOfbasic"
>
<
Col
span
=
{
6
}
>
<
p
>
Succeeded
</
p
>
<
Row
className
=
"basic colorOfbasic"
>
<
div
>
{
count
.
get
(
'
SUCCEEDED
'
)
}
</
div
>
<
p
>
Succeeded
</
p
>
</
div
>
<
div
>
{
count
.
get
(
'
SUCCEEDED
'
)
}
</
div
>
<
div
style
=
{
itemStyles
}
className
=
"basic"
>
</
Row
>
<
p
>
Stopped
</
p
>
</
Col
>
<
div
>
{
stoppedCount
}
</
div
>
<
Col
span
=
{
6
}
>
</
div
>
<
Row
className
=
"basic"
>
<
div
style
=
{
itemStyles
}
className
=
"basic"
>
<
p
>
Stopped
</
p
>
<
p
>
Failed
</
p
>
<
div
>
{
stoppedCount
}
</
div
>
<
div
>
{
count
.
get
(
'
FAILED
'
)
}
</
div
>
</
Row
>
</
div
>
</
Col
>
</
Stack
>
<
Col
span
=
{
6
}
>
<
Row
className
=
"basic"
>
<
p
>
Failed
</
p
>
<
div
>
{
count
.
get
(
'
FAILED
'
)
}
</
div
>
</
Row
>
</
Col
>
</
Row
>
{
/* learn about click -> default active key is dispatcher. */
}
{
/* learn about click -> default active key is dispatcher. */
}
{
isShowLogDrawer
?
(
{
isShowLogDrawer
?
(
<
LogDrawer
<
LogDrawer
...
@@ -194,9 +294,10 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
...
@@ -194,9 +294,10 @@ class Progressed extends React.Component<ProgressProps, ProgressState> {
activeTab
=
"dispatcher"
activeTab
=
"dispatcher"
/>
/>
)
:
null
}
)
:
null
}
</
Row
>
</
Stack
>
);
);
}
}
}
}
export
default
Progressed
;
export
default
Progressed
;
src/webui/src/components/overview/ProgressItem.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Row
,
Col
,
Progress
}
from
'
antd
'
;
import
{
Stack
,
StackItem
,
ProgressIndicator
}
from
'
office-ui-fabric-react
'
;
interface
ProItemProps
{
interface
ProItemProps
{
who
:
string
;
who
:
string
;
...
@@ -18,29 +18,23 @@ class ProgressBar extends React.Component<ProItemProps, {}> {
...
@@ -18,29 +18,23 @@ class ProgressBar extends React.Component<ProItemProps, {}> {
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
const
{
who
,
percent
,
description
,
maxString
,
bgclass
}
=
this
.
props
;
const
{
who
,
percent
,
description
,
maxString
,
bgclass
}
=
this
.
props
;
return
(
return
(
<
div
>
<
div
>
<
Row
className
=
{
`probar
${
bgclass
}
`
}
>
<
Stack
horizontal
className
=
{
`probar
${
bgclass
}
`
}
>
<
Col
span
=
{
8
}
>
<
div
className
=
"name"
>
{
who
}
</
div
>
<
div
className
=
"name"
>
{
who
}
</
div
>
<
div
className
=
"showProgress"
style
=
{
{
width
:
'
80%
'
}
}
>
</
Col
>
<
ProgressIndicator
<
Col
span
=
{
16
}
className
=
"bar"
>
barHeight
=
{
30
}
<
div
className
=
"showProgress"
>
percentComplete
=
{
percent
}
<
Progress
/>
percent
=
{
percent
}
<
Stack
horizontal
className
=
"boundary"
>
strokeWidth
=
{
30
}
<
StackItem
grow
=
{
30
}
>
0
</
StackItem
>
// strokeLinecap={'square'}
<
StackItem
className
=
"right"
grow
=
{
70
}
>
{
maxString
}
</
StackItem
>
format
=
{
():
string
=>
description
}
</
Stack
>
/>
</
div
>
</
div
>
<
div
className
=
"description"
style
=
{
{
width
:
'
20%
'
}
}
>
{
description
}
</
div
>
<
Row
className
=
"description"
>
</
Stack
>
<
Col
span
=
{
9
}
>
0
</
Col
>
<
br
/>
<
Col
className
=
"right"
span
=
{
15
}
>
{
maxString
}
</
Col
>
</
Row
>
</
Col
>
</
Row
>
<
br
/>
</
div
>
</
div
>
);
);
}
}
...
...
src/webui/src/components/overview/SearchSpace.tsx
View file @
c7187946
...
@@ -18,7 +18,6 @@ class SearchSpace extends React.Component<SearchspaceProps, {}> {
...
@@ -18,7 +18,6 @@ class SearchSpace extends React.Component<SearchspaceProps, {}> {
return
(
return
(
<
div
className
=
"searchSpace"
>
<
div
className
=
"searchSpace"
>
<
MonacoEditor
<
MonacoEditor
width
=
"100%"
height
=
"361"
height
=
"361"
language
=
"json"
language
=
"json"
theme
=
"vs-light"
theme
=
"vs-light"
...
...
src/webui/src/components/overview/SuccessTable.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Table
}
from
'
antd
'
;
import
{
DetailsList
,
IDetailsListProps
,
IColumn
}
from
'
office-ui-fabric-react
'
;
import
OpenRow
from
'
../public-child/OpenRow
'
;
import
DefaultMetric
from
'
../public-child/DefaultMetric
'
;
import
DefaultMetric
from
'
../public-child/DefaultMetrc
'
;
import
Details
from
'
./Details
'
;
import
{
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
TableRecord
}
from
'
../../static/interface
'
;
import
{
convertDuration
}
from
'
../../static/function
'
;
import
{
convertDuration
}
from
'
../../static/function
'
;
import
'
../../static/style/tableStatus.css
'
;
import
{
TRIALS
}
from
'
../../static/datamodel
'
;
import
'
../../static/style/succTable.scss
'
;
import
'
../../static/style/openRow.scss
'
;
import
'
../../static/style/openRow.scss
'
;
interface
SuccessTableProps
{
interface
SuccessTableProps
{
trialIds
:
string
[];
trialIds
:
string
[];
}
}
function
openRow
(
record
:
TableRecord
):
any
{
interface
SuccessTableState
{
return
(
columns
:
IColumn
[];
<
OpenRow
trialId
=
{
record
.
id
}
/>
source
:
Array
<
any
>
;
);
}
}
class
SuccessTable
extends
React
.
Component
<
SuccessTableProps
,
{}
>
{
class
SuccessTable
extends
React
.
Component
<
SuccessTableProps
,
SuccessTableState
>
{
constructor
(
props
:
SuccessTableProps
)
{
constructor
(
props
:
SuccessTableProps
)
{
super
(
props
);
super
(
props
);
this
.
state
=
{
columns
:
this
.
columns
,
source
:
TRIALS
.
table
(
this
.
props
.
trialIds
)
};
}
}
render
():
React
.
ReactNode
{
private
onRenderRow
:
IDetailsListProps
[
'
onRenderRow
'
]
=
props
=>
{
const
columns
=
[
if
(
props
)
{
{
return
<
Details
detailsProps
=
{
props
}
/>;
title
:
'
Trial No.
'
,
}
dataIndex
:
'
sequenceId
'
,
return
null
;
className
:
'
tableHead
'
};
},
{
title
:
'
ID
'
,
onColumnClick
=
(
ev
:
React
.
MouseEvent
<
HTMLElement
>
,
getColumn
:
IColumn
):
void
=>
{
dataIndex
:
'
id
'
,
const
{
columns
,
source
}
=
this
.
state
;
width
:
80
,
const
newColumns
:
IColumn
[]
=
columns
.
slice
();
className
:
'
tableHead leftTitle
'
,
const
currColumn
:
IColumn
=
newColumns
.
filter
(
item
=>
getColumn
.
key
===
item
.
key
)[
0
];
render
:
(
text
:
string
,
record
:
TableRecord
):
React
.
ReactNode
=>
{
newColumns
.
forEach
((
newCol
:
IColumn
)
=>
{
return
(
if
(
newCol
===
currColumn
)
{
<
div
>
{
record
.
id
}
</
div
>
currColumn
.
isSortedDescending
=
!
currColumn
.
isSortedDescending
;
);
currColumn
.
isSorted
=
true
;
},
}
else
{
},
{
newCol
.
isSorted
=
false
;
title
:
'
Duration
'
,
newCol
.
isSortedDescending
=
true
;
dataIndex
:
'
duration
'
,
width
:
140
,
render
:
(
text
:
string
,
record
:
TableRecord
):
React
.
ReactNode
=>
{
return
(
<
div
className
=
"durationsty"
><
div
>
{
convertDuration
(
record
.
duration
)
}
</
div
></
div
>
);
},
},
{
title
:
'
Status
'
,
dataIndex
:
'
status
'
,
width
:
150
,
className
:
'
tableStatus
'
,
render
:
(
text
:
string
,
record
:
TableRecord
):
React
.
ReactNode
=>
{
return
(
<
div
className
=
{
`
${
record
.
status
}
commonStyle`
}
>
{
record
.
status
}
</
div
>
);
}
},
{
title
:
'
Default metric
'
,
dataIndex
:
'
accuracy
'
,
render
:
(
text
:
string
,
record
:
TableRecord
):
React
.
ReactNode
=>
{
return
(
<
DefaultMetric
trialId
=
{
record
.
id
}
/>
);
}
}
}
];
});
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const
newItems
=
this
.
copyAndSort
(
source
,
currColumn
.
fieldName
!
,
currColumn
.
isSortedDescending
);
this
.
setState
({
columns
:
newColumns
,
source
:
newItems
});
};
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
));
}
columns
=
[
{
name
:
'
Trial No.
'
,
key
:
'
sequenceId
'
,
fieldName
:
'
sequenceId
'
,
// required!
minWidth
:
60
,
maxWidth
:
80
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
},
{
name
:
'
ID
'
,
key
:
'
id
'
,
fieldName
:
'
id
'
,
minWidth
:
80
,
maxWidth
:
150
,
className
:
'
tableHead leftTitle
'
,
data
:
'
string
'
,
onColumnClick
:
this
.
onColumnClick
},
{
name
:
'
Duration
'
,
key
:
'
duration
'
,
minWidth
:
100
,
maxWidth
:
150
,
fieldName
:
'
duration
'
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
{
return
(
<
div
className
=
"durationsty"
><
div
>
{
convertDuration
(
item
.
duration
)
}
</
div
></
div
>
);
},
},
{
name
:
'
Status
'
,
key
:
'
status
'
,
minWidth
:
100
,
maxWidth
:
150
,
fieldName
:
'
status
'
,
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
{
return
(
<
div
className
=
{
`
${
item
.
status
}
commonStyle`
}
>
{
item
.
status
}
</
div
>
);
}
},
{
name
:
'
Default metric
'
,
key
:
'
accuracy
'
,
fieldName
:
'
accuracy
'
,
minWidth
:
100
,
maxWidth
:
150
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
{
return
(
<
DefaultMetric
trialId
=
{
item
.
id
}
/>
);
}
}
];
render
():
React
.
ReactNode
{
const
{
columns
,
source
}
=
this
.
state
;
return
(
return
(
<
div
className
=
"tabScroll"
>
<
div
id
=
"succTable"
>
<
Table
{
/* TODO: [style] lineHeight question */
}
<
DetailsList
columns
=
{
columns
}
columns
=
{
columns
}
expandedRowRender
=
{
openRow
}
items
=
{
source
}
dataSource
=
{
TRIALS
.
table
(
this
.
props
.
trialIds
)
}
setKey
=
"set"
className
=
"commonTableStyle"
compact
=
{
true
}
pagination
=
{
false
}
onRenderRow
=
{
this
.
onRenderRow
}
selectionMode
=
{
0
}
// close selector function
/>
/>
</
div
>
</
div
>
);
);
...
...
src/webui/src/components/overview/Title1.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Stack
}
from
'
office-ui-fabric-react
'
;
import
'
../../static/style/overviewTitle.scss
'
;
interface
Title1Props
{
interface
Title1Props
{
text
:
string
;
text
:
string
;
icon
?:
string
;
icon
?:
string
;
...
@@ -15,12 +16,10 @@ class Title1 extends React.Component<Title1Props, {}> {
...
@@ -15,12 +16,10 @@ class Title1 extends React.Component<Title1Props, {}> {
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
const
{
text
,
icon
,
bgcolor
}
=
this
.
props
;
const
{
text
,
icon
,
bgcolor
}
=
this
.
props
;
return
(
return
(
<
div
>
<
Stack
horizontal
className
=
"panelTitle"
style
=
{
{
backgroundColor
:
bgcolor
}
}
>
<
div
className
=
"panelTitle"
style
=
{
{
backgroundColor
:
bgcolor
}
}
>
<
img
src
=
{
require
(
`../../static/img/icon/
${
icon
}
`
)
}
alt
=
"icon"
/>
<
img
src
=
{
require
(
`../../static/img/icon/
${
icon
}
`
)
}
alt
=
"icon"
/>
<
span
>
{
text
}
</
span
>
<
span
>
{
text
}
</
span
>
</
Stack
>
</
div
>
</
div
>
);
);
}
}
}
}
...
...
src/webui/src/components/overview/TrialProfile.tsx
View file @
c7187946
...
@@ -27,7 +27,6 @@ class TrialInfo extends React.Component<TrialInfoProps, {}> {
...
@@ -27,7 +27,6 @@ class TrialInfo extends React.Component<TrialInfoProps, {}> {
};
};
const
profile
=
JSON
.
stringify
(
EXPERIMENT
.
profile
,
filter
,
2
);
const
profile
=
JSON
.
stringify
(
EXPERIMENT
.
profile
,
filter
,
2
);
// FIXME: highlight not working?
return
(
return
(
<
div
className
=
"profile"
>
<
div
className
=
"profile"
>
<
MonacoEditor
<
MonacoEditor
...
...
src/webui/src/components/public-child/DefaultMetrc.tsx
→
src/webui/src/components/public-child/DefaultMetr
i
c.tsx
View file @
c7187946
File moved
src/webui/src/components/public-child/LogPath.tsx
deleted
100644 → 0
View file @
fdfff50d
import
*
as
React
from
'
react
'
;
import
LogPathChild
from
'
./LogPathChild
'
;
interface
LogpathProps
{
logStr
:
string
;
}
class
LogPath
extends
React
.
Component
<
LogpathProps
,
{}
>
{
constructor
(
props
:
LogpathProps
)
{
super
(
props
);
}
render
():
React
.
ReactNode
{
const
{
logStr
}
=
this
.
props
;
const
isTwopath
=
logStr
.
indexOf
(
'
,
'
)
!==
-
1
?
true
:
false
;
return
(
<
div
>
{
isTwopath
?
<
div
>
<
LogPathChild
eachLogpath
=
{
logStr
.
split
(
'
,
'
)[
0
]
}
logName
=
"LogPath:"
/>
<
LogPathChild
eachLogpath
=
{
logStr
.
split
(
'
,
'
)[
1
]
}
logName
=
"Log on HDFS:"
/>
</
div
>
:
<
LogPathChild
eachLogpath
=
{
logStr
}
logName
=
"Log path:"
/>
}
</
div
>
);
}
}
export
default
LogPath
;
\ No newline at end of file
src/webui/src/components/public-child/MonacoEditor.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Spin
}
from
'
antd
'
;
import
{
Spin
ner
}
from
'
office-ui-fabric-react
'
;
import
{
DRAWEROPTION
}
from
'
../../static/const
'
;
import
{
DRAWEROPTION
}
from
'
../../static/const
'
;
import
MonacoEditor
from
'
react-monaco-editor
'
;
import
MonacoEditor
from
'
react-monaco-editor
'
;
...
@@ -11,7 +11,7 @@ interface MonacoEditorProps {
...
@@ -11,7 +11,7 @@ interface MonacoEditorProps {
class
MonacoHTML
extends
React
.
Component
<
MonacoEditorProps
,
{}
>
{
class
MonacoHTML
extends
React
.
Component
<
MonacoEditorProps
,
{}
>
{
public
_isMonacoMount
:
boolean
;
public
_isMonacoMount
!
:
boolean
;
constructor
(
props
:
MonacoEditorProps
)
{
constructor
(
props
:
MonacoEditorProps
)
{
super
(
props
);
super
(
props
);
...
@@ -25,23 +25,37 @@ class MonacoHTML extends React.Component<MonacoEditorProps, {}> {
...
@@ -25,23 +25,37 @@ class MonacoHTML extends React.Component<MonacoEditorProps, {}> {
this
.
_isMonacoMount
=
false
;
this
.
_isMonacoMount
=
false
;
}
}
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
const
{
content
,
loading
,
height
}
=
this
.
props
;
const
{
content
,
loading
,
height
}
=
this
.
props
;
return
(
return
(
<
div
className
=
"just-for-log"
>
<
div
className
=
"just-for-log"
>
<
Spin
{
// tip="Loading..."
loading
style
=
{
{
width
:
'
100%
'
,
height
:
height
}
}
?
spinning
=
{
loading
}
<
Spinner
>
label
=
"Wait, wait..."
<
MonacoEditor
ariaLive
=
"assertive"
width
=
"100%"
labelPosition
=
"right"
height
=
{
height
}
styles
=
{
{
root
:
{
width
:
'
100%
'
,
height
:
height
}
}
}
language
=
"json"
>
value
=
{
content
}
<
MonacoEditor
options
=
{
DRAWEROPTION
}
width
=
"100%"
/>
height
=
{
height
}
</
Spin
>
language
=
"json"
value
=
{
content
}
options
=
{
DRAWEROPTION
}
/>
</
Spinner
>
:
<
MonacoEditor
width
=
"100%"
height
=
{
height
}
language
=
"json"
value
=
{
content
}
options
=
{
DRAWEROPTION
}
/>
}
</
div
>
</
div
>
);
);
}
}
...
...
src/webui/src/components/public-child/OpenRow.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
*
as
copy
from
'
copy-to-clipboard
'
;
import
*
as
copy
from
'
copy-to-clipboard
'
;
import
PaiTrialLog
from
'
../public-child/PaiTrialLog
'
;
import
{
Stack
,
PrimaryButton
,
Pivot
,
PivotItem
}
from
'
office-ui-fabric-react
'
;
import
TrialLog
from
'
../public-child/TrialLog
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
Trial
}
from
'
../../static/model/trial
'
;
import
{
Trial
}
from
'
../../static/model/trial
'
;
import
{
Row
,
Tabs
,
Button
,
message
,
Modal
}
from
'
antd
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
MANAGER_IP
}
from
'
../../static/const
'
;
import
{
MANAGER_IP
}
from
'
../../static/const
'
;
import
JSONTree
from
'
react-json-tree
'
;
import
PaiTrialLog
from
'
../public-child/PaiTrialLog
'
;
import
TrialLog
from
'
../public-child/TrialLog
'
;
import
MessageInfo
from
'
../Modals/MessageInfo
'
;
import
'
../../static/style/overview.scss
'
;
import
'
../../static/style/overview.scss
'
;
import
'
../../static/style/copyParameter.scss
'
;
import
'
../../static/style/copyParameter.scss
'
;
import
JSONTree
from
'
react-json-tree
'
;
const
TabPane
=
Tabs
.
TabPane
;
interface
OpenRowProps
{
interface
OpenRowProps
{
trialId
:
string
;
trialId
:
string
;
}
}
interface
OpenRowState
{
interface
OpenRowState
{
isShowFormatModal
:
boolean
;
typeInfo
:
string
;
formatStr
:
string
;
info
:
string
;
isHidenInfo
:
boolean
;
}
}
class
OpenRow
extends
React
.
Component
<
OpenRowProps
,
OpenRowState
>
{
class
OpenRow
extends
React
.
Component
<
OpenRowProps
,
OpenRowState
>
{
...
@@ -25,127 +26,111 @@ class OpenRow extends React.Component<OpenRowProps, OpenRowState> {
...
@@ -25,127 +26,111 @@ class OpenRow extends React.Component<OpenRowProps, OpenRowState> {
constructor
(
props
:
OpenRowProps
)
{
constructor
(
props
:
OpenRowProps
)
{
super
(
props
);
super
(
props
);
this
.
state
=
{
this
.
state
=
{
isShowFormatModal
:
false
,
typeInfo
:
''
,
formatStr
:
''
info
:
''
,
isHidenInfo
:
true
};
};
}
}
showFormatModal
=
(
trial
:
Trial
):
void
=>
{
hideMessageInfo
=
():
void
=>
{
// get copy parameters
this
.
setState
(()
=>
({
isHidenInfo
:
true
}));
const
params
=
JSON
.
stringify
(
trial
.
info
.
hyperParameters
,
null
,
4
);
// open modal with format string
this
.
setState
({
isShowFormatModal
:
true
,
formatStr
:
params
});
}
}
hideFormatModal
=
():
void
=>
{
/**
// close modal, destroy state format string data
* info: message content
this
.
setState
({
isShowFormatModal
:
false
,
formatStr
:
''
});
* typeInfo: message type: success | error...
* continuousTime: show time, 2000ms
*/
getCopyStatus
=
(
info
:
string
,
typeInfo
:
string
):
void
=>
{
this
.
setState
(()
=>
({
info
,
typeInfo
,
isHidenInfo
:
false
}));
setTimeout
(
this
.
hideMessageInfo
,
2000
);
}
}
copyParams
=
():
void
=>
{
copyParams
=
(
trial
:
Trial
):
void
=>
{
// json format
// get copy parameters
const
{
formatStr
}
=
this
.
state
;
const
params
=
JSON
.
stringify
(
trial
.
description
.
parameters
,
null
,
4
);
if
(
copy
(
formatStr
))
{
if
(
copy
.
default
(
params
))
{
message
.
destroy
();
this
.
getCopyStatus
(
'
Success copy parameters to clipboard in form of python dict !
'
,
'
success
'
);
message
.
success
(
'
Success copy parameters to clipboard in form of python dict !
'
,
3
);
}
else
{
}
else
{
message
.
destroy
();
this
.
getCopyStatus
(
'
Failed !
'
,
'
error
'
);
message
.
error
(
'
Failed !
'
,
2
);
}
}
this
.
hideFormatModal
();
}
}
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
const
{
is
ShowFormatModal
,
formatStr
}
=
this
.
state
;
const
{
is
HidenInfo
,
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
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
;
const
multiProgress
=
trial
.
info
.
hyperParameters
===
undefined
?
0
:
trial
.
info
.
hyperParameters
.
length
;
return
(
return
(
<
Row
className
=
"openRowContent hyperpar"
>
<
Stack
className
=
"openRow"
>
<
Tabs
tabPosition
=
"left"
className
=
"card"
>
<
Stack
className
=
"openRowContent"
>
<
TabPane
tab
=
"Parameters"
key
=
"1"
>
<
Pivot
>
{
<
PivotItem
headerText
=
"Parameters"
key
=
"1"
itemIcon
=
"TestParameter"
>
EXPERIMENT
.
multiPhase
{
?
EXPERIMENT
.
multiPhase
<
Row
className
=
"link"
>
?
Trails for multiphase experiment will return a set of parameters,
<
Stack
className
=
"link"
>
we are listing the latest parameter in webportal.
{
<
br
/>
`
For the entire parameter set, please refer to the following
"
Trails for multiphase experiment will return a set of parameters,
<
a
we are listing the latest parameter in webportal.
href
=
{
trialLink
}
For the entire parameter set, please refer to the following "
rel
=
"noopener noreferrer"
`
target
=
"_blank"
}
style
=
{
{
marginLeft
:
2
}
}
<
a
href
=
{
trialLink
}
rel
=
"noopener noreferrer"
target
=
"_blank"
>
{
trialLink
}
</
a
>
{
`".`
}
>
<
div
>
Current Phase:
{
multiProgress
}
.
</
div
>
{
trialLink
}
</
Stack
>
</
a
>
"
:
<
br
/>
null
Current Phase:
{
multiProgress
}
.
}
</
Row
>
{
:
trial
.
info
.
hyperParameters
!==
undefined
<
div
/>
?
}
<
Stack
id
=
"description"
>
{
<
Stack
className
=
"bgHyper"
>
trial
.
info
.
hyperParameters
!==
undefined
<
JSONTree
?
hideRoot
=
{
true
}
<
Row
id
=
"description"
>
shouldExpandNode
=
{
():
boolean
=>
true
}
// default expandNode
<
Row
className
=
"bgHyper"
>
getItemString
=
{
():
null
=>
null
}
// remove the {} items
<
JSONTree
data
=
{
trial
.
description
.
parameters
}
hideRoot
=
{
true
}
/>
shouldExpandNode
=
{
():
boolean
=>
true
}
// default expandNode
</
Stack
>
getItemString
=
{
():
any
=>
(<
span
/>)
}
// remove the {} items
<
Stack
horizontal
className
=
"copy"
>
data
=
{
trial
.
description
.
parameters
}
<
PrimaryButton
/>
onClick
=
{
this
.
copyParams
.
bind
(
this
,
trial
)
}
</
Row
>
text
=
"Copy as json"
<
Row
className
=
"copy"
>
styles
=
{
{
root
:
{
width
:
128
,
marginRight
:
10
}
}
}
<
Button
/>
onClick
=
{
this
.
showFormatModal
.
bind
(
this
,
trial
)
}
{
/* copy success | failed message info */
}
>
{
!
isHidenInfo
&&
<
MessageInfo
typeInfo
=
{
typeInfo
}
info
=
{
info
}
/>
}
Copy as json
</
Stack
>
</
Button
>
</
Stack
>
</
Row
>
:
</
Row
>
<
Stack
className
=
"logpath"
>
:
<
span
className
=
"logName"
>
Error:
</
span
>
<
Row
className
=
"logpath"
>
<
span
className
=
"error"
>
{
`This trial's parameters are not available.'`
}
</
span
>
<
span
className
=
"logName"
style
=
{
{
marginRight
:
2
}
}
>
Error:
</
span
>
</
Stack
>
<
span
className
=
"error"
>
'
This trial
'
s parameters are not available.
'
</
span
>
}
</
Row
>
</
PivotItem
>
}
<
PivotItem
headerText
=
"Log"
key
=
"2"
itemIcon
=
"M365InvoicingLogo"
>
</
TabPane
>
{
<
TabPane
tab
=
"Log"
key
=
"2"
>
// FIXME: this should not be handled in web UI side
{
EXPERIMENT
.
trainingServicePlatform
!==
'
local
'
// FIXME: this should not be handled in web UI side
?
EXPERIMENT
.
trainingServicePlatform
!==
'
local
'
<
PaiTrialLog
?
logStr
=
{
logPathRow
}
<
PaiTrialLog
id
=
{
trialId
}
logStr
=
{
logPathRow
}
logCollection
=
{
EXPERIMENT
.
logCollectionEnabled
}
id
=
{
trialId
}
/>
logCollection
=
{
EXPERIMENT
.
logCollectionEnabled
}
:
/>
<
TrialLog
logStr
=
{
logPathRow
}
id
=
{
trialId
}
/>
:
}
<
TrialLog
logStr
=
{
logPathRow
}
id
=
{
trialId
}
/>
</
PivotItem
>
}
</
Pivot
>
</
TabPane
>
</
Stack
>
</
Tabs
>
</
Stack
>
<
Modal
title
=
"Format"
okText
=
"Copy"
centered
=
{
true
}
visible
=
{
isShowFormatModal
}
onCancel
=
{
this
.
hideFormatModal
}
maskClosable
=
{
false
}
// click mongolian layer don't close modal
onOk
=
{
this
.
copyParams
}
destroyOnClose
=
{
true
}
width
=
"60%"
className
=
"format"
>
{
/* write string in pre to show format string */
}
<
pre
className
=
"formatStr"
>
{
formatStr
}
</
pre
>
</
Modal
>
</
Row
>
);
);
}
}
}
}
...
...
src/webui/src/components/public-child/PaiTrialChild.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Row
}
from
'
antd
'
;
import
{
DOWNLOAD_IP
}
from
'
../../static/const
'
;
import
{
DOWNLOAD_IP
}
from
'
../../static/const
'
;
interface
PaiTrialChildProps
{
interface
PaiTrialChildProps
{
...
@@ -24,7 +23,7 @@ class PaiTrialChild extends React.Component<PaiTrialChildProps, {}> {
...
@@ -24,7 +23,7 @@ class PaiTrialChild extends React.Component<PaiTrialChildProps, {}> {
?
?
<
div
/>
<
div
/>
:
:
<
Row
>
<
div
>
{
{
logCollect
logCollect
?
?
...
@@ -39,7 +38,7 @@ class PaiTrialChild extends React.Component<PaiTrialChildProps, {}> {
...
@@ -39,7 +38,7 @@ class PaiTrialChild extends React.Component<PaiTrialChildProps, {}> {
:
:
<
span
>
trial stdout:
{
logString
}
</
span
>
<
span
>
trial stdout:
{
logString
}
</
span
>
}
}
</
Row
>
</
div
>
}
}
</
div
>
</
div
>
);
);
...
...
src/webui/src/components/public-child/PaiTrialLog.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Row
}
from
'
antd
'
;
import
{
DOWNLOAD_IP
}
from
'
../../static/const
'
;
import
{
DOWNLOAD_IP
}
from
'
../../static/const
'
;
import
PaiTrialChild
from
'
./PaiTrialChild
'
;
import
PaiTrialChild
from
'
./PaiTrialChild
'
;
import
LogPathChild
from
'
./LogPathChild
'
;
import
LogPathChild
from
'
./LogPathChild
'
;
...
@@ -30,11 +29,11 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
...
@@ -30,11 +29,11 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
{
{
isTwopath
isTwopath
?
?
<
Row
>
<
div
>
{
{
logCollection
logCollection
?
?
<
Row
>
<
div
>
<
a
<
a
target
=
"_blank"
target
=
"_blank"
rel
=
"noopener noreferrer"
rel
=
"noopener noreferrer"
...
@@ -44,9 +43,9 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
...
@@ -44,9 +43,9 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
Trial stdout
Trial stdout
</
a
>
</
a
>
<
a
target
=
"_blank"
rel
=
"noopener noreferrer"
href
=
{
logStr
.
split
(
'
,
'
)[
1
]
}
>
hdfsLog
</
a
>
<
a
target
=
"_blank"
rel
=
"noopener noreferrer"
href
=
{
logStr
.
split
(
'
,
'
)[
1
]
}
>
hdfsLog
</
a
>
</
Row
>
</
div
>
:
:
<
Row
>
<
div
>
<
LogPathChild
<
LogPathChild
eachLogpath
=
{
logStr
.
split
(
'
,
'
)[
0
]
}
eachLogpath
=
{
logStr
.
split
(
'
,
'
)[
0
]
}
logName
=
"Trial stdout:"
logName
=
"Trial stdout:"
...
@@ -55,9 +54,9 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
...
@@ -55,9 +54,9 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
eachLogpath
=
{
logStr
.
split
(
'
,
'
)[
1
]
}
eachLogpath
=
{
logStr
.
split
(
'
,
'
)[
1
]
}
logName
=
"Log on HDFS:"
logName
=
"Log on HDFS:"
/>
/>
</
Row
>
</
div
>
}
}
</
Row
>
</
div
>
:
:
<
PaiTrialChild
<
PaiTrialChild
logString
=
{
logStr
}
logString
=
{
logStr
}
...
...
src/webui/src/components/trial-detail/DefaultMetricPoint.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Switch
}
from
'
antd
'
;
import
{
Toggle
,
Stack
}
from
'
office-ui-fabric-react
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
ReactEcharts
from
'
echarts-for-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
{
TooltipForAccuracy
,
EventMap
}
from
'
../../static/interface
'
;
import
{
TooltipForAccuracy
,
EventMap
}
from
'
../../static/interface
'
;
require
(
'
echarts/lib/chart/scatter
'
);
import
'
echarts/lib/chart/scatter
'
;
require
(
'
echarts/lib/component/tooltip
'
);
import
'
echarts/lib/component/tooltip
'
;
require
(
'
echarts/lib/component/title
'
);
import
'
echarts/lib/component/title
'
;
const
EmptyGraph
=
{
const
EmptyGraph
=
{
grid
:
{
grid
:
{
left
:
'
8%
'
left
:
'
8%
'
...
@@ -18,9 +19,9 @@ const EmptyGraph = {
...
@@ -18,9 +19,9 @@ const EmptyGraph = {
yAxis
:
{
yAxis
:
{
name
:
'
Default metric
'
,
name
:
'
Default metric
'
,
type
:
'
value
'
,
type
:
'
value
'
,
scale
:
true
,
}
}
};
};
interface
DefaultPointProps
{
interface
DefaultPointProps
{
trialIds
:
string
[];
trialIds
:
string
[];
visible
:
boolean
;
visible
:
boolean
;
...
@@ -28,7 +29,7 @@ interface DefaultPointProps {
...
@@ -28,7 +29,7 @@ interface DefaultPointProps {
}
}
interface
DefaultPointState
{
interface
DefaultPointState
{
bestCurveEnabled
:
boolean
;
bestCurveEnabled
?
:
boolean
|
undefined
;
startY
:
number
;
// dataZoomY
startY
:
number
;
// dataZoomY
endY
:
number
;
endY
:
number
;
}
}
...
@@ -39,11 +40,11 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
...
@@ -39,11 +40,11 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
this
.
state
=
{
this
.
state
=
{
bestCurveEnabled
:
false
,
bestCurveEnabled
:
false
,
startY
:
0
,
// dataZoomY
startY
:
0
,
// dataZoomY
endY
:
100
,
endY
:
100
};
};
}
}
loadDefault
=
(
checked
:
boolean
):
void
=>
{
loadDefault
=
(
ev
:
React
.
MouseEvent
<
HTMLElement
>
,
checked
?
:
boolean
):
void
=>
{
this
.
setState
({
bestCurveEnabled
:
checked
});
this
.
setState
({
bestCurveEnabled
:
checked
});
}
}
...
@@ -51,7 +52,59 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
...
@@ -51,7 +52,59 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
return
nextProps
.
visible
;
return
nextProps
.
visible
;
}
}
generateScatterSeries
=
(
trials
:
Trial
[]):
any
=>
{
metricDataZoom
=
(
e
:
EventMap
):
void
=>
{
if
(
e
.
batch
!==
undefined
)
{
this
.
setState
(()
=>
({
startY
:
(
e
.
batch
[
0
].
start
!==
null
?
e
.
batch
[
0
].
start
:
0
),
endY
:
(
e
.
batch
[
0
].
end
!==
null
?
e
.
batch
[
0
].
end
:
100
)
}));
}
}
generateGraphConfig
(
maxSequenceId
:
number
):
any
{
const
{
startY
,
endY
}
=
this
.
state
;
return
{
grid
:
{
left
:
'
8%
'
,
},
tooltip
:
{
trigger
:
'
item
'
,
enterable
:
true
,
position
:
(
point
:
number
[],
data
:
TooltipForAccuracy
):
number
[]
=>
(
[(
data
.
data
[
0
]
<
maxSequenceId
?
point
[
0
]
:
(
point
[
0
]
-
300
)),
80
]
),
formatter
:
(
data
:
TooltipForAccuracy
):
React
.
ReactNode
=>
(
'
<div class="tooldetailAccuracy">
'
+
'
<div>Trial No.:
'
+
data
.
data
[
0
]
+
'
</div>
'
+
'
<div>Default metric:
'
+
data
.
data
[
1
]
+
'
</div>
'
+
'
<div>Parameters: <pre>
'
+
JSON
.
stringify
(
data
.
data
[
2
],
null
,
4
)
+
'
</pre></div>
'
+
'
</div>
'
),
},
dataZoom
:
[
{
id
:
'
dataZoomY
'
,
type
:
'
inside
'
,
yAxisIndex
:
[
0
],
filterMode
:
'
empty
'
,
start
:
startY
,
end
:
endY
}
],
xAxis
:
{
name
:
'
Trial
'
,
type
:
'
category
'
,
},
yAxis
:
{
name
:
'
Default metric
'
,
type
:
'
value
'
,
scale
:
true
,
},
series
:
undefined
,
};
}
generateScatterSeries
(
trials
:
Trial
[]):
any
{
const
data
=
trials
.
map
(
trial
=>
[
const
data
=
trials
.
map
(
trial
=>
[
trial
.
sequenceId
,
trial
.
sequenceId
,
trial
.
accuracy
,
trial
.
accuracy
,
...
@@ -63,27 +116,24 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
...
@@ -63,27 +116,24 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
data
,
data
,
};
};
}
}
generateBestCurveSeries
=
(
trials
:
Trial
[]):
any
=>
{
generateBestCurveSeries
(
trials
:
Trial
[]):
any
{
let
best
=
trials
[
0
];
let
best
=
trials
[
0
];
const
data
=
[[
best
.
sequenceId
,
best
.
accuracy
,
best
.
description
.
parameters
]];
const
data
=
[[
best
.
sequenceId
,
best
.
accuracy
,
best
.
description
.
parameters
]];
for
(
let
i
=
1
;
i
<
trials
.
length
;
i
++
)
{
for
(
let
i
=
1
;
i
<
trials
.
length
;
i
++
)
{
const
trial
=
trials
[
i
];
const
trial
=
trials
[
i
];
if
(
trial
.
accuracy
!==
undefined
)
{
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if
(
best
.
accuracy
!==
undefined
)
{
const
delta
=
trial
.
accuracy
!
-
best
.
accuracy
!
;
const
delta
=
trial
.
accuracy
-
best
.
accuracy
;
const
better
=
(
EXPERIMENT
.
optimizeMode
===
'
minimize
'
)
?
(
delta
<
0
)
:
(
delta
>
0
);
const
better
=
(
EXPERIMENT
.
optimizeMode
===
'
minimize
'
)
?
(
delta
<
0
)
:
(
delta
>
0
);
if
(
better
)
{
if
(
better
)
{
data
.
push
([
trial
.
sequenceId
,
trial
.
accuracy
,
trial
.
description
.
parameters
]);
data
.
push
([
trial
.
sequenceId
,
trial
.
accuracy
,
trial
.
description
.
parameters
]);
best
=
trial
;
best
=
trial
;
}
else
{
}
else
{
data
.
push
([
trial
.
sequenceId
,
best
.
accuracy
,
trial
.
description
.
parameters
]);
data
.
push
([
trial
.
sequenceId
,
best
.
accuracy
,
trial
.
description
.
parameters
]);
}
}
}
}
}
}
return
{
return
{
type
:
'
line
'
,
type
:
'
line
'
,
lineStyle
:
{
color
:
'
#FF6600
'
},
lineStyle
:
{
color
:
'
#FF6600
'
},
...
@@ -98,24 +148,26 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
...
@@ -98,24 +148,26 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
return
(
return
(
<
div
>
<
div
>
<
div
className
=
"default-metric"
>
<
Stack
horizontalAlign
=
"end"
className
=
"default-metric"
>
<
div
className
=
"position"
>
<
Toggle
label
=
"Optimization curve"
<
span
className
=
"bold"
>
Optimization curve
</
span
>
inlineLabel
<
Switch
defaultChecked
=
{
false
}
onChange
=
{
this
.
loadDefault
}
/>
onChange
=
{
this
.
loadDefault
}
</
div
>
/>
</
Stack
>
<
div
className
=
"default-metric-graph"
>
<
ReactEcharts
option
=
{
graph
}
style
=
{
{
width
:
'
100%
'
,
height
:
402
,
margin
:
'
0 auto
'
,
}
}
theme
=
"my_theme"
notMerge
=
{
true
}
// update now
onEvents
=
{
onEvents
}
/>
<
div
className
=
"default-metric-noData"
>
{
accNodata
}
</
div
>
</
div
>
</
div
>
<
ReactEcharts
option
=
{
graph
}
style
=
{
{
width
:
'
100%
'
,
height
:
402
,
margin
:
'
0 auto
'
,
}
}
theme
=
"my_theme"
notMerge
=
{
true
}
// update now
onEvents
=
{
onEvents
}
/>
<
div
className
=
"showMess"
>
{
accNodata
}
</
div
>
</
div
>
</
div
>
);
);
}
}
...
@@ -133,58 +185,6 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
...
@@ -133,58 +185,6 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
}
}
return
graph
;
return
graph
;
}
}
private
generateGraphConfig
(
maxSequenceId
:
number
):
any
{
const
{
startY
,
endY
}
=
this
.
state
;
return
{
grid
:
{
left
:
'
8%
'
,
},
tooltip
:
{
trigger
:
'
item
'
,
enterable
:
true
,
position
:
(
point
:
number
[],
data
:
TooltipForAccuracy
):
number
[]
=>
(
[(
data
.
data
[
0
]
<
maxSequenceId
?
point
[
0
]
:
(
point
[
0
]
-
300
)),
80
]
),
formatter
:
(
data
:
TooltipForAccuracy
):
any
=>
(
'
<div class="tooldetailAccuracy">
'
+
'
<div>Trial No.:
'
+
data
.
data
[
0
]
+
'
</div>
'
+
'
<div>Default metric:
'
+
data
.
data
[
1
]
+
'
</div>
'
+
'
<div>Parameters: <pre>
'
+
JSON
.
stringify
(
data
.
data
[
2
],
null
,
4
)
+
'
</pre></div>
'
+
'
</div>
'
),
},
dataZoom
:
[
{
id
:
'
dataZoomY
'
,
type
:
'
inside
'
,
yAxisIndex
:
[
0
],
filterMode
:
'
empty
'
,
start
:
startY
,
end
:
endY
}
],
xAxis
:
{
name
:
'
Trial
'
,
type
:
'
category
'
,
},
yAxis
:
{
name
:
'
Default metric
'
,
type
:
'
value
'
,
scale
:
true
,
},
series
:
undefined
,
};
}
private
metricDataZoom
=
(
e
:
EventMap
):
void
=>
{
if
(
e
.
batch
!==
undefined
)
{
this
.
setState
(()
=>
({
startY
:
(
e
.
batch
[
0
].
start
!==
null
?
e
.
batch
[
0
].
start
:
0
),
endY
:
(
e
.
batch
[
0
].
end
!==
null
?
e
.
batch
[
0
].
end
:
100
)
}));
}
}
}
}
export
default
DefaultPoint
;
export
default
DefaultPoint
;
src/webui/src/components/trial-detail/Duration.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
{
TableObj
,
EventMap
}
from
'
src
/static/interface
'
;
import
{
TableObj
,
EventMap
}
from
'
../..
/static/interface
'
;
// eslint-disable-line no-unused-vars
import
{
filterDuration
}
from
'
src
/static/function
'
;
import
{
filterDuration
}
from
'
../..
/static/function
'
;
require
(
'
echarts/lib/chart/bar
'
)
;
import
'
echarts/lib/chart/bar
'
;
require
(
'
echarts/lib/component/tooltip
'
)
;
import
'
echarts/lib/component/tooltip
'
;
require
(
'
echarts/lib/component/title
'
)
;
import
'
echarts/lib/component/title
'
;
interface
Runtrial
{
interface
Runtrial
{
trialId
:
Array
<
string
>
;
trialId
:
string
[]
;
trialTime
:
number
[];
trialTime
:
number
[];
}
}
...
@@ -19,6 +19,7 @@ interface DurationProps {
...
@@ -19,6 +19,7 @@ interface DurationProps {
interface
DurationState
{
interface
DurationState
{
startDuration
:
number
;
// for record data zoom
startDuration
:
number
;
// for record data zoom
endDuration
:
number
;
endDuration
:
number
;
durationSource
:
{};
}
}
class
Duration
extends
React
.
Component
<
DurationProps
,
DurationState
>
{
class
Duration
extends
React
.
Component
<
DurationProps
,
DurationState
>
{
...
@@ -29,6 +30,59 @@ class Duration extends React.Component<DurationProps, DurationState> {
...
@@ -29,6 +30,59 @@ class Duration extends React.Component<DurationProps, DurationState> {
this
.
state
=
{
this
.
state
=
{
startDuration
:
0
,
// for record data zoom
startDuration
:
0
,
// for record data zoom
endDuration
:
100
,
endDuration
:
100
,
durationSource
:
this
.
initDuration
(
this
.
props
.
source
),
};
}
initDuration
=
(
source
:
Array
<
TableObj
>
):
any
=>
{
const
trialId
:
number
[]
=
[];
const
trialTime
:
number
[]
=
[];
const
trialJobs
=
source
.
filter
(
filterDuration
);
trialJobs
.
forEach
(
item
=>
{
trialId
.
push
(
item
.
sequenceId
);
trialTime
.
push
(
item
.
duration
);
});
return
{
tooltip
:
{
trigger
:
'
axis
'
,
axisPointer
:
{
type
:
'
shadow
'
}
},
grid
:
{
bottom
:
'
3%
'
,
containLabel
:
true
,
left
:
'
1%
'
,
right
:
'
5%
'
},
dataZoom
:
[
{
id
:
'
dataZoomY
'
,
type
:
'
inside
'
,
yAxisIndex
:
[
0
],
filterMode
:
'
empty
'
,
start
:
0
,
end
:
100
},
],
xAxis
:
{
name
:
'
Time/s
'
,
type
:
'
value
'
,
},
yAxis
:
{
name
:
'
Trial No.
'
,
type
:
'
category
'
,
data
:
trialId
,
nameTextStyle
:
{
padding
:
[
0
,
0
,
0
,
30
]
}
},
series
:
[{
type
:
'
bar
'
,
data
:
trialTime
}]
};
};
}
}
...
@@ -45,7 +99,7 @@ class Duration extends React.Component<DurationProps, DurationState> {
...
@@ -45,7 +99,7 @@ class Duration extends React.Component<DurationProps, DurationState> {
bottom
:
'
3%
'
,
bottom
:
'
3%
'
,
containLabel
:
true
,
containLabel
:
true
,
left
:
'
1%
'
,
left
:
'
1%
'
,
right
:
'
4
%
'
right
:
'
5
%
'
},
},
dataZoom
:
[
dataZoom
:
[
{
{
...
@@ -64,7 +118,10 @@ class Duration extends React.Component<DurationProps, DurationState> {
...
@@ -64,7 +118,10 @@ class Duration extends React.Component<DurationProps, DurationState> {
yAxis
:
{
yAxis
:
{
name
:
'
Trial
'
,
name
:
'
Trial
'
,
type
:
'
category
'
,
type
:
'
category
'
,
data
:
dataObj
.
trialId
data
:
dataObj
.
trialId
,
nameTextStyle
:
{
padding
:
[
0
,
0
,
0
,
30
]
}
},
},
series
:
[{
series
:
[{
type
:
'
bar
'
,
type
:
'
bar
'
,
...
@@ -73,11 +130,11 @@ class Duration extends React.Component<DurationProps, DurationState> {
...
@@ -73,11 +130,11 @@ class Duration extends React.Component<DurationProps, DurationState> {
};
};
}
}
drawDurationGraph
=
(
source
:
Array
<
TableObj
>
):
any
=>
{
drawDurationGraph
=
(
source
:
Array
<
TableObj
>
):
void
=>
{
// why this function run two times when props changed?
// why this function run two times when props changed?
const
trialId
:
Array
<
string
>
=
[];
const
trialId
:
string
[]
=
[];
const
trialTime
:
number
[]
=
[];
const
trialTime
:
number
[]
=
[];
const
trialRun
:
Array
<
Runtrial
>
=
[];
const
trialRun
:
Runtrial
[]
=
[];
const
trialJobs
=
source
.
filter
(
filterDuration
);
const
trialJobs
=
source
.
filter
(
filterDuration
);
Object
.
keys
(
trialJobs
).
map
(
item
=>
{
Object
.
keys
(
trialJobs
).
map
(
item
=>
{
const
temp
=
trialJobs
[
item
];
const
temp
=
trialJobs
[
item
];
...
@@ -88,7 +145,21 @@ class Duration extends React.Component<DurationProps, DurationState> {
...
@@ -88,7 +145,21 @@ class Duration extends React.Component<DurationProps, DurationState> {
trialId
:
trialId
,
trialId
:
trialId
,
trialTime
:
trialTime
trialTime
:
trialTime
});
});
return
this
.
getOption
(
trialRun
[
0
]);
this
.
setState
({
durationSource
:
this
.
getOption
(
trialRun
[
0
])
});
}
componentDidMount
():
void
{
const
{
source
}
=
this
.
props
;
this
.
drawDurationGraph
(
source
);
}
componentWillReceiveProps
(
nextProps
:
DurationProps
):
void
{
const
{
whichGraph
,
source
}
=
nextProps
;
if
(
whichGraph
===
'
3
'
)
{
this
.
drawDurationGraph
(
source
);
}
}
}
shouldComponentUpdate
(
nextProps
:
DurationProps
):
boolean
{
shouldComponentUpdate
(
nextProps
:
DurationProps
):
boolean
{
...
@@ -117,15 +188,13 @@ class Duration extends React.Component<DurationProps, DurationState> {
...
@@ -117,15 +188,13 @@ class Duration extends React.Component<DurationProps, DurationState> {
}
}
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
const
{
durationSource
}
=
this
.
state
;
const
{
source
}
=
this
.
props
;
const
graph
=
this
.
drawDurationGraph
(
source
);
const
onEvents
=
{
'
dataZoom
'
:
this
.
durationDataZoom
};
const
onEvents
=
{
'
dataZoom
'
:
this
.
durationDataZoom
};
return
(
return
(
<
div
>
<
div
>
<
ReactEcharts
<
ReactEcharts
option
=
{
graph
}
option
=
{
durationSource
}
style
=
{
{
width
:
'
9
5
%
'
,
height
:
412
,
margin
:
'
0 auto
'
}
}
style
=
{
{
width
:
'
9
4
%
'
,
height
:
412
,
margin
:
'
0 auto
'
,
marginTop
:
15
}
}
theme
=
"my_theme"
theme
=
"my_theme"
notMerge
=
{
true
}
// update now
notMerge
=
{
true
}
// update now
onEvents
=
{
onEvents
}
onEvents
=
{
onEvents
}
...
...
src/webui/src/components/trial-detail/Intermediate.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Row
,
Button
,
Switch
}
from
'
antd
'
;
import
{
Stack
,
PrimaryButton
,
Toggle
,
IStackTokens
}
from
'
office-ui-fabric-react
'
;
import
{
TooltipForIntermediate
,
TableObj
,
Intermedia
,
EventMap
}
from
'
../../static/interface
'
;
import
{
TooltipForIntermediate
,
TableObj
,
Intermedia
,
EventMap
}
from
'
../../static/interface
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
require
(
'
echarts/lib/component/tooltip
'
);
import
'
echarts/lib/component/tooltip
'
;
require
(
'
echarts/lib/component/title
'
);
import
'
echarts/lib/component/title
'
;
const
stackTokens
:
IStackTokens
=
{
childrenGap
:
20
};
interface
IntermediateState
{
interface
IntermediateState
{
detailSource
:
Array
<
TableObj
>
;
detailSource
:
Array
<
TableObj
>
;
...
@@ -11,7 +15,7 @@ interface IntermediateState {
...
@@ -11,7 +15,7 @@ interface IntermediateState {
filterSource
:
Array
<
TableObj
>
;
filterSource
:
Array
<
TableObj
>
;
eachIntermediateNum
:
number
;
// trial's intermediate number count
eachIntermediateNum
:
number
;
// trial's intermediate number count
isLoadconfirmBtn
:
boolean
;
isLoadconfirmBtn
:
boolean
;
isFilter
:
boolean
;
isFilter
?
:
boolean
|
undefined
;
length
:
number
;
length
:
number
;
clickCounts
:
number
;
// user filter intermediate click confirm btn's counts
clickCounts
:
number
;
// user filter intermediate click confirm btn's counts
startMediaY
:
number
;
startMediaY
:
number
;
...
@@ -26,9 +30,9 @@ interface IntermediateProps {
...
@@ -26,9 +30,9 @@ interface IntermediateProps {
class
Intermediate
extends
React
.
Component
<
IntermediateProps
,
IntermediateState
>
{
class
Intermediate
extends
React
.
Component
<
IntermediateProps
,
IntermediateState
>
{
static
intervalMediate
=
1
;
static
intervalMediate
=
1
;
public
pointInput
:
HTMLInputElement
|
null
;
public
pointInput
!
:
HTMLInputElement
|
null
;
public
minValInput
:
HTMLInputElement
|
null
;
public
minValInput
!
:
HTMLInputElement
|
null
;
public
maxValInput
:
HTMLInputElement
|
null
;
public
maxValInput
!
:
HTMLInputElement
|
null
;
constructor
(
props
:
IntermediateProps
)
{
constructor
(
props
:
IntermediateProps
)
{
super
(
props
);
super
(
props
);
...
@@ -65,7 +69,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
...
@@ -65,7 +69,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
});
});
// find max intermediate number
// find max intermediate number
trialIntermediate
.
sort
((
a
,
b
)
=>
{
return
(
b
.
data
.
length
-
a
.
data
.
length
);
});
trialIntermediate
.
sort
((
a
,
b
)
=>
{
return
(
b
.
data
.
length
-
a
.
data
.
length
);
});
const
legend
:
Array
<
string
>
=
[];
const
legend
:
string
[]
=
[];
// max length
// max length
const
length
=
trialIntermediate
[
0
].
data
.
length
;
const
length
=
trialIntermediate
[
0
].
data
.
length
;
const
xAxis
:
number
[]
=
[];
const
xAxis
:
number
[]
=
[];
...
@@ -87,7 +91,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
...
@@ -87,7 +91,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
return
[
point
[
0
]
-
300
,
80
];
return
[
point
[
0
]
-
300
,
80
];
}
}
},
},
formatter
:
function
(
data
:
TooltipForIntermediate
):
any
{
formatter
:
function
(
data
:
TooltipForIntermediate
):
React
.
ReactNode
{
const
trialId
=
data
.
seriesName
;
const
trialId
=
data
.
seriesName
;
let
obj
=
{};
let
obj
=
{};
const
temp
=
trialIntermediate
.
find
(
key
=>
key
.
name
===
trialId
);
const
temp
=
trialIntermediate
.
find
(
key
=>
key
.
name
===
trialId
);
...
@@ -116,7 +120,8 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
...
@@ -116,7 +120,8 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
},
},
yAxis
:
{
yAxis
:
{
type
:
'
value
'
,
type
:
'
value
'
,
name
:
'
Metric
'
name
:
'
Metric
'
,
scale
:
true
,
},
},
dataZoom
:
[
dataZoom
:
[
{
{
...
@@ -195,7 +200,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
...
@@ -195,7 +200,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
});
});
}
}
switchTurn
=
(
checked
:
boolean
):
void
=>
{
switchTurn
=
(
ev
:
React
.
MouseEvent
<
HTMLElement
>
,
checked
?
:
boolean
):
void
=>
{
this
.
setState
({
isFilter
:
checked
});
this
.
setState
({
isFilter
:
checked
});
if
(
checked
===
false
)
{
if
(
checked
===
false
)
{
this
.
drawIntermediate
(
this
.
props
.
source
);
this
.
drawIntermediate
(
this
.
props
.
source
);
...
@@ -226,62 +231,18 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
...
@@ -226,62 +231,18 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
}
}
}
}
shouldComponentUpdate
(
nextProps
:
IntermediateProps
,
nextState
:
IntermediateState
):
boolean
{
const
{
whichGraph
,
source
}
=
nextProps
;
const
beforeGraph
=
this
.
props
.
whichGraph
;
if
(
whichGraph
===
'
4
'
)
{
const
{
isFilter
,
length
,
clickCounts
}
=
nextState
;
const
beforeLength
=
this
.
state
.
length
;
const
beforeSource
=
this
.
props
.
source
;
const
beforeClickCounts
=
this
.
state
.
clickCounts
;
if
(
isFilter
!==
this
.
state
.
isFilter
)
{
return
true
;
}
if
(
clickCounts
!==
beforeClickCounts
)
{
return
true
;
}
if
(
isFilter
===
false
)
{
if
(
whichGraph
!==
beforeGraph
)
{
return
true
;
}
if
(
length
!==
beforeLength
)
{
return
true
;
}
if
(
beforeSource
.
length
!==
source
.
length
)
{
return
true
;
}
if
(
beforeSource
[
beforeSource
.
length
-
1
]
!==
undefined
)
{
if
(
source
[
source
.
length
-
1
].
description
.
intermediate
.
length
!==
beforeSource
[
beforeSource
.
length
-
1
].
description
.
intermediate
.
length
)
{
return
true
;
}
if
(
source
[
source
.
length
-
1
].
duration
!==
beforeSource
[
beforeSource
.
length
-
1
].
duration
)
{
return
true
;
}
if
(
source
[
source
.
length
-
1
].
status
!==
beforeSource
[
beforeSource
.
length
-
1
].
status
)
{
return
true
;
}
}
}
}
return
false
;
}
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
const
{
interSource
,
isLoadconfirmBtn
,
isFilter
}
=
this
.
state
;
const
{
interSource
,
isLoadconfirmBtn
,
isFilter
}
=
this
.
state
;
const
IntermediateEvents
=
{
'
dataZoom
'
:
this
.
intermediateDataZoom
};
const
IntermediateEvents
=
{
'
dataZoom
'
:
this
.
intermediateDataZoom
};
return
(
return
(
<
div
>
<
div
>
{
/* style in para.scss */
}
{
/* style in para.scss */
}
<
Row
className
=
"meline intermediate"
>
<
Stack
horizontal
horizontalAlign
=
"end"
tokens
=
{
stackTokens
}
className
=
"meline intermediate"
>
{
{
isFilter
isFilter
?
?
<
span
style
=
{
{
marginRight
:
15
}
}
>
<
div
>
<
span
className
=
"filter-x"
>
# Intermediate result
</
span
>
<
span
className
=
"filter-x"
>
# Intermediate result
</
span
>
<
input
<
input
// placeholder="point"
// placeholder="point"
...
@@ -298,34 +259,31 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
...
@@ -298,34 +259,31 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
// placeholder="range"
// placeholder="range"
ref
=
{
(
input
):
any
=>
this
.
maxValInput
=
input
}
ref
=
{
(
input
):
any
=>
this
.
maxValInput
=
input
}
/>
/>
<
Button
<
PrimaryButton
type
=
"primary"
text
=
"Confirm"
className
=
"changeBtu tableButton"
onClick
=
{
this
.
filterLines
}
onClick
=
{
this
.
filterLines
}
disabled
=
{
isLoadconfirmBtn
}
disabled
=
{
isLoadconfirmBtn
}
>
/>
Confirm
</
div
>
</
Button
>
</
span
>
:
:
null
null
}
}
{
/* filter message */
}
{
/* filter message */
}
<
span
>
Filter
</
span
>
<
Stack
horizontal
className
=
"filter-toggle"
>
<
Switch
<
span
>
Filter
</
span
>
defaultChecked
=
{
false
}
<
Toggle
onChange
=
{
this
.
switchTurn
}
/>
onChange
=
{
this
.
switchTurn
}
</
Stack
>
/>
</
Row
>
</
Stack
>
<
Row
className
=
"intermediate-graph"
>
<
div
className
=
"intermediate-graph"
>
<
ReactEcharts
<
ReactEcharts
option
=
{
interSource
}
option
=
{
interSource
}
style
=
{
{
width
:
'
100%
'
,
height
:
4
18
,
margin
:
'
0 auto
'
}
}
style
=
{
{
width
:
'
100%
'
,
height
:
4
00
,
margin
:
'
0 auto
'
}
}
notMerge
=
{
true
}
// update now
notMerge
=
{
true
}
// update now
onEvents
=
{
IntermediateEvents
}
onEvents
=
{
IntermediateEvents
}
/>
/>
<
div
className
=
"yAxis"
>
# Intermediate result
</
div
>
<
div
className
=
"yAxis"
>
# Intermediate result
</
div
>
</
Row
>
</
div
>
</
div
>
</
div
>
);
);
}
}
...
...
src/webui/src/components/trial-detail/Para.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
{
filterByStatus
}
from
'
../../static/function
'
;
import
{
filterByStatus
}
from
'
../../static/function
'
;
import
{
Row
,
Col
,
Select
,
Button
,
message
}
from
'
antd
'
;
import
{
Stack
,
PrimaryButton
,
Dropdown
,
IDropdownOption
,
}
from
'
office-ui-fabric-react
'
;
// eslint-disable-line no-unused-vars
import
{
ParaObj
,
Dimobj
,
TableObj
}
from
'
../../static/interface
'
;
import
{
ParaObj
,
Dimobj
,
TableObj
}
from
'
../../static/interface
'
;
// eslint-disable-line no-unused-vars
const
Option
=
Select
.
Option
;
import
'
echarts/lib/chart/parallel
'
;
require
(
'
echarts/lib/chart/parallel
'
);
import
'
echarts/lib/component/tooltip
'
;
require
(
'
echarts/lib/component/tooltip
'
);
import
'
echarts/lib/component/title
'
;
require
(
'
echarts/lib/component/title
'
);
import
'
echarts/lib/component/visualMap
'
;
require
(
'
echarts/lib/component/visualMap
'
);
import
'
../../static/style/para.scss
'
;
require
(
'
../../static/style/para.scss
'
);
import
'
../../static/style/button.scss
'
;
require
(
'
../../static/style/button.scss
'
);
interface
ParaState
{
interface
ParaState
{
// paraSource: Array<TableObj>;
// paraSource: Array<TableObj>;
option
:
object
;
option
:
object
;
paraBack
:
ParaObj
;
paraBack
:
ParaObj
;
dimName
:
Array
<
string
>
;
dimName
:
string
[]
;
swapAxisArr
:
Array
<
string
>
;
swapAxisArr
:
string
[]
;
percent
:
number
;
percent
:
number
;
paraNodata
:
string
;
paraNodata
:
string
;
max
:
number
;
// graph color bar limit
max
:
number
;
// graph color bar limit
...
@@ -25,6 +24,9 @@ interface ParaState {
...
@@ -25,6 +24,9 @@ interface ParaState {
succeedRenderCount
:
number
;
// all succeed trials number
succeedRenderCount
:
number
;
// all succeed trials number
clickCounts
:
number
;
clickCounts
:
number
;
isLoadConfirm
:
boolean
;
isLoadConfirm
:
boolean
;
// office-fabric-ui
selectedItem
?:
{
key
:
string
|
number
|
undefined
};
// percent Selector
swapyAxis
?:
string
[];
// yAxis Selector
}
}
interface
ParaProps
{
interface
ParaProps
{
...
@@ -33,11 +35,6 @@ interface ParaProps {
...
@@ -33,11 +35,6 @@ interface ParaProps {
whichGraph
:
string
;
whichGraph
:
string
;
}
}
message
.
config
({
top
:
250
,
duration
:
2
,
});
class
Para
extends
React
.
Component
<
ParaProps
,
ParaState
>
{
class
Para
extends
React
.
Component
<
ParaProps
,
ParaState
>
{
private
chartMulineStyle
=
{
private
chartMulineStyle
=
{
...
@@ -69,14 +66,15 @@ class Para extends React.Component<ParaProps, ParaState> {
...
@@ -69,14 +66,15 @@ class Para extends React.Component<ParaProps, ParaState> {
sutrialCount
:
10000000
,
sutrialCount
:
10000000
,
succeedRenderCount
:
10000000
,
succeedRenderCount
:
10000000
,
clickCounts
:
1
,
clickCounts
:
1
,
isLoadConfirm
:
false
isLoadConfirm
:
false
,
swapyAxis
:
[]
};
};
}
}
getParallelAxis
=
getParallelAxis
=
(
(
dimName
:
Array
<
string
>
,
parallelAxis
:
Array
<
Dimobj
>
,
dimName
:
string
[]
,
parallelAxis
:
Array
<
Dimobj
>
,
accPara
:
number
[],
eachTrialParams
:
Array
<
string
>
,
accPara
:
number
[],
eachTrialParams
:
string
[]
,
lengthofTrials
:
number
lengthofTrials
:
number
):
void
=>
{
):
void
=>
{
// get data for every lines. if dim is choice type, number -> toString()
// get data for every lines. if dim is choice type, number -> toString()
...
@@ -128,7 +126,7 @@ class Para extends React.Component<ParaProps, ParaState> {
...
@@ -128,7 +126,7 @@ class Para extends React.Component<ParaProps, ParaState> {
const
lenOfDataSource
:
number
=
dataSource
.
length
;
const
lenOfDataSource
:
number
=
dataSource
.
length
;
const
accPara
:
number
[]
=
[];
const
accPara
:
number
[]
=
[];
// specific value array
// specific value array
const
eachTrialParams
:
Array
<
string
>
=
[];
const
eachTrialParams
:
string
[]
=
[];
// experiment interface search space obj
// experiment interface search space obj
const
searchRange
=
searchSpace
!==
undefined
?
JSON
.
parse
(
searchSpace
)
:
''
;
const
searchRange
=
searchSpace
!==
undefined
?
JSON
.
parse
(
searchSpace
)
:
''
;
// nest search space
// nest search space
...
@@ -147,8 +145,8 @@ class Para extends React.Component<ParaProps, ParaState> {
...
@@ -147,8 +145,8 @@ class Para extends React.Component<ParaProps, ParaState> {
let
i
=
0
;
let
i
=
0
;
if
(
isNested
===
false
)
{
if
(
isNested
===
false
)
{
for
(
i
;
i
<
dimName
.
length
;
i
++
)
{
for
(
i
;
i
<
dimName
.
length
;
i
++
)
{
const
data
:
string
[]
=
[];
const
searchKey
=
searchRange
[
dimName
[
i
]];
const
searchKey
=
searchRange
[
dimName
[
i
]];
const
data
:
Array
<
string
>
=
[];
switch
(
searchKey
.
_type
)
{
switch
(
searchKey
.
_type
)
{
case
'
uniform
'
:
case
'
uniform
'
:
case
'
quniform
'
:
case
'
quniform
'
:
...
@@ -220,10 +218,11 @@ class Para extends React.Component<ParaProps, ParaState> {
...
@@ -220,10 +218,11 @@ class Para extends React.Component<ParaProps, ParaState> {
}
else
{
}
else
{
for
(
i
;
i
<
dimName
.
length
;
i
++
)
{
for
(
i
;
i
<
dimName
.
length
;
i
++
)
{
const
searchKey
=
searchRange
[
dimName
[
i
]];
const
searchKey
=
searchRange
[
dimName
[
i
]];
const
data
:
Array
<
string
>
=
[];
const
data
:
string
[]
=
[];
let
j
=
0
;
switch
(
searchKey
.
_type
)
{
switch
(
searchKey
.
_type
)
{
case
'
choice
'
:
case
'
choice
'
:
for
(
let
j
=
0
;
j
<
searchKey
.
_value
.
length
;
j
++
)
{
for
(
j
;
j
<
searchKey
.
_value
.
length
;
j
++
)
{
const
item
=
searchKey
.
_value
[
j
];
const
item
=
searchKey
.
_value
[
j
];
Object
.
keys
(
item
).
map
(
key
=>
{
Object
.
keys
(
item
).
map
(
key
=>
{
if
(
key
!==
'
_name
'
&&
key
!==
'
_type
'
)
{
if
(
key
!==
'
_name
'
&&
key
!==
'
_type
'
)
{
...
@@ -362,10 +361,15 @@ class Para extends React.Component<ParaProps, ParaState> {
...
@@ -362,10 +361,15 @@ class Para extends React.Component<ParaProps, ParaState> {
}
}
// get percent value number
// get percent value number
percentNum
=
(
value
:
string
):
void
=>
{
// percentNum = (value: string) => {
percentNum
=
(
event
:
React
.
FormEvent
<
HTMLDivElement
>
,
item
?:
IDropdownOption
):
void
=>
{
const
vals
=
parseFloat
(
value
);
// percentNum = (event: React.FormEvent<HTMLDivElement>, item?: ISelectableOption) => {
this
.
setState
({
percent
:
vals
},
()
=>
{
this
.
reInit
();
});
if
(
item
!==
undefined
)
{
const
vals
=
parseFloat
(
item
!==
undefined
?
item
.
text
:
''
);
this
.
setState
({
percent
:
vals
/
100
,
selectedItem
:
item
},
()
=>
{
this
.
reInit
();
});
}
}
}
// deal with response data into pic data
// deal with response data into pic data
...
@@ -439,8 +443,24 @@ class Para extends React.Component<ParaProps, ParaState> {
...
@@ -439,8 +443,24 @@ class Para extends React.Component<ParaProps, ParaState> {
}
}
// get swap parallel axis
// get swap parallel axis
getSwapArr
=
(
value
:
Array
<
string
>
):
void
=>
{
getSwapArr
=
(
event
:
React
.
FormEvent
<
HTMLDivElement
>
,
item
?:
IDropdownOption
):
void
=>
{
this
.
setState
({
swapAxisArr
:
value
});
const
newSelectedItems
=
[...
this
.
state
.
swapyAxis
];
if
(
item
!==
undefined
)
{
if
(
item
.
selected
)
{
// add the option if it's checked
newSelectedItems
.
push
(
item
.
key
as
string
);
}
else
{
// remove the option if it's unchecked
const
currIndex
=
newSelectedItems
.
indexOf
(
item
.
key
as
string
);
if
(
currIndex
>
-
1
)
{
newSelectedItems
.
splice
(
currIndex
,
1
);
}
}
this
.
setState
({
swapAxisArr
:
newSelectedItems
,
swapyAxis
:
newSelectedItems
});
}
}
}
reInit
=
():
void
=>
{
reInit
=
():
void
=>
{
...
@@ -571,80 +591,47 @@ class Para extends React.Component<ParaProps, ParaState> {
...
@@ -571,80 +591,47 @@ class Para extends React.Component<ParaProps, ParaState> {
}
}
}
}
shouldComponentUpdate
(
nextProps
:
ParaProps
,
nextState
:
ParaState
):
boolean
{
const
{
whichGraph
}
=
nextProps
;
const
beforeGraph
=
this
.
props
.
whichGraph
;
if
(
whichGraph
===
'
2
'
)
{
if
(
whichGraph
!==
beforeGraph
)
{
return
true
;
}
const
{
sutrialCount
,
clickCounts
,
succeedRenderCount
}
=
nextState
;
const
beforeCount
=
this
.
state
.
sutrialCount
;
const
beforeClickCount
=
this
.
state
.
clickCounts
;
const
beforeRealRenderCount
=
this
.
state
.
succeedRenderCount
;
if
(
sutrialCount
!==
beforeCount
)
{
return
true
;
}
if
(
succeedRenderCount
!==
beforeRealRenderCount
)
{
return
true
;
}
if
(
clickCounts
!==
beforeClickCount
)
{
return
true
;
}
}
return
false
;
}
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
const
{
option
,
paraNodata
,
dimName
,
isLoadConfirm
}
=
this
.
state
;
const
{
option
,
paraNodata
,
dimName
,
isLoadConfirm
,
selectedItem
,
swapyAxis
}
=
this
.
state
;
return
(
return
(
<
Row
className
=
"parameter"
>
<
div
className
=
"parameter"
>
<
Row
>
<
Stack
horizontal
className
=
"para-filter"
horizontalAlign
=
"end"
>
<
Col
span
=
{
6
}
/>
<
span
className
=
"para-filter-text"
>
Top
</
span
>
<
Col
span
=
{
18
}
>
<
Dropdown
<
Row
className
=
"meline"
>
selectedKey
=
{
selectedItem
?
selectedItem
.
key
:
undefined
}
<
span
>
Top
</
span
>
onChange
=
{
this
.
percentNum
}
<
Select
placeholder
=
"100%"
style
=
{
{
width
:
'
20%
'
,
marginRight
:
10
}
}
defaultSelectedKeys
=
{
[
0.2
]
}
placeholder
=
"100%"
options
=
{
[
optionFilterProp
=
"children"
{
key
:
'
0.2
'
,
text
:
'
20%
'
},
onSelect
=
{
this
.
percentNum
}
{
key
:
'
0.5
'
,
text
:
'
50%
'
},
>
{
key
:
'
0.8
'
,
text
:
'
80%
'
},
<
Option
value
=
"0.2"
>
20%
</
Option
>
{
key
:
'
1
'
,
text
:
'
100%
'
},
<
Option
value
=
"0.5"
>
50%
</
Option
>
]
}
<
Option
value
=
"0.8"
>
80%
</
Option
>
styles
=
{
{
dropdown
:
{
width
:
300
}
}
}
<
Option
value
=
"1"
>
100%
</
Option
>
className
=
"para-filter-percent"
</
Select
>
/>
<
Select
<
Dropdown
style
=
{
{
width
:
'
60%
'
}
}
placeholder
=
"Select options"
mode
=
"multiple"
selectedKeys
=
{
swapyAxis
}
placeholder
=
"Please select two items to swap"
onChange
=
{
this
.
getSwapArr
}
onChange
=
{
this
.
getSwapArr
}
multiSelect
maxTagCount
=
{
2
}
options
=
{
>
dimName
.
map
((
key
,
item
)
=>
{
{
return
{
dimName
.
map
((
key
,
item
)
=>
{
key
:
key
,
text
:
dimName
[
item
]
return
(
};
<
Option
key
=
{
key
}
value
=
{
dimName
[
item
]
}
>
{
dimName
[
item
]
}
</
Option
>
})
);
}
})
styles
=
{
{
dropdown
:
{
width
:
300
}
}
}
}
/>
</
Select
>
<
PrimaryButton
<
Button
text
=
"Confirm"
type
=
"primary"
onClick
=
{
this
.
swapReInit
}
className
=
"changeBtu tableButton"
disabled
=
{
isLoadConfirm
}
onClick
=
{
this
.
swapReInit
}
/>
disabled
=
{
isLoadConfirm
}
</
Stack
>
>
<
div
className
=
"searcHyper"
>
Confirm
</
Button
>
</
Row
>
</
Col
>
</
Row
>
<
Row
className
=
"searcHyper"
>
<
ReactEcharts
<
ReactEcharts
option
=
{
option
}
option
=
{
option
}
style
=
{
this
.
chartMulineStyle
}
style
=
{
this
.
chartMulineStyle
}
...
@@ -652,8 +639,8 @@ class Para extends React.Component<ParaProps, ParaState> {
...
@@ -652,8 +639,8 @@ class Para extends React.Component<ParaProps, ParaState> {
notMerge
=
{
true
}
// update now
notMerge
=
{
true
}
// update now
/>
/>
<
div
className
=
"noneData"
>
{
paraNodata
}
</
div
>
<
div
className
=
"noneData"
>
{
paraNodata
}
</
div
>
</
Row
>
</
div
>
</
Row
>
</
div
>
);
);
}
}
}
}
...
...
src/webui/src/components/trial-detail/TableList.tsx
View file @
c7187946
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
{
Row
,
Table
,
Button
,
Popconfirm
,
Modal
,
Checkbox
,
Select
,
Icon
}
from
'
antd
'
;
import
{
import
{
ColumnProps
}
from
'
antd/lib/table
'
;
Stack
,
Dropdown
,
DetailsList
,
IDetailsListProps
,
DetailsListLayoutMode
,
const
Option
=
Select
.
Option
;
PrimaryButton
,
Modal
,
IDropdownOption
,
IColumn
,
Selection
,
SelectionMode
,
IconButton
const
CheckboxGroup
=
Checkbox
.
Group
;
}
from
'
office-ui-fabric-react
'
;
import
{
MANAGER_IP
,
trialJobStatus
,
COLUMN_INDEX
,
COLUMNPro
}
from
'
../../static/const
'
;
import
{
LineChart
,
blocked
,
copy
}
from
'
../Buttons/Icon
'
;
import
{
convertDuration
,
formatTimestamp
,
intermediateGraphOption
,
killJob
,
parseMetrics
}
from
'
../../static/function
'
;
import
{
MANAGER_IP
,
COLUMNPro
}
from
'
../../static/const
'
;
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
}
from
'
../../static/interface
'
;
import
OpenRow
from
'
../public-child/OpenRow
'
;
import
Details
from
'
../overview/Details
'
;
import
Compare
from
'
../Modal/Compare
'
;
import
ChangeColumnComponent
from
'
../Modals/ChangeColumnComponent
'
;
import
Customize
from
'
../Modal/CustomizedTrial
'
;
import
Compare
from
'
../Modals/Compare
'
;
import
KillJob
from
'
../Modals/Killjob
'
;
import
Customize
from
'
../Modals/CustomizedTrial
'
;
import
{
contentStyles
,
iconButtonStyles
}
from
'
../Buttons/ModalTheme
'
;
import
'
../../static/style/search.scss
'
;
import
'
../../static/style/search.scss
'
;
require
(
'
../../static/style/tableStatus.css
'
)
;
import
'
../../static/style/tableStatus.css
'
;
require
(
'
../../static/style/logPath.scss
'
)
;
import
'
../../static/style/logPath.scss
'
;
require
(
'
../../static/style/search.scss
'
)
;
import
'
../../static/style/search.scss
'
;
require
(
'
../../static/style/table.scss
'
)
;
import
'
../../static/style/table.scss
'
;
require
(
'
../../static/style/button.scss
'
)
;
import
'
../../static/style/button.scss
'
;
require
(
'
../../static/style/openRow.scss
'
)
;
import
'
../../static/style/openRow.scss
'
;
const
echarts
=
require
(
'
echarts/lib/echarts
'
);
const
echarts
=
require
(
'
echarts/lib/echarts
'
);
require
(
'
echarts/lib/chart/line
'
);
require
(
'
echarts/lib/chart/line
'
);
require
(
'
echarts/lib/component/tooltip
'
);
require
(
'
echarts/lib/component/tooltip
'
);
...
@@ -27,11 +31,12 @@ echarts.registerTheme('my_theme', {
...
@@ -27,11 +31,12 @@ echarts.registerTheme('my_theme', {
color
:
'
#3c8dbc
'
color
:
'
#3c8dbc
'
});
});
interface
TableListProps
{
interface
TableListProps
{
pageSize
:
number
;
pageSize
:
number
;
tableSource
:
Array
<
TableRecord
>
;
tableSource
:
Array
<
TableRecord
>
;
columnList
:
Array
<
string
>
;
// user select columnKeys
columnList
:
string
[]
;
// user select columnKeys
changeColumn
:
(
val
:
Array
<
string
>
)
=>
void
;
changeColumn
:
(
val
:
string
[]
)
=>
void
;
trialsUpdateBroadcast
:
number
;
trialsUpdateBroadcast
:
number
;
}
}
...
@@ -40,115 +45,29 @@ interface TableListState {
...
@@ -40,115 +45,29 @@ interface TableListState {
modalVisible
:
boolean
;
modalVisible
:
boolean
;
isObjFinal
:
boolean
;
isObjFinal
:
boolean
;
isShowColumn
:
boolean
;
isShowColumn
:
boolean
;
selectRows
:
Array
<
TableRecord
>
;
selectRows
:
Array
<
any
>
;
isShowCompareModal
:
boolean
;
isShowCompareModal
:
boolean
;
selectedRowKeys
:
string
[]
|
number
[];
selectedRowKeys
:
string
[]
|
number
[];
intermediateData
:
Array
<
object
>
;
// a trial's intermediate results (include dict)
intermediateData
:
Array
<
object
>
;
// a trial's intermediate results (include dict)
intermediateId
:
string
;
intermediateId
:
string
;
intermediateOtherKeys
:
Array
<
string
>
;
intermediateOtherKeys
:
string
[]
;
isShowCustomizedModal
:
boolean
;
isShowCustomizedModal
:
boolean
;
copyTrialId
:
string
;
// user copy trial to submit a new customized trial
copyTrialId
:
string
;
// user copy trial to submit a new customized trial
isCalloutVisible
:
boolean
;
// kill job button callout [kill or not kill job window]
intermediateKeys
:
string
[];
// intermeidate modal: which key is choosed.
isExpand
:
boolean
;
modalIntermediateWidth
:
number
;
modalIntermediateHeight
:
number
;
tableColumns
:
IColumn
[];
allColumnList
:
string
[];
tableSourceForSort
:
Array
<
TableRecord
>
;
}
}
interface
ColumnIndex
{
name
:
string
;
index
:
number
;
}
const
AccuracyColumnConfig
:
ColumnProps
<
TableRecord
>
=
{
title
:
'
Default metric
'
,
className
:
'
leftTitle
'
,
dataIndex
:
'
accuracy
'
,
sorter
:
(
a
,
b
,
sortOrder
)
=>
{
if
(
a
.
latestAccuracy
===
undefined
)
{
return
sortOrder
===
'
ascend
'
?
1
:
-
1
;
}
else
if
(
b
.
latestAccuracy
===
undefined
)
{
return
sortOrder
===
'
ascend
'
?
-
1
:
1
;
}
else
{
return
a
.
latestAccuracy
-
b
.
latestAccuracy
;
}
},
render
:
(
text
,
record
):
React
.
ReactNode
=>
<
div
>
{
record
.
formattedLatestAccuracy
}
</
div
>
};
const
SequenceIdColumnConfig
:
ColumnProps
<
TableRecord
>
=
{
title
:
'
Trial No.
'
,
dataIndex
:
'
sequenceId
'
,
className
:
'
tableHead
'
,
sorter
:
(
a
,
b
)
=>
a
.
sequenceId
-
b
.
sequenceId
};
const
IdColumnConfig
:
ColumnProps
<
TableRecord
>
=
{
title
:
'
ID
'
,
dataIndex
:
'
id
'
,
className
:
'
tableHead leftTitle
'
,
sorter
:
(
a
,
b
)
=>
a
.
id
.
localeCompare
(
b
.
id
),
render
:
(
text
,
record
):
React
.
ReactNode
=>
(
<
div
>
{
record
.
id
}
</
div
>
)
};
const
StartTimeColumnConfig
:
ColumnProps
<
TableRecord
>
=
{
title
:
'
Start Time
'
,
dataIndex
:
'
startTime
'
,
sorter
:
(
a
,
b
)
=>
a
.
startTime
-
b
.
startTime
,
render
:
(
text
,
record
):
React
.
ReactNode
=>
(
<
span
>
{
formatTimestamp
(
record
.
startTime
)
}
</
span
>
)
};
const
EndTimeColumnConfig
:
ColumnProps
<
TableRecord
>
=
{
title
:
'
End Time
'
,
dataIndex
:
'
endTime
'
,
sorter
:
(
a
,
b
,
sortOrder
)
=>
{
if
(
a
.
endTime
===
undefined
)
{
return
sortOrder
===
'
ascend
'
?
1
:
-
1
;
}
else
if
(
b
.
endTime
===
undefined
)
{
return
sortOrder
===
'
ascend
'
?
-
1
:
1
;
}
else
{
return
a
.
endTime
-
b
.
endTime
;
}
},
render
:
(
text
,
record
):
React
.
ReactNode
=>
(
<
span
>
{
formatTimestamp
(
record
.
endTime
,
'
--
'
)
}
</
span
>
)
};
const
DurationColumnConfig
:
ColumnProps
<
TableRecord
>
=
{
title
:
'
Duration
'
,
dataIndex
:
'
duration
'
,
sorter
:
(
a
,
b
)
=>
a
.
duration
-
b
.
duration
,
render
:
(
text
,
record
):
React
.
ReactNode
=>
(
<
span
className
=
"durationsty"
>
{
convertDuration
(
record
.
duration
)
}
</
span
>
)
};
const
StatusColumnConfig
:
ColumnProps
<
TableRecord
>
=
{
title
:
'
Status
'
,
dataIndex
:
'
status
'
,
className
:
'
tableStatus
'
,
render
:
(
text
,
record
):
React
.
ReactNode
=>
(
<
span
className
=
{
`
${
record
.
status
}
commonStyle`
}
>
{
record
.
status
}
</
span
>
),
sorter
:
(
a
,
b
)
=>
a
.
status
.
localeCompare
(
b
.
status
),
filters
:
trialJobStatus
.
map
(
status
=>
({
text
:
status
,
value
:
status
})),
onFilter
:
(
value
,
record
)
=>
(
record
.
status
===
value
)
};
const
IntermediateCountColumnConfig
:
ColumnProps
<
TableRecord
>
=
{
title
:
'
Intermediate result
'
,
dataIndex
:
'
intermediateCount
'
,
sorter
:
(
a
,
b
)
=>
a
.
intermediateCount
-
b
.
intermediateCount
,
render
:
(
text
,
record
):
React
.
ReactNode
=>
(
<
span
>
{
`#
${
record
.
intermediateCount
}
`
}
</
span
>
)
};
class
TableList
extends
React
.
Component
<
TableListProps
,
TableListState
>
{
class
TableList
extends
React
.
Component
<
TableListProps
,
TableListState
>
{
public
intervalTrialLog
=
10
;
public
intervalTrialLog
=
10
;
public
_trialId
:
string
;
public
trialId
!
:
string
;
public
tables
:
Table
<
TableRecord
>
|
null
;
constructor
(
props
:
TableListProps
)
{
constructor
(
props
:
TableListProps
)
{
super
(
props
);
super
(
props
);
...
@@ -165,18 +84,164 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -165,18 +84,164 @@ class TableList extends React.Component<TableListProps, TableListState> {
intermediateId
:
''
,
intermediateId
:
''
,
intermediateOtherKeys
:
[],
intermediateOtherKeys
:
[],
isShowCustomizedModal
:
false
,
isShowCustomizedModal
:
false
,
copyTrialId
:
''
isCalloutVisible
:
false
,
copyTrialId
:
''
,
intermediateKeys
:
[
'
default
'
],
isExpand
:
false
,
modalIntermediateWidth
:
window
.
innerWidth
,
modalIntermediateHeight
:
window
.
innerHeight
,
tableColumns
:
this
.
initTableColumnList
(
this
.
props
.
columnList
),
allColumnList
:
this
.
getAllColumnKeys
(),
tableSourceForSort
:
this
.
props
.
tableSource
};
};
}
}
showIntermediateModal
=
async
(
id
:
string
):
Promise
<
void
>
=>
{
// sort for table column
onColumnClick
=
(
ev
:
React
.
MouseEvent
<
HTMLElement
>
,
getColumn
:
IColumn
):
void
=>
{
const
{
tableColumns
}
=
this
.
state
;
const
{
tableSource
}
=
this
.
props
;
const
newColumns
:
IColumn
[]
=
tableColumns
.
slice
();
const
currColumn
:
IColumn
=
newColumns
.
filter
(
item
=>
getColumn
.
key
===
item
.
key
)[
0
];
newColumns
.
forEach
((
newCol
:
IColumn
)
=>
{
if
(
newCol
===
currColumn
)
{
currColumn
.
isSortedDescending
=
!
currColumn
.
isSortedDescending
;
currColumn
.
isSorted
=
true
;
}
else
{
newCol
.
isSorted
=
false
;
newCol
.
isSortedDescending
=
true
;
}
});
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const
newItems
=
this
.
copyAndSort
(
tableSource
,
currColumn
.
fieldName
!
,
currColumn
.
isSortedDescending
);
this
.
setState
({
tableColumns
:
newColumns
,
tableSourceForSort
:
newItems
});
};
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
));
}
AccuracyColumnConfig
:
any
=
{
name
:
'
Default metric
'
,
className
:
'
leftTitle
'
,
key
:
'
accuracy
'
,
fieldName
:
'
accuracy
'
,
minWidth
:
200
,
maxWidth
:
300
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
item
):
React
.
ReactNode
=>
<
div
>
{
item
.
formattedLatestAccuracy
}
</
div
>
};
SequenceIdColumnConfig
:
any
=
{
name
:
'
Trial No.
'
,
key
:
'
sequenceId
'
,
fieldName
:
'
sequenceId
'
,
minWidth
:
80
,
maxWidth
:
120
,
className
:
'
tableHead
'
,
data
:
'
string
'
,
onColumnClick
:
this
.
onColumnClick
,
};
IdColumnConfig
:
any
=
{
name
:
'
ID
'
,
key
:
'
id
'
,
fieldName
:
'
id
'
,
minWidth
:
150
,
maxWidth
:
200
,
isResizable
:
true
,
data
:
'
string
'
,
onColumnClick
:
this
.
onColumnClick
,
className
:
'
tableHead leftTitle
'
};
StartTimeColumnConfig
:
any
=
{
name
:
'
Start Time
'
,
key
:
'
startTime
'
,
fieldName
:
'
startTime
'
,
minWidth
:
150
,
maxWidth
:
200
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
record
):
React
.
ReactNode
=>
(
<
span
>
{
formatTimestamp
(
record
.
startTime
)
}
</
span
>
)
};
EndTimeColumnConfig
:
any
=
{
name
:
'
End Time
'
,
key
:
'
endTime
'
,
fieldName
:
'
endTime
'
,
minWidth
:
150
,
maxWidth
:
200
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
record
):
React
.
ReactNode
=>
(
<
span
>
{
formatTimestamp
(
record
.
endTime
,
'
--
'
)
}
</
span
>
)
};
DurationColumnConfig
:
any
=
{
name
:
'
Duration
'
,
key
:
'
duration
'
,
fieldName
:
'
duration
'
,
minWidth
:
150
,
maxWidth
:
200
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
record
):
React
.
ReactNode
=>
(
<
span
className
=
"durationsty"
>
{
convertDuration
(
record
.
duration
)
}
</
span
>
)
};
StatusColumnConfig
:
any
=
{
name
:
'
Status
'
,
key
:
'
status
'
,
fieldName
:
'
status
'
,
className
:
'
tableStatus
'
,
minWidth
:
150
,
maxWidth
:
200
,
isResizable
:
true
,
data
:
'
string
'
,
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
record
):
React
.
ReactNode
=>
(
<
span
className
=
{
`
${
record
.
status
}
commonStyle`
}
>
{
record
.
status
}
</
span
>
),
};
IntermediateCountColumnConfig
:
any
=
{
name
:
'
Intermediate result
'
,
dataIndex
:
'
intermediateCount
'
,
fieldName
:
'
intermediateCount
'
,
minWidth
:
150
,
maxWidth
:
200
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
onRender
:
(
record
):
React
.
ReactNode
=>
(
<
span
>
{
`#
${
record
.
intermediateCount
}
`
}
</
span
>
)
};
showIntermediateModal
=
async
(
id
:
string
,
event
:
React
.
SyntheticEvent
<
EventTarget
>
):
Promise
<
void
>
=>
{
event
.
preventDefault
();
event
.
stopPropagation
();
const
res
=
await
axios
.
get
(
`
${
MANAGER_IP
}
/metric-data/
${
id
}
`
);
const
res
=
await
axios
.
get
(
`
${
MANAGER_IP
}
/metric-data/
${
id
}
`
);
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
let
otherkeys
:
Array
<
string
>
=
[
'
default
'
];
let
otherkeys
:
string
[]
=
[
'
default
'
];
if
(
res
.
data
.
length
!==
0
)
{
if
(
res
.
data
.
length
!==
0
)
{
otherkeys
=
Object
.
keys
(
parseMetrics
(
res
.
data
[
0
].
data
));
otherkeys
=
Object
.
keys
(
parseMetrics
(
res
.
data
[
0
].
data
));
}
}
...
@@ -202,34 +267,37 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -202,34 +267,37 @@ class TableList extends React.Component<TableListProps, TableListState> {
// intermediate button click -> intermediate graph for each trial
// intermediate button click -> intermediate graph for each trial
// support intermediate is dict
// support intermediate is dict
selectOtherKeys
=
(
value
:
string
):
void
=>
{
selectOtherKeys
=
(
event
:
React
.
FormEvent
<
HTMLDivElement
>
,
item
?:
IDropdownOption
):
void
=>
{
if
(
item
!==
undefined
)
{
const
isShowDefault
:
boolean
=
value
===
'
default
'
?
true
:
false
;
const
value
=
item
.
text
;
const
{
intermediateData
,
intermediateId
}
=
this
.
state
;
const
isShowDefault
:
boolean
=
value
===
'
default
'
?
true
:
false
;
const
intermediateArr
:
number
[]
=
[];
const
{
intermediateData
,
intermediateId
}
=
this
.
state
;
// just watch default key-val
const
intermediateArr
:
number
[]
=
[];
if
(
isShowDefault
===
true
)
{
// just watch default key-val
Object
.
keys
(
intermediateData
).
map
(
item
=>
{
if
(
isShowDefault
===
true
)
{
const
temp
=
parseMetrics
(
intermediateData
[
item
].
data
);
Object
.
keys
(
intermediateData
).
map
(
item
=>
{
if
(
typeof
temp
===
'
object
'
)
{
const
temp
=
parseMetrics
(
intermediateData
[
item
].
data
);
intermediateArr
.
push
(
temp
[
value
]);
if
(
typeof
temp
===
'
object
'
)
{
}
else
{
intermediateArr
.
push
(
temp
[
value
]);
intermediateArr
.
push
(
temp
);
}
else
{
}
intermediateArr
.
push
(
temp
);
});
}
}
else
{
});
Object
.
keys
(
intermediateData
).
map
(
item
=>
{
}
else
{
const
temp
=
parseMetrics
(
intermediateData
[
item
].
data
);
Object
.
keys
(
intermediateData
).
map
(
item
=>
{
if
(
typeof
temp
===
'
object
'
)
{
const
temp
=
parseMetrics
(
intermediateData
[
item
].
data
);
intermediateArr
.
push
(
temp
[
value
]);
if
(
typeof
temp
===
'
object
'
)
{
}
intermediateArr
.
push
(
temp
[
value
]);
}
});
}
const
intermediate
=
intermediateGraphOption
(
intermediateArr
,
intermediateId
);
// re-render
this
.
setState
({
intermediateKeys
:
[
value
],
intermediateOption
:
intermediate
});
});
}
}
const
intermediate
=
intermediateGraphOption
(
intermediateArr
,
intermediateId
);
// re-render
this
.
setState
({
intermediateOption
:
intermediate
});
}
}
hideIntermediateModal
=
():
void
=>
{
hideIntermediateModal
=
():
void
=>
{
...
@@ -239,81 +307,20 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -239,81 +307,20 @@ class TableList extends React.Component<TableListProps, TableListState> {
}
}
hideShowColumnModal
=
():
void
=>
{
hideShowColumnModal
=
():
void
=>
{
this
.
setState
({
isShowColumn
:
false
this
.
setState
(()
=>
({
isShowColumn
:
false
}));
});
}
}
// click add column btn, just show the modal of addcolumn
// click add column btn, just show the modal of addcolumn
addColumn
=
():
void
=>
{
addColumn
=
():
void
=>
{
// show user select check button
// show user select check button
this
.
setState
({
this
.
setState
(()
=>
({
isShowColumn
:
true
}));
isShowColumn
:
true
});
}
// checkbox for coloumn
selectedColumn
=
(
checkedValues
:
Array
<
string
>
):
void
=>
{
// 9: because have nine common column,
// [Intermediate count, Start Time, End Time] is hidden by default
let
count
=
9
;
const
want
:
Array
<
object
>
=
[];
const
finalKeys
:
Array
<
string
>
=
[];
const
wantResult
:
Array
<
string
>
=
[];
Object
.
keys
(
checkedValues
).
map
(
m
=>
{
switch
(
checkedValues
[
m
])
{
case
'
Trial No.
'
:
case
'
ID
'
:
case
'
Start Time
'
:
case
'
End Time
'
:
case
'
Duration
'
:
case
'
Status
'
:
case
'
Operation
'
:
case
'
Default
'
:
case
'
Intermediate result
'
:
break
;
default
:
finalKeys
.
push
(
checkedValues
[
m
]);
}
});
Object
.
keys
(
finalKeys
).
map
(
n
=>
{
want
.
push
({
name
:
finalKeys
[
n
],
index
:
count
++
});
});
Object
.
keys
(
checkedValues
).
map
(
item
=>
{
const
temp
=
checkedValues
[
item
];
Object
.
keys
(
COLUMN_INDEX
).
map
(
key
=>
{
const
index
=
COLUMN_INDEX
[
key
];
if
(
index
.
name
===
temp
)
{
want
.
push
(
index
);
}
});
});
want
.
sort
((
a
:
ColumnIndex
,
b
:
ColumnIndex
)
=>
{
return
a
.
index
-
b
.
index
;
});
Object
.
keys
(
want
).
map
(
i
=>
{
wantResult
.
push
(
want
[
i
].
name
);
});
this
.
props
.
changeColumn
(
wantResult
);
}
openRow
=
(
record
:
TableRecord
):
any
=>
{
return
(
<
OpenRow
trialId
=
{
record
.
id
}
/>
);
}
}
fillSelectedRowsTostate
=
(
selected
:
number
[]
|
string
[],
selectedRows
:
Array
<
TableRecord
>
):
void
=>
{
fillSelectedRowsTostate
=
(
selected
:
number
[]
|
string
[],
selectedRows
:
Array
<
TableRecord
>
):
void
=>
{
this
.
setState
({
selectRows
:
selectedRows
,
selectedRowKeys
:
selected
});
this
.
setState
({
selectRows
:
selectedRows
,
selectedRowKeys
:
selected
});
}
}
// open Compare-modal
// open Compare-modal
compareBtn
=
():
void
=>
{
compareBtn
=
():
void
=>
{
...
@@ -324,6 +331,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -324,6 +331,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
this
.
setState
({
isShowCompareModal
:
true
});
this
.
setState
({
isShowCompareModal
:
true
});
}
}
}
}
// close Compare-modal
// close Compare-modal
hideCompareModal
=
():
void
=>
{
hideCompareModal
=
():
void
=>
{
// close modal. clear select rows data, clear selected track
// close modal. clear select rows data, clear selected track
...
@@ -331,178 +339,181 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -331,178 +339,181 @@ class TableList extends React.Component<TableListProps, TableListState> {
}
}
// open customized trial modal
// open customized trial modal
setCustomizedTrial
=
(
trialId
:
string
):
void
=>
{
private
setCustomizedTrial
=
(
trialId
:
string
,
event
:
React
.
SyntheticEvent
<
EventTarget
>
):
void
=>
{
event
.
preventDefault
();
event
.
stopPropagation
();
this
.
setState
({
this
.
setState
({
isShowCustomizedModal
:
true
,
isShowCustomizedModal
:
true
,
copyTrialId
:
trialId
copyTrialId
:
trialId
});
});
}
}
closeCustomizedTrial
=
():
void
=>
{
private
closeCustomizedTrial
=
():
void
=>
{
this
.
setState
({
this
.
setState
({
isShowCustomizedModal
:
false
,
isShowCustomizedModal
:
false
,
copyTrialId
:
''
copyTrialId
:
''
});
});
}
}
render
():
React
.
ReactNode
{
const
{
pageSize
,
columnList
}
=
this
.
props
;
const
tableSource
:
Array
<
TableRecord
>
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
props
.
tableSource
));
const
{
intermediateOption
,
modalVisible
,
isShowColumn
,
selectRows
,
isShowCompareModal
,
selectedRowKeys
,
intermediateOtherKeys
,
isShowCustomizedModal
,
copyTrialId
}
=
this
.
state
;
const
rowSelection
=
{
selectedRowKeys
:
selectedRowKeys
,
onChange
:
(
selected
:
string
[]
|
number
[],
selectedRows
:
Array
<
TableRecord
>
):
void
=>
{
this
.
fillSelectedRowsTostate
(
selected
,
selectedRows
);
}
};
// [supportCustomizedTrial: true]
const
supportCustomizedTrial
=
(
EXPERIMENT
.
multiPhase
===
true
)
?
false
:
true
;
const
disabledAddCustomizedTrial
=
[
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
].
includes
(
EXPERIMENT
.
status
);
let
showTitle
=
COLUMNPro
;
const
showColumn
:
Array
<
object
>
=
[];
private
onWindowResize
=
():
void
=>
{
this
.
setState
(()
=>
({
modalIntermediateHeight
:
window
.
innerHeight
,
modalIntermediateWidth
:
window
.
innerWidth
}));
}
private
onRenderRow
:
IDetailsListProps
[
'
onRenderRow
'
]
=
props
=>
{
if
(
props
)
{
return
<
Details
detailsProps
=
{
props
}
/>;
}
return
null
;
};
private
getSelectedRows
=
new
Selection
({
onSelectionChanged
:
():
void
=>
{
this
.
setState
(()
=>
({
selectRows
:
this
.
getSelectedRows
.
getSelection
()
}));
}
});
// trial parameters & dict final keys & Trial No. Id ...
private
getAllColumnKeys
=
():
string
[]
=>
{
const
tableSource
:
Array
<
TableRecord
>
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
props
.
tableSource
));
// parameter as table column
// parameter as table column
const
parameterStr
:
Array
<
string
>
=
[];
const
parameterStr
:
string
[]
=
[];
if
(
tableSource
.
length
>
0
)
{
if
(
tableSource
.
length
>
0
)
{
const
trialMess
=
TRIALS
.
getTrial
(
tableSource
[
0
].
id
);
const
trialMess
=
TRIALS
.
getTrial
(
tableSource
[
0
].
id
);
const
trial
=
trialMess
.
description
.
parameters
;
const
trial
=
trialMess
.
description
.
parameters
;
const
parameterColumn
:
Array
<
string
>
=
Object
.
keys
(
trial
);
const
parameterColumn
:
string
[]
=
Object
.
keys
(
trial
);
parameterColumn
.
forEach
(
value
=>
{
parameterColumn
.
forEach
(
value
=>
{
parameterStr
.
push
(
`
${
value
}
(search space)`
);
parameterStr
.
push
(
`
${
value
}
(search space)`
);
});
});
}
}
showTitle
=
COLUMNPro
.
concat
(
parameterStr
);
let
allColumnList
=
COLUMNPro
;
// eslint-disable-line @typescript-eslint/no-unused-vars
allColumnList
=
COLUMNPro
.
concat
(
parameterStr
);
// only succeed trials have final keys
// only succeed trials have final keys
if
(
tableSource
.
filter
(
record
=>
record
.
status
===
'
SUCCEEDED
'
).
length
>=
1
)
{
if
(
tableSource
.
filter
(
record
=>
record
.
status
===
'
SUCCEEDED
'
).
length
>=
1
)
{
const
temp
=
tableSource
.
filter
(
record
=>
record
.
status
===
'
SUCCEEDED
'
)[
0
].
accuracy
;
const
temp
=
tableSource
.
filter
(
record
=>
record
.
status
===
'
SUCCEEDED
'
)[
0
].
accuracy
;
if
(
temp
!==
undefined
&&
typeof
temp
===
'
object
'
)
{
if
(
temp
!==
undefined
&&
typeof
temp
===
'
object
'
)
{
// concat default column and finalkeys
if
(
!
isNaN
(
temp
))
{
const
item
=
Object
.
keys
(
temp
);
// concat default column and finalkeys
// item: ['default', 'other-keys', 'maybe loss']
const
item
=
Object
.
keys
(
temp
);
if
(
item
.
length
>
1
)
{
// item: ['default', 'other-keys', 'maybe loss']
const
want
:
Array
<
string
>
=
[];
if
(
item
.
length
>
1
)
{
item
.
forEach
(
value
=>
{
const
want
:
string
[]
=
[];
if
(
value
!==
'
default
'
)
{
item
.
forEach
(
value
=>
{
want
.
push
(
value
);
if
(
value
!==
'
default
'
)
{
}
want
.
push
(
value
);
});
}
showTitle
=
COLUMNPro
.
concat
(
want
);
});
allColumnList
=
COLUMNPro
.
concat
(
want
);
}
}
}
}
}
}
}
return
allColumnList
;
}
// get IColumn[]
// when user click [Add Column] need to use the function
private
initTableColumnList
=
(
columnList
:
string
[]):
IColumn
[]
=>
{
// const { columnList } = this.props;
// [supportCustomizedTrial: true]
const
supportCustomizedTrial
=
(
EXPERIMENT
.
multiPhase
===
true
)
?
false
:
true
;
const
disabledAddCustomizedTrial
=
[
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
].
includes
(
EXPERIMENT
.
status
);
const
showColumn
:
IColumn
[]
=
[];
for
(
const
item
of
columnList
)
{
for
(
const
item
of
columnList
)
{
const
paraColumn
=
item
.
match
(
/
\(
search space
\)
$/
);
const
paraColumn
=
item
.
match
(
/
\(
search space
\)
$/
);
let
cc
;
let
result
;
if
(
paraColumn
!==
null
)
{
if
(
paraColumn
!==
null
)
{
cc
=
paraColumn
.
input
;
result
=
paraColumn
.
input
;
}
}
switch
(
item
)
{
switch
(
item
)
{
case
'
Trial No.
'
:
case
'
Trial No.
'
:
showColumn
.
push
(
SequenceIdColumnConfig
);
showColumn
.
push
(
this
.
SequenceIdColumnConfig
);
break
;
break
;
case
'
ID
'
:
case
'
ID
'
:
showColumn
.
push
(
IdColumnConfig
);
showColumn
.
push
(
this
.
IdColumnConfig
);
break
;
break
;
case
'
Start Time
'
:
case
'
Start Time
'
:
showColumn
.
push
(
StartTimeColumnConfig
);
showColumn
.
push
(
this
.
StartTimeColumnConfig
);
break
;
break
;
case
'
End Time
'
:
case
'
End Time
'
:
showColumn
.
push
(
EndTimeColumnConfig
);
showColumn
.
push
(
this
.
EndTimeColumnConfig
);
break
;
break
;
case
'
Duration
'
:
case
'
Duration
'
:
showColumn
.
push
(
DurationColumnConfig
);
showColumn
.
push
(
this
.
DurationColumnConfig
);
break
;
break
;
case
'
Status
'
:
case
'
Status
'
:
showColumn
.
push
(
StatusColumnConfig
);
showColumn
.
push
(
this
.
StatusColumnConfig
);
break
;
break
;
case
'
Intermediate result
'
:
case
'
Intermediate result
'
:
showColumn
.
push
(
IntermediateCountColumnConfig
);
showColumn
.
push
(
this
.
IntermediateCountColumnConfig
);
break
;
break
;
case
'
Default
'
:
case
'
Default
'
:
showColumn
.
push
(
AccuracyColumnConfig
);
showColumn
.
push
(
this
.
AccuracyColumnConfig
);
break
;
break
;
case
'
Operation
'
:
case
'
Operation
'
:
showColumn
.
push
({
showColumn
.
push
({
title
:
'
Operation
'
,
name
:
'
Operation
'
,
dataIndex
:
'
operation
'
,
key
:
'
operation
'
,
key
:
'
operation
'
,
render
:
(
text
:
string
,
record
:
TableRecord
)
=>
{
fieldName
:
'
operation
'
,
minWidth
:
160
,
maxWidth
:
200
,
isResizable
:
true
,
className
:
'
detail-table
'
,
onRender
:
(
record
:
any
)
=>
{
const
trialStatus
=
record
.
status
;
const
trialStatus
=
record
.
status
;
// could kill a job when its status is RUNNING or UNKNOWN
const
flag
:
boolean
=
(
trialStatus
===
'
RUNNING
'
||
trialStatus
===
'
UNKNOWN
'
)
?
false
:
true
;
const
flag
:
boolean
=
(
trialStatus
===
'
RUNNING
'
||
trialStatus
===
'
UNKNOWN
'
)
?
false
:
true
;
return
(
return
(
<
Row
id
=
"detail-button"
>
<
Stack
className
=
"detail-button"
horizontal
>
{
/* see intermediate result graph */
}
{
/* see intermediate result graph */
}
<
Button
<
PrimaryButton
type
=
"primary"
className
=
"detail-button-operation"
className
=
"common-style"
onClick
=
{
this
.
showIntermediateModal
.
bind
(
this
,
record
.
id
)
}
title
=
"Intermediate"
title
=
"Intermediate"
onClick
=
{
this
.
showIntermediateModal
.
bind
(
this
,
record
.
id
)
}
>
>
<
Icon
type
=
"l
ine
-c
hart
"
/>
{
L
ine
C
hart
}
</
Button
>
</
Primary
Button
>
{
/* kill job */
}
{
/* kill job */
}
{
{
flag
flag
?
?
<
Button
<
PrimaryButton
className
=
"detail-button-operation"
disabled
=
{
true
}
title
=
"kill"
>
type
=
"default"
{
blocked
}
disabled
=
{
true
}
</
PrimaryButton
>
className
=
"margin-mediate special"
title
=
"kill"
>
<
Icon
type
=
"stop"
/>
</
Button
>
:
:
<
Popconfirm
<
KillJob
trial
=
{
record
}
/>
title
=
"Are you sure to cancel this trial?"
okText
=
"Yes"
cancelText
=
"No"
onConfirm
=
{
killJob
.
bind
(
this
,
record
.
key
,
record
.
id
,
record
.
status
)
}
>
<
Button
type
=
"default"
disabled
=
{
false
}
className
=
"margin-mediate special"
title
=
"kill"
>
<
Icon
type
=
"stop"
/>
</
Button
>
</
Popconfirm
>
}
}
{
/* Add a new trial-customized trial */
}
{
/* Add a new trial-customized trial */
}
{
{
supportCustomizedTrial
supportCustomizedTrial
?
?
<
Button
<
PrimaryButton
type
=
"primary"
className
=
"detail-button-operation"
className
=
"common-style"
disabled
=
{
disabledAddCustomizedTrial
}
onClick
=
{
this
.
setCustomizedTrial
.
bind
(
this
,
record
.
id
)
}
title
=
"Customized trial"
title
=
"Customized trial"
onClick
=
{
this
.
setCustomizedTrial
.
bind
(
this
,
record
.
id
)
}
disabled
=
{
disabledAddCustomizedTrial
}
>
>
<
Icon
type
=
"copy"
/>
{
copy
}
</
Button
>
</
Primary
Button
>
:
:
null
null
}
}
</
Row
>
</
Stack
>
);
);
},
},
});
});
break
;
break
;
case
(
cc
):
case
(
result
):
// remove SEARCH_SPACE title
// remove SEARCH_SPACE title
// const realItem = item.replace(' (search space)', '');
// const realItem = item.replace(' (search space)', '');
showColumn
.
push
({
showColumn
.
push
({
title
:
item
.
replace
(
'
(search space)
'
,
''
),
name
:
item
.
replace
(
'
(search space)
'
,
''
),
dataIndex
:
item
,
key
:
item
,
key
:
item
,
render
:
(
text
:
string
,
record
:
TableRecord
)
=>
{
fieldName
:
item
,
minWidth
:
150
,
onRender
:
(
record
:
TableRecord
)
=>
{
const
eachTrial
=
TRIALS
.
getTrial
(
record
.
id
);
const
eachTrial
=
TRIALS
.
getTrial
(
record
.
id
);
return
(
return
(
<
span
>
{
eachTrial
.
description
.
parameters
[
item
.
replace
(
'
(search space)
'
,
''
)]
}
</
span
>
<
span
>
{
eachTrial
.
description
.
parameters
[
item
.
replace
(
'
(search space)
'
,
''
)]
}
</
span
>
...
@@ -515,88 +526,110 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -515,88 +526,110 @@ class TableList extends React.Component<TableListProps, TableListState> {
alert
(
'
Unexpected column type
'
);
alert
(
'
Unexpected column type
'
);
}
}
}
}
return
showColumn
;
}
componentDidMount
():
void
{
window
.
addEventListener
(
'
resize
'
,
this
.
onWindowResize
);
}
UNSAFE_componentWillReceiveProps
(
nextProps
:
TableListProps
):
void
{
const
{
columnList
}
=
nextProps
;
this
.
setState
({
tableColumns
:
this
.
initTableColumnList
(
columnList
)
});
}
render
():
React
.
ReactNode
{
const
{
intermediateKeys
,
modalIntermediateWidth
,
modalIntermediateHeight
,
tableColumns
,
allColumnList
,
isShowColumn
,
modalVisible
,
selectRows
,
isShowCompareModal
,
intermediateOtherKeys
,
isShowCustomizedModal
,
copyTrialId
,
intermediateOption
}
=
this
.
state
;
const
{
columnList
}
=
this
.
props
;
const
tableSource
:
Array
<
TableRecord
>
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
state
.
tableSourceForSort
));
return
(
return
(
<
Row
className
=
"tableList"
>
<
Stack
>
<
div
id
=
"tableList"
>
<
div
id
=
"tableList"
>
<
Table
<
DetailsList
ref
=
{
(
table
:
Table
<
TableRecord
>
|
null
):
any
=>
this
.
tables
=
table
}
columns
=
{
tableColumns
}
columns
=
{
showColumn
}
items
=
{
tableSource
}
rowSelection
=
{
rowSelection
}
setKey
=
"set"
expandedRowRender
=
{
this
.
openRow
}
compact
=
{
true
}
dataSource
=
{
tableSource
}
onRenderRow
=
{
this
.
onRenderRow
}
c
la
ssName
=
"commonTableStyle"
la
youtMode
=
{
DetailsListLayoutMode
.
justified
}
s
croll
=
{
{
x
:
'
max-content
'
}
}
s
electionMode
=
{
SelectionMode
.
multiple
}
pagination
=
{
pageSize
>
0
?
{
pageSize
}
:
false
}
selection
=
{
this
.
getSelectedRows
}
/>
/>
{
/* Intermediate Result Modal */
}
<
Modal
title
=
"Intermediate result"
visible
=
{
modalVisible
}
onCancel
=
{
this
.
hideIntermediateModal
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
width
=
"80%"
>
{
intermediateOtherKeys
.
length
>
1
?
<
Row
className
=
"selectKeys"
>
<
Select
className
=
"select"
defaultValue
=
"default"
onSelect
=
{
this
.
selectOtherKeys
}
>
{
Object
.
keys
(
intermediateOtherKeys
).
map
(
item
=>
{
const
keys
=
intermediateOtherKeys
[
item
];
return
<
Option
value
=
{
keys
}
key
=
{
item
}
>
{
keys
}
</
Option
>;
})
}
</
Select
>
</
Row
>
:
<
div
/>
}
<
ReactEcharts
option
=
{
intermediateOption
}
style
=
{
{
width
:
'
100%
'
,
height
:
0.7
*
window
.
innerHeight
}
}
theme
=
"my_theme"
/>
</
Modal
>
</
div
>
</
div
>
{
/*
Add Column
Modal */
}
{
/*
Intermediate Result
Modal */
}
<
Modal
<
Modal
title
=
"Table Title"
isOpen
=
{
modalVisible
}
visible
=
{
isShowColumn
}
onDismiss
=
{
this
.
hideIntermediateModal
}
onCancel
=
{
this
.
hideShowColumnModal
}
containerClassName
=
{
contentStyles
.
container
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
width
=
"40%"
>
>
<
CheckboxGroup
<
div
className
=
{
contentStyles
.
header
}
>
options
=
{
showTitle
}
<
span
>
Intermediate result
</
span
>
defaultValue
=
{
columnList
}
<
IconButton
// defaultValue={columnSelected}
styles
=
{
iconButtonStyles
}
onChange
=
{
this
.
selectedColumn
}
iconProps
=
{
{
iconName
:
'
Cancel
'
}
}
className
=
"titleColumn"
ariaLabel
=
"Close popup modal"
onClick
=
{
this
.
hideIntermediateModal
as
any
}
/>
</
div
>
{
intermediateOtherKeys
.
length
>
1
?
<
Stack
className
=
"selectKeys"
styles
=
{
{
root
:
{
width
:
800
}
}
}
>
<
Dropdown
className
=
"select"
selectedKeys
=
{
intermediateKeys
}
onChange
=
{
this
.
selectOtherKeys
}
options
=
{
intermediateOtherKeys
.
map
((
key
,
item
)
=>
{
return
{
key
:
key
,
text
:
intermediateOtherKeys
[
item
]
};
})
}
styles
=
{
{
dropdown
:
{
width
:
300
}
}
}
/>
</
Stack
>
:
null
}
<
ReactEcharts
option
=
{
intermediateOption
}
style
=
{
{
width
:
0.5
*
modalIntermediateWidth
,
height
:
0.7
*
modalIntermediateHeight
,
padding
:
20
}
}
theme
=
"my_theme"
/>
/>
</
Modal
>
</
Modal
>
{
/* Add Column Modal */
}
{
isShowColumn
&&
<
ChangeColumnComponent
hideShowColumnDialog
=
{
this
.
hideShowColumnModal
}
isHideDialog
=
{
!
isShowColumn
}
showColumn
=
{
allColumnList
}
selectedColumn
=
{
columnList
}
changeColumn
=
{
this
.
props
.
changeColumn
}
/>
}
{
/* compare trials based message */
}
{
/* compare trials based message */
}
<
Compare
compare
Row
s
=
{
selectRows
}
visible
=
{
isShowCompareModal
}
cancelFunc
=
{
this
.
hideCompareModal
}
/>
{
isShowCompareModal
&&
<
Compare
compare
Stack
s
=
{
selectRows
}
cancelFunc
=
{
this
.
hideCompareModal
}
/>
}
{
/* clone trial parameters and could submit a customized trial */
}
{
/* clone trial parameters and could submit a customized trial */
}
<
Customize
<
Customize
visible
=
{
isShowCustomizedModal
}
visible
=
{
isShowCustomizedModal
}
copyTrialId
=
{
copyTrialId
}
copyTrialId
=
{
copyTrialId
}
closeCustomizeModal
=
{
this
.
closeCustomizedTrial
}
closeCustomizeModal
=
{
this
.
closeCustomizedTrial
}
/>
/>
</
Row
>
</
Stack
>
);
);
}
}
}
}
export
default
TableList
;
export
default
TableList
;
\ No newline at end of file
Prev
1
2
3
4
5
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