You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Lidarr/frontend/src/InteractiveImport/Interactive/InteractiveImportModalConte...

241 lines
6.4 KiB

import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import * as commandNames from 'Commands/commandNames';
import { executeCommand } from 'Store/Actions/commandActions';
import {
clearInteractiveImport,
fetchInteractiveImportItems,
saveInteractiveImportItem,
setInteractiveImportMode,
setInteractiveImportSort,
updateInteractiveImportItem } from 'Store/Actions/interactiveImportActions';
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
import InteractiveImportModalContent from './InteractiveImportModalContent';
function createMapStateToProps() {
return createSelector(
createClientSideCollectionSelector('interactiveImport'),
(interactiveImport) => {
return interactiveImport;
}
);
}
const mapDispatchToProps = {
fetchInteractiveImportItems,
setInteractiveImportSort,
setInteractiveImportMode,
clearInteractiveImport,
updateInteractiveImportItem,
saveInteractiveImportItem,
executeCommand
};
class InteractiveImportModalContentConnector extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
interactiveImportErrorMessage: null,
filterExistingFiles: props.filterExistingFiles,
replaceExistingFiles: props.replaceExistingFiles
};
}
componentDidMount() {
const {
artistId,
downloadId,
folder
} = this.props;
const {
filterExistingFiles,
replaceExistingFiles
} = this.state;
this.props.fetchInteractiveImportItems({
artistId,
downloadId,
folder,
filterExistingFiles,
replaceExistingFiles
});
}
componentDidUpdate(prevProps, prevState) {
const {
filterExistingFiles,
replaceExistingFiles
} = this.state;
if (prevState.filterExistingFiles !== filterExistingFiles ||
prevState.replaceExistingFiles !== replaceExistingFiles) {
const {
artistId,
downloadId,
folder
} = this.props;
this.props.fetchInteractiveImportItems({
artistId,
downloadId,
folder,
filterExistingFiles,
replaceExistingFiles
});
}
}
componentWillUnmount() {
this.props.clearInteractiveImport();
}
//
// Listeners
onSortPress = (sortKey, sortDirection) => {
this.props.setInteractiveImportSort({ sortKey, sortDirection });
};
onFilterExistingFilesChange = (filterExistingFiles) => {
this.setState({ filterExistingFiles });
};
onReplaceExistingFilesChange = (replaceExistingFiles) => {
this.setState({ replaceExistingFiles });
};
onImportModeChange = (importMode) => {
this.props.setInteractiveImportMode({ importMode });
};
onImportSelectedPress = (selected, importMode) => {
const files = [];
if (importMode === 'chooseImportMode') {
this.setState({ interactiveImportErrorMessage: 'An import mode must be selected' });
return;
}
_.forEach(this.props.items, (item) => {
const isSelected = selected.indexOf(item.id) > -1;
if (isSelected) {
const {
artist,
album,
albumReleaseId,
tracks,
isSingleFileRelease,
cueSheetPath,
quality,
disableReleaseSwitching
} = item;
if (!artist) {
this.setState({ interactiveImportErrorMessage: 'Artist must be chosen for each selected file' });
return false;
}
if (!album) {
this.setState({ interactiveImportErrorMessage: 'Album must be chosen for each selected file' });
return false;
}
if (!(isSingleFileRelease && cueSheetPath) && (!tracks || !tracks.length)) {
this.setState({ interactiveImportErrorMessage: 'One or more tracks must be chosen for each selected file' });
return false;
}
if (!quality) {
this.setState({ interactiveImportErrorMessage: 'Quality must be chosen for each selected file' });
return false;
}
files.push({
path: item.path,
artistId: artist.id,
albumId: album.id,
albumReleaseId,
trackIds: _.map(tracks, 'id'),
isSingleFileRelease: item.isSingleFileRelease,
cueSheetPath: item.cueSheetPath,
quality,
downloadId: this.props.downloadId,
disableReleaseSwitching
});
}
});
if (!files.length) {
return;
}
this.props.executeCommand({
name: commandNames.INTERACTIVE_IMPORT,
files,
importMode,
replaceExistingFiles: this.state.replaceExistingFiles
});
this.props.onModalClose();
};
//
// Render
render() {
const {
interactiveImportErrorMessage,
filterExistingFiles,
replaceExistingFiles
} = this.state;
return (
<InteractiveImportModalContent
{...this.props}
interactiveImportErrorMessage={interactiveImportErrorMessage}
filterExistingFiles={filterExistingFiles}
replaceExistingFiles={replaceExistingFiles}
onSortPress={this.onSortPress}
onFilterExistingFilesChange={this.onFilterExistingFilesChange}
onReplaceExistingFilesChange={this.onReplaceExistingFilesChange}
onImportModeChange={this.onImportModeChange}
onImportSelectedPress={this.onImportSelectedPress}
/>
);
}
}
InteractiveImportModalContentConnector.propTypes = {
artistId: PropTypes.number.isRequired,
downloadId: PropTypes.string,
folder: PropTypes.string,
filterExistingFiles: PropTypes.bool.isRequired,
replaceExistingFiles: PropTypes.bool.isRequired,
items: PropTypes.arrayOf(PropTypes.object).isRequired,
fetchInteractiveImportItems: PropTypes.func.isRequired,
setInteractiveImportSort: PropTypes.func.isRequired,
clearInteractiveImport: PropTypes.func.isRequired,
setInteractiveImportMode: PropTypes.func.isRequired,
updateInteractiveImportItem: PropTypes.func.isRequired,
executeCommand: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
InteractiveImportModalContentConnector.defaultProps = {
artistId: 0,
filterExistingFiles: true,
replaceExistingFiles: false
};
export default connect(createMapStateToProps, mapDispatchToProps)(InteractiveImportModalContentConnector);