@@ -840,6 +840,7 @@ function Details({ details, daily, partitions = [], accounts = [], users = [] })
840840function Rates ( { onRatesUpdated } ) {
841841 const [ config , setConfig ] = useState ( null ) ;
842842 const [ overrides , setOverrides ] = useState ( [ ] ) ;
843+ const [ accounts , setAccounts ] = useState ( [ ] ) ;
843844 const [ error , setError ] = useState ( null ) ;
844845 const [ saving , setSaving ] = useState ( false ) ;
845846 const [ status , setStatus ] = useState ( null ) ;
@@ -864,7 +865,7 @@ function Rates({ onRatesUpdated }) {
864865 ? Object . entries ( json . overrides ) . map ( ( [ account , cfg ] ) => ( {
865866 account,
866867 rate : cfg . rate ?? '' ,
867- discount : cfg . discount ?? ''
868+ discount : cfg . discount != null ? cfg . discount * 100 : ''
868869 } ) )
869870 : [ ] ;
870871 setOverrides ( ovrs ) ;
@@ -879,6 +880,41 @@ function Rates({ onRatesUpdated }) {
879880 } ;
880881 } , [ ] ) ;
881882
883+ useEffect ( ( ) => {
884+ let cancelled = false ;
885+ async function loadAccounts ( ) {
886+ try {
887+ let json ;
888+ if ( window . cockpit && window . cockpit . spawn ) {
889+ const { start, end } = getBillingPeriod ( ) ;
890+ const args = [
891+ 'python3' ,
892+ `${ PLUGIN_BASE } /slurmdb.py` ,
893+ '--start' ,
894+ start ,
895+ '--end' ,
896+ end ,
897+ '--output' ,
898+ '-' ,
899+ ] ;
900+ const output = await window . cockpit . spawn ( args , { err : 'message' } ) ;
901+ json = JSON . parse ( output ) ;
902+ } else {
903+ const resp = await fetch ( 'billing.json' ) ;
904+ if ( ! resp . ok ) throw new Error ( 'Failed to fetch billing data' ) ;
905+ json = await resp . json ( ) ;
906+ }
907+ if ( ! cancelled ) setAccounts ( json . accounts || [ ] ) ;
908+ } catch ( e ) {
909+ console . error ( e ) ;
910+ }
911+ }
912+ loadAccounts ( ) ;
913+ return ( ) => {
914+ cancelled = true ;
915+ } ;
916+ } , [ ] ) ;
917+
882918 function updateOverride ( index , field , value ) {
883919 setOverrides ( prev =>
884920 prev . map ( ( o , i ) => ( i === index ? { ...o , [ field ] : value } : o ) )
@@ -924,7 +960,7 @@ function Rates({ onRatesUpdated }) {
924960 if ( o . discount !== '' ) {
925961 const discount = parseFloat ( o . discount ) ;
926962 if ( Number . isFinite ( discount ) ) {
927- entry . discount = discount ;
963+ entry . discount = discount / 100 ;
928964 } else {
929965 console . warn (
930966 `Ignoring invalid discount for account ${ o . account } :` ,
@@ -994,7 +1030,7 @@ function Rates({ onRatesUpdated }) {
9941030 null ,
9951031 React . createElement ( 'th' , null , 'Account' ) ,
9961032 React . createElement ( 'th' , null , 'Rate' ) ,
997- React . createElement ( 'th' , null , 'Discount' ) ,
1033+ React . createElement ( 'th' , null , 'Discount (%) ' ) ,
9981034 React . createElement ( 'th' , null )
9991035 )
10001036 ) ,
@@ -1005,12 +1041,22 @@ function Rates({ onRatesUpdated }) {
10051041 React . createElement (
10061042 'tr' ,
10071043 { key : idx } ,
1008- React . createElement ( 'td' , null ,
1009- React . createElement ( 'input' , {
1010- value : o . account ,
1011- onChange : e =>
1012- updateOverride ( idx , 'account' , e . target . value )
1013- } )
1044+ React . createElement (
1045+ 'td' ,
1046+ null ,
1047+ React . createElement (
1048+ 'select' ,
1049+ {
1050+ value : o . account ,
1051+ onChange : e => updateOverride ( idx , 'account' , e . target . value )
1052+ } ,
1053+ [
1054+ React . createElement ( 'option' , { key : '' , value : '' } , '' ) ,
1055+ ...accounts . map ( acct =>
1056+ React . createElement ( 'option' , { key : acct , value : acct } , acct )
1057+ )
1058+ ]
1059+ )
10141060 ) ,
10151061 React . createElement ( 'td' , null ,
10161062 React . createElement ( 'input' , {
@@ -1024,7 +1070,7 @@ function Rates({ onRatesUpdated }) {
10241070 React . createElement ( 'td' , null ,
10251071 React . createElement ( 'input' , {
10261072 type : 'number' ,
1027- step : '0.01 ' ,
1073+ step : '0.1 ' ,
10281074 value : o . discount ,
10291075 onChange : e =>
10301076 updateOverride ( idx , 'discount' , e . target . value )
0 commit comments