@@ -279,54 +279,62 @@ function HistoricalUsageChart({ monthly }) {
279279 return React . createElement ( 'div' , { className : 'chart-container' } , React . createElement ( 'canvas' , { ref : canvasRef , width : 600 , height : 300 } ) ) ;
280280}
281281
282- function PiConsumptionTable ( { details } ) {
283- const totals = { } ;
284- details . forEach ( acc => {
285- ( acc . users || [ ] ) . forEach ( u => {
286- totals [ u . user ] = ( totals [ u . user ] || 0 ) + ( u . core_hours || 0 ) ;
282+ function PiConsumptionChart ( { details } ) {
283+ const canvasRef = useRef ( null ) ;
284+ useEffect ( ( ) => {
285+ if ( ! canvasRef . current ) return ;
286+
287+ const totals = { } ;
288+ details . forEach ( acc => {
289+ ( acc . users || [ ] ) . forEach ( u => {
290+ totals [ u . user ] = ( totals [ u . user ] || 0 ) + ( u . core_hours || 0 ) ;
291+ } ) ;
287292 } ) ;
288- } ) ;
289- const entries = Object . entries ( totals ) . map ( ( [ user , core ] ) => ( { user, core } ) ) ;
290- entries . sort ( ( a , b ) => b . core - a . core ) ;
291- const top = entries . slice ( 0 , 10 ) ;
292- const max = top [ 0 ] ? top [ 0 ] . core : 0 ;
293+
294+ const entries = Object . entries ( totals ) . map ( ( [ user , core ] ) => ( { user, core } ) ) ;
295+ entries . sort ( ( a , b ) => b . core - a . core ) ;
296+ const top = entries . slice ( 0 , 10 ) ;
297+
298+ const colors = [
299+ '#4e79a7' ,
300+ '#f28e2b' ,
301+ '#e15759' ,
302+ '#76b7b2' ,
303+ '#59a14f' ,
304+ '#edc949' ,
305+ '#af7aa1' ,
306+ '#ff9da7' ,
307+ '#9c755f' ,
308+ '#bab0ac'
309+ ] ;
310+
311+ const chart = new Chart ( canvasRef . current . getContext ( '2d' ) , {
312+ type : 'pie' ,
313+ data : {
314+ labels : top . map ( e => e . user ) ,
315+ datasets : [
316+ {
317+ data : top . map ( e => e . core ) ,
318+ backgroundColor : colors . slice ( 0 , top . length )
319+ }
320+ ]
321+ } ,
322+ options : {
323+ responsive : false ,
324+ maintainAspectRatio : false ,
325+ plugins : {
326+ legend : { position : 'right' }
327+ }
328+ }
329+ } ) ;
330+
331+ return ( ) => chart . destroy ( ) ;
332+ } , [ details ] ) ;
333+
293334 return React . createElement (
294- 'table' ,
295- { className : 'pi-table' } ,
296- React . createElement (
297- 'thead' ,
298- null ,
299- React . createElement (
300- 'tr' ,
301- null ,
302- React . createElement ( 'th' , null , 'PI' ) ,
303- React . createElement ( 'th' , null , 'CPU Hours' )
304- )
305- ) ,
306- React . createElement (
307- 'tbody' ,
308- null ,
309- top . map ( ( e , i ) =>
310- React . createElement (
311- 'tr' ,
312- { key : i } ,
313- React . createElement ( 'td' , null , e . user ) ,
314- React . createElement (
315- 'td' ,
316- null ,
317- React . createElement (
318- 'div' ,
319- { style : { display : 'flex' , alignItems : 'center' } } ,
320- React . createElement ( 'div' , {
321- className : 'pi-bar' ,
322- style : { width : `${ max ? ( e . core / max ) * 100 : 0 } %` }
323- } ) ,
324- React . createElement ( 'span' , { style : { marginLeft : '0.5em' } } , e . core )
325- )
326- )
327- )
328- )
329- )
335+ 'div' ,
336+ { className : 'chart-container' , style : { width : '300px' , height : '300px' } } ,
337+ React . createElement ( 'canvas' , { ref : canvasRef , width : 300 , height : 300 } )
330338 ) ;
331339}
332340
@@ -496,7 +504,7 @@ function Summary({ summary, details, daily, monthly }) {
496504 } )
497505 ) ,
498506 React . createElement ( 'h3' , null , 'Top 10 PIs by consumption' ) ,
499- React . createElement ( PiConsumptionTable , { details } ) ,
507+ React . createElement ( PiConsumptionChart , { details } ) ,
500508 React . createElement ( 'h3' , null , 'CPU/GPU-hrs per Slurm account' ) ,
501509 React . createElement ( AccountsChart , { details } ) ,
502510 React . createElement ( 'h3' , null , 'Historical CPU/GPU-hrs (monthly)' ) ,
0 commit comments