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
744885eb
Commit
744885eb
authored
Nov 01, 2018
by
Lijiao
Committed by
chicm-ms
Nov 01, 2018
Browse files
Update WebUI (#295)
parent
c5c0fa2e
Changes
67
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1010 additions
and
436 deletions
+1010
-436
src/webui/config-overrides.js
src/webui/config-overrides.js
+1
-22
src/webui/images.d.ts
src/webui/images.d.ts
+3
-0
src/webui/package-lock.json
src/webui/package-lock.json
+0
-193
src/webui/package.json
src/webui/package.json
+11
-11
src/webui/public/favicon.ico
src/webui/public/favicon.ico
+0
-0
src/webui/public/icon.png
src/webui/public/icon.png
+0
-0
src/webui/public/index.html
src/webui/public/index.html
+2
-0
src/webui/public/manifest.json
src/webui/public/manifest.json
+15
-0
src/webui/src/App.css
src/webui/src/App.css
+22
-20
src/webui/src/App.tsx
src/webui/src/App.tsx
+14
-10
src/webui/src/components/Accuracy.tsx
src/webui/src/components/Accuracy.tsx
+0
-136
src/webui/src/components/Control.tsx
src/webui/src/components/Control.tsx
+2
-2
src/webui/src/components/Overview.tsx
src/webui/src/components/Overview.tsx
+435
-0
src/webui/src/components/SlideBar.tsx
src/webui/src/components/SlideBar.tsx
+15
-40
src/webui/src/components/Tensor.tsx
src/webui/src/components/Tensor.tsx
+2
-2
src/webui/src/components/TrialsDetail.tsx
src/webui/src/components/TrialsDetail.tsx
+218
-0
src/webui/src/components/overview/Accuracy.tsx
src/webui/src/components/overview/Accuracy.tsx
+43
-0
src/webui/src/components/overview/BasicInfo.tsx
src/webui/src/components/overview/BasicInfo.tsx
+76
-0
src/webui/src/components/overview/Progress.tsx
src/webui/src/components/overview/Progress.tsx
+103
-0
src/webui/src/components/overview/ProgressItem.tsx
src/webui/src/components/overview/ProgressItem.tsx
+48
-0
No files found.
src/webui/config-overrides.js
View file @
744885eb
const
tsImportPluginFactory
=
require
(
'
ts-import-plugin
'
)
const
{
getLoader
}
=
require
(
"
react-app-rewired
"
);
module
.
exports
=
function
override
(
config
,
env
)
{
module
.
exports
=
function
override
(
config
,
env
)
{
const
tsLoader
=
getLoader
(
config
.
module
.
rules
,
rule
=>
rule
.
loader
&&
typeof
rule
.
loader
===
'
string
'
&&
rule
.
loader
.
includes
(
'
ts-loader
'
)
);
tsLoader
.
options
=
{
getCustomTransformers
:
()
=>
({
before
:
[
tsImportPluginFactory
({
libraryName
:
'
antd
'
,
libraryDirectory
:
'
es
'
,
style
:
'
css
'
,
})
]
})
};
return
config
;
return
config
;
}
};
\ No newline at end of file
\ No newline at end of file
src/webui/images.d.ts
0 → 100644
View file @
744885eb
declare
module
'
*.svg
'
declare
module
'
*.png
'
declare
module
'
*.jpg
'
src/webui/package-lock.json
deleted
100644 → 0
View file @
c5c0fa2e
{
"name"
:
"my-app"
,
"version"
:
"0.1.0"
,
"lockfileVersion"
:
1
,
"requires"
:
true
,
"dependencies"
:
{
"asap"
:
{
"version"
:
"2.0.6"
,
"resolved"
:
"https://registry.npmjs.org/asap/-/asap-2.0.6.tgz"
,
"integrity"
:
"sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
},
"base16"
:
{
"version"
:
"1.0.0"
,
"resolved"
:
"https://registry.npmjs.org/base16/-/base16-1.0.0.tgz"
,
"integrity"
:
"sha1-4pf2DX7BAUp6lxo568ipjAtoHnA="
},
"core-js"
:
{
"version"
:
"1.2.7"
,
"resolved"
:
"https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz"
,
"integrity"
:
"sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
},
"encoding"
:
{
"version"
:
"0.1.12"
,
"resolved"
:
"https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz"
,
"integrity"
:
"sha1-U4tm8+5izRq1HsMjgp0flIDHS+s="
,
"requires"
:
{
"iconv-lite"
:
"0.4.21"
}
},
"fbemitter"
:
{
"version"
:
"2.1.1"
,
"resolved"
:
"https://registry.npmjs.org/fbemitter/-/fbemitter-2.1.1.tgz"
,
"integrity"
:
"sha1-Uj4U/a9SSIBbsC9i78M75wP1GGU="
,
"requires"
:
{
"fbjs"
:
"0.8.16"
}
},
"fbjs"
:
{
"version"
:
"0.8.16"
,
"resolved"
:
"https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz"
,
"integrity"
:
"sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s="
,
"requires"
:
{
"core-js"
:
"1.2.7"
,
"isomorphic-fetch"
:
"2.2.1"
,
"loose-envify"
:
"1.3.1"
,
"object-assign"
:
"4.1.1"
,
"promise"
:
"7.3.1"
,
"setimmediate"
:
"1.0.5"
,
"ua-parser-js"
:
"0.7.17"
}
},
"flux"
:
{
"version"
:
"3.1.3"
,
"resolved"
:
"https://registry.npmjs.org/flux/-/flux-3.1.3.tgz"
,
"integrity"
:
"sha1-0jvtUVp5oi2TOrU6tK2hnQWy8Io="
,
"requires"
:
{
"fbemitter"
:
"2.1.1"
,
"fbjs"
:
"0.8.16"
}
},
"iconv-lite"
:
{
"version"
:
"0.4.21"
,
"resolved"
:
"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz"
,
"integrity"
:
"sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw=="
,
"requires"
:
{
"safer-buffer"
:
"2.1.2"
}
},
"is-stream"
:
{
"version"
:
"1.1.0"
,
"resolved"
:
"https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz"
,
"integrity"
:
"sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"isomorphic-fetch"
:
{
"version"
:
"2.2.1"
,
"resolved"
:
"https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz"
,
"integrity"
:
"sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk="
,
"requires"
:
{
"node-fetch"
:
"1.7.3"
,
"whatwg-fetch"
:
"2.0.4"
}
},
"js-tokens"
:
{
"version"
:
"3.0.2"
,
"resolved"
:
"https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz"
,
"integrity"
:
"sha1-mGbfOVECEw449/mWvOtlRDIJwls="
},
"lodash.curry"
:
{
"version"
:
"4.1.1"
,
"resolved"
:
"https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz"
,
"integrity"
:
"sha1-JI42By7ekGUB11lmIAqG2riyMXA="
},
"lodash.flow"
:
{
"version"
:
"3.5.0"
,
"resolved"
:
"https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz"
,
"integrity"
:
"sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o="
},
"loose-envify"
:
{
"version"
:
"1.3.1"
,
"resolved"
:
"https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz"
,
"integrity"
:
"sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg="
,
"requires"
:
{
"js-tokens"
:
"3.0.2"
}
},
"node-fetch"
:
{
"version"
:
"1.7.3"
,
"resolved"
:
"https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz"
,
"integrity"
:
"sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ=="
,
"requires"
:
{
"encoding"
:
"0.1.12"
,
"is-stream"
:
"1.1.0"
}
},
"object-assign"
:
{
"version"
:
"4.1.1"
,
"resolved"
:
"https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
,
"integrity"
:
"sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"promise"
:
{
"version"
:
"7.3.1"
,
"resolved"
:
"https://registry.npmjs.org/promise/-/promise-7.3.1.tgz"
,
"integrity"
:
"sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="
,
"requires"
:
{
"asap"
:
"2.0.6"
}
},
"prop-types"
:
{
"version"
:
"15.6.1"
,
"resolved"
:
"https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz"
,
"integrity"
:
"sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ=="
,
"requires"
:
{
"fbjs"
:
"0.8.16"
,
"loose-envify"
:
"1.3.1"
,
"object-assign"
:
"4.1.1"
}
},
"pure-color"
:
{
"version"
:
"1.3.0"
,
"resolved"
:
"https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz"
,
"integrity"
:
"sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4="
},
"react-base16-styling"
:
{
"version"
:
"0.5.3"
,
"resolved"
:
"https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.5.3.tgz"
,
"integrity"
:
"sha1-OFjyTpxN2MvT9wLz901YHKKRcmk="
,
"requires"
:
{
"base16"
:
"1.0.0"
,
"lodash.curry"
:
"4.1.1"
,
"lodash.flow"
:
"3.5.0"
,
"pure-color"
:
"1.3.0"
}
},
"react-json-view"
:
{
"version"
:
"1.16.1"
,
"resolved"
:
"https://registry.npmjs.org/react-json-view/-/react-json-view-1.16.1.tgz"
,
"integrity"
:
"sha512-9gx2S+b9+LHbjnIzIXrcDU14YI5KP3hhDgNHrQiLsV3dtnzoT8m6j37h7dpCaO1hPLZEc3Q/6VS1QjiLi0HT/w=="
,
"requires"
:
{
"flux"
:
"3.1.3"
,
"react-base16-styling"
:
"0.5.3"
,
"react-textarea-autosize"
:
"5.2.1"
}
},
"react-textarea-autosize"
:
{
"version"
:
"5.2.1"
,
"resolved"
:
"https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-5.2.1.tgz"
,
"integrity"
:
"sha512-bx6z2I35aapr71ggw2yZIA4qhmqeTa4ZVsSaTeFvtf9kfcZppDBh2PbMt8lvbdmzEk7qbSFhAxR9vxEVm6oiMg=="
,
"requires"
:
{
"prop-types"
:
"15.6.1"
}
},
"safer-buffer"
:
{
"version"
:
"2.1.2"
,
"resolved"
:
"https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
,
"integrity"
:
"sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"setimmediate"
:
{
"version"
:
"1.0.5"
,
"resolved"
:
"https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz"
,
"integrity"
:
"sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
},
"ua-parser-js"
:
{
"version"
:
"0.7.17"
,
"resolved"
:
"https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz"
,
"integrity"
:
"sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g=="
},
"whatwg-fetch"
:
{
"version"
:
"2.0.4"
,
"resolved"
:
"https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz"
,
"integrity"
:
"sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
}
}
}
src/webui/package.json
View file @
744885eb
...
@@ -9,24 +9,24 @@
...
@@ -9,24 +9,24 @@
"echarts"
:
"^4.1.0"
,
"echarts"
:
"^4.1.0"
,
"echarts-for-react"
:
"^2.0.14"
,
"echarts-for-react"
:
"^2.0.14"
,
"react"
:
"^16.4.2"
,
"react"
:
"^16.4.2"
,
"react-app-rewired"
:
"^1.5.2"
,
"react-dom"
:
"^16.4.2"
,
"react-dom"
:
"^16.4.2"
,
"react-json-tree"
:
"^0.11.0"
,
"react-json-tree"
:
"^0.11.0"
,
"react-router"
:
"3.2.1"
"react-router"
:
"3.2.1"
,
"react-scripts-ts-antd"
:
"2.17.0"
},
},
"scripts"
:
{
"scripts"
:
{
"start"
:
"react-
app-rewired start --scripts-version react-scripts-ts
"
,
"start"
:
"react-
scripts-ts-antd start
"
,
"build"
:
"react-
app-rewired build --scripts-version react-scripts-ts
"
,
"build"
:
"react-
scripts-ts-antd build
"
,
"test"
:
"react-
app-rewire
d test --env=jsdom
--scripts-version react-scripts-ts
"
,
"test"
:
"react-
scripts-ts-ant
d test --env=jsdom"
,
"eject"
:
"react-scripts-ts eject"
"eject"
:
"react-scripts-ts
-antd
eject"
},
},
"devDependencies"
:
{
"devDependencies"
:
{
"@types/jest"
:
"^23.3.5"
,
"@types/node"
:
"^10.7.0"
,
"@types/node"
:
"^10.7.0"
,
"@types/react-router"
:
"3.0.15"
,
"@types/react"
:
"^16.4.17"
,
"@types/react-json-tree"
:
"^0.6.8"
,
"@types/react-dom"
:
"^16.0.7"
,
"@types/react-dom"
:
"^16.0.7"
,
"
react-scripts-ts"
:
"^2.17.0
"
,
"
@types/react-json-tree"
:
"^0.6.8
"
,
"
ts-import-plugin"
:
"^1.5.4
"
,
"
@types/react-router"
:
"3.0.15
"
,
"typescript"
:
"^3.0.1"
"typescript"
:
"^3.0.1"
}
}
}
}
\ No newline at end of file
src/webui/public/favicon.ico
0 → 100644
View file @
744885eb
3.78 KB
src/webui/public/icon.png
0 → 100644
View file @
744885eb
29.9 KB
src/webui/public/index.html
View file @
744885eb
...
@@ -5,6 +5,8 @@
...
@@ -5,6 +5,8 @@
<meta
charset=
"utf-8"
>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1, shrink-to-fit=no"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1, shrink-to-fit=no"
>
<title>
Neural Network Intelligence
</title>
<title>
Neural Network Intelligence
</title>
<link
rel=
"manifest"
href=
"%PUBLIC_URL%/manifest.json"
>
<link
rel=
"shortcut icon"
href=
"%PUBLIC_URL%/icon.png"
>
</head>
</head>
<body>
<body>
...
...
src/webui/public/manifest.json
0 → 100644
View file @
744885eb
{
"short_name"
:
"React App"
,
"name"
:
"Create React App Sample"
,
"icons"
:
[
{
"src"
:
"favicon.ico"
,
"sizes"
:
"64x64 32x32 24x24 16x16"
,
"type"
:
"image/x-icon"
}
],
"start_url"
:
"./index.html"
,
"display"
:
"standalone"
,
"theme_color"
:
"#000000"
,
"background_color"
:
"#ffffff"
}
\ No newline at end of file
src/webui/src/App.css
View file @
744885eb
.header_title
{
.nni
{
width
:
100%
;
font-family
:
'Segoe'
;
height
:
60px
;
color
:
#212121
;
line-height
:
60px
;
font-size
:
14px
;
font-size
:
24px
;
}
font-family
:
'Segoe UI'
,
Tahoma
,
Geneva
,
Verdana
,
sans-serif
;
color
:
white
;
.header
{
background-color
:
rgb
(
60
,
141
,
188
)
;
user-select
:
none
;
text-align
:
center
;
position
:
fixed
;
position
:
fixed
;
left
:
0
;
left
:
0
;
top
:
0
;
top
:
0
;
z-index
:
999
;
width
:
100%
;
height
:
80px
;
background
:
#0071BC
;
border-right
:
1px
solid
#ccc
;
z-index
:
1000
;
}
}
.header
_title
img
{
.header
Con
{
height
:
60px
;
min-width
:
60
0
px
}
}
.right
{
.content
{
position
:
absolute
;
width
:
86%
;
left
:
250px
;
min-width
:
1024px
;
top
:
50px
;
margin
:
0
auto
;
width
:
calc
(
100%
-
250px
);
margin-top
:
90px
;
/* padding-left: 20px; */
margin-bottom
:
30px
;
/* background: rgb(236,240,245); */
}
}
src/webui/src/App.tsx
View file @
744885eb
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Row
,
Col
}
from
'
antd
'
;
import
'
./App.css
'
;
import
'
./App.css
'
;
import
SlideBar
from
'
./components/SlideBar
'
;
import
SlideBar
from
'
./components/SlideBar
'
;
class
App
extends
React
.
Component
<
{},
{}
>
{
class
App
extends
React
.
Component
<
{},
{}
>
{
render
()
{
render
()
{
return
(
return
(
<
div
className
=
"App"
>
<
Row
className
=
"nni"
>
{
/* <header className="header_title"><img src={require('./logo.jpg')} alt=""/></header> */
}
<
Row
className
=
"header"
>
<
header
className
=
"header_title"
>
Neural Network Intelligence
</
header
>
<
Col
span
=
{
2
}
/>
<
div
className
=
"content"
>
<
Col
className
=
"headerCon"
span
=
{
22
}
>
<
SlideBar
/>
<
SlideBar
/>
<
div
className
=
"right"
>
{
this
.
props
.
children
}
</
div
>
</
Col
>
</
div
>
</
Row
>
</
div
>
<
Row
className
=
"content"
>
{
this
.
props
.
children
}
</
Row
>
</
Row
>
);
);
}
}
}
}
...
...
src/webui/src/components/Accuracy.tsx
deleted
100644 → 0
View file @
c5c0fa2e
import
*
as
React
from
'
react
'
;
import
axios
from
'
axios
'
;
import
{
MANAGER_IP
}
from
'
../const
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
const
echarts
=
require
(
'
echarts/lib/echarts
'
);
echarts
.
registerTheme
(
'
my_theme
'
,
{
color
:
'
#3c8dbc
'
});
require
(
'
echarts/lib/chart/scatter
'
);
require
(
'
echarts/lib/component/tooltip
'
);
require
(
'
echarts/lib/component/title
'
);
require
(
'
../style/accuracy.css
'
);
const
accStyle
=
{
width
:
'
100%
'
,
height
:
600
,
margin
:
'
0 auto
'
};
interface
ChartState
{
option
:
object
;
accNodata
:
string
;
}
interface
AccurPoint
{
yAxis
:
Array
<
number
>
;
}
class
Accuracy
extends
React
.
Component
<
{},
ChartState
>
{
public
_isMounted
=
false
;
public
intervalID
=
0
;
constructor
(
props
:
{})
{
super
(
props
);
this
.
state
=
{
option
:
{},
accNodata
:
''
};
}
getOption
=
(
dataObj
:
AccurPoint
)
=>
{
const
yAxis
=
dataObj
.
yAxis
;
const
xAxis
:
Array
<
number
>
=
[];
for
(
let
i
=
1
;
i
<=
yAxis
.
length
;
i
++
)
{
xAxis
.
push
(
i
);
}
return
{
tooltip
:
{
trigger
:
'
item
'
},
xAxis
:
{
name
:
'
Trial
'
,
type
:
'
category
'
,
data
:
xAxis
},
yAxis
:
{
name
:
'
Accuracy
'
,
type
:
'
value
'
,
data
:
yAxis
},
series
:
[{
symbolSize
:
6
,
type
:
'
scatter
'
,
data
:
yAxis
}]
};
}
drawPointGraph
=
()
=>
{
axios
(
`
${
MANAGER_IP
}
/trial-jobs`
,
{
method
:
'
GET
'
})
.
then
(
res
=>
{
if
(
res
.
status
===
200
&&
this
.
_isMounted
)
{
const
accData
=
res
.
data
;
const
accArr
:
Array
<
number
>
=
[];
const
accY
:
Array
<
AccurPoint
>
=
[];
Object
.
keys
(
accData
).
map
(
item
=>
{
if
(
accData
[
item
].
status
===
'
SUCCEEDED
'
&&
accData
[
item
].
finalMetricData
)
{
accArr
.
push
(
parseFloat
(
accData
[
item
].
finalMetricData
.
data
));
}
});
accY
.
push
({
yAxis
:
accArr
});
let
optionObj
=
this
.
getOption
(
accY
[
0
]);
this
.
setState
({
option
:
optionObj
},
()
=>
{
if
(
accArr
.
length
===
0
)
{
this
.
setState
({
accNodata
:
'
No data
'
});
}
else
{
this
.
setState
({
accNodata
:
''
});
}
});
}
});
}
componentDidMount
()
{
this
.
_isMounted
=
true
;
this
.
drawPointGraph
();
this
.
intervalID
=
window
.
setInterval
(
this
.
drawPointGraph
,
10000
);
}
componentWillUnmount
()
{
this
.
_isMounted
=
false
;
window
.
clearInterval
(
this
.
intervalID
);
}
render
()
{
const
{
accNodata
,
option
}
=
this
.
state
;
return
(
<
div
className
=
"graph"
>
<
div
className
=
"trial"
>
<
div
className
=
"title"
>
<
div
>
Trial Accuracy
</
div
>
</
div
>
<
div
>
<
ReactEcharts
option
=
{
option
}
style
=
{
accStyle
}
theme
=
"my_theme"
/>
<
div
className
=
"showMess"
>
{
accNodata
}
</
div
>
</
div
>
</
div
>
</
div
>
);
}
}
export
default
Accuracy
;
\ No newline at end of file
src/webui/src/components/Control.tsx
View file @
744885eb
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Input
,
Button
,
message
}
from
'
antd
'
;
import
{
Input
,
Button
,
message
}
from
'
antd
'
;
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
;
import
{
MANAGER_IP
,
CONTROLTYPE
}
from
'
../const
'
;
import
{
MANAGER_IP
,
CONTROLTYPE
}
from
'
../
static/
const
'
;
const
{
TextArea
}
=
Input
;
const
{
TextArea
}
=
Input
;
import
'
../style/control.css
'
;
import
'
../
static/
style/control.
s
css
'
;
interface
ExperimentParams
{
interface
ExperimentParams
{
authorName
:
string
;
authorName
:
string
;
...
...
src/webui/src/components/
Sessionpro
.tsx
→
src/webui/src/components/
Overview
.tsx
View file @
744885eb
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
;
import
{
Table
,
Select
,
Row
,
Col
,
Icon
,
Button
}
from
'
antd
'
;
import
{
Row
,
Col
}
from
'
antd
'
;
import
{
MANAGER_IP
,
overviewItem
}
from
'
../const
'
;
import
{
MANAGER_IP
,
overviewItem
}
from
'
../static/const
'
;
const
Option
=
Select
.
Option
;
import
{
import
JSONTree
from
'
react-json-tree
'
;
Experiment
,
TableObj
,
require
(
'
../style/sessionpro.css
'
);
Parameters
,
AccurPoint
,
TrialNumber
require
(
'
../style/logPath.css
'
);
}
from
'
../static/interface
'
;
import
{
getAccuracyData
}
from
'
../static/function
'
;
import
SuccessTable
from
'
./overview/SuccessTable
'
;
import
Title1
from
'
./overview/Title1
'
;
import
Progressed
from
'
./overview/Progress
'
;
import
Accuracy
from
'
./overview/Accuracy
'
;
import
SearchSpace
from
'
./overview/SearchSpace
'
;
import
BasicInfo
from
'
./overview/BasicInfo
'
;
import
TrialPro
from
'
./overview/TrialProfile
'
;
interface
ErrorPara
{
require
(
'
../static/style/overview.scss
'
);
error
?:
string
;
require
(
'
../static/style/logPath.scss
'
);
}
require
(
'
../static/style/accuracy.css
'
);
require
(
'
../static/style/table.scss
'
);
interface
TableObj
{
require
(
'
../static/style/overviewTitle.scss
'
);
key
:
number
;
id
:
string
;
duration
:
number
;
start
:
string
;
end
:
string
;
status
:
string
;
acc
?:
number
;
description
:
Parameters
;
}
interface
Parameters
{
parameters
:
ErrorPara
;
logPath
?:
string
;
isLink
?:
boolean
;
}
interface
Experiment
{
id
:
string
;
author
:
string
;
experName
:
string
;
runConcurren
:
number
;
maxDuration
:
number
;
execDuration
:
number
;
MaxTrialNum
:
number
;
startTime
:
string
;
endTime
:
string
;
}
interface
SessionState
{
interface
SessionState
{
tableData
:
Array
<
TableObj
>
;
tableData
:
Array
<
TableObj
>
;
searchSpace
:
object
;
searchSpace
:
object
;
status
:
string
;
status
:
string
;
trialProfile
:
Experiment
;
trialProfile
:
Experiment
;
tunerAssessor
:
object
;
selNum
:
number
;
selNum
:
number
;
option
:
object
;
option
:
object
;
noData
:
string
;
noData
:
string
;
accuracyData
:
object
;
bestAccuracy
:
string
;
accNodata
:
string
;
trialNumber
:
TrialNumber
;
}
}
class
Sessionpro
extends
React
.
Component
<
{},
SessionState
>
{
class
Overview
extends
React
.
Component
<
{},
SessionState
>
{
public
_isMounted
=
false
;
public
_isMounted
=
false
;
public
intervalID
=
0
;
public
intervalID
=
0
;
public
intervalProfile
=
1
;
public
intervalProfile
=
1
;
public
intervalAccuracy
=
2
;
constructor
(
props
:
{})
{
constructor
(
props
:
{})
{
super
(
props
);
super
(
props
);
...
@@ -70,16 +57,15 @@ class Sessionpro extends React.Component<{}, SessionState> {
...
@@ -70,16 +57,15 @@ class Sessionpro extends React.Component<{}, SessionState> {
maxDuration
:
0
,
maxDuration
:
0
,
execDuration
:
0
,
execDuration
:
0
,
MaxTrialNum
:
0
,
MaxTrialNum
:
0
,
startTime
:
''
,
startTime
:
0
,
endTime
:
''
tuner
:
{},
trainingServicePlatform
:
''
},
},
tunerAssessor
:
{},
tableData
:
[{
tableData
:
[{
key
:
0
,
key
:
0
,
sequenceId
:
0
,
id
:
''
,
id
:
''
,
duration
:
0
,
duration
:
0
,
start
:
''
,
end
:
''
,
status
:
''
,
status
:
''
,
acc
:
0
,
acc
:
0
,
description
:
{
description
:
{
...
@@ -88,20 +74,23 @@ class Sessionpro extends React.Component<{}, SessionState> {
...
@@ -88,20 +74,23 @@ class Sessionpro extends React.Component<{}, SessionState> {
}],
}],
selNum
:
overviewItem
,
selNum
:
overviewItem
,
option
:
{},
option
:
{},
noData
:
''
noData
:
''
,
// accuracy
accuracyData
:
{},
accNodata
:
''
,
bestAccuracy
:
''
,
trialNumber
:
{
succTrial
:
0
,
failTrial
:
0
,
stopTrial
:
0
,
waitTrial
:
0
,
runTrial
:
0
,
unknowTrial
:
0
,
totalCurrentTrial
:
0
}
};
};
}
}
convertTime
=
(
num
:
number
)
=>
{
if
(
num
%
3600
===
0
)
{
return
num
/
3600
+
'
h
'
;
}
else
{
const
hour
=
Math
.
floor
(
num
/
3600
);
const
min
=
Math
.
floor
(
num
/
60
%
60
);
return
hour
>
0
?
`
${
hour
}
h
${
min
}
min`
:
`
${
min
}
min`
;
}
}
// show session
// show session
showSessionPro
=
()
=>
{
showSessionPro
=
()
=>
{
axios
(
`
${
MANAGER_IP
}
/experiment`
,
{
axios
(
`
${
MANAGER_IP
}
/experiment`
,
{
...
@@ -110,29 +99,28 @@ class Sessionpro extends React.Component<{}, SessionState> {
...
@@ -110,29 +99,28 @@ class Sessionpro extends React.Component<{}, SessionState> {
.
then
(
res
=>
{
.
then
(
res
=>
{
if
(
res
.
status
===
200
)
{
if
(
res
.
status
===
200
)
{
let
sessionData
=
res
.
data
;
let
sessionData
=
res
.
data
;
let
tunerAsstemp
=
[];
let
trialPro
=
[];
let
trialPro
=
[];
const
startExper
=
new
Date
(
sessionData
.
startTime
).
toLocaleString
(
'
en-US
'
);
const
trainingPlatform
=
sessionData
.
params
.
trainingServicePlatform
;
let
experEndStr
:
string
;
// assessor clusterMeteData
if
(
sessionData
.
endTime
!==
undefined
)
{
const
clusterMetaData
=
sessionData
.
params
.
clusterMetaData
;
experEndStr
=
new
Date
(
sessionData
.
endTime
).
toLocaleString
(
'
en-US
'
);
const
endTimenum
=
sessionData
.
endTime
;
}
else
{
const
assessor
=
sessionData
.
params
.
assessor
;
experEndStr
=
'
not over
'
;
}
trialPro
.
push
({
trialPro
.
push
({
id
:
sessionData
.
id
,
id
:
sessionData
.
id
,
author
:
sessionData
.
params
.
authorName
,
author
:
sessionData
.
params
.
authorName
,
revision
:
sessionData
.
revision
,
experName
:
sessionData
.
params
.
experimentName
,
experName
:
sessionData
.
params
.
experimentName
,
runConcurren
:
sessionData
.
params
.
trialConcurrency
,
runConcurren
:
sessionData
.
params
.
trialConcurrency
,
logDir
:
sessionData
.
logDir
?
sessionData
.
logDir
:
'
undefined
'
,
maxDuration
:
sessionData
.
params
.
maxExecDuration
,
maxDuration
:
sessionData
.
params
.
maxExecDuration
,
execDuration
:
sessionData
.
execDuration
,
execDuration
:
sessionData
.
execDuration
,
MaxTrialNum
:
sessionData
.
params
.
maxTrialNum
,
MaxTrialNum
:
sessionData
.
params
.
maxTrialNum
,
startTime
:
startExper
,
startTime
:
sessionData
.
startTime
,
endTime
:
experEndStr
endTime
:
endTimenum
?
endTimenum
:
undefined
,
});
trainingServicePlatform
:
trainingPlatform
,
tunerAsstemp
.
push
({
tuner
:
sessionData
.
params
.
tuner
,
tuner
:
sessionData
.
params
.
tuner
,
assessor
:
sessionData
.
params
.
assessor
assessor
:
assessor
?
assessor
:
undefined
,
clusterMetaData
:
clusterMetaData
?
clusterMetaData
:
undefined
});
});
// search space format loguniform max and min
// search space format loguniform max and min
const
searchSpace
=
JSON
.
parse
(
sessionData
.
params
.
searchSpace
);
const
searchSpace
=
JSON
.
parse
(
sessionData
.
params
.
searchSpace
);
...
@@ -161,8 +149,7 @@ class Sessionpro extends React.Component<{}, SessionState> {
...
@@ -161,8 +149,7 @@ class Sessionpro extends React.Component<{}, SessionState> {
if
(
this
.
_isMounted
)
{
if
(
this
.
_isMounted
)
{
this
.
setState
({
this
.
setState
({
trialProfile
:
trialPro
[
0
],
trialProfile
:
trialPro
[
0
],
searchSpace
:
searchSpace
,
searchSpace
:
searchSpace
tunerAssessor
:
tunerAsstemp
[
0
]
});
});
}
}
}
}
...
@@ -189,40 +176,69 @@ class Sessionpro extends React.Component<{}, SessionState> {
...
@@ -189,40 +176,69 @@ class Sessionpro extends React.Component<{}, SessionState> {
const
{
selNum
}
=
this
.
state
;
const
{
selNum
}
=
this
.
state
;
const
tableData
=
res
.
data
;
const
tableData
=
res
.
data
;
const
topTableData
:
Array
<
TableObj
>
=
[];
const
topTableData
:
Array
<
TableObj
>
=
[];
const
profile
:
TrialNumber
=
{
succTrial
:
0
,
failTrial
:
0
,
stopTrial
:
0
,
waitTrial
:
0
,
runTrial
:
0
,
unknowTrial
:
0
,
totalCurrentTrial
:
0
};
// currently totoal number
profile
.
totalCurrentTrial
=
tableData
.
length
;
Object
.
keys
(
tableData
).
map
(
item
=>
{
Object
.
keys
(
tableData
).
map
(
item
=>
{
if
(
tableData
[
item
].
status
===
'
SUCCEEDED
'
)
{
switch
(
tableData
[
item
].
status
)
{
const
desJobDetail
:
Parameters
=
{
case
'
WAITING
'
:
parameters
:
{}
profile
.
waitTrial
+=
1
;
};
break
;
const
startTime
=
new
Date
(
tableData
[
item
].
startTime
).
toLocaleString
(
'
en-US
'
);
const
endTime
=
new
Date
(
tableData
[
item
].
endTime
).
toLocaleString
(
'
en-US
'
);
case
'
UNKNOWN
'
:
const
duration
=
(
tableData
[
item
].
endTime
-
tableData
[
item
].
startTime
)
/
1000
;
profile
.
unknowTrial
+=
1
;
let
acc
;
break
;
if
(
tableData
[
item
].
finalMetricData
)
{
acc
=
parseFloat
(
tableData
[
item
].
finalMetricData
.
data
);
case
'
FAILED
'
:
}
profile
.
failTrial
+=
1
;
if
(
tableData
[
item
].
hyperParameters
)
{
break
;
desJobDetail
.
parameters
=
JSON
.
parse
(
tableData
[
item
].
hyperParameters
).
parameters
;
}
else
{
case
'
USER_CANCELED
'
:
desJobDetail
.
parameters
=
{
error
:
'
This trial
\'
s parameters are not available.
'
};
case
'
SYS_CANCELED
'
:
}
profile
.
stopTrial
+=
1
;
if
(
tableData
[
item
].
logPath
!==
undefined
)
{
break
;
desJobDetail
.
logPath
=
tableData
[
item
].
logPath
;
case
'
SUCCEEDED
'
:
const
isSessionLink
=
/^http/gi
.
test
(
tableData
[
item
].
logPath
);
profile
.
succTrial
+=
1
;
if
(
isSessionLink
)
{
const
desJobDetail
:
Parameters
=
{
desJobDetail
.
isLink
=
true
;
parameters
:
{}
};
const
duration
=
(
tableData
[
item
].
endTime
-
tableData
[
item
].
startTime
)
/
1000
;
let
acc
;
if
(
tableData
[
item
].
finalMetricData
)
{
acc
=
parseFloat
(
tableData
[
item
].
finalMetricData
.
data
);
}
}
}
// if hyperparameters is undefine, show error message, else, show parameters value
topTableData
.
push
({
if
(
tableData
[
item
].
hyperParameters
)
{
key
:
topTableData
.
length
,
desJobDetail
.
parameters
=
JSON
.
parse
(
tableData
[
item
].
hyperParameters
).
parameters
;
id
:
tableData
[
item
].
id
,
}
else
{
duration
:
duration
,
desJobDetail
.
parameters
=
{
error
:
'
This trial
\'
s parameters are not available.
'
};
start
:
startTime
,
}
end
:
endTime
,
if
(
tableData
[
item
].
logPath
!==
undefined
)
{
status
:
tableData
[
item
].
status
,
desJobDetail
.
logPath
=
tableData
[
item
].
logPath
;
acc
:
acc
,
const
isSessionLink
=
/^http/gi
.
test
(
tableData
[
item
].
logPath
);
description
:
desJobDetail
if
(
isSessionLink
)
{
});
desJobDetail
.
isLink
=
true
;
}
}
topTableData
.
push
({
key
:
topTableData
.
length
,
sequenceId
:
tableData
[
item
].
sequenceId
,
id
:
tableData
[
item
].
id
,
duration
:
duration
,
status
:
tableData
[
item
].
status
,
acc
:
acc
,
description
:
desJobDetail
});
break
;
default
:
}
}
});
});
topTableData
.
sort
((
a
:
TableObj
,
b
:
TableObj
)
=>
{
topTableData
.
sort
((
a
:
TableObj
,
b
:
TableObj
)
=>
{
...
@@ -235,41 +251,14 @@ class Sessionpro extends React.Component<{}, SessionState> {
...
@@ -235,41 +251,14 @@ class Sessionpro extends React.Component<{}, SessionState> {
topTableData
.
length
=
Math
.
min
(
selNum
,
topTableData
.
length
);
topTableData
.
length
=
Math
.
min
(
selNum
,
topTableData
.
length
);
if
(
this
.
_isMounted
)
{
if
(
this
.
_isMounted
)
{
this
.
setState
({
this
.
setState
({
tableData
:
topTableData
tableData
:
topTableData
,
trialNumber
:
profile
});
});
}
}
}
}
});
});
}
}
handleChange
=
(
value
:
string
)
=>
{
let
num
=
parseFloat
(
value
);
window
.
clearInterval
(
this
.
intervalID
);
if
(
this
.
_isMounted
)
{
this
.
setState
({
selNum
:
num
},
()
=>
{
this
.
showTrials
();
this
.
intervalID
=
window
.
setInterval
(
this
.
showTrials
,
10000
);
});
}
}
// trial's duration, accurate to seconds
convertDuration
=
(
num
:
number
)
=>
{
const
hour
=
Math
.
floor
(
num
/
3600
);
const
min
=
Math
.
floor
(
num
/
60
%
60
);
const
second
=
Math
.
floor
(
num
%
60
);
const
result
=
hour
>
0
?
`
${
hour
}
h
${
min
}
min
${
second
}
s`
:
`
${
min
}
min
${
second
}
s`
;
if
(
hour
<=
0
&&
min
===
0
&&
second
!==
0
)
{
return
`
${
second
}
s`
;
}
else
if
(
hour
===
0
&&
min
!==
0
&&
second
===
0
)
{
return
`
${
min
}
min`
;
}
else
if
(
hour
===
0
&&
min
!==
0
&&
second
!==
0
)
{
return
`
${
min
}
min
${
second
}
s`
;
}
else
{
return
result
;
}
}
downExperimentContent
=
()
=>
{
downExperimentContent
=
()
=>
{
axios
axios
.
all
([
.
all
([
...
@@ -319,9 +308,48 @@ class Sessionpro extends React.Component<{}, SessionState> {
...
@@ -319,9 +308,48 @@ class Sessionpro extends React.Component<{}, SessionState> {
}));
}));
}
}
// trial accuracy graph
drawPointGraph
=
()
=>
{
axios
(
`
${
MANAGER_IP
}
/trial-jobs`
,
{
method
:
'
GET
'
})
.
then
(
res
=>
{
if
(
res
.
status
===
200
&&
this
.
_isMounted
)
{
const
accData
=
res
.
data
;
const
accArr
:
Array
<
number
>
=
[];
const
accY
:
Array
<
AccurPoint
>
=
[];
Object
.
keys
(
accData
).
map
(
item
=>
{
if
(
accData
[
item
].
status
===
'
SUCCEEDED
'
&&
accData
[
item
].
finalMetricData
)
{
accArr
.
push
(
parseFloat
(
accData
[
item
].
finalMetricData
.
data
));
}
});
accArr
.
sort
((
a
,
b
)
=>
{
return
a
-
b
;
});
accArr
.
length
=
Math
.
min
(
10
,
accArr
.
length
);
accY
.
push
({
yAxis
:
accArr
});
let
optionObj
=
getAccuracyData
(
accY
[
0
]);
const
bestAccnum
=
Math
.
max
(...
accArr
);
this
.
setState
({
accuracyData
:
optionObj
},
()
=>
{
if
(
accArr
.
length
===
0
)
{
this
.
setState
({
accNodata
:
'
No data
'
});
}
else
{
this
.
setState
({
accNodata
:
''
,
bestAccuracy
:
bestAccnum
.
toFixed
(
6
)
});
}
});
}
});
}
componentDidMount
()
{
componentDidMount
()
{
this
.
showSessionPro
();
this
.
showSessionPro
();
this
.
showTrials
();
this
.
showTrials
();
this
.
drawPointGraph
();
this
.
intervalAccuracy
=
window
.
setInterval
(
this
.
drawPointGraph
,
10000
);
this
.
_isMounted
=
true
;
this
.
_isMounted
=
true
;
this
.
intervalID
=
window
.
setInterval
(
this
.
showTrials
,
10000
);
this
.
intervalID
=
window
.
setInterval
(
this
.
showTrials
,
10000
);
this
.
intervalProfile
=
window
.
setInterval
(
this
.
showSessionPro
,
60000
);
this
.
intervalProfile
=
window
.
setInterval
(
this
.
showSessionPro
,
60000
);
...
@@ -331,254 +359,77 @@ class Sessionpro extends React.Component<{}, SessionState> {
...
@@ -331,254 +359,77 @@ class Sessionpro extends React.Component<{}, SessionState> {
this
.
_isMounted
=
false
;
this
.
_isMounted
=
false
;
window
.
clearInterval
(
this
.
intervalID
);
window
.
clearInterval
(
this
.
intervalID
);
window
.
clearInterval
(
this
.
intervalProfile
);
window
.
clearInterval
(
this
.
intervalProfile
);
window
.
clearInterval
(
this
.
intervalAccuracy
);
}
}
render
()
{
render
()
{
// show better job details
let
bgColor
=
''
;
const
columns
=
[{
title
:
'
Id
'
,
dataIndex
:
'
id
'
,
key
:
'
id
'
,
width
:
150
,
className
:
'
tableHead
'
,
},
{
title
:
'
Duration
'
,
dataIndex
:
'
duration
'
,
key
:
'
duration
'
,
width
:
'
9%
'
,
sorter
:
(
a
:
TableObj
,
b
:
TableObj
)
=>
(
a
.
duration
as
number
)
-
(
b
.
duration
as
number
),
render
:
(
text
:
string
,
record
:
TableObj
)
=>
{
let
duration
;
if
(
record
.
duration
)
{
duration
=
this
.
convertDuration
(
record
.
duration
);
}
return
(
<
span
>
{
duration
}
</
span
>
);
},
},
{
title
:
'
Start
'
,
dataIndex
:
'
start
'
,
key
:
'
start
'
,
width
:
150
},
{
title
:
'
End
'
,
dataIndex
:
'
end
'
,
key
:
'
end
'
,
width
:
150
},
{
title
:
'
Status
'
,
dataIndex
:
'
status
'
,
key
:
'
status
'
,
width
:
150
,
className
:
'
tableStatus
'
,
render
:
(
text
:
string
,
record
:
TableObj
)
=>
{
bgColor
=
record
.
status
;
return
(
<
span
className
=
{
`
${
bgColor
}
commonStyle`
}
>
{
record
.
status
}
</
span
>
);
}
},
{
title
:
'
Loss/Accuracy
'
,
dataIndex
:
'
acc
'
,
key
:
'
acc
'
,
width
:
150
}];
const
openRow
=
(
record
:
TableObj
)
=>
{
let
isHasParameters
=
true
;
if
(
record
.
description
.
parameters
.
error
)
{
isHasParameters
=
false
;
}
const
openRowDataSource
=
{
parameters
:
record
.
description
.
parameters
};
let
isLogLink
:
boolean
=
false
;
const
logPathRow
=
record
.
description
.
logPath
;
if
(
record
.
description
.
isLink
!==
undefined
)
{
isLogLink
=
true
;
}
return
(
<
pre
id
=
"description"
className
=
"jsontree"
>
{
isHasParameters
?
<
JSONTree
hideRoot
=
{
true
}
shouldExpandNode
=
{
()
=>
true
}
// default expandNode
getItemString
=
{
()
=>
(<
span
/>)
}
// remove the {} items
data
=
{
openRowDataSource
}
/>
:
<
div
className
=
"logpath"
>
<
span
className
=
"logName"
>
Error:
</
span
>
<
span
className
=
"error"
>
'This trial's parameters are not available.'
</
span
>
</
div
>
}
{
isLogLink
?
<
div
className
=
"logpath"
>
<
span
className
=
"logName"
>
logPath:
</
span
>
<
a
className
=
"logContent logHref"
href
=
{
logPathRow
}
target
=
"_blank"
>
{
logPathRow
}
</
a
>
</
div
>
:
<
div
className
=
"logpath"
>
<
span
className
=
"logName"
>
logPath:
</
span
>
<
span
className
=
"logContent"
>
{
logPathRow
}
</
span
>
</
div
>
}
</
pre
>
);
};
const
{
const
{
trialProfile
,
searchSpace
,
tunerAssessor
,
tableData
,
status
trialProfile
,
searchSpace
,
tableData
,
accuracyData
,
accNodata
,
status
,
trialNumber
,
bestAccuracy
}
=
this
.
state
;
}
=
this
.
state
;
const
maxRuntime
=
this
.
convertTime
(
trialProfile
.
maxDuration
);
let
running
;
let
runningStr
=
''
;
if
(
trialProfile
.
endTime
===
'
not over
'
)
{
running
=
trialProfile
.
maxDuration
-
trialProfile
.
execDuration
;
runningStr
=
this
.
convertTime
(
running
);
}
else
{
runningStr
=
'
0
'
;
}
return
(
return
(
<
div
className
=
"session"
id
=
"session"
>
<
div
className
=
"overview"
>
<
div
className
=
"head"
>
{
/* status and experiment block */
}
<
div
className
=
"headCon"
>
<
Row
className
=
"basicExperiment"
>
<
div
className
=
"author"
>
<
Title1
text
=
"Experiment"
icon
=
"11.png"
/>
<
div
className
=
"message"
>
<
BasicInfo
trialProfile
=
{
trialProfile
}
status
=
{
status
}
/>
<
div
className
=
"proKey"
>
</
Row
>
<
span
>
Author:
</
span
>
<
Row
className
=
"overMessage"
>
<
span
className
=
"messcont"
>
{
trialProfile
.
author
}
</
span
>
{
/* status graph */
}
</
div
>
<
Col
span
=
{
8
}
className
=
"prograph overviewBoder"
>
<
span
>
Experiment
Name:
</
span
>
<
Title1
text
=
"Status"
icon
=
"5.png"
/>
<
p
className
=
"messcont"
>
{
trialProfile
.
experName
}
</
p
>
<
Progressed
</
div
>
trialNumber
=
{
trialNumber
}
<
div
className
=
"logo"
>
trialProfile
=
{
trialProfile
}
<
Icon
className
=
"bone"
type
=
"user"
/>
bestAccuracy
=
{
bestAccuracy
}
</
div
>
status
=
{
status
}
</
div
>
/>
<
div
className
=
"type"
>
</
Col
>
<
div
className
=
"message"
>
{
/* experiment parameters search space tuner assessor... */
}
<
div
className
=
"proKey"
>
<
Col
span
=
{
8
}
className
=
"overviewBoder"
>
id:
<
Title1
text
=
"Search Space"
icon
=
"10.png"
/>
<
span
className
=
"messcont"
>
{
trialProfile
.
id
}
</
span
>
<
Row
className
=
"experiment"
>
</
div
>
<
SearchSpace
searchSpace
=
{
searchSpace
}
/>
<
p
>
</
Row
>
Duration:
</
Col
>
<
span
className
=
"messcont"
>
{
maxRuntime
}
</
span
>
<
Col
span
=
{
8
}
className
=
"overviewBoder"
>
</
p
>
<
Title1
text
=
"Trial Profile"
icon
=
"4.png"
/>
<
p
>
<
Row
className
=
"experiment"
>
Still
run:
{
/* the scroll bar all the trial profile in the searchSpace div*/
}
<
span
className
=
"messcont"
>
{
runningStr
}
</
span
>
<
div
className
=
"experiment searchSpace"
>
</
p
>
<
TrialPro
</
div
>
tiralProInfo
=
{
trialProfile
}
<
div
className
=
"logo"
>
/>
<
Icon
className
=
"tyellow"
type
=
"bulb"
/>
</
div
>
</
div
>
<
div
className
=
"runtime message"
>
<
p
className
=
"proTime"
>
<
span
>
Start Time:
</
span
><
br
/>
<
span
className
=
"messcont"
>
{
trialProfile
.
startTime
}
</
span
>
</
p
>
<
span
>
End Time:
</
span
>
<
p
className
=
"messcont"
>
{
trialProfile
.
endTime
}
</
p
>
</
div
>
<
div
className
=
"cdf"
>
<
div
className
=
"message"
>
<
div
className
=
"proKey trialNum"
>
Concurrency
Trial:
<
span
className
=
"messcont"
>
{
trialProfile
.
runConcurren
}
</
span
>
</
div
>
<
p
>
MaxTrial
Number:
<
span
className
=
"messcont"
>
{
trialProfile
.
MaxTrialNum
}
</
span
>
</
p
>
<
p
className
=
"experStatus"
>
Status:
<
span
className
=
"messcont"
>
{
status
}
</
span
>
</
p
>
</
div
>
<
div
className
=
"logo"
>
<
Icon
className
=
"fogreen"
type
=
"picture"
/>
</
div
>
</
div
>
</
div
>
</
Row
>
</
div
>
</
Col
>
</
div
>
</
Row
>
<
div
className
=
"clear"
/>
<
Row
className
=
"overGraph"
>
<
div
className
=
"jsonbox"
>
<
Col
span
=
{
8
}
className
=
"overviewBoder"
>
<
div
>
<
Title1
text
=
"Optimization Progress"
icon
=
"3.png"
/>
<
h2
className
=
"searchTitle title"
>
Search Space
</
h2
>
<
Row
className
=
"accuracy"
>
<
pre
className
=
"searchSpace jsontree"
>
<
Accuracy
<
JSONTree
accuracyData
=
{
accuracyData
}
hideRoot
=
{
true
}
accNodata
=
{
accNodata
}
shouldExpandNode
=
{
()
=>
true
}
height
=
{
324
}
getItemString
=
{
()
=>
(<
span
/>)
}
data
=
{
searchSpace
}
/>
</
pre
>
</
div
>
<
div
>
<
h2
className
=
"searchTitle title"
>
Trial Profile
</
h2
>
<
pre
className
=
"trialProfile jsontree"
>
<
JSONTree
hideRoot
=
{
true
}
shouldExpandNode
=
{
()
=>
true
}
getItemString
=
{
()
=>
(<
span
/>)
}
data
=
{
tunerAssessor
}
/>
/>
</
pre
>
</
div
>
</
div
>
<
div
className
=
"clear"
/>
<
div
className
=
"comtable"
>
<
div
className
=
"selectInline"
>
<
Row
>
<
Col
span
=
{
18
}
>
<
h2
>
The trials that succeeded
</
h2
>
</
Col
>
<
Col
span
=
{
6
}
>
<
span
className
=
"tabuser1"
>
top
</
span
>
<
Select
style
=
{
{
width
:
200
}
}
placeholder
=
"50"
optionFilterProp
=
"children"
onSelect
=
{
this
.
handleChange
}
>
<
Option
value
=
"5"
>
5
</
Option
>
<
Option
value
=
"50"
>
50
</
Option
>
<
Option
value
=
"100"
>
100
</
Option
>
<
Option
value
=
"150"
>
150
</
Option
>
<
Option
value
=
"200"
>
200
</
Option
>
</
Select
>
</
Col
>
</
Row
>
</
Row
>
</
div
>
</
Col
>
<
Table
<
Col
span
=
{
16
}
id
=
"succeTable"
>
columns
=
{
columns
}
<
Title1
text
=
"Top10 Trials"
icon
=
"7.png"
/>
expandedRowRender
=
{
openRow
}
<
SuccessTable
tableSource
=
{
tableData
}
/>
dataSource
=
{
tableData
}
</
Col
>
className
=
"tables"
</
Row
>
bordered
=
{
true
}
/>
</
div
>
<
div
className
=
"downExp"
>
<
Button
type
=
"primary"
className
=
"tableButton"
onClick
=
{
this
.
downExperimentContent
}
>
Download experiment summary
</
Button
>
</
div
>
</
div
>
</
div
>
);
);
}
}
}
}
export
default
Sessionpro
;
export
default
Overview
;
src/webui/src/components/SlideBar.tsx
View file @
744885eb
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
{
Link
,
IndexLink
}
from
'
react-router
'
;
import
{
Link
}
from
'
react-router
'
;
import
{
Icon
}
from
'
antd
'
;
import
'
../static/style/slideBar.scss
'
;
import
'
../style/slideBar.css
'
;
class
SlideBar
extends
React
.
Component
<
{},
{}
>
{
class
SlideBar
extends
React
.
Component
<
{},
{}
>
{
render
()
{
render
()
{
return
(
return
(
<
div
className
=
"slider"
>
<
ul
className
=
"nav"
>
<
ul
className
=
"nav"
>
<
li
className
=
"logo"
>
<
li
>
<
img
src
=
{
require
(
'
../static/img/logo.png
'
)
}
style
=
{
{
width
:
156
}
}
alt
=
"NNI logo"
/>
<
IndexLink
to
=
{
'
/oview
'
}
activeClassName
=
"high"
>
</
li
>
<
Icon
className
=
"icon"
type
=
"home"
/>
Overview
<
li
className
=
"tab"
>
<
Icon
className
=
"floicon"
type
=
"right"
/>
<
Link
to
=
{
'
/oview
'
}
activeClassName
=
"high"
>
</
IndexLink
>
Overview
</
li
>
<
li
>
<
Link
to
=
{
'
/all
'
}
activeClassName
=
"high"
>
<
Icon
className
=
"icon"
type
=
"dot-chart"
/>
Optimization Progress
<
Icon
className
=
"floicon"
type
=
"right"
/>
</
Link
>
</
Link
>
</
li
>
</
li
>
<
li
>
<
li
className
=
"tab"
>
<
Link
to
=
{
'
/hyper
'
}
activeClassName
=
"high"
>
<
Link
to
=
{
'
/detail
'
}
activeClassName
=
"high"
>
<
Icon
className
=
"icon"
type
=
"rocket"
/>
Hyper Parameter
Trials Detail
<
Icon
className
=
"floicon"
type
=
"right"
/>
</
Link
>
</
Link
>
</
li
>
</
li
>
<
li
>
</
ul
>
<
Link
to
=
{
'
/trastaus
'
}
activeClassName
=
"high"
>
<
Icon
className
=
"icon"
type
=
"bar-chart"
/>
Trial Status
<
Icon
className
=
"floicon"
type
=
"right"
/>
</
Link
>
</
li
>
<
li
>
<
Link
to
=
{
'
/control
'
}
activeClassName
=
"high"
>
<
Icon
className
=
"icon"
type
=
"form"
/>
Control
<
Icon
className
=
"floicon"
type
=
"right"
/>
</
Link
>
</
li
>
<
li
>
<
a
href
=
"https://github.com/Microsoft/nni/issues"
target
=
"_blank"
>
<
Icon
className
=
"icon"
type
=
"smile"
/>
Feedback
</
a
>
</
li
>
</
ul
>
</
div
>
);
);
}
}
}
}
...
...
src/webui/src/components/Tensor.tsx
View file @
744885eb
import
*
as
React
from
'
react
'
;
import
*
as
React
from
'
react
'
;
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
;
import
{
message
}
from
'
antd
'
;
import
{
message
}
from
'
antd
'
;
import
{
MANAGER_IP
}
from
'
../const
'
;
import
{
MANAGER_IP
}
from
'
../
static/
const
'
;
import
'
../style/tensor.css
'
;
import
'
../
static/
style/tensor.
s
css
'
;
interface
TensorState
{
interface
TensorState
{
urlTensor
:
string
;
urlTensor
:
string
;
...
...
src/webui/src/components/TrialsDetail.tsx
0 → 100644
View file @
744885eb
import
*
as
React
from
'
react
'
;
import
axios
from
'
axios
'
;
import
{
MANAGER_IP
}
from
'
../static/const
'
;
import
{
Row
,
Tabs
}
from
'
antd
'
;
import
{
getAccuracyData
}
from
'
../static/function
'
;
import
{
TableObj
,
Parameters
,
AccurPoint
}
from
'
../static/interface
'
;
import
Accuracy
from
'
./overview/Accuracy
'
;
import
Duration
from
'
./trial-detail/Duration
'
;
import
Title1
from
'
./overview/Title1
'
;
import
Para
from
'
./trial-detail/Para
'
;
import
TableList
from
'
./trial-detail/TableList
'
;
const
TabPane
=
Tabs
.
TabPane
;
import
'
../static/style/trialsDetail.scss
'
;
interface
TrialDetailState
{
accSource
:
object
;
accNodata
:
string
;
tableListSource
:
Array
<
TableObj
>
;
}
class
TrialsDetail
extends
React
.
Component
<
{},
TrialDetailState
>
{
public
_isMounted
=
false
;
public
interAccuracy
=
0
;
public
interTableList
=
1
;
constructor
(
props
:
{})
{
super
(
props
);
this
.
state
=
{
accSource
:
{},
accNodata
:
''
,
tableListSource
:
[]
};
}
// trial accuracy graph
drawPointGraph
=
()
=>
{
axios
(
`
${
MANAGER_IP
}
/trial-jobs`
,
{
method
:
'
GET
'
})
.
then
(
res
=>
{
if
(
res
.
status
===
200
&&
this
.
_isMounted
)
{
const
accData
=
res
.
data
;
const
accArr
:
Array
<
number
>
=
[];
const
accY
:
Array
<
AccurPoint
>
=
[];
Object
.
keys
(
accData
).
map
(
item
=>
{
if
(
accData
[
item
].
status
===
'
SUCCEEDED
'
&&
accData
[
item
].
finalMetricData
)
{
accArr
.
push
(
parseFloat
(
accData
[
item
].
finalMetricData
.
data
));
}
});
accY
.
push
({
yAxis
:
accArr
});
const
optionObj
=
getAccuracyData
(
accY
[
0
]);
this
.
setState
({
accSource
:
optionObj
},
()
=>
{
if
(
accArr
.
length
===
0
)
{
this
.
setState
({
accNodata
:
'
No data
'
});
}
else
{
this
.
setState
({
accNodata
:
''
});
}
});
}
});
}
drawTableList
=
()
=>
{
axios
(
`
${
MANAGER_IP
}
/trial-jobs`
,
{
method
:
'
GET
'
})
.
then
(
res
=>
{
if
(
res
.
status
===
200
)
{
const
trialJobs
=
res
.
data
;
const
trialTable
:
Array
<
TableObj
>
=
[];
Object
.
keys
(
trialJobs
).
map
(
item
=>
{
// only succeeded trials have finalMetricData
let
desc
:
Parameters
=
{
parameters
:
{}
};
let
acc
=
0
;
let
duration
=
0
;
const
id
=
trialJobs
[
item
].
id
!==
undefined
?
trialJobs
[
item
].
id
:
''
;
const
status
=
trialJobs
[
item
].
status
!==
undefined
?
trialJobs
[
item
].
status
:
''
;
const
begin
=
trialJobs
[
item
].
startTime
;
const
end
=
trialJobs
[
item
].
endTime
;
if
(
begin
)
{
if
(
end
)
{
duration
=
(
end
-
begin
)
/
1000
;
}
else
{
duration
=
(
new
Date
().
getTime
()
-
begin
)
/
1000
;
}
}
if
(
trialJobs
[
item
].
hyperParameters
!==
undefined
)
{
desc
.
parameters
=
JSON
.
parse
(
trialJobs
[
item
].
hyperParameters
).
parameters
;
}
else
{
desc
.
parameters
=
{
error
:
'
This trial
\'
s parameters are not available.
'
};
}
if
(
trialJobs
[
item
].
logPath
!==
undefined
)
{
desc
.
logPath
=
trialJobs
[
item
].
logPath
;
const
isHyperLink
=
/^http/gi
.
test
(
trialJobs
[
item
].
logPath
);
if
(
isHyperLink
)
{
desc
.
isLink
=
true
;
}
}
if
(
trialJobs
[
item
].
finalMetricData
!==
undefined
)
{
acc
=
parseFloat
(
trialJobs
[
item
].
finalMetricData
.
data
);
}
trialTable
.
push
({
key
:
trialTable
.
length
,
sequenceId
:
trialJobs
[
item
].
sequenceId
,
id
:
id
,
status
:
status
,
duration
:
duration
,
acc
:
acc
,
description
:
desc
});
});
if
(
this
.
_isMounted
)
{
this
.
setState
(()
=>
({
tableListSource
:
trialTable
}));
}
}
});
}
callback
=
(
key
:
string
)
=>
{
switch
(
key
)
{
case
'
1
'
:
window
.
clearInterval
(
Para
.
intervalIDPara
);
window
.
clearInterval
(
Duration
.
intervalDuration
);
this
.
drawPointGraph
();
this
.
interAccuracy
=
window
.
setInterval
(
this
.
drawPointGraph
,
10000
);
break
;
case
'
2
'
:
window
.
clearInterval
(
this
.
interAccuracy
);
window
.
clearInterval
(
Duration
.
intervalDuration
);
break
;
case
'
3
'
:
window
.
clearInterval
(
this
.
interAccuracy
);
window
.
clearInterval
(
Para
.
intervalIDPara
);
break
;
default
:
}
}
componentDidMount
()
{
this
.
_isMounted
=
true
;
this
.
drawPointGraph
();
this
.
drawTableList
();
this
.
interAccuracy
=
window
.
setInterval
(
this
.
drawPointGraph
,
10000
);
this
.
interTableList
=
window
.
setInterval
(
this
.
drawTableList
,
10000
);
}
componentWillUnmount
()
{
this
.
_isMounted
=
false
;
window
.
clearInterval
(
this
.
interTableList
);
window
.
clearInterval
(
this
.
interAccuracy
);
}
render
()
{
const
{
accSource
,
accNodata
,
tableListSource
}
=
this
.
state
;
const
titleOfacc
=
(
<
Title1
text
=
"Trial Accuracy"
icon
=
"3.png"
/>
);
const
titleOfhyper
=
(
<
Title1
text
=
"Hyper Parameter"
icon
=
"1.png"
/>
);
const
titleOfDuration
=
(
<
Title1
text
=
"Trial Duration"
icon
=
"2.png"
/>
);
return
(
<
div
>
<
div
className
=
"trial"
id
=
"tabsty"
>
<
Tabs
onChange
=
{
this
.
callback
}
type
=
"card"
>
<
TabPane
tab
=
{
titleOfacc
}
key
=
"1"
>
<
Row
className
=
"graph"
>
<
Accuracy
height
=
{
432
}
accuracyData
=
{
accSource
}
accNodata
=
{
accNodata
}
/>
</
Row
>
</
TabPane
>
<
TabPane
tab
=
{
titleOfhyper
}
key
=
"2"
>
<
Row
className
=
"graph"
><
Para
/></
Row
>
</
TabPane
>
<
TabPane
tab
=
{
titleOfDuration
}
key
=
"3"
>
<
Duration
/>
</
TabPane
>
</
Tabs
>
</
div
>
{
/* trial table list */
}
<
TableList
tableSource
=
{
tableListSource
}
updateList
=
{
this
.
drawTableList
}
/>
</
div
>
);
}
}
export
default
TrialsDetail
;
\ No newline at end of file
src/webui/src/components/overview/Accuracy.tsx
0 → 100644
View file @
744885eb
import
*
as
React
from
'
react
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
const
echarts
=
require
(
'
echarts/lib/echarts
'
);
echarts
.
registerTheme
(
'
my_theme
'
,
{
color
:
'
#3c8dbc
'
});
require
(
'
echarts/lib/chart/scatter
'
);
require
(
'
echarts/lib/component/tooltip
'
);
require
(
'
echarts/lib/component/title
'
);
interface
AccuracyProps
{
accuracyData
:
object
;
accNodata
:
string
;
height
:
number
;
}
class
Accuracy
extends
React
.
Component
<
AccuracyProps
,
{}
>
{
constructor
(
props
:
AccuracyProps
)
{
super
(
props
);
}
render
()
{
const
{
accNodata
,
accuracyData
,
height
}
=
this
.
props
;
return
(
<
div
>
<
ReactEcharts
option
=
{
accuracyData
}
style
=
{
{
width
:
'
100%
'
,
height
:
height
,
margin
:
'
0 auto
'
,
}
}
theme
=
"my_theme"
/>
<
div
className
=
"showMess"
>
{
accNodata
}
</
div
>
</
div
>
);
}
}
export
default
Accuracy
;
\ No newline at end of file
src/webui/src/components/overview/BasicInfo.tsx
0 → 100644
View file @
744885eb
import
*
as
React
from
'
react
'
;
import
{
Row
,
Col
,
Tooltip
}
from
'
antd
'
;
import
{
Experiment
}
from
'
../../static/interface
'
;
interface
BasicInfoProps
{
trialProfile
:
Experiment
;
status
:
string
;
}
class
BasicInfo
extends
React
.
Component
<
BasicInfoProps
,
{}
>
{
constructor
(
props
:
BasicInfoProps
)
{
super
(
props
);
}
render
()
{
const
{
trialProfile
,
// status
}
=
this
.
props
;
return
(
<
Row
className
=
"main"
>
<
Col
span
=
{
8
}
className
=
"padItem basic"
>
<
p
>
Name
</
p
>
<
div
>
{
trialProfile
.
experName
}
</
div
>
<
p
>
ID
</
p
>
<
div
>
{
trialProfile
.
id
}
</
div
>
</
Col
>
<
Col
span
=
{
8
}
className
=
"padItem basic"
>
<
Row
>
<
Col
span
=
{
18
}
>
<
p
>
Start Time
</
p
>
<
div
className
=
"nowrap"
>
{
new
Date
(
trialProfile
.
startTime
).
toLocaleString
(
'
en-US
'
)
}
</
div
>
<
p
>
End Time
</
p
>
<
div
className
=
"nowrap"
>
{
trialProfile
.
endTime
?
new
Date
(
trialProfile
.
endTime
).
toLocaleString
(
'
en-US
'
)
:
'
none
'
}
</
div
>
</
Col
>
</
Row
>
</
Col
>
<
Col
span
=
{
8
}
className
=
"padItem basic"
>
<
p
>
LogPath
</
p
>
<
div
className
=
"logPath"
>
<
Tooltip
placement
=
"top"
title
=
{
trialProfile
.
logDir
}
>
{
trialProfile
.
logDir
}
</
Tooltip
>
</
div
>
<
p
>
TrainingPlatform
</
p
>
<
div
className
=
"nowrap"
>
{
trialProfile
.
trainingServicePlatform
?
trialProfile
.
trainingServicePlatform
:
'
none
'
}
</
div
>
</
Col
>
</
Row
>
);
}
}
export
default
BasicInfo
;
\ No newline at end of file
src/webui/src/components/overview/Progress.tsx
0 → 100644
View file @
744885eb
import
*
as
React
from
'
react
'
;
import
{
Row
,
Col
,
}
from
'
antd
'
;
import
{
Experiment
,
TrialNumber
}
from
'
../../static/interface
'
;
import
{
convertTime
}
from
'
../../static/function
'
;
import
ProgressBar
from
'
./ProgressItem
'
;
import
'
../../static/style/progress.scss
'
;
interface
ProgressProps
{
trialProfile
:
Experiment
;
trialNumber
:
TrialNumber
;
bestAccuracy
:
string
;
status
:
string
;
}
class
Progressed
extends
React
.
Component
<
ProgressProps
,
{}
>
{
constructor
(
props
:
ProgressProps
)
{
super
(
props
);
}
render
()
{
const
{
trialProfile
,
trialNumber
,
bestAccuracy
,
status
}
=
this
.
props
;
// remaining time
const
bar2
=
trialNumber
.
totalCurrentTrial
-
trialNumber
.
waitTrial
-
trialNumber
.
unknowTrial
;
const
bar2Percent
=
(
bar2
/
trialProfile
.
MaxTrialNum
)
*
100
;
const
percent
=
(
trialProfile
.
execDuration
/
trialProfile
.
maxDuration
)
*
100
;
const
runDuration
=
convertTime
(
trialProfile
.
execDuration
);
const
remaining
=
convertTime
(
trialProfile
.
maxDuration
-
trialProfile
.
execDuration
);
return
(
<
Row
className
=
"progress"
>
<
Row
className
=
"basic"
>
<
p
>
Status
</
p
>
<
div
className
=
"status"
>
{
status
}
</
div
>
</
Row
>
<
ProgressBar
who
=
"Duration"
percent
=
{
percent
}
description
=
{
runDuration
}
maxString
=
{
`MaxDuration:
${
convertTime
(
trialProfile
.
maxDuration
)}
`
}
/>
<
ProgressBar
who
=
"TrialNum"
percent
=
{
bar2Percent
}
description
=
{
bar2
.
toString
()
}
maxString
=
{
`MaxTrialNumber:
${
trialProfile
.
MaxTrialNum
}
`
}
/>
<
Row
className
=
"basic colorOfbasic mess"
>
<
p
>
Best Accuracy
</
p
>
<
div
>
{
bestAccuracy
}
</
div
>
</
Row
>
<
Row
className
=
"mess"
>
<
Col
span
=
{
8
}
>
<
Row
className
=
"basic colorOfbasic"
>
<
p
>
Time Spent
</
p
>
<
div
>
{
convertTime
(
trialProfile
.
execDuration
)
}
</
div
>
</
Row
>
</
Col
>
<
Col
span
=
{
9
}
>
<
Row
className
=
"basic colorOfbasic"
>
<
p
>
Remaining Time
</
p
>
<
div
>
{
remaining
}
</
div
>
</
Row
>
</
Col
>
<
Col
span
=
{
7
}
>
<
Row
className
=
"basic colorOfbasic"
>
<
p
>
Duration
</
p
>
<
div
>
{
convertTime
(
trialProfile
.
maxDuration
)
}
</
div
>
</
Row
>
</
Col
>
</
Row
>
<
Row
className
=
"mess"
>
<
Col
span
=
{
8
}
>
<
Row
className
=
"basic colorOfbasic"
>
<
p
>
Succeed Trial
</
p
>
<
div
>
{
trialNumber
.
succTrial
}
</
div
>
</
Row
>
</
Col
>
<
Col
span
=
{
9
}
>
<
Row
className
=
"basic"
>
<
p
>
Stopped Trial
</
p
>
<
div
>
{
trialNumber
.
stopTrial
}
</
div
>
</
Row
>
</
Col
>
<
Col
span
=
{
7
}
>
<
Row
className
=
"basic"
>
<
p
>
Failed Trial
</
p
>
<
div
>
{
trialNumber
.
failTrial
}
</
div
>
</
Row
>
</
Col
>
</
Row
>
</
Row
>
);
}
}
export
default
Progressed
;
\ No newline at end of file
src/webui/src/components/overview/ProgressItem.tsx
0 → 100644
View file @
744885eb
import
*
as
React
from
'
react
'
;
import
{
Row
,
Col
,
Progress
}
from
'
antd
'
;
interface
ProItemProps
{
who
:
string
;
percent
:
number
;
description
:
string
;
maxString
:
string
;
}
class
ProgressBar
extends
React
.
Component
<
ProItemProps
,
{}
>
{
constructor
(
props
:
ProItemProps
)
{
super
(
props
);
}
render
()
{
const
{
who
,
percent
,
description
,
maxString
}
=
this
.
props
;
return
(
<
div
>
<
Row
className
=
"probar"
>
<
Col
span
=
{
6
}
>
<
div
className
=
"name"
>
{
who
}
</
div
>
</
Col
>
<
Col
span
=
{
17
}
className
=
"bar"
>
<
div
className
=
"showProgress"
>
<
Progress
percent
=
{
percent
}
strokeWidth
=
{
30
}
// strokeLinecap={'square'}
format
=
{
()
=>
description
}
/>
</
div
>
<
Row
className
=
"description"
>
<
Col
span
=
{
12
}
>
0
</
Col
>
<
Col
className
=
"right"
span
=
{
12
}
>
{
maxString
}
</
Col
>
</
Row
>
</
Col
>
</
Row
>
<
br
/>
</
div
>
);
}
}
export
default
ProgressBar
;
\ No newline at end of file
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