@@ -210,11 +210,21 @@ class Channel {
210210 // event source
211211 _event_source_init ( ) {
212212 this . _event_source = new EventSource ( this . url + "_event" ) ;
213- this . _event_source . onopen = ( event ) => {
214- console . log ( event )
215- }
216- this . _event_source . onmessage = ( event ) => {
217- console . log ( event )
213+ this . _event_source . onmessage = ( e ) => {
214+ const raw_data = JSON . parse ( e . data ) ;
215+ const type = raw_data . event . split ( "_" ) [ 0 ] ;
216+ const event = raw_data . event . slice ( type . length + 1 ) ;
217+ const data = raw_data . data ;
218+ window . dispatchEvent ( new CustomEvent ( `sse_${ type } ` , {
219+ detail : {
220+ event,
221+ data,
222+ }
223+ } ) )
224+ if ( event . length == 0 ) return ;
225+ window . dispatchEvent ( new CustomEvent ( `sse_${ type } _${ event } ` , {
226+ detail : data
227+ } ) )
218228 }
219229
220230 }
@@ -239,9 +249,6 @@ class Channel {
239249 this . _ws_initizalized = false ;
240250 this . _ws_reconnect ( ) ;
241251 }
242- this . _ws . onerror = ( event ) => {
243- console . log ( "websocket error" , event )
244- }
245252 }
246253 _ws_reconnect ( ) {
247254 if ( this . _ws_reconnect_task ) return ;
@@ -757,7 +764,16 @@ $i18n.addLanguageTable("zh_CN", {
757764 "dashboard.value.storage.total.today" : "共请求 %hits% | 共请求流量 %bytes%" ,
758765 "dashboard.value.cluster.total.today" : "共请求 %hits% | 共请求流量 %bytes%" ,
759766 "dashboard.value.storage.total.30days" : "共请求 %hits% | 共请求流量 %bytes%" ,
760- "dashboard.value.cluster.total.30days" : "共请求 %hits% | 共请求流量 %bytes%"
767+ "dashboard.value.cluster.total.30days" : "共请求 %hits% | 共请求流量 %bytes%" ,
768+ "dashboard.value.status.clusters" : "节点正常运行(%online%/%total%)" ,
769+ "dashboard.value.status.cluster.status.checking_files" : "检查文件中" ,
770+ "dashboard.value.status.clusters.enabling" : "启用节点中(%online%/%total%)" ,
771+ "dashboard.value.status.cluster.status.listing_files" : "列出存储文件中" ,
772+ "dashboard.value.status.cluster.status.get_certificates" : "正在获取证书中" ,
773+ "dashboard.value.status.cluster.fetch_filelist" : "获取文件列表中" ,
774+ "dashboard.value.status.default" : "加载中……" ,
775+ "dashboard.value.status.storage.check_available" : "检查可用存储" ,
776+ "dashboard.value.status.cluster.status.sync" : "同步文件中"
761777
762778} )
763779$style . setTheme ( "light" , {
@@ -948,10 +964,41 @@ $style.addAll({
948964 ".label-text .flex-between" : {
949965 "flex-direction" : "row" ,
950966 "justify-content" : "space-between"
967+ } ,
968+ ".info-progressbar" : {
969+ "display" : "flex" ,
970+ "margin-top" : "8px" ,
971+ "border-top" : "1px solid var(--title-color)" ,
972+ "padding-top" : "8px"
973+ } ,
974+ ".info-progressbar.hidden" : {
975+ "display" : "none"
976+ } ,
977+ ".info-progressbar .container-bar" : {
978+ "margin-left" : "8px" ,
979+ "margin-right" : "8px" ,
980+ "display" : "flex" ,
981+ "flex-grow" : 1 ,
982+ "align-items" : "center" ,
983+ } ,
984+ ".info-progressbar .container-bar .bar" : {
985+ "padding" : "2px" ,
986+ "margin-left" : "8px" ,
987+ "height" : "4px" ,
988+ "background" : "var(--main-color)" ,
989+ "border-radius" : "8px" ,
990+ "width" : "100%" ,
991+ "transition" : "width 0.5s ease-in-out"
951992 }
952993} )
953994class Tools {
954995 static formatTime ( seconds ) {
996+ if ( seconds < 0 || seconds == null ) return $i18n . t ( "format.count_time.days" , {
997+ day : "--" ,
998+ hour : "--" ,
999+ minute : "--" ,
1000+ second : "--" ,
1001+ } )
9551002 var s = Math . floor ( seconds % 60 )
9561003 var m = Math . floor ( seconds / 60 % 60 )
9571004 var h = Math . floor ( seconds / 3600 % 24 )
@@ -963,6 +1010,14 @@ class Tools {
9631010 second : s . toString ( ) . padStart ( 2 , "0" ) ,
9641011 } )
9651012 }
1013+ static formatCountTime ( seconds ) {
1014+ if ( seconds < 0 || seconds == null ) return "--:--"
1015+ var s = Math . floor ( seconds % 60 )
1016+ var m = Math . floor ( seconds / 60 % 60 )
1017+ var h = Math . floor ( seconds / 3600 % 24 )
1018+ if ( h > 0 ) return `${ h . toString ( ) . padStart ( 2 , "0" ) } :${ m . toString ( ) . padStart ( 2 , "0" ) } :${ s . toString ( ) . padStart ( 2 , "0" ) } `
1019+ return `${ m . toString ( ) . padStart ( 2 , "0" ) } :${ s . toString ( ) . padStart ( 2 , "0" ) } `
1020+ }
9661021 static runTask ( executor , handler , interval ) {
9671022 handler ( )
9681023 return executor ( handler , interval )
@@ -1025,6 +1080,22 @@ class Tools {
10251080 value
10261081 )
10271082 }
1083+ static createElementWithI18n (
1084+ tag ,
1085+ options = {
1086+ key : "" ,
1087+ callback : ( ) => { }
1088+ }
1089+ ) {
1090+ var element = createElement ( tag )
1091+ var obj = ref ( { } , {
1092+ handler : ( args ) => {
1093+ element . t18n ( key , args . object )
1094+ }
1095+ } )
1096+ options . callback ( obj )
1097+ return element
1098+ }
10281099 static formatSimpleNumber ( number ) {
10291100 // convert number to belike: 100,000, if 100000.0, we are 100,000.0
10301101 return number . toString ( ) . replace ( / \B (? = ( \d { 3 } ) + (? ! \d ) ) / g, ", " )
@@ -1109,6 +1180,20 @@ async function load() {
11091180 $dashboard_locals . advanced = [ ] ;
11101181 // info
11111182 ( ( ) => {
1183+ $dashboard_locals . info_progressbar_bar = {
1184+ rate : createElement ( "p" ) . classes ( "text" ) ,
1185+ bar : createElement ( "div" ) . classes ( "bar" ) ,
1186+ desc : createElement ( "p" ) . classes ( "text" ) ,
1187+ postfix : createElement ( "p" ) . classes ( "text" ) ,
1188+ }
1189+ $dashboard_locals . info_progressbar = createElement ( "div" ) . classes ( "info-progressbar" , "hidden" ) . append (
1190+ $dashboard_locals . info_progressbar_bar . desc ,
1191+ createElement ( "div" ) . classes ( "container-bar" ) . append (
1192+ $dashboard_locals . info_progressbar_bar . rate ,
1193+ $dashboard_locals . info_progressbar_bar . bar ,
1194+ ) ,
1195+ $dashboard_locals . info_progressbar_bar . postfix ,
1196+ )
11121197 $dashboard_locals . info = Tools . createPanel ( ( { pre, panel } ) => {
11131198 panel . append (
11141199 Tools . createFlexElement ( ) . append (
@@ -1134,11 +1219,12 @@ async function load() {
11341219 i18n : {
11351220 "zh_CN" : {
11361221 "dashboard.title.status" : "当前状态" ,
1137- "dashboard.value.status" : "正常……? "
1222+ "dashboard.value.status" : "%value% "
11381223 }
11391224 }
11401225 } ) ,
1141- ) . child ( 2 ) . minWidth ( 680 )
1226+ ) . child ( 2 ) . minWidth ( 680 ) ,
1227+ $dashboard_locals . info_progressbar
11421228 )
11431229 } )
11441230 $dashboard_locals . info_runtime = ref ( { } , {
@@ -1167,6 +1253,74 @@ async function load() {
11671253 $dashboard_locals . info_runtime [ key ] = value
11681254 }
11691255 } , 5000 )
1256+ const status_handlers = {
1257+ "clusters_clusters" : ( data ) => {
1258+ return {
1259+ "total" : data . params . total ,
1260+ "online" : data . count
1261+ }
1262+ } ,
1263+ "clusters_clusters.enabling" : ( data ) => {
1264+ return {
1265+ "total" : data . params . total ,
1266+ "online" : data . count ,
1267+ "enabling" : data . params . enabling
1268+ }
1269+ } ,
1270+ }
1271+ window . addEventListener ( "sse_status" , event => {
1272+ const obj = $dashboard_locals . status
1273+ // 先 sort cluster 在前面,然后再storage
1274+ const clusters = [ ] ;
1275+ const storages = [ ] ;
1276+ for ( const item of event . detail . data ) {
1277+ if ( item . name . startsWith ( "cluster" ) ) clusters . push ( item )
1278+ else storages . push ( item )
1279+ }
1280+ clusters . sort ( ( a , b ) => a . name . localeCompare ( b . name ) )
1281+ storages . sort ( ( a , b ) => a . name . localeCompare ( b . name ) )
1282+ var params = { }
1283+ var key = "default" ;
1284+ if ( clusters . length != 0 ) {
1285+ const cluster = clusters [ 0 ] ;
1286+ key = cluster . name ;
1287+ params = ( status_handlers [ "clusters_" + key ] || ( ( ) => { } ) ) ( cluster ) || { } ;
1288+ } else if ( storages . length != 0 ) {
1289+ const storage = storages [ 0 ] ;
1290+ key = storage . name ;
1291+ params = ( status_handlers [ "storages_" + key ] || ( ( ) => { } ) ) ( storage ) || { } ;
1292+ }
1293+ obj . value = $i18n . t ( `dashboard.value.status.${ key } ` , params )
1294+ if ( obj . value == `dashboard.value.status.${ key } ` ) console . log ( `dashboard.value.status.${ key } ` )
1295+ } )
1296+ window . addEventListener ( "sse_progress" , event => {
1297+ const resp = event . detail . data ;
1298+ const isEmpty = resp . length == 0
1299+ if ( isEmpty ) {
1300+ $dashboard_locals . info_progressbar . classes ( "hidden" )
1301+ $dashboard_locals . info_progressbar_bar . bar . style ( "width" , "0%" )
1302+ return
1303+ }
1304+ const data = resp [ 0 ] ;
1305+ const rate = ( ( data . total == 0 || data . total < data . current ? 1 : data . current / data . total ) * 100.0 ) ;
1306+ $dashboard_locals . info_progressbar_bar . desc . text ( data . desc )
1307+ $dashboard_locals . info_progressbar_bar . rate . text ( rate . toFixed ( 2 ) + "%" )
1308+ $dashboard_locals . info_progressbar_bar . bar . style ( "width" , rate + "%" )
1309+
1310+ // calc elapsed time
1311+ if ( rate < 100 ) {
1312+ var speed = ( data . speed . slice ( data . speed . length - 1 ) || [ 0 ] ) [ 0 ] ;
1313+ var e = speed == 0 ? null : ( data . total - data . current ) / speed ;
1314+ var d = Tools . formatCountTime ( e ) ;
1315+ var running = Tools . formatCountTime ( data . current_time - data . start_time ) ;
1316+ var postfix = data . postfix == null ? "" : ", " + data . postfix ;
1317+ $dashboard_locals . info_progressbar_bar . postfix . text ( `${ data . current } /${ data . total } [${ running } <${ d } , ${ speed . toFixed ( 2 ) } ${ data . unit } /s${ postfix } ]` )
1318+ }
1319+
1320+ $dashboard_locals . info_progressbar . removeClasses ( "hidden" )
1321+
1322+
1323+ } )
11701324 } ) ( ) ;
11711325 // basic
11721326 ( ( ) => {
0 commit comments