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
1cd7ad5f
Unverified
Commit
1cd7ad5f
authored
Oct 12, 2020
by
Lijiaoa
Committed by
GitHub
Oct 12, 2020
Browse files
[webui] refactor overview page (#2924)
parent
0a6c234a
Changes
67
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
357 additions
and
38 deletions
+357
-38
src/webui/src/components/overview/experiment/Command.tsx
src/webui/src/components/overview/experiment/Command.tsx
+63
-0
src/webui/src/components/overview/experiment/basicInfoStyles.ts
...bui/src/components/overview/experiment/basicInfoStyles.ts
+52
-0
src/webui/src/components/overview/overviewConst.ts
src/webui/src/components/overview/overviewConst.ts
+21
-0
src/webui/src/components/overview/table/Details.tsx
src/webui/src/components/overview/table/Details.tsx
+1
-1
src/webui/src/components/overview/table/SuccessTable.tsx
src/webui/src/components/overview/table/SuccessTable.tsx
+34
-18
src/webui/src/components/public-child/OpenRow.tsx
src/webui/src/components/public-child/OpenRow.tsx
+1
-1
src/webui/src/components/public-child/config/TrialConfigButton.tsx
.../src/components/public-child/config/TrialConfigButton.tsx
+27
-0
src/webui/src/components/public-child/config/TrialConfigPanel.tsx
...i/src/components/public-child/config/TrialConfigPanel.tsx
+104
-0
src/webui/src/components/stateless-component/NNItabs.tsx
src/webui/src/components/stateless-component/NNItabs.tsx
+1
-1
src/webui/src/components/trial-detail/TableList.tsx
src/webui/src/components/trial-detail/TableList.tsx
+1
-1
src/webui/src/index.tsx
src/webui/src/index.tsx
+8
-1
src/webui/src/static/const.ts
src/webui/src/static/const.ts
+1
-1
src/webui/src/static/function.ts
src/webui/src/static/function.ts
+43
-14
src/webui/src/static/img/icon/1.png
src/webui/src/static/img/icon/1.png
+0
-0
src/webui/src/static/img/icon/10.png
src/webui/src/static/img/icon/10.png
+0
-0
src/webui/src/static/img/icon/11.png
src/webui/src/static/img/icon/11.png
+0
-0
src/webui/src/static/img/icon/2.png
src/webui/src/static/img/icon/2.png
+0
-0
src/webui/src/static/img/icon/3.png
src/webui/src/static/img/icon/3.png
+0
-0
src/webui/src/static/img/icon/4.png
src/webui/src/static/img/icon/4.png
+0
-0
src/webui/src/static/img/icon/5.png
src/webui/src/static/img/icon/5.png
+0
-0
No files found.
src/webui/src/components/overview/experiment/Command.tsx
0 → 100644
View file @
1cd7ad5f
import
React
from
'
react
'
;
import
{
TooltipHost
,
Stack
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
'
../../../static/style/overview/command.scss
'
;
export
const
Command
=
():
any
=>
{
const
clusterMetaData
=
EXPERIMENT
.
profile
.
params
.
clusterMetaData
;
const
tuner
=
EXPERIMENT
.
profile
.
params
.
tuner
;
const
advisor
=
EXPERIMENT
.
profile
.
params
.
advisor
;
const
assessor
=
EXPERIMENT
.
profile
.
params
.
assessor
;
let
title
=
''
;
let
builtinName
=
''
;
let
trialCommand
=
'
unknown
'
;
if
(
tuner
!==
undefined
)
{
title
=
title
.
concat
(
'
Tuner
'
);
if
(
tuner
.
builtinTunerName
!==
undefined
)
{
builtinName
=
builtinName
.
concat
(
tuner
.
builtinTunerName
);
}
}
if
(
advisor
!==
undefined
)
{
title
=
title
.
concat
(
'
/ Assessor
'
);
if
(
advisor
.
builtinAdvisorName
!==
undefined
)
{
builtinName
=
builtinName
.
concat
(
advisor
.
builtinAdvisorName
);
}
}
if
(
assessor
!==
undefined
)
{
title
=
title
.
concat
(
'
/ Addvisor
'
);
if
(
assessor
.
builtinAssessorName
!==
undefined
)
{
builtinName
=
builtinName
.
concat
(
assessor
.
builtinAssessorName
);
}
}
if
(
clusterMetaData
!==
undefined
)
{
for
(
const
item
of
clusterMetaData
)
{
if
(
item
.
key
===
'
command
'
)
{
trialCommand
=
item
.
value
;
}
}
}
return
(
<
div
className
=
'command basic'
>
<
div
className
=
'command1'
>
<
p
>
Training platform
</
p
>
<
div
className
=
'nowrap'
>
{
EXPERIMENT
.
profile
.
params
.
trainingServicePlatform
}
</
div
>
<
p
className
=
'lineMargin'
>
{
title
}
</
p
>
<
div
className
=
'nowrap'
>
{
builtinName
}
</
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
>
);
};
src/webui/src/components/overview/experiment/basicInfoStyles.ts
0 → 100644
View file @
1cd7ad5f
import
{
FontWeights
,
mergeStyleSets
,
getTheme
}
from
'
@fluentui/react
'
;
const
theme
=
getTheme
();
export
const
styles
=
mergeStyleSets
({
buttonArea
:
{
verticalAlign
:
'
top
'
,
display
:
'
inline-block
'
,
textAlign
:
'
center
'
,
// margin: '0 100px',
minWidth
:
30
,
height
:
30
},
callout
:
{
maxWidth
:
300
},
header
:
{
padding
:
'
18px 24px 12px
'
},
title
:
[
theme
.
fonts
.
xLarge
,
{
margin
:
0
,
color
:
theme
.
palette
.
neutralPrimary
,
fontWeight
:
FontWeights
.
semilight
}
],
inner
:
{
height
:
'
100%
'
,
padding
:
'
0 24px 20px
'
},
actions
:
{
position
:
'
relative
'
,
marginTop
:
20
,
width
:
'
100%
'
,
whiteSpace
:
'
nowrap
'
},
subtext
:
[
theme
.
fonts
.
small
,
{
margin
:
0
,
color
:
theme
.
palette
.
neutralPrimary
,
fontWeight
:
FontWeights
.
semilight
}
],
link
:
[
theme
.
fonts
.
medium
,
{
color
:
theme
.
palette
.
neutralPrimary
}
]
});
src/webui/src/components/overview/overviewConst.ts
0 → 100644
View file @
1cd7ad5f
const
itemStyle1
:
React
.
CSSProperties
=
{
width
:
'
75%
'
};
const
itemStyleSucceed
:
React
.
CSSProperties
=
{
width
:
'
28%
'
};
const
itemStyle2
:
React
.
CSSProperties
=
{
height
:
38
};
// top trials entries
const
entriesOption
=
[
{
key
:
'
10
'
,
text
:
'
10
'
},
{
key
:
'
20
'
,
text
:
'
20
'
},
{
key
:
'
30
'
,
text
:
'
30
'
},
{
key
:
'
50
'
,
text
:
'
40
'
},
{
key
:
'
100
'
,
text
:
'
100
'
}
];
export
{
itemStyle1
,
itemStyleSucceed
,
itemStyle2
,
entriesOption
};
src/webui/src/components/overview/Details.tsx
→
src/webui/src/components/overview/
table/
Details.tsx
View file @
1cd7ad5f
import
*
as
React
from
'
react
'
;
import
{
DetailsRow
,
IDetailsRowBaseProps
}
from
'
@fluentui/react
'
;
import
OpenRow
from
'
../public-child/OpenRow
'
;
import
OpenRow
from
'
../
../
public-child/OpenRow
'
;
interface
DetailsProps
{
detailsProps
:
IDetailsRowBaseProps
;
...
...
src/webui/src/components/overview/SuccessTable.tsx
→
src/webui/src/components/overview/
table/
SuccessTable.tsx
View file @
1cd7ad5f
import
*
as
React
from
'
react
'
;
import
{
DetailsList
,
IDetailsListProps
,
IColumn
}
from
'
@fluentui/react
'
;
import
DefaultMetric
from
'
../public-child/DefaultMetric
'
;
import
DefaultMetric
from
'
../
../
public-child/DefaultMetric
'
;
import
Details
from
'
./Details
'
;
import
{
convertDuration
}
from
'
../../static/function
'
;
import
{
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
DETAILTABS
}
from
'
../stateless-component/NNItabs
'
;
import
'
../../static/style/succTable.scss
'
;
import
'
../../static/style/openRow.scss
'
;
import
{
convertDuration
}
from
'
../../../static/function
'
;
import
{
TRIALS
}
from
'
../../../static/datamodel
'
;
import
{
DETAILTABS
}
from
'
../../stateless-component/NNItabs
'
;
import
'
../../../static/style/succTable.scss
'
;
import
'
../../../static/style/tableStatus.css
'
;
import
'
../../../static/style/openRow.scss
'
;
interface
SuccessTableProps
{
trialIds
:
string
[];
...
...
@@ -15,12 +16,17 @@ interface SuccessTableProps {
interface
SuccessTableState
{
columns
:
IColumn
[];
source
:
Array
<
any
>
;
innerWidth
:
number
;
}
class
SuccessTable
extends
React
.
Component
<
SuccessTableProps
,
SuccessTableState
>
{
constructor
(
props
:
SuccessTableProps
)
{
super
(
props
);
this
.
state
=
{
columns
:
this
.
columns
,
source
:
TRIALS
.
table
(
this
.
props
.
trialIds
)
};
this
.
state
=
{
columns
:
this
.
columns
,
source
:
TRIALS
.
table
(
this
.
props
.
trialIds
),
innerWidth
:
window
.
innerWidth
};
}
private
onRenderRow
:
IDetailsListProps
[
'
onRenderRow
'
]
=
props
=>
{
...
...
@@ -70,8 +76,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
name
:
'
Trial No.
'
,
key
:
'
sequenceId
'
,
fieldName
:
'
sequenceId
'
,
// required!
minWidth
:
60
,
maxWidth
:
120
,
minWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
maxWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
...
...
@@ -80,8 +86,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
name
:
'
ID
'
,
key
:
'
id
'
,
fieldName
:
'
id
'
,
minWidth
:
80
,
maxWidth
:
100
,
minWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
maxWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
isResizable
:
true
,
className
:
'
tableHead leftTitle
'
,
data
:
'
string
'
,
...
...
@@ -90,8 +96,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
{
name
:
'
Duration
'
,
key
:
'
duration
'
,
minWidth
:
100
,
maxWidth
:
210
,
minWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
maxWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
isResizable
:
true
,
fieldName
:
'
duration
'
,
data
:
'
number
'
,
...
...
@@ -105,8 +111,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
{
name
:
'
Status
'
,
key
:
'
status
'
,
minWidth
:
140
,
maxWidth
:
210
,
minWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
maxWidth
:
(
window
.
innerWidth
*
0.333
-
150
)
/
5
,
isResizable
:
true
,
fieldName
:
'
status
'
,
onRender
:
(
item
:
any
):
React
.
ReactNode
=>
{
...
...
@@ -117,8 +123,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
name
:
'
Default metric
'
,
key
:
'
accuracy
'
,
fieldName
:
'
accuracy
'
,
minWidth
:
120
,
maxWidth
:
360
,
minWidth
:
(
window
.
innerWidth
*
0.333
-
200
)
/
5
,
//
maxWidth:
(window.innerWidth * 0.333 - 150) / 5
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
...
...
@@ -128,6 +134,17 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
}
];
setInnerWidth
=
():
void
=>
{
this
.
setState
(()
=>
({
innerWidth
:
window
.
innerWidth
}));
};
componentDidMount
():
void
{
window
.
addEventListener
(
'
resize
'
,
this
.
setInnerWidth
);
}
componentWillUnmount
():
void
{
window
.
removeEventListener
(
'
resize
'
,
this
.
setInnerWidth
);
}
componentDidUpdate
(
prevProps
:
SuccessTableProps
):
void
{
if
(
this
.
props
.
trialIds
!==
prevProps
.
trialIds
)
{
const
{
trialIds
}
=
this
.
props
;
...
...
@@ -138,7 +155,6 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
render
():
React
.
ReactNode
{
const
{
columns
,
source
}
=
this
.
state
;
const
isNoneData
=
source
.
length
===
0
?
true
:
false
;
return
(
<
div
id
=
'succTable'
>
<
DetailsList
...
...
src/webui/src/components/public-child/OpenRow.tsx
View file @
1cd7ad5f
...
...
@@ -8,7 +8,7 @@ import JSONTree from 'react-json-tree';
import
PaiTrialLog
from
'
../public-child/PaiTrialLog
'
;
import
TrialLog
from
'
../public-child/TrialLog
'
;
import
MessageInfo
from
'
../modals/MessageInfo
'
;
import
'
../../static/style/overview.scss
'
;
import
'
../../static/style/overview
/overview
.scss
'
;
import
'
../../static/style/copyParameter.scss
'
;
import
'
../../static/style/openRow.scss
'
;
...
...
src/webui/src/components/public-child/config/TrialConfigButton.tsx
0 → 100644
View file @
1cd7ad5f
import
React
,
{
useState
,
useCallback
}
from
'
react
'
;
import
{
DefaultButton
,
Stack
}
from
'
@fluentui/react
'
;
import
TrialConfigPanel
from
'
./TrialConfigPanel
'
;
import
'
../../../static/style/overview/config.scss
'
;
export
const
TrialConfigButton
=
():
any
=>
{
const
[
isShowConfigPanel
,
setShowConfigPanle
]
=
useState
(
false
);
const
[
activeTab
,
setActiveTab
]
=
useState
(
'
1
'
);
const
hideConfigPanel
=
useCallback
(()
=>
setShowConfigPanle
(
false
),
[]);
const
showTrialConfigpPanel
=
useCallback
(()
=>
{
setShowConfigPanle
(
true
);
setActiveTab
(
'
config
'
);
},
[]);
const
showSearchSpacePanel
=
useCallback
(()
=>
{
setShowConfigPanle
(
true
);
setActiveTab
(
'
search space
'
);
},
[]);
return
(
<
React
.
Fragment
>
<
Stack
className
=
'config'
>
<
DefaultButton
text
=
'Config'
onClick
=
{
showTrialConfigpPanel
}
/>
<
DefaultButton
text
=
'Search space'
onClick
=
{
showSearchSpacePanel
}
/>
</
Stack
>
{
isShowConfigPanel
&&
<
TrialConfigPanel
hideConfigPanel
=
{
hideConfigPanel
}
activeTab
=
{
activeTab
}
/>
}
</
React
.
Fragment
>
);
};
src/webui/src/components/public-child/config/TrialConfigPanel.tsx
0 → 100644
View file @
1cd7ad5f
import
*
as
React
from
'
react
'
;
import
{
Stack
,
Panel
,
Pivot
,
PivotItem
,
PrimaryButton
}
from
'
@fluentui/react
'
;
import
{
EXPERIMENT
}
from
'
../../../static/datamodel
'
;
import
MonacoEditor
from
'
react-monaco-editor
'
;
import
{
MONACO
}
from
'
../../../static/const
'
;
import
{
convertDuration
}
from
'
../../../static/function
'
;
import
{
prettyStringify
}
from
'
../../../static/json_util
'
;
import
lodash
from
'
lodash
'
;
import
'
../../../static/style/logDrawer.scss
'
;
interface
LogDrawerProps
{
hideConfigPanel
:
()
=>
void
;
activeTab
?:
string
;
}
interface
LogDrawerState
{
panelInnerHeight
:
number
;
}
class
TrialConfigPanel
extends
React
.
Component
<
LogDrawerProps
,
LogDrawerState
>
{
constructor
(
props
:
LogDrawerProps
)
{
super
(
props
);
this
.
state
=
{
panelInnerHeight
:
window
.
innerHeight
};
}
setLogDrawerHeight
():
void
{
this
.
setState
(()
=>
({
panelInnerHeight
:
window
.
innerHeight
}));
}
async
componentDidMount
():
Promise
<
void
>
{
window
.
addEventListener
(
'
resize
'
,
this
.
setLogDrawerHeight
);
}
componentWillUnmount
():
void
{
window
.
removeEventListener
(
'
resize
'
,
this
.
setLogDrawerHeight
);
}
render
():
React
.
ReactNode
{
const
{
hideConfigPanel
,
activeTab
}
=
this
.
props
;
const
{
panelInnerHeight
}
=
this
.
state
;
// [marginTop 16px] + [Search space 46px] +
// button[height: 32px, marginTop: 45px, marginBottom: 25px] + [padding-bottom: 20px]
const
monacoEditorHeight
=
panelInnerHeight
-
184
;
const
blacklist
=
[
'
id
'
,
'
logDir
'
,
'
startTime
'
,
'
endTime
'
,
'
experimentName
'
,
'
searchSpace
'
,
'
trainingServicePlatform
'
];
const
filter
=
(
key
:
string
,
val
:
any
):
any
=>
{
return
blacklist
.
includes
(
key
)
?
undefined
:
val
;
};
const
profile
=
lodash
.
cloneDeep
(
EXPERIMENT
.
profile
);
profile
.
execDuration
=
convertDuration
(
profile
.
execDuration
);
profile
.
params
.
maxExecDuration
=
convertDuration
(
profile
.
params
.
maxExecDuration
);
const
showProfile
=
JSON
.
stringify
(
profile
,
filter
,
2
);
return
(
<
Stack
>
<
Panel
isOpen
=
{
true
}
hasCloseButton
=
{
false
}
isFooterAtBottom
=
{
true
}
isLightDismiss
=
{
true
}
onLightDismissClick
=
{
hideConfigPanel
}
>
<
div
className
=
'log-tab-body'
>
<
Pivot
initialSelectedKey
=
{
activeTab
}
style
=
{
{
minHeight
:
190
,
paddingTop
:
'
16px
'
}
}
>
<
PivotItem
headerText
=
'Search space'
itemKey
=
'search space'
>
<
MonacoEditor
height
=
{
monacoEditorHeight
}
language
=
'json'
theme
=
'vs-light'
value
=
{
prettyStringify
(
EXPERIMENT
.
searchSpace
,
300
,
2
)
}
options
=
{
MONACO
}
/>
</
PivotItem
>
<
PivotItem
headerText
=
'Config'
itemKey
=
'config'
>
<
div
className
=
'profile'
>
<
MonacoEditor
width
=
'100%'
height
=
{
monacoEditorHeight
}
language
=
'json'
theme
=
'vs-light'
value
=
{
showProfile
}
options
=
{
MONACO
}
/>
</
div
>
</
PivotItem
>
</
Pivot
>
</
div
>
<
PrimaryButton
text
=
'Close'
className
=
'configClose'
onClick
=
{
hideConfigPanel
}
/>
</
Panel
>
</
Stack
>
);
}
}
export
default
TrialConfigPanel
;
src/webui/src/components/stateless-component/NNItabs.tsx
View file @
1cd7ad5f
...
...
@@ -15,7 +15,7 @@ const DETAILTABS = (
const
NNILOGO
=
(
<
NavLink
to
=
{
'
/oview
'
}
>
<
img
src
=
{
require
(
'
../../static/img/logo
2
.png
'
)
}
alt
=
'NNI logo'
style
=
{
{
height
:
40
}
}
/>
<
img
src
=
{
require
(
'
../../static/img/logo.png
'
)
}
alt
=
'NNI logo'
style
=
{
{
height
:
40
}
}
/>
</
NavLink
>
);
...
...
src/webui/src/components/trial-detail/TableList.tsx
View file @
1cd7ad5f
...
...
@@ -23,7 +23,7 @@ import { MANAGER_IP, COLUMNPro } from '../../static/const';
import
{
convertDuration
,
formatTimestamp
,
intermediateGraphOption
,
parseMetrics
}
from
'
../../static/function
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
TableRecord
,
TrialJobInfo
}
from
'
../../static/interface
'
;
const
Details
=
lazy
(()
=>
import
(
'
../overview/Details
'
));
const
Details
=
lazy
(()
=>
import
(
'
../overview/
table/
Details
'
));
const
ChangeColumnComponent
=
lazy
(()
=>
import
(
'
../modals/ChangeColumnComponent
'
));
const
Compare
=
lazy
(()
=>
import
(
'
../modals/Compare
'
));
const
KillJob
=
lazy
(()
=>
import
(
'
../modals/Killjob
'
));
...
...
src/webui/src/index.tsx
View file @
1cd7ad5f
...
...
@@ -5,13 +5,20 @@ import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-d
const
Overview
=
lazy
(()
=>
import
(
'
./components/Overview
'
));
const
TrialsDetail
=
lazy
(()
=>
import
(
'
./components/TrialsDetail
'
));
import
'
./index.css
'
;
import
'
./static/style/loading.scss
'
;
import
*
as
serviceWorker
from
'
./serviceWorker
'
;
ReactDOM
.
render
(
<
Router
>
<
App
>
<
Switch
>
<
Suspense
fallback
=
{
null
}
>
<
Suspense
fallback
=
{
<
div
className
=
'loading'
>
<
img
src
=
{
require
(
'
./static/img/loading.gif
'
)
}
/>
</
div
>
}
>
<
Route
path
=
'/oview'
component
=
{
Overview
}
/>
<
Route
path
=
'/detail'
component
=
{
TrialsDetail
}
/>
<
Route
path
=
'/'
render
=
{
():
React
.
ReactNode
=>
<
Redirect
to
=
{
{
pathname
:
'
/oview
'
}
}
/>
}
/>
...
...
src/webui/src/static/const.ts
View file @
1cd7ad5f
...
...
@@ -15,7 +15,7 @@ const trialJobStatus = [
'
SYS_CANCELED
'
,
'
EARLY_STOPPED
'
];
const
CONTROLTYPE
=
[
'
SEARCH_SPACE
'
,
'
TRIAL_CONCURRENCY
'
,
'
MAX_EXEC_DURATION
'
];
const
CONTROLTYPE
=
[
'
MAX_EXEC_DURATION
'
,
'
MAX_TRIAL_NUM
'
,
'
TRIAL_CONCURRENCY
'
,
'
SEARCH_SPACE
'
];
const
MONACO
=
{
readOnly
:
true
,
automaticLayout
:
true
,
...
...
src/webui/src/static/function.ts
View file @
1cd7ad5f
...
...
@@ -29,25 +29,53 @@ const convertTime = (num: number): string => {
}
};
const
convertTimeToSecond
=
(
str
:
string
):
number
=>
{
let
seconds
=
0
;
let
d
,
h
,
m
;
if
(
str
.
includes
(
'
d
'
))
{
[
d
,
str
]
=
str
.
split
(
'
d
'
);
seconds
+=
parseInt
(
d
)
*
24
*
3600
;
}
if
(
str
.
includes
(
'
h
'
))
{
[
h
,
str
]
=
str
.
split
(
'
h
'
);
seconds
+=
parseInt
(
h
)
*
3600
;
}
if
(
str
.
includes
(
'
m
'
))
{
[
m
,
str
]
=
str
.
split
(
'
m
'
);
seconds
+=
parseInt
(
m
)
*
60
;
}
if
(
str
)
{
seconds
+=
parseInt
(
str
.
split
(
'
s
'
)[
0
]);
}
return
seconds
;
};
// trial's duration, accurate to seconds for example 10min 30s
const
convertDuration
=
(
num
:
number
):
string
=>
{
if
(
num
<
1
)
{
return
'
0s
'
;
const
convertDuration
=
(
seconds
:
number
):
string
=>
{
let
str
=
''
;
const
d
=
Math
.
floor
(
seconds
/
(
24
*
3600
));
if
(
d
>
0
)
{
str
+=
`
${
d
}
d `
;
}
const
hour
=
Math
.
floor
(
num
/
3600
);
const
minute
=
Math
.
floor
((
num
/
60
)
%
60
);
const
second
=
Math
.
floor
(
num
%
60
);
const
result
:
string
[]
=
[];
if
(
hour
>
0
)
{
result
.
push
(
`
${
hour
}
h`
);
seconds
-=
d
*
24
*
3600
;
const
h
=
Math
.
floor
(
seconds
/
3600
);
if
(
h
>
0
)
{
str
+=
`
${
h
}
h `
;
}
if
(
minute
>
0
)
{
result
.
push
(
`
${
minute
}
min`
);
seconds
-=
h
*
3600
;
const
m
=
Math
.
floor
(
seconds
/
60
);
if
(
m
>
0
)
{
str
+=
`
${
m
}
m `
;
}
if
(
second
>
0
)
{
result
.
push
(
`
${
second
}
s`
);
seconds
-=
m
*
60
;
if
(
seconds
>
0
)
{
str
+=
`
${
Math
.
floor
(
seconds
)}
s`
;
}
return
result
.
join
(
'
'
)
;
return
str
?
str
:
'
0s
'
;
};
function
parseMetrics
(
metricData
:
string
):
any
{
...
...
@@ -246,6 +274,7 @@ function formatComplexTypeValue(value: any): string | number {
export
{
convertTime
,
convertDuration
,
convertTimeToSecond
,
getFinalResult
,
getFinal
,
downFile
,
...
...
src/webui/src/static/img/icon/1.png
deleted
100644 → 0
View file @
0a6c234a
626 Bytes
src/webui/src/static/img/icon/10.png
deleted
100644 → 0
View file @
0a6c234a
2.57 KB
src/webui/src/static/img/icon/11.png
deleted
100644 → 0
View file @
0a6c234a
1.01 KB
src/webui/src/static/img/icon/2.png
deleted
100644 → 0
View file @
0a6c234a
323 Bytes
src/webui/src/static/img/icon/3.png
deleted
100644 → 0
View file @
0a6c234a
324 Bytes
src/webui/src/static/img/icon/4.png
deleted
100644 → 0
View file @
0a6c234a
400 Bytes
src/webui/src/static/img/icon/5.png
deleted
100644 → 0
View file @
0a6c234a
647 Bytes
Prev
1
2
3
4
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