mirror of
https://github.com/lidarr/lidarr.git
synced 2025-08-21 05:53:33 -07:00
New: Add tag support to indexers
Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
This commit is contained in:
parent
77041a5401
commit
a26cbdf61f
29 changed files with 351 additions and 578 deletions
|
@ -43,6 +43,7 @@ function EditIndexerModalContent(props) {
|
|||
enableInteractiveSearch,
|
||||
supportsRss,
|
||||
supportsSearch,
|
||||
tags,
|
||||
fields,
|
||||
priority,
|
||||
protocol,
|
||||
|
@ -168,18 +169,30 @@ function EditIndexerModalContent(props) {
|
|||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>DownloadClient</FormLabel>
|
||||
<FormLabel>{translate('DownloadClient')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.DOWNLOAD_CLIENT_SELECT}
|
||||
name="downloadClientId"
|
||||
helpText={'Specify which download client is used for grabs from this indexer'}
|
||||
helpText={translate('IndexerDownloadClientHelpText')}
|
||||
{...downloadClientId}
|
||||
includeAny={true}
|
||||
protocol={protocol.value}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Tags')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TAG}
|
||||
name="tags"
|
||||
helpText={translate('IndexerTagHelpText')}
|
||||
{...tags}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
}
|
||||
</ModalBody>
|
||||
|
|
|
@ -4,6 +4,7 @@ import Card from 'Components/Card';
|
|||
import Label from 'Components/Label';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import TagList from 'Components/TagList';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import EditIndexerModalConnector from './EditIndexerModalConnector';
|
||||
|
@ -68,6 +69,8 @@ class Indexer extends Component {
|
|||
enableRss,
|
||||
enableAutomaticSearch,
|
||||
enableInteractiveSearch,
|
||||
tags,
|
||||
tagList,
|
||||
supportsRss,
|
||||
supportsSearch,
|
||||
priority,
|
||||
|
@ -133,6 +136,11 @@ class Indexer extends Component {
|
|||
}
|
||||
</div>
|
||||
|
||||
<TagList
|
||||
tags={tags}
|
||||
tagList={tagList}
|
||||
/>
|
||||
|
||||
<EditIndexerModalConnector
|
||||
id={id}
|
||||
isOpen={this.state.isEditIndexerModalOpen}
|
||||
|
@ -161,6 +169,8 @@ Indexer.propTypes = {
|
|||
enableRss: PropTypes.bool.isRequired,
|
||||
enableAutomaticSearch: PropTypes.bool.isRequired,
|
||||
enableInteractiveSearch: PropTypes.bool.isRequired,
|
||||
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
tagList: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
supportsRss: PropTypes.bool.isRequired,
|
||||
supportsSearch: PropTypes.bool.isRequired,
|
||||
showPriority: PropTypes.bool.isRequired,
|
||||
|
|
|
@ -54,6 +54,7 @@ class Indexers extends Component {
|
|||
render() {
|
||||
const {
|
||||
items,
|
||||
tagList,
|
||||
dispatchCloneIndexer,
|
||||
onConfirmDeleteIndexer,
|
||||
...otherProps
|
||||
|
@ -79,6 +80,7 @@ class Indexers extends Component {
|
|||
<Indexer
|
||||
key={item.id}
|
||||
{...item}
|
||||
tagList={tagList}
|
||||
showPriority={showPriority}
|
||||
onCloneIndexerPress={this.onCloneIndexerPress}
|
||||
onConfirmDeleteIndexer={onConfirmDeleteIndexer}
|
||||
|
@ -119,6 +121,7 @@ Indexers.propTypes = {
|
|||
isFetching: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
tagList: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
dispatchCloneIndexer: PropTypes.func.isRequired,
|
||||
onConfirmDeleteIndexer: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
|
@ -4,13 +4,20 @@ import { connect } from 'react-redux';
|
|||
import { createSelector } from 'reselect';
|
||||
import { cloneIndexer, deleteIndexer, fetchIndexers } from 'Store/Actions/settingsActions';
|
||||
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
|
||||
import createTagsSelector from 'Store/Selectors/createTagsSelector';
|
||||
import sortByName from 'Utilities/Array/sortByName';
|
||||
import Indexers from './Indexers';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createSortedSectionSelector('settings.indexers', sortByName),
|
||||
(indexers) => indexers
|
||||
createTagsSelector(),
|
||||
(indexers, tagList) => {
|
||||
return {
|
||||
...indexers,
|
||||
tagList
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ function TagDetailsModalContent(props) {
|
|||
importLists,
|
||||
notifications,
|
||||
releaseProfiles,
|
||||
indexers,
|
||||
onModalClose,
|
||||
onDeleteTagPress
|
||||
} = props;
|
||||
|
@ -41,7 +42,7 @@ function TagDetailsModalContent(props) {
|
|||
}
|
||||
|
||||
{
|
||||
!!artist.length &&
|
||||
artist.length ?
|
||||
<FieldSet legend={translate('Artists')}>
|
||||
{
|
||||
artist.map((item) => {
|
||||
|
@ -52,11 +53,12 @@ function TagDetailsModalContent(props) {
|
|||
);
|
||||
})
|
||||
}
|
||||
</FieldSet>
|
||||
</FieldSet> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!!delayProfiles.length &&
|
||||
delayProfiles.length ?
|
||||
<FieldSet legend={translate('DelayProfile')}>
|
||||
{
|
||||
delayProfiles.map((item) => {
|
||||
|
@ -81,11 +83,12 @@ function TagDetailsModalContent(props) {
|
|||
);
|
||||
})
|
||||
}
|
||||
</FieldSet>
|
||||
</FieldSet> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!!notifications.length &&
|
||||
notifications.length ?
|
||||
<FieldSet legend={translate('Connections')}>
|
||||
{
|
||||
notifications.map((item) => {
|
||||
|
@ -96,11 +99,12 @@ function TagDetailsModalContent(props) {
|
|||
);
|
||||
})
|
||||
}
|
||||
</FieldSet>
|
||||
</FieldSet> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!!importLists.length &&
|
||||
importLists.length ?
|
||||
<FieldSet legend={translate('ImportLists')}>
|
||||
{
|
||||
importLists.map((item) => {
|
||||
|
@ -111,11 +115,12 @@ function TagDetailsModalContent(props) {
|
|||
);
|
||||
})
|
||||
}
|
||||
</FieldSet>
|
||||
</FieldSet> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!!releaseProfiles.length &&
|
||||
releaseProfiles.length ?
|
||||
<FieldSet legend={translate('ReleaseProfiles')}>
|
||||
{
|
||||
releaseProfiles.map((item) => {
|
||||
|
@ -157,7 +162,24 @@ function TagDetailsModalContent(props) {
|
|||
);
|
||||
})
|
||||
}
|
||||
</FieldSet>
|
||||
</FieldSet> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
indexers.length ?
|
||||
<FieldSet legend="Indexers">
|
||||
{
|
||||
indexers.map((item) => {
|
||||
return (
|
||||
<div key={item.id}>
|
||||
{item.name}
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</FieldSet> :
|
||||
null
|
||||
}
|
||||
</ModalBody>
|
||||
|
||||
|
@ -192,6 +214,7 @@ TagDetailsModalContent.propTypes = {
|
|||
importLists: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
notifications: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
releaseProfiles: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
indexers: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
onDeleteTagPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
|
@ -69,6 +69,14 @@ function createMatchingReleaseProfilesSelector() {
|
|||
);
|
||||
}
|
||||
|
||||
function createMatchingIndexersSelector() {
|
||||
return createSelector(
|
||||
(state, { indexerIds }) => indexerIds,
|
||||
(state) => state.settings.indexers.items,
|
||||
findMatchingItems
|
||||
);
|
||||
}
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createMatchingArtistSelector(),
|
||||
|
@ -76,13 +84,15 @@ function createMapStateToProps() {
|
|||
createMatchingImportListsSelector(),
|
||||
createMatchingNotificationsSelector(),
|
||||
createMatchingReleaseProfilesSelector(),
|
||||
(artist, delayProfiles, importLists, notifications, releaseProfiles) => {
|
||||
createMatchingIndexersSelector(),
|
||||
(artist, delayProfiles, importLists, notifications, releaseProfiles, indexers) => {
|
||||
return {
|
||||
artist,
|
||||
delayProfiles,
|
||||
importLists,
|
||||
notifications,
|
||||
releaseProfiles
|
||||
releaseProfiles,
|
||||
indexers
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
|
@ -57,6 +57,7 @@ class Tag extends Component {
|
|||
importListIds,
|
||||
notificationIds,
|
||||
restrictionIds,
|
||||
indexerIds,
|
||||
artistIds
|
||||
} = this.props;
|
||||
|
||||
|
@ -70,6 +71,7 @@ class Tag extends Component {
|
|||
importListIds.length ||
|
||||
notificationIds.length ||
|
||||
restrictionIds.length ||
|
||||
indexerIds.length ||
|
||||
artistIds.length
|
||||
);
|
||||
|
||||
|
@ -87,38 +89,50 @@ class Tag extends Component {
|
|||
isTagUsed &&
|
||||
<div>
|
||||
{
|
||||
!!artistIds.length &&
|
||||
artistIds.length ?
|
||||
<div>
|
||||
{artistIds.length} artists
|
||||
</div>
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!!delayProfileIds.length &&
|
||||
delayProfileIds.length ?
|
||||
<div>
|
||||
{delayProfileIds.length} delay profile{delayProfileIds.length > 1 && 's'}
|
||||
</div>
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!!importListIds.length &&
|
||||
importListIds.length ?
|
||||
<div>
|
||||
{importListIds.length} import list{importListIds.length > 1 && 's'}
|
||||
</div>
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!!notificationIds.length &&
|
||||
notificationIds.length ?
|
||||
<div>
|
||||
{notificationIds.length} connection{notificationIds.length > 1 && 's'}
|
||||
</div>
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!!restrictionIds.length &&
|
||||
restrictionIds.length ?
|
||||
<div>
|
||||
{restrictionIds.length} restriction{restrictionIds.length > 1 && 's'}
|
||||
</div>
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
{
|
||||
indexerIds.length ?
|
||||
<div>
|
||||
{indexerIds.length} indexer{indexerIds.length > 1 && 's'}
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
@ -138,6 +152,7 @@ class Tag extends Component {
|
|||
importListIds={importListIds}
|
||||
notificationIds={notificationIds}
|
||||
restrictionIds={restrictionIds}
|
||||
indexerIds={indexerIds}
|
||||
isOpen={isDetailsModalOpen}
|
||||
onModalClose={this.onDetailsModalClose}
|
||||
onDeleteTagPress={this.onDeleteTagPress}
|
||||
|
@ -164,6 +179,7 @@ Tag.propTypes = {
|
|||
importListIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
notificationIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
restrictionIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
indexerIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
artistIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
onConfirmDeleteTag: PropTypes.func.isRequired
|
||||
};
|
||||
|
@ -173,6 +189,7 @@ Tag.defaultProps = {
|
|||
importListIds: [],
|
||||
notificationIds: [],
|
||||
restrictionIds: [],
|
||||
indexerIds: [],
|
||||
artistIds: []
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { fetchDelayProfiles, fetchImportLists, fetchNotifications, fetchReleaseProfiles } from 'Store/Actions/settingsActions';
|
||||
import { fetchDelayProfiles, fetchImportLists, fetchIndexers, fetchNotifications, fetchReleaseProfiles } from 'Store/Actions/settingsActions';
|
||||
import { fetchTagDetails } from 'Store/Actions/tagActions';
|
||||
import Tags from './Tags';
|
||||
|
||||
|
@ -29,7 +29,8 @@ const mapDispatchToProps = {
|
|||
dispatchFetchDelayProfiles: fetchDelayProfiles,
|
||||
dispatchFetchImportLists: fetchImportLists,
|
||||
dispatchFetchNotifications: fetchNotifications,
|
||||
dispatchFetchReleaseProfiles: fetchReleaseProfiles
|
||||
dispatchFetchReleaseProfiles: fetchReleaseProfiles,
|
||||
dispatchFetchIndexers: fetchIndexers
|
||||
};
|
||||
|
||||
class MetadatasConnector extends Component {
|
||||
|
@ -43,7 +44,8 @@ class MetadatasConnector extends Component {
|
|||
dispatchFetchDelayProfiles,
|
||||
dispatchFetchImportLists,
|
||||
dispatchFetchNotifications,
|
||||
dispatchFetchReleaseProfiles
|
||||
dispatchFetchReleaseProfiles,
|
||||
dispatchFetchIndexers
|
||||
} = this.props;
|
||||
|
||||
dispatchFetchTagDetails();
|
||||
|
@ -51,6 +53,7 @@ class MetadatasConnector extends Component {
|
|||
dispatchFetchImportLists();
|
||||
dispatchFetchNotifications();
|
||||
dispatchFetchReleaseProfiles();
|
||||
dispatchFetchIndexers();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -70,7 +73,8 @@ MetadatasConnector.propTypes = {
|
|||
dispatchFetchDelayProfiles: PropTypes.func.isRequired,
|
||||
dispatchFetchImportLists: PropTypes.func.isRequired,
|
||||
dispatchFetchNotifications: PropTypes.func.isRequired,
|
||||
dispatchFetchReleaseProfiles: PropTypes.func.isRequired
|
||||
dispatchFetchReleaseProfiles: PropTypes.func.isRequired,
|
||||
dispatchFetchIndexers: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(MetadatasConnector);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue