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
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