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
aec4ce14
Unverified
Commit
aec4ce14
authored
Apr 09, 2021
by
Lijiaoa
Committed by
GitHub
Apr 09, 2021
Browse files
[WebUI] support tensorboard (#3361)
parent
817ec68b
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
408 additions
and
18 deletions
+408
-18
ts/webui/src/components/managementExp/ExperimentManager.tsx
ts/webui/src/components/managementExp/ExperimentManager.tsx
+10
-2
ts/webui/src/components/modals/Compare.tsx
ts/webui/src/components/modals/Compare.tsx
+1
-1
ts/webui/src/components/modals/tensorboard/TensorboardDialog.tsx
...i/src/components/modals/tensorboard/TensorboardDialog.tsx
+75
-0
ts/webui/src/components/modals/tensorboard/TensorboardUI.tsx
ts/webui/src/components/modals/tensorboard/TensorboardUI.tsx
+144
-0
ts/webui/src/components/overview/count/TrialCount.tsx
ts/webui/src/components/overview/count/TrialCount.tsx
+10
-3
ts/webui/src/components/trial-detail/TableList.tsx
ts/webui/src/components/trial-detail/TableList.tsx
+12
-9
ts/webui/src/static/function.ts
ts/webui/src/static/function.ts
+44
-2
ts/webui/src/static/interface.ts
ts/webui/src/static/interface.ts
+12
-1
ts/webui/src/static/style/common.scss
ts/webui/src/static/style/common.scss
+25
-0
ts/webui/src/static/style/tensorboard.scss
ts/webui/src/static/style/tensorboard.scss
+75
-0
No files found.
ts/webui/src/components/managementExp/ExperimentManager.tsx
View file @
aec4ce14
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Stack
,
DetailsList
,
DefaultButton
,
Icon
,
SearchBox
,
IColumn
}
from
'
@fluentui/react
'
;
import
{
Stack
,
DetailsList
,
DefaultButton
,
Icon
,
SearchBox
,
IColumn
,
IStackTokens
}
from
'
@fluentui/react
'
;
import
{
ExperimentsManager
}
from
'
../../static/model/experimentsManager
'
;
import
{
ExperimentsManager
}
from
'
../../static/model/experimentsManager
'
;
import
{
expformatTimestamp
,
copyAndSort
}
from
'
../../static/function
'
;
import
{
expformatTimestamp
,
copyAndSort
}
from
'
../../static/function
'
;
import
{
AllExperimentList
,
SortInfo
}
from
'
../../static/interface
'
;
import
{
AllExperimentList
,
SortInfo
}
from
'
../../static/interface
'
;
...
@@ -18,6 +18,10 @@ import '../../static/style/experiment/experiment.scss';
...
@@ -18,6 +18,10 @@ import '../../static/style/experiment/experiment.scss';
import
'
../../static/style/overview/probar.scss
'
;
import
'
../../static/style/overview/probar.scss
'
;
import
'
../../static/style/tableStatus.css
'
;
import
'
../../static/style/tableStatus.css
'
;
const
expTokens
:
IStackTokens
=
{
childrenGap
:
25
};
interface
ExpListState
{
interface
ExpListState
{
columns
:
IColumn
[];
columns
:
IColumn
[];
platform
:
string
[];
platform
:
string
[];
...
@@ -111,7 +115,11 @@ class Experiment extends React.Component<{}, ExpListState> {
...
@@ -111,7 +115,11 @@ class Experiment extends React.Component<{}, ExpListState> {
</
DefaultButton
>
</
DefaultButton
>
</
div
>
</
div
>
</
Stack
>
</
Stack
>
<
Stack
className
=
{
`
${
hideFilter
?
'
hidden
'
:
''
}
filter-condition`
}
horizontal
gap
=
{
25
}
>
<
Stack
className
=
{
`
${
hideFilter
?
'
hidden
'
:
''
}
filter-condition`
}
horizontal
tokens
=
{
expTokens
}
>
<
FilterBtns
<
FilterBtns
platform
=
{
platform
}
platform
=
{
platform
}
selectedStatus
=
{
selectedStatus
}
selectedStatus
=
{
selectedStatus
}
...
...
ts/webui/src/components/modals/Compare.tsx
View file @
aec4ce14
...
@@ -4,9 +4,9 @@ import { Stack, Modal, IconButton, IDragOptions, ContextualMenu } from '@fluentu
...
@@ -4,9 +4,9 @@ import { Stack, Modal, IconButton, IDragOptions, ContextualMenu } from '@fluentu
import
ReactEcharts
from
'
echarts-for-react
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
{
TooltipForIntermediate
,
TableObj
,
SingleAxis
}
from
'
../../static/interface
'
;
import
{
TooltipForIntermediate
,
TableObj
,
SingleAxis
}
from
'
../../static/interface
'
;
import
{
contentStyles
,
iconButtonStyles
}
from
'
../buttons/ModalTheme
'
;
import
{
contentStyles
,
iconButtonStyles
}
from
'
../buttons/ModalTheme
'
;
import
'
../../static/style/compare.scss
'
;
import
{
convertDuration
,
parseMetrics
}
from
'
../../static/function
'
;
import
{
convertDuration
,
parseMetrics
}
from
'
../../static/function
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
'
../../static/style/compare.scss
'
;
function
_getWebUIWidth
():
number
{
function
_getWebUIWidth
():
number
{
return
window
.
innerWidth
;
return
window
.
innerWidth
;
...
...
ts/webui/src/components/modals/tensorboard/TensorboardDialog.tsx
0 → 100644
View file @
aec4ce14
import
React
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
{
PrimaryButton
,
Dialog
,
DialogType
,
DialogFooter
}
from
'
@fluentui/react
'
;
function
TensorboardDialog
(
props
):
any
{
const
{
isReaptedStartTensorboard
,
onHideDialog
,
item
,
isShowTensorboardDetail
,
errorMessage
}
=
props
;
const
dialogContentProps
=
{
type
:
DialogType
.
normal
,
title
:
`
${
isShowTensorboardDetail
?
item
.
id
:
'
TensorBoard
'
}
`
};
function
gotoTensorboard
():
void
{
const
hostname
=
window
.
location
.
hostname
;
const
protocol
=
window
.
location
.
protocol
;
window
.
open
(
`
${
protocol
}
//
${
hostname
}
:
${
item
.
port
}
`
);
onHideDialog
();
}
const
startTensorboard
=
isReaptedStartTensorboard
?
(
<
div
>
You had started this tensorBoard with these trials:
<
span
className
=
'bold'
>
{
item
.
trialJobIdList
.
join
(
'
,
'
)
}
</
span
>
.
<
div
className
=
'line-height'
>
Its tensorBoard id:
<
span
className
=
'bold'
>
{
item
.
id
}
</
span
>
</
div
>
</
div
>
)
:
(
<
div
>
You are starting a new TensorBoard with trials:
<
span
className
=
'bold'
>
{
item
.
trialJobIdList
.
join
(
'
,
'
)
}
</
span
>
.
<
div
className
=
'line-height'
>
TensorBoard id:
<
span
className
=
'bold'
>
{
item
.
id
}
</
span
>
</
div
>
</
div
>
);
return
(
<
Dialog
hidden
=
{
false
}
dialogContentProps
=
{
dialogContentProps
}
modalProps
=
{
{
className
:
'
dialog
'
}
}
>
{
errorMessage
.
error
?
(
<
div
>
<
span
>
Failed to start tensorBoard! Error message:
{
errorMessage
.
message
}
</
span
>
.
</
div
>
)
:
isShowTensorboardDetail
?
(
<
div
>
This tensorBoard with trials:
<
span
className
=
'bold'
>
{
item
.
trialJobIdList
.
join
(
'
,
'
)
}
</
span
>
.
</
div
>
)
:
(
startTensorboard
)
}
{
errorMessage
.
error
?
(
<
DialogFooter
>
<
PrimaryButton
onClick
=
{
onHideDialog
}
text
=
'Close'
/>
</
DialogFooter
>
)
:
(
<
DialogFooter
>
<
PrimaryButton
onClick
=
{
gotoTensorboard
}
text
=
{
`
${
isShowTensorboardDetail
?
'
See tensorBoard
'
:
'
Ok
'
}
`
}
/>
</
DialogFooter
>
)
}
</
Dialog
>
);
}
TensorboardDialog
.
propTypes
=
{
isReaptedStartTensorboard
:
PropTypes
.
bool
,
isShowTensorboardDetail
:
PropTypes
.
bool
,
onHideDialog
:
PropTypes
.
func
,
item
:
PropTypes
.
object
,
errorMessage
:
PropTypes
.
object
};
export
default
TensorboardDialog
;
ts/webui/src/components/modals/tensorboard/TensorboardUI.tsx
0 → 100644
View file @
aec4ce14
import
React
,
{
useState
,
useEffect
}
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
axios
from
'
axios
'
;
import
{
DefaultButton
,
IContextualMenuProps
}
from
'
@fluentui/react
'
;
import
{
MANAGER_IP
}
from
'
../../../static/const
'
;
import
{
disableTensorboard
,
getTensorboardMenu
}
from
'
../../../static/function
'
;
import
{
Tensorboard
}
from
'
../../../static/interface
'
;
import
TensorboardDialog
from
'
./TensorboardDialog
'
;
function
TensorboardUI
(
props
):
any
{
let
refreshTensorboard
=
0
;
const
{
selectedRowIds
}
=
props
;
const
[
queryTensorboardList
,
setQueryTensorboardList
]
=
useState
([]);
const
[
isReaptedStartTensorboard
,
setReaptedTensorboard
]
=
useState
(
false
);
const
[
tensorboardPanelVisible
,
setTensorboardPanelVisible
]
=
useState
(
false
);
const
[
isShowTensorboardDetail
,
setIsShowTensorboardDetail
]
=
useState
(
false
);
const
[
selectedTensorboard
,
setSelectedTensorboard
]
=
useState
({});
const
[
errorMessage
,
setErrorMessage
]
=
useState
({});
const
[
timerList
,
setTimerList
]
=
useState
([
0
]);
function
startTrialTensorboard
():
void
{
const
{
selectedRowIds
}
=
props
;
if
(
selectedRowIds
.
length
>
0
)
{
setIsShowTensorboardDetail
(
false
);
const
result
=
queryTensorboardList
.
filter
(
(
item
:
Tensorboard
)
=>
item
.
trialJobIdList
.
join
(
'
,
'
)
===
selectedRowIds
.
join
(
'
,
'
)
);
if
(
result
.
length
>
0
)
{
setReaptedTensorboard
(
true
);
setSelectedTensorboard
(
result
[
0
]);
setTensorboardPanelVisible
(
true
);
}
else
{
const
startTensorboard
=
axios
.
post
(
`
${
MANAGER_IP
}
/tensorboard`
,
{
trials
:
selectedRowIds
.
join
(
'
,
'
)
});
startTensorboard
.
then
(
res
=>
{
if
(
res
.
status
===
200
)
{
setSelectedTensorboard
(
res
.
data
);
closeTimer
();
queryAllTensorboard
();
setErrorMessage
({
error
:
false
,
message
:
''
});
setTensorboardPanelVisible
(
true
);
}
})
.
catch
(
error
=>
{
setErrorMessage
({
error
:
true
,
message
:
error
.
message
||
'
Tensorboard start failed
'
});
setTensorboardPanelVisible
(
true
);
});
setReaptedTensorboard
(
false
);
}
}
else
{
alert
(
'
Please select trials first!
'
);
}
}
function
queryAllTensorboard
():
void
{
const
queryTensorboard
=
axios
.
get
(
`
${
MANAGER_IP
}
/tensorboard-tasks`
);
queryTensorboard
.
then
(
res
=>
{
if
(
res
.
status
===
200
)
{
setQueryTensorboardList
(
res
.
data
);
if
(
res
.
data
.
length
!==
0
)
{
refreshTensorboard
=
window
.
setTimeout
(
queryAllTensorboard
,
10000
);
const
storeTimerList
=
timerList
;
storeTimerList
.
push
(
refreshTensorboard
);
setTimerList
(
storeTimerList
);
}
}
});
}
function
closeTimer
():
void
{
timerList
.
forEach
(
item
=>
{
window
.
clearTimeout
(
item
);
});
}
function
stopAllTensorboard
():
void
{
const
delTensorboard
=
axios
.
delete
(
`
${
MANAGER_IP
}
/tensorboard-tasks`
);
delTensorboard
.
then
(
res
=>
{
if
(
res
.
status
===
200
)
{
setQueryTensorboardList
([]);
closeTimer
();
}
});
}
function
seeTensorboardWebportal
(
item
:
Tensorboard
):
void
{
setSelectedTensorboard
(
item
);
setIsShowTensorboardDetail
(
true
);
setTensorboardPanelVisible
(
true
);
}
const
isDisableTensorboardBtn
=
disableTensorboard
(
selectedRowIds
,
queryTensorboardList
);
const
tensorboardMenu
:
IContextualMenuProps
=
getTensorboardMenu
(
queryTensorboardList
,
stopAllTensorboard
,
seeTensorboardWebportal
);
useEffect
(()
=>
{
queryAllTensorboard
();
// clear timer when component is unmounted
return
function
closeTimer
():
void
{
timerList
.
forEach
(
item
=>
{
window
.
clearTimeout
(
item
);
});
};
},
[]);
return
(
<
React
.
Fragment
>
<
DefaultButton
text
=
'TensorBoard'
className
=
'elementMarginLeft'
split
splitButtonAriaLabel
=
'See 2 options'
aria
-
roledescription
=
'split button'
menuProps
=
{
tensorboardMenu
}
onClick
=
{
():
void
=>
startTrialTensorboard
()
}
disabled
=
{
isDisableTensorboardBtn
}
/>
{
queryTensorboardList
.
length
!==
0
?
<
span
className
=
'circle'
>
{
queryTensorboardList
.
length
}
</
span
>
:
null
}
{
tensorboardPanelVisible
&&
(
<
TensorboardDialog
isReaptedStartTensorboard
=
{
isReaptedStartTensorboard
}
isShowTensorboardDetail
=
{
isShowTensorboardDetail
}
errorMessage
=
{
errorMessage
}
item
=
{
selectedTensorboard
}
onHideDialog
=
{
():
void
=>
{
setTensorboardPanelVisible
(
false
);
}
}
/>
)
}
</
React
.
Fragment
>
);
}
TensorboardUI
.
propTypes
=
{
selectedRowIds
:
PropTypes
.
array
};
export
default
TensorboardUI
;
ts/webui/src/components/overview/count/TrialCount.tsx
View file @
aec4ce14
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Stack
,
TooltipHost
,
ProgressIndicator
,
DirectionalHint
}
from
'
@fluentui/react
'
;
import
{
Stack
,
TooltipHost
,
ProgressIndicator
,
DirectionalHint
,
IStackTokens
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../../static/datamodel
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../../static/datamodel
'
;
import
{
CONTROLTYPE
,
TOOLTIP_BACKGROUND_COLOR
,
MAX_TRIAL_NUMBERS
}
from
'
../../../static/const
'
;
import
{
CONTROLTYPE
,
TOOLTIP_BACKGROUND_COLOR
,
MAX_TRIAL_NUMBERS
}
from
'
../../../static/const
'
;
import
{
EditExperimentParam
}
from
'
./EditExperimentParam
'
;
import
{
EditExperimentParam
}
from
'
./EditExperimentParam
'
;
...
@@ -7,6 +7,13 @@ import { EditExpeParamContext } from './context';
...
@@ -7,6 +7,13 @@ import { EditExpeParamContext } from './context';
import
{
ExpDurationContext
}
from
'
./ExpDurationContext
'
;
import
{
ExpDurationContext
}
from
'
./ExpDurationContext
'
;
import
{
leftProgress
,
rightEidtParam
,
progressHeight
}
from
'
./commonStyle
'
;
import
{
leftProgress
,
rightEidtParam
,
progressHeight
}
from
'
./commonStyle
'
;
const
line1Tokens
:
IStackTokens
=
{
childrenGap
:
60
};
const
line2Tokens
:
IStackTokens
=
{
childrenGap
:
80
};
export
const
TrialCount
=
():
any
=>
{
export
const
TrialCount
=
():
any
=>
{
const
count
=
TRIALS
.
countStatus
();
const
count
=
TRIALS
.
countStatus
();
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...
@@ -52,7 +59,7 @@ export const TrialCount = (): any => {
...
@@ -52,7 +59,7 @@ export const TrialCount = (): any => {
</
Stack
>
</
Stack
>
<
Stack
horizontal
className
=
'marginTop'
>
<
Stack
horizontal
className
=
'marginTop'
>
<
div
style
=
{
leftProgress
}
>
<
div
style
=
{
leftProgress
}
>
<
Stack
horizontal
className
=
'status-count'
gap
=
{
60
}
>
<
Stack
horizontal
className
=
'status-count'
tokens
=
{
line1Tokens
}
>
<
div
>
<
div
>
<
span
>
Running
</
span
>
<
span
>
Running
</
span
>
<
p
>
{
count
.
get
(
'
RUNNING
'
)
}
</
p
>
<
p
>
{
count
.
get
(
'
RUNNING
'
)
}
</
p
>
...
@@ -66,7 +73,7 @@ export const TrialCount = (): any => {
...
@@ -66,7 +73,7 @@ export const TrialCount = (): any => {
<
p
>
{
stoppedCount
}
</
p
>
<
p
>
{
stoppedCount
}
</
p
>
</
div
>
</
div
>
</
Stack
>
</
Stack
>
<
Stack
horizontal
className
=
'status-count marginTop'
gap
=
{
80
}
>
<
Stack
horizontal
className
=
'status-count marginTop'
tokens
=
{
line2Tokens
}
>
<
div
>
<
div
>
<
span
>
Failed
</
span
>
<
span
>
Failed
</
span
>
<
p
>
{
count
.
get
(
'
FAILED
'
)
}
</
p
>
<
p
>
{
count
.
get
(
'
FAILED
'
)
}
</
p
>
...
...
ts/webui/src/components/trial-detail/TableList.tsx
View file @
aec4ce14
import
React
from
'
react
'
;
import
{
import
{
DefaultButton
,
DefaultButton
,
Dropdown
,
Dropdown
,
...
@@ -12,28 +13,29 @@ import {
...
@@ -12,28 +13,29 @@ import {
TooltipHost
,
TooltipHost
,
DirectionalHint
DirectionalHint
}
from
'
@fluentui/react
'
;
}
from
'
@fluentui/react
'
;
import
React
from
'
react
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
TOOLTIP_BACKGROUND_COLOR
}
from
'
../../static/const
'
;
import
{
TOOLTIP_BACKGROUND_COLOR
}
from
'
../../static/const
'
;
import
{
convertDuration
,
formatTimestamp
,
copyAndSort
}
from
'
../../static/function
'
;
import
{
convertDuration
,
formatTimestamp
,
copyAndSort
}
from
'
../../static/function
'
;
import
{
TableObj
,
SortInfo
}
from
'
../../static/interface
'
;
import
{
TableObj
,
SortInfo
}
from
'
../../static/interface
'
;
import
'
../../static/style/search.scss
'
;
import
'
../../static/style/tableStatus.css
'
;
import
'
../../static/style/logPath.scss
'
;
import
'
../../static/style/table.scss
'
;
import
'
../../static/style/button.scss
'
;
import
'
../../static/style/openRow.scss
'
;
import
'
../../static/style/pagination.scss
'
;
import
'
../../static/style/overview/overviewTitle.scss
'
;
import
{
blocked
,
copy
,
LineChart
,
tableListIcon
}
from
'
../buttons/Icon
'
;
import
{
blocked
,
copy
,
LineChart
,
tableListIcon
}
from
'
../buttons/Icon
'
;
import
ChangeColumnComponent
from
'
../modals/ChangeColumnComponent
'
;
import
ChangeColumnComponent
from
'
../modals/ChangeColumnComponent
'
;
import
Compare
from
'
../modals/Compare
'
;
import
Compare
from
'
../modals/Compare
'
;
import
Customize
from
'
../modals/CustomizedTrial
'
;
import
Customize
from
'
../modals/CustomizedTrial
'
;
import
TensorboardUI
from
'
../modals/tensorboard/TensorboardUI
'
;
import
KillJob
from
'
../modals/Killjob
'
;
import
KillJob
from
'
../modals/Killjob
'
;
import
ExpandableDetails
from
'
../public-child/ExpandableDetails
'
;
import
ExpandableDetails
from
'
../public-child/ExpandableDetails
'
;
import
PaginationTable
from
'
../public-child/PaginationTable
'
;
import
PaginationTable
from
'
../public-child/PaginationTable
'
;
import
CopyButton
from
'
../public-child/CopyButton
'
;
import
CopyButton
from
'
../public-child/CopyButton
'
;
import
{
Trial
}
from
'
../../static/model/trial
'
;
import
{
Trial
}
from
'
../../static/model/trial
'
;
import
'
../../static/style/button.scss
'
;
import
'
../../static/style/logPath.scss
'
;
import
'
../../static/style/openRow.scss
'
;
import
'
../../static/style/pagination.scss
'
;
import
'
../../static/style/search.scss
'
;
import
'
../../static/style/table.scss
'
;
import
'
../../static/style/tableStatus.css
'
;
import
'
../../static/style/tensorboard.scss
'
;
import
'
../../static/style/overview/overviewTitle.scss
'
;
require
(
'
echarts/lib/chart/line
'
);
require
(
'
echarts/lib/chart/line
'
);
require
(
'
echarts/lib/component/tooltip
'
);
require
(
'
echarts/lib/component/tooltip
'
);
...
@@ -491,6 +493,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -491,6 +493,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
}
}
}
}
disabled
=
{
selectedRowIds
.
length
===
0
}
disabled
=
{
selectedRowIds
.
length
===
0
}
/>
/>
<
TensorboardUI
selectedRowIds
=
{
selectedRowIds
}
/>
</
StackItem
>
</
StackItem
>
<
StackItem
grow
=
{
50
}
>
<
StackItem
grow
=
{
50
}
>
<
Stack
horizontal
horizontalAlign
=
'end'
className
=
'allList'
>
<
Stack
horizontal
horizontalAlign
=
'end'
className
=
'allList'
>
...
...
ts/webui/src/static/function.ts
View file @
aec4ce14
import
*
as
JSON5
from
'
json5
'
;
import
*
as
JSON5
from
'
json5
'
;
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
;
import
{
IContextualMenuProps
}
from
'
@fluentui/react
'
;
import
{
MANAGER_IP
}
from
'
./const
'
;
import
{
MANAGER_IP
}
from
'
./const
'
;
import
{
MetricDataRecord
,
FinalType
,
TableObj
}
from
'
./interface
'
;
import
{
MetricDataRecord
,
FinalType
,
TableObj
,
Tensorboard
}
from
'
./interface
'
;
async
function
requestAxios
(
url
:
string
):
Promise
<
any
>
{
async
function
requestAxios
(
url
:
string
):
Promise
<
any
>
{
const
response
=
await
axios
.
get
(
url
);
const
response
=
await
axios
.
get
(
url
);
...
@@ -305,6 +306,45 @@ function copyAndSort<T>(items: T[], columnKey: string, isSortedDescending?: bool
...
@@ -305,6 +306,45 @@ function copyAndSort<T>(items: T[], columnKey: string, isSortedDescending?: bool
return
(
isSortedDescending
?
a
[
key
]
<
b
[
key
]
:
a
[
key
]
>
b
[
key
])
?
1
:
-
1
;
return
(
isSortedDescending
?
a
[
key
]
<
b
[
key
]
:
a
[
key
]
>
b
[
key
])
?
1
:
-
1
;
});
});
}
}
function
disableTensorboard
(
selectedRowIds
:
string
[],
queryTensorboardList
:
Tensorboard
[]):
boolean
{
let
flag
=
true
;
if
(
selectedRowIds
.
length
!==
0
)
{
flag
=
false
;
}
if
(
selectedRowIds
.
length
===
0
&&
queryTensorboardList
.
length
!==
0
)
{
flag
=
false
;
}
return
flag
;
}
function
getTensorboardMenu
(
queryTensorboardList
:
Tensorboard
[],
stopFunc
,
seeDetailFunc
):
IContextualMenuProps
{
const
result
:
Array
<
object
>
=
[];
if
(
queryTensorboardList
.
length
!==
0
)
{
result
.
push
({
key
:
'
delete
'
,
text
:
'
Stop all tensorBoard
'
,
className
:
'
clearAll
'
,
onClick
:
stopFunc
});
queryTensorboardList
.
forEach
(
item
=>
{
result
.
push
({
key
:
item
.
id
,
text
:
`
${
item
.
id
}
`
,
className
:
`CommandBarButton-
${
item
.
status
}
`
,
onClick
:
():
void
=>
seeDetailFunc
(
item
)
});
});
}
const
tensorboardMenu
:
IContextualMenuProps
=
{
items
:
result
.
reverse
()
as
any
};
return
tensorboardMenu
;
}
export
{
export
{
convertTime
,
convertTime
,
convertDuration
,
convertDuration
,
...
@@ -327,5 +367,7 @@ export {
...
@@ -327,5 +367,7 @@ export {
formatComplexTypeValue
,
formatComplexTypeValue
,
isManagerExperimentPage
,
isManagerExperimentPage
,
caclMonacoEditorHeight
,
caclMonacoEditorHeight
,
copyAndSort
copyAndSort
,
disableTensorboard
,
getTensorboardMenu
};
};
ts/webui/src/static/interface.ts
View file @
aec4ce14
...
@@ -193,6 +193,16 @@ interface AllExperimentList {
...
@@ -193,6 +193,16 @@ interface AllExperimentList {
webuiUrl
:
string
[];
webuiUrl
:
string
[];
logDir
:
string
[];
logDir
:
string
[];
}
}
interface
Tensorboard
{
id
:
string
;
status
:
string
;
trialJobIdList
:
string
[];
trialLogDirectoryList
:
string
[];
pid
:
number
;
port
:
string
;
}
export
{
export
{
TableObj
,
TableObj
,
TableRecord
,
TableRecord
,
...
@@ -215,5 +225,6 @@ export {
...
@@ -215,5 +225,6 @@ export {
SingleAxis
,
SingleAxis
,
MultipleAxes
,
MultipleAxes
,
SortInfo
,
SortInfo
,
AllExperimentList
AllExperimentList
,
Tensorboard
};
};
ts/webui/src/static/style/common.scss
View file @
aec4ce14
$themeBlue
:
#0071bc
;
.ellipsis
{
.ellipsis
{
overflow
:
hidden
;
overflow
:
hidden
;
white-space
:
nowrap
;
white-space
:
nowrap
;
...
@@ -48,3 +50,26 @@
...
@@ -48,3 +50,26 @@
padding
:
0
!
important
;
padding
:
0
!
important
;
border
:
none
!
important
;
border
:
none
!
important
;
}
}
.elementMarginLeft
{
margin-left
:
10px
;
}
.operationBtn
{
i
{
color
:
$themeBlue
;
}
}
/* for table row border */
.ms-List-cell
{
border-bottom
:
1px
solid
#eeecea
;
}
.line-height
{
line-height
:
30px
;
}
.bold
{
font-weight
:
bold
;
}
ts/webui/src/static/style/tensorboard.scss
0 → 100644
View file @
aec4ce14
$cicleBg
:
#009ee7
;
$size
:
24px
;
.circle
{
display
:
inline-block
;
width
:
$size
;
height
:
$size
;
border-radius
:
50%
;
color
:
#fff
;
line-height
:
$size
;
text-align
:
center
;
background
:
$cicleBg
;
margin-left
:
4px
;
position
:
relative
;
top
:
-16px
;
left
:
-20px
;
}
.CommandBarButton
{
&
-RUNNING
{
.
ms-ContextualMenu-itemText
:
:
after
{
content
:
'RUNNING'
;
color
:
#0071bc
;
margin-left
:
15px
;
}
}
&
-STOPPED
{
.
ms-ContextualMenu-itemText
:
:
after
{
content
:
'STOPPED'
;
color
:
green
;
margin-left
:
15px
;
}
}
&
-STOPPING
{
.
ms-ContextualMenu-itemText
:
:
after
{
content
:
'STOPPING'
;
color
:
green
;
margin-left
:
15px
;
}
}
&
-DOWNLOADING_DATA
{
.
ms-ContextualMenu-itemText
:
:
after
{
content
:
'DOWNLOADING_DATA'
;
color
:
green
;
margin-left
:
15px
;
}
}
&
-ERROR
{
.
ms-ContextualMenu-itemText
:
:
after
{
content
:
'ERROR'
;
color
:
red
;
margin-left
:
15px
;
}
}
&
-FAIL_DOWNLOAD_DATA
{
.
ms-ContextualMenu-itemText
:
:
after
{
content
:
'FAIL_DOWNLOAD_DATA'
;
color
:
red
;
margin-left
:
15px
;
}
}
}
.clearAll
{
border-top
:
1px
solid
#ccc
;
.ms-ContextualMenu-itemText
{
text-align
:
center
;
}
}
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