chore: add more linting rules and fix warnings (#325)
This commit is contained in:
parent
76741d6fb8
commit
87403c9407
11 changed files with 28 additions and 19 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||||
"plugins": ["unicorn", "typescript", "oxc"],
|
"plugins": ["eslint", "unicorn", "typescript", "oxc", "import", "react", "react-perf", "node", "jsx-a11y"],
|
||||||
"categories": {},
|
"categories": {},
|
||||||
"rules": {
|
"rules": {
|
||||||
"constructor-super": "warn",
|
"constructor-super": "warn",
|
||||||
|
|
@ -112,7 +112,8 @@
|
||||||
"unicorn/no-useless-length-check": "warn",
|
"unicorn/no-useless-length-check": "warn",
|
||||||
"unicorn/no-useless-spread": "warn",
|
"unicorn/no-useless-spread": "warn",
|
||||||
"unicorn/prefer-set-size": "warn",
|
"unicorn/prefer-set-size": "warn",
|
||||||
"unicorn/prefer-string-starts-ends-with": "warn"
|
"unicorn/prefer-string-starts-ends-with": "warn",
|
||||||
|
"import/no-cycle": "error"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"jsx-a11y": {
|
"jsx-a11y": {
|
||||||
|
|
|
||||||
|
|
@ -489,18 +489,27 @@ interface ButtonProps {
|
||||||
const NodeButton = memo(({ depth, icon, onClick, onMouseEnter, className, children }: ButtonProps) => {
|
const NodeButton = memo(({ depth, icon, onClick, onMouseEnter, className, children }: ButtonProps) => {
|
||||||
const paddingLeft = useMemo(() => `${8 + depth * NODE_PADDING_LEFT}px`, [depth]);
|
const paddingLeft = useMemo(() => `${8 + depth * NODE_PADDING_LEFT}px`, [depth]);
|
||||||
|
|
||||||
|
const handleKeyDown = useCallback(
|
||||||
|
(e: React.KeyboardEvent) => {
|
||||||
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
|
e.preventDefault();
|
||||||
|
onClick?.();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onClick],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// biome-ignore lint/a11y/noStaticElementInteractions: we handle click and hover manually
|
<button
|
||||||
// biome-ignore lint/a11y/useKeyWithClickEvents: we handle click and hover manually
|
|
||||||
<div
|
|
||||||
className={cn("flex items-center gap-2 w-full pr-2 text-sm py-1.5 text-left", className)}
|
className={cn("flex items-center gap-2 w-full pr-2 text-sm py-1.5 text-left", className)}
|
||||||
style={{ paddingLeft }}
|
style={{ paddingLeft }}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
>
|
>
|
||||||
{icon}
|
{icon}
|
||||||
<div className="truncate w-full flex items-center gap-2">{children}</div>
|
<div className="truncate w-full flex items-center gap-2">{children}</div>
|
||||||
</div>
|
</button>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ export const SnapshotsTable = ({ snapshots, repositoryId, backups }: Props) => {
|
||||||
}
|
}
|
||||||
setSelectedIds(newSelected);
|
setSelectedIds(newSelected);
|
||||||
}}
|
}}
|
||||||
aria-label={`Select snapshot ${snapshot.short_id}`}
|
aria-label={`Select snapshot ${snapshot.short_id}` as string}
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="font-mono text-sm">
|
<TableCell className="font-mono text-sm">
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ const Alert = React.forwardRef<
|
||||||
));
|
));
|
||||||
Alert.displayName = "Alert";
|
Alert.displayName = "Alert";
|
||||||
|
|
||||||
const AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(
|
const AlertTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(
|
||||||
({ className, ...props }, ref) => (
|
({ className, ...props }, ref) => (
|
||||||
<h5 ref={ref} className={cn("mb-1 font-medium leading-none tracking-tight", className)} {...props} />
|
<h5 ref={ref} className={cn("mb-1 font-medium leading-none tracking-tight", className)} {...props}>{props.children}</h5>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
AlertTitle.displayName = "AlertTitle";
|
AlertTitle.displayName = "AlertTitle";
|
||||||
|
|
|
||||||
|
|
@ -43,16 +43,17 @@ function BreadcrumbLink({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
function BreadcrumbPage({ className, children, ...props }: React.ComponentProps<"a">) {
|
||||||
return (
|
return (
|
||||||
<span
|
<a
|
||||||
data-slot="breadcrumb-page"
|
data-slot="breadcrumb-page"
|
||||||
role="link"
|
|
||||||
aria-disabled="true"
|
aria-disabled="true"
|
||||||
aria-current="page"
|
aria-current="page"
|
||||||
className={cn("text-foreground font-normal truncate", className)}
|
className={cn("text-foreground font-normal truncate", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
>
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,6 @@ export default function DownloadRecoveryKeyPage() {
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
placeholder="Enter your password"
|
placeholder="Enter your password"
|
||||||
required
|
required
|
||||||
autoFocus
|
|
||||||
disabled={downloadResticPassword.isPending}
|
disabled={downloadResticPassword.isPending}
|
||||||
/>
|
/>
|
||||||
<p className="text-xs text-muted-foreground">Enter your account password to download the recovery key</p>
|
<p className="text-xs text-muted-foreground">Enter your account password to download the recovery key</p>
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ export default function LoginPage() {
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Username</FormLabel>
|
<FormLabel>Username</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} type="text" placeholder="admin" disabled={isLoggingIn} autoFocus />
|
<Input {...field} type="text" placeholder="admin" disabled={isLoggingIn} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ export default function OnboardingPage() {
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Username</FormLabel>
|
<FormLabel>Username</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} type="text" placeholder="admin" disabled={submitting} autoFocus />
|
<Input {...field} type="text" placeholder="admin" disabled={submitting} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>Choose a username for the admin account</FormDescription>
|
<FormDescription>Choose a username for the admin account</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
|
||||||
|
|
@ -393,7 +393,7 @@ export const CreateScheduleForm = ({ initialValues, formId, onSubmit, volume }:
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleRemovePath(path)}
|
onClick={() => handleRemovePath(path)}
|
||||||
className="ml-1 hover:bg-destructive/20 rounded p-0.5 transition-colors"
|
className="ml-1 hover:bg-destructive/20 rounded p-0.5 transition-colors"
|
||||||
aria-label={`Remove ${path}`}
|
aria-label={`Remove ${path}` as string}
|
||||||
>
|
>
|
||||||
<X className="h-3 w-3" />
|
<X className="h-3 w-3" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ export const ScheduleSummary = (props: Props) => {
|
||||||
repositoryLabel: schedule.repositoryId || "No repository selected",
|
repositoryLabel: schedule.repositoryId || "No repository selected",
|
||||||
retentionLabel: retentionParts.length > 0 ? retentionParts.join(" • ") : "No retention policy",
|
retentionLabel: retentionParts.length > 0 ? retentionParts.join(" • ") : "No retention policy",
|
||||||
};
|
};
|
||||||
}, [schedule, schedule.volume.name]);
|
}, [schedule]);
|
||||||
|
|
||||||
const handleConfirmDelete = () => {
|
const handleConfirmDelete = () => {
|
||||||
setShowDeleteConfirm(false);
|
setShowDeleteConfirm(false);
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,6 @@ export default function Settings({ loaderData }: Route.ComponentProps) {
|
||||||
onChange={(e) => setDownloadPassword(e.target.value)}
|
onChange={(e) => setDownloadPassword(e.target.value)}
|
||||||
placeholder="Enter your password"
|
placeholder="Enter your password"
|
||||||
required
|
required
|
||||||
autoFocus
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue