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
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:
@ -1,7 +1,7 @@
|
|||||||
import js from '@eslint/js';
|
import js from '@eslint/js';
|
||||||
import tseslint from '@typescript-eslint/eslint-plugin';
|
import tseslint from '@typescript-eslint/eslint-plugin';
|
||||||
import tsparser from '@typescript-eslint/parser';
|
import tsparser from '@typescript-eslint/parser';
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks';
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
files: ['src/**/*.{ts,tsx}'],
|
files: ['src/**/*.{ts,tsx}'],
|
||||||
@ -16,6 +16,7 @@ export default [
|
|||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
'@typescript-eslint': tseslint,
|
'@typescript-eslint': tseslint,
|
||||||
|
'react-hooks': reactHooks,
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
// Error rules
|
// Error rules
|
||||||
@ -42,6 +43,8 @@ export default [
|
|||||||
'no-var': 'error',
|
'no-var': 'error',
|
||||||
'eqeqeq': ['error', 'always'],
|
'eqeqeq': ['error', 'always'],
|
||||||
'curly': ['error', 'multi-line'],
|
'curly': ['error', 'multi-line'],
|
||||||
|
'react-hooks/rules-of-hooks': 'error',
|
||||||
|
'react-hooks/exhaustive-deps': 'warn',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
"@typescript-eslint/parser": "^8.30.0",
|
"@typescript-eslint/parser": "^8.30.0",
|
||||||
"@vitejs/plugin-react": "^4.4.1",
|
"@vitejs/plugin-react": "^4.4.1",
|
||||||
"eslint": "^9.24.0",
|
"eslint": "^9.24.0",
|
||||||
|
"eslint-plugin-react-hooks": "^5.0.0",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vite": "^6.3.3"
|
"vite": "^6.3.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import axios, { type AxiosError } from 'axios'
|
import axios, { type AxiosError, type InternalAxiosRequestConfig } from 'axios'
|
||||||
import type { InternalAxiosRequestConfig } from 'axios'
|
|
||||||
import { useAuthStore } from '../store/authStore'
|
import { useAuthStore } from '../store/authStore'
|
||||||
import type {
|
import type {
|
||||||
FleetStatus,
|
FleetStatus,
|
||||||
|
|||||||
@ -111,7 +111,7 @@ export function useJobWebSocket(options: JobWsOptions = {}): JobWsState {
|
|||||||
|
|
||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
if (!mountedRef.current) { ws.close(); return }
|
if (!mountedRef.current) { ws.close(); return }
|
||||||
console.debug('[JobWS] Connected')
|
console.warn('[JobWS] Connected')
|
||||||
backoffRef.current = BACKOFF_INITIAL_MS // reset backoff on successful connect
|
backoffRef.current = BACKOFF_INITIAL_MS // reset backoff on successful connect
|
||||||
setConnected(true)
|
setConnected(true)
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ export function useJobWebSocket(options: JobWsOptions = {}): JobWsState {
|
|||||||
|
|
||||||
ws.onclose = () => {
|
ws.onclose = () => {
|
||||||
if (!mountedRef.current) return
|
if (!mountedRef.current) return
|
||||||
console.debug('[JobWS] Disconnected — scheduling reconnect')
|
console.warn('[JobWS] Disconnected — scheduling reconnect')
|
||||||
setConnected(false)
|
setConnected(false)
|
||||||
wsRef.current = null
|
wsRef.current = null
|
||||||
scheduleReconnect()
|
scheduleReconnect()
|
||||||
@ -147,7 +147,7 @@ export function useJobWebSocket(options: JobWsOptions = {}): JobWsState {
|
|||||||
clearRetryTimer()
|
clearRetryTimer()
|
||||||
const delay = backoffRef.current
|
const delay = backoffRef.current
|
||||||
backoffRef.current = Math.min(delay * BACKOFF_FACTOR, BACKOFF_MAX_MS)
|
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(() => {
|
retryTimerRef.current = setTimeout(() => {
|
||||||
if (mountedRef.current) connect()
|
if (mountedRef.current) connect()
|
||||||
}, delay)
|
}, delay)
|
||||||
|
|||||||
@ -4,7 +4,9 @@ import { BrowserRouter } from 'react-router-dom'
|
|||||||
import App from './App'
|
import App from './App'
|
||||||
import './index.css'
|
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>
|
<React.StrictMode>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<App />
|
<App />
|
||||||
|
|||||||
@ -64,11 +64,11 @@ function scheduleDescription(w: MaintenanceWindow): string {
|
|||||||
case 'daily':
|
case 'daily':
|
||||||
return `Every day at ${time} for ${dur}`
|
return `Every day at ${time} for ${dur}`
|
||||||
case 'weekly': {
|
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}`
|
return `Every ${day} at ${time} for ${dur}`
|
||||||
}
|
}
|
||||||
case 'monthly': {
|
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}`
|
return `Monthly on day ${day} at ${time} for ${dur}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,7 @@ import {
|
|||||||
} from '@mui/material'
|
} from '@mui/material'
|
||||||
import { Add as AddIcon, Refresh as RefreshIcon, Delete as DeleteIcon } from '@mui/icons-material'
|
import { Add as AddIcon, Refresh as RefreshIcon, Delete as DeleteIcon } from '@mui/icons-material'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { apiClient } from '../api/client'
|
import { apiClient, hostsApi } from '../api/client'
|
||||||
import { hostsApi } from '../api/client'
|
|
||||||
import type { Host, HostHealthStatus } from '../types'
|
import type { Host, HostHealthStatus } from '../types'
|
||||||
|
|
||||||
const statusColor = (s: HostHealthStatus) =>
|
const statusColor = (s: HostHealthStatus) =>
|
||||||
|
|||||||
@ -81,11 +81,11 @@ function scheduleDescription(w: MaintenanceWindow): string {
|
|||||||
case 'daily':
|
case 'daily':
|
||||||
return `Every day at ${time} for ${dur}`
|
return `Every day at ${time} for ${dur}`
|
||||||
case 'weekly': {
|
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}`
|
return `Every ${day} at ${time} for ${dur}`
|
||||||
}
|
}
|
||||||
case 'monthly': {
|
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}`
|
return `Monthly on day ${day} at ${time} for ${dur}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,7 +126,7 @@ export default function ReportsPage() {
|
|||||||
link.click()
|
link.click()
|
||||||
link.remove()
|
link.remove()
|
||||||
window.URL.revokeObjectURL(url)
|
window.URL.revokeObjectURL(url)
|
||||||
} catch (err: unknown) {
|
} catch (_err: unknown) {
|
||||||
setError('Failed to generate report. Please try again.')
|
setError('Failed to generate report. Please try again.')
|
||||||
} finally {
|
} finally {
|
||||||
setDownloading(false)
|
setDownloading(false)
|
||||||
|
|||||||
Reference in New Issue
Block a user