From f5202f596dfcc517b6dbdeeea95e9ce661a50288 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Fri, 28 Mar 2025 12:25:04 +0100 Subject: [PATCH] Fix all ESLint errors --- .drone.yml | 1 + virtweb_frontend/eslint.config.js | 1 + virtweb_frontend/src/api/ApiClient.ts | 29 ++++++++++--------- virtweb_frontend/src/routes/EditVMRoute.tsx | 6 ++-- virtweb_frontend/src/routes/IsoFilesRoute.tsx | 2 +- .../src/routes/NetworkFiltersListRoute.tsx | 10 ++++--- virtweb_frontend/src/routes/SysInfoRoute.tsx | 1 + .../src/routes/TokensListRoute.tsx | 5 ++-- virtweb_frontend/src/routes/VMListRoute.tsx | 12 +++++--- virtweb_frontend/src/routes/VNCRoute.tsx | 12 +++++--- virtweb_frontend/src/utils/RandUtils.ts | 3 +- virtweb_frontend/src/widgets/AsyncWidget.tsx | 2 +- .../src/widgets/ConfigImportExportButtons.tsx | 8 +++-- .../src/widgets/StateActionButton.tsx | 2 +- virtweb_frontend/src/widgets/TabsWidget.tsx | 5 +++- .../src/widgets/forms/EditSection.tsx | 1 + .../src/widgets/forms/IPInput.tsx | 3 +- .../forms/NWFSelectReferencedFilters.tsx | 2 ++ .../src/widgets/forms/NWFilterSelectInput.tsx | 6 ++-- .../src/widgets/forms/RadioGroupInput.tsx | 5 +++- .../src/widgets/forms/VMNetworksList.tsx | 2 +- 21 files changed, 74 insertions(+), 44 deletions(-) diff --git a/.drone.yml b/.drone.yml index 8c8194e..b074e26 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,6 +12,7 @@ steps: commands: - cd virtweb_frontend - npm install --legacy-peer-deps # TODO : remove when mui-file-input is updated + - npm run lint - npm run build - mv dist /tmp/web_build diff --git a/virtweb_frontend/eslint.config.js b/virtweb_frontend/eslint.config.js index 56bdec9..ce416c6 100644 --- a/virtweb_frontend/eslint.config.js +++ b/virtweb_frontend/eslint.config.js @@ -46,6 +46,7 @@ export default tseslint.config( "@typescript-eslint/no-unsafe-assignment": "off", "@typescript-eslint/no-unsafe-return": "off", "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/no-unsafe-member-access": "off", "@typescript-eslint/no-unsafe-argument": "off", "react-refresh/only-export-components": "off", }, diff --git a/virtweb_frontend/src/api/ApiClient.ts b/virtweb_frontend/src/api/ApiClient.ts index 7cb9445..49558b5 100644 --- a/virtweb_frontend/src/api/ApiClient.ts +++ b/virtweb_frontend/src/api/ApiClient.ts @@ -66,22 +66,25 @@ export class APIClient { if (args.upProgress) { const res: XMLHttpRequest = await new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); - xhr.upload.addEventListener("progress", (e) => - { args.upProgress!(e.loaded / e.total); } - ); - xhr.addEventListener("load", () => { resolve(xhr); }); - xhr.addEventListener("error", () => - { reject(new Error("File upload failed")); } - ); - xhr.addEventListener("abort", () => - { reject(new Error("File upload aborted")); } - ); - xhr.addEventListener("timeout", () => - { reject(new Error("File upload timeout")); } - ); + xhr.upload.addEventListener("progress", (e) => { + args.upProgress!(e.loaded / e.total); + }); + xhr.addEventListener("load", () => { + resolve(xhr); + }); + xhr.addEventListener("error", () => { + reject(new Error("File upload failed")); + }); + xhr.addEventListener("abort", () => { + reject(new Error("File upload aborted")); + }); + xhr.addEventListener("timeout", () => { + reject(new Error("File upload timeout")); + }); xhr.open(args.method, url, true); xhr.withCredentials = true; for (const key in headers) { + // eslint-disable-next-line no-prototype-builtins if (headers.hasOwnProperty(key)) xhr.setRequestHeader(key, headers[key]); } diff --git a/virtweb_frontend/src/routes/EditVMRoute.tsx b/virtweb_frontend/src/routes/EditVMRoute.tsx index 6d1e401..3c09f13 100644 --- a/virtweb_frontend/src/routes/EditVMRoute.tsx +++ b/virtweb_frontend/src/routes/EditVMRoute.tsx @@ -15,7 +15,7 @@ export function CreateVMRoute(): React.ReactElement { const alert = useAlert(); const navigate = useNavigate(); - const [vm, setVM] = React.useState(VMInfo.NewEmpty); + const [vm, setVM] = React.useState(VMInfo.NewEmpty()); const create = async (v: VMInfo) => { try { @@ -103,7 +103,9 @@ function EditVMInner(p: { const [changed, setChanged] = React.useState(false); const [, updateState] = React.useState(); - const forceUpdate = React.useCallback(() => { updateState({}); }, []); + const forceUpdate = React.useCallback(() => { + updateState({}); + }, []); const valueChanged = () => { setChanged(true); diff --git a/virtweb_frontend/src/routes/IsoFilesRoute.tsx b/virtweb_frontend/src/routes/IsoFilesRoute.tsx index c30a6fd..3dc2e2d 100644 --- a/virtweb_frontend/src/routes/IsoFilesRoute.tsx +++ b/virtweb_frontend/src/routes/IsoFilesRoute.tsx @@ -206,7 +206,7 @@ function IsoFilesList(p: { try { const blob = await IsoFilesApi.Download(entry, setDlProgress); - await downloadBlob(blob, entry.filename); + downloadBlob(blob, entry.filename); } catch (e) { console.error(e); alert("Failed to download iso file!"); diff --git a/virtweb_frontend/src/routes/NetworkFiltersListRoute.tsx b/virtweb_frontend/src/routes/NetworkFiltersListRoute.tsx index 77d6845..7c5df6a 100644 --- a/virtweb_frontend/src/routes/NetworkFiltersListRoute.tsx +++ b/virtweb_frontend/src/routes/NetworkFiltersListRoute.tsx @@ -66,7 +66,7 @@ function NetworkFiltersListRouteInner(p: { const onlyBuiltin = visibleFilters === VisibleFilters.Builtin; return p.list.filter((f) => NWFilterIsBuiltin(f) === onlyBuiltin); - }, [visibleFilters]); + }, [visibleFilters, p.list]); return ( { setVisibleFilters(v); }} + onChange={(_ev, v) => { + setVisibleFilters(v); + }} aria-label="visible filters" > All @@ -130,8 +132,8 @@ function NetworkFiltersListRouteInner(p: {
    - {t.join_filters.map((f, n) => ( -
  • {f}
  • + {t.join_filters.map((f) => ( +
  • {f}
  • ))}
diff --git a/virtweb_frontend/src/routes/SysInfoRoute.tsx b/virtweb_frontend/src/routes/SysInfoRoute.tsx index 08c4c50..dd4c1eb 100644 --- a/virtweb_frontend/src/routes/SysInfoRoute.tsx +++ b/virtweb_frontend/src/routes/SysInfoRoute.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-x/no-array-index-key */ import { mdiHarddisk, mdiInformation, diff --git a/virtweb_frontend/src/routes/TokensListRoute.tsx b/virtweb_frontend/src/routes/TokensListRoute.tsx index ed162b2..8ed1b0e 100644 --- a/virtweb_frontend/src/routes/TokensListRoute.tsx +++ b/virtweb_frontend/src/routes/TokensListRoute.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-x/no-array-index-key */ import VisibilityIcon from "@mui/icons-material/Visibility"; import { Button, @@ -99,9 +100,9 @@ export function TokensListRouteInner(p: { {t.max_inactivity && timeDiff(0, t.max_inactivity)} - {t.rights.map((r) => { + {t.rights.map((r, n) => { return ( -
+
{r.verb} {r.path}
); diff --git a/virtweb_frontend/src/routes/VMListRoute.tsx b/virtweb_frontend/src/routes/VMListRoute.tsx index a36035b..065be57 100644 --- a/virtweb_frontend/src/routes/VMListRoute.tsx +++ b/virtweb_frontend/src/routes/VMListRoute.tsx @@ -115,8 +115,8 @@ function VMListWidget(p: { - {p.groups.map((g, num) => ( - + {p.groups.map((g) => ( + {p.groups.length > 1 && ( { toggleHiddenGroup(g); }} + onClick={() => { + toggleHiddenGroup(g); + }} > {!hiddenGroups.has(g) ? ( @@ -157,7 +159,9 @@ function VMListWidget(p: { { updateVMState(row, s); }} + onChange={(s) => { + updateVMState(row, s); + }} /> diff --git a/virtweb_frontend/src/routes/VNCRoute.tsx b/virtweb_frontend/src/routes/VNCRoute.tsx index 7e33933..6160e74 100644 --- a/virtweb_frontend/src/routes/VNCRoute.tsx +++ b/virtweb_frontend/src/routes/VNCRoute.tsx @@ -44,8 +44,8 @@ function VNCInner(p: { vm: VMInfo }): React.ReactElement { const [counter, setCounter] = React.useState(1); const [connected, setConnected] = React.useState(false); - const vncRef = React.createRef(); - const vncScreenRef = React.createRef(); + const vncRef = React.useRef(null); + const vncScreenRef = React.useRef(null); const connect = async (force: boolean) => { try { @@ -91,7 +91,9 @@ function VNCInner(p: { vm: VMInfo }): React.ReactElement { connect(false); if (vncRef.current) { - vncRef.current.onfullscreenchange = () => { setCounter(counter + 1); }; + vncRef.current.onfullscreenchange = () => { + setCounter(counter + 1); + }; } }); @@ -143,7 +145,9 @@ function VNCInner(p: { vm: VMInfo }): React.ReactElement { console.info("VNC disconnected " + token.url); disconnected(); }} - onConnect={() => { setConnected(true); }} + onConnect={() => { + setConnected(true); + }} />
diff --git a/virtweb_frontend/src/utils/RandUtils.ts b/virtweb_frontend/src/utils/RandUtils.ts index 3c2c85c..944de3d 100644 --- a/virtweb_frontend/src/utils/RandUtils.ts +++ b/virtweb_frontend/src/utils/RandUtils.ts @@ -2,8 +2,9 @@ * Generate a random MAC address */ export function randomMacAddress(prefix: string | undefined): string { + prefix = prefix ?? ""; let mac = "XX:XX:XX:XX:XX:XX"; - mac = prefix + mac.slice(prefix?.length); + mac = prefix + mac.slice(prefix.length); return mac.replace(/X/g, () => "0123456789abcdef".charAt(Math.floor(Math.random() * 16)) diff --git a/virtweb_frontend/src/widgets/AsyncWidget.tsx b/virtweb_frontend/src/widgets/AsyncWidget.tsx index d7424bb..c0d4de0 100644 --- a/virtweb_frontend/src/widgets/AsyncWidget.tsx +++ b/virtweb_frontend/src/widgets/AsyncWidget.tsx @@ -19,7 +19,7 @@ export function AsyncWidget(p: { }): React.ReactElement { const [state, setState] = useState(State.Loading); - const counter = useRef(null); + const counter = useRef(null); const load = async () => { try { diff --git a/virtweb_frontend/src/widgets/ConfigImportExportButtons.tsx b/virtweb_frontend/src/widgets/ConfigImportExportButtons.tsx index f966c58..9441c84 100644 --- a/virtweb_frontend/src/widgets/ConfigImportExportButtons.tsx +++ b/virtweb_frontend/src/widgets/ConfigImportExportButtons.tsx @@ -31,9 +31,11 @@ export function ConfigImportExportButtons(p: { fileEl.click(); // Wait for a file to be chosen - await new Promise((res, _rej) => - { fileEl.addEventListener("change", () => { res(null); }); } - ); + await new Promise((res) => { + fileEl.addEventListener("change", () => { + res(null); + }); + }); if ((fileEl.files?.length ?? 0) === 0) return null; diff --git a/virtweb_frontend/src/widgets/StateActionButton.tsx b/virtweb_frontend/src/widgets/StateActionButton.tsx index ed69ba9..5754d3f 100644 --- a/virtweb_frontend/src/widgets/StateActionButton.tsx +++ b/virtweb_frontend/src/widgets/StateActionButton.tsx @@ -23,7 +23,7 @@ export function StateActionButton(p: { p.onExecuted(); } catch (e) { console.error(e); - alert("Failed to perform action! " + e); + alert(`Failed to perform action! ${e}`); } }; diff --git a/virtweb_frontend/src/widgets/TabsWidget.tsx b/virtweb_frontend/src/widgets/TabsWidget.tsx index 9148662..dd4f759 100644 --- a/virtweb_frontend/src/widgets/TabsWidget.tsx +++ b/virtweb_frontend/src/widgets/TabsWidget.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-x/no-array-index-key */ import { Box, Tab, Tabs } from "@mui/material"; export interface TabWidgetOption { @@ -24,7 +25,9 @@ export function TabsWidget(p: { { updateActiveTab(newVal); }} + onChange={(_ev, newVal) => { + updateActiveTab(newVal); + }} > {activeOptions.map((o, index) => ( diff --git a/virtweb_frontend/src/widgets/forms/EditSection.tsx b/virtweb_frontend/src/widgets/forms/EditSection.tsx index 9545d8e..8974b3f 100644 --- a/virtweb_frontend/src/widgets/forms/EditSection.tsx +++ b/virtweb_frontend/src/widgets/forms/EditSection.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ import { Paper, Typography } from "@mui/material"; import React, { PropsWithChildren } from "react"; import Grid from "@mui/material/Grid"; diff --git a/virtweb_frontend/src/widgets/forms/IPInput.tsx b/virtweb_frontend/src/widgets/forms/IPInput.tsx index 46a4d02..48e921b 100644 --- a/virtweb_frontend/src/widgets/forms/IPInput.tsx +++ b/virtweb_frontend/src/widgets/forms/IPInput.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unnecessary-condition */ import React from "react"; import { TextInput } from "./TextInput"; @@ -32,7 +33,7 @@ export function IPInputWithMask(p: { const currValue = p.ipAndMask ?? - (p.ip ?? "") + (p.mask || showSlash.current ? "/" : "") + (p.mask ?? ""); + `${p.ip ?? ""}${p.mask || showSlash.current ? "/" : ""}${p.mask ?? ""}`; const { onValueChange, ...props } = p; return ( diff --git a/virtweb_frontend/src/widgets/forms/NWFSelectReferencedFilters.tsx b/virtweb_frontend/src/widgets/forms/NWFSelectReferencedFilters.tsx index ae1feb2..f6dee86 100644 --- a/virtweb_frontend/src/widgets/forms/NWFSelectReferencedFilters.tsx +++ b/virtweb_frontend/src/widgets/forms/NWFSelectReferencedFilters.tsx @@ -1,3 +1,5 @@ +/* eslint-disable react-x/no-array-index-key */ +/* eslint-disable react-hooks/exhaustive-deps */ import React from "react"; import { useNavigate } from "react-router-dom"; import { NWFilter, NWFilterURL } from "../../api/NWFilterApi"; diff --git a/virtweb_frontend/src/widgets/forms/NWFilterSelectInput.tsx b/virtweb_frontend/src/widgets/forms/NWFilterSelectInput.tsx index b28cb7c..980ea7c 100644 --- a/virtweb_frontend/src/widgets/forms/NWFilterSelectInput.tsx +++ b/virtweb_frontend/src/widgets/forms/NWFilterSelectInput.tsx @@ -25,9 +25,7 @@ export function NWFilterSelectInput(p: { value={selectedValue} onDelete={p.editable ? () => p.onChange?.(undefined) : undefined} onClick={ - !p.editable && selectedValue - ? () => navigate(NWFilterURL(selectedValue)) - : undefined + !p.editable ? () => navigate(NWFilterURL(selectedValue)) : undefined } /> ); @@ -48,7 +46,7 @@ export function NWFilterSelectInput(p: { renderInput={(params) => ( )} - renderOption={(_props, option, _state) => ( + renderOption={(_props, option) => ( { diff --git a/virtweb_frontend/src/widgets/forms/RadioGroupInput.tsx b/virtweb_frontend/src/widgets/forms/RadioGroupInput.tsx index 11cf4ba..6f0397a 100644 --- a/virtweb_frontend/src/widgets/forms/RadioGroupInput.tsx +++ b/virtweb_frontend/src/widgets/forms/RadioGroupInput.tsx @@ -24,10 +24,13 @@ export function RadioGroupInput(p: { { p.onValueChange(v); }} + onChange={(_ev, v) => { + p.onValueChange(v); + }} > {p.options.map((o) => ( } diff --git a/virtweb_frontend/src/widgets/forms/VMNetworksList.tsx b/virtweb_frontend/src/widgets/forms/VMNetworksList.tsx index b7e5f80..5585c5c 100644 --- a/virtweb_frontend/src/widgets/forms/VMNetworksList.tsx +++ b/virtweb_frontend/src/widgets/forms/VMNetworksList.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-x/no-array-index-key */ import { mdiNetworkOutline } from "@mdi/js"; import Icon from "@mdi/react"; import DeleteIcon from "@mui/icons-material/Delete"; @@ -51,7 +52,6 @@ export function VMNetworksList(p: { {p.vm.networks.map((n, num) => ( { p.vm.networks.splice(num, 1);