mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-10-01 07:55:22 +02:00
Update React Lint rules for TSX
(cherry picked from commit 1299a97579bec52ee3d16ab8d05c9e22edd80330)
This commit is contained in:
@@ -357,11 +357,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',
|
||||
@@ -374,7 +379,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'
|
||||
})
|
||||
},
|
||||
{
|
||||
|
@@ -23,6 +23,10 @@ import Tasks from 'System/Tasks/Tasks';
|
||||
import UpdatesConnector from 'System/Updates/UpdatesConnector';
|
||||
import getPathWithUrlBase from 'Utilities/getPathWithUrlBase';
|
||||
|
||||
function RedirectWithUrlBase() {
|
||||
return <Redirect to={getPathWithUrlBase('/')} />;
|
||||
}
|
||||
|
||||
function AppRoutes() {
|
||||
return (
|
||||
<Switch>
|
||||
@@ -39,9 +43,7 @@ function AppRoutes() {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
addUrlBase={false}
|
||||
render={() => {
|
||||
return <Redirect to={getPathWithUrlBase('/')} />;
|
||||
}}
|
||||
render={RedirectWithUrlBase}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
@@ -63,11 +63,7 @@ function ErrorBoundaryError(props: ErrorBoundaryErrorProps) {
|
||||
<div>{info.componentStack}</div>
|
||||
)}
|
||||
|
||||
{
|
||||
<div className={styles.version}>
|
||||
Version: {window.Prowlarr.version}
|
||||
</div>
|
||||
}
|
||||
<div className={styles.version}>Version: {window.Prowlarr.version}</div>
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
|
@@ -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];
|
||||
}
|
||||
|
@@ -29,8 +29,8 @@ function AddIndexerModal({
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
size={sizes.EXTRA_LARGE}
|
||||
onModalClose={onModalClosePress}
|
||||
className={styles.modal}
|
||||
onModalClose={onModalClosePress}
|
||||
>
|
||||
<AddIndexerModalContent
|
||||
{...otherProps}
|
||||
|
@@ -168,6 +168,34 @@ function AddIndexerModalContent(props: AddIndexerModalContentProps) {
|
||||
[setFilter]
|
||||
);
|
||||
|
||||
const onFilterProtocolsChange = useCallback(
|
||||
({ value }: { value: string[] }) => {
|
||||
setFilterProtocols(value);
|
||||
},
|
||||
[setFilterProtocols]
|
||||
);
|
||||
|
||||
const onFilterLanguagesChange = useCallback(
|
||||
({ value }: { value: string[] }) => {
|
||||
setFilterLanguages(value);
|
||||
},
|
||||
[setFilterLanguages]
|
||||
);
|
||||
|
||||
const onFilterPrivacyLevelsChange = useCallback(
|
||||
({ value }: { value: string[] }) => {
|
||||
setFilterPrivacyLevels(value);
|
||||
},
|
||||
[setFilterPrivacyLevels]
|
||||
);
|
||||
|
||||
const onFilterCategoriesChange = useCallback(
|
||||
({ value }: { value: number[] }) => {
|
||||
setFilterCategories(value);
|
||||
},
|
||||
[setFilterCategories]
|
||||
);
|
||||
|
||||
const onIndexerSelect = useCallback(
|
||||
({
|
||||
implementation,
|
||||
@@ -304,9 +332,7 @@ function AddIndexerModalContent(props: AddIndexerModalContentProps) {
|
||||
name="indexerProtocols"
|
||||
value={filterProtocols}
|
||||
values={PROTOCOLS}
|
||||
onChange={({ value }: { value: string[] }) =>
|
||||
setFilterProtocols(value)
|
||||
}
|
||||
onChange={onFilterProtocolsChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -319,9 +345,7 @@ function AddIndexerModalContent(props: AddIndexerModalContentProps) {
|
||||
name="indexerLanguages"
|
||||
value={filterLanguages}
|
||||
values={languages}
|
||||
onChange={({ value }: { value: string[] }) =>
|
||||
setFilterLanguages(value)
|
||||
}
|
||||
onChange={onFilterLanguagesChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -331,9 +355,7 @@ function AddIndexerModalContent(props: AddIndexerModalContentProps) {
|
||||
name="indexerPrivacyLevels"
|
||||
value={filterPrivacyLevels}
|
||||
values={PRIVACY_LEVELS}
|
||||
onChange={({ value }: { value: string[] }) =>
|
||||
setFilterPrivacyLevels(value)
|
||||
}
|
||||
onChange={onFilterPrivacyLevelsChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -345,9 +367,7 @@ function AddIndexerModalContent(props: AddIndexerModalContentProps) {
|
||||
<NewznabCategorySelectInputConnector
|
||||
name="indexerCategories"
|
||||
value={filterCategories}
|
||||
onChange={({ value }: { value: number[] }) =>
|
||||
setFilterCategories(value)
|
||||
}
|
||||
onChange={onFilterCategoriesChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,6 +2,7 @@ import { uniqBy } from 'lodash';
|
||||
import React from 'react';
|
||||
import Label from 'Components/Label';
|
||||
import { IndexerCapabilities } from 'Indexer/Indexer';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
interface CapabilitiesLabelProps {
|
||||
capabilities: IndexerCapabilities;
|
||||
@@ -38,7 +39,7 @@ function CapabilitiesLabel(props: CapabilitiesLabelProps) {
|
||||
);
|
||||
})}
|
||||
|
||||
{filteredList.length === 0 ? <Label>{'None'}</Label> : null}
|
||||
{filteredList.length === 0 ? <Label>{translate('None')}</Label> : null}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@@ -46,11 +46,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, onCloneIndexerPress } = data;
|
||||
|
||||
if (index >= items.length) {
|
||||
@@ -77,7 +73,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,19 +32,17 @@ function IndexerIndexTableOptions(props: IndexerIndexTableOptionsProps) {
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('ShowSearch')}</FormLabel>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('ShowSearch')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="showSearchAction"
|
||||
value={showSearchAction}
|
||||
helpText={translate('ShowSearchHelpText')}
|
||||
onChange={onTableOptionChangeWrapper}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Fragment>
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="showSearchAction"
|
||||
value={showSearchAction}
|
||||
helpText={translate('ShowSearchHelpText')}
|
||||
onChange={onTableOptionChangeWrapper}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -38,14 +38,12 @@ function IndexerStatusCell(props: IndexerStatusCellProps) {
|
||||
|
||||
return (
|
||||
<Component className={className} {...otherProps}>
|
||||
{
|
||||
<Icon
|
||||
className={styles.statusIcon}
|
||||
kind={enabled ? enableKind : kinds.DEFAULT}
|
||||
name={enabled ? enableIcon : icons.BLOCKLIST}
|
||||
title={enabled ? enableTitle : translate('Disabled')}
|
||||
/>
|
||||
}
|
||||
<Icon
|
||||
className={styles.statusIcon}
|
||||
kind={enabled ? enableKind : kinds.DEFAULT}
|
||||
name={enabled ? enableIcon : icons.BLOCKLIST}
|
||||
title={enabled ? enableTitle : translate('Disabled')}
|
||||
/>
|
||||
{status ? (
|
||||
<Popover
|
||||
className={styles.indexerStatusTooltip}
|
||||
|
@@ -83,8 +83,8 @@ function IndexerHistoryRow(props: IndexerHistoryRowProps) {
|
||||
<TableRowCell className={styles.details}>
|
||||
<IconButton
|
||||
name={icons.INFO}
|
||||
onPress={onDetailsModalPress}
|
||||
title={translate('HistoryDetails')}
|
||||
onPress={onDetailsModalPress}
|
||||
/>
|
||||
</TableRowCell>
|
||||
|
||||
|
@@ -28,7 +28,7 @@ function NoIndexer(props: NoIndexerProps) {
|
||||
</div>
|
||||
|
||||
<div className={styles.buttonContainer}>
|
||||
<Button onPress={onAddIndexerPress} kind={kinds.PRIMARY}>
|
||||
<Button kind={kinds.PRIMARY} onPress={onAddIndexerPress}>
|
||||
{translate('AddNewIndexer')}
|
||||
</Button>
|
||||
</div>
|
||||
|
@@ -230,9 +230,9 @@ function IndexerStats() {
|
||||
selectedFilterKey={selectedFilterKey}
|
||||
filters={filters}
|
||||
customFilters={customFilters}
|
||||
onFilterSelect={onFilterSelect}
|
||||
filterModalConnectorComponent={IndexerStatsFilterModal}
|
||||
isDisabled={false}
|
||||
onFilterSelect={onFilterSelect}
|
||||
/>
|
||||
</PageToolbarSection>
|
||||
</PageToolbar>
|
||||
|
@@ -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}
|
||||
|
@@ -184,9 +184,9 @@ function SearchIndexRow(props: SearchIndexRowProps) {
|
||||
if (name === 'select') {
|
||||
return (
|
||||
<VirtualTableSelectCell
|
||||
key={name}
|
||||
inputClassName={styles.checkInput}
|
||||
id={guid}
|
||||
key={name}
|
||||
isSelected={isSelected}
|
||||
isDisabled={false}
|
||||
onSelectedChange={onSelectedChange}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, { Fragment, useCallback, useState } from 'react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import AppState from 'App/State/AppState';
|
||||
import { APP_INDEXER_SYNC } from 'Commands/commandNames';
|
||||
@@ -56,7 +56,7 @@ function ApplicationSettings() {
|
||||
// @ts-ignore
|
||||
showSave={false}
|
||||
additionalButtons={
|
||||
<Fragment>
|
||||
<>
|
||||
<PageToolbarSeparator />
|
||||
|
||||
<PageToolbarButton
|
||||
@@ -78,7 +78,7 @@ function ApplicationSettings() {
|
||||
iconName={icons.MANAGE}
|
||||
onPress={onManageApplicationsPress}
|
||||
/>
|
||||
</Fragment>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
|
@@ -213,9 +213,9 @@ function ManageApplicationsModalContent(
|
||||
selectAll={true}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
onSortPress={onSortPress}
|
||||
>
|
||||
<TableBody>
|
||||
@@ -268,9 +268,9 @@ function ManageApplicationsModalContent(
|
||||
|
||||
<ManageApplicationsEditModal
|
||||
isOpen={isEditModalOpen}
|
||||
applicationIds={selectedIds}
|
||||
onModalClose={onEditModalClose}
|
||||
onSavePress={onSavePress}
|
||||
applicationIds={selectedIds}
|
||||
/>
|
||||
|
||||
<TagsModal
|
||||
|
@@ -186,9 +186,9 @@ function ManageDownloadClientsModalContent(
|
||||
selectAll={true}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
onSortPress={onSortPress}
|
||||
>
|
||||
<TableBody>
|
||||
@@ -233,9 +233,9 @@ function ManageDownloadClientsModalContent(
|
||||
|
||||
<ManageDownloadClientsEditModal
|
||||
isOpen={isEditModalOpen}
|
||||
downloadClientIds={selectedIds}
|
||||
onModalClose={onEditModalClose}
|
||||
onSavePress={onSavePress}
|
||||
downloadClientIds={selectedIds}
|
||||
/>
|
||||
|
||||
<ConfirmModal
|
||||
|
@@ -45,11 +45,12 @@ function About() {
|
||||
title={translate('PackageVersion')}
|
||||
data={
|
||||
packageAuthor ? (
|
||||
<span>
|
||||
{' '}
|
||||
{packageVersion} {' by '}{' '}
|
||||
<InlineMarkdown data={packageAuthor} />{' '}
|
||||
</span>
|
||||
<InlineMarkdown
|
||||
data={translate('PackageVersionInfo', {
|
||||
packageVersion,
|
||||
packageAuthor,
|
||||
})}
|
||||
/>
|
||||
) : (
|
||||
packageVersion
|
||||
)
|
||||
@@ -57,16 +58,16 @@ function About() {
|
||||
/>
|
||||
)}
|
||||
|
||||
{isNetCore && (
|
||||
{isNetCore ? (
|
||||
<DescriptionListItem
|
||||
title={translate('NetCore')}
|
||||
data={`Yes (${runtimeVersion})`}
|
||||
/>
|
||||
)}
|
||||
) : null}
|
||||
|
||||
{isDocker && (
|
||||
<DescriptionListItem title={translate('Docker')} data={'Yes'} />
|
||||
)}
|
||||
{isDocker ? (
|
||||
<DescriptionListItem title={translate('Docker')} data="Yes" />
|
||||
) : null}
|
||||
|
||||
<DescriptionListItem
|
||||
title={translate('Database')}
|
||||
|
@@ -527,6 +527,7 @@
|
||||
"PackSeedTime": "Pack Seed Time",
|
||||
"PackSeedTimeHelpText": "The time a pack (season or discography) torrent should be seeded before stopping, empty is app's default",
|
||||
"PackageVersion": "Package Version",
|
||||
"PackageVersionInfo": "{packageVersion} by {packageAuthor}",
|
||||
"PageSize": "Page Size",
|
||||
"PageSizeHelpText": "Number of items to show on each page",
|
||||
"Parameters": "Parameters",
|
||||
|
Reference in New Issue
Block a user