mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
Update typescript and eslint config (#1878)
* Update eslint rules * Update typescript to 4.4 * Disable react/display-name * Add @typescript-eslint/typescript-estree
This commit is contained in:
@@ -10,18 +10,23 @@
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
"@typescript-eslint",
|
||||
"jsx-a11y"
|
||||
],
|
||||
"extends": [
|
||||
"airbnb-typescript",
|
||||
"airbnb/hooks",
|
||||
"plugin:react/recommended",
|
||||
"plugin:import/recommended",
|
||||
"prettier",
|
||||
"prettier/prettier",
|
||||
"prettier/react",
|
||||
"prettier/@typescript-eslint"
|
||||
"prettier/prettier"
|
||||
],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": 2,
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
@@ -48,36 +53,17 @@
|
||||
],
|
||||
"import/named": "off",
|
||||
"import/namespace": "off",
|
||||
"import/default": "off",
|
||||
"import/no-named-as-default-member": "off",
|
||||
"import/no-named-as-default": "off",
|
||||
"import/no-cycle": "off",
|
||||
"import/no-unused-modules": "off",
|
||||
"import/no-deprecated": "off",
|
||||
"import/no-unresolved": "off",
|
||||
"import/prefer-default-export": "off",
|
||||
"import/no-extraneous-dependencies": "off",
|
||||
"indent": "off",
|
||||
"@typescript-eslint/indent": "off",
|
||||
"react/display-name": "off",
|
||||
"react/prop-types": "off",
|
||||
"react/destructuring-assignment": "off",
|
||||
"react/require-default-props": "off",
|
||||
"react/jsx-props-no-spreading": "off",
|
||||
"react/sort-comp": "off",
|
||||
"react/style-prop-object": ["error", {
|
||||
"allow": ["FormattedNumber"]
|
||||
}],
|
||||
"spaced-comment": ["error", "always", {
|
||||
"markers": ["/"]
|
||||
}],
|
||||
"max-classes-per-file": "off",
|
||||
"no-plusplus": "off",
|
||||
"prefer-destructuring": ["error", {"object": true, "array": false}],
|
||||
"default-case": "off",
|
||||
"consistent-return": "off",
|
||||
"@typescript-eslint/no-use-before-define": ["error", { "functions": false, "classes": true }],
|
||||
"no-underscore-dangle": "off",
|
||||
"no-nested-ternary": "off",
|
||||
"jsx-a11y/media-has-caption": "off"
|
||||
"no-nested-ternary": "off"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,9 +55,9 @@
|
||||
"mousetrap": "^1.6.5",
|
||||
"mousetrap-pause": "^1.0.0",
|
||||
"query-string": "6.13.8",
|
||||
"react": "17.0.1",
|
||||
"react": "17.0.2",
|
||||
"react-bootstrap": "1.4.3",
|
||||
"react-dom": "17.0.1",
|
||||
"react-dom": "17.0.2",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-intl": "^5.10.16",
|
||||
"react-jw-player": "1.19.1",
|
||||
@@ -88,21 +88,22 @@
|
||||
"@types/lodash": "^4.14.168",
|
||||
"@types/mousetrap": "^1.6.5",
|
||||
"@types/node": "14.14.22",
|
||||
"@types/react": "17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@types/react": "17.0.31",
|
||||
"@types/react-dom": "^17.0.10",
|
||||
"@types/react-helmet": "^6.1.3",
|
||||
"@types/react-router-bootstrap": "^0.24.5",
|
||||
"@types/react-router-dom": "5.1.7",
|
||||
"@types/react-router-hash-link": "^1.2.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.14.0",
|
||||
"@typescript-eslint/parser": "^4.14.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"craco-esbuild": "^0.4.2",
|
||||
"eslint": "^7.18.0",
|
||||
"eslint-config-airbnb-typescript": "^12.0.0",
|
||||
"eslint-config-prettier": "^7.2.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-airbnb": "^18.2.1",
|
||||
"eslint-config-airbnb-typescript": "^14.0.1",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-import": "^2.25.2",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-react": "^7.22.0",
|
||||
"eslint-plugin-react": "^7.26.1",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"extract-react-intl-messages": "^4.1.1",
|
||||
"postcss-safe-parser": "^5.0.2",
|
||||
@@ -111,6 +112,6 @@
|
||||
"stylelint": "^13.9.0",
|
||||
"stylelint-config-prettier": "^8.0.2",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"typescript": "~4.0.5"
|
||||
"typescript": "~4.4.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { Route, Switch, useRouteMatch } from "react-router-dom";
|
||||
import { IntlProvider } from "react-intl";
|
||||
import { IntlProvider, CustomFormats } from "react-intl";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { mergeWith } from "lodash";
|
||||
import { ToastProvider } from "src/hooks/Toast";
|
||||
@@ -32,7 +32,7 @@ import { Setup } from "./components/Setup/Setup";
|
||||
import { Migrate } from "./components/Setup/Migrate";
|
||||
import * as GQL from "./core/generated-graphql";
|
||||
import { LoadingIndicator, TITLE_SUFFIX } from "./components/Shared";
|
||||
import ConfigurationProvider from "./hooks/Config";
|
||||
import { ConfigurationProvider } from "./hooks/Config";
|
||||
|
||||
initPolyfills();
|
||||
|
||||
@@ -41,7 +41,7 @@ MousetrapPause(Mousetrap);
|
||||
// Set fontawesome/free-solid-svg as default fontawesome icons
|
||||
library.add(fas);
|
||||
|
||||
const intlFormats = {
|
||||
const intlFormats: CustomFormats = {
|
||||
date: {
|
||||
long: { year: "numeric", month: "long", day: "numeric" },
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useHistory, Prompt } from "react-router-dom";
|
||||
import {
|
||||
Button,
|
||||
Dropdown,
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
} from "src/components/Shared";
|
||||
import { useToast } from "src/hooks";
|
||||
import { useFormik } from "formik";
|
||||
import { Prompt } from "react-router";
|
||||
import { FormUtils, TextUtils } from "src/utils";
|
||||
import { RatingStars } from "src/components/Scenes/SceneDetails/RatingStars";
|
||||
import { GalleryScrapeDialog } from "./GalleryScrapeDialog";
|
||||
|
||||
@@ -11,7 +11,7 @@ export const GalleryScenesPanel: React.FC<IGalleryScenesPanelProps> = ({
|
||||
}) => (
|
||||
<div className="container gallery-scenes">
|
||||
{scenes.map((scene) => (
|
||||
<SceneCard scene={scene} />
|
||||
<SceneCard scene={scene} key={scene.id} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
import { useToast } from "src/hooks";
|
||||
import { FormUtils } from "src/utils";
|
||||
import { useFormik } from "formik";
|
||||
import { Prompt } from "react-router";
|
||||
import { Prompt } from "react-router-dom";
|
||||
import { RatingStars } from "src/components/Scenes/SceneDetails/RatingStars";
|
||||
|
||||
interface IProps {
|
||||
|
||||
@@ -162,7 +162,7 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
const SavedFilterDropdown = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
HTMLAttributes<HTMLDivElement>
|
||||
>(({ style, className }, ref) => (
|
||||
>(({ style, className }: HTMLAttributes<HTMLDivElement>, ref) => (
|
||||
<div ref={ref} style={style} className={className}>
|
||||
<SavedFilterList
|
||||
filter={filter}
|
||||
@@ -173,6 +173,7 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
SavedFilterDropdown.displayName = "SavedFilterDropdown";
|
||||
|
||||
function render() {
|
||||
const currentSortBy = filterOptions.sortByOptions.find(
|
||||
|
||||
@@ -100,6 +100,7 @@ export const ListOperationButtons: React.FC<IListOperationButtonsProps> = ({
|
||||
return (
|
||||
<OverlayTrigger
|
||||
overlay={<Tooltip id="edit">{button.text}</Tooltip>}
|
||||
key={button.text}
|
||||
>
|
||||
<Button
|
||||
variant={button.buttonVariant ?? "secondary"}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { LoadingIndicator } from "src/components/Shared";
|
||||
import { useToast } from "src/hooks";
|
||||
import { MovieEditPanel } from "./MovieEditPanel";
|
||||
|
||||
export const MovieCreate: React.FC = () => {
|
||||
const MovieCreate: React.FC = () => {
|
||||
const history = useHistory();
|
||||
const Toast = useToast();
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import { useToast } from "src/hooks";
|
||||
import { ImageUtils, FormUtils, TextUtils, getStashIDs } from "src/utils";
|
||||
import { MovieSelect } from "src/components/Shared/Select";
|
||||
import { useFormik } from "formik";
|
||||
import { Prompt } from "react-router";
|
||||
import { Prompt } from "react-router-dom";
|
||||
import { ConfigurationContext } from "src/hooks/Config";
|
||||
import { stashboxDisplayName } from "src/utils/stashbox";
|
||||
import { SceneMovieTable } from "./SceneMovieTable";
|
||||
|
||||
@@ -25,7 +25,11 @@ const SceneSearchResultDetails: React.FC<ISceneSearchResultDetailsProps> = ({
|
||||
<Row>
|
||||
<Col>
|
||||
{scene.performers?.map((performer) => (
|
||||
<Badge className="tag-item" variant="secondary">
|
||||
<Badge
|
||||
className="tag-item"
|
||||
variant="secondary"
|
||||
key={performer.name}
|
||||
>
|
||||
{performer.name}
|
||||
</Badge>
|
||||
))}
|
||||
@@ -41,7 +45,11 @@ const SceneSearchResultDetails: React.FC<ISceneSearchResultDetailsProps> = ({
|
||||
<Row>
|
||||
<Col>
|
||||
{scene.tags?.map((tag) => (
|
||||
<Badge className="tag-item" variant="secondary">
|
||||
<Badge
|
||||
className="tag-item"
|
||||
variant="secondary"
|
||||
key={tag.stored_id}
|
||||
>
|
||||
{tag.name}
|
||||
</Badge>
|
||||
))}
|
||||
@@ -136,7 +144,7 @@ export const SceneQueryModal: React.FC<IProps> = ({
|
||||
const r = await queryScrapeSceneQuery(scraper, input);
|
||||
setScenes(r.data.scrapeSingleScene);
|
||||
} catch (err) {
|
||||
setError(err);
|
||||
if (err instanceof Error) setError(err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import {
|
||||
} from "src/core/StashService";
|
||||
import { useToast } from "src/hooks";
|
||||
import { Icon, LoadingIndicator } from "src/components/Shared";
|
||||
import StashBoxConfiguration, {
|
||||
import {
|
||||
StashBoxConfiguration,
|
||||
IStashBoxInstance,
|
||||
} from "./StashBoxConfiguration";
|
||||
import StashConfiguration from "./StashConfiguration";
|
||||
@@ -47,7 +48,7 @@ export const ExclusionPatterns: React.FC<IExclusionPatternsProps> = (props) => {
|
||||
<Form.Group>
|
||||
{props.excludes &&
|
||||
props.excludes.map((regexp, i) => (
|
||||
<InputGroup>
|
||||
<InputGroup key={regexp}>
|
||||
<Form.Control
|
||||
className="col col-sm-6 text-input"
|
||||
value={regexp}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
import { Formik, useFormikContext } from "formik";
|
||||
import { Button, Form } from "react-bootstrap";
|
||||
import { Prompt } from "react-router";
|
||||
import { Prompt } from "react-router-dom";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import * as yup from "yup";
|
||||
import {
|
||||
|
||||
@@ -72,7 +72,7 @@ export const SettingsPluginsPanel: React.FC = () => {
|
||||
>
|
||||
<ul>
|
||||
{h.hooks?.map((hh) => (
|
||||
<li>
|
||||
<li key={hh}>
|
||||
<code>{hh}</code>
|
||||
</li>
|
||||
))}
|
||||
|
||||
@@ -50,7 +50,7 @@ export const DirectorySelectionDialog: React.FC<IDirectorySelectionDialogProps>
|
||||
>
|
||||
<div className="dialog-container">
|
||||
{paths.map((p) => (
|
||||
<Row className="align-items-center mb-1">
|
||||
<Row className="align-items-center mb-1" key={p}>
|
||||
<Form.Label column xs={10}>
|
||||
{p}
|
||||
</Form.Label>
|
||||
|
||||
@@ -140,5 +140,3 @@ export const StashBoxConfiguration: React.FC<IStashBoxConfigurationProps> = ({
|
||||
</Form.Group>
|
||||
);
|
||||
};
|
||||
|
||||
export default StashBoxConfiguration;
|
||||
|
||||
@@ -64,7 +64,7 @@ interface IStashConfigurationProps {
|
||||
setStashes: (v: GQL.StashConfig[]) => void;
|
||||
}
|
||||
|
||||
export const StashConfiguration: React.FC<IStashConfigurationProps> = ({
|
||||
const StashConfiguration: React.FC<IStashConfigurationProps> = ({
|
||||
stashes,
|
||||
setStashes,
|
||||
}) => {
|
||||
|
||||
@@ -80,7 +80,7 @@ export const Migrate: React.FC = () => {
|
||||
const newURL = new URL("/", window.location.toString());
|
||||
window.location.href = newURL.toString();
|
||||
} catch (e) {
|
||||
setMigrateError(e.message ?? e.toString());
|
||||
if (e instanceof Error) setMigrateError(e.message ?? e.toString());
|
||||
setMigrateLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ export const Setup: React.FC = () => {
|
||||
return (
|
||||
<ul>
|
||||
{stashes.map((s) => (
|
||||
<li>
|
||||
<li key={s.path}>
|
||||
<code>{s.path} </code>
|
||||
{maybeRenderExclusions(s)}
|
||||
</li>
|
||||
@@ -329,7 +329,7 @@ export const Setup: React.FC = () => {
|
||||
stashes,
|
||||
});
|
||||
} catch (e) {
|
||||
setSetupError(e.message ?? e.toString());
|
||||
if (e instanceof Error) setSetupError(e.message ?? e.toString());
|
||||
} finally {
|
||||
setLoading(false);
|
||||
next();
|
||||
|
||||
@@ -104,7 +104,7 @@ const DeleteEntityDialog: React.FC<IDeleteEntityDialogProps> = ({
|
||||
</p>
|
||||
<ul>
|
||||
{selected.slice(0, 10).map((s) => (
|
||||
<li>{s.name}</li>
|
||||
<li key={s.name}>{s.name}</li>
|
||||
))}
|
||||
{selected.length > 10 && (
|
||||
<FormattedMessage
|
||||
|
||||
@@ -42,7 +42,7 @@ export const StudioDetailsPanel: React.FC<IStudioDetailsPanel> = ({
|
||||
</dt>
|
||||
<dd>
|
||||
{studio.aliases.map((a) => (
|
||||
<Badge className="tag-item" variant="secondary">
|
||||
<Badge className="tag-item" variant="secondary" key={a}>
|
||||
{a}
|
||||
</Badge>
|
||||
))}
|
||||
|
||||
@@ -46,7 +46,7 @@ const Config: React.FC<IConfigProps> = ({ show, config, setConfig }) => {
|
||||
<span>
|
||||
{excludedFields.length > 0
|
||||
? excludedFields.map((f) => (
|
||||
<Badge variant="secondary" className="tag-item">
|
||||
<Badge variant="secondary" className="tag-item" key={f}>
|
||||
{TextUtils.capitalize(f)}
|
||||
</Badge>
|
||||
))
|
||||
|
||||
@@ -271,7 +271,7 @@ const PerformerTaggerList: React.FC<IPerformerTaggerListProps> = ({
|
||||
-1;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div key={performer.id}>
|
||||
<InputGroup className="PerformerTagger-box-link">
|
||||
<InputGroup.Text>{link}</InputGroup.Text>
|
||||
<InputGroup.Append>
|
||||
|
||||
@@ -89,7 +89,7 @@ const getFingerprintStatus = (
|
||||
const phashList = (
|
||||
<div className="m-2">
|
||||
{phashMatches.map((fp) => (
|
||||
<div>
|
||||
<div key={fp.hash}>
|
||||
<b>{fp.hash}</b>
|
||||
{fp.hash === stashScene.phash
|
||||
? ", Exact match"
|
||||
|
||||
@@ -21,7 +21,7 @@ export const TagDetailsPanel: React.FC<ITagDetails> = ({ tag }) => {
|
||||
</dt>
|
||||
<dd className="col-9 col-xl-10">
|
||||
{tag.aliases.map((a) => (
|
||||
<Badge className="tag-item" variant="secondary">
|
||||
<Badge className="tag-item" variant="secondary" key={a}>
|
||||
{a}
|
||||
</Badge>
|
||||
))}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { FormUtils } from "src/utils";
|
||||
import { useTagsMerge } from "src/core/StashService";
|
||||
import { useIntl } from "react-intl";
|
||||
import { useToast } from "src/hooks";
|
||||
import { useHistory } from "react-router";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
interface ITagMergeModalProps {
|
||||
show: boolean;
|
||||
|
||||
@@ -24,5 +24,3 @@ export const ConfigurationProvider: React.FC<IContext> = ({
|
||||
</ConfigurationContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfigurationProvider;
|
||||
|
||||
@@ -27,7 +27,7 @@ export function useLocalForage<T>(
|
||||
key: string,
|
||||
defaultValue: T = {} as T
|
||||
): [ILocalForage<T>, Dispatch<SetStateAction<T>>] {
|
||||
const [error, setError] = React.useState(null);
|
||||
const [error, setError] = React.useState<Error | null>(null);
|
||||
const [data, setData] = React.useState<T>(Cache[key] as T);
|
||||
const [loading, setLoading] = React.useState(Loading[key]);
|
||||
|
||||
@@ -45,7 +45,7 @@ export function useLocalForage<T>(
|
||||
}
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err);
|
||||
if (err instanceof Error) setError(err);
|
||||
Cache[key] = defaultValue;
|
||||
} finally {
|
||||
Loading[key] = false;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react",
|
||||
"jsx": "react-jsx",
|
||||
"downlevelIteration": true,
|
||||
"experimentalDecorators": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
2656
ui/v2.5/yarn.lock
2656
ui/v2.5/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user