mirror of
https://github.com/gethomepage/homepage.git
synced 2026-09-26 05:51:17 -07:00
Fix: re-enable global lint, fix un-caught warnings / errors (#6990)
This commit is contained in:
@@ -17,6 +17,8 @@ const compat = new FlatCompat({
|
|||||||
|
|
||||||
export default defineConfig([
|
export default defineConfig([
|
||||||
{
|
{
|
||||||
|
files: ["**/*.{js,mjs,cjs,jsx}"],
|
||||||
|
|
||||||
extends: fixupConfigRules(compat.extends("next/core-web-vitals", "prettier", "plugin:react-hooks/recommended")),
|
extends: fixupConfigRules(compat.extends("next/core-web-vitals", "prettier", "plugin:react-hooks/recommended")),
|
||||||
|
|
||||||
plugins: {
|
plugins: {
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ export default class ErrorBoundary extends React.Component {
|
|||||||
|
|
||||||
// You can also log error messages to an error reporting service here
|
// You can also log error messages to an error reporting service here
|
||||||
if (error || errorInfo) {
|
if (error || errorInfo) {
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error("component error: %s, info: %s", error, errorInfo);
|
console.error("component error: %s, info: %s", error, errorInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea
|
|||||||
let descriptionMatch;
|
let descriptionMatch;
|
||||||
if (searchDescriptions) {
|
if (searchDescriptions) {
|
||||||
descriptionMatch = r.description?.toLowerCase().includes(searchString);
|
descriptionMatch = r.description?.toLowerCase().includes(searchString);
|
||||||
r.priority = nameMatch ? 2 * +nameMatch : +descriptionMatch; // eslint-disable-line no-param-reassign
|
r.priority = nameMatch ? 2 * +nameMatch : +descriptionMatch;
|
||||||
}
|
}
|
||||||
return nameMatch || descriptionMatch;
|
return nameMatch || descriptionMatch;
|
||||||
});
|
});
|
||||||
@@ -244,7 +244,6 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea
|
|||||||
<span>
|
<span>
|
||||||
{parts.map((part, i) =>
|
{parts.map((part, i) =>
|
||||||
part.toLowerCase() === searchString.toLowerCase() ? (
|
part.toLowerCase() === searchString.toLowerCase() ? (
|
||||||
// eslint-disable-next-line react/no-array-index-key
|
|
||||||
<span key={`${searchString}_${i}`} className="bg-theme-300/10">
|
<span key={`${searchString}_${i}`} className="bg-theme-300/10">
|
||||||
{part}
|
{part}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ export default function Error({ error }) {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
if (typeof error === "string") {
|
if (typeof error === "string") {
|
||||||
error = { message: error }; // eslint-disable-line no-param-reassign
|
error = { message: error };
|
||||||
} else if (typeof error === "number") {
|
} else if (typeof error === "number") {
|
||||||
error = { message: `Error ${error}` }; // eslint-disable-line no-param-reassign
|
error = { message: `Error ${error}` };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error?.data?.error) {
|
if (error?.data?.error) {
|
||||||
error = error.data.error; // eslint-disable-line no-param-reassign
|
error = error.data.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import Resource from "../widget/resource";
|
|||||||
|
|
||||||
export default function Network({ options, refresh = 1500 }) {
|
export default function Network({ options, refresh = 1500 }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
if (options.network === true) options.network = "default";
|
if (options.network === true) options.network = "default";
|
||||||
|
|
||||||
const { data, error } = useSWR(`/api/widgets/resources?type=network&interfaceName=${options.network}`, {
|
const { data, error } = useSWR(`/api/widgets/resources?type=network&interfaceName=${options.network}`, {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
} from "@headlessui/react";
|
} from "@headlessui/react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useTranslation } from "next-i18next/pages";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { Fragment, useEffect, useState } from "react";
|
import { Fragment, useEffect, useMemo, useState } from "react";
|
||||||
import { BiLogoBing } from "react-icons/bi";
|
import { BiLogoBing } from "react-icons/bi";
|
||||||
import { FiSearch } from "react-icons/fi";
|
import { FiSearch } from "react-icons/fi";
|
||||||
import { SiBaidu, SiBrave, SiDuckduckgo, SiGoogle } from "react-icons/si";
|
import { SiBaidu, SiBrave, SiDuckduckgo, SiGoogle } from "react-icons/si";
|
||||||
@@ -57,12 +57,12 @@ export const searchProviders = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function getAvailableProviderIds(options) {
|
function getAvailableProviderIds(provider) {
|
||||||
if (options.provider && Array.isArray(options.provider)) {
|
if (provider && Array.isArray(provider)) {
|
||||||
return options.provider.filter((value) => searchProviders.hasOwnProperty(value));
|
return provider.filter((value) => searchProviders.hasOwnProperty(value));
|
||||||
}
|
}
|
||||||
if (options.provider && searchProviders[options.provider]) {
|
if (provider && searchProviders[provider]) {
|
||||||
return [options.provider];
|
return [provider];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,8 @@ export function getStoredProvider() {
|
|||||||
export default function Search({ options }) {
|
export default function Search({ options }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const availableProviderIds = getAvailableProviderIds(options) ?? [];
|
// options is a fresh object each render, so memo on provider itself
|
||||||
|
const availableProviderIds = useMemo(() => getAvailableProviderIds(options.provider) ?? [], [options.provider]);
|
||||||
|
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
const [selectedProvider, setSelectedProvider] = useState(searchProviders[availableProviderIds[0] ?? "google"]);
|
const [selectedProvider, setSelectedProvider] = useState(searchProviders[availableProviderIds[0] ?? "google"]);
|
||||||
@@ -184,7 +185,6 @@ export default function Search({ options }) {
|
|||||||
autoCapitalize="off"
|
autoCapitalize="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
// eslint-disable-next-line jsx-a11y/no-autofocus
|
|
||||||
autoFocus={options.focus}
|
autoFocus={options.focus}
|
||||||
onBlur={(e) => e.preventDefault()}
|
onBlur={(e) => e.preventDefault()}
|
||||||
onKeyDown={handleSearchKeyDown}
|
onKeyDown={handleSearchKeyDown}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import useWidgetAPI from "utils/proxy/use-widget-api";
|
|||||||
export default function Widget({ options }) {
|
export default function Widget({ options }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign, no-multi-assign
|
|
||||||
options.service_group = options.service_name = "unifi_console";
|
options.service_group = options.service_name = "unifi_console";
|
||||||
const { data: statsData, error: statsError } = useWidgetAPI(options, "stat/sites", { index: options.index });
|
const { data: statsData, error: statsError } = useWidgetAPI(options, "stat/sites", { index: options.index });
|
||||||
|
|
||||||
@@ -39,8 +38,8 @@ export default function Widget({ options }) {
|
|||||||
const lan = defaultSite.health.find((h) => h.subsystem === "lan");
|
const lan = defaultSite.health.find((h) => h.subsystem === "lan");
|
||||||
const wlan = defaultSite.health.find((h) => h.subsystem === "wlan");
|
const wlan = defaultSite.health.find((h) => h.subsystem === "wlan");
|
||||||
[wan, lan, wlan].forEach((s) => {
|
[wan, lan, wlan].forEach((s) => {
|
||||||
s.up = s.status === "ok"; // eslint-disable-line no-param-reassign
|
s.up = s.status === "ok";
|
||||||
s.show = s.status !== "unknown"; // eslint-disable-line no-param-reassign
|
s.show = s.status !== "unknown";
|
||||||
});
|
});
|
||||||
const name = wan.gw_name ?? defaultSite.desc;
|
const name = wan.gw_name ?? defaultSite.desc;
|
||||||
const uptime = wan["gw_system-stats"] ? wan["gw_system-stats"].uptime : null;
|
const uptime = wan["gw_system-stats"] ? wan["gw_system-stats"].uptime : null;
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import WidgetIcon from "./widget_icon";
|
|||||||
export function getAllClasses(options, additionalClassNames = "") {
|
export function getAllClasses(options, additionalClassNames = "") {
|
||||||
if (options?.style?.header === "boxedWidgets") {
|
if (options?.style?.header === "boxedWidgets") {
|
||||||
if (options?.style?.cardBlur !== undefined) {
|
if (options?.style?.cardBlur !== undefined) {
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
additionalClassNames = [
|
additionalClassNames = [
|
||||||
additionalClassNames,
|
additionalClassNames,
|
||||||
`backdrop-blur${options.style.cardBlur.length ? "-" : ""}${options.style.cardBlur}`,
|
`backdrop-blur${options.style.cardBlur.length ? "-" : ""}${options.style.cardBlur}`,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable react/jsx-props-no-spreading */
|
|
||||||
import { SessionProvider } from "next-auth/react";
|
import { SessionProvider } from "next-auth/react";
|
||||||
import { appWithTranslation } from "next-i18next/pages";
|
import { appWithTranslation } from "next-i18next/pages";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
@@ -13,7 +12,6 @@ import { ThemeProvider } from "utils/contexts/theme";
|
|||||||
|
|
||||||
import nextI18nextConfig from "../../next-i18next.config";
|
import nextI18nextConfig from "../../next-i18next.config";
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const tailwindSafelist = [
|
const tailwindSafelist = [
|
||||||
// TODO: remove pending https://github.com/tailwindlabs/tailwindcss/pull/17147
|
// TODO: remove pending https://github.com/tailwindlabs/tailwindcss/pull/17147
|
||||||
"backdrop-blur",
|
"backdrop-blur",
|
||||||
|
|||||||
+1
-2
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable react/no-array-index-key */
|
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import BookmarksGroup from "components/bookmarks/group";
|
import BookmarksGroup from "components/bookmarks/group";
|
||||||
import ErrorBoundary from "components/errorboundry";
|
import ErrorBoundary from "components/errorboundry";
|
||||||
@@ -175,7 +174,7 @@ function Index({ initialSettings, fallback }) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="p-2 text-theme-100 dark:text-theme-200">
|
<div className="p-2 text-theme-100 dark:text-theme-200">
|
||||||
<pre className="opacity-50 font-bold pb-2">
|
<pre className="opacity-50 font-bold pb-2">
|
||||||
Reason: "{error.reason}" at line {error.mark?.line}
|
Reason: "{error.reason}" at line {error.mark?.line}
|
||||||
</pre>
|
</pre>
|
||||||
<pre className="font-italic">Check logs for details.</pre>
|
<pre className="font-italic">Check logs for details.</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { render } from "@testing-library/react";
|
import { render } from "@testing-library/react";
|
||||||
|
|
||||||
import { SettingsContext } from "utils/contexts/settings";
|
import { SettingsContext } from "utils/contexts/settings";
|
||||||
|
|
||||||
export function renderWithProviders(ui, { settings = {} } = {}) {
|
export function renderWithProviders(ui, { settings = {} } = {}) {
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ export function ColorProvider({ initialTheme, children }) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (initialTheme !== undefined) setColor(initialTheme ?? getInitialColor());
|
if (initialTheme !== undefined) setColor(initialTheme ?? getInitialColor());
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [initialTheme]);
|
}, [initialTheme]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ export function ThemeProvider({ initialTheme, children }) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (initialTheme !== undefined) setTheme(initialTheme ?? getInitialTheme());
|
if (initialTheme !== undefined) setTheme(initialTheme ?? getInitialTheme());
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [initialTheme]);
|
}, [initialTheme]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -16,14 +16,16 @@ export default function Component({ service }) {
|
|||||||
widget.fields = widget.fields.slice(0, MAX_FIELDS);
|
widget.fields = widget.fields.slice(0, MAX_FIELDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget?.env == null || widget.env === "") {
|
const envNotSet = widget.env == null || widget.env === "";
|
||||||
|
|
||||||
|
const { data: containers, error: containersError } = useWidgetAPI(widget, envNotSet ? "" : "containers");
|
||||||
|
const { data: images, error: imagesError } = useWidgetAPI(widget, envNotSet ? "" : "images");
|
||||||
|
const { data: updates, error: updatesError } = useWidgetAPI(widget, envNotSet ? "" : "updates");
|
||||||
|
|
||||||
|
if (envNotSet) {
|
||||||
return <Container service={service} error={t("arcane.environment_required")} />;
|
return <Container service={service} error={t("arcane.environment_required")} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data: containers, error: containersError } = useWidgetAPI(widget, "containers");
|
|
||||||
const { data: images, error: imagesError } = useWidgetAPI(widget, "images");
|
|
||||||
const { data: updates, error: updatesError } = useWidgetAPI(widget, "updates");
|
|
||||||
|
|
||||||
const error =
|
const error =
|
||||||
containersError ?? imagesError ?? updatesError ?? containers?.detail ?? images?.detail ?? updates?.detail;
|
containersError ?? imagesError ?? updatesError ?? containers?.detail ?? images?.detail ?? updates?.detail;
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|||||||
@@ -20,11 +20,15 @@ describe("widgets/arcane/component", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("shows an environment required error when env is missing", () => {
|
it("shows an environment required error when env is missing", () => {
|
||||||
|
useWidgetAPI.mockImplementation(() => ({ data: undefined, error: undefined }));
|
||||||
|
|
||||||
renderWithProviders(<Component service={{ widget: { type: "arcane" } }} />, {
|
renderWithProviders(<Component service={{ widget: { type: "arcane" } }} />, {
|
||||||
settings: { hideErrors: false },
|
settings: { hideErrors: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(useWidgetAPI).not.toHaveBeenCalled();
|
// hooks always run; the empty endpoint is what skips the request
|
||||||
|
expect(useWidgetAPI).toHaveBeenCalledTimes(3);
|
||||||
|
useWidgetAPI.mock.calls.forEach((call) => expect(call[1]).toBe(""));
|
||||||
expect(screen.getByText("arcane.environment_required")).toBeInTheDocument();
|
expect(screen.getByText("arcane.environment_required")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ export default function Component({ service }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// uptime info
|
// uptime info
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const [hour, minutes, seconds] = infoData.data.up_time.split(":");
|
const [hour, minutes, seconds] = infoData.data.up_time.split(":");
|
||||||
const days = Math.floor(hour / 24);
|
const days = Math.floor(hour / 24);
|
||||||
const uptime = `${t("common.number", { value: days })} ${t("diskstation.days")}`;
|
const uptime = `${t("common.number", { value: days })} ${t("diskstation.days")}`;
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ export default function Component({ service }) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data && !data.error) {
|
if (data && !data.error) {
|
||||||
// eslint-disable-next-line eqeqeq
|
|
||||||
const gpuData = data.find((item) => item[item.key] == gpuName);
|
const gpuData = data.find((item) => item[item.key] == gpuName);
|
||||||
|
|
||||||
if (gpuData) {
|
if (gpuData) {
|
||||||
@@ -56,7 +55,6 @@ export default function Component({ service }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line eqeqeq
|
|
||||||
const gpuData = data.find((item) => item[item.key] == gpuName);
|
const gpuData = data.find((item) => item[item.key] == gpuName);
|
||||||
|
|
||||||
if (!gpuData) {
|
if (!gpuData) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next/pages";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
export default function Component({ service }) {
|
export default function Component({ service }) {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ export default function Component({ service }) {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { widget } = service;
|
const { widget } = service;
|
||||||
|
|
||||||
// eslint-disable-next-line prefer-const
|
|
||||||
let { data: spoolData, error: spoolError } = useWidgetAPI(widget, "spools");
|
let { data: spoolData, error: spoolError } = useWidgetAPI(widget, "spools");
|
||||||
|
|
||||||
if (spoolError) {
|
if (spoolError) {
|
||||||
@@ -20,7 +19,6 @@ export default function Component({ service }) {
|
|||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
{[...Array(nBlocksGuess)].map((_, i) => (
|
{[...Array(nBlocksGuess)].map((_, i) => (
|
||||||
// eslint-disable-next-line react/no-array-index-key
|
|
||||||
<Block key={i} label="spoolman.loading" />
|
<Block key={i} label="spoolman.loading" />
|
||||||
))}
|
))}
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable camelcase */
|
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next/pages";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { BsCpu, BsFillCpuFill, BsFillPlayFill, BsPauseFill } from "react-icons/bs";
|
import { BsCpu, BsFillCpuFill, BsFillPlayFill, BsPauseFill } from "react-icons/bs";
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable camelcase */
|
|
||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next/pages";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ export default function Component({ service }) {
|
|||||||
const lan = defaultSite.health.find((h) => h.subsystem === "lan");
|
const lan = defaultSite.health.find((h) => h.subsystem === "lan");
|
||||||
const wlan = defaultSite.health.find((h) => h.subsystem === "wlan");
|
const wlan = defaultSite.health.find((h) => h.subsystem === "wlan");
|
||||||
[wan, lan, wlan].forEach((s) => {
|
[wan, lan, wlan].forEach((s) => {
|
||||||
s.up = s.status === "ok"; // eslint-disable-line no-param-reassign
|
s.up = s.status === "ok";
|
||||||
s.show = s.status !== "unknown"; // eslint-disable-line no-param-reassign
|
s.show = s.status !== "unknown";
|
||||||
});
|
});
|
||||||
|
|
||||||
const uptime = wan["gw_system-stats"]
|
const uptime = wan["gw_system-stats"]
|
||||||
|
|||||||
Reference in New Issue
Block a user