mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-23 22:25:09 -04:00
New: Readarr 0.1
This commit is contained in:
+14
-2
@@ -15,8 +15,9 @@ const newRemotePathMapping = {
|
||||
|
||||
const selectDownloadClientHosts = createSelector(
|
||||
(state) => state.settings.downloadClients.items,
|
||||
(downloadClients) => {
|
||||
const hosts = downloadClients.reduce((acc, downloadClient) => {
|
||||
(state) => state.settings.rootFolders.items,
|
||||
(downloadClients, rootFolders) => {
|
||||
const dlhosts = downloadClients.reduce((acc, downloadClient) => {
|
||||
const name = downloadClient.name;
|
||||
const host = downloadClient.fields.find((field) => {
|
||||
return field.name === 'host';
|
||||
@@ -30,6 +31,17 @@ const selectDownloadClientHosts = createSelector(
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const hosts = rootFolders.reduce((acc, folder) => {
|
||||
const name = folder.name;
|
||||
|
||||
if (folder.isCalibreLibrary) {
|
||||
const group = acc[folder.host] = acc[folder.host] || [];
|
||||
group.push(name);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, dlhosts);
|
||||
|
||||
return Object.keys(hosts).map((host) => {
|
||||
return {
|
||||
key: host,
|
||||
|
||||
@@ -24,17 +24,17 @@ function ImportListMonitoringOptionsPopoverContent() {
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
title="None"
|
||||
data="Do not monitor artists or albums"
|
||||
data="Do not monitor authors or books"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Specific Album"
|
||||
data="Monitor artists but only monitor albums explicitly included in the list"
|
||||
title="Specific Book"
|
||||
data="Monitor authors but only monitor books explicitly included in the list"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="All Artist Albums"
|
||||
data="Monitor artists and all albums for each artist included on the import list"
|
||||
title="All Author Books"
|
||||
data="Monitor authors and all books for each author included on the import list"
|
||||
/>
|
||||
</DescriptionList>
|
||||
);
|
||||
@@ -44,8 +44,8 @@ function EditImportListModalContent(props) {
|
||||
|
||||
const monitorOptions = [
|
||||
{ key: 'none', value: 'None' },
|
||||
{ key: 'specificAlbum', value: 'Specific Album' },
|
||||
{ key: 'entireArtist', value: 'All Artist Albums' }
|
||||
{ key: 'specificAlbum', value: 'Specific Book' },
|
||||
{ key: 'entireArtist', value: 'All Author Books' }
|
||||
];
|
||||
|
||||
const {
|
||||
@@ -115,7 +115,7 @@ function EditImportListModalContent(props) {
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="enableAutomaticAdd"
|
||||
helpText={'Add artist/albums to Readarr when syncs are performed via the UI or by Readarr'}
|
||||
helpText={'Add author/books to Readarr when syncs are performed via the UI or by Readarr'}
|
||||
{...enableAutomaticAdd}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
@@ -142,7 +142,7 @@ function EditImportListModalContent(props) {
|
||||
type={inputTypes.SELECT}
|
||||
name="shouldMonitor"
|
||||
values={monitorOptions}
|
||||
helpText={'Monitor artists and albums added from this list'}
|
||||
helpText={'Monitor authors and books added from this list'}
|
||||
{...shouldMonitor}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
@@ -191,7 +191,7 @@ function EditImportListModalContent(props) {
|
||||
<FormInputGroup
|
||||
type={inputTypes.TAG}
|
||||
name="tags"
|
||||
helpText="Add artists from this list with these tags"
|
||||
helpText="Add authors from this list with these tags"
|
||||
{...tags}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
|
||||
@@ -11,6 +11,7 @@ import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import RootFoldersConnector from './RootFolder/RootFoldersConnector';
|
||||
import RemotePathMappingsConnector from 'Settings/DownloadClients/RemotePathMappings/RemotePathMappingsConnector';
|
||||
import NamingConnector from './Naming/NamingConnector';
|
||||
|
||||
const rescanAfterRefreshOptions = [
|
||||
@@ -64,6 +65,7 @@ class MediaManagement extends Component {
|
||||
|
||||
<PageContentBodyConnector>
|
||||
<RootFoldersConnector />
|
||||
<RemotePathMappingsConnector />
|
||||
<NamingConnector />
|
||||
|
||||
{
|
||||
|
||||
@@ -40,18 +40,6 @@ class Naming extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
onMultiDiscNamingModalOpenClick = () => {
|
||||
this.setState({
|
||||
isNamingModalOpen: true,
|
||||
namingModalOptions: {
|
||||
name: 'multiDiscTrackFormat',
|
||||
album: true,
|
||||
track: true,
|
||||
additional: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onArtistFolderNamingModalOpenClick = () => {
|
||||
this.setState({
|
||||
isNamingModalOpen: true,
|
||||
@@ -61,16 +49,6 @@ class Naming extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
onAlbumFolderNamingModalOpenClick = () => {
|
||||
this.setState({
|
||||
isNamingModalOpen: true,
|
||||
namingModalOptions: {
|
||||
name: 'albumFolderFormat',
|
||||
album: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onNamingModalClose = () => {
|
||||
this.setState({ isNamingModalOpen: false });
|
||||
}
|
||||
@@ -99,12 +77,8 @@ class Naming extends Component {
|
||||
|
||||
const standardTrackFormatHelpTexts = [];
|
||||
const standardTrackFormatErrors = [];
|
||||
const multiDiscTrackFormatHelpTexts = [];
|
||||
const multiDiscTrackFormatErrors = [];
|
||||
const artistFolderFormatHelpTexts = [];
|
||||
const artistFolderFormatErrors = [];
|
||||
const albumFolderFormatHelpTexts = [];
|
||||
const albumFolderFormatErrors = [];
|
||||
|
||||
if (examplesPopulated) {
|
||||
if (examples.singleTrackExample) {
|
||||
@@ -113,23 +87,11 @@ class Naming extends Component {
|
||||
standardTrackFormatErrors.push({ message: 'Single Track: Invalid Format' });
|
||||
}
|
||||
|
||||
if (examples.multiDiscTrackExample) {
|
||||
multiDiscTrackFormatHelpTexts.push(`Multi Disc Track: ${examples.multiDiscTrackExample}`);
|
||||
} else {
|
||||
multiDiscTrackFormatErrors.push({ message: 'Single Track: Invalid Format' });
|
||||
}
|
||||
|
||||
if (examples.artistFolderExample) {
|
||||
artistFolderFormatHelpTexts.push(`Example: ${examples.artistFolderExample}`);
|
||||
} else {
|
||||
artistFolderFormatErrors.push({ message: 'Invalid Format' });
|
||||
}
|
||||
|
||||
if (examples.albumFolderExample) {
|
||||
albumFolderFormatHelpTexts.push(`Example: ${examples.albumFolderExample}`);
|
||||
} else {
|
||||
albumFolderFormatErrors.push({ message: 'Invalid Format' });
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -188,22 +150,6 @@ class Naming extends Component {
|
||||
errors={[...standardTrackFormatErrors, ...settings.standardTrackFormat.errors]}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup size={sizes.LARGE}>
|
||||
<FormLabel>Multi Disc Track Format</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
inputClassName={styles.namingInput}
|
||||
type={inputTypes.TEXT}
|
||||
name="multiDiscTrackFormat"
|
||||
buttons={<FormInputButton onPress={this.onMultiDiscNamingModalOpenClick}>?</FormInputButton>}
|
||||
onChange={onInputChange}
|
||||
{...settings.multiDiscTrackFormat}
|
||||
helpTexts={multiDiscTrackFormatHelpTexts}
|
||||
errors={[...multiDiscTrackFormatErrors, ...settings.multiDiscTrackFormat.errors]}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -225,21 +171,6 @@ class Naming extends Component {
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Album Folder Format</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
inputClassName={styles.namingInput}
|
||||
type={inputTypes.TEXT}
|
||||
name="albumFolderFormat"
|
||||
buttons={<FormInputButton onPress={this.onAlbumFolderNamingModalOpenClick}>?</FormInputButton>}
|
||||
onChange={onInputChange}
|
||||
{...settings.albumFolderFormat}
|
||||
helpTexts={albumFolderFormatHelpTexts}
|
||||
errors={[...albumFolderFormatErrors, ...settings.albumFolderFormat.errors]}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{
|
||||
namingModalOptions &&
|
||||
<NamingModal
|
||||
|
||||
@@ -42,7 +42,16 @@ function EditRootFolderModalContent(props) {
|
||||
defaultQualityProfileId,
|
||||
defaultMetadataProfileId,
|
||||
defaultMonitorOption,
|
||||
defaultTags
|
||||
defaultTags,
|
||||
isCalibreLibrary,
|
||||
host,
|
||||
port,
|
||||
urlBase,
|
||||
username,
|
||||
password,
|
||||
outputFormat,
|
||||
outputProfile,
|
||||
useSsl
|
||||
} = item;
|
||||
|
||||
return (
|
||||
@@ -83,13 +92,129 @@ function EditRootFolderModalContent(props) {
|
||||
type={id ? inputTypes.TEXT : inputTypes.PATH}
|
||||
readOnly={!!id}
|
||||
name="path"
|
||||
helpText="Root Folder containing your music library"
|
||||
helpText="Root Folder containing your book library"
|
||||
helpTextWarning="This must be different to the directory where your download client puts files"
|
||||
{...path}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Library</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="isCalibreLibrary"
|
||||
helpText="Use calibre content server to manipulate library"
|
||||
{...isCalibreLibrary}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{
|
||||
isCalibreLibrary !== undefined && isCalibreLibrary.value &&
|
||||
<div>
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Host</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="host"
|
||||
helpText="Calibre content server host"
|
||||
{...host}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Port</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="port"
|
||||
helpText="Calibre content server port"
|
||||
{...port}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Calibre Url Base</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="urlBase"
|
||||
helpText="Adds a prefix to the calibre url, e.g. http://[host]:[port]/[urlBase]"
|
||||
{...urlBase}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Username</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="username"
|
||||
helpText="Calibre content server username"
|
||||
{...username}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Password</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.PASSWORD}
|
||||
name="password"
|
||||
helpText="Calibre content server password"
|
||||
{...password}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Convert to format</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="outputFormat"
|
||||
helpText="Optionally ask calibre to convert to other formats on import. Comma separated list."
|
||||
{...outputFormat}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Output Profile</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="outputProfile"
|
||||
helpText="Output profile for conversion"
|
||||
{...outputProfile}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Use SSL</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="useSsl"
|
||||
helpText="Use SSL to connect to calibre content server"
|
||||
{...useSsl}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
</div>
|
||||
}
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
Monitor
|
||||
@@ -112,7 +237,7 @@ function EditRootFolderModalContent(props) {
|
||||
name="defaultMonitorOption"
|
||||
onChange={onInputChange}
|
||||
{...defaultMonitorOption}
|
||||
helpText="Default Monitoring Options for albums by artists detected in this folder"
|
||||
helpText="Default Monitoring Options for books by authors detected in this folder"
|
||||
/>
|
||||
|
||||
</FormGroup>
|
||||
@@ -123,7 +248,7 @@ function EditRootFolderModalContent(props) {
|
||||
<FormInputGroup
|
||||
type={inputTypes.QUALITY_PROFILE_SELECT}
|
||||
name="defaultQualityProfileId"
|
||||
helpText="Default Quality Profile for artists detected in this folder"
|
||||
helpText="Default Quality Profile for authors detected in this folder"
|
||||
{...defaultQualityProfileId}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
@@ -148,7 +273,7 @@ function EditRootFolderModalContent(props) {
|
||||
<FormInputGroup
|
||||
type={inputTypes.METADATA_PROFILE_SELECT}
|
||||
name="defaultMetadataProfileId"
|
||||
helpText="Default Metadata Profile for artists detected in this folder"
|
||||
helpText="Default Metadata Profile for authors detected in this folder"
|
||||
{...defaultMetadataProfileId}
|
||||
includeNone={true}
|
||||
onChange={onInputChange}
|
||||
@@ -161,7 +286,7 @@ function EditRootFolderModalContent(props) {
|
||||
<FormInputGroup
|
||||
type={inputTypes.TAG}
|
||||
name="defaultTags"
|
||||
helpText="Default Readarr Tags for artists detected in this folder"
|
||||
helpText="Default Readarr Tags for authors detected in this folder"
|
||||
{...defaultTags}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
|
||||
@@ -12,9 +12,6 @@ import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import PrimaryTypeItems from './PrimaryTypeItems';
|
||||
import SecondaryTypeItems from './SecondaryTypeItems';
|
||||
import ReleaseStatusItems from './ReleaseStatusItems';
|
||||
import styles from './EditMetadataProfileModalContent.css';
|
||||
|
||||
function EditMetadataProfileModalContent(props) {
|
||||
@@ -23,8 +20,6 @@ function EditMetadataProfileModalContent(props) {
|
||||
error,
|
||||
isSaving,
|
||||
saveError,
|
||||
primaryAlbumTypes,
|
||||
secondaryAlbumTypes,
|
||||
item,
|
||||
isInUse,
|
||||
onInputChange,
|
||||
@@ -37,9 +32,13 @@ function EditMetadataProfileModalContent(props) {
|
||||
const {
|
||||
id,
|
||||
name,
|
||||
primaryAlbumTypes: itemPrimaryAlbumTypes,
|
||||
secondaryAlbumTypes: itemSecondaryAlbumTypes,
|
||||
releaseStatuses: itemReleaseStatuses
|
||||
minRating,
|
||||
minRatingCount,
|
||||
skipMissingDate,
|
||||
skipMissingIsbn,
|
||||
skipPartsAndSets,
|
||||
skipSeriesSecondary,
|
||||
allowedLanguages
|
||||
} = item;
|
||||
|
||||
return (
|
||||
@@ -73,29 +72,86 @@ function EditMetadataProfileModalContent(props) {
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<PrimaryTypeItems
|
||||
metadataProfileItems={itemPrimaryAlbumTypes.value}
|
||||
errors={itemPrimaryAlbumTypes.errors}
|
||||
warnings={itemPrimaryAlbumTypes.warnings}
|
||||
formLabel="Primary Album Types"
|
||||
{...otherProps}
|
||||
/>
|
||||
<FormGroup>
|
||||
<FormLabel>Minimum Rating</FormLabel>
|
||||
|
||||
<SecondaryTypeItems
|
||||
metadataProfileItems={itemSecondaryAlbumTypes.value}
|
||||
errors={itemSecondaryAlbumTypes.errors}
|
||||
warnings={itemSecondaryAlbumTypes.warnings}
|
||||
formLabel="Secondary Album Types"
|
||||
{...otherProps}
|
||||
/>
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="minRating"
|
||||
{...minRating}
|
||||
isFloat={true}
|
||||
min={0}
|
||||
max={5}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<ReleaseStatusItems
|
||||
metadataProfileItems={itemReleaseStatuses.value}
|
||||
errors={itemReleaseStatuses.errors}
|
||||
warnings={itemReleaseStatuses.warnings}
|
||||
formLabel="Release Statuses"
|
||||
{...otherProps}
|
||||
/>
|
||||
<FormGroup>
|
||||
<FormLabel>Minimum Number of Ratings</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="minRatingCount"
|
||||
{...minRatingCount}
|
||||
min={0}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Skip books with missing release date</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="skipMissingDate"
|
||||
{...skipMissingDate}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Skip books with no ISBN or ASIN</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="skipMissingIsbn"
|
||||
{...skipMissingIsbn}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Skip part books and sets</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="skipPartsAndSets"
|
||||
{...skipPartsAndSets}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Skip secondary series books</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="skipSeriesSecondary"
|
||||
{...skipSeriesSecondary}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Allowed Languages</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="allowedLanguages"
|
||||
{...allowedLanguages}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
</Form>
|
||||
}
|
||||
@@ -140,9 +196,6 @@ EditMetadataProfileModalContent.propTypes = {
|
||||
error: PropTypes.object,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
saveError: PropTypes.object,
|
||||
primaryAlbumTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
secondaryAlbumTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
releaseStatuses: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
item: PropTypes.object.isRequired,
|
||||
isInUse: PropTypes.bool.isRequired,
|
||||
onInputChange: PropTypes.func.isRequired,
|
||||
|
||||
+1
-120
@@ -1,4 +1,3 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
@@ -8,87 +7,12 @@ import createProviderSettingsSelector from 'Store/Selectors/createProviderSettin
|
||||
import { fetchMetadataProfileSchema, setMetadataProfileValue, saveMetadataProfile } from 'Store/Actions/settingsActions';
|
||||
import EditMetadataProfileModalContent from './EditMetadataProfileModalContent';
|
||||
|
||||
function createPrimaryAlbumTypesSelector() {
|
||||
return createSelector(
|
||||
createProviderSettingsSelector('metadataProfiles'),
|
||||
(metadataProfile) => {
|
||||
const primaryAlbumTypes = metadataProfile.item.primaryAlbumTypes;
|
||||
if (!primaryAlbumTypes || !primaryAlbumTypes.value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return _.reduceRight(primaryAlbumTypes.value, (result, { allowed, albumType }) => {
|
||||
if (allowed) {
|
||||
result.push({
|
||||
key: albumType.id,
|
||||
value: albumType.name
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}, []);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createSecondaryAlbumTypesSelector() {
|
||||
return createSelector(
|
||||
createProviderSettingsSelector('metadataProfiles'),
|
||||
(metadataProfile) => {
|
||||
const secondaryAlbumTypes = metadataProfile.item.secondaryAlbumTypes;
|
||||
if (!secondaryAlbumTypes || !secondaryAlbumTypes.value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return _.reduceRight(secondaryAlbumTypes.value, (result, { allowed, albumType }) => {
|
||||
if (allowed) {
|
||||
result.push({
|
||||
key: albumType.id,
|
||||
value: albumType.name
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}, []);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createReleaseStatusesSelector() {
|
||||
return createSelector(
|
||||
createProviderSettingsSelector('metadataProfiles'),
|
||||
(metadataProfile) => {
|
||||
const releaseStatuses = metadataProfile.item.releaseStatuses;
|
||||
if (!releaseStatuses || !releaseStatuses.value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return _.reduceRight(releaseStatuses.value, (result, { allowed, releaseStatus }) => {
|
||||
if (allowed) {
|
||||
result.push({
|
||||
key: releaseStatus.id,
|
||||
value: releaseStatus.name
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}, []);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createProviderSettingsSelector('metadataProfiles'),
|
||||
createPrimaryAlbumTypesSelector(),
|
||||
createSecondaryAlbumTypesSelector(),
|
||||
createReleaseStatusesSelector(),
|
||||
createProfileInUseSelector('metadataProfileId'),
|
||||
(metadataProfile, primaryAlbumTypes, secondaryAlbumTypes, releaseStatuses, isInUse) => {
|
||||
(metadataProfile, isInUse) => {
|
||||
return {
|
||||
primaryAlbumTypes,
|
||||
secondaryAlbumTypes,
|
||||
releaseStatuses,
|
||||
...metadataProfile,
|
||||
isInUse
|
||||
};
|
||||
@@ -139,59 +63,16 @@ class EditMetadataProfileModalContentConnector extends Component {
|
||||
this.props.saveMetadataProfile({ id: this.props.id });
|
||||
}
|
||||
|
||||
onMetadataPrimaryTypeItemAllowedChange = (id, allowed) => {
|
||||
const metadataProfile = _.cloneDeep(this.props.item);
|
||||
|
||||
const item = _.find(metadataProfile.primaryAlbumTypes.value, (i) => i.albumType.id === id);
|
||||
item.allowed = allowed;
|
||||
|
||||
this.props.setMetadataProfileValue({
|
||||
name: 'primaryAlbumTypes',
|
||||
value: metadataProfile.primaryAlbumTypes.value
|
||||
});
|
||||
}
|
||||
|
||||
onMetadataSecondaryTypeItemAllowedChange = (id, allowed) => {
|
||||
const metadataProfile = _.cloneDeep(this.props.item);
|
||||
|
||||
const item = _.find(metadataProfile.secondaryAlbumTypes.value, (i) => i.albumType.id === id);
|
||||
item.allowed = allowed;
|
||||
|
||||
this.props.setMetadataProfileValue({
|
||||
name: 'secondaryAlbumTypes',
|
||||
value: metadataProfile.secondaryAlbumTypes.value
|
||||
});
|
||||
}
|
||||
|
||||
onMetadataReleaseStatusItemAllowedChange = (id, allowed) => {
|
||||
const metadataProfile = _.cloneDeep(this.props.item);
|
||||
|
||||
const item = _.find(metadataProfile.releaseStatuses.value, (i) => i.releaseStatus.id === id);
|
||||
item.allowed = allowed;
|
||||
|
||||
this.props.setMetadataProfileValue({
|
||||
name: 'releaseStatuses',
|
||||
value: metadataProfile.releaseStatuses.value
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
if (_.isEmpty(this.props.item.primaryAlbumTypes) && !this.props.isFetching) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<EditMetadataProfileModalContent
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
onSavePress={this.onSavePress}
|
||||
onInputChange={this.onInputChange}
|
||||
onMetadataPrimaryTypeItemAllowedChange={this.onMetadataPrimaryTypeItemAllowedChange}
|
||||
onMetadataSecondaryTypeItemAllowedChange={this.onMetadataSecondaryTypeItemAllowedChange}
|
||||
onMetadataReleaseStatusItemAllowedChange={this.onMetadataReleaseStatusItemAllowedChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import Card from 'Components/Card';
|
||||
import Label from 'Components/Label';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import EditMetadataProfileModalConnector from './EditMetadataProfileModalConnector';
|
||||
@@ -64,8 +63,6 @@ class MetadataProfile extends Component {
|
||||
const {
|
||||
id,
|
||||
name,
|
||||
primaryAlbumTypes,
|
||||
secondaryAlbumTypes,
|
||||
isDeleting
|
||||
} = this.props;
|
||||
|
||||
@@ -88,46 +85,6 @@ class MetadataProfile extends Component {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.albumTypes}>
|
||||
{
|
||||
primaryAlbumTypes.map((item) => {
|
||||
if (!item.allowed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Label
|
||||
key={item.albumType.id}
|
||||
kind={kinds.default}
|
||||
title={null}
|
||||
>
|
||||
{item.albumType.name}
|
||||
</Label>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className={styles.albumTypes}>
|
||||
{
|
||||
secondaryAlbumTypes.map((item) => {
|
||||
if (!item.allowed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Label
|
||||
key={item.albumType.id}
|
||||
kind={kinds.INFO}
|
||||
title={null}
|
||||
>
|
||||
{item.albumType.name}
|
||||
</Label>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
<EditMetadataProfileModalConnector
|
||||
id={id}
|
||||
isOpen={this.state.isEditMetadataProfileModalOpen}
|
||||
@@ -153,8 +110,6 @@ class MetadataProfile extends Component {
|
||||
MetadataProfile.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
primaryAlbumTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
secondaryAlbumTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
isDeleting: PropTypes.bool.isRequired,
|
||||
onConfirmDeleteMetadataProfile: PropTypes.func.isRequired,
|
||||
onCloneMetadataProfilePress: PropTypes.func.isRequired
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import CheckInput from 'Components/Form/CheckInput';
|
||||
import styles from './TypeItem.css';
|
||||
|
||||
class PrimaryTypeItem extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onAllowedChange = ({ value }) => {
|
||||
const {
|
||||
albumTypeId,
|
||||
onMetadataPrimaryTypeItemAllowedChange
|
||||
} = this.props;
|
||||
|
||||
onMetadataPrimaryTypeItemAllowedChange(albumTypeId, value);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
name,
|
||||
allowed
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
styles.metadataProfileItem
|
||||
)}
|
||||
>
|
||||
<label
|
||||
className={styles.albumTypeName}
|
||||
>
|
||||
<CheckInput
|
||||
containerClassName={styles.checkContainer}
|
||||
name={name}
|
||||
value={allowed}
|
||||
onChange={this.onAllowedChange}
|
||||
/>
|
||||
{name}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PrimaryTypeItem.propTypes = {
|
||||
albumTypeId: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
allowed: PropTypes.bool.isRequired,
|
||||
sortIndex: PropTypes.number.isRequired,
|
||||
onMetadataPrimaryTypeItemAllowedChange: PropTypes.func
|
||||
};
|
||||
|
||||
export default PrimaryTypeItem;
|
||||
@@ -1,87 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import FormInputHelpText from 'Components/Form/FormInputHelpText';
|
||||
import PrimaryTypeItem from './PrimaryTypeItem';
|
||||
import styles from './TypeItems.css';
|
||||
|
||||
class PrimaryTypeItems extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
metadataProfileItems,
|
||||
errors,
|
||||
warnings,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FormGroup>
|
||||
<FormLabel>Primary Types</FormLabel>
|
||||
<div>
|
||||
|
||||
{
|
||||
errors.map((error, index) => {
|
||||
return (
|
||||
<FormInputHelpText
|
||||
key={index}
|
||||
text={error.message}
|
||||
isError={true}
|
||||
isCheckInput={false}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
{
|
||||
warnings.map((warning, index) => {
|
||||
return (
|
||||
<FormInputHelpText
|
||||
key={index}
|
||||
text={warning.message}
|
||||
isWarning={true}
|
||||
isCheckInput={false}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
<div className={styles.albumTypes}>
|
||||
{
|
||||
metadataProfileItems.map(({ allowed, albumType }, index) => {
|
||||
return (
|
||||
<PrimaryTypeItem
|
||||
key={albumType.id}
|
||||
albumTypeId={albumType.id}
|
||||
name={albumType.name}
|
||||
allowed={allowed}
|
||||
sortIndex={index}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
}).reverse()
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PrimaryTypeItems.propTypes = {
|
||||
metadataProfileItems: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
errors: PropTypes.arrayOf(PropTypes.object),
|
||||
warnings: PropTypes.arrayOf(PropTypes.object),
|
||||
formLabel: PropTypes.string
|
||||
};
|
||||
|
||||
PrimaryTypeItems.defaultProps = {
|
||||
errors: [],
|
||||
warnings: []
|
||||
};
|
||||
|
||||
export default PrimaryTypeItems;
|
||||
@@ -1,60 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import CheckInput from 'Components/Form/CheckInput';
|
||||
import styles from './TypeItem.css';
|
||||
|
||||
class ReleaseStatusItem extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onAllowedChange = ({ value }) => {
|
||||
const {
|
||||
albumTypeId,
|
||||
onMetadataReleaseStatusItemAllowedChange
|
||||
} = this.props;
|
||||
|
||||
onMetadataReleaseStatusItemAllowedChange(albumTypeId, value);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
name,
|
||||
allowed
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
styles.metadataProfileItem
|
||||
)}
|
||||
>
|
||||
<label
|
||||
className={styles.albumTypeName}
|
||||
>
|
||||
<CheckInput
|
||||
containerClassName={styles.checkContainer}
|
||||
name={name}
|
||||
value={allowed}
|
||||
onChange={this.onAllowedChange}
|
||||
/>
|
||||
{name}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseStatusItem.propTypes = {
|
||||
albumTypeId: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
allowed: PropTypes.bool.isRequired,
|
||||
sortIndex: PropTypes.number.isRequired,
|
||||
onMetadataReleaseStatusItemAllowedChange: PropTypes.func
|
||||
};
|
||||
|
||||
export default ReleaseStatusItem;
|
||||
@@ -1,87 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import FormInputHelpText from 'Components/Form/FormInputHelpText';
|
||||
import ReleaseStatusItem from './ReleaseStatusItem';
|
||||
import styles from './TypeItems.css';
|
||||
|
||||
class ReleaseStatusItems extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
metadataProfileItems,
|
||||
errors,
|
||||
warnings,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FormGroup>
|
||||
<FormLabel>Release Statuses</FormLabel>
|
||||
<div>
|
||||
|
||||
{
|
||||
errors.map((error, index) => {
|
||||
return (
|
||||
<FormInputHelpText
|
||||
key={index}
|
||||
text={error.message}
|
||||
isError={true}
|
||||
isCheckInput={false}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
{
|
||||
warnings.map((warning, index) => {
|
||||
return (
|
||||
<FormInputHelpText
|
||||
key={index}
|
||||
text={warning.message}
|
||||
isWarning={true}
|
||||
isCheckInput={false}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
<div className={styles.albumTypes}>
|
||||
{
|
||||
metadataProfileItems.map(({ allowed, releaseStatus }, index) => {
|
||||
return (
|
||||
<ReleaseStatusItem
|
||||
key={releaseStatus.id}
|
||||
albumTypeId={releaseStatus.id}
|
||||
name={releaseStatus.name}
|
||||
allowed={allowed}
|
||||
sortIndex={index}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseStatusItems.propTypes = {
|
||||
metadataProfileItems: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
errors: PropTypes.arrayOf(PropTypes.object),
|
||||
warnings: PropTypes.arrayOf(PropTypes.object),
|
||||
formLabel: PropTypes.string
|
||||
};
|
||||
|
||||
ReleaseStatusItems.defaultProps = {
|
||||
errors: [],
|
||||
warnings: []
|
||||
};
|
||||
|
||||
export default ReleaseStatusItems;
|
||||
@@ -1,60 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import CheckInput from 'Components/Form/CheckInput';
|
||||
import styles from './TypeItem.css';
|
||||
|
||||
class SecondaryTypeItem extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onAllowedChange = ({ value }) => {
|
||||
const {
|
||||
albumTypeId,
|
||||
onMetadataSecondaryTypeItemAllowedChange
|
||||
} = this.props;
|
||||
|
||||
onMetadataSecondaryTypeItemAllowedChange(albumTypeId, value);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
name,
|
||||
allowed
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
styles.metadataProfileItem
|
||||
)}
|
||||
>
|
||||
<label
|
||||
className={styles.albumTypeName}
|
||||
>
|
||||
<CheckInput
|
||||
containerClassName={styles.checkContainer}
|
||||
name={name}
|
||||
value={allowed}
|
||||
onChange={this.onAllowedChange}
|
||||
/>
|
||||
{name}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SecondaryTypeItem.propTypes = {
|
||||
albumTypeId: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
allowed: PropTypes.bool.isRequired,
|
||||
sortIndex: PropTypes.number.isRequired,
|
||||
onMetadataSecondaryTypeItemAllowedChange: PropTypes.func
|
||||
};
|
||||
|
||||
export default SecondaryTypeItem;
|
||||
@@ -1,87 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import FormInputHelpText from 'Components/Form/FormInputHelpText';
|
||||
import SecondaryTypeItem from './SecondaryTypeItem';
|
||||
import styles from './TypeItems.css';
|
||||
|
||||
class SecondaryTypeItems extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
metadataProfileItems,
|
||||
errors,
|
||||
warnings,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FormGroup>
|
||||
<FormLabel>Secondary Types</FormLabel>
|
||||
<div>
|
||||
|
||||
{
|
||||
errors.map((error, index) => {
|
||||
return (
|
||||
<FormInputHelpText
|
||||
key={index}
|
||||
text={error.message}
|
||||
isError={true}
|
||||
isCheckInput={false}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
{
|
||||
warnings.map((warning, index) => {
|
||||
return (
|
||||
<FormInputHelpText
|
||||
key={index}
|
||||
text={warning.message}
|
||||
isWarning={true}
|
||||
isCheckInput={false}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
<div className={styles.albumTypes}>
|
||||
{
|
||||
metadataProfileItems.map(({ allowed, albumType }, index) => {
|
||||
return (
|
||||
<SecondaryTypeItem
|
||||
key={albumType.id}
|
||||
albumTypeId={albumType.id}
|
||||
name={albumType.name}
|
||||
allowed={allowed}
|
||||
sortIndex={index}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SecondaryTypeItems.propTypes = {
|
||||
metadataProfileItems: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
errors: PropTypes.arrayOf(PropTypes.object),
|
||||
warnings: PropTypes.arrayOf(PropTypes.object),
|
||||
formLabel: PropTypes.string
|
||||
};
|
||||
|
||||
SecondaryTypeItems.defaultProps = {
|
||||
errors: [],
|
||||
warnings: []
|
||||
};
|
||||
|
||||
export default SecondaryTypeItems;
|
||||
@@ -1,25 +0,0 @@
|
||||
.metadataProfileItem {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.checkContainer {
|
||||
position: relative;
|
||||
margin-right: 4px;
|
||||
margin-bottom: 7px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.albumTypeName {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
margin-bottom: 0;
|
||||
margin-left: 2px;
|
||||
font-weight: normal;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.isDragging {
|
||||
opacity: 0.25;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
.albumTypes {
|
||||
margin-top: 10px;
|
||||
/* TODO: This should consider the number of types in the list */
|
||||
min-height: 200px;
|
||||
user-select: none;
|
||||
}
|
||||
@@ -46,28 +46,12 @@ class QualityDefinition extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this._forceUpdateTimeout = null;
|
||||
|
||||
this.state = {
|
||||
sliderMinSize: getSliderValue(props.minSize, slider.min),
|
||||
sliderMaxSize: getSliderValue(props.maxSize, slider.max)
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// A hack to deal with a bug in the slider component until a fix for it
|
||||
// lands and an updated version is available.
|
||||
// See: https://github.com/mpowaga/react-slider/issues/115
|
||||
|
||||
this._forceUpdateTimeout = setTimeout(() => this.forceUpdate(), 1);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this._forceUpdateTimeout) {
|
||||
clearTimeout(this._forceUpdateTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
@@ -167,11 +151,11 @@ class QualityDefinition extends Component {
|
||||
step={slider.step}
|
||||
minDistance={10}
|
||||
value={[sliderMinSize, sliderMaxSize]}
|
||||
withBars={true}
|
||||
withTracks={true}
|
||||
snapDragDisabled={true}
|
||||
className={styles.slider}
|
||||
barClassName={styles.bar}
|
||||
handleClassName={styles.handle}
|
||||
trackClassName={styles.bar}
|
||||
thumbClassName={styles.handle}
|
||||
onChange={this.onSliderChange}
|
||||
onAfterChange={this.onAfterSliderChange}
|
||||
/>
|
||||
|
||||
@@ -11,7 +11,7 @@ function findMatchingItems(ids, items) {
|
||||
|
||||
function createMatchingArtistSelector() {
|
||||
return createSelector(
|
||||
(state, { artistIds }) => artistIds,
|
||||
(state, { authorIds }) => authorIds,
|
||||
createAllArtistSelector(),
|
||||
findMatchingItems
|
||||
);
|
||||
|
||||
@@ -56,7 +56,7 @@ class Tag extends Component {
|
||||
importListIds,
|
||||
notificationIds,
|
||||
restrictionIds,
|
||||
artistIds
|
||||
authorIds
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@@ -69,7 +69,7 @@ class Tag extends Component {
|
||||
importListIds.length ||
|
||||
notificationIds.length ||
|
||||
restrictionIds.length ||
|
||||
artistIds.length
|
||||
authorIds.length
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -86,9 +86,9 @@ class Tag extends Component {
|
||||
isTagUsed &&
|
||||
<div>
|
||||
{
|
||||
!!artistIds.length &&
|
||||
!!authorIds.length &&
|
||||
<div>
|
||||
{artistIds.length} artists
|
||||
{authorIds.length} artists
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ class Tag extends Component {
|
||||
<TagDetailsModal
|
||||
label={label}
|
||||
isTagUsed={isTagUsed}
|
||||
artistIds={artistIds}
|
||||
authorIds={authorIds}
|
||||
delayProfileIds={delayProfileIds}
|
||||
importListIds={importListIds}
|
||||
notificationIds={notificationIds}
|
||||
@@ -163,7 +163,7 @@ Tag.propTypes = {
|
||||
importListIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
notificationIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
restrictionIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
artistIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
authorIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
onConfirmDeleteTag: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
@@ -172,7 +172,7 @@ Tag.defaultProps = {
|
||||
importListIds: [],
|
||||
notificationIds: [],
|
||||
restrictionIds: [],
|
||||
artistIds: []
|
||||
authorIds: []
|
||||
};
|
||||
|
||||
export default Tag;
|
||||
|
||||
Reference in New Issue
Block a user