@@ -12,24 +12,37 @@ const PLUGIN_BASE =
1212 window . cockpit . manifest . path ) ||
1313 '/usr/share/cockpit/slurmcostmanager' ;
1414
15- function getBillingPeriod ( now = new Date ( ) ) {
16- const end = new Date ( Date . UTC ( now . getFullYear ( ) , now . getMonth ( ) , now . getDate ( ) ) ) ;
17- const start = new Date ( Date . UTC ( now . getFullYear ( ) , now . getMonth ( ) , 1 ) ) ;
15+ function getBillingPeriod ( ref = new Date ( ) ) {
16+ const today = new Date ( ) ;
17+ let year , month , end ;
18+ if ( typeof ref === 'string' ) {
19+ [ year , month ] = ref . split ( '-' ) . map ( Number ) ;
20+ month -= 1 ;
21+ const isCurrent = year === today . getFullYear ( ) && month === today . getMonth ( ) ;
22+ end = isCurrent
23+ ? new Date ( Date . UTC ( today . getFullYear ( ) , today . getMonth ( ) , today . getDate ( ) ) )
24+ : new Date ( Date . UTC ( year , month + 1 , 0 ) ) ;
25+ } else {
26+ year = ref . getFullYear ( ) ;
27+ month = ref . getMonth ( ) ;
28+ end = new Date ( Date . UTC ( year , month , ref . getDate ( ) ) ) ;
29+ }
30+ const start = new Date ( Date . UTC ( year , month , 1 ) ) ;
1831 return {
1932 start : start . toISOString ( ) . slice ( 0 , 10 ) ,
2033 end : end . toISOString ( ) . slice ( 0 , 10 )
2134 } ;
2235}
2336
24- function useBillingData ( ) {
37+ function useBillingData ( month ) {
2538 const [ data , setData ] = useState ( null ) ;
2639 const [ error , setError ] = useState ( null ) ;
2740
2841 const load = useCallback ( async ( ) => {
2942 try {
3043 let json ;
3144 if ( window . cockpit && window . cockpit . spawn ) {
32- const { start, end } = getBillingPeriod ( ) ;
45+ const { start, end } = getBillingPeriod ( month ) ;
3346 const args = [
3447 'python3' ,
3548 `${ PLUGIN_BASE } /slurmdb.py` ,
@@ -53,7 +66,7 @@ function useBillingData() {
5366 console . error ( e ) ;
5467 setError ( e . message || String ( e ) ) ;
5568 }
56- } , [ ] ) ;
69+ } , [ month ] ) ;
5770
5871 useEffect ( ( ) => {
5972 load ( ) ;
@@ -1049,8 +1062,18 @@ function Rates({ onRatesUpdated }) {
10491062
10501063function App ( ) {
10511064 const [ view , setView ] = useState ( 'summary' ) ;
1052- const { data, error, reload } = useBillingData ( ) ;
1065+ const now = new Date ( ) ;
1066+ const defaultMonth = `${ now . getFullYear ( ) } -${ String ( now . getMonth ( ) + 1 ) . padStart (
1067+ 2 ,
1068+ '0'
1069+ ) } `;
1070+ const [ month , setMonth ] = useState ( defaultMonth ) ;
1071+ const { data, error, reload } = useBillingData ( month ) ;
10531072 const [ showErrorDetails , setShowErrorDetails ] = useState ( false ) ;
1073+ const monthOptions = Array . from (
1074+ { length : now . getMonth ( ) + 1 } ,
1075+ ( _ , i ) => `${ now . getFullYear ( ) } -${ String ( i + 1 ) . padStart ( 2 , '0' ) } `
1076+ ) ;
10541077
10551078 return React . createElement (
10561079 'div' ,
@@ -1074,6 +1097,23 @@ function App() {
10741097 'Settings'
10751098 )
10761099 ) ,
1100+ view !== 'settings' &&
1101+ React . createElement (
1102+ 'div' ,
1103+ { className : 'month-select' } ,
1104+ React . createElement (
1105+ 'label' ,
1106+ null ,
1107+ 'Month: ' ,
1108+ React . createElement (
1109+ 'select' ,
1110+ { value : month , onChange : e => setMonth ( e . target . value ) } ,
1111+ monthOptions . map ( m =>
1112+ React . createElement ( 'option' , { key : m , value : m } , m )
1113+ )
1114+ )
1115+ )
1116+ ) ,
10771117 view !== 'settings' && ! data && ! error && React . createElement ( 'p' , null , 'Loading...' ) ,
10781118 view !== 'settings' &&
10791119 error &&
0 commit comments