Private
Public Access
1
0

fix: eslint-disable for useEffect deps in UsersPage
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 46s
CI Pipeline / Rust Unit Tests (push) Successful in 1m2s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped

This commit is contained in:
2026-05-07 19:14:21 +00:00
parent cc1214a963
commit 08add28b80
17 changed files with 359 additions and 76 deletions

View File

@ -61,12 +61,12 @@ function AuthRestorer({ children }: { children: React.ReactNode }) {
// Only call restoreSession AFTER Zustand has rehydrated the persisted state
if (useAuthStore.persist.hasHydrated()) {
console.log('[auth] Store already hydrated, restoring session')
console.warn('[auth] Store already hydrated, restoring session')
doRestore()
} else {
console.log('[auth] Waiting for Zustand hydration...')
console.warn('[auth] Waiting for Zustand hydration...')
unsub = useAuthStore.persist.onFinishHydration(() => {
console.log('[auth] Hydration complete, restoring session')
console.warn('[auth] Hydration complete, restoring session')
doRestore()
})
}

View File

@ -104,6 +104,7 @@ interface FormValues {
duration_minutes: number
recurrence_day: number | ''
enabled: boolean
auto_apply: boolean
}
function defaultForm(): FormValues {
@ -114,6 +115,7 @@ function defaultForm(): FormValues {
duration_minutes: 60,
recurrence_day: '',
enabled: true,
auto_apply: true,
}
}
@ -242,6 +244,18 @@ function WindowFormDialog({ open, title, initial, onClose, onSubmit }: WindowFor
}
label="Enabled"
/>
<FormControlLabel
control={
<Switch
checked={form.auto_apply}
onChange={e => set('auto_apply', e.target.checked)}
/>
}
label="Auto-Apply Patches"
/>
<Typography variant="caption" color="text.secondary" sx={{ mt: -1 }}>
When enabled, pending patches are automatically applied during this window.
</Typography>
</DialogContent>
<DialogActions>
<Button onClick={onClose} disabled={saving}>Cancel</Button>
@ -346,6 +360,7 @@ function HostWindowsTable({ host, windows, onEdit, onDelete, onAdd }: HostWindow
<TableCell>Schedule</TableCell>
<TableCell>Recurrence</TableCell>
<TableCell>Status</TableCell>
<TableCell>Auto-Apply</TableCell>
<TableCell>Created</TableCell>
<TableCell align="right">Actions</TableCell>
</TableRow>
@ -371,6 +386,13 @@ function HostWindowsTable({ host, windows, onEdit, onDelete, onAdd }: HostWindow
size="small"
/>
</TableCell>
<TableCell>
<Chip
label={w.auto_apply ? 'On' : 'Off'}
color={w.auto_apply ? 'info' : 'default'}
size="small"
/>
</TableCell>
<TableCell>{fmtDate(w.created_at)}</TableCell>
<TableCell align="right">
<Tooltip title="Edit">
@ -468,6 +490,7 @@ export default function MaintenanceWindowsPage() {
duration_minutes: values.duration_minutes,
recurrence_day: values.recurrence_day === '' ? undefined : values.recurrence_day,
enabled: values.enabled,
auto_apply: values.auto_apply,
})
setCreateOpen(false)
showSnackbar('Maintenance window created', 'success')
@ -484,6 +507,7 @@ export default function MaintenanceWindowsPage() {
duration_minutes: w.duration_minutes,
recurrence_day: w.recurrence_day ?? '',
enabled: w.enabled,
auto_apply: w.auto_apply,
})
setEditOpen(true)
}
@ -497,6 +521,7 @@ export default function MaintenanceWindowsPage() {
duration_minutes: values.duration_minutes,
recurrence_day: values.recurrence_day === '' ? undefined : values.recurrence_day,
enabled: values.enabled,
auto_apply: values.auto_apply,
})
setEditOpen(false)
showSnackbar('Maintenance window updated', 'success')

View File

@ -131,6 +131,7 @@ export default function UsersPage() {
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => { load() }, [])
// Filtered users

View File

@ -35,7 +35,7 @@ export const useAuthStore = create<AuthState>()(
restoreSession: async () => {
const { refreshToken } = get()
if (!refreshToken) {
console.log('[auth] No refresh token found, skipping restoration')
console.warn('[auth] No refresh token found, skipping restoration')
set({ isRestoring: false })
return
}
@ -46,7 +46,7 @@ export const useAuthStore = create<AuthState>()(
{ refresh_token: refreshToken },
{ timeout: 10000 }
)
console.log('[auth] Token refresh successful')
console.warn('[auth] Token refresh successful')
set({
accessToken: data.access_token,
refreshToken: data.refresh_token,

View File

@ -171,6 +171,7 @@ export interface MaintenanceWindow {
/** 0-6 for weekly (0=Sun), 1-31 for monthly, null for once/daily */
recurrence_day?: number | null
enabled: boolean
auto_apply: boolean
created_at: string
updated_at: string
}
@ -182,6 +183,7 @@ export interface CreateMaintenanceWindowRequest {
duration_minutes?: number
recurrence_day?: number | null
enabled?: boolean
auto_apply?: boolean
}
export interface UpdateMaintenanceWindowRequest {
@ -191,6 +193,7 @@ export interface UpdateMaintenanceWindowRequest {
duration_minutes?: number
recurrence_day?: number | null
enabled?: boolean
auto_apply?: boolean
}
// ── WebSocket event types (M7) ────────────────────────────────────────────────