mirror of
https://github.com/luckfox-eng29/kvm.git
synced 2026-06-03 03:42:58 +02:00
Apply and Upgrade Eslint (#288)
* Upgrade ESLINT and fix issues * feat: add frontend linting job to GitHub Actions workflow * Move UI linting to separate file * More linting fixes * Remove pull_request trigger from UI linting workflow * Update UI linting workflow * Rename frontend-lint workflow to ui-lint for clarity
This commit is contained in:
@@ -1,19 +1,20 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { LuPower, LuTerminal, LuPlugZap } from "react-icons/lu";
|
||||
|
||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||
import Card, { GridCard } from "@components/Card";
|
||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||
import { Button } from "../Button";
|
||||
import { LuPower, LuTerminal, LuPlugZap } from "react-icons/lu";
|
||||
import { ATXPowerControl } from "@components/extensions/ATXPowerControl";
|
||||
import { DCPowerControl } from "@components/extensions/DCPowerControl";
|
||||
import { SerialConsole } from "@components/extensions/SerialConsole";
|
||||
import notifications from "../../notifications";
|
||||
import { Button } from "@components/Button";
|
||||
import notifications from "@/notifications";
|
||||
|
||||
interface Extension {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
icon: any;
|
||||
icon: React.ElementType;
|
||||
}
|
||||
|
||||
const AVAILABLE_EXTENSIONS: Extension[] = [
|
||||
@@ -58,7 +59,9 @@ export default function ExtensionPopover() {
|
||||
const handleSetActiveExtension = (extension: Extension | null) => {
|
||||
send("setActiveExtension", { extensionId: extension?.id || "" }, resp => {
|
||||
if ("error" in resp) {
|
||||
notifications.error(`Failed to set active extension: ${resp.error.data || "Unknown error"}`);
|
||||
notifications.error(
|
||||
`Failed to set active extension: ${resp.error.data || "Unknown error"}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
setActiveExtension(extension);
|
||||
@@ -80,7 +83,7 @@ export default function ExtensionPopover() {
|
||||
|
||||
return (
|
||||
<GridCard>
|
||||
<div className="p-4 py-3 space-y-4">
|
||||
<div className="space-y-4 p-4 py-3">
|
||||
<div className="grid h-full grid-rows-headerBody">
|
||||
<div className="space-y-4">
|
||||
{activeExtension ? (
|
||||
@@ -89,7 +92,7 @@ export default function ExtensionPopover() {
|
||||
{renderActiveExtension()}
|
||||
|
||||
<div
|
||||
className="flex items-center justify-end space-x-2 opacity-0 animate-fadeIn"
|
||||
className="flex animate-fadeIn items-center justify-end space-x-2 opacity-0"
|
||||
style={{
|
||||
animationDuration: "0.7s",
|
||||
animationDelay: "0.2s",
|
||||
@@ -110,7 +113,7 @@ export default function ExtensionPopover() {
|
||||
title="Extensions"
|
||||
description="Load and manage your extensions"
|
||||
/>
|
||||
<Card className="opacity-0 animate-fadeIn">
|
||||
<Card className="animate-fadeIn opacity-0">
|
||||
<div className="w-full divide-y divide-slate-700/30 dark:divide-slate-600/30">
|
||||
{AVAILABLE_EXTENSIONS.map(extension => (
|
||||
<div
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import { Button } from "@components/Button";
|
||||
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
import Card, { GridCard } from "@components/Card";
|
||||
import { PlusCircleIcon } from "@heroicons/react/20/solid";
|
||||
import { useMemo, forwardRef, useEffect, useCallback } from "react";
|
||||
import { formatters } from "@/utils";
|
||||
import { RemoteVirtualMediaState, useMountMediaStore, useRTCStore } from "@/hooks/stores";
|
||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||
import {
|
||||
LuArrowUpFromLine,
|
||||
LuCheckCheck,
|
||||
@@ -13,11 +8,17 @@ import {
|
||||
LuPlus,
|
||||
LuRadioReceiver,
|
||||
} from "react-icons/lu";
|
||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||
import notifications from "../../notifications";
|
||||
import { useClose } from "@headlessui/react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
import { Button } from "@components/Button";
|
||||
import Card, { GridCard } from "@components/Card";
|
||||
import { formatters } from "@/utils";
|
||||
import { RemoteVirtualMediaState, useMountMediaStore, useRTCStore } from "@/hooks/stores";
|
||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
||||
import notifications from "@/notifications";
|
||||
|
||||
const MountPopopover = forwardRef<HTMLDivElement, object>((_props, ref) => {
|
||||
const diskDataChannelStats = useRTCStore(state => state.diskDataChannelStats);
|
||||
@@ -194,7 +195,7 @@ const MountPopopover = forwardRef<HTMLDivElement, object>((_props, ref) => {
|
||||
<GridCard>
|
||||
<div className="space-y-4 p-4 py-3">
|
||||
<div ref={ref} className="grid h-full grid-rows-headerBody">
|
||||
<div className="h-full space-y-4 ">
|
||||
<div className="h-full space-y-4">
|
||||
<div className="space-y-4">
|
||||
<SettingsPageHeader
|
||||
title="Virtual Media"
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { LuCornerDownLeft } from "react-icons/lu";
|
||||
import { ExclamationCircleIcon } from "@heroicons/react/16/solid";
|
||||
import { useClose } from "@headlessui/react";
|
||||
|
||||
import { Button } from "@components/Button";
|
||||
import { GridCard } from "@components/Card";
|
||||
import { TextAreaWithLabel } from "@components/TextArea";
|
||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||
import { useHidStore, useRTCStore, useUiStore } from "@/hooks/stores";
|
||||
import notifications from "../../notifications";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { LuCornerDownLeft } from "react-icons/lu";
|
||||
import { ExclamationCircleIcon } from "@heroicons/react/16/solid";
|
||||
import { useClose } from "@headlessui/react";
|
||||
import { chars, keys, modifiers } from "@/keyboardMappings";
|
||||
import notifications from "@/notifications";
|
||||
|
||||
const hidKeyboardPayload = (keys: number[], modifier: number) => {
|
||||
return { keys, modifier };
|
||||
@@ -59,6 +60,7 @@ export default function PasteModal() {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
notifications.error("Failed to paste text");
|
||||
}
|
||||
}, [rpcDataChannel?.readyState, send, setDisableVideoFocusTrap, setPasteMode]);
|
||||
@@ -71,7 +73,7 @@ export default function PasteModal() {
|
||||
|
||||
return (
|
||||
<GridCard>
|
||||
<div className="p-4 py-3 space-y-4">
|
||||
<div className="space-y-4 p-4 py-3">
|
||||
<div className="grid h-full grid-rows-headerBody">
|
||||
<div className="h-full space-y-4">
|
||||
<div className="space-y-4">
|
||||
@@ -81,7 +83,7 @@ export default function PasteModal() {
|
||||
/>
|
||||
|
||||
<div
|
||||
className="space-y-2 opacity-0 animate-fadeIn"
|
||||
className="animate-fadeIn space-y-2 opacity-0"
|
||||
style={{
|
||||
animationDuration: "0.7s",
|
||||
animationDelay: "0.1s",
|
||||
@@ -120,8 +122,8 @@ export default function PasteModal() {
|
||||
/>
|
||||
|
||||
{invalidChars.length > 0 && (
|
||||
<div className="flex items-center mt-2 gap-x-2">
|
||||
<ExclamationCircleIcon className="w-4 h-4 text-red-500 dark:text-red-400" />
|
||||
<div className="mt-2 flex items-center gap-x-2">
|
||||
<ExclamationCircleIcon className="h-4 w-4 text-red-500 dark:text-red-400" />
|
||||
<span className="text-xs text-red-500 dark:text-red-400">
|
||||
The following characters won't be pasted:{" "}
|
||||
{invalidChars.join(", ")}
|
||||
@@ -135,7 +137,7 @@ export default function PasteModal() {
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="flex items-center justify-end opacity-0 animate-fadeIn gap-x-2"
|
||||
className="flex animate-fadeIn items-center justify-end gap-x-2 opacity-0"
|
||||
style={{
|
||||
animationDuration: "0.7s",
|
||||
animationDelay: "0.2s",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { InputFieldWithLabel } from "@components/InputField";
|
||||
import { useState, useRef } from "react";
|
||||
import { LuPlus } from "react-icons/lu";
|
||||
import { Button } from "../../Button";
|
||||
import { LuArrowLeft } from "react-icons/lu";
|
||||
import { LuPlus, LuArrowLeft } from "react-icons/lu";
|
||||
|
||||
import { InputFieldWithLabel } from "@/components/InputField";
|
||||
import { Button } from "@/components/Button";
|
||||
|
||||
interface AddDeviceFormProps {
|
||||
onAddDevice: (name: string, macAddress: string) => void;
|
||||
@@ -26,7 +26,7 @@ export default function AddDeviceForm({
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div
|
||||
className="space-y-4 opacity-0 animate-fadeIn"
|
||||
className="animate-fadeIn space-y-4 opacity-0"
|
||||
style={{
|
||||
animationDuration: "0.5s",
|
||||
animationFillMode: "forwards",
|
||||
@@ -73,7 +73,7 @@ export default function AddDeviceForm({
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="flex items-center justify-end space-x-2 opacity-0 animate-fadeIn"
|
||||
className="flex animate-fadeIn items-center justify-end space-x-2 opacity-0"
|
||||
style={{
|
||||
animationDuration: "0.7s",
|
||||
animationDelay: "0.2s",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Button } from "@components/Button";
|
||||
import Card from "@components/Card";
|
||||
import { FieldError } from "@components/InputField";
|
||||
import { LuPlus, LuSend, LuTrash2 } from "react-icons/lu";
|
||||
|
||||
import { Button } from "@/components/Button";
|
||||
import Card from "@/components/Card";
|
||||
import { FieldError } from "@/components/InputField";
|
||||
|
||||
export interface StoredDevice {
|
||||
name: string;
|
||||
macAddress: string;
|
||||
@@ -27,12 +28,14 @@ export default function DeviceList({
|
||||
}: DeviceListProps) {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Card className="opacity-0 animate-fadeIn">
|
||||
<Card className="animate-fadeIn opacity-0">
|
||||
<div className="w-full divide-y divide-slate-700/30 dark:divide-slate-600/30">
|
||||
{storedDevices.map((device, index) => (
|
||||
<div key={index} className="flex items-center justify-between p-3 gap-x-2">
|
||||
<div key={index} className="flex items-center justify-between gap-x-2 p-3">
|
||||
<div className="space-y-0.5">
|
||||
<p className="text-sm font-semibold leading-none text-slate-900 dark:text-slate-100">{device?.name}</p>
|
||||
<p className="text-sm font-semibold leading-none text-slate-900 dark:text-slate-100">
|
||||
{device?.name}
|
||||
</p>
|
||||
<p className="text-sm text-slate-600 dark:text-slate-400">
|
||||
{device.macAddress?.toLowerCase()}
|
||||
</p>
|
||||
@@ -60,18 +63,13 @@ export default function DeviceList({
|
||||
</div>
|
||||
</Card>
|
||||
<div
|
||||
className="flex items-center justify-end space-x-2 opacity-0 animate-fadeIn"
|
||||
className="flex animate-fadeIn items-center justify-end space-x-2 opacity-0"
|
||||
style={{
|
||||
animationDuration: "0.7s",
|
||||
animationDelay: "0.2s",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
size="SM"
|
||||
theme="blank"
|
||||
text="Close"
|
||||
onClick={onCancelWakeOnLanModal}
|
||||
/>
|
||||
<Button size="SM" theme="blank" text="Close" onClick={onCancelWakeOnLanModal} />
|
||||
<Button
|
||||
size="SM"
|
||||
theme="primary"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import Card from "@components/Card";
|
||||
import { PlusCircleIcon } from "@heroicons/react/16/solid";
|
||||
import { LuPlus } from "react-icons/lu";
|
||||
import { Button } from "../../Button";
|
||||
|
||||
import Card from "@/components/Card";
|
||||
import { Button } from "@/components/Button";
|
||||
|
||||
export default function EmptyStateCard({
|
||||
onCancelWakeOnLanModal,
|
||||
@@ -11,15 +12,15 @@ export default function EmptyStateCard({
|
||||
setShowAddForm: (show: boolean) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="space-y-4 select-none">
|
||||
<Card className="opacity-0 animate-fadeIn">
|
||||
<div className="select-none space-y-4">
|
||||
<Card className="animate-fadeIn opacity-0">
|
||||
<div className="flex items-center justify-center py-8 text-center">
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-1">
|
||||
<div className="inline-block">
|
||||
<Card>
|
||||
<div className="p-1">
|
||||
<PlusCircleIcon className="w-4 h-4 text-blue-700 shrink-0 dark:text-white" />
|
||||
<PlusCircleIcon className="h-4 w-4 shrink-0 text-blue-700 dark:text-white" />
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
@@ -34,7 +35,7 @@ export default function EmptyStateCard({
|
||||
</div>
|
||||
</Card>
|
||||
<div
|
||||
className="flex items-center justify-end space-x-2 opacity-0 animate-fadeIn"
|
||||
className="flex animate-fadeIn items-center justify-end space-x-2 opacity-0"
|
||||
style={{
|
||||
animationDuration: "0.7s",
|
||||
animationDelay: "0.2s",
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useClose } from "@headlessui/react";
|
||||
|
||||
import { GridCard } from "@components/Card";
|
||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||
import { useRTCStore, useUiStore } from "@/hooks/stores";
|
||||
import notifications from "@/notifications";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useClose } from "@headlessui/react";
|
||||
|
||||
import EmptyStateCard from "./EmptyStateCard";
|
||||
import DeviceList, { StoredDevice } from "./DeviceList";
|
||||
import AddDeviceForm from "./AddDeviceForm";
|
||||
@@ -99,7 +101,7 @@ export default function WakeOnLanModal() {
|
||||
|
||||
return (
|
||||
<GridCard>
|
||||
<div className="p-4 py-3 space-y-4">
|
||||
<div className="space-y-4 p-4 py-3">
|
||||
<div className="grid h-full grid-rows-headerBody">
|
||||
<div className="space-y-4">
|
||||
<SettingsPageHeader
|
||||
|
||||
Reference in New Issue
Block a user