Update React Lint rules for TSX
This commit is contained in:
parent
4c0de55672
commit
1299a97579
|
@ -359,11 +359,16 @@ module.exports = {
|
|||
],
|
||||
|
||||
rules: Object.assign(typescriptEslintRecommended.rules, {
|
||||
'no-shadow': 'off',
|
||||
// These should be enabled after cleaning things up
|
||||
'@typescript-eslint/no-unused-vars': 'warn',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
args: 'after-used',
|
||||
argsIgnorePattern: '^_',
|
||||
ignoreRestSiblings: true
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'react/prop-types': 'off',
|
||||
'no-shadow': 'off',
|
||||
'prettier/prettier': 'error',
|
||||
'simple-import-sort/imports': [
|
||||
'error',
|
||||
|
@ -376,7 +381,41 @@ module.exports = {
|
|||
['^@?\\w', `^(${dirs})(/.*|$)`, '^\\.', '^\\..*css$']
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
// React Hooks
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'error',
|
||||
|
||||
// React
|
||||
'react/function-component-definition': 'error',
|
||||
'react/hook-use-state': 'error',
|
||||
'react/jsx-boolean-value': ['error', 'always'],
|
||||
'react/jsx-curly-brace-presence': [
|
||||
'error',
|
||||
{ props: 'never', children: 'never' }
|
||||
],
|
||||
'react/jsx-fragments': 'error',
|
||||
'react/jsx-handler-names': [
|
||||
'error',
|
||||
{
|
||||
eventHandlerPrefix: 'on',
|
||||
eventHandlerPropPrefix: 'on'
|
||||
}
|
||||
],
|
||||
'react/jsx-no-bind': ['error', { ignoreRefs: true }],
|
||||
'react/jsx-no-useless-fragment': ['error', { allowExpressions: true }],
|
||||
'react/jsx-pascal-case': ['error', { allowAllCaps: true }],
|
||||
'react/jsx-sort-props': [
|
||||
'error',
|
||||
{
|
||||
callbacksLast: true,
|
||||
noSortAlphabetically: true,
|
||||
reservedFirst: true
|
||||
}
|
||||
],
|
||||
'react/prop-types': 'off',
|
||||
'react/self-closing-comp': 'error'
|
||||
})
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Fragment, useCallback } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import AppState from 'App/State/AppState';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
|
@ -31,19 +31,17 @@ function QueueOptions() {
|
|||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('ShowUnknownSeriesItems')}</FormLabel>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('ShowUnknownSeriesItems')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="includeUnknownSeriesItems"
|
||||
value={includeUnknownSeriesItems}
|
||||
helpText={translate('ShowUnknownSeriesItemsHelpText')}
|
||||
onChange={handleOptionChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Fragment>
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="includeUnknownSeriesItems"
|
||||
value={includeUnknownSeriesItems}
|
||||
helpText={translate('ShowUnknownSeriesItemsHelpText')}
|
||||
onChange={handleOptionChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,10 @@ import getPathWithUrlBase from 'Utilities/getPathWithUrlBase';
|
|||
import CutoffUnmetConnector from 'Wanted/CutoffUnmet/CutoffUnmetConnector';
|
||||
import MissingConnector from 'Wanted/Missing/MissingConnector';
|
||||
|
||||
function RedirectWithUrlBase() {
|
||||
return <Redirect to={getPathWithUrlBase('/')} />;
|
||||
}
|
||||
|
||||
function AppRoutes() {
|
||||
return (
|
||||
<Switch>
|
||||
|
@ -51,9 +55,7 @@ function AppRoutes() {
|
|||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
addUrlBase={false}
|
||||
render={() => {
|
||||
return <Redirect to={getPathWithUrlBase('/')} />;
|
||||
}}
|
||||
render={RedirectWithUrlBase}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
@ -61,21 +63,9 @@ function AppRoutes() {
|
|||
|
||||
<Route path="/add/import" component={ImportSeries} />
|
||||
|
||||
<Route
|
||||
path="/serieseditor"
|
||||
exact={true}
|
||||
render={() => {
|
||||
return <Redirect to={getPathWithUrlBase('/')} />;
|
||||
}}
|
||||
/>
|
||||
<Route path="/serieseditor" exact={true} render={RedirectWithUrlBase} />
|
||||
|
||||
<Route
|
||||
path="/seasonpass"
|
||||
exact={true}
|
||||
render={() => {
|
||||
return <Redirect to={getPathWithUrlBase('/')} />;
|
||||
}}
|
||||
/>
|
||||
<Route path="/seasonpass" exact={true} render={RedirectWithUrlBase} />
|
||||
|
||||
<Route path="/series/:titleSlug" component={SeriesDetailsPageConnector} />
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ function ErrorBoundaryError(props: ErrorBoundaryErrorProps) {
|
|||
<div>{info.componentStack}</div>
|
||||
)}
|
||||
|
||||
{<div className={styles.version}>Version: {window.Sonarr.version}</div>}
|
||||
<div className={styles.version}>Version: {window.Sonarr.version}</div>
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import Icon from 'Components/Icon';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||
|
@ -82,9 +82,7 @@ function EpisodeNumber(props: EpisodeNumberProps) {
|
|||
<Popover
|
||||
anchor={
|
||||
<span>
|
||||
{showSeasonNumber && seasonNumber != null && (
|
||||
<Fragment>{seasonNumber}x</Fragment>
|
||||
)}
|
||||
{showSeasonNumber && seasonNumber != null && <>{seasonNumber}x</>}
|
||||
|
||||
{showSeasonNumber ? padNumber(episodeNumber, 2) : episodeNumber}
|
||||
|
||||
|
@ -111,9 +109,7 @@ function EpisodeNumber(props: EpisodeNumberProps) {
|
|||
/>
|
||||
) : (
|
||||
<span>
|
||||
{showSeasonNumber && seasonNumber != null && (
|
||||
<Fragment>{seasonNumber}x</Fragment>
|
||||
)}
|
||||
{showSeasonNumber && seasonNumber != null && <>{seasonNumber}x</>}
|
||||
|
||||
{showSeasonNumber ? padNumber(episodeNumber, 2) : episodeNumber}
|
||||
|
||||
|
|
|
@ -3,15 +3,15 @@ import { useCallback, useState } from 'react';
|
|||
export default function useModalOpenState(
|
||||
initialState: boolean
|
||||
): [boolean, () => void, () => void] {
|
||||
const [isOpen, setOpen] = useState(initialState);
|
||||
const [isOpen, setIsOpen] = useState(initialState);
|
||||
|
||||
const setModalOpen = useCallback(() => {
|
||||
setOpen(true);
|
||||
}, [setOpen]);
|
||||
setIsOpen(true);
|
||||
}, [setIsOpen]);
|
||||
|
||||
const setModalClosed = useCallback(() => {
|
||||
setOpen(false);
|
||||
}, [setOpen]);
|
||||
setIsOpen(false);
|
||||
}, [setIsOpen]);
|
||||
|
||||
return [isOpen, setModalOpen, setModalClosed];
|
||||
}
|
||||
|
|
|
@ -857,7 +857,7 @@ function InteractiveImportModalContent(
|
|||
|
||||
<MenuContent>
|
||||
<SelectedMenuItem
|
||||
name={'all'}
|
||||
name="all"
|
||||
isSelected={!filterExistingFiles}
|
||||
onPress={onFilterExistingFilesChange}
|
||||
>
|
||||
|
@ -865,7 +865,7 @@ function InteractiveImportModalContent(
|
|||
</SelectedMenuItem>
|
||||
|
||||
<SelectedMenuItem
|
||||
name={'new'}
|
||||
name="new"
|
||||
isSelected={filterExistingFiles}
|
||||
onPress={onFilterExistingFilesChange}
|
||||
>
|
||||
|
@ -945,7 +945,7 @@ function InteractiveImportModalContent(
|
|||
<SelectInput
|
||||
className={styles.bulkSelect}
|
||||
name="select"
|
||||
value={'select'}
|
||||
value="select"
|
||||
values={bulkSelectOptions}
|
||||
isDisabled={!selectedIds.length}
|
||||
onChange={onSelectModalSelect}
|
||||
|
|
|
@ -17,7 +17,7 @@ function SelectLanguageModal(props: SelectLanguageModalProps) {
|
|||
props;
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onModalClose={onModalClose} size={sizes.MEDIUM}>
|
||||
<Modal isOpen={isOpen} size={sizes.MEDIUM} onModalClose={onModalClose}>
|
||||
<SelectLanguageModalContent
|
||||
languageIds={languageIds}
|
||||
modalTitle={modalTitle}
|
||||
|
|
|
@ -64,19 +64,20 @@ interface RowItemData {
|
|||
onSeriesSelect(seriesId: number): void;
|
||||
}
|
||||
|
||||
const Row: React.FC<ListChildComponentProps<RowItemData>> = ({
|
||||
index,
|
||||
style,
|
||||
data,
|
||||
}) => {
|
||||
function Row({ index, style, data }: ListChildComponentProps<RowItemData>) {
|
||||
const { items, columns, onSeriesSelect } = data;
|
||||
const series = index >= items.length ? null : items[index];
|
||||
|
||||
if (index >= items.length) {
|
||||
const handlePress = useCallback(() => {
|
||||
if (series?.id) {
|
||||
onSeriesSelect(series.id);
|
||||
}
|
||||
}, [series?.id, onSeriesSelect]);
|
||||
|
||||
if (series == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const series = items[index];
|
||||
|
||||
return (
|
||||
<VirtualTableRowButton
|
||||
style={{
|
||||
|
@ -84,7 +85,7 @@ const Row: React.FC<ListChildComponentProps<RowItemData>> = ({
|
|||
justifyContent: 'space-between',
|
||||
...style,
|
||||
}}
|
||||
onPress={() => onSeriesSelect(series.id)}
|
||||
onPress={handlePress}
|
||||
>
|
||||
<SelectSeriesRow
|
||||
key={series.id}
|
||||
|
@ -98,7 +99,7 @@ const Row: React.FC<ListChildComponentProps<RowItemData>> = ({
|
|||
/>
|
||||
</VirtualTableRowButton>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function SelectSeriesModalContent(props: SelectSeriesModalContentProps) {
|
||||
const { modalTitle, onSeriesSelect, onModalClose } = props;
|
||||
|
@ -197,9 +198,9 @@ function SelectSeriesModalContent(props: SelectSeriesModalContentProps) {
|
|||
/>
|
||||
|
||||
<Scroller
|
||||
ref={scrollerRef}
|
||||
className={styles.scroller}
|
||||
autoFocus={false}
|
||||
ref={scrollerRef}
|
||||
>
|
||||
<SelectSeriesModalTableHeader columns={columns} />
|
||||
<List<RowItemData>
|
||||
|
|
|
@ -17,7 +17,7 @@ function SelectDownloadClientModal(props: SelectDownloadClientModalProps) {
|
|||
props;
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onModalClose={onModalClose} size={sizes.MEDIUM}>
|
||||
<Modal isOpen={isOpen} size={sizes.MEDIUM} onModalClose={onModalClose}>
|
||||
<SelectDownloadClientModalContent
|
||||
protocol={protocol}
|
||||
modalTitle={modalTitle}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Fragment, useCallback, useState } from 'react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import ParseModal from 'Parse/ParseModal';
|
||||
|
@ -16,7 +16,7 @@ function ParseToolbarButton() {
|
|||
}, [setIsParseModalOpen]);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<>
|
||||
<PageToolbarButton
|
||||
label={translate('TestParsing')}
|
||||
iconName={icons.PARSE}
|
||||
|
@ -24,7 +24,7 @@ function ParseToolbarButton() {
|
|||
/>
|
||||
|
||||
<ParseModal isOpen={isParseModalOpen} onModalClose={onParseModalClose} />
|
||||
</Fragment>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,11 +42,7 @@ interface SeriesIndexOverviewsProps {
|
|||
isSmallScreen: boolean;
|
||||
}
|
||||
|
||||
const Row: React.FC<ListChildComponentProps<RowItemData>> = ({
|
||||
index,
|
||||
style,
|
||||
data,
|
||||
}) => {
|
||||
function Row({ index, style, data }: ListChildComponentProps<RowItemData>) {
|
||||
const { items, ...otherData } = data;
|
||||
|
||||
if (index >= items.length) {
|
||||
|
@ -60,7 +56,7 @@ const Row: React.FC<ListChildComponentProps<RowItemData>> = ({
|
|||
<SeriesIndexOverview seriesId={series.id} {...otherData} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function getWindowScrollTopPosition() {
|
||||
return document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||
|
|
|
@ -60,12 +60,12 @@ const seriesIndexSelector = createSelector(
|
|||
}
|
||||
);
|
||||
|
||||
const Cell: React.FC<GridChildComponentProps<CellItemData>> = ({
|
||||
function Cell({
|
||||
columnIndex,
|
||||
rowIndex,
|
||||
style,
|
||||
data,
|
||||
}) => {
|
||||
}: GridChildComponentProps<CellItemData>) {
|
||||
const { layout, items, sortKey, isSelectMode } = data;
|
||||
const { columnCount, padding, posterWidth, posterHeight } = layout;
|
||||
const index = rowIndex * columnCount + columnIndex;
|
||||
|
@ -92,7 +92,7 @@ const Cell: React.FC<GridChildComponentProps<CellItemData>> = ({
|
|||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function getWindowScrollTopPosition() {
|
||||
return document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||
|
|
|
@ -45,11 +45,7 @@ const columnsSelector = createSelector(
|
|||
(columns) => columns
|
||||
);
|
||||
|
||||
const Row: React.FC<ListChildComponentProps<RowItemData>> = ({
|
||||
index,
|
||||
style,
|
||||
data,
|
||||
}) => {
|
||||
function Row({ index, style, data }: ListChildComponentProps<RowItemData>) {
|
||||
const { items, sortKey, columns, isSelectMode } = data;
|
||||
|
||||
if (index >= items.length) {
|
||||
|
@ -75,7 +71,7 @@ const Row: React.FC<ListChildComponentProps<RowItemData>> = ({
|
|||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function getWindowScrollTopPosition() {
|
||||
return document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Fragment, useCallback } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
|
@ -32,7 +32,7 @@ function SeriesIndexTableOptions(props: SeriesIndexTableOptionsProps) {
|
|||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('ShowBanners')}</FormLabel>
|
||||
|
||||
|
@ -56,7 +56,7 @@ function SeriesIndexTableOptions(props: SeriesIndexTableOptionsProps) {
|
|||
onChange={onTableOptionChangeWrapper}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Fragment>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
|
@ -17,11 +17,11 @@ function CustomFormatSettingsPage() {
|
|||
// @ts-ignore
|
||||
showSave={false}
|
||||
additionalButtons={
|
||||
<Fragment>
|
||||
<>
|
||||
<PageToolbarSeparator />
|
||||
|
||||
<ParseToolbarButton />
|
||||
</Fragment>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
|
|
|
@ -231,9 +231,9 @@ function ManageDownloadClientsModalContent(
|
|||
selectAll={true}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
onSortPress={onSortPress}
|
||||
>
|
||||
<TableBody>
|
||||
|
@ -286,9 +286,9 @@ function ManageDownloadClientsModalContent(
|
|||
|
||||
<ManageDownloadClientsEditModal
|
||||
isOpen={isEditModalOpen}
|
||||
downloadClientIds={selectedIds}
|
||||
onModalClose={onEditModalClose}
|
||||
onSavePress={onSavePress}
|
||||
downloadClientIds={selectedIds}
|
||||
/>
|
||||
|
||||
<TagsModal
|
||||
|
|
|
@ -261,9 +261,9 @@ function ManageImportListsModalContent(
|
|||
|
||||
<ManageImportListsEditModal
|
||||
isOpen={isEditModalOpen}
|
||||
importListIds={selectedIds}
|
||||
onModalClose={onEditModalClose}
|
||||
onSavePress={onSavePress}
|
||||
importListIds={selectedIds}
|
||||
/>
|
||||
|
||||
<TagsModal
|
||||
|
|
|
@ -226,9 +226,9 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) {
|
|||
selectAll={true}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
onSortPress={onSortPress}
|
||||
>
|
||||
<TableBody>
|
||||
|
@ -281,9 +281,9 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) {
|
|||
|
||||
<ManageIndexersEditModal
|
||||
isOpen={isEditModalOpen}
|
||||
indexerIds={selectedIds}
|
||||
onModalClose={onEditModalClose}
|
||||
onSavePress={onSavePress}
|
||||
indexerIds={selectedIds}
|
||||
/>
|
||||
|
||||
<TagsModal
|
||||
|
|
|
@ -66,7 +66,7 @@ function About() {
|
|||
) : null}
|
||||
|
||||
{isDocker ? (
|
||||
<DescriptionListItem title={translate('Docker')} data={'Yes'} />
|
||||
<DescriptionListItem title={translate('Docker')} data="Yes" />
|
||||
) : null}
|
||||
|
||||
<DescriptionListItem
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import React, {
|
||||
Fragment,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import AppState from 'App/State/AppState';
|
||||
|
@ -158,7 +152,7 @@ function Updates() {
|
|||
{translate('InstallLatest')}
|
||||
</SpinnerButton>
|
||||
) : (
|
||||
<Fragment>
|
||||
<>
|
||||
<Icon name={icons.WARNING} kind={kinds.WARNING} size={30} />
|
||||
|
||||
<div className={styles.message}>
|
||||
|
@ -171,7 +165,7 @@ function Updates() {
|
|||
}
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
|
||||
{isFetching ? (
|
||||
|
|
Loading…
Reference in New Issue