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
3b90b9d9
Commit
3b90b9d9
authored
Oct 26, 2020
by
liuzhe
Browse files
Merge branch 'master' into v2.0-merge
parents
e21a6984
77dac12b
Changes
143
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
418 additions
and
181 deletions
+418
-181
test/nni_test/nnitest/generate_ts_config.py
test/nni_test/nnitest/generate_ts_config.py
+3
-0
test/pipelines/pipelines-it-remote-linux-to-linux.yml
test/pipelines/pipelines-it-remote-linux-to-linux.yml
+1
-1
test/pipelines/pipelines-it-remote-windows-to-linux.yml
test/pipelines/pipelines-it-remote-windows-to-linux.yml
+1
-1
ts/nni_manager/training_service/remote_machine/extends/linuxCommands.ts
.../training_service/remote_machine/extends/linuxCommands.ts
+4
-0
ts/nni_manager/training_service/remote_machine/extends/windowsCommands.ts
...raining_service/remote_machine/extends/windowsCommands.ts
+4
-0
ts/nni_manager/training_service/remote_machine/osCommands.ts
ts/nni_manager/training_service/remote_machine/osCommands.ts
+1
-0
ts/nni_manager/training_service/remote_machine/shellExecutor.ts
..._manager/training_service/remote_machine/shellExecutor.ts
+6
-0
ts/nni_manager/training_service/reusable/environments/remoteEnvironmentService.ts
...service/reusable/environments/remoteEnvironmentService.ts
+34
-31
ts/nni_manager/training_service/reusable/trialDispatcher.ts
ts/nni_manager/training_service/reusable/trialDispatcher.ts
+11
-8
ts/nni_manager/yarn.lock
ts/nni_manager/yarn.lock
+60
-27
ts/webui/src/App.scss
ts/webui/src/App.scss
+1
-1
ts/webui/src/App.tsx
ts/webui/src/App.tsx
+32
-2
ts/webui/src/components/Overview.tsx
ts/webui/src/components/Overview.tsx
+28
-8
ts/webui/src/components/TrialsDetail.tsx
ts/webui/src/components/TrialsDetail.tsx
+1
-1
ts/webui/src/components/modals/CustomizedTrial.tsx
ts/webui/src/components/modals/CustomizedTrial.tsx
+4
-1
ts/webui/src/components/modals/Killjob.tsx
ts/webui/src/components/modals/Killjob.tsx
+6
-2
ts/webui/src/components/overview/command/Command1.tsx
ts/webui/src/components/overview/command/Command1.tsx
+5
-28
ts/webui/src/components/overview/command/Command2.tsx
ts/webui/src/components/overview/command/Command2.tsx
+65
-0
ts/webui/src/components/overview/count/EditExperimentParam.tsx
...bui/src/components/overview/count/EditExperimentParam.tsx
+122
-51
ts/webui/src/components/overview/count/ExpDuration.tsx
ts/webui/src/components/overview/count/ExpDuration.tsx
+29
-19
No files found.
test/nni_test/nnitest/generate_ts_config.py
View file @
3b90b9d9
...
@@ -86,6 +86,8 @@ def update_training_service_config(args):
...
@@ -86,6 +86,8 @@ def update_training_service_config(args):
config
[
args
.
ts
][
'machineList'
][
0
][
'port'
]
=
args
.
remote_port
config
[
args
.
ts
][
'machineList'
][
0
][
'port'
]
=
args
.
remote_port
if
args
.
remote_pwd
is
not
None
:
if
args
.
remote_pwd
is
not
None
:
config
[
args
.
ts
][
'machineList'
][
0
][
'passwd'
]
=
args
.
remote_pwd
config
[
args
.
ts
][
'machineList'
][
0
][
'passwd'
]
=
args
.
remote_pwd
if
args
.
remote_reuse
is
not
None
:
config
[
args
.
ts
][
'remoteConfig'
][
'reuse'
]
=
args
.
remote_reuse
.
lower
()
==
'true'
dump_yml_content
(
TRAINING_SERVICE_FILE
,
config
)
dump_yml_content
(
TRAINING_SERVICE_FILE
,
config
)
...
@@ -119,6 +121,7 @@ if __name__ == '__main__':
...
@@ -119,6 +121,7 @@ if __name__ == '__main__':
parser
.
add_argument
(
"--remote_pwd"
,
type
=
str
)
parser
.
add_argument
(
"--remote_pwd"
,
type
=
str
)
parser
.
add_argument
(
"--remote_host"
,
type
=
str
)
parser
.
add_argument
(
"--remote_host"
,
type
=
str
)
parser
.
add_argument
(
"--remote_port"
,
type
=
int
)
parser
.
add_argument
(
"--remote_port"
,
type
=
int
)
parser
.
add_argument
(
"--remote_reuse"
,
type
=
str
)
args
=
parser
.
parse_args
()
args
=
parser
.
parse_args
()
update_training_service_config
(
args
)
update_training_service_config
(
args
)
test/pipelines/pipelines-it-remote-linux-to-linux.yml
View file @
3b90b9d9
...
@@ -62,7 +62,7 @@ jobs:
...
@@ -62,7 +62,7 @@ jobs:
-
script
:
|
-
script
:
|
set -e
set -e
cd test
cd test
python3 nni_test/nnitest/generate_ts_config.py --ts remote --remote_user $(docker_user) --remote_host $(remote_host) \
python3 nni_test/nnitest/generate_ts_config.py --ts remote
--remote_reuse $(remote_reuse)
--remote_user $(docker_user) --remote_host $(remote_host) \
--remote_port $(cat port) --remote_pwd $(docker_pwd) --nni_manager_ip $(nni_manager_ip)
--remote_port $(cat port) --remote_pwd $(docker_pwd) --nni_manager_ip $(nni_manager_ip)
cat config/training_service.yml
cat config/training_service.yml
PATH=$HOME/.local/bin:$PATH python3 nni_test/nnitest/run_tests.py --config config/integration_tests.yml --ts remote
PATH=$HOME/.local/bin:$PATH python3 nni_test/nnitest/run_tests.py --config config/integration_tests.yml --ts remote
...
...
test/pipelines/pipelines-it-remote-windows-to-linux.yml
View file @
3b90b9d9
...
@@ -48,7 +48,7 @@ jobs:
...
@@ -48,7 +48,7 @@ jobs:
displayName
:
'
Get
docker
port'
displayName
:
'
Get
docker
port'
-
powershell
:
|
-
powershell
:
|
cd test
cd test
python nni_test/nnitest/generate_ts_config.py --ts remote --remote_user $(docker_user) --remote_host $(remote_host) --remote_port $(Get-Content port) --remote_pwd $(docker_pwd) --nni_manager_ip $(nni_manager_ip)
python nni_test/nnitest/generate_ts_config.py --ts remote
--remote_reuse $(remote_reuse)
--remote_user $(docker_user) --remote_host $(remote_host) --remote_port $(Get-Content port) --remote_pwd $(docker_pwd) --nni_manager_ip $(nni_manager_ip)
Get-Content config/training_service.yml
Get-Content config/training_service.yml
python nni_test/nnitest/run_tests.py --config config/integration_tests.yml --ts remote --exclude cifar10
python nni_test/nnitest/run_tests.py --config config/integration_tests.yml --ts remote --exclude cifar10
displayName
:
'
integration
test'
displayName
:
'
integration
test'
...
...
ts/nni_manager/training_service/remote_machine/extends/linuxCommands.ts
View file @
3b90b9d9
...
@@ -136,6 +136,10 @@ class LinuxCommands extends OsCommands {
...
@@ -136,6 +136,10 @@ class LinuxCommands extends OsCommands {
return
`
${
preCommand
}
&&
${
command
}
`
;
return
`
${
preCommand
}
&&
${
command
}
`
;
}
}
}
}
public
fileExistCommand
(
filePath
:
string
):
string
{
return
`test -e
${
filePath
}
&& echo True || echo False`
;
}
}
}
export
{
LinuxCommands
};
export
{
LinuxCommands
};
ts/nni_manager/training_service/remote_machine/extends/windowsCommands.ts
View file @
3b90b9d9
...
@@ -130,6 +130,10 @@ class WindowsCommands extends OsCommands {
...
@@ -130,6 +130,10 @@ class WindowsCommands extends OsCommands {
return
`
${
preCommand
}
&& set prePath=%path% &&
${
command
}
`
;
return
`
${
preCommand
}
&& set prePath=%path% &&
${
command
}
`
;
}
}
}
}
public
fileExistCommand
(
filePath
:
string
):
string
{
return
`powershell Test-Path
${
filePath
}
-PathType Leaf`
;
}
}
}
export
{
WindowsCommands
};
export
{
WindowsCommands
};
ts/nni_manager/training_service/remote_machine/osCommands.ts
View file @
3b90b9d9
...
@@ -29,6 +29,7 @@ abstract class OsCommands {
...
@@ -29,6 +29,7 @@ abstract class OsCommands {
public
abstract
extractFile
(
tarFileName
:
string
,
targetFolder
:
string
):
string
;
public
abstract
extractFile
(
tarFileName
:
string
,
targetFolder
:
string
):
string
;
public
abstract
executeScript
(
script
:
string
,
isFile
:
boolean
):
string
;
public
abstract
executeScript
(
script
:
string
,
isFile
:
boolean
):
string
;
public
abstract
addPreCommand
(
preCommand
:
string
|
undefined
,
command
:
string
|
undefined
):
string
|
undefined
;
public
abstract
addPreCommand
(
preCommand
:
string
|
undefined
,
command
:
string
|
undefined
):
string
|
undefined
;
public
abstract
fileExistCommand
(
filePath
:
string
):
string
|
undefined
;
public
joinPath
(...
paths
:
string
[]):
string
{
public
joinPath
(...
paths
:
string
[]):
string
{
let
dir
:
string
=
paths
.
filter
((
path
:
any
)
=>
path
!==
''
).
join
(
this
.
pathSpliter
);
let
dir
:
string
=
paths
.
filter
((
path
:
any
)
=>
path
!==
''
).
join
(
this
.
pathSpliter
);
...
...
ts/nni_manager/training_service/remote_machine/shellExecutor.ts
View file @
3b90b9d9
...
@@ -238,6 +238,12 @@ class ShellExecutor {
...
@@ -238,6 +238,12 @@ class ShellExecutor {
return
commandResult
.
exitCode
==
0
;
return
commandResult
.
exitCode
==
0
;
}
}
public
async
fileExist
(
filePath
:
string
):
Promise
<
boolean
>
{
const
commandText
=
this
.
osCommands
&&
this
.
osCommands
.
fileExistCommand
(
filePath
);
const
commandResult
=
await
this
.
execute
(
commandText
);
return
commandResult
.
stdout
!==
undefined
&&
commandResult
.
stdout
.
trim
()
===
'
True
'
;
}
public
async
extractFile
(
tarFileName
:
string
,
targetFolder
:
string
):
Promise
<
boolean
>
{
public
async
extractFile
(
tarFileName
:
string
,
targetFolder
:
string
):
Promise
<
boolean
>
{
const
commandText
=
this
.
osCommands
&&
this
.
osCommands
.
extractFile
(
tarFileName
,
targetFolder
);
const
commandText
=
this
.
osCommands
&&
this
.
osCommands
.
extractFile
(
tarFileName
,
targetFolder
);
const
commandResult
=
await
this
.
execute
(
commandText
);
const
commandResult
=
await
this
.
execute
(
commandText
);
...
...
ts/nni_manager/training_service/reusable/environments/remoteEnvironmentService.ts
View file @
3b90b9d9
...
@@ -137,40 +137,43 @@ export class RemoteEnvironmentService extends EnvironmentService {
...
@@ -137,40 +137,43 @@ export class RemoteEnvironmentService extends EnvironmentService {
private
async
refreshEnvironment
(
environment
:
EnvironmentInformation
):
Promise
<
void
>
{
private
async
refreshEnvironment
(
environment
:
EnvironmentInformation
):
Promise
<
void
>
{
const
executor
=
await
this
.
getExecutor
(
environment
.
id
);
const
executor
=
await
this
.
getExecutor
(
environment
.
id
);
const
jobpidPath
:
string
=
`
${
environment
.
runnerWorkingFolder
}
/pid`
;
const
jobpidPath
:
string
=
`
${
environment
.
runnerWorkingFolder
}
/pid`
;
const
runnerReturnCodeFilePath
:
string
=
`
${
environment
.
runnerWorkingFolder
}
/code`
;
const
runnerReturnCodeFilePath
:
string
=
`
${
environment
.
runnerWorkingFolder
}
/code`
;
if
(
fs
.
existsSync
(
jobpidPath
))
{
/* eslint-disable require-atomic-updates */
/* eslint-disable require-atomic-updates */
try
{
try
{
// check if pid file exist
const
isAlive
=
await
executor
.
isProcessAlive
(
jobpidPath
);
const
pidExist
=
await
executor
.
fileExist
(
jobpidPath
);
// if the process of jobpid is not alive any more
if
(
!
pidExist
)
{
if
(
!
isAlive
)
{
return
;
const
remoteEnvironment
:
RemoteMachineEnvironmentInformation
=
environment
as
RemoteMachineEnvironmentInformation
;
}
if
(
remoteEnvironment
.
rmMachineMeta
===
undefined
)
{
const
isAlive
=
await
executor
.
isProcessAlive
(
jobpidPath
);
throw
new
Error
(
`
${
remoteEnvironment
.
id
}
machine meta not initialized!`
);
environment
.
status
=
'
RUNNING
'
;
}
// if the process of jobpid is not alive any more
this
.
log
.
info
(
`pid in
${
remoteEnvironment
.
rmMachineMeta
.
ip
}
:
${
jobpidPath
}
is not alive!`
);
if
(
!
isAlive
)
{
if
(
fs
.
existsSync
(
runnerReturnCodeFilePath
))
{
const
remoteEnvironment
:
RemoteMachineEnvironmentInformation
=
environment
as
RemoteMachineEnvironmentInformation
;
const
runnerReturnCode
:
string
=
await
executor
.
getRemoteFileContent
(
runnerReturnCodeFilePath
);
if
(
remoteEnvironment
.
rmMachineMeta
===
undefined
)
{
const
match
:
RegExpMatchArray
|
null
=
runnerReturnCode
.
trim
()
throw
new
Error
(
`
${
remoteEnvironment
.
id
}
machine meta not initialized!`
);
.
match
(
/^-
?(\d
+
)\s
+
(\d
+
)
$/
);
}
if
(
match
!==
null
)
{
this
.
log
.
info
(
`pid in
${
remoteEnvironment
.
rmMachineMeta
.
ip
}
:
${
jobpidPath
}
is not alive!`
);
const
{
1
:
code
}
=
match
;
if
(
fs
.
existsSync
(
runnerReturnCodeFilePath
))
{
// Update trial job's status based on result code
const
runnerReturnCode
:
string
=
await
executor
.
getRemoteFileContent
(
runnerReturnCodeFilePath
);
if
(
parseInt
(
code
,
10
)
===
0
)
{
const
match
:
RegExpMatchArray
|
null
=
runnerReturnCode
.
trim
()
environment
.
setStatus
(
'
SUCCEEDED
'
);
.
match
(
/^-
?(\d
+
)\s
+
(\d
+
)
$/
);
}
else
{
if
(
match
!==
null
)
{
environment
.
setStatus
(
'
FAILED
'
);
const
{
1
:
code
}
=
match
;
}
// Update trial job's status based on result code
this
.
releaseEnvironmentResource
(
environment
);
if
(
parseInt
(
code
,
10
)
===
0
)
{
}
environment
.
setStatus
(
'
SUCCEEDED
'
);
}
else
{
environment
.
setStatus
(
'
FAILED
'
);
}
}
this
.
releaseEnvironmentResource
(
environment
);
}
}
}
catch
(
error
)
{
this
.
releaseEnvironmentResource
(
environment
);
this
.
log
.
error
(
`Update job status exception, error is
${
error
.
message
}
`
);
}
}
}
}
}
catch
(
error
)
{
this
.
log
.
error
(
`Update job status exception, error is
${
error
.
message
}
`
);
}
}
}
public
async
refreshEnvironmentsStatus
(
environments
:
EnvironmentInformation
[]):
Promise
<
void
>
{
public
async
refreshEnvironmentsStatus
(
environments
:
EnvironmentInformation
[]):
Promise
<
void
>
{
...
@@ -245,6 +248,7 @@ export class RemoteEnvironmentService extends EnvironmentService {
...
@@ -245,6 +248,7 @@ export class RemoteEnvironmentService extends EnvironmentService {
'
envs
'
,
environment
.
id
)
'
envs
'
,
environment
.
id
)
environment
.
command
=
`cd
${
environment
.
runnerWorkingFolder
}
&& \
environment
.
command
=
`cd
${
environment
.
runnerWorkingFolder
}
&& \
${
environment
.
command
}
--job_pid_file
${
environment
.
runnerWorkingFolder
}
/pid \
${
environment
.
command
}
--job_pid_file
${
environment
.
runnerWorkingFolder
}
/pid \
1>
${
environment
.
runnerWorkingFolder
}
/trialrunner_stdout 2>
${
environment
.
runnerWorkingFolder
}
/trialrunner_stderr \
&& echo $?
\`
date +%s%3N
\`
>
${
environment
.
runnerWorkingFolder
}
/code`
;
&& echo $?
\`
date +%s%3N
\`
>
${
environment
.
runnerWorkingFolder
}
/code`
;
return
Promise
.
resolve
(
true
);
return
Promise
.
resolve
(
true
);
}
}
...
@@ -266,7 +270,6 @@ ${environment.command} --job_pid_file ${environment.runnerWorkingFolder}/pid \
...
@@ -266,7 +270,6 @@ ${environment.command} --job_pid_file ${environment.runnerWorkingFolder}/pid \
// Execute command in remote machine
// Execute command in remote machine
executor
.
executeScript
(
executor
.
joinPath
(
environment
.
runnerWorkingFolder
,
executor
.
executeScript
(
executor
.
joinPath
(
environment
.
runnerWorkingFolder
,
executor
.
getScriptName
(
"
run
"
)),
true
,
false
);
executor
.
getScriptName
(
"
run
"
)),
true
,
false
);
environment
.
status
=
'
RUNNING
'
;
if
(
environment
.
rmMachineMeta
===
undefined
)
{
if
(
environment
.
rmMachineMeta
===
undefined
)
{
throw
new
Error
(
`
${
environment
.
id
}
rmMachineMeta not initialized!`
);
throw
new
Error
(
`
${
environment
.
id
}
rmMachineMeta not initialized!`
);
}
}
...
...
ts/nni_manager/training_service/reusable/trialDispatcher.ts
View file @
3b90b9d9
...
@@ -663,19 +663,22 @@ class TrialDispatcher implements TrainingService {
...
@@ -663,19 +663,22 @@ class TrialDispatcher implements TrainingService {
trial
.
status
=
"
RUNNING
"
;
trial
.
status
=
"
RUNNING
"
;
await
this
.
commandChannel
.
sendCommand
(
trial
.
environment
,
NEW_TRIAL_JOB
,
trial
.
settings
);
await
this
.
commandChannel
.
sendCommand
(
trial
.
environment
,
NEW_TRIAL_JOB
,
trial
.
settings
);
}
}
/**
* release the trial assigned environment resources
* @param trial
*/
private
releaseEnvironment
(
trial
:
TrialDetail
):
void
{
private
releaseEnvironment
(
trial
:
TrialDetail
):
void
{
if
(
undefined
===
trial
.
environment
)
{
if
(
trial
.
environment
!==
undefined
)
{
throw
new
Error
(
`TrialDispatcher: environment is not assigned to trial
${
trial
.
id
}
, and cannot be released!`
);
if
(
trial
.
environment
.
runningTrialCount
<=
0
)
{
}
throw
new
Error
(
`TrialDispatcher: environment
${
trial
.
environment
.
id
}
has no counted running trial!`
);
if
(
trial
.
environment
.
runningTrialCount
<=
0
)
{
}
throw
new
Error
(
`TrialDispatcher: environment
${
trial
.
environment
.
id
}
has no counted running trial!`
);
trial
.
environment
.
runningTrialCount
--
;
trial
.
environment
=
undefined
;
}
}
if
(
true
===
this
.
enableGpuScheduler
)
{
if
(
true
===
this
.
enableGpuScheduler
)
{
this
.
gpuScheduler
.
removeGpuReservation
(
trial
);
this
.
gpuScheduler
.
removeGpuReservation
(
trial
);
}
}
trial
.
environment
.
runningTrialCount
--
;
trial
.
environment
=
undefined
;
}
}
private
async
handleMetricData
(
trialId
:
string
,
data
:
any
):
Promise
<
void
>
{
private
async
handleMetricData
(
trialId
:
string
,
data
:
any
):
Promise
<
void
>
{
...
...
ts/nni_manager/yarn.lock
View file @
3b90b9d9
...
@@ -1096,10 +1096,10 @@ cli-width@^2.0.0:
...
@@ -1096,10 +1096,10 @@ cli-width@^2.0.0:
version "2.2.0"
version "2.2.0"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
cliui@^7.0.
0
:
cliui@^7.0.
2
:
version "7.0.
1
"
version "7.0.
3
"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.
1
.tgz#
a4cb67aad45cd83d8d05128fc9f4d8fbb887e6b3
"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.
3
.tgz#
ef180f26c8d9bff3927ee52428bfec2090427981
"
integrity sha512-
rcvHOWyGyid6I1WjT/3NatKj2kDt9OdSHSXpyLXaMWFbKpGACNW8pRhhdPUq9MWUOdwn8Rz9AVETjF4105rZZQ
==
integrity sha512-
Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw
==
dependencies:
dependencies:
string-width "^4.2.0"
string-width "^4.2.0"
strip-ansi "^6.0.0"
strip-ansi "^6.0.0"
...
@@ -1336,7 +1336,7 @@ debug@^3.1.0:
...
@@ -1336,7 +1336,7 @@ debug@^3.1.0:
dependencies:
dependencies:
ms "^2.1.1"
ms "^2.1.1"
debuglog@^1.0.1:
debuglog@*,
debuglog@^1.0.1:
version "1.0.1"
version "1.0.1"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
...
@@ -1606,10 +1606,10 @@ es6-promisify@^5.0.0:
...
@@ -1606,10 +1606,10 @@ es6-promisify@^5.0.0:
dependencies:
dependencies:
es6-promise "^4.0.3"
es6-promise "^4.0.3"
escalade@^3.
0.2
:
escalade@^3.
1.1
:
version "3.1.
0
"
version "3.1.
1
"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.
0
.tgz#
e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e
"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.
1
.tgz#
d8cfdc7000965c5a0174b4a82eaa5c0552742e40
"
integrity sha512-
mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig
==
integrity sha512-
k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw
==
escape-html@~1.0.3:
escape-html@~1.0.3:
version "1.0.3"
version "1.0.3"
...
@@ -2392,7 +2392,7 @@ import-lazy@^2.1.0:
...
@@ -2392,7 +2392,7 @@ import-lazy@^2.1.0:
version "2.1.0"
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
imurmurhash@^0.1.4:
imurmurhash@*,
imurmurhash@^0.1.4:
version "0.1.4"
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
...
@@ -3074,6 +3074,11 @@ lockfile@^1.0.4:
...
@@ -3074,6 +3074,11 @@ lockfile@^1.0.4:
dependencies:
dependencies:
signal-exit "^3.0.2"
signal-exit "^3.0.2"
lodash._baseindexof@*:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=
lodash._baseuniq@~4.6.0:
lodash._baseuniq@~4.6.0:
version "4.6.0"
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
...
@@ -3081,10 +3086,32 @@ lodash._baseuniq@~4.6.0:
...
@@ -3081,10 +3086,32 @@ lodash._baseuniq@~4.6.0:
lodash._createset "~4.0.0"
lodash._createset "~4.0.0"
lodash._root "~3.0.0"
lodash._root "~3.0.0"
lodash._bindcallback@*:
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=
lodash._cacheindexof@*:
version "3.0.2"
resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=
lodash._createcache@*:
version "3.1.2"
resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=
dependencies:
lodash._getnative "^3.0.0"
lodash._createset@~4.0.0:
lodash._createset@~4.0.0:
version "4.0.3"
version "4.0.3"
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
lodash._getnative@*, lodash._getnative@^3.0.0:
version "3.9.1"
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=
lodash._root@~3.0.0:
lodash._root@~3.0.0:
version "3.0.1"
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
...
@@ -3133,6 +3160,11 @@ lodash.pick@^4.4.0:
...
@@ -3133,6 +3160,11 @@ lodash.pick@^4.4.0:
version "4.4.0"
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
lodash.restparam@*:
version "3.6.1"
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=
lodash.unescape@4.0.1:
lodash.unescape@4.0.1:
version "4.0.1"
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c"
resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c"
...
@@ -3723,8 +3755,9 @@ npm-run-path@^2.0.0:
...
@@ -3723,8 +3755,9 @@ npm-run-path@^2.0.0:
path-key "^2.0.0"
path-key "^2.0.0"
npm-user-validate@~1.0.0:
npm-user-validate@~1.0.0:
version "1.0.0"
version "1.0.1"
resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.0.tgz#8ceca0f5cea04d4e93519ef72d0557a75122e951"
resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.1.tgz#31428fc5475fe8416023f178c0ab47935ad8c561"
integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw==
npm@5.1.0, npm@>=6.14.8:
npm@5.1.0, npm@>=6.14.8:
version "6.14.8"
version "6.14.8"
...
@@ -5724,10 +5757,10 @@ y18n@^4.0.0:
...
@@ -5724,10 +5757,10 @@ y18n@^4.0.0:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
y18n@^5.0.
1
:
y18n@^5.0.
2
:
version "5.0.
1
"
version "5.0.
4
"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.
1
.tgz#
1ad2a7eddfa8bce7caa2e1f6b5da96c39d99d571
"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.
4
.tgz#
0ab2db89dd5873b5ec4682d8e703e833373ea897
"
integrity sha512-
/jJ831jEs4vGDbYPQp4yGKDYPSCCEQ45uZWJHE1AoYBzqdZi8+LDWas0z4HrmJXmKdpFsTiowSHXdxyFhpmdMg
==
integrity sha512-
deLOfD+RvFgrpAmSZgfGdWYE+OKyHcVHaRQ7NphG/63scpRvTHHeQMAxGGvaLVGJ+HYVcCXlzcTK0ZehFf+eHQ
==
yallist@^2.1.2:
yallist@^2.1.2:
version "2.1.2"
version "2.1.2"
...
@@ -5746,10 +5779,10 @@ yallist@^4.0.0:
...
@@ -5746,10 +5779,10 @@ yallist@^4.0.0:
version "4.0.0"
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
yargs-parser@13.1.2, yargs-parser@>=20.2.0, yargs-parser@^20.
0.0
:
yargs-parser@13.1.2, yargs-parser@>=20.2.0, yargs-parser@^20.
2.2
:
version "20.2.
2
"
version "20.2.
3
"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.
2
.tgz#
84562c6b1c41ccec2f13d346c7dd83f8d1a0dc70
"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.
3
.tgz#
92419ba867b858c868acf8bae9bf74af0dd0ce26
"
integrity sha512-
XmrpXaTl6noDsf1dKpBuUNCOHqjs0g3jRMXf/ztRxdOmb+er8kE5z5b55Lz3p5u2T8KJ59ENBnASS8/iapVJ5g
==
integrity sha512-
emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww
==
yargs-unparser@1.6.1:
yargs-unparser@1.6.1:
version "1.6.1"
version "1.6.1"
...
@@ -5763,17 +5796,17 @@ yargs-unparser@1.6.1:
...
@@ -5763,17 +5796,17 @@ yargs-unparser@1.6.1:
yargs "^14.2.3"
yargs "^14.2.3"
yargs@13.3.2, yargs@>=16.0.3, yargs@^11.0.0, yargs@^14.2.3, yargs@^15.0.2, yargs@^8.0.2:
yargs@13.3.2, yargs@>=16.0.3, yargs@^11.0.0, yargs@^14.2.3, yargs@^15.0.2, yargs@^8.0.2:
version "16.
0.3
"
version "16.
1.0
"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.
0.3
.tgz#
7a919b9e43c90f80d4a142a89795e85399a7e54c
"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.
1.0
.tgz#
fc333fe4791660eace5a894b39d42f851cd48f2a
"
integrity sha512-
6+nLw8xa9uK1BOEOykaiYAJVh6/CjxWXK/q9b5FpRgNslt8s22F2xMBqVIKgCRjNgGvGPBy8Vog7WN7yh4amtA
==
integrity sha512-
upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g
==
dependencies:
dependencies:
cliui "^7.0.
0
"
cliui "^7.0.
2
"
escalade "^3.
0.2
"
escalade "^3.
1.1
"
get-caller-file "^2.0.5"
get-caller-file "^2.0.5"
require-directory "^2.1.1"
require-directory "^2.1.1"
string-width "^4.2.0"
string-width "^4.2.0"
y18n "^5.0.
1
"
y18n "^5.0.
2
"
yargs-parser "^20.
0.0
"
yargs-parser "^20.
2.2
"
yn@^2.0.0:
yn@^2.0.0:
version "2.0.0"
version "2.0.0"
...
...
ts/webui/src/App.scss
View file @
3b90b9d9
...
@@ -53,7 +53,7 @@
...
@@ -53,7 +53,7 @@
.ms-Callout-main
{
.ms-Callout-main
{
p
{
p
{
font-weight
:
500
;
font-weight
:
500
;
color
:
#
333
;
color
:
#
fff
;
}
}
}
}
...
...
ts/webui/src/App.tsx
View file @
3b90b9d9
...
@@ -12,6 +12,7 @@ interface AppState {
...
@@ -12,6 +12,7 @@ interface AppState {
columnList
:
string
[];
columnList
:
string
[];
experimentUpdateBroadcast
:
number
;
experimentUpdateBroadcast
:
number
;
trialsUpdateBroadcast
:
number
;
trialsUpdateBroadcast
:
number
;
maxDurationUnit
:
string
;
metricGraphMode
:
'
max
'
|
'
min
'
;
// tuner's optimize_mode filed
metricGraphMode
:
'
max
'
|
'
min
'
;
// tuner's optimize_mode filed
isillegalFinal
:
boolean
;
isillegalFinal
:
boolean
;
expWarningMessage
:
string
;
expWarningMessage
:
string
;
...
@@ -26,11 +27,14 @@ export const AppContext = React.createContext({
...
@@ -26,11 +27,14 @@ export const AppContext = React.createContext({
trialsUpdateBroadcast
:
0
,
trialsUpdateBroadcast
:
0
,
metricGraphMode
:
'
max
'
,
metricGraphMode
:
'
max
'
,
bestTrialEntries
:
'
10
'
,
bestTrialEntries
:
'
10
'
,
maxDurationUnit
:
'
m
'
,
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
changeColumn
:
(
val
:
string
[])
=>
{},
changeColumn
:
(
val
:
string
[])
=>
{},
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
changeMetricGraphMode
:
(
val
:
'
max
'
|
'
min
'
)
=>
{},
changeMetricGraphMode
:
(
val
:
'
max
'
|
'
min
'
)
=>
{},
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
changeMaxDurationUnit
:
(
val
:
string
)
=>
{},
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
changeEntries
:
(
val
:
string
)
=>
{},
changeEntries
:
(
val
:
string
)
=>
{},
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
updateOverviewPage
:
()
=>
{}
updateOverviewPage
:
()
=>
{}
...
@@ -47,6 +51,7 @@ class App extends React.Component<{}, AppState> {
...
@@ -47,6 +51,7 @@ class App extends React.Component<{}, AppState> {
experimentUpdateBroadcast
:
0
,
experimentUpdateBroadcast
:
0
,
trialsUpdateBroadcast
:
0
,
trialsUpdateBroadcast
:
0
,
metricGraphMode
:
'
max
'
,
metricGraphMode
:
'
max
'
,
maxDurationUnit
:
'
m
'
,
isillegalFinal
:
false
,
isillegalFinal
:
false
,
expWarningMessage
:
''
,
expWarningMessage
:
''
,
bestTrialEntries
:
'
10
'
,
bestTrialEntries
:
'
10
'
,
...
@@ -91,6 +96,11 @@ class App extends React.Component<{}, AppState> {
...
@@ -91,6 +96,11 @@ class App extends React.Component<{}, AppState> {
this
.
setState
({
bestTrialEntries
:
entries
});
this
.
setState
({
bestTrialEntries
:
entries
});
};
};
// overview max duration unit
changeMaxDurationUnit
=
(
unit
:
string
):
void
=>
{
this
.
setState
({
maxDurationUnit
:
unit
});
};
updateOverviewPage
=
():
void
=>
{
updateOverviewPage
=
():
void
=>
{
this
.
setState
(
state
=>
({
this
.
setState
(
state
=>
({
experimentUpdateBroadcast
:
state
.
experimentUpdateBroadcast
+
1
experimentUpdateBroadcast
:
state
.
experimentUpdateBroadcast
+
1
...
@@ -114,7 +124,8 @@ class App extends React.Component<{}, AppState> {
...
@@ -114,7 +124,8 @@ class App extends React.Component<{}, AppState> {
metricGraphMode
,
metricGraphMode
,
isillegalFinal
,
isillegalFinal
,
expWarningMessage
,
expWarningMessage
,
bestTrialEntries
bestTrialEntries
,
maxDurationUnit
}
=
this
.
state
;
}
=
this
.
state
;
if
(
experimentUpdateBroadcast
===
0
||
trialsUpdateBroadcast
===
0
)
{
if
(
experimentUpdateBroadcast
===
0
||
trialsUpdateBroadcast
===
0
)
{
return
null
;
// TODO: render a loading page
return
null
;
// TODO: render a loading page
...
@@ -137,7 +148,24 @@ class App extends React.Component<{}, AppState> {
...
@@ -137,7 +148,24 @@ class App extends React.Component<{}, AppState> {
<
Stack
className
=
'contentBox'
>
<
Stack
className
=
'contentBox'
>
<
Stack
className
=
'content'
>
<
Stack
className
=
'content'
>
{
/* search space & config */
}
{
/* search space & config */
}
<
TrialConfigButton
/>
<
AppContext
.
Provider
value
=
{
{
interval
,
columnList
,
changeColumn
:
this
.
changeColumn
,
experimentUpdateBroadcast
,
trialsUpdateBroadcast
,
metricGraphMode
,
maxDurationUnit
,
changeMaxDurationUnit
:
this
.
changeMaxDurationUnit
,
changeMetricGraphMode
:
this
.
changeMetricGraphMode
,
bestTrialEntries
,
changeEntries
:
this
.
changeEntries
,
updateOverviewPage
:
this
.
updateOverviewPage
}
}
>
<
TrialConfigButton
/>
</
AppContext
.
Provider
>
{
/* if api has error field, show error message */
}
{
/* if api has error field, show error message */
}
{
errorList
.
map
(
{
errorList
.
map
(
(
item
,
key
)
=>
(
item
,
key
)
=>
...
@@ -160,6 +188,8 @@ class App extends React.Component<{}, AppState> {
...
@@ -160,6 +188,8 @@ class App extends React.Component<{}, AppState> {
experimentUpdateBroadcast
,
experimentUpdateBroadcast
,
trialsUpdateBroadcast
,
trialsUpdateBroadcast
,
metricGraphMode
,
metricGraphMode
,
maxDurationUnit
,
changeMaxDurationUnit
:
this
.
changeMaxDurationUnit
,
changeMetricGraphMode
:
this
.
changeMetricGraphMode
,
changeMetricGraphMode
:
this
.
changeMetricGraphMode
,
bestTrialEntries
,
bestTrialEntries
,
changeEntries
:
this
.
changeEntries
,
changeEntries
:
this
.
changeEntries
,
...
...
ts/webui/src/components/Overview.tsx
View file @
3b90b9d9
...
@@ -10,7 +10,8 @@ import { ReBasicInfo } from './overview/experiment/BasicInfo';
...
@@ -10,7 +10,8 @@ import { ReBasicInfo } from './overview/experiment/BasicInfo';
import
{
ExpDuration
}
from
'
./overview/count/ExpDuration
'
;
import
{
ExpDuration
}
from
'
./overview/count/ExpDuration
'
;
import
{
ExpDurationContext
}
from
'
./overview/count/ExpDurationContext
'
;
import
{
ExpDurationContext
}
from
'
./overview/count/ExpDurationContext
'
;
import
{
TrialCount
}
from
'
./overview/count/TrialCount
'
;
import
{
TrialCount
}
from
'
./overview/count/TrialCount
'
;
import
{
Command
}
from
'
./overview/experiment/Command
'
;
import
{
Command1
}
from
'
./overview/command/Command1
'
;
import
{
Command2
}
from
'
./overview/command/Command2
'
;
import
{
TitleContext
}
from
'
./overview/TitleContext
'
;
import
{
TitleContext
}
from
'
./overview/TitleContext
'
;
import
{
itemStyle1
,
itemStyleSucceed
,
itemStyle2
,
entriesOption
}
from
'
./overview/overviewConst
'
;
import
{
itemStyle1
,
itemStyleSucceed
,
itemStyle2
,
entriesOption
}
from
'
./overview/overviewConst
'
;
import
'
../static/style/overview/overview.scss
'
;
import
'
../static/style/overview/overview.scss
'
;
...
@@ -66,7 +67,13 @@ class Overview extends React.Component<{}, OverviewState> {
...
@@ -66,7 +67,13 @@ class Overview extends React.Component<{}, OverviewState> {
return
(
return
(
<
AppContext
.
Consumer
>
<
AppContext
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
{
{
(
value
):
React
.
ReactNode
=>
{
const
{
metricGraphMode
,
bestTrialEntries
,
updateOverviewPage
}
=
value
;
const
{
metricGraphMode
,
bestTrialEntries
,
maxDurationUnit
,
updateOverviewPage
,
changeMaxDurationUnit
}
=
value
;
const
maxActive
=
metricGraphMode
===
'
max
'
?
'
active
'
:
''
;
const
maxActive
=
metricGraphMode
===
'
max
'
?
'
active
'
:
''
;
const
minActive
=
metricGraphMode
===
'
min
'
?
'
active
'
:
''
;
const
minActive
=
metricGraphMode
===
'
min
'
?
'
active
'
:
''
;
return
(
return
(
...
@@ -88,18 +95,29 @@ class Overview extends React.Component<{}, OverviewState> {
...
@@ -88,18 +95,29 @@ class Overview extends React.Component<{}, OverviewState> {
<
Title
/>
<
Title
/>
</
TitleContext
.
Provider
>
</
TitleContext
.
Provider
>
<
ExpDurationContext
.
Provider
<
ExpDurationContext
.
Provider
value
=
{
{
maxExecDuration
,
execDuration
,
updateOverviewPage
}
}
value
=
{
{
maxExecDuration
,
execDuration
,
updateOverviewPage
,
maxDurationUnit
,
changeMaxDurationUnit
}
}
>
>
<
ExpDuration
/>
<
ExpDuration
/>
</
ExpDurationContext
.
Provider
>
</
ExpDurationContext
.
Provider
>
</
div
>
</
div
>
<
div
className
=
'empty'
/>
<
div
className
=
'trialCount'
>
<
div
className
=
'trialCount'
>
<
TitleContext
.
Provider
value
=
{
{
text
:
'
Trial numbers
'
,
icon
:
'
NumberSymbol
'
}
}
>
<
TitleContext
.
Provider
value
=
{
{
text
:
'
Trial numbers
'
,
icon
:
'
NumberSymbol
'
}
}
>
<
Title
/>
<
Title
/>
</
TitleContext
.
Provider
>
</
TitleContext
.
Provider
>
<
ExpDurationContext
.
Provider
<
ExpDurationContext
.
Provider
value
=
{
{
maxExecDuration
,
execDuration
,
updateOverviewPage
}
}
value
=
{
{
maxExecDuration
,
execDuration
,
updateOverviewPage
,
maxDurationUnit
,
changeMaxDurationUnit
}
}
>
>
<
TrialCount
/>
<
TrialCount
/>
</
ExpDurationContext
.
Provider
>
</
ExpDurationContext
.
Provider
>
...
@@ -114,7 +132,6 @@ class Overview extends React.Component<{}, OverviewState> {
...
@@ -114,7 +132,6 @@ class Overview extends React.Component<{}, OverviewState> {
</
TitleContext
.
Provider
>
</
TitleContext
.
Provider
>
</
div
>
</
div
>
<
div
className
=
'topTrialTitle'
>
<
div
className
=
'topTrialTitle'
>
{
/* <Stack horizontal horizontalAlign='space-between'> */
}
<
Stack
horizontal
horizontalAlign
=
'end'
>
<
Stack
horizontal
horizontalAlign
=
'end'
>
<
DefaultButton
<
DefaultButton
onClick
=
{
this
.
clickMaxTop
}
onClick
=
{
this
.
clickMaxTop
}
...
@@ -152,8 +169,11 @@ class Overview extends React.Component<{}, OverviewState> {
...
@@ -152,8 +169,11 @@ class Overview extends React.Component<{}, OverviewState> {
</
Stack
>
</
Stack
>
<
SuccessTable
trialIds
=
{
bestTrials
.
map
(
trial
=>
trial
.
info
.
id
)
}
/>
<
SuccessTable
trialIds
=
{
bestTrials
.
map
(
trial
=>
trial
.
info
.
id
)
}
/>
</
div
>
</
div
>
<
div
className
=
'overviewCommand'
>
<
div
className
=
'overviewCommand1'
>
<
Command
/>
<
Command1
/>
</
div
>
<
div
className
=
'overviewCommand2'
>
<
Command2
/>
</
div
>
</
div
>
<
div
className
=
'overviewChart'
>
<
div
className
=
'overviewChart'
>
<
Stack
horizontal
>
<
Stack
horizontal
>
...
...
ts/webui/src/components/TrialsDetail.tsx
View file @
3b90b9d9
...
@@ -82,7 +82,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
...
@@ -82,7 +82,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
</
Pivot
>
</
Pivot
>
</
div
>
</
div
>
{
/* trial table list */
}
{
/* trial table list */
}
<
div
style
=
{
{
backgroundColor
:
'
#fff
'
}
}
>
<
div
style
=
{
{
backgroundColor
:
'
#fff
'
,
marginTop
:
10
}
}
>
<
TableList
<
TableList
tableSource
=
{
source
}
tableSource
=
{
source
}
trialsUpdateBroadcast
=
{
this
.
context
.
trialsUpdateBroadcast
}
trialsUpdateBroadcast
=
{
this
.
context
.
trialsUpdateBroadcast
}
...
...
ts/webui/src/components/modals/CustomizedTrial.tsx
View file @
3b90b9d9
...
@@ -60,7 +60,10 @@ class Customize extends React.Component<CustomizeProps, CustomizeState> {
...
@@ -60,7 +60,10 @@ class Customize extends React.Component<CustomizeProps, CustomizeState> {
Object
.
keys
(
customized
).
map
(
item
=>
{
Object
.
keys
(
customized
).
map
(
item
=>
{
if
(
item
!==
'
tag
'
)
{
if
(
item
!==
'
tag
'
)
{
// unified data type
// unified data type
if
(
typeof
copyTrialParameter
[
item
]
===
'
number
'
&&
typeof
customized
[
item
]
===
'
string
'
)
{
if
(
(
typeof
copyTrialParameter
[
item
]
===
'
number
'
&&
typeof
customized
[
item
]
===
'
string
'
)
||
(
typeof
copyTrialParameter
[
item
]
===
'
boolean
'
&&
typeof
customized
[
item
]
===
'
string
'
)
)
{
customized
[
item
]
=
JSON
.
parse
(
customized
[
item
]);
customized
[
item
]
=
JSON
.
parse
(
customized
[
item
]);
}
}
if
(
searchSpace
[
item
]
===
undefined
)
{
if
(
searchSpace
[
item
]
===
undefined
)
{
...
...
ts/webui/src/components/modals/Killjob.tsx
View file @
3b90b9d9
...
@@ -112,11 +112,15 @@ class KillJob extends React.Component<KillJobProps, KillJobState> {
...
@@ -112,11 +112,15 @@ class KillJob extends React.Component<KillJobProps, KillJobState> {
setInitialFocus
=
{
true
}
setInitialFocus
=
{
true
}
>
>
<
div
className
=
{
styles
.
header
}
>
<
div
className
=
{
styles
.
header
}
>
<
p
className
=
{
styles
.
title
}
>
Kill trial
</
p
>
<
p
className
=
{
styles
.
title
}
style
=
{
{
color
:
'
#333
'
}
}
>
Kill trial
</
p
>
</
div
>
</
div
>
<
div
className
=
{
styles
.
inner
}
>
<
div
className
=
{
styles
.
inner
}
>
<
div
>
<
div
>
<
p
className
=
{
styles
.
subtext
}
>
{
prompString
}
</
p
>
<
p
className
=
{
styles
.
subtext
}
style
=
{
{
color
:
'
#333
'
}
}
>
{
prompString
}
</
p
>
</
div
>
</
div
>
</
div
>
</
div
>
<
FocusZone
>
<
FocusZone
>
...
...
ts/webui/src/components/overview/
experiment
/Command.tsx
→
ts/webui/src/components/overview/
command
/Command
1
.tsx
View file @
3b90b9d9
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
TooltipHost
,
Stack
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
'
../../../static/style/overview/command.scss
'
;
import
'
../../../static/style/overview/command.scss
'
;
export
const
Command
=
():
any
=>
{
export
const
Command1
=
():
any
=>
{
const
clusterMetaData
=
EXPERIMENT
.
profile
.
params
.
clusterMetaData
;
const
tuner
=
EXPERIMENT
.
profile
.
params
.
tuner
;
const
tuner
=
EXPERIMENT
.
profile
.
params
.
tuner
;
const
advisor
=
EXPERIMENT
.
profile
.
params
.
advisor
;
const
advisor
=
EXPERIMENT
.
profile
.
params
.
advisor
;
const
assessor
=
EXPERIMENT
.
profile
.
params
.
assessor
;
const
assessor
=
EXPERIMENT
.
profile
.
params
.
assessor
;
let
title
=
''
;
let
title
=
''
;
let
builtinName
=
''
;
let
builtinName
=
''
;
let
trialCommand
=
'
unknown
'
;
if
(
tuner
!==
undefined
)
{
if
(
tuner
!==
undefined
)
{
title
=
title
.
concat
(
'
Tuner
'
);
title
=
title
.
concat
(
'
Tuner
'
);
if
(
tuner
.
builtinTunerName
!==
undefined
)
{
if
(
tuner
.
builtinTunerName
!==
undefined
)
{
...
@@ -29,35 +26,15 @@ export const Command = (): any => {
...
@@ -29,35 +26,15 @@ export const Command = (): any => {
builtinName
=
builtinName
.
concat
(
assessor
.
builtinAssessorName
);
builtinName
=
builtinName
.
concat
(
assessor
.
builtinAssessorName
);
}
}
}
}
if
(
clusterMetaData
!==
undefined
)
{
for
(
const
item
of
clusterMetaData
)
{
if
(
item
.
key
===
'
command
'
)
{
trialCommand
=
item
.
value
;
}
}
}
return
(
return
(
<
div
className
=
'
command
basic'
>
<
div
className
=
'basic'
>
<
div
className
=
'command1'
>
<
div
>
<
p
>
Training platform
</
p
>
<
p
className
=
'command'
>
Training platform
</
p
>
<
div
className
=
'nowrap'
>
{
EXPERIMENT
.
profile
.
params
.
trainingServicePlatform
}
</
div
>
<
div
className
=
'nowrap'
>
{
EXPERIMENT
.
profile
.
params
.
trainingServicePlatform
}
</
div
>
<
p
className
=
'lineMargin'
>
{
title
}
</
p
>
<
p
className
=
'lineMargin'
>
{
title
}
</
p
>
<
div
className
=
'nowrap'
>
{
builtinName
}
</
div
>
<
div
className
=
'nowrap'
>
{
builtinName
}
</
div
>
</
div
>
</
div
>
<
Stack
className
=
'command2'
>
<
p
>
Log directory
</
p
>
<
div
className
=
'nowrap'
>
<
TooltipHost
content
=
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
className
=
'nowrap'
>
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
</
TooltipHost
>
</
div
>
<
p
className
=
'lineMargin'
>
Trial command
</
p
>
<
div
className
=
'nowrap'
>
<
TooltipHost
content
=
{
trialCommand
||
'
unknown
'
}
className
=
'nowrap'
>
{
trialCommand
||
'
unknown
'
}
</
TooltipHost
>
</
div
>
</
Stack
>
</
div
>
</
div
>
);
);
};
};
ts/webui/src/components/overview/command/Command2.tsx
0 → 100644
View file @
3b90b9d9
import
React
from
'
react
'
;
import
{
TooltipHost
,
DirectionalHint
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
{
TOOLTIP_BACKGROUND_COLOR
}
from
'
../../../static/const
'
;
import
'
../../../static/style/overview/command.scss
'
;
export
const
Command2
=
():
any
=>
{
const
clusterMetaData
=
EXPERIMENT
.
profile
.
params
.
clusterMetaData
;
let
trialCommand
=
'
unknown
'
;
if
(
clusterMetaData
!==
undefined
)
{
for
(
const
item
of
clusterMetaData
)
{
if
(
item
.
key
===
'
command
'
)
{
trialCommand
=
item
.
value
as
string
;
}
if
(
item
.
key
===
'
trial_config
'
)
{
if
(
typeof
item
.
value
===
'
object
'
&&
'
command
'
in
item
.
value
)
{
trialCommand
=
item
.
value
.
command
as
string
;
}
}
}
}
return
(
<
div
className
=
'basic'
>
<
p
className
=
'command'
>
Log directory
</
p
>
<
div
className
=
'nowrap'
>
<
TooltipHost
content
=
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
className
=
'nowrap'
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
tooltipProps
=
{
{
calloutProps
:
{
styles
:
{
beak
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
beakCurtain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
calloutMain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
}
}
}
}
}
>
{
EXPERIMENT
.
profile
.
logDir
||
'
unknown
'
}
</
TooltipHost
>
</
div
>
<
p
className
=
'lineMargin'
>
Trial command
</
p
>
<
div
className
=
'nowrap'
>
<
TooltipHost
content
=
{
trialCommand
||
'
unknown
'
}
className
=
'nowrap'
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
tooltipProps
=
{
{
calloutProps
:
{
styles
:
{
beak
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
beakCurtain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
calloutMain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
}
}
}
}
}
>
{
trialCommand
||
'
unknown
'
}
</
TooltipHost
>
</
div
>
</
div
>
);
};
ts/webui/src/components/overview/count/EditExperimentParam.tsx
View file @
3b90b9d9
import
React
,
{
useState
,
useCallback
,
useContext
}
from
'
react
'
;
import
React
,
{
useState
,
useCallback
,
useContext
}
from
'
react
'
;
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
;
import
{
Dropdown
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
{
AppContext
}
from
'
../../../App
'
;
import
{
EditExpeParamContext
}
from
'
./context
'
;
import
{
EditExpeParamContext
}
from
'
./context
'
;
import
{
MANAGER_IP
}
from
'
../../../static/c
onst
'
;
import
{
durationUnit
}
from
'
../overviewC
onst
'
;
import
{
convertTimeToSecond
}
from
'
../../../static/
function
'
;
import
{
MANAGER_IP
,
MAX_TRIAL_NUMBERS
}
from
'
../../../static/
const
'
;
import
{
Edit
,
CheckMark
,
Cancel
}
from
'
../../buttons/Icon
'
;
import
{
Edit
,
CheckMark
,
Cancel
}
from
'
../../buttons/Icon
'
;
import
MessageInfo
from
'
../../modals/MessageInfo
'
;
import
MessageInfo
from
'
../../modals/MessageInfo
'
;
import
'
../../../static/style/overview/count.scss
'
;
import
'
../../../static/style/overview/count.scss
'
;
...
@@ -28,12 +30,14 @@ export const EditExperimentParam = (): any => {
...
@@ -28,12 +30,14 @@ export const EditExperimentParam = (): any => {
const
{
title
,
field
,
editType
,
maxExecDuration
,
maxTrialNum
,
trialConcurrency
,
updateOverviewPage
}
=
useContext
(
const
{
title
,
field
,
editType
,
maxExecDuration
,
maxTrialNum
,
trialConcurrency
,
updateOverviewPage
}
=
useContext
(
EditExpeParamContext
EditExpeParamContext
);
);
const
{
maxDurationUnit
,
changeMaxDurationUnit
}
=
useContext
(
AppContext
);
const
[
unit
,
setUnit
]
=
useState
(
maxDurationUnit
);
let
defaultVal
=
''
;
let
defaultVal
=
''
;
let
editVal
=
''
;
let
editVal
=
''
;
if
(
title
===
'
Max duration
'
)
{
if
(
title
===
'
Max duration
'
)
{
defaultVal
=
maxExecDuration
;
defaultVal
=
maxExecDuration
;
editVal
=
maxExecDuration
;
editVal
=
maxExecDuration
;
}
else
if
(
title
===
'
Max trial numbers
'
)
{
}
else
if
(
title
===
MAX_TRIAL_NUMBERS
)
{
defaultVal
=
maxTrialNum
.
toString
();
defaultVal
=
maxTrialNum
.
toString
();
editVal
=
maxTrialNum
.
toString
();
editVal
=
maxTrialNum
.
toString
();
}
else
{
}
else
{
...
@@ -46,32 +50,64 @@ export const EditExperimentParam = (): any => {
...
@@ -46,32 +50,64 @@ export const EditExperimentParam = (): any => {
setEditValInput
(
event
.
target
.
value
);
setEditValInput
(
event
.
target
.
value
);
}
}
function
cancelEdit
():
void
{
function
showMessageInfo
(
info
:
string
,
typeInfo
:
string
):
any
{
setEditValInput
(
defaultVal
);
setInfo
(
info
);
showPencil
();
setTypeInfo
(
typeInfo
);
showSucceedInfo
();
setTimeout
(
hideSucceedInfo
,
2000
);
}
function
updateUnit
(
event
:
React
.
FormEvent
<
HTMLDivElement
>
,
item
:
any
):
void
{
if
(
item
!==
undefined
)
{
setUnit
(
item
.
key
);
}
}
}
async
function
confirmEdit
():
Promise
<
void
>
{
async
function
confirmEdit
():
Promise
<
void
>
{
const
isMaxDuration
=
title
===
'
Max duration
'
;
const
isMaxDuration
=
title
===
'
Max duration
'
;
const
newProfile
=
Object
.
assign
({},
EXPERIMENT
.
profile
);
const
newProfile
=
Object
.
assign
({},
EXPERIMENT
.
profile
);
let
beforeParam
=
''
;
let
beforeParam
=
''
;
if
(
!
isMaxDuration
&&
!
editInputVal
.
match
(
/^
[
1-9
]\d
*$/
))
{
if
(
isMaxDuration
)
{
showMessageInfo
(
'
Please enter a positive integer!
'
,
'
error
'
);
if
(
!
editInputVal
.
match
(
/^
\d
+
(?=\.{0,1}\d
+$|$
)
/
))
{
return
;
showMessageInfo
(
'
Please enter a number!
'
,
'
error
'
);
setEditValInput
(
defaultVal
);
return
;
}
}
else
{
if
(
!
editInputVal
.
match
(
/^
[
1-9
]\d
*$/
))
{
showMessageInfo
(
'
Please enter a positive integer!
'
,
'
error
'
);
setEditValInput
(
defaultVal
);
return
;
}
}
}
if
(
isMaxDuration
)
{
if
(
isMaxDuration
)
{
beforeParam
=
maxExecDuration
;
beforeParam
=
maxExecDuration
;
}
else
if
(
title
===
'
Max trial numbers
'
)
{
}
else
if
(
title
===
MAX_TRIAL_NUMBERS
)
{
beforeParam
=
maxTrialNum
.
toString
();
beforeParam
=
maxTrialNum
.
toString
();
}
else
{
}
else
{
beforeParam
=
trialConcurrency
.
toString
();
beforeParam
=
trialConcurrency
.
toString
();
}
}
if
(
editInputVal
===
beforeParam
)
{
if
(
editInputVal
===
beforeParam
)
{
showMessageInfo
(
`Trial
${
field
}
has not changed`
,
'
error
'
);
if
(
isMaxDuration
)
{
return
;
if
(
maxDurationUnit
===
unit
)
{
showMessageInfo
(
`Trial
${
field
}
has not changed`
,
'
error
'
);
return
;
}
}
else
{
showMessageInfo
(
`Trial
${
field
}
has not changed`
,
'
error
'
);
return
;
}
}
}
if
(
isMaxDuration
)
{
if
(
isMaxDuration
)
{
newProfile
.
params
[
field
]
=
convertTimeToSecond
(
editInputVal
);
const
maxDura
=
JSON
.
parse
(
editInputVal
);
if
(
unit
===
'
m
'
)
{
newProfile
.
params
[
field
]
=
maxDura
*
60
;
}
else
if
(
unit
===
'
h
'
)
{
newProfile
.
params
[
field
]
=
maxDura
*
3600
;
}
else
{
newProfile
.
params
[
field
]
=
maxDura
*
24
*
60
*
60
;
}
}
else
{
}
else
{
newProfile
.
params
[
field
]
=
parseInt
(
editInputVal
,
10
);
newProfile
.
params
[
field
]
=
parseInt
(
editInputVal
,
10
);
}
}
...
@@ -82,7 +118,8 @@ export const EditExperimentParam = (): any => {
...
@@ -82,7 +118,8 @@ export const EditExperimentParam = (): any => {
params
:
{
update_type
:
editType
}
params
:
{
update_type
:
editType
}
});
});
if
(
res
.
status
===
200
)
{
if
(
res
.
status
===
200
)
{
showMessageInfo
(
`Successfully updated
${
field
}
`
,
'
success
'
);
showMessageInfo
(
`Successfully updated experiment's
${
field
}
`
,
'
success
'
);
changeMaxDurationUnit
(
unit
);
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
if
(
error
.
response
&&
error
.
response
.
data
.
error
)
{
if
(
error
.
response
&&
error
.
response
.
data
.
error
)
{
...
@@ -94,54 +131,88 @@ export const EditExperimentParam = (): any => {
...
@@ -94,54 +131,88 @@ export const EditExperimentParam = (): any => {
}
else
{
}
else
{
showMessageInfo
(
`Failed to update trial
${
field
}
\nUnknown error`
,
'
error
'
);
showMessageInfo
(
`Failed to update trial
${
field
}
\nUnknown error`
,
'
error
'
);
}
}
setEditValInput
(
defaultVal
);
}
}
showPencil
();
showPencil
();
updateOverviewPage
();
updateOverviewPage
();
}
}
function
showMessageInfo
(
info
:
string
,
typeInfo
:
string
):
any
{
function
cancelEdit
():
void
{
setInfo
(
info
);
setEditValInput
(
defaultVal
);
setTypeInfo
(
typeInfo
);
showPencil
();
showSucceedInfo
();
setUnit
(
maxDurationUnit
);
setTimeout
(
hideSucceedInfo
,
2000
);
}
function
convertUnit
(
val
:
string
):
string
{
if
(
val
===
'
d
'
)
{
return
'
day
'
;
}
else
if
(
val
===
'
h
'
)
{
return
'
hour
'
;
}
else
if
(
val
===
'
m
'
)
{
return
'
min
'
;
}
else
{
return
val
;
}
}
}
return
(
return
(
<
EditExpeParam
Context
.
Consumer
>
<
App
Context
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
{
{
(
value
s
):
React
.
ReactNode
=>
{
return
(
return
(
<
React
.
Fragment
>
<
EditExpeParamContext
.
Consumer
>
<
p
>
{
value
.
title
}
</
p
>
{
(
value
):
React
.
ReactNode
=>
{
<
div
>
let
editClassName
=
''
;
<
input
if
(
value
.
field
===
'
maxExecDuration
'
)
{
className
=
{
`
${
value
.
field
}
durationInput`
}
editClassName
=
isShowPencil
?
'
noEditDuration
'
:
'
editDuration
'
;
ref
=
{
DurationInputRef
}
}
disabled
=
{
isShowPencil
?
true
:
false
}
return
(
value
=
{
editInputVal
}
<
React
.
Fragment
>
onChange
=
{
setInputVal
}
<
div
className
=
{
`
${
editClassName
}
editparam`
}
>
/>
<
span
>
{
value
.
title
}
</
span
>
{
isShowPencil
&&
(
<
input
<
span
className
=
'edit'
onClick
=
{
hidePencil
}
>
className
=
{
`
${
value
.
field
}
editparam-Input`
}
{
Edit
}
ref
=
{
DurationInputRef
}
</
span
>
disabled
=
{
isShowPencil
?
true
:
false
}
)
}
value
=
{
editInputVal
}
onChange
=
{
setInputVal
}
{
!
isShowPencil
&&
(
/>
<
span
className
=
'series'
>
{
isShowPencil
&&
title
===
'
Max duration
'
&&
(
<
span
className
=
'confirm'
onClick
=
{
confirmEdit
}
>
<
span
>
{
convertUnit
(
values
.
maxDurationUnit
)
}
</
span
>
{
CheckMark
}
)
}
</
span
>
{
!
isShowPencil
&&
title
===
'
Max duration
'
&&
(
<
span
className
=
'cancel'
onClick
=
{
cancelEdit
}
>
<
Dropdown
{
Cancel
}
selectedKey
=
{
unit
}
</
span
>
options
=
{
durationUnit
}
</
span
>
className
=
'editparam-dropdown'
)
}
onChange
=
{
updateUnit
}
/>
)
}
{
isShowPencil
&&
(
<
span
className
=
'edit'
onClick
=
{
hidePencil
}
>
{
Edit
}
</
span
>
)
}
{
!
isShowPencil
&&
(
<
span
className
=
'series'
>
<
span
className
=
'confirm'
onClick
=
{
confirmEdit
}
>
{
CheckMark
}
</
span
>
<
span
className
=
'cancel'
onClick
=
{
cancelEdit
}
>
{
Cancel
}
</
span
>
</
span
>
)
}
{
isShowSucceedInfo
&&
<
MessageInfo
className
=
'info'
typeInfo
=
{
typeInfo
}
info
=
{
info
}
/>
}
{
isShowSucceedInfo
&&
(
</
div
>
<
MessageInfo
className
=
'info'
typeInfo
=
{
typeInfo
}
info
=
{
info
}
/>
</
React
.
Fragment
>
)
}
</
div
>
</
React
.
Fragment
>
);
}
}
</
EditExpeParamContext
.
Consumer
>
);
);
}
}
}
}
</
EditExpeParam
Context
.
Consumer
>
</
App
Context
.
Consumer
>
);
);
};
};
ts/webui/src/components/overview/count/ExpDuration.tsx
View file @
3b90b9d9
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
Stack
,
TooltipHost
,
ProgressIndicator
}
from
'
@fluentui/react
'
;
import
{
Stack
,
ProgressIndicator
,
TooltipHost
,
DirectionalHint
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
{
CONTROLTYPE
}
from
'
../../../static/const
'
;
import
{
CONTROLTYPE
,
TOOLTIP_BACKGROUND_COLOR
}
from
'
../../../static/const
'
;
import
{
convertDuration
}
from
'
../../../static/function
'
;
import
{
convertDuration
,
convertTimeAsUnit
}
from
'
../../../static/function
'
;
import
{
EditExperimentParam
}
from
'
./EditExperimentParam
'
;
import
{
EditExperimentParam
}
from
'
./EditExperimentParam
'
;
import
{
ExpDurationContext
}
from
'
./ExpDurationContext
'
;
import
{
ExpDurationContext
}
from
'
./ExpDurationContext
'
;
import
{
EditExpeParamContext
}
from
'
./context
'
;
import
{
EditExpeParamContext
}
from
'
./context
'
;
import
{
durationItem1
,
durationItem2
}
from
'
./commonStyle
'
;
import
'
../../../static/style/overview/count.scss
'
;
import
'
../../../static/style/overview/count.scss
'
;
const
itemStyle1
:
React
.
CSSProperties
=
{
width
:
'
62%
'
,
height
:
80
};
const
itemStyle2
:
React
.
CSSProperties
=
{
width
:
'
63%
'
,
height
:
80
,
textAlign
:
'
right
'
};
export
const
ExpDuration
=
():
any
=>
(
export
const
ExpDuration
=
():
any
=>
(
<
ExpDurationContext
.
Consumer
>
<
ExpDurationContext
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
{
{
(
value
):
React
.
ReactNode
=>
{
const
{
maxExecDuration
,
execDuration
,
updateOverviewPage
}
=
value
;
const
{
maxExecDuration
,
execDuration
,
maxDurationUnit
,
updateOverviewPage
}
=
value
;
const
tooltip
=
maxExecDuration
-
execDuration
;
const
tooltip
=
maxExecDuration
-
execDuration
;
const
maxExecDurationStr
=
convertDuration
(
maxExecDuration
);
const
percent
=
execDuration
/
maxExecDuration
;
const
percent
=
execDuration
/
maxExecDuration
;
const
execDurationStr
=
convertDuration
(
execDuration
);
const
maxExecDurationStr
=
convertTimeAsUnit
(
maxDurationUnit
,
maxExecDuration
).
toString
();
return
(
return
(
<
Stack
horizontal
className
=
'ExpDuration'
>
<
Stack
horizontal
className
=
'ExpDuration'
>
<
div
style
=
{
itemStyle1
}
>
<
div
style
=
{
durationItem1
}
>
<
TooltipHost
content
=
{
`
${
convertDuration
(
tooltip
)}
remaining`
}
>
<
TooltipHost
<
ProgressIndicator
percentComplete
=
{
percent
}
barHeight
=
{
15
}
/>
content
=
{
`
${
convertDuration
(
tooltip
)}
remaining`
}
directionalHint
=
{
DirectionalHint
.
bottomCenter
}
tooltipProps
=
{
{
calloutProps
:
{
styles
:
{
beak
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
beakCurtain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
},
calloutMain
:
{
background
:
TOOLTIP_BACKGROUND_COLOR
}
}
}
}
}
>
<
ProgressIndicator
className
=
{
EXPERIMENT
.
status
}
percentComplete
=
{
percent
}
barHeight
=
{
15
}
/>
</
TooltipHost
>
</
TooltipHost
>
{
/* execDuration / maxDuration: 20min / 1h */
}
<
div
className
=
'exp-progress'
>
<
span
className
=
{
`
${
EXPERIMENT
.
status
}
bold`
}
>
{
execDurationStr
}
</
span
>
<
span
className
=
'joiner'
>
/
</
span
>
<
span
>
{
`
${
maxExecDurationStr
}
${
maxDurationUnit
}
`
}
</
span
>
</
div
>
</
div
>
</
div
>
<
div
style
=
{
itemStyle2
}
>
<
div
style
=
{
durationItem2
}
>
<
Stack
horizontal
></
Stack
>
<
EditExpeParamContext
.
Provider
<
EditExpeParamContext
.
Provider
value
=
{
{
value
=
{
{
editType
:
CONTROLTYPE
[
0
],
editType
:
CONTROLTYPE
[
0
],
...
...
Prev
1
2
3
4
5
6
7
8
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