mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-06 13:02:23 -07:00
Fixed: Manual Import Reprocessing
This commit is contained in:
parent
9e1009bc85
commit
84a758064c
20 changed files with 424 additions and 26 deletions
|
@ -70,7 +70,7 @@ class SelectAlbumModalContentConnector extends Component {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.props.saveInteractiveImportItem({ id: ids });
|
this.props.saveInteractiveImportItem({ ids });
|
||||||
|
|
||||||
this.props.onModalClose(true);
|
this.props.onModalClose(true);
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,7 +37,7 @@ class SelectAlbumReleaseModalContentConnector extends Component {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.props.saveInteractiveImportItem({ id: ids });
|
this.props.saveInteractiveImportItem({ ids });
|
||||||
|
|
||||||
this.props.onModalClose(true);
|
this.props.onModalClose(true);
|
||||||
};
|
};
|
||||||
|
|
|
@ -54,7 +54,7 @@ class SelectArtistModalContentConnector extends Component {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.props.saveInteractiveImportItem({ id: ids });
|
this.props.saveInteractiveImportItem({ ids });
|
||||||
|
|
||||||
this.props.onModalClose(true);
|
this.props.onModalClose(true);
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@ import SelectAlbumReleaseModal from 'InteractiveImport/AlbumRelease/SelectAlbumR
|
||||||
import SelectArtistModal from 'InteractiveImport/Artist/SelectArtistModal';
|
import SelectArtistModal from 'InteractiveImport/Artist/SelectArtistModal';
|
||||||
import ConfirmImportModal from 'InteractiveImport/Confirmation/ConfirmImportModal';
|
import ConfirmImportModal from 'InteractiveImport/Confirmation/ConfirmImportModal';
|
||||||
import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal';
|
import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal';
|
||||||
|
import SelectReleaseGroupModal from 'InteractiveImport/ReleaseGroup/SelectReleaseGroupModal';
|
||||||
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
||||||
|
@ -52,6 +53,11 @@ const columns = [
|
||||||
label: translate('Tracks'),
|
label: translate('Tracks'),
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'releaseGroup',
|
||||||
|
label: translate('ReleaseGroup'),
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'quality',
|
name: 'quality',
|
||||||
label: translate('Quality'),
|
label: translate('Quality'),
|
||||||
|
@ -81,6 +87,7 @@ const filterExistingFilesOptions = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const importModeOptions = [
|
const importModeOptions = [
|
||||||
|
{ key: 'chooseImportMode', value: translate('ChooseImportMethod'), disabled: true },
|
||||||
{ key: 'move', value: translate('MoveFiles') },
|
{ key: 'move', value: translate('MoveFiles') },
|
||||||
{ key: 'copy', value: translate('HardlinkCopyFiles') }
|
{ key: 'copy', value: translate('HardlinkCopyFiles') }
|
||||||
];
|
];
|
||||||
|
@ -89,6 +96,7 @@ const SELECT = 'select';
|
||||||
const ARTIST = 'artist';
|
const ARTIST = 'artist';
|
||||||
const ALBUM = 'album';
|
const ALBUM = 'album';
|
||||||
const ALBUM_RELEASE = 'albumRelease';
|
const ALBUM_RELEASE = 'albumRelease';
|
||||||
|
const RELEASE_GROUP = 'releaseGroup';
|
||||||
const QUALITY = 'quality';
|
const QUALITY = 'quality';
|
||||||
|
|
||||||
const replaceExistingFilesOptions = {
|
const replaceExistingFilesOptions = {
|
||||||
|
@ -292,7 +300,8 @@ class InteractiveImportModalContent extends Component {
|
||||||
{ key: SELECT, value: translate('Select...'), disabled: true },
|
{ key: SELECT, value: translate('Select...'), disabled: true },
|
||||||
{ key: ALBUM, value: translate('SelectAlbum') },
|
{ key: ALBUM, value: translate('SelectAlbum') },
|
||||||
{ key: ALBUM_RELEASE, value: translate('SelectAlbumRelease') },
|
{ key: ALBUM_RELEASE, value: translate('SelectAlbumRelease') },
|
||||||
{ key: QUALITY, value: translate('SelectQuality') }
|
{ key: QUALITY, value: translate('SelectQuality') },
|
||||||
|
{ key: RELEASE_GROUP, value: translate('SelectReleaseGroup') }
|
||||||
];
|
];
|
||||||
|
|
||||||
if (allowArtistChange) {
|
if (allowArtistChange) {
|
||||||
|
@ -513,6 +522,13 @@ class InteractiveImportModalContent extends Component {
|
||||||
onModalClose={this.onSelectModalClose}
|
onModalClose={this.onSelectModalClose}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<SelectReleaseGroupModal
|
||||||
|
isOpen={selectModalOpen === RELEASE_GROUP}
|
||||||
|
ids={selectedIds}
|
||||||
|
releaseGroup=""
|
||||||
|
onModalClose={this.onSelectModalClose}
|
||||||
|
/>
|
||||||
|
|
||||||
<SelectQualityModal
|
<SelectQualityModal
|
||||||
isOpen={selectModalOpen === QUALITY}
|
isOpen={selectModalOpen === QUALITY}
|
||||||
ids={selectedIds}
|
ids={selectedIds}
|
||||||
|
|
|
@ -120,6 +120,11 @@ class InteractiveImportModalContentConnector extends Component {
|
||||||
onImportSelectedPress = (selected, importMode) => {
|
onImportSelectedPress = (selected, importMode) => {
|
||||||
const files = [];
|
const files = [];
|
||||||
|
|
||||||
|
if (importMode === 'chooseImportMethod') {
|
||||||
|
this.setState({ interactiveImportErrorMessage: 'An import mode must be selected' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_.forEach(this.props.items, (item) => {
|
_.forEach(this.props.items, (item) => {
|
||||||
const isSelected = selected.indexOf(item.id) > -1;
|
const isSelected = selected.indexOf(item.id) > -1;
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading {
|
.reprocessing {
|
||||||
composes: loading from '~Components/Loading/LoadingIndicator.css';
|
composes: loading from '~Components/Loading/LoadingIndicator.css';
|
||||||
|
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
text-align: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.additionalFile {
|
.additionalFile {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { icons, kinds, sortDirections, tooltipPositions } from 'Helpers/Props';
|
||||||
import SelectAlbumModal from 'InteractiveImport/Album/SelectAlbumModal';
|
import SelectAlbumModal from 'InteractiveImport/Album/SelectAlbumModal';
|
||||||
import SelectArtistModal from 'InteractiveImport/Artist/SelectArtistModal';
|
import SelectArtistModal from 'InteractiveImport/Artist/SelectArtistModal';
|
||||||
import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal';
|
import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal';
|
||||||
|
import SelectReleaseGroupModal from 'InteractiveImport/ReleaseGroup/SelectReleaseGroupModal';
|
||||||
import SelectTrackModal from 'InteractiveImport/Track/SelectTrackModal';
|
import SelectTrackModal from 'InteractiveImport/Track/SelectTrackModal';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
|
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
|
||||||
|
@ -32,6 +33,7 @@ class InteractiveImportRow extends Component {
|
||||||
isSelectArtistModalOpen: false,
|
isSelectArtistModalOpen: false,
|
||||||
isSelectAlbumModalOpen: false,
|
isSelectAlbumModalOpen: false,
|
||||||
isSelectTrackModalOpen: false,
|
isSelectTrackModalOpen: false,
|
||||||
|
isSelectReleaseGroupModalOpen: false,
|
||||||
isSelectQualityModalOpen: false
|
isSelectQualityModalOpen: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -119,6 +121,10 @@ class InteractiveImportRow extends Component {
|
||||||
this.setState({ isSelectTrackModalOpen: true });
|
this.setState({ isSelectTrackModalOpen: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onSelectReleaseGroupPress = () => {
|
||||||
|
this.setState({ isSelectReleaseGroupModalOpen: true });
|
||||||
|
};
|
||||||
|
|
||||||
onSelectQualityPress = () => {
|
onSelectQualityPress = () => {
|
||||||
this.setState({ isSelectQualityModalOpen: true });
|
this.setState({ isSelectQualityModalOpen: true });
|
||||||
};
|
};
|
||||||
|
@ -138,6 +144,11 @@ class InteractiveImportRow extends Component {
|
||||||
this.selectRowAfterChange(changed);
|
this.selectRowAfterChange(changed);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onSelectReleaseGroupModalClose = (changed) => {
|
||||||
|
this.setState({ isSelectReleaseGroupModalOpen: false });
|
||||||
|
this.selectRowAfterChange(changed);
|
||||||
|
};
|
||||||
|
|
||||||
onSelectQualityModalClose = (changed) => {
|
onSelectQualityModalClose = (changed) => {
|
||||||
this.setState({ isSelectQualityModalOpen: false });
|
this.setState({ isSelectQualityModalOpen: false });
|
||||||
this.selectRowAfterChange(changed);
|
this.selectRowAfterChange(changed);
|
||||||
|
@ -156,12 +167,13 @@ class InteractiveImportRow extends Component {
|
||||||
albumReleaseId,
|
albumReleaseId,
|
||||||
tracks,
|
tracks,
|
||||||
quality,
|
quality,
|
||||||
|
releaseGroup,
|
||||||
size,
|
size,
|
||||||
rejections,
|
rejections,
|
||||||
|
isReprocessing,
|
||||||
audioTags,
|
audioTags,
|
||||||
additionalFile,
|
additionalFile,
|
||||||
isSelected,
|
isSelected,
|
||||||
isSaving,
|
|
||||||
onSelectedChange
|
onSelectedChange
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -169,6 +181,7 @@ class InteractiveImportRow extends Component {
|
||||||
isSelectArtistModalOpen,
|
isSelectArtistModalOpen,
|
||||||
isSelectAlbumModalOpen,
|
isSelectAlbumModalOpen,
|
||||||
isSelectTrackModalOpen,
|
isSelectTrackModalOpen,
|
||||||
|
isSelectReleaseGroupModalOpen,
|
||||||
isSelectQualityModalOpen
|
isSelectQualityModalOpen
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
|
@ -185,8 +198,9 @@ class InteractiveImportRow extends Component {
|
||||||
|
|
||||||
const showArtistPlaceholder = isSelected && !artist;
|
const showArtistPlaceholder = isSelected && !artist;
|
||||||
const showAlbumNumberPlaceholder = isSelected && !!artist && !album;
|
const showAlbumNumberPlaceholder = isSelected && !!artist && !album;
|
||||||
const showTrackNumbersPlaceholder = !isSaving && isSelected && !!album && !tracks.length;
|
const showTrackNumbersPlaceholder = !isReprocessing && isSelected && !!album && !tracks.length;
|
||||||
const showTrackNumbersLoading = isSaving && !tracks.length;
|
const showTrackNumbersLoading = isReprocessing && !tracks.length;
|
||||||
|
const showReleaseGroupPlaceholder = isSelected && !releaseGroup;
|
||||||
const showQualityPlaceholder = isSelected && !quality;
|
const showQualityPlaceholder = isSelected && !quality;
|
||||||
|
|
||||||
const pathCellContents = (
|
const pathCellContents = (
|
||||||
|
@ -253,6 +267,17 @@ class InteractiveImportRow extends Component {
|
||||||
}
|
}
|
||||||
</TableRowCellButton>
|
</TableRowCellButton>
|
||||||
|
|
||||||
|
<TableRowCellButton
|
||||||
|
title={translate('ClickToChangeReleaseGroup')}
|
||||||
|
onPress={this.onSelectReleaseGroupPress}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
showReleaseGroupPlaceholder ?
|
||||||
|
<InteractiveImportRowCellPlaceholder /> :
|
||||||
|
releaseGroup
|
||||||
|
}
|
||||||
|
</TableRowCellButton>
|
||||||
|
|
||||||
<TableRowCellButton
|
<TableRowCellButton
|
||||||
className={styles.quality}
|
className={styles.quality}
|
||||||
title={translate('ClickToChangeQuality')}
|
title={translate('ClickToChangeQuality')}
|
||||||
|
@ -301,6 +326,7 @@ class InteractiveImportRow extends Component {
|
||||||
</ul>
|
</ul>
|
||||||
}
|
}
|
||||||
position={tooltipPositions.LEFT}
|
position={tooltipPositions.LEFT}
|
||||||
|
canFlip={false}
|
||||||
/> :
|
/> :
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -333,6 +359,13 @@ class InteractiveImportRow extends Component {
|
||||||
onModalClose={this.onSelectTrackModalClose}
|
onModalClose={this.onSelectTrackModalClose}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<SelectReleaseGroupModal
|
||||||
|
isOpen={isSelectReleaseGroupModalOpen}
|
||||||
|
ids={[id]}
|
||||||
|
releaseGroup={releaseGroup ?? ''}
|
||||||
|
onModalClose={this.onSelectReleaseGroupModalClose}
|
||||||
|
/>
|
||||||
|
|
||||||
<SelectQualityModal
|
<SelectQualityModal
|
||||||
isOpen={isSelectQualityModalOpen}
|
isOpen={isSelectQualityModalOpen}
|
||||||
ids={[id]}
|
ids={[id]}
|
||||||
|
@ -355,13 +388,14 @@ InteractiveImportRow.propTypes = {
|
||||||
album: PropTypes.object,
|
album: PropTypes.object,
|
||||||
albumReleaseId: PropTypes.number,
|
albumReleaseId: PropTypes.number,
|
||||||
tracks: PropTypes.arrayOf(PropTypes.object).isRequired,
|
tracks: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
releaseGroup: PropTypes.string,
|
||||||
quality: PropTypes.object,
|
quality: PropTypes.object,
|
||||||
size: PropTypes.number.isRequired,
|
size: PropTypes.number.isRequired,
|
||||||
rejections: PropTypes.arrayOf(PropTypes.object).isRequired,
|
rejections: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
audioTags: PropTypes.object.isRequired,
|
audioTags: PropTypes.object.isRequired,
|
||||||
additionalFile: PropTypes.bool.isRequired,
|
additionalFile: PropTypes.bool.isRequired,
|
||||||
|
isReprocessing: PropTypes.bool,
|
||||||
isSelected: PropTypes.bool,
|
isSelected: PropTypes.bool,
|
||||||
isSaving: PropTypes.bool.isRequired,
|
|
||||||
onSelectedChange: PropTypes.func.isRequired,
|
onSelectedChange: PropTypes.func.isRequired,
|
||||||
onValidRowChange: PropTypes.func.isRequired
|
onValidRowChange: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import Modal from 'Components/Modal/Modal';
|
import Modal from 'Components/Modal/Modal';
|
||||||
|
import { sizes } from 'Helpers/Props';
|
||||||
import InteractiveImportSelectFolderModalContentConnector from './Folder/InteractiveImportSelectFolderModalContentConnector';
|
import InteractiveImportSelectFolderModalContentConnector from './Folder/InteractiveImportSelectFolderModalContentConnector';
|
||||||
import InteractiveImportModalContentConnector from './Interactive/InteractiveImportModalContentConnector';
|
import InteractiveImportModalContentConnector from './Interactive/InteractiveImportModalContentConnector';
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ class InteractiveImportModal extends Component {
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
|
size={sizes.EXTRA_LARGE}
|
||||||
closeOnBackgroundClick={false}
|
closeOnBackgroundClick={false}
|
||||||
onModalClose={onModalClose}
|
onModalClose={onModalClose}
|
||||||
>
|
>
|
||||||
|
@ -73,7 +75,12 @@ InteractiveImportModal.propTypes = {
|
||||||
isOpen: PropTypes.bool.isRequired,
|
isOpen: PropTypes.bool.isRequired,
|
||||||
folder: PropTypes.string,
|
folder: PropTypes.string,
|
||||||
downloadId: PropTypes.string,
|
downloadId: PropTypes.string,
|
||||||
|
modalTitle: PropTypes.string.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
InteractiveImportModal.defaultProps = {
|
||||||
|
modalTitle: 'Manual Import'
|
||||||
|
};
|
||||||
|
|
||||||
export default InteractiveImportModal;
|
export default InteractiveImportModal;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { updateInteractiveImportItems } from 'Store/Actions/interactiveImportActions';
|
import { saveInteractiveImportItem, updateInteractiveImportItems } from 'Store/Actions/interactiveImportActions';
|
||||||
import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions';
|
import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions';
|
||||||
import getQualities from 'Utilities/Quality/getQualities';
|
import getQualities from 'Utilities/Quality/getQualities';
|
||||||
import SelectQualityModalContent from './SelectQualityModalContent';
|
import SelectQualityModalContent from './SelectQualityModalContent';
|
||||||
|
@ -31,7 +31,8 @@ function createMapStateToProps() {
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
dispatchFetchQualityProfileSchema: fetchQualityProfileSchema,
|
dispatchFetchQualityProfileSchema: fetchQualityProfileSchema,
|
||||||
dispatchUpdateInteractiveImportItems: updateInteractiveImportItems
|
dispatchUpdateInteractiveImportItems: updateInteractiveImportItems,
|
||||||
|
dispatchSaveInteractiveImportItems: saveInteractiveImportItem
|
||||||
};
|
};
|
||||||
|
|
||||||
class SelectQualityModalContentConnector extends Component {
|
class SelectQualityModalContentConnector extends Component {
|
||||||
|
@ -49,6 +50,12 @@ class SelectQualityModalContentConnector extends Component {
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onQualitySelect = ({ qualityId, proper, real }) => {
|
onQualitySelect = ({ qualityId, proper, real }) => {
|
||||||
|
const {
|
||||||
|
ids,
|
||||||
|
dispatchUpdateInteractiveImportItems,
|
||||||
|
dispatchSaveInteractiveImportItems
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
const quality = _.find(this.props.items,
|
const quality = _.find(this.props.items,
|
||||||
(item) => item.id === qualityId);
|
(item) => item.id === qualityId);
|
||||||
|
|
||||||
|
@ -57,14 +64,16 @@ class SelectQualityModalContentConnector extends Component {
|
||||||
real: real ? 1 : 0
|
real: real ? 1 : 0
|
||||||
};
|
};
|
||||||
|
|
||||||
this.props.dispatchUpdateInteractiveImportItems({
|
dispatchUpdateInteractiveImportItems({
|
||||||
ids: this.props.ids,
|
ids,
|
||||||
quality: {
|
quality: {
|
||||||
quality,
|
quality,
|
||||||
revision
|
revision
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dispatchSaveInteractiveImportItems({ ids });
|
||||||
|
|
||||||
this.props.onModalClose(true);
|
this.props.onModalClose(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,6 +98,7 @@ SelectQualityModalContentConnector.propTypes = {
|
||||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
dispatchFetchQualityProfileSchema: PropTypes.func.isRequired,
|
dispatchFetchQualityProfileSchema: PropTypes.func.isRequired,
|
||||||
dispatchUpdateInteractiveImportItems: PropTypes.func.isRequired,
|
dispatchUpdateInteractiveImportItems: PropTypes.func.isRequired,
|
||||||
|
dispatchSaveInteractiveImportItems: PropTypes.func.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import Modal from 'Components/Modal/Modal';
|
||||||
|
import SelectReleaseGroupModalContentConnector from './SelectReleaseGroupModalContentConnector';
|
||||||
|
|
||||||
|
class SelectReleaseGroupModal extends Component {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
isOpen,
|
||||||
|
onModalClose,
|
||||||
|
...otherProps
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onModalClose={onModalClose}
|
||||||
|
>
|
||||||
|
<SelectReleaseGroupModalContentConnector
|
||||||
|
{...otherProps}
|
||||||
|
onModalClose={onModalClose}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectReleaseGroupModal.propTypes = {
|
||||||
|
isOpen: PropTypes.bool.isRequired,
|
||||||
|
onModalClose: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelectReleaseGroupModal;
|
|
@ -0,0 +1,7 @@
|
||||||
|
.modalBody {
|
||||||
|
composes: modalBody from '~Components/Modal/ModalBody.css';
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import Form from 'Components/Form/Form';
|
||||||
|
import FormGroup from 'Components/Form/FormGroup';
|
||||||
|
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||||
|
import FormLabel from 'Components/Form/FormLabel';
|
||||||
|
import Button from 'Components/Link/Button';
|
||||||
|
import ModalBody from 'Components/Modal/ModalBody';
|
||||||
|
import ModalContent from 'Components/Modal/ModalContent';
|
||||||
|
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||||
|
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||||
|
import { inputTypes, kinds, scrollDirections } from 'Helpers/Props';
|
||||||
|
import styles from './SelectReleaseGroupModalContent.css';
|
||||||
|
|
||||||
|
class SelectReleaseGroupModalContent extends Component {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Lifecycle
|
||||||
|
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props, context);
|
||||||
|
|
||||||
|
const {
|
||||||
|
releaseGroup
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
releaseGroup
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Listeners
|
||||||
|
|
||||||
|
onReleaseGroupChange = ({ value }) => {
|
||||||
|
this.setState({ releaseGroup: value });
|
||||||
|
};
|
||||||
|
|
||||||
|
onReleaseGroupSelect = () => {
|
||||||
|
this.props.onReleaseGroupSelect(this.state);
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
onModalClose
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const {
|
||||||
|
releaseGroup
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalContent onModalClose={onModalClose}>
|
||||||
|
<ModalHeader>
|
||||||
|
Manual Import - Set Release Group
|
||||||
|
</ModalHeader>
|
||||||
|
|
||||||
|
<ModalBody
|
||||||
|
className={styles.modalBody}
|
||||||
|
scrollDirection={scrollDirections.NONE}
|
||||||
|
>
|
||||||
|
<Form>
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>Release Group</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.TEXT}
|
||||||
|
name="releaseGroup"
|
||||||
|
value={releaseGroup}
|
||||||
|
autoFocus={true}
|
||||||
|
onChange={this.onReleaseGroupChange}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
</ModalBody>
|
||||||
|
|
||||||
|
<ModalFooter>
|
||||||
|
<Button onPress={onModalClose}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
kind={kinds.SUCCESS}
|
||||||
|
onPress={this.onReleaseGroupSelect}
|
||||||
|
>
|
||||||
|
Set Release Group
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectReleaseGroupModalContent.propTypes = {
|
||||||
|
releaseGroup: PropTypes.string.isRequired,
|
||||||
|
onReleaseGroupSelect: PropTypes.func.isRequired,
|
||||||
|
onModalClose: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelectReleaseGroupModalContent;
|
|
@ -0,0 +1,54 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { saveInteractiveImportItem, updateInteractiveImportItems } from 'Store/Actions/interactiveImportActions';
|
||||||
|
import SelectReleaseGroupModalContent from './SelectReleaseGroupModalContent';
|
||||||
|
|
||||||
|
const mapDispatchToProps = {
|
||||||
|
dispatchUpdateInteractiveImportItems: updateInteractiveImportItems,
|
||||||
|
dispatchSaveInteractiveImportItems: saveInteractiveImportItem
|
||||||
|
};
|
||||||
|
|
||||||
|
class SelectReleaseGroupModalContentConnector extends Component {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Listeners
|
||||||
|
|
||||||
|
onReleaseGroupSelect = ({ releaseGroup }) => {
|
||||||
|
const {
|
||||||
|
ids,
|
||||||
|
dispatchUpdateInteractiveImportItems,
|
||||||
|
dispatchSaveInteractiveImportItems
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
dispatchUpdateInteractiveImportItems({
|
||||||
|
ids,
|
||||||
|
releaseGroup
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatchSaveInteractiveImportItems({ ids });
|
||||||
|
|
||||||
|
this.props.onModalClose(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<SelectReleaseGroupModalContent
|
||||||
|
{...this.props}
|
||||||
|
onReleaseGroupSelect={this.onReleaseGroupSelect}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectReleaseGroupModalContentConnector.propTypes = {
|
||||||
|
ids: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||||
|
dispatchUpdateInteractiveImportItems: PropTypes.func.isRequired,
|
||||||
|
dispatchSaveInteractiveImportItems: PropTypes.func.isRequired,
|
||||||
|
onModalClose: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(SelectReleaseGroupModalContentConnector);
|
|
@ -5,10 +5,9 @@ import { sortDirections } from 'Helpers/Props';
|
||||||
import { createThunk, handleThunks } from 'Store/thunks';
|
import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||||
import updateSectionState from 'Utilities/State/updateSectionState';
|
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||||
import { set, update } from './baseActions';
|
import { set, update, updateItem } from './baseActions';
|
||||||
import createFetchHandler from './Creators/createFetchHandler';
|
import createFetchHandler from './Creators/createFetchHandler';
|
||||||
import createHandleActions from './Creators/createHandleActions';
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
import createSaveProviderHandler from './Creators/createSaveProviderHandler';
|
|
||||||
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
|
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -18,6 +17,8 @@ export const section = 'interactiveImport';
|
||||||
|
|
||||||
const albumsSection = `${section}.albums`;
|
const albumsSection = `${section}.albums`;
|
||||||
const trackFilesSection = `${section}.trackFiles`;
|
const trackFilesSection = `${section}.trackFiles`;
|
||||||
|
let abortCurrentRequest = null;
|
||||||
|
let currentIds = [];
|
||||||
|
|
||||||
const MAXIMUM_RECENT_FOLDERS = 10;
|
const MAXIMUM_RECENT_FOLDERS = 10;
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ export const defaultState = {
|
||||||
sortKey: 'path',
|
sortKey: 'path',
|
||||||
sortDirection: sortDirections.ASCENDING,
|
sortDirection: sortDirections.ASCENDING,
|
||||||
recentFolders: [],
|
recentFolders: [],
|
||||||
importMode: 'move',
|
importMode: 'chooseImportMode',
|
||||||
sortPredicates: {
|
sortPredicates: {
|
||||||
path: function(item, direction) {
|
path: function(item, direction) {
|
||||||
const path = item.path;
|
const path = item.path;
|
||||||
|
@ -156,7 +157,83 @@ export const actionHandlers = handleThunks({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
[SAVE_INTERACTIVE_IMPORT_ITEM]: createSaveProviderHandler(section, '/manualimport', {}, true),
|
[SAVE_INTERACTIVE_IMPORT_ITEM]: function(getState, payload, dispatch) {
|
||||||
|
if (abortCurrentRequest) {
|
||||||
|
abortCurrentRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(batchActions([
|
||||||
|
...currentIds.map((id) => updateItem({
|
||||||
|
section,
|
||||||
|
id,
|
||||||
|
isReprocessing: false,
|
||||||
|
updateOnly: true
|
||||||
|
})),
|
||||||
|
...payload.ids.map((id) => updateItem({
|
||||||
|
section,
|
||||||
|
id,
|
||||||
|
isReprocessing: true,
|
||||||
|
updateOnly: true
|
||||||
|
}))
|
||||||
|
]));
|
||||||
|
|
||||||
|
const items = getState()[section].items;
|
||||||
|
|
||||||
|
const requestPayload = payload.ids.map((id) => {
|
||||||
|
const item = items.find((i) => i.id === id);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
path: item.path,
|
||||||
|
artistId: item.artist ? item.artist.id : undefined,
|
||||||
|
albumId: item.album ? item.album.id : undefined,
|
||||||
|
albumReleaseId: item.albumReleaseId ? item.albumReleaseId : undefined,
|
||||||
|
trackIds: (item.tracks || []).map((e) => e.id),
|
||||||
|
quality: item.quality,
|
||||||
|
releaseGroup: item.releaseGroup,
|
||||||
|
downloadId: item.downloadId,
|
||||||
|
additionalFile: item.additionalFile,
|
||||||
|
replaceExistingFiles: item.replaceExistingFiles,
|
||||||
|
disableReleaseSwitching: item.disableReleaseSwitching
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const { request, abortRequest } = createAjaxRequest({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/manualimport',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify(requestPayload)
|
||||||
|
});
|
||||||
|
|
||||||
|
abortCurrentRequest = abortRequest;
|
||||||
|
currentIds = payload.ids;
|
||||||
|
|
||||||
|
request.done((data) => {
|
||||||
|
dispatch(batchActions(
|
||||||
|
data.map((item) => updateItem({
|
||||||
|
section,
|
||||||
|
...item,
|
||||||
|
isReprocessing: false,
|
||||||
|
updateOnly: true
|
||||||
|
}))
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
request.fail((xhr) => {
|
||||||
|
if (xhr.aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(batchActions(
|
||||||
|
payload.ids.map((id) => updateItem({
|
||||||
|
section,
|
||||||
|
id,
|
||||||
|
isReprocessing: false,
|
||||||
|
updateOnly: true
|
||||||
|
}))
|
||||||
|
));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
[FETCH_INTERACTIVE_IMPORT_ALBUMS]: createFetchHandler(albumsSection, '/album'),
|
[FETCH_INTERACTIVE_IMPORT_ALBUMS]: createFetchHandler(albumsSection, '/album'),
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ namespace Lidarr.Api.V1.ManualImport
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut]
|
[HttpPost]
|
||||||
public IActionResult UpdateItems(List<ManualImportResource> resource)
|
public IActionResult UpdateItems(List<ManualImportUpdateResource> resource)
|
||||||
{
|
{
|
||||||
return Accepted(UpdateImportItems(resource));
|
return Accepted(UpdateImportItems(resource));
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ namespace Lidarr.Api.V1.ManualImport
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ManualImportResource> UpdateImportItems(List<ManualImportResource> resources)
|
private List<ManualImportResource> UpdateImportItems(List<ManualImportUpdateResource> resources)
|
||||||
{
|
{
|
||||||
var items = new List<ManualImportItem>();
|
var items = new List<ManualImportItem>();
|
||||||
foreach (var resource in resources)
|
foreach (var resource in resources)
|
||||||
|
@ -75,11 +75,11 @@ namespace Lidarr.Api.V1.ManualImport
|
||||||
Id = resource.Id,
|
Id = resource.Id,
|
||||||
Path = resource.Path,
|
Path = resource.Path,
|
||||||
Name = resource.Name,
|
Name = resource.Name,
|
||||||
Size = resource.Size,
|
Artist = resource.ArtistId.HasValue ? _artistService.GetArtist(resource.ArtistId.Value) : null,
|
||||||
Artist = resource.Artist == null ? null : _artistService.GetArtist(resource.Artist.Id),
|
Album = resource.AlbumId.HasValue ? _albumService.GetAlbum(resource.AlbumId.Value) : null,
|
||||||
Album = resource.Album == null ? null : _albumService.GetAlbum(resource.Album.Id),
|
Release = resource.AlbumReleaseId.HasValue ? _releaseService.GetRelease(resource.AlbumReleaseId.Value) : null,
|
||||||
Release = resource.AlbumReleaseId == 0 ? null : _releaseService.GetRelease(resource.AlbumReleaseId),
|
|
||||||
Quality = resource.Quality,
|
Quality = resource.Quality,
|
||||||
|
ReleaseGroup = resource.ReleaseGroup,
|
||||||
DownloadId = resource.DownloadId,
|
DownloadId = resource.DownloadId,
|
||||||
AdditionalFile = resource.AdditionalFile,
|
AdditionalFile = resource.AdditionalFile,
|
||||||
ReplaceExistingFiles = resource.ReplaceExistingFiles,
|
ReplaceExistingFiles = resource.ReplaceExistingFiles,
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace Lidarr.Api.V1.ManualImport
|
||||||
public int AlbumReleaseId { get; set; }
|
public int AlbumReleaseId { get; set; }
|
||||||
public List<TrackResource> Tracks { get; set; }
|
public List<TrackResource> Tracks { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
|
public string ReleaseGroup { get; set; }
|
||||||
public int QualityWeight { get; set; }
|
public int QualityWeight { get; set; }
|
||||||
public string DownloadId { get; set; }
|
public string DownloadId { get; set; }
|
||||||
public IEnumerable<Rejection> Rejections { get; set; }
|
public IEnumerable<Rejection> Rejections { get; set; }
|
||||||
|
@ -50,6 +51,7 @@ namespace Lidarr.Api.V1.ManualImport
|
||||||
AlbumReleaseId = model.Release?.Id ?? 0,
|
AlbumReleaseId = model.Release?.Id ?? 0,
|
||||||
Tracks = model.Tracks.ToResource(),
|
Tracks = model.Tracks.ToResource(),
|
||||||
Quality = model.Quality,
|
Quality = model.Quality,
|
||||||
|
ReleaseGroup = model.ReleaseGroup,
|
||||||
|
|
||||||
// QualityWeight
|
// QualityWeight
|
||||||
DownloadId = model.DownloadId,
|
DownloadId = model.DownloadId,
|
||||||
|
|
29
src/Lidarr.Api.V1/ManualImport/ManualImportUpdateResource.cs
Normal file
29
src/Lidarr.Api.V1/ManualImport/ManualImportUpdateResource.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Lidarr.Api.V1.Albums;
|
||||||
|
using Lidarr.Api.V1.Tracks;
|
||||||
|
using Lidarr.Http.REST;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
|
namespace Lidarr.Api.V1.ManualImport
|
||||||
|
{
|
||||||
|
public class ManualImportUpdateResource : RestResource
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int? ArtistId { get; set; }
|
||||||
|
public int? AlbumId { get; set; }
|
||||||
|
public int? AlbumReleaseId { get; set; }
|
||||||
|
public List<TrackResource> Tracks { get; set; }
|
||||||
|
public List<int> TrackIds { get; set; }
|
||||||
|
public QualityModel Quality { get; set; }
|
||||||
|
public string ReleaseGroup { get; set; }
|
||||||
|
public string DownloadId { get; set; }
|
||||||
|
public bool AdditionalFile { get; set; }
|
||||||
|
public bool ReplaceExistingFiles { get; set; }
|
||||||
|
public bool DisableReleaseSwitching { get; set; }
|
||||||
|
|
||||||
|
public IEnumerable<Rejection> Rejections { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -119,11 +119,13 @@
|
||||||
"ChmodFolder": "chmod Folder",
|
"ChmodFolder": "chmod Folder",
|
||||||
"ChmodFolderHelpText": "Octal, applied during import/rename to media folders and files (without execute bits)",
|
"ChmodFolderHelpText": "Octal, applied during import/rename to media folders and files (without execute bits)",
|
||||||
"ChmodFolderHelpTextWarning": "This only works if the user running Lidarr is the owner of the file. It's better to ensure the download client sets the permissions properly.",
|
"ChmodFolderHelpTextWarning": "This only works if the user running Lidarr is the owner of the file. It's better to ensure the download client sets the permissions properly.",
|
||||||
|
"ChooseImportMethod": "Choose Import Method",
|
||||||
"ChownGroup": "chown Group",
|
"ChownGroup": "chown Group",
|
||||||
"ChownGroupHelpText": "Group name or gid. Use gid for remote file systems.",
|
"ChownGroupHelpText": "Group name or gid. Use gid for remote file systems.",
|
||||||
"ChownGroupHelpTextWarning": "This only works if the user running Lidarr is the owner of the file. It's better to ensure the download client uses the same group as Lidarr.",
|
"ChownGroupHelpTextWarning": "This only works if the user running Lidarr is the owner of the file. It's better to ensure the download client uses the same group as Lidarr.",
|
||||||
"Clear": "Clear",
|
"Clear": "Clear",
|
||||||
"ClickToChangeQuality": "Click to change quality",
|
"ClickToChangeQuality": "Click to change quality",
|
||||||
|
"ClickToChangeReleaseGroup": "Click to change release group",
|
||||||
"ClientPriority": "Client Priority",
|
"ClientPriority": "Client Priority",
|
||||||
"CloneIndexer": "Clone Indexer",
|
"CloneIndexer": "Clone Indexer",
|
||||||
"CloneProfile": "Clone Profile",
|
"CloneProfile": "Clone Profile",
|
||||||
|
@ -497,11 +499,11 @@
|
||||||
"NotificationTriggers": "Notification Triggers",
|
"NotificationTriggers": "Notification Triggers",
|
||||||
"NoUpdatesAreAvailable": "No updates are available",
|
"NoUpdatesAreAvailable": "No updates are available",
|
||||||
"Ok": "Ok",
|
"Ok": "Ok",
|
||||||
"OnAlbumDeleteHelpText": "On Album Delete",
|
|
||||||
"OnAlbumDelete": "On Album Delete",
|
"OnAlbumDelete": "On Album Delete",
|
||||||
"OnArtistDelete": "On Artist Delete",
|
"OnAlbumDeleteHelpText": "On Album Delete",
|
||||||
"OnApplicationUpdate": "On Application Update",
|
"OnApplicationUpdate": "On Application Update",
|
||||||
"OnApplicationUpdateHelpText": "On Application Update",
|
"OnApplicationUpdateHelpText": "On Application Update",
|
||||||
|
"OnArtistDelete": "On Artist Delete",
|
||||||
"OnArtistDeleteHelpText": "On Artist Delete",
|
"OnArtistDeleteHelpText": "On Artist Delete",
|
||||||
"OnDownloadFailure": "On Download Failure",
|
"OnDownloadFailure": "On Download Failure",
|
||||||
"OnDownloadFailureHelpText": "On Download Failure",
|
"OnDownloadFailureHelpText": "On Download Failure",
|
||||||
|
@ -692,6 +694,7 @@
|
||||||
"SelectedCountArtistsSelectedInterp": "{0} Artist(s) Selected",
|
"SelectedCountArtistsSelectedInterp": "{0} Artist(s) Selected",
|
||||||
"SelectFolder": "Select Folder",
|
"SelectFolder": "Select Folder",
|
||||||
"SelectQuality": "Select Quality",
|
"SelectQuality": "Select Quality",
|
||||||
|
"SelectReleaseGroup": "Select Release Group",
|
||||||
"SelectTracks": "Select Tracks",
|
"SelectTracks": "Select Tracks",
|
||||||
"SendAnonymousUsageData": "Send Anonymous Usage Data",
|
"SendAnonymousUsageData": "Send Anonymous Usage Data",
|
||||||
"SetPermissions": "Set Permissions",
|
"SetPermissions": "Set Permissions",
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
||||||
public AlbumRelease Release { get; set; }
|
public AlbumRelease Release { get; set; }
|
||||||
public List<Track> Tracks { get; set; }
|
public List<Track> Tracks { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
|
public string ReleaseGroup { get; set; }
|
||||||
public string DownloadId { get; set; }
|
public string DownloadId { get; set; }
|
||||||
public IEnumerable<Rejection> Rejections { get; set; }
|
public IEnumerable<Rejection> Rejections { get; set; }
|
||||||
public ParsedTrackInfo Tags { get; set; }
|
public ParsedTrackInfo Tags { get; set; }
|
||||||
|
|
|
@ -17,6 +17,7 @@ using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Core.Music;
|
using NzbDrone.Core.Music;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.RootFolders;
|
using NzbDrone.Core.RootFolders;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
||||||
|
@ -237,7 +238,18 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
||||||
item.Tracks = decision.Item.Tracks;
|
item.Tracks = decision.Item.Tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.Quality?.Quality == Quality.Unknown)
|
||||||
|
{
|
||||||
|
item.Quality = decision.Item.Quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.ReleaseGroup.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
item.ReleaseGroup = decision.Item.ReleaseGroup;
|
||||||
|
}
|
||||||
|
|
||||||
item.Rejections = decision.Rejections;
|
item.Rejections = decision.Rejections;
|
||||||
|
item.Size = decision.Item.Size;
|
||||||
|
|
||||||
result.Add(item);
|
result.Add(item);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue