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