@@ -35,6 +35,8 @@ import { ToggleButton } from 'primereact/togglebutton'
3535import { confirmDialog } from 'primereact/confirmdialog'
3636import { OverlayPanel } from 'primereact/overlaypanel'
3737import { MultiSelect } from 'primereact/multiselect'
38+ import { DataTable } from 'primereact/datatable'
39+ import { Column } from 'primereact/column'
3840// eslint-disable-next-line camelcase
3941import jwt_decode from 'jwt-decode'
4042import axios from 'axios'
@@ -1162,6 +1164,27 @@ class App extends Component {
11621164 }
11631165 }
11641166
1167+ async fetchCloudState ( ) {
1168+ try {
1169+ const response = await axios . get ( '/cloudstatus' , this . axiosConfig ( ) )
1170+ if ( response ) {
1171+ if ( response . data . error ) {
1172+ if ( this . messages )
1173+ this . messages . show ( {
1174+ severity : 'error' ,
1175+ summary : 'get /cloudstatus failed' ,
1176+ detail : response . data . error
1177+ } )
1178+ } else {
1179+ console . log ( 'cloud state' , response . data )
1180+ this . setState ( { curcloudstate : response . data } )
1181+ }
1182+ }
1183+ } catch ( error ) {
1184+ this . errorMessage ( error )
1185+ }
1186+ }
1187+
11651188 async jupyterLicense ( ) {
11661189 const { licenses } = await this . jupyteredit . current . getLicenses ( )
11671190 const lines = [ ]
@@ -2048,6 +2071,7 @@ class App extends Component {
20482071 let displaynames = 'loading...'
20492072
20502073 let joinlecture = false
2074+ let cloudstatus = false
20512075 let startlecture = false
20522076 let pictures = false
20532077 let pastlectures = false
@@ -2196,6 +2220,9 @@ class App extends Component {
21962220 if ( this . state . decodedtoken . role . includes ( 'audience' ) ) {
21972221 joinlecture = true
21982222 }
2223+ if ( this . state . decodedtoken . role . includes ( 'administrator' ) ) {
2224+ cloudstatus = true
2225+ }
21992226 }
22002227
22012228 if ( lectdetail ?. ipynbs ) {
@@ -2604,6 +2631,24 @@ class App extends Component {
26042631 </ Card >
26052632 </ div >
26062633 ) }
2634+ { cloudstatus && (
2635+ < div className = 'p-col-12 p-md-6' >
2636+ < Card title = 'Cloud status' >
2637+ < Button
2638+ icon = 'pi pi-cloud'
2639+ href = { this . state . support . url }
2640+ label = 'Open'
2641+ className = 'p-m-2'
2642+ onClick = { ( event ) => {
2643+ this . fetchCloudState ( )
2644+ this . setState ( {
2645+ cloudstatus : true
2646+ } )
2647+ } }
2648+ > </ Button >
2649+ </ Card >
2650+ </ div >
2651+ ) }
26072652 </ div >
26082653 </ div >
26092654 < div className = 'p-col-12 p-md-6' >
@@ -2778,6 +2823,113 @@ class App extends Component {
27782823 { uaparser . getEngine ( ) . name } (Version:{ ' ' }
27792824 { uaparser . getEngine ( ) . version } )
27802825 </ OverlayPanel >
2826+ { cloudstatus && (
2827+ < Dialog
2828+ visible = { this . state . cloudstatus }
2829+ modal = { true }
2830+ closable = { true }
2831+ header = {
2832+ < Fragment >
2833+ < h3 >
2834+ Current cloud status{ ' ' }
2835+ < Button
2836+ icon = 'pi pi-refresh'
2837+ className = 'p-button-text p-button-sm'
2838+ iconPos = 'right'
2839+ tooltip = 'Refresh data'
2840+ onClick = { ( ) => {
2841+ this . fetchCloudState ( )
2842+ } }
2843+ /> { ' ' }
2844+ </ h3 >
2845+ </ Fragment >
2846+ }
2847+ position = 'top'
2848+ onHide = { ( ) => {
2849+ if ( ! this . state . cloudstatus ) return
2850+ this . setState ( { cloudstatus : undefined } )
2851+ } }
2852+ >
2853+ { this . state . curcloudstate && (
2854+ < Fragment >
2855+ < h4 > Available AVS routers</ h4 >
2856+ { this . state . curcloudstate . routerDetails && (
2857+ < DataTable
2858+ value = { this . state . curcloudstate . routerDetails }
2859+ paginator
2860+ rows = { 5 }
2861+ size = 'small'
2862+ scrollable
2863+ scrollHeight = 'flex'
2864+ rowsPerPageOptions = { [ 5 , 10 , 25 , 50 ] }
2865+ tableStyle = { { minWidth : '50rem' } }
2866+ >
2867+ < Column field = 'region' header = 'Region' > </ Column >
2868+ < Column
2869+ field = 'url'
2870+ header = 'Server URL'
2871+ bodyClassName = 'urlTableEntry'
2872+ > </ Column >
2873+ < Column field = 'numClients' header = 'Clients' > </ Column >
2874+ < Column
2875+ field = 'numLocalClients'
2876+ header = 'Local sending clients'
2877+ > </ Column >
2878+ < Column
2879+ field = 'numRemoteClients'
2880+ header = 'Remote sending clients'
2881+ > </ Column >
2882+ < Column
2883+ field = 'primaryLectureNum'
2884+ header = 'Primary lectures'
2885+ > </ Column >
2886+ < Column
2887+ field = 'isPrimary'
2888+ header = 'My primary router'
2889+ body = { ( rowData ) => ( rowData ? 'Yes' : 'No' ) }
2890+ > </ Column >
2891+ </ DataTable >
2892+ ) }
2893+ < h4 > Running lectures</ h4 >
2894+ { this . state . curcloudstate . lectureDetails && (
2895+ < DataTable
2896+ value = { this . state . curcloudstate . lectureDetails }
2897+ paginator
2898+ rows = { 5 }
2899+ size = 'small'
2900+ scrollable
2901+ scrollHeight = 'flex'
2902+ rowsPerPageOptions = { [ 5 , 10 , 25 , 50 ] }
2903+ tableStyle = { { minWidth : '50rem' } }
2904+ >
2905+ < Column
2906+ field = 'coursetitle'
2907+ header = 'Course'
2908+ bodyClassName = 'urlTableEntry'
2909+ > </ Column >
2910+ < Column
2911+ field = 'title'
2912+ header = 'Title'
2913+ bodyClassName = 'urlTableEntry'
2914+ > </ Column >
2915+ < Column
2916+ field = 'numberOfIdents'
2917+ header = 'Active identities'
2918+ > </ Column >
2919+ < Column
2920+ field = 'numberOfNotescreens'
2921+ header = 'Number of notepads/screens'
2922+ > </ Column >
2923+ < Column field = 'uuid' header = 'UUID' > </ Column >
2924+ </ DataTable >
2925+ ) }
2926+ </ Fragment >
2927+ ) }
2928+ { ! this . state . curcloudstate && (
2929+ < Fragment > No cloud status retrieved</ Fragment >
2930+ ) }
2931+ </ Dialog >
2932+ ) }
27812933 { jupyter && (
27822934 < Dialog
27832935 visible = { this . state . jupyteredit }
0 commit comments