@@ -27,7 +27,7 @@ import {
2727 useUserSecrets ,
2828 useUsers ,
2929} from "@/hooks/useApi" ;
30- import { fmtTime } from "@/lib/format" ;
30+ import { fmtInt , fmtTime } from "@/lib/format" ;
3131import type { OrgUser } from "@/types/api" ;
3232
3333export function UsersPage ( ) {
@@ -66,6 +66,14 @@ export function UsersPage() {
6666 return v ? < Badge variant = "secondary" > { v } </ Badge > : < span className = "text-muted-foreground" > —</ span > ;
6767 } ,
6868 } ,
69+ {
70+ accessorKey : "max_vcpus" ,
71+ header : "Max vCPUs" ,
72+ cell : ( { getValue } ) => {
73+ const v = getValue ( ) as number ;
74+ return < span className = "tabular-nums" > { v === 0 ? "∞" : fmtInt ( v ) } </ span > ;
75+ } ,
76+ } ,
6977 {
7078 accessorKey : "created_at" ,
7179 header : "Created" ,
@@ -125,7 +133,7 @@ export function UsersPage() {
125133 < PageBody >
126134 < Card className = "overflow-hidden" >
127135 { users . isLoading ? (
128- < TableSkeleton cols = { 6 } />
136+ < TableSkeleton cols = { 7 } />
129137 ) : users . isError ? (
130138 < ErrorState error = { users . error } onRetry = { ( ) => users . refetch ( ) } />
131139 ) : (
@@ -186,6 +194,7 @@ function CreateUserDialog({ onClose }: { onClose: () => void }) {
186194 const [ password , setPassword ] = useState ( "" ) ;
187195 const [ passthrough , setPassthrough ] = useState ( false ) ;
188196 const [ iceberg , setIceberg ] = useState ( false ) ;
197+ const [ maxVCPUs , setMaxVCPUs ] = useState ( "0" ) ;
189198 const [ err , setErr ] = useState < string | null > ( null ) ;
190199
191200 const submit = async ( ) => {
@@ -197,6 +206,7 @@ function CreateUserDialog({ onClose }: { onClose: () => void }) {
197206 password,
198207 passthrough,
199208 default_catalog : iceberg ? "iceberg" : "" ,
209+ max_vcpus : Number ( maxVCPUs ) || 0 ,
200210 } ) ;
201211 onClose ( ) ;
202212 } catch ( e ) {
@@ -226,6 +236,10 @@ function CreateUserDialog({ onClose }: { onClose: () => void }) {
226236 < Label > Password</ Label >
227237 < Input type = "password" value = { password } onChange = { ( e ) => setPassword ( e . target . value ) } />
228238 </ div >
239+ < div className = "space-y-1" >
240+ < Label > Max vCPUs (0 = unbounded)</ Label >
241+ < Input type = "number" min = { 0 } value = { maxVCPUs } onChange = { ( e ) => setMaxVCPUs ( e . target . value ) } />
242+ </ div >
229243 < div className = "flex items-center gap-6" >
230244 < label className = "flex items-center gap-2 text-sm" >
231245 < Switch checked = { passthrough } onCheckedChange = { setPassthrough } /> Passthrough
@@ -254,6 +268,7 @@ function EditUserDialog({ user, onClose }: { user: OrgUser; onClose: () => void
254268 const [ password , setPassword ] = useState ( "" ) ;
255269 const [ passthrough , setPassthrough ] = useState ( user . passthrough ) ;
256270 const [ iceberg , setIceberg ] = useState ( user . default_catalog === "iceberg" ) ;
271+ const [ maxVCPUs , setMaxVCPUs ] = useState ( String ( user . max_vcpus ) ) ;
257272 const [ err , setErr ] = useState < string | null > ( null ) ;
258273
259274 const submit = async ( ) => {
@@ -266,6 +281,7 @@ function EditUserDialog({ user, onClose }: { user: OrgUser; onClose: () => void
266281 ...( password ? { password } : { } ) ,
267282 passthrough,
268283 default_catalog : iceberg ? "iceberg" : "" ,
284+ max_vcpus : Number ( maxVCPUs ) || 0 ,
269285 } ,
270286 } ) ;
271287 onClose ( ) ;
@@ -290,6 +306,10 @@ function EditUserDialog({ user, onClose }: { user: OrgUser; onClose: () => void
290306 < Label > New password</ Label >
291307 < Input type = "password" value = { password } onChange = { ( e ) => setPassword ( e . target . value ) } placeholder = "unchanged" />
292308 </ div >
309+ < div className = "space-y-1" >
310+ < Label > Max vCPUs (0 = unbounded)</ Label >
311+ < Input type = "number" min = { 0 } value = { maxVCPUs } onChange = { ( e ) => setMaxVCPUs ( e . target . value ) } />
312+ </ div >
293313 < div className = "flex items-center gap-6" >
294314 < label className = "flex items-center gap-2 text-sm" >
295315 < Switch checked = { passthrough } onCheckedChange = { setPassthrough } /> Passthrough
0 commit comments