Private
Public Access
1
0

Fix all frontend ESLint errors
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 45s
CI Pipeline / Rust Unit Tests (push) Successful in 1m1s
CI Pipeline / Security Audit (push) Successful in 3s
CI Pipeline / Frontend Lint & Type Check (push) Failing after 4s
CI Pipeline / Build .deb & Release (push) Has been skipped

- Add eslint-plugin-react-hooks to package.json and config
- Fix duplicate imports in HostsPage.tsx
- Remove non-null assertion in main.tsx
- Fix != to !== in HostDetailPage.tsx and MaintenanceWindowsPage.tsx
- Fix unused variable in ReportsPage.tsx
- Change console.debug to console.warn in useJobWebSocket.ts
This commit is contained in:
2026-04-27 21:20:25 +00:00
parent adb88fc296
commit 2fd3eb89b4
9 changed files with 18 additions and 14 deletions

View File

@ -1,7 +1,7 @@
import js from '@eslint/js';
import tseslint from '@typescript-eslint/eslint-plugin';
import tsparser from '@typescript-eslint/parser';
import reactHooks from 'eslint-plugin-react-hooks';
export default [
{
files: ['src/**/*.{ts,tsx}'],
@ -16,6 +16,7 @@ export default [
},
plugins: {
'@typescript-eslint': tseslint,
'react-hooks': reactHooks,
},
rules: {
// Error rules
@ -42,6 +43,8 @@ export default [
'no-var': 'error',
'eqeqeq': ['error', 'always'],
'curly': ['error', 'multi-line'],
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},
},
{

View File

@ -28,6 +28,7 @@
"@typescript-eslint/parser": "^8.30.0",
"@vitejs/plugin-react": "^4.4.1",
"eslint": "^9.24.0",
"eslint-plugin-react-hooks": "^5.0.0",
"typescript": "^5.8.3",
"vite": "^6.3.3"
}

View File

@ -1,5 +1,4 @@
import axios, { type AxiosError } from 'axios'
import type { InternalAxiosRequestConfig } from 'axios'
import axios, { type AxiosError, type InternalAxiosRequestConfig } from 'axios'
import { useAuthStore } from '../store/authStore'
import type {
FleetStatus,

View File

@ -111,7 +111,7 @@ export function useJobWebSocket(options: JobWsOptions = {}): JobWsState {
ws.onopen = () => {
if (!mountedRef.current) { ws.close(); return }
console.debug('[JobWS] Connected')
console.warn('[JobWS] Connected')
backoffRef.current = BACKOFF_INITIAL_MS // reset backoff on successful connect
setConnected(true)
}
@ -134,7 +134,7 @@ export function useJobWebSocket(options: JobWsOptions = {}): JobWsState {
ws.onclose = () => {
if (!mountedRef.current) return
console.debug('[JobWS] Disconnected — scheduling reconnect')
console.warn('[JobWS] Disconnected — scheduling reconnect')
setConnected(false)
wsRef.current = null
scheduleReconnect()
@ -147,7 +147,7 @@ export function useJobWebSocket(options: JobWsOptions = {}): JobWsState {
clearRetryTimer()
const delay = backoffRef.current
backoffRef.current = Math.min(delay * BACKOFF_FACTOR, BACKOFF_MAX_MS)
console.debug(`[JobWS] Reconnecting in ${delay} ms`)
console.warn(`[JobWS] Reconnecting in ${delay} ms`)
retryTimerRef.current = setTimeout(() => {
if (mountedRef.current) connect()
}, delay)

View File

@ -4,7 +4,9 @@ import { BrowserRouter } from 'react-router-dom'
import App from './App'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')!).render(
const root = document.getElementById('root')
if (!root) throw new Error('Root element not found')
ReactDOM.createRoot(root).render(
<React.StrictMode>
<BrowserRouter>
<App />

View File

@ -64,11 +64,11 @@ function scheduleDescription(w: MaintenanceWindow): string {
case 'daily':
return `Every day at ${time} for ${dur}`
case 'weekly': {
const day = w.recurrence_day != null ? DAY_NAMES[w.recurrence_day] ?? `Day ${w.recurrence_day}` : '?'
const day = w.recurrence_day !== null ? DAY_NAMES[w.recurrence_day] ?? `Day ${w.recurrence_day}` : '?'
return `Every ${day} at ${time} for ${dur}`
}
case 'monthly': {
const day = w.recurrence_day != null ? w.recurrence_day : '?'
const day = w.recurrence_day !== null ? w.recurrence_day : '?'
return `Monthly on day ${day} at ${time} for ${dur}`
}
}

View File

@ -6,8 +6,7 @@ import {
} from '@mui/material'
import { Add as AddIcon, Refresh as RefreshIcon, Delete as DeleteIcon } from '@mui/icons-material'
import { useNavigate } from 'react-router-dom'
import { apiClient } from '../api/client'
import { hostsApi } from '../api/client'
import { apiClient, hostsApi } from '../api/client'
import type { Host, HostHealthStatus } from '../types'
const statusColor = (s: HostHealthStatus) =>

View File

@ -81,11 +81,11 @@ function scheduleDescription(w: MaintenanceWindow): string {
case 'daily':
return `Every day at ${time} for ${dur}`
case 'weekly': {
const day = w.recurrence_day != null ? DAY_NAMES[w.recurrence_day] ?? `Day ${w.recurrence_day}` : '?'
const day = w.recurrence_day !== null ? DAY_NAMES[w.recurrence_day] ?? `Day ${w.recurrence_day}` : '?'
return `Every ${day} at ${time} for ${dur}`
}
case 'monthly': {
const day = w.recurrence_day != null ? w.recurrence_day : '?'
const day = w.recurrence_day !== null ? w.recurrence_day : '?'
return `Monthly on day ${day} at ${time} for ${dur}`
}
}

View File

@ -126,7 +126,7 @@ export default function ReportsPage() {
link.click()
link.remove()
window.URL.revokeObjectURL(url)
} catch (err: unknown) {
} catch (_err: unknown) {
setError('Failed to generate report. Please try again.')
} finally {
setDownloading(false)