mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-15 17:43:49 -07:00
[UI Work] Add Artist, Import Artist, Calendar
This commit is contained in:
parent
a747c5f135
commit
77f1d2e64c
109 changed files with 891 additions and 1082 deletions
|
@ -8,10 +8,10 @@ import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
|||
import TextInput from 'Components/Form/TextInput';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import AddNewSeriesSearchResultConnector from './AddNewSeriesSearchResultConnector';
|
||||
import styles from './AddNewSeries.css';
|
||||
import AddNewArtistSearchResultConnector from './AddNewArtistSearchResultConnector';
|
||||
import styles from './AddNewArtist.css';
|
||||
|
||||
class AddNewSeries extends Component {
|
||||
class AddNewArtist extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -29,7 +29,7 @@ class AddNewSeries extends Component {
|
|||
const term = this.state.term;
|
||||
|
||||
if (term) {
|
||||
this.props.onSeriesLookupChange(term);
|
||||
this.props.onArtistLookupChange(term);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ class AddNewSeries extends Component {
|
|||
term,
|
||||
isFetching: true
|
||||
});
|
||||
this.props.onSeriesLookupChange(term);
|
||||
this.props.onArtistLookupChange(term);
|
||||
} else if (isFetching !== prevProps.isFetching) {
|
||||
this.setState({
|
||||
isFetching
|
||||
|
@ -60,16 +60,16 @@ class AddNewSeries extends Component {
|
|||
|
||||
this.setState({ term: value, isFetching: hasValue }, () => {
|
||||
if (hasValue) {
|
||||
this.props.onSeriesLookupChange(value);
|
||||
this.props.onArtistLookupChange(value);
|
||||
} else {
|
||||
this.props.onClearSeriesLookup();
|
||||
this.props.onClearArtistLookup();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onClearSeriesLookupPress = () => {
|
||||
onClearArtistLookupPress = () => {
|
||||
this.setState({ term: '' });
|
||||
this.props.onClearSeriesLookup();
|
||||
this.props.onClearArtistLookup();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -97,7 +97,7 @@ class AddNewSeries extends Component {
|
|||
|
||||
<TextInput
|
||||
className={styles.searchInput}
|
||||
name="seriesLookup"
|
||||
name="artistLookup"
|
||||
value={term}
|
||||
placeholder="eg. Breaking Benjamin, lidarr:####"
|
||||
onChange={this.onSearchInputChange}
|
||||
|
@ -105,7 +105,7 @@ class AddNewSeries extends Component {
|
|||
|
||||
<Button
|
||||
className={styles.clearLookupButton}
|
||||
onPress={this.onClearSeriesLookupPress}
|
||||
onPress={this.onClearArtistLookupPress}
|
||||
>
|
||||
<Icon
|
||||
name={icons.REMOVE}
|
||||
|
@ -130,7 +130,7 @@ class AddNewSeries extends Component {
|
|||
{
|
||||
items.map((item) => {
|
||||
return (
|
||||
<AddNewSeriesSearchResultConnector
|
||||
<AddNewArtistSearchResultConnector
|
||||
key={item.foreignArtistId}
|
||||
{...item}
|
||||
/>
|
||||
|
@ -157,7 +157,7 @@ class AddNewSeries extends Component {
|
|||
!term &&
|
||||
<div className={styles.message}>
|
||||
<div className={styles.helpText}>It's easy to add a new artist, just start typing the name the artist you want to add.</div>
|
||||
<div>You can also search using MusicBrainz ID of a show. eg. lidarr:71663</div>
|
||||
<div>You can also search using MusicBrainz ID of a show. eg. lidarr:cc197bad-dc9c-440d-a5b5-d52ba2e14234</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
@ -170,15 +170,15 @@ class AddNewSeries extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
AddNewSeries.propTypes = {
|
||||
AddNewArtist.propTypes = {
|
||||
term: PropTypes.string,
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
isAdding: PropTypes.bool.isRequired,
|
||||
addError: PropTypes.object,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onSeriesLookupChange: PropTypes.func.isRequired,
|
||||
onClearSeriesLookup: PropTypes.func.isRequired
|
||||
onArtistLookupChange: PropTypes.func.isRequired,
|
||||
onClearArtistLookup: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default AddNewSeries;
|
||||
export default AddNewArtist;
|
|
@ -3,32 +3,32 @@ import React, { Component } from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import queryString from 'query-string';
|
||||
import { lookupSeries, clearAddSeries } from 'Store/Actions/addSeriesActions';
|
||||
import { lookupArtist, clearAddArtist } from 'Store/Actions/addArtistActions';
|
||||
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||
import AddNewSeries from './AddNewSeries';
|
||||
import AddNewArtist from './AddNewArtist';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.addSeries,
|
||||
(state) => state.addArtist,
|
||||
(state) => state.routing.location,
|
||||
(addSeries, location) => {
|
||||
(addArtist, location) => {
|
||||
const query = queryString.parse(location.search);
|
||||
|
||||
return {
|
||||
term: query.term,
|
||||
...addSeries
|
||||
...addArtist
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
lookupSeries,
|
||||
clearAddSeries,
|
||||
lookupArtist,
|
||||
clearAddArtist,
|
||||
fetchRootFolders
|
||||
};
|
||||
|
||||
class AddNewSeriesConnector extends Component {
|
||||
class AddNewArtistConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -36,7 +36,7 @@ class AddNewSeriesConnector extends Component {
|
|||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this._seriesLookupTimeout = null;
|
||||
this._artistLookupTimeout = null;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -44,32 +44,32 @@ class AddNewSeriesConnector extends Component {
|
|||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this._seriesLookupTimeout) {
|
||||
clearTimeout(this._seriesLookupTimeout);
|
||||
if (this._artistLookupTimeout) {
|
||||
clearTimeout(this._artistLookupTimeout);
|
||||
}
|
||||
|
||||
this.props.clearAddSeries();
|
||||
this.props.clearAddArtist();
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onSeriesLookupChange = (term) => {
|
||||
if (this._seriesLookupTimeout) {
|
||||
clearTimeout(this._seriesLookupTimeout);
|
||||
onArtistLookupChange = (term) => {
|
||||
if (this._artistLookupTimeout) {
|
||||
clearTimeout(this._artistLookupTimeout);
|
||||
}
|
||||
|
||||
if (term.trim() === '') {
|
||||
this.props.clearAddSeries();
|
||||
this.props.clearAddArtist();
|
||||
} else {
|
||||
this._seriesLookupTimeout = setTimeout(() => {
|
||||
this.props.lookupSeries({ term });
|
||||
this._artistLookupTimeout = setTimeout(() => {
|
||||
this.props.lookupArtist({ term });
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
onClearSeriesLookup = () => {
|
||||
this.props.clearAddSeries();
|
||||
onClearArtistLookup = () => {
|
||||
this.props.clearAddArtist();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -82,21 +82,21 @@ class AddNewSeriesConnector extends Component {
|
|||
} = this.props;
|
||||
|
||||
return (
|
||||
<AddNewSeries
|
||||
<AddNewArtist
|
||||
term={term}
|
||||
{...otherProps}
|
||||
onSeriesLookupChange={this.onSeriesLookupChange}
|
||||
onClearSeriesLookup={this.onClearSeriesLookup}
|
||||
onArtistLookupChange={this.onArtistLookupChange}
|
||||
onClearArtistLookup={this.onClearArtistLookup}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AddNewSeriesConnector.propTypes = {
|
||||
AddNewArtistConnector.propTypes = {
|
||||
term: PropTypes.string,
|
||||
lookupSeries: PropTypes.func.isRequired,
|
||||
clearAddSeries: PropTypes.func.isRequired,
|
||||
lookupArtist: PropTypes.func.isRequired,
|
||||
clearAddArtist: PropTypes.func.isRequired,
|
||||
fetchRootFolders: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(AddNewSeriesConnector);
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(AddNewArtistConnector);
|
|
@ -1,9 +1,9 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import AddNewSeriesModalContentConnector from './AddNewSeriesModalContentConnector';
|
||||
import AddNewArtistModalContentConnector from './AddNewArtistModalContentConnector';
|
||||
|
||||
function AddNewSeriesModal(props) {
|
||||
function AddNewArtistModal(props) {
|
||||
const {
|
||||
isOpen,
|
||||
onModalClose,
|
||||
|
@ -15,7 +15,7 @@ function AddNewSeriesModal(props) {
|
|||
isOpen={isOpen}
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<AddNewSeriesModalContentConnector
|
||||
<AddNewArtistModalContentConnector
|
||||
{...otherProps}
|
||||
onModalClose={onModalClose}
|
||||
/>
|
||||
|
@ -23,9 +23,9 @@ function AddNewSeriesModal(props) {
|
|||
);
|
||||
}
|
||||
|
||||
AddNewSeriesModal.propTypes = {
|
||||
AddNewArtistModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default AddNewSeriesModal;
|
||||
export default AddNewArtistModal;
|
|
@ -25,23 +25,23 @@
|
|||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.searchForMissingEpisodesLabelContainer {
|
||||
.searchForMissingAlbumsLabelContainer {
|
||||
display: flex;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.searchForMissingEpisodesLabel {
|
||||
.searchForMissingAlbumsLabel {
|
||||
margin-right: 8px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.searchForMissingEpisodesContainer {
|
||||
.searchForMissingAlbumsContainer {
|
||||
composes: container from 'Components/Form/CheckInput.css';
|
||||
|
||||
flex: 0 1 0;
|
||||
}
|
||||
|
||||
.searchForMissingEpisodesInput {
|
||||
.searchForMissingAlbumsInput {
|
||||
composes: input from 'Components/Form/CheckInput.css';
|
||||
|
||||
margin-top: 0;
|
|
@ -14,11 +14,11 @@ import ModalBody from 'Components/Modal/ModalBody';
|
|||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import ArtistPoster from 'Artist/ArtistPoster';
|
||||
import SeriesMonitoringOptionsPopoverContent from 'AddArtist/SeriesMonitoringOptionsPopoverContent';
|
||||
import SeriesTypePopoverContent from 'AddArtist/SeriesTypePopoverContent';
|
||||
import styles from './AddNewSeriesModalContent.css';
|
||||
import ArtistMonitoringOptionsPopoverContent from 'AddArtist/ArtistMonitoringOptionsPopoverContent';
|
||||
// import SeriesTypePopoverContent from 'AddArtist/SeriesTypePopoverContent';
|
||||
import styles from './AddNewArtistModalContent.css';
|
||||
|
||||
class AddNewSeriesModalContent extends Component {
|
||||
class AddNewArtistModalContent extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -27,15 +27,15 @@ class AddNewSeriesModalContent extends Component {
|
|||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
searchForMissingEpisodes: false
|
||||
searchForMissingAlbums: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onSearchForMissingEpisodesChange = ({ value }) => {
|
||||
this.setState({ searchForMissingEpisodes: value });
|
||||
onSearchForMissingAlbumsChange = ({ value }) => {
|
||||
this.setState({ searchForMissingAlbums: value });
|
||||
}
|
||||
|
||||
onQualityProfileIdChange = ({ value }) => {
|
||||
|
@ -46,8 +46,8 @@ class AddNewSeriesModalContent extends Component {
|
|||
this.props.onInputChange({ name: 'languageProfileId', value: parseInt(value) });
|
||||
}
|
||||
|
||||
onAddSeriesPress = () => {
|
||||
this.props.onAddSeriesPress(this.state.searchForMissingEpisodes);
|
||||
onAddArtistPress = () => {
|
||||
this.props.onAddArtistPress(this.state.searchForMissingAlbums);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -56,7 +56,7 @@ class AddNewSeriesModalContent extends Component {
|
|||
render() {
|
||||
const {
|
||||
artistName,
|
||||
year,
|
||||
// year,
|
||||
overview,
|
||||
images,
|
||||
isAdding,
|
||||
|
@ -64,7 +64,7 @@ class AddNewSeriesModalContent extends Component {
|
|||
monitor,
|
||||
qualityProfileId,
|
||||
languageProfileId,
|
||||
seriesType,
|
||||
// seriesType,
|
||||
albumFolder,
|
||||
tags,
|
||||
showLanguageProfile,
|
||||
|
@ -77,11 +77,6 @@ class AddNewSeriesModalContent extends Component {
|
|||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
{artistName}
|
||||
|
||||
{
|
||||
!name.contains(year) &&
|
||||
<span className={styles.year}>({year})</span>
|
||||
}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
|
@ -126,13 +121,13 @@ class AddNewSeriesModalContent extends Component {
|
|||
/>
|
||||
}
|
||||
title="Monitoring Options"
|
||||
body={<SeriesMonitoringOptionsPopoverContent />}
|
||||
body={<ArtistMonitoringOptionsPopoverContent />}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.MONITOR_EPISODES_SELECT}
|
||||
type={inputTypes.MONITOR_ALBUMS_SELECT}
|
||||
name="monitor"
|
||||
onChange={onInputChange}
|
||||
{...monitor}
|
||||
|
@ -161,31 +156,6 @@ class AddNewSeriesModalContent extends Component {
|
|||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
Series Type
|
||||
|
||||
<Popover
|
||||
anchor={
|
||||
<Icon
|
||||
className={styles.labelIcon}
|
||||
name={icons.INFO}
|
||||
/>
|
||||
}
|
||||
title="Series Types"
|
||||
body={<SeriesTypePopoverContent />}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SERIES_TYPE_SELECT}
|
||||
name="seriesType"
|
||||
onChange={onInputChange}
|
||||
{...seriesType}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Album Folder</FormLabel>
|
||||
|
||||
|
@ -213,17 +183,17 @@ class AddNewSeriesModalContent extends Component {
|
|||
</ModalBody>
|
||||
|
||||
<ModalFooter className={styles.modalFooter}>
|
||||
<label className={styles.searchForMissingEpisodesLabelContainer}>
|
||||
<span className={styles.searchForMissingEpisodesLabel}>
|
||||
Start search for missing episodes
|
||||
<label className={styles.searchForMissingAlbumsLabelContainer}>
|
||||
<span className={styles.searchForMissingAlbumsLabel}>
|
||||
Start search for missing albums
|
||||
</span>
|
||||
|
||||
<CheckInput
|
||||
containerClassName={styles.searchForMissingEpisodesContainer}
|
||||
className={styles.searchForMissingEpisodesInput}
|
||||
name="searchForMissingEpisodes"
|
||||
value={this.state.searchForMissingEpisodes}
|
||||
onChange={this.onSearchForMissingEpisodesChange}
|
||||
containerClassName={styles.searchForMissingAlbumsContainer}
|
||||
className={styles.searchForMissingAlbumsInput}
|
||||
name="searchForMissingAlbums"
|
||||
value={this.state.searchForMissingAlbums}
|
||||
onChange={this.onSearchForMissingAlbumsChange}
|
||||
/>
|
||||
</label>
|
||||
|
||||
|
@ -231,7 +201,7 @@ class AddNewSeriesModalContent extends Component {
|
|||
className={styles.addButton}
|
||||
kind={kinds.SUCCESS}
|
||||
isSpinning={isAdding}
|
||||
onPress={this.onAddSeriesPress}
|
||||
onPress={this.onAddArtistPress}
|
||||
>
|
||||
Add {artistName}
|
||||
</SpinnerButton>
|
||||
|
@ -241,9 +211,9 @@ class AddNewSeriesModalContent extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
AddNewSeriesModalContent.propTypes = {
|
||||
AddNewArtistModalContent.propTypes = {
|
||||
artistName: PropTypes.string.isRequired,
|
||||
year: PropTypes.number.isRequired,
|
||||
// year: PropTypes.number.isRequired,
|
||||
overview: PropTypes.string,
|
||||
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
isAdding: PropTypes.bool.isRequired,
|
||||
|
@ -252,14 +222,14 @@ AddNewSeriesModalContent.propTypes = {
|
|||
monitor: PropTypes.object.isRequired,
|
||||
qualityProfileId: PropTypes.object,
|
||||
languageProfileId: PropTypes.object,
|
||||
seriesType: PropTypes.object.isRequired,
|
||||
// seriesType: PropTypes.object.isRequired,
|
||||
albumFolder: PropTypes.object.isRequired,
|
||||
tags: PropTypes.object.isRequired,
|
||||
showLanguageProfile: PropTypes.bool.isRequired,
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
onInputChange: PropTypes.func.isRequired,
|
||||
onAddSeriesPress: PropTypes.func.isRequired
|
||||
onAddArtistPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default AddNewSeriesModalContent;
|
||||
export default AddNewArtistModalContent;
|
|
@ -2,22 +2,22 @@ import PropTypes from 'prop-types';
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { setAddSeriesDefault, addSeries } from 'Store/Actions/addSeriesActions';
|
||||
import { setAddArtistDefault, addArtist } from 'Store/Actions/addArtistActions';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import selectSettings from 'Store/Selectors/selectSettings';
|
||||
import AddNewSeriesModalContent from './AddNewSeriesModalContent';
|
||||
import AddNewArtistModalContent from './AddNewArtistModalContent';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.addSeries,
|
||||
(state) => state.addArtist,
|
||||
(state) => state.settings.languageProfiles,
|
||||
createDimensionsSelector(),
|
||||
(addSeriesState, languageProfiles, dimensions) => {
|
||||
(addArtistState, languageProfiles, dimensions) => {
|
||||
const {
|
||||
isAdding,
|
||||
addError,
|
||||
defaults
|
||||
} = addSeriesState;
|
||||
} = addArtistState;
|
||||
|
||||
const {
|
||||
settings,
|
||||
|
@ -39,20 +39,20 @@ function createMapStateToProps() {
|
|||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
setAddSeriesDefault,
|
||||
addSeries
|
||||
setAddArtistDefault,
|
||||
addArtist
|
||||
};
|
||||
|
||||
class AddNewSeriesModalContentConnector extends Component {
|
||||
class AddNewArtistModalContentConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onInputChange = ({ name, value }) => {
|
||||
this.props.setAddSeriesDefault({ [name]: value });
|
||||
this.props.setAddArtistDefault({ [name]: value });
|
||||
}
|
||||
|
||||
onAddSeriesPress = (searchForMissingEpisodes) => {
|
||||
onAddArtistPress = (searchForMissingAlbums) => {
|
||||
const {
|
||||
foreignArtistId,
|
||||
rootFolderPath,
|
||||
|
@ -63,7 +63,7 @@ class AddNewSeriesModalContentConnector extends Component {
|
|||
tags
|
||||
} = this.props;
|
||||
|
||||
this.props.addSeries({
|
||||
this.props.addArtist({
|
||||
foreignArtistId,
|
||||
rootFolderPath: rootFolderPath.value,
|
||||
monitor: monitor.value,
|
||||
|
@ -71,7 +71,7 @@ class AddNewSeriesModalContentConnector extends Component {
|
|||
languageProfileId: languageProfileId.value,
|
||||
albumFolder: albumFolder.value,
|
||||
tags: tags.value,
|
||||
searchForMissingEpisodes
|
||||
searchForMissingAlbums
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -80,16 +80,16 @@ class AddNewSeriesModalContentConnector extends Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<AddNewSeriesModalContent
|
||||
<AddNewArtistModalContent
|
||||
{...this.props}
|
||||
onInputChange={this.onInputChange}
|
||||
onAddSeriesPress={this.onAddSeriesPress}
|
||||
onAddArtistPress={this.onAddArtistPress}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AddNewSeriesModalContentConnector.propTypes = {
|
||||
AddNewArtistModalContentConnector.propTypes = {
|
||||
foreignArtistId: PropTypes.string.isRequired,
|
||||
rootFolderPath: PropTypes.object,
|
||||
monitor: PropTypes.object.isRequired,
|
||||
|
@ -98,8 +98,8 @@ AddNewSeriesModalContentConnector.propTypes = {
|
|||
albumFolder: PropTypes.object.isRequired,
|
||||
tags: PropTypes.object.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
setAddSeriesDefault: PropTypes.func.isRequired,
|
||||
addSeries: PropTypes.func.isRequired
|
||||
setAddArtistDefault: PropTypes.func.isRequired,
|
||||
addArtist: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(AddNewSeriesModalContentConnector);
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(AddNewArtistModalContentConnector);
|
|
@ -6,10 +6,10 @@ import Icon from 'Components/Icon';
|
|||
import Label from 'Components/Label';
|
||||
import Link from 'Components/Link/Link';
|
||||
import ArtistPoster from 'Artist/ArtistPoster';
|
||||
import AddNewSeriesModal from './AddNewSeriesModal';
|
||||
import styles from './AddNewSeriesSearchResult.css';
|
||||
import AddNewArtistModal from './AddNewArtistModal';
|
||||
import styles from './AddNewArtistSearchResult.css';
|
||||
|
||||
class AddNewSeriesSearchResult extends Component {
|
||||
class AddNewArtistSearchResult extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -23,7 +23,7 @@ class AddNewSeriesSearchResult extends Component {
|
|||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (!prevProps.isExistingSeries && this.props.isExistingSeries) {
|
||||
if (!prevProps.isExistingArtist && this.props.isExistingArtist) {
|
||||
this.onAddSerisModalClose();
|
||||
}
|
||||
}
|
||||
|
@ -54,11 +54,11 @@ class AddNewSeriesSearchResult extends Component {
|
|||
seasonCount,
|
||||
ratings,
|
||||
images,
|
||||
isExistingSeries,
|
||||
isExistingArtist,
|
||||
isSmallScreen
|
||||
} = this.props;
|
||||
|
||||
const linkProps = isExistingSeries ? { to: `/series/${nameSlug}` } : { onPress: this.onPress };
|
||||
const linkProps = isExistingArtist ? { to: `/series/${nameSlug}` } : { onPress: this.onPress };
|
||||
let seasons = '1 Season';
|
||||
|
||||
if (seasonCount > 1) {
|
||||
|
@ -89,12 +89,12 @@ class AddNewSeriesSearchResult extends Component {
|
|||
}
|
||||
|
||||
{
|
||||
isExistingSeries &&
|
||||
isExistingArtist &&
|
||||
<Icon
|
||||
className={styles.alreadyExistsIcon}
|
||||
name={icons.CHECK_CIRCLE}
|
||||
size={36}
|
||||
artistName="Already in your library"
|
||||
title="Already in your library"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
@ -137,8 +137,8 @@ class AddNewSeriesSearchResult extends Component {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<AddNewSeriesModal
|
||||
isOpen={this.state.isNewAddSeriesModalOpen && !isExistingSeries}
|
||||
<AddNewArtistModal
|
||||
isOpen={this.state.isNewAddSeriesModalOpen && !isExistingArtist}
|
||||
foreignArtistId={foreignArtistId}
|
||||
artistName={artistName}
|
||||
year={year}
|
||||
|
@ -151,7 +151,7 @@ class AddNewSeriesSearchResult extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
AddNewSeriesSearchResult.propTypes = {
|
||||
AddNewArtistSearchResult.propTypes = {
|
||||
foreignArtistId: PropTypes.string.isRequired,
|
||||
artistName: PropTypes.string.isRequired,
|
||||
nameSlug: PropTypes.string.isRequired,
|
||||
|
@ -162,8 +162,8 @@ AddNewSeriesSearchResult.propTypes = {
|
|||
seasonCount: PropTypes.number,
|
||||
ratings: PropTypes.object.isRequired,
|
||||
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
isExistingSeries: PropTypes.bool.isRequired,
|
||||
isExistingArtist: PropTypes.bool.isRequired,
|
||||
isSmallScreen: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
export default AddNewSeriesSearchResult;
|
||||
export default AddNewArtistSearchResult;
|
|
@ -1,20 +1,20 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createExistingSeriesSelector from 'Store/Selectors/createExistingSeriesSelector';
|
||||
import createExistingArtistSelector from 'Store/Selectors/createExistingArtistSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import AddNewSeriesSearchResult from './AddNewSeriesSearchResult';
|
||||
import AddNewArtistSearchResult from './AddNewArtistSearchResult';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createExistingSeriesSelector(),
|
||||
createExistingArtistSelector(),
|
||||
createDimensionsSelector(),
|
||||
(isExistingSeries, dimensions) => {
|
||||
(isExistingArtist, dimensions) => {
|
||||
return {
|
||||
isExistingSeries,
|
||||
isExistingArtist,
|
||||
isSmallScreen: dimensions.isSmallScreen
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps)(AddNewSeriesSearchResult);
|
||||
export default connect(createMapStateToProps)(AddNewArtistSearchResult);
|
|
@ -0,0 +1,46 @@
|
|||
import React from 'react';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
|
||||
function ArtistMonitoringOptionsPopoverContent() {
|
||||
return (
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
title="All Albums"
|
||||
data="Monitor all albums except specials"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Future Albums"
|
||||
data="Monitor albums that have not released yet"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Missing Albums"
|
||||
data="Monitor albums that do not have files or have not released yet"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Existing Albums"
|
||||
data="Monitor albums that have files or have not released yet"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="First Album"
|
||||
data="Monitor the first albums. All other albums will be ignored"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Latest Album"
|
||||
data="Monitor the latest albums and future albums"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="None"
|
||||
data="No albums will be monitored."
|
||||
/>
|
||||
</DescriptionList>
|
||||
);
|
||||
}
|
||||
|
||||
export default ArtistMonitoringOptionsPopoverContent;
|
|
@ -6,10 +6,10 @@ import toggleSelected from 'Utilities/Table/toggleSelected';
|
|||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import ImportSeriesTableConnector from './ImportSeriesTableConnector';
|
||||
import ImportSeriesFooterConnector from './ImportSeriesFooterConnector';
|
||||
import ImportArtistTableConnector from './ImportArtistTableConnector';
|
||||
import ImportArtistFooterConnector from './ImportArtistFooterConnector';
|
||||
|
||||
class ImportSeries extends Component {
|
||||
class ImportArtist extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -98,7 +98,7 @@ class ImportSeries extends Component {
|
|||
} = this.state;
|
||||
|
||||
return (
|
||||
<PageContent title="Import Series">
|
||||
<PageContent title="Import Artist">
|
||||
<PageContentBodyConnector
|
||||
ref={this.setContentBodyRef}
|
||||
onScroll={this.onScroll}
|
||||
|
@ -122,7 +122,7 @@ class ImportSeries extends Component {
|
|||
|
||||
{
|
||||
!rootFoldersError && rootFoldersPopulated && !!unmappedFolders.length && contentBody &&
|
||||
<ImportSeriesTableConnector
|
||||
<ImportArtistTableConnector
|
||||
rootFolderId={rootFolderId}
|
||||
unmappedFolders={unmappedFolders}
|
||||
allSelected={allSelected}
|
||||
|
@ -141,7 +141,7 @@ class ImportSeries extends Component {
|
|||
|
||||
{
|
||||
!rootFoldersError && rootFoldersPopulated && !!unmappedFolders.length &&
|
||||
<ImportSeriesFooterConnector
|
||||
<ImportArtistFooterConnector
|
||||
selectedIds={this.getSelectedIds()}
|
||||
showLanguageProfile={showLanguageProfile}
|
||||
onInputChange={this.onInputChange}
|
||||
|
@ -153,7 +153,7 @@ class ImportSeries extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
ImportSeries.propTypes = {
|
||||
ImportArtist.propTypes = {
|
||||
rootFolderId: PropTypes.number.isRequired,
|
||||
path: PropTypes.string,
|
||||
rootFoldersFetching: PropTypes.bool.isRequired,
|
||||
|
@ -166,8 +166,8 @@ ImportSeries.propTypes = {
|
|||
onImportPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
ImportSeries.defaultProps = {
|
||||
ImportArtist.defaultProps = {
|
||||
unmappedFolders: []
|
||||
};
|
||||
|
||||
export default ImportSeries;
|
||||
export default ImportArtist;
|
|
@ -3,20 +3,20 @@ import PropTypes from 'prop-types';
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { setImportSeriesValue, importSeries, clearImportSeries } from 'Store/Actions/importSeriesActions';
|
||||
import { setImportArtistValue, importArtist, clearImportArtist } from 'Store/Actions/importArtistActions';
|
||||
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||
import { setAddSeriesDefault } from 'Store/Actions/addSeriesActions';
|
||||
import { setAddArtistDefault } from 'Store/Actions/addArtistActions';
|
||||
import createRouteMatchShape from 'Helpers/Props/Shapes/createRouteMatchShape';
|
||||
import ImportSeries from './ImportSeries';
|
||||
import ImportArtist from './ImportArtist';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state, { match }) => match,
|
||||
(state) => state.rootFolders,
|
||||
(state) => state.addSeries,
|
||||
(state) => state.importSeries,
|
||||
(state) => state.addArtist,
|
||||
(state) => state.importArtist,
|
||||
(state) => state.settings.languageProfiles,
|
||||
(match, rootFolders, addSeries, importSeriesState, languageProfiles) => {
|
||||
(match, rootFolders, addArtist, importArtistState, languageProfiles) => {
|
||||
const {
|
||||
isFetching: rootFoldersFetching,
|
||||
isPopulated: rootFoldersPopulated,
|
||||
|
@ -40,7 +40,7 @@ function createMapStateToProps() {
|
|||
return {
|
||||
...result,
|
||||
...rootFolder,
|
||||
items: importSeriesState.items
|
||||
items: importArtistState.items
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -50,14 +50,14 @@ function createMapStateToProps() {
|
|||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
setImportSeriesValue,
|
||||
importSeries,
|
||||
clearImportSeries,
|
||||
setImportArtistValue,
|
||||
importArtist,
|
||||
clearImportArtist,
|
||||
fetchRootFolders,
|
||||
setAddSeriesDefault
|
||||
setAddArtistDefault
|
||||
};
|
||||
|
||||
class ImportSeriesConnector extends Component {
|
||||
class ImportArtistConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -69,17 +69,17 @@ class ImportSeriesConnector extends Component {
|
|||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.clearImportSeries();
|
||||
this.props.clearImportArtist();
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onInputChange = (ids, name, value) => {
|
||||
this.props.setAddSeriesDefault({ [name]: value });
|
||||
this.props.setAddArtistDefault({ [name]: value });
|
||||
|
||||
ids.forEach((id) => {
|
||||
this.props.setImportSeriesValue({
|
||||
this.props.setImportArtistValue({
|
||||
id,
|
||||
[name]: value
|
||||
});
|
||||
|
@ -87,7 +87,7 @@ class ImportSeriesConnector extends Component {
|
|||
}
|
||||
|
||||
onImportPress = (ids) => {
|
||||
this.props.importSeries({ ids });
|
||||
this.props.importArtist({ ids });
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -95,7 +95,7 @@ class ImportSeriesConnector extends Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<ImportSeries
|
||||
<ImportArtist
|
||||
{...this.props}
|
||||
onInputChange={this.onInputChange}
|
||||
onImportPress={this.onImportPress}
|
||||
|
@ -108,14 +108,14 @@ const routeMatchShape = createRouteMatchShape({
|
|||
rootFolderId: PropTypes.string.isRequired
|
||||
});
|
||||
|
||||
ImportSeriesConnector.propTypes = {
|
||||
ImportArtistConnector.propTypes = {
|
||||
match: routeMatchShape.isRequired,
|
||||
rootFoldersPopulated: PropTypes.bool.isRequired,
|
||||
setImportSeriesValue: PropTypes.func.isRequired,
|
||||
importSeries: PropTypes.func.isRequired,
|
||||
clearImportSeries: PropTypes.func.isRequired,
|
||||
setImportArtistValue: PropTypes.func.isRequired,
|
||||
importArtist: PropTypes.func.isRequired,
|
||||
clearImportArtist: PropTypes.func.isRequired,
|
||||
fetchRootFolders: PropTypes.func.isRequired,
|
||||
setAddSeriesDefault: PropTypes.func.isRequired
|
||||
setAddArtistDefault: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportSeriesConnector);
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportArtistConnector);
|
|
@ -7,11 +7,11 @@ import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
|||
import CheckInput from 'Components/Form/CheckInput';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import PageContentFooter from 'Components/Page/PageContentFooter';
|
||||
import styles from './ImportSeriesFooter.css';
|
||||
import styles from './ImportArtistFooter.css';
|
||||
|
||||
const MIXED = 'mixed';
|
||||
|
||||
class ImportSeriesFooter extends Component {
|
||||
class ImportArtistFooter extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -23,7 +23,7 @@ class ImportSeriesFooter extends Component {
|
|||
defaultMonitor,
|
||||
defaultQualityProfileId,
|
||||
defaultLanguageProfileId,
|
||||
defaultSeasonFolder,
|
||||
defaultAlbumFolder,
|
||||
defaultSeriesType
|
||||
} = props;
|
||||
|
||||
|
@ -32,7 +32,7 @@ class ImportSeriesFooter extends Component {
|
|||
qualityProfileId: defaultQualityProfileId,
|
||||
languageProfileId: defaultLanguageProfileId,
|
||||
seriesType: defaultSeriesType,
|
||||
seasonFolder: defaultSeasonFolder
|
||||
albumFolder: defaultAlbumFolder
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -41,21 +41,21 @@ class ImportSeriesFooter extends Component {
|
|||
defaultMonitor,
|
||||
defaultQualityProfileId,
|
||||
defaultLanguageProfileId,
|
||||
defaultSeriesType,
|
||||
defaultSeasonFolder,
|
||||
// defaultSeriesType,
|
||||
defaultAlbumFolder,
|
||||
isMonitorMixed,
|
||||
isQualityProfileIdMixed,
|
||||
isLanguageProfileIdMixed,
|
||||
isSeriesTypeMixed,
|
||||
isSeasonFolderMixed
|
||||
// isSeriesTypeMixed,
|
||||
isAlbumFolderMixed
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
monitor,
|
||||
qualityProfileId,
|
||||
languageProfileId,
|
||||
seriesType,
|
||||
seasonFolder
|
||||
// seriesType,
|
||||
albumFolder
|
||||
} = this.state;
|
||||
|
||||
const newState = {};
|
||||
|
@ -78,16 +78,10 @@ class ImportSeriesFooter extends Component {
|
|||
newState.languageProfileId = defaultLanguageProfileId;
|
||||
}
|
||||
|
||||
if (isSeriesTypeMixed && seriesType !== MIXED) {
|
||||
newState.seriesType = MIXED;
|
||||
} else if (!isSeriesTypeMixed && seriesType !== defaultSeriesType) {
|
||||
newState.seriesType = defaultSeriesType;
|
||||
}
|
||||
|
||||
if (isSeasonFolderMixed && seasonFolder != null) {
|
||||
newState.seasonFolder = null;
|
||||
} else if (!isSeasonFolderMixed && seasonFolder !== defaultSeasonFolder) {
|
||||
newState.seasonFolder = defaultSeasonFolder;
|
||||
if (isAlbumFolderMixed && albumFolder != null) {
|
||||
newState.albumFolder = null;
|
||||
} else if (!isAlbumFolderMixed && albumFolder !== defaultAlbumFolder) {
|
||||
newState.albumFolder = defaultAlbumFolder;
|
||||
}
|
||||
|
||||
if (!_.isEmpty(newState)) {
|
||||
|
@ -110,11 +104,11 @@ class ImportSeriesFooter extends Component {
|
|||
const {
|
||||
selectedCount,
|
||||
isImporting,
|
||||
isLookingUpSeries,
|
||||
isLookingUpArtist,
|
||||
isMonitorMixed,
|
||||
isQualityProfileIdMixed,
|
||||
isLanguageProfileIdMixed,
|
||||
isSeriesTypeMixed,
|
||||
// isSeriesTypeMixed,
|
||||
showLanguageProfile,
|
||||
onImportPress
|
||||
} = this.props;
|
||||
|
@ -123,8 +117,8 @@ class ImportSeriesFooter extends Component {
|
|||
monitor,
|
||||
qualityProfileId,
|
||||
languageProfileId,
|
||||
seriesType,
|
||||
seasonFolder
|
||||
// seriesType,
|
||||
albumFolder
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
|
@ -135,7 +129,7 @@ class ImportSeriesFooter extends Component {
|
|||
</div>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.MONITOR_EPISODES_SELECT}
|
||||
type={inputTypes.MONITOR_ALBUMS_SELECT}
|
||||
name="monitor"
|
||||
value={monitor}
|
||||
isDisabled={!selectedCount}
|
||||
|
@ -180,27 +174,12 @@ class ImportSeriesFooter extends Component {
|
|||
|
||||
<div className={styles.inputContainer}>
|
||||
<div className={styles.label}>
|
||||
Series Type
|
||||
</div>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SERIES_TYPE_SELECT}
|
||||
name="seriesType"
|
||||
value={seriesType}
|
||||
isDisabled={!selectedCount}
|
||||
includeMixed={isSeriesTypeMixed}
|
||||
onChange={this.onInputChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.inputContainer}>
|
||||
<div className={styles.label}>
|
||||
Season Folder
|
||||
Album Folder
|
||||
</div>
|
||||
|
||||
<CheckInput
|
||||
name="seasonFolder"
|
||||
value={seasonFolder}
|
||||
name="albumFolder"
|
||||
value={albumFolder}
|
||||
isDisabled={!selectedCount}
|
||||
onChange={this.onInputChange}
|
||||
/>
|
||||
|
@ -216,14 +195,14 @@ class ImportSeriesFooter extends Component {
|
|||
className={styles.importButton}
|
||||
kind={kinds.PRIMARY}
|
||||
isSpinning={isImporting}
|
||||
isDisabled={!selectedCount || isLookingUpSeries}
|
||||
isDisabled={!selectedCount || isLookingUpArtist}
|
||||
onPress={onImportPress}
|
||||
>
|
||||
Import {selectedCount} Series
|
||||
Import {selectedCount} Artist(s)
|
||||
</SpinnerButton>
|
||||
|
||||
{
|
||||
isLookingUpSeries &&
|
||||
isLookingUpArtist &&
|
||||
<LoadingIndicator
|
||||
className={styles.loading}
|
||||
size={24}
|
||||
|
@ -231,7 +210,7 @@ class ImportSeriesFooter extends Component {
|
|||
}
|
||||
|
||||
{
|
||||
isLookingUpSeries &&
|
||||
isLookingUpArtist &&
|
||||
'Processing Folders'
|
||||
}
|
||||
</div>
|
||||
|
@ -241,23 +220,23 @@ class ImportSeriesFooter extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
ImportSeriesFooter.propTypes = {
|
||||
ImportArtistFooter.propTypes = {
|
||||
selectedCount: PropTypes.number.isRequired,
|
||||
isImporting: PropTypes.bool.isRequired,
|
||||
isLookingUpSeries: PropTypes.bool.isRequired,
|
||||
isLookingUpArtist: PropTypes.bool.isRequired,
|
||||
defaultMonitor: PropTypes.string.isRequired,
|
||||
defaultQualityProfileId: PropTypes.number,
|
||||
defaultLanguageProfileId: PropTypes.number,
|
||||
defaultSeriesType: PropTypes.string.isRequired,
|
||||
defaultSeasonFolder: PropTypes.bool.isRequired,
|
||||
defaultAlbumFolder: PropTypes.bool.isRequired,
|
||||
isMonitorMixed: PropTypes.bool.isRequired,
|
||||
isQualityProfileIdMixed: PropTypes.bool.isRequired,
|
||||
isLanguageProfileIdMixed: PropTypes.bool.isRequired,
|
||||
isSeriesTypeMixed: PropTypes.bool.isRequired,
|
||||
isSeasonFolderMixed: PropTypes.bool.isRequired,
|
||||
// isSeriesTypeMixed: PropTypes.bool.isRequired,
|
||||
isAlbumFolderMixed: PropTypes.bool.isRequired,
|
||||
showLanguageProfile: PropTypes.bool.isRequired,
|
||||
onInputChange: PropTypes.func.isRequired,
|
||||
onImportPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default ImportSeriesFooter;
|
||||
export default ImportArtistFooter;
|
|
@ -1,7 +1,7 @@
|
|||
import _ from 'lodash';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import ImportSeriesFooter from './ImportSeriesFooter';
|
||||
import ImportArtistFooter from './ImportArtistFooter';
|
||||
|
||||
function isMixed(items, selectedIds, defaultValue, key) {
|
||||
return _.some(items, (series) => {
|
||||
|
@ -11,21 +11,21 @@ function isMixed(items, selectedIds, defaultValue, key) {
|
|||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.addSeries,
|
||||
(state) => state.importSeries,
|
||||
(state) => state.addArtist,
|
||||
(state) => state.importArtist,
|
||||
(state, { selectedIds }) => selectedIds,
|
||||
(addSeries, importSeries, selectedIds) => {
|
||||
(addArtist, importArtist, selectedIds) => {
|
||||
const {
|
||||
monitor: defaultMonitor,
|
||||
qualityProfileId: defaultQualityProfileId,
|
||||
languageProfileId: defaultLanguageProfileId,
|
||||
seriesType: defaultSeriesType,
|
||||
seasonFolder: defaultSeasonFolder
|
||||
} = addSeries.defaults;
|
||||
albumFolder: defaultAlbumFolder
|
||||
} = addArtist.defaults;
|
||||
|
||||
const items = importSeries.items;
|
||||
const items = importArtist.items;
|
||||
|
||||
const isLookingUpSeries = _.some(importSeries.items, (series) => {
|
||||
const isLookingUpArtist = _.some(importArtist.items, (series) => {
|
||||
return !series.isPopulated && series.error == null;
|
||||
});
|
||||
|
||||
|
@ -33,25 +33,25 @@ function createMapStateToProps() {
|
|||
const isQualityProfileIdMixed = isMixed(items, selectedIds, defaultQualityProfileId, 'qualityProfileId');
|
||||
const isLanguageProfileIdMixed = isMixed(items, selectedIds, defaultLanguageProfileId, 'languageProfileId');
|
||||
const isSeriesTypeMixed = isMixed(items, selectedIds, defaultSeriesType, 'seriesType');
|
||||
const isSeasonFolderMixed = isMixed(items, selectedIds, defaultSeasonFolder, 'seasonFolder');
|
||||
const isAlbumFolderMixed = isMixed(items, selectedIds, defaultAlbumFolder, 'albumFolder');
|
||||
|
||||
return {
|
||||
selectedCount: selectedIds.length,
|
||||
isImporting: importSeries.isImporting,
|
||||
isLookingUpSeries,
|
||||
isImporting: importArtist.isImporting,
|
||||
isLookingUpArtist,
|
||||
defaultMonitor,
|
||||
defaultQualityProfileId,
|
||||
defaultLanguageProfileId,
|
||||
defaultSeriesType,
|
||||
defaultSeasonFolder,
|
||||
defaultAlbumFolder,
|
||||
isMonitorMixed,
|
||||
isQualityProfileIdMixed,
|
||||
isLanguageProfileIdMixed,
|
||||
isSeriesTypeMixed,
|
||||
isSeasonFolderMixed
|
||||
isAlbumFolderMixed
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps)(ImportSeriesFooter);
|
||||
export default connect(createMapStateToProps)(ImportArtistFooter);
|
|
@ -26,14 +26,14 @@
|
|||
min-width: 120px;
|
||||
}
|
||||
|
||||
.seasonFolder {
|
||||
.albumFolder {
|
||||
composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css';
|
||||
|
||||
flex: 0 1 150px;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.series {
|
||||
.artist {
|
||||
composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css';
|
||||
|
||||
flex: 0 1 400px;
|
|
@ -6,11 +6,11 @@ import Popover from 'Components/Tooltip/Popover';
|
|||
import VirtualTableHeader from 'Components/Table/VirtualTableHeader';
|
||||
import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell';
|
||||
import VirtualTableSelectAllHeaderCell from 'Components/Table/VirtualTableSelectAllHeaderCell';
|
||||
import SeriesMonitoringOptionsPopoverContent from 'AddArtist/SeriesMonitoringOptionsPopoverContent';
|
||||
import SeriesTypePopoverContent from 'AddArtist/SeriesTypePopoverContent';
|
||||
import styles from './ImportSeriesHeader.css';
|
||||
import ArtistMonitoringOptionsPopoverContent from 'AddArtist/ArtistMonitoringOptionsPopoverContent';
|
||||
// import SeriesTypePopoverContent from 'AddArtist/SeriesTypePopoverContent';
|
||||
import styles from './ImportArtistHeader.css';
|
||||
|
||||
function ImportSeriesHeader(props) {
|
||||
function ImportArtistHeader(props) {
|
||||
const {
|
||||
showLanguageProfile,
|
||||
allSelected,
|
||||
|
@ -47,7 +47,7 @@ function ImportSeriesHeader(props) {
|
|||
/>
|
||||
}
|
||||
title="Monitoring Options"
|
||||
body={<SeriesMonitoringOptionsPopoverContent />}
|
||||
body={<ArtistMonitoringOptionsPopoverContent />}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
</VirtualTableHeaderCell>
|
||||
|
@ -70,46 +70,27 @@ function ImportSeriesHeader(props) {
|
|||
}
|
||||
|
||||
<VirtualTableHeaderCell
|
||||
className={styles.seriesType}
|
||||
name="seriesType"
|
||||
className={styles.albumFolder}
|
||||
name="albumFolder"
|
||||
>
|
||||
Series Type
|
||||
|
||||
<Popover
|
||||
anchor={
|
||||
<Icon
|
||||
className={styles.detailsIcon}
|
||||
name={icons.INFO}
|
||||
/>
|
||||
}
|
||||
title="Series Type"
|
||||
body={<SeriesTypePopoverContent />}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
Album Folder
|
||||
</VirtualTableHeaderCell>
|
||||
|
||||
<VirtualTableHeaderCell
|
||||
className={styles.seasonFolder}
|
||||
name="seasonFolder"
|
||||
>
|
||||
Season Folder
|
||||
</VirtualTableHeaderCell>
|
||||
|
||||
<VirtualTableHeaderCell
|
||||
className={styles.series}
|
||||
className={styles.artist}
|
||||
name="series"
|
||||
>
|
||||
Series
|
||||
Artist
|
||||
</VirtualTableHeaderCell>
|
||||
</VirtualTableHeader>
|
||||
);
|
||||
}
|
||||
|
||||
ImportSeriesHeader.propTypes = {
|
||||
ImportArtistHeader.propTypes = {
|
||||
showLanguageProfile: PropTypes.bool.isRequired,
|
||||
allSelected: PropTypes.bool.isRequired,
|
||||
allUnselected: PropTypes.bool.isRequired,
|
||||
onSelectAllChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default ImportSeriesHeader;
|
||||
export default ImportArtistHeader;
|
|
@ -31,7 +31,7 @@
|
|||
min-width: 120px;
|
||||
}
|
||||
|
||||
.seasonFolder {
|
||||
.albumFolder {
|
||||
composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css';
|
||||
|
||||
flex: 0 1 150px;
|
|
@ -5,20 +5,20 @@ import FormInputGroup from 'Components/Form/FormInputGroup';
|
|||
import VirtualTableRow from 'Components/Table/VirtualTableRow';
|
||||
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
|
||||
import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
|
||||
import ImportSeriesSelectSeriesConnector from './SelectSeries/ImportSeriesSelectSeriesConnector';
|
||||
import styles from './ImportSeriesRow.css';
|
||||
import ImportArtistSelectArtistConnector from './SelectArtist/ImportArtistSelectArtistConnector';
|
||||
import styles from './ImportArtistRow.css';
|
||||
|
||||
function ImportSeriesRow(props) {
|
||||
function ImportArtistRow(props) {
|
||||
const {
|
||||
style,
|
||||
id,
|
||||
monitor,
|
||||
qualityProfileId,
|
||||
languageProfileId,
|
||||
seasonFolder,
|
||||
seriesType,
|
||||
albumFolder,
|
||||
// seriesType,
|
||||
selectedSeries,
|
||||
isExistingSeries,
|
||||
isExistingArtist,
|
||||
showLanguageProfile,
|
||||
isSelected,
|
||||
onSelectedChange,
|
||||
|
@ -31,7 +31,7 @@ function ImportSeriesRow(props) {
|
|||
inputClassName={styles.selectInput}
|
||||
id={id}
|
||||
isSelected={isSelected}
|
||||
isDisabled={!selectedSeries || isExistingSeries}
|
||||
isDisabled={!selectedSeries || isExistingArtist}
|
||||
onSelectedChange={onSelectedChange}
|
||||
/>
|
||||
|
||||
|
@ -41,7 +41,7 @@ function ImportSeriesRow(props) {
|
|||
|
||||
<VirtualTableRowCell className={styles.monitor}>
|
||||
<FormInputGroup
|
||||
type={inputTypes.MONITOR_EPISODES_SELECT}
|
||||
type={inputTypes.MONITOR_ALBUMS_SELECT}
|
||||
name="monitor"
|
||||
value={monitor}
|
||||
onChange={onInputChange}
|
||||
|
@ -68,44 +68,35 @@ function ImportSeriesRow(props) {
|
|||
/>
|
||||
</VirtualTableRowCell>
|
||||
|
||||
<VirtualTableRowCell className={styles.seriesType}>
|
||||
<FormInputGroup
|
||||
type={inputTypes.SERIES_TYPE_SELECT}
|
||||
name="seriesType"
|
||||
value={seriesType}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</VirtualTableRowCell>
|
||||
|
||||
<VirtualTableRowCell className={styles.seasonFolder}>
|
||||
<VirtualTableRowCell className={styles.albumFolder}>
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="seasonFolder"
|
||||
value={seasonFolder}
|
||||
name="albumFolder"
|
||||
value={albumFolder}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</VirtualTableRowCell>
|
||||
|
||||
<VirtualTableRowCell className={styles.series}>
|
||||
<ImportSeriesSelectSeriesConnector
|
||||
<ImportArtistSelectArtistConnector
|
||||
id={id}
|
||||
isExistingSeries={isExistingSeries}
|
||||
isExistingArtist={isExistingArtist}
|
||||
/>
|
||||
</VirtualTableRowCell>
|
||||
</VirtualTableRow>
|
||||
);
|
||||
}
|
||||
|
||||
ImportSeriesRow.propTypes = {
|
||||
ImportArtistRow.propTypes = {
|
||||
style: PropTypes.object.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
monitor: PropTypes.string.isRequired,
|
||||
qualityProfileId: PropTypes.number.isRequired,
|
||||
languageProfileId: PropTypes.number.isRequired,
|
||||
seriesType: PropTypes.string.isRequired,
|
||||
seasonFolder: PropTypes.bool.isRequired,
|
||||
// seriesType: PropTypes.string.isRequired,
|
||||
albumFolder: PropTypes.bool.isRequired,
|
||||
selectedSeries: PropTypes.object,
|
||||
isExistingSeries: PropTypes.bool.isRequired,
|
||||
isExistingArtist: PropTypes.bool.isRequired,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
queued: PropTypes.bool.isRequired,
|
||||
showLanguageProfile: PropTypes.bool.isRequired,
|
||||
|
@ -114,8 +105,8 @@ ImportSeriesRow.propTypes = {
|
|||
onInputChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
ImportSeriesRow.defaultsProps = {
|
||||
ImportArtistRow.defaultsProps = {
|
||||
items: []
|
||||
};
|
||||
|
||||
export default ImportSeriesRow;
|
||||
export default ImportArtistRow;
|
|
@ -3,14 +3,14 @@ import PropTypes from 'prop-types';
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { queueLookupSeries, setImportSeriesValue } from 'Store/Actions/importSeriesActions';
|
||||
import { queueLookupSeries, setImportArtistValue } from 'Store/Actions/importArtistActions';
|
||||
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
|
||||
import ImportSeriesRow from './ImportSeriesRow';
|
||||
import ImportArtistRow from './ImportArtistRow';
|
||||
|
||||
function createImportSeriesItemSelector() {
|
||||
function createImportArtistItemSelector() {
|
||||
return createSelector(
|
||||
(state, { id }) => id,
|
||||
(state) => state.importSeries.items,
|
||||
(state) => state.importArtist.items,
|
||||
(id, items) => {
|
||||
return _.find(items, { id }) || {};
|
||||
}
|
||||
|
@ -19,15 +19,15 @@ function createImportSeriesItemSelector() {
|
|||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createImportSeriesItemSelector(),
|
||||
createImportArtistItemSelector(),
|
||||
createAllSeriesSelector(),
|
||||
(item, series) => {
|
||||
const selectedSeries = item && item.selectedSeries;
|
||||
const isExistingSeries = !!selectedSeries && _.some(series, { tvdbId: selectedSeries.tvdbId });
|
||||
const isExistingArtist = !!selectedSeries && _.some(series, { foreignArtistId: selectedSeries.foreignArtistId });
|
||||
|
||||
return {
|
||||
...item,
|
||||
isExistingSeries
|
||||
isExistingArtist
|
||||
};
|
||||
}
|
||||
);
|
||||
|
@ -35,16 +35,16 @@ function createMapStateToProps() {
|
|||
|
||||
const mapDispatchToProps = {
|
||||
queueLookupSeries,
|
||||
setImportSeriesValue
|
||||
setImportArtistValue
|
||||
};
|
||||
|
||||
class ImportSeriesRowConnector extends Component {
|
||||
class ImportArtistRowConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onInputChange = ({ name, value }) => {
|
||||
this.props.setImportSeriesValue({
|
||||
this.props.setImportArtistValue({
|
||||
id: this.props.id,
|
||||
[name]: value
|
||||
});
|
||||
|
@ -59,16 +59,16 @@ class ImportSeriesRowConnector extends Component {
|
|||
const {
|
||||
items,
|
||||
monitor,
|
||||
seriesType,
|
||||
seasonFolder
|
||||
// seriesType,
|
||||
albumFolder
|
||||
} = this.props;
|
||||
|
||||
if (!items || !monitor || !seriesType || !seasonFolder == null) {
|
||||
if (!items || !monitor || !albumFolder == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ImportSeriesRow
|
||||
<ImportArtistRow
|
||||
{...this.props}
|
||||
onInputChange={this.onInputChange}
|
||||
onSeriesSelect={this.onSeriesSelect}
|
||||
|
@ -77,15 +77,15 @@ class ImportSeriesRowConnector extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
ImportSeriesRowConnector.propTypes = {
|
||||
ImportArtistRowConnector.propTypes = {
|
||||
rootFolderId: PropTypes.number.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
monitor: PropTypes.string,
|
||||
seriesType: PropTypes.string,
|
||||
seasonFolder: PropTypes.bool,
|
||||
// seriesType: PropTypes.string,
|
||||
albumFolder: PropTypes.bool,
|
||||
items: PropTypes.arrayOf(PropTypes.object),
|
||||
queueLookupSeries: PropTypes.func.isRequired,
|
||||
setImportSeriesValue: PropTypes.func.isRequired
|
||||
setImportArtistValue: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportSeriesRowConnector);
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportArtistRowConnector);
|
|
@ -2,10 +2,10 @@ import _ from 'lodash';
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import VirtualTable from 'Components/Table/VirtualTable';
|
||||
import ImportSeriesHeader from './ImportSeriesHeader';
|
||||
import ImportSeriesRowConnector from './ImportSeriesRowConnector';
|
||||
import ImportArtistHeader from './ImportArtistHeader';
|
||||
import ImportArtistRowConnector from './ImportArtistRowConnector';
|
||||
|
||||
class ImportSeriesTable extends Component {
|
||||
class ImportArtistTable extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -23,9 +23,9 @@ class ImportSeriesTable extends Component {
|
|||
defaultQualityProfileId,
|
||||
defaultLanguageProfileId,
|
||||
defaultSeriesType,
|
||||
defaultSeasonFolder,
|
||||
defaultAlbumFolder,
|
||||
onSeriesLookup,
|
||||
onSetImportSeriesValue
|
||||
onSetImportArtistValue
|
||||
} = this.props;
|
||||
|
||||
const values = {
|
||||
|
@ -33,7 +33,7 @@ class ImportSeriesTable extends Component {
|
|||
qualityProfileId: defaultQualityProfileId,
|
||||
languageProfileId: defaultLanguageProfileId,
|
||||
seriesType: defaultSeriesType,
|
||||
seasonFolder: defaultSeasonFolder
|
||||
albumFolder: defaultAlbumFolder
|
||||
};
|
||||
|
||||
unmappedFolders.forEach((unmappedFolder) => {
|
||||
|
@ -41,7 +41,7 @@ class ImportSeriesTable extends Component {
|
|||
|
||||
onSeriesLookup(id, unmappedFolder.path);
|
||||
|
||||
onSetImportSeriesValue({
|
||||
onSetImportArtistValue({
|
||||
id,
|
||||
...values
|
||||
});
|
||||
|
@ -75,12 +75,12 @@ class ImportSeriesTable extends Component {
|
|||
const selectedSeries = item.selectedSeries;
|
||||
const isSelected = selectedState[id];
|
||||
|
||||
const isExistingSeries = !!selectedSeries &&
|
||||
const isExistingArtist = !!selectedSeries &&
|
||||
_.some(prevProps.allSeries, { tvdbId: selectedSeries.tvdbId });
|
||||
|
||||
// Props doesn't have a selected series or
|
||||
// the selected series is an existing series.
|
||||
if ((selectedSeries && !prevItem.selectedSeries) || (isExistingSeries && !prevItem.selectedSeries)) {
|
||||
if ((selectedSeries && !prevItem.selectedSeries) || (isExistingArtist && !prevItem.selectedSeries)) {
|
||||
onSelectedChange({ id, value: false });
|
||||
|
||||
return;
|
||||
|
@ -88,7 +88,7 @@ class ImportSeriesTable extends Component {
|
|||
|
||||
// State is selected, but a series isn't selected or
|
||||
// the selected series is an existing series.
|
||||
if (isSelected && (!selectedSeries || isExistingSeries)) {
|
||||
if (isSelected && (!selectedSeries || isExistingArtist)) {
|
||||
onSelectedChange({ id, value: false });
|
||||
|
||||
return;
|
||||
|
@ -129,7 +129,7 @@ class ImportSeriesTable extends Component {
|
|||
const item = items[rowIndex];
|
||||
|
||||
return (
|
||||
<ImportSeriesRowConnector
|
||||
<ImportArtistRowConnector
|
||||
key={key}
|
||||
style={style}
|
||||
rootFolderId={rootFolderId}
|
||||
|
@ -172,7 +172,7 @@ class ImportSeriesTable extends Component {
|
|||
overscanRowCount={2}
|
||||
rowRenderer={this.rowRenderer}
|
||||
header={
|
||||
<ImportSeriesHeader
|
||||
<ImportArtistHeader
|
||||
showLanguageProfile={showLanguageProfile}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
|
@ -185,7 +185,7 @@ class ImportSeriesTable extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
ImportSeriesTable.propTypes = {
|
||||
ImportArtistTable.propTypes = {
|
||||
rootFolderId: PropTypes.number.isRequired,
|
||||
items: PropTypes.arrayOf(PropTypes.object),
|
||||
unmappedFolders: PropTypes.arrayOf(PropTypes.object),
|
||||
|
@ -193,7 +193,7 @@ ImportSeriesTable.propTypes = {
|
|||
defaultQualityProfileId: PropTypes.number,
|
||||
defaultLanguageProfileId: PropTypes.number,
|
||||
defaultSeriesType: PropTypes.string.isRequired,
|
||||
defaultSeasonFolder: PropTypes.bool.isRequired,
|
||||
defaultAlbumFolder: PropTypes.bool.isRequired,
|
||||
allSelected: PropTypes.bool.isRequired,
|
||||
allUnselected: PropTypes.bool.isRequired,
|
||||
selectedState: PropTypes.object.isRequired,
|
||||
|
@ -206,8 +206,8 @@ ImportSeriesTable.propTypes = {
|
|||
onSelectedChange: PropTypes.func.isRequired,
|
||||
onRemoveSelectedStateItem: PropTypes.func.isRequired,
|
||||
onSeriesLookup: PropTypes.func.isRequired,
|
||||
onSetImportSeriesValue: PropTypes.func.isRequired,
|
||||
onSetImportArtistValue: PropTypes.func.isRequired,
|
||||
onScroll: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default ImportSeriesTable;
|
||||
export default ImportArtistTable;
|
|
@ -0,0 +1,44 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { queueLookupSeries, setImportArtistValue } from 'Store/Actions/importArtistActions';
|
||||
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
|
||||
import ImportArtistTable from './ImportArtistTable';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.addArtist,
|
||||
(state) => state.importArtist,
|
||||
(state) => state.app.dimensions,
|
||||
createAllSeriesSelector(),
|
||||
(addArtist, importArtist, dimensions, allSeries) => {
|
||||
return {
|
||||
defaultMonitor: addArtist.defaults.monitor,
|
||||
defaultQualityProfileId: addArtist.defaults.qualityProfileId,
|
||||
defaultLanguageProfileId: addArtist.defaults.languageProfileId,
|
||||
defaultSeriesType: addArtist.defaults.seriesType,
|
||||
defaultAlbumFolder: addArtist.defaults.albumFolder,
|
||||
items: importArtist.items,
|
||||
isSmallScreen: dimensions.isSmallScreen,
|
||||
allSeries
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createMapDispatchToProps(dispatch, props) {
|
||||
return {
|
||||
onSeriesLookup(name, path) {
|
||||
dispatch(queueLookupSeries({
|
||||
name,
|
||||
path,
|
||||
term: name
|
||||
}));
|
||||
},
|
||||
|
||||
onSetImportArtistValue(values) {
|
||||
dispatch(setImportArtistValue(values));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps, createMapDispatchToProps)(ImportArtistTable);
|
|
@ -1,12 +1,17 @@
|
|||
.titleContainer {
|
||||
.artistNameContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
.artistName {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.overview {
|
||||
margin-right: 5px;
|
||||
color: $disabledColor;
|
||||
}
|
||||
|
||||
.year {
|
||||
margin-left: 5px;
|
||||
color: $disabledColor;
|
|
@ -0,0 +1,45 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import Label from 'Components/Label';
|
||||
import styles from './ImportArtistName.css';
|
||||
|
||||
function ImportArtistName(props) {
|
||||
const {
|
||||
artistName,
|
||||
overview,
|
||||
// year,
|
||||
// network,
|
||||
isExistingArtist
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div className={styles.artistNameContainer}>
|
||||
<div className={styles.artistName}>
|
||||
{artistName}
|
||||
</div>
|
||||
<div className={styles.overview}>
|
||||
{overview}
|
||||
</div>
|
||||
|
||||
{
|
||||
isExistingArtist &&
|
||||
<Label
|
||||
kind={kinds.WARNING}
|
||||
>
|
||||
Existing
|
||||
</Label>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ImportArtistName.propTypes = {
|
||||
artistName: PropTypes.string.isRequired,
|
||||
overview: PropTypes.string.isRequired,
|
||||
// year: PropTypes.number.isRequired,
|
||||
// network: PropTypes.string,
|
||||
isExistingArtist: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
export default ImportArtistName;
|
|
@ -1,4 +1,4 @@
|
|||
.series {
|
||||
.artist {
|
||||
padding: 10px 20px;
|
||||
width: 100%;
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Link from 'Components/Link/Link';
|
||||
import ImportArtistName from './ImportArtistName';
|
||||
import styles from './ImportArtistSearchResult.css';
|
||||
|
||||
class ImportArtistSearchResult extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onPress = () => {
|
||||
this.props.onPress(this.props.foreignArtistId);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
artistName,
|
||||
overview,
|
||||
// year,
|
||||
// network,
|
||||
isExistingArtist
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Link
|
||||
className={styles.artist}
|
||||
onPress={this.onPress}
|
||||
>
|
||||
<ImportArtistName
|
||||
artistName={artistName}
|
||||
overview={overview}
|
||||
// year={year}
|
||||
// network={network}
|
||||
isExistingArtist={isExistingArtist}
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImportArtistSearchResult.propTypes = {
|
||||
foreignArtistId: PropTypes.string.isRequired,
|
||||
artistName: PropTypes.string.isRequired,
|
||||
overview: PropTypes.string.isRequired,
|
||||
// year: PropTypes.number.isRequired,
|
||||
// network: PropTypes.string,
|
||||
isExistingArtist: PropTypes.bool.isRequired,
|
||||
onPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default ImportArtistSearchResult;
|
|
@ -0,0 +1,17 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createExistingArtistSelector from 'Store/Selectors/createExistingArtistSelector';
|
||||
import ImportArtistSearchResult from './ImportArtistSearchResult';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createExistingArtistSelector(),
|
||||
(isExistingArtist) => {
|
||||
return {
|
||||
isExistingArtist
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps)(ImportArtistSearchResult);
|
|
@ -8,9 +8,9 @@ import SpinnerIcon from 'Components/SpinnerIcon';
|
|||
import Link from 'Components/Link/Link';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import TextInput from 'Components/Form/TextInput';
|
||||
import ImportSeriesSearchResultConnector from './ImportSeriesSearchResultConnector';
|
||||
import ImportSeriesTitle from './ImportSeriesTitle';
|
||||
import styles from './ImportSeriesSelectSeries.css';
|
||||
import ImportArtistSearchResultConnector from './ImportArtistSearchResultConnector';
|
||||
import ImportArtistName from './ImportArtistName';
|
||||
import styles from './ImportArtistSelectArtist.css';
|
||||
|
||||
const tetherOptions = {
|
||||
skipMoveElement: true,
|
||||
|
@ -25,7 +25,7 @@ const tetherOptions = {
|
|||
targetAttachment: 'bottom center'
|
||||
};
|
||||
|
||||
class ImportSeriesSelectSeries extends Component {
|
||||
class ImportArtistSelectArtist extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -33,7 +33,7 @@ class ImportSeriesSelectSeries extends Component {
|
|||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this._seriesLookupTimeout = null;
|
||||
this._artistLookupTimeout = null;
|
||||
|
||||
this.state = {
|
||||
term: props.id,
|
||||
|
@ -88,12 +88,12 @@ class ImportSeriesSelectSeries extends Component {
|
|||
}
|
||||
|
||||
onSearchInputChange = ({ value }) => {
|
||||
if (this._seriesLookupTimeout) {
|
||||
clearTimeout(this._seriesLookupTimeout);
|
||||
if (this._artistLookupTimeout) {
|
||||
clearTimeout(this._artistLookupTimeout);
|
||||
}
|
||||
|
||||
this.setState({ term: value }, () => {
|
||||
this._seriesLookupTimeout = setTimeout(() => {
|
||||
this._artistLookupTimeout = setTimeout(() => {
|
||||
this.props.onSearchInputChange(value);
|
||||
}, 200);
|
||||
});
|
||||
|
@ -111,7 +111,7 @@ class ImportSeriesSelectSeries extends Component {
|
|||
render() {
|
||||
const {
|
||||
selectedSeries,
|
||||
isExistingSeries,
|
||||
isExistingArtist,
|
||||
isFetching,
|
||||
isPopulated,
|
||||
error,
|
||||
|
@ -146,7 +146,7 @@ class ImportSeriesSelectSeries extends Component {
|
|||
}
|
||||
|
||||
{
|
||||
isPopulated && selectedSeries && isExistingSeries &&
|
||||
isPopulated && selectedSeries && isExistingArtist &&
|
||||
<Icon
|
||||
className={styles.warningIcon}
|
||||
name={icons.WARNING}
|
||||
|
@ -156,11 +156,12 @@ class ImportSeriesSelectSeries extends Component {
|
|||
|
||||
{
|
||||
isPopulated && selectedSeries &&
|
||||
<ImportSeriesTitle
|
||||
title={selectedSeries.title}
|
||||
year={selectedSeries.year}
|
||||
network={selectedSeries.network}
|
||||
isExistingSeries={isExistingSeries}
|
||||
<ImportArtistName
|
||||
artistName={selectedSeries.artistName}
|
||||
overview={selectedSeries.overview}
|
||||
// year={selectedSeries.year}
|
||||
// network={selectedSeries.network}
|
||||
isExistingArtist={isExistingArtist}
|
||||
/>
|
||||
}
|
||||
|
||||
|
@ -225,12 +226,13 @@ class ImportSeriesSelectSeries extends Component {
|
|||
{
|
||||
items.map((item) => {
|
||||
return (
|
||||
<ImportSeriesSearchResultConnector
|
||||
key={item.tvdbId}
|
||||
tvdbId={item.tvdbId}
|
||||
title={item.title}
|
||||
year={item.year}
|
||||
network={item.network}
|
||||
<ImportArtistSearchResultConnector
|
||||
key={item.foreignArtistId}
|
||||
foreignArtistId={item.foreignArtistId}
|
||||
artistName={item.artistName}
|
||||
overview={item.overview}
|
||||
// year={item.year}
|
||||
// network={item.network}
|
||||
onPress={this.onSeriesSelect}
|
||||
/>
|
||||
);
|
||||
|
@ -245,10 +247,10 @@ class ImportSeriesSelectSeries extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
ImportSeriesSelectSeries.propTypes = {
|
||||
ImportArtistSelectArtist.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
selectedSeries: PropTypes.object,
|
||||
isExistingSeries: PropTypes.bool.isRequired,
|
||||
isExistingArtist: PropTypes.bool.isRequired,
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
isPopulated: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
|
@ -258,11 +260,11 @@ ImportSeriesSelectSeries.propTypes = {
|
|||
onSeriesSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
ImportSeriesSelectSeries.defaultProps = {
|
||||
ImportArtistSelectArtist.defaultProps = {
|
||||
isFetching: true,
|
||||
isPopulated: false,
|
||||
items: [],
|
||||
queued: true
|
||||
};
|
||||
|
||||
export default ImportSeriesSelectSeries;
|
||||
export default ImportArtistSelectArtist;
|
|
@ -3,13 +3,13 @@ import PropTypes from 'prop-types';
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { queueLookupSeries, setImportSeriesValue } from 'Store/Actions/importSeriesActions';
|
||||
import createImportSeriesItemSelector from 'Store/Selectors/createImportSeriesItemSelector';
|
||||
import ImportSeriesSelectSeries from './ImportSeriesSelectSeries';
|
||||
import { queueLookupSeries, setImportArtistValue } from 'Store/Actions/importArtistActions';
|
||||
import createImportArtistItemSelector from 'Store/Selectors/createImportArtistItemSelector';
|
||||
import ImportArtistSelectArtist from './ImportArtistSelectArtist';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createImportSeriesItemSelector(),
|
||||
createImportArtistItemSelector(),
|
||||
(item) => {
|
||||
return item;
|
||||
}
|
||||
|
@ -18,10 +18,10 @@ function createMapStateToProps() {
|
|||
|
||||
const mapDispatchToProps = {
|
||||
queueLookupSeries,
|
||||
setImportSeriesValue
|
||||
setImportArtistValue
|
||||
};
|
||||
|
||||
class ImportSeriesSelectSeriesConnector extends Component {
|
||||
class ImportArtistSelectArtistConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
@ -33,15 +33,15 @@ class ImportSeriesSelectSeriesConnector extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
onSeriesSelect = (tvdbId) => {
|
||||
onSeriesSelect = (foreignArtistId) => {
|
||||
const {
|
||||
id,
|
||||
items
|
||||
} = this.props;
|
||||
|
||||
this.props.setImportSeriesValue({
|
||||
this.props.setImportArtistValue({
|
||||
id,
|
||||
selectedSeries: _.find(items, { tvdbId })
|
||||
selectedSeries: _.find(items, { foreignArtistId })
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ class ImportSeriesSelectSeriesConnector extends Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<ImportSeriesSelectSeries
|
||||
<ImportArtistSelectArtist
|
||||
{...this.props}
|
||||
onSearchInputChange={this.onSearchInputChange}
|
||||
onSeriesSelect={this.onSeriesSelect}
|
||||
|
@ -59,13 +59,13 @@ class ImportSeriesSelectSeriesConnector extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
ImportSeriesSelectSeriesConnector.propTypes = {
|
||||
ImportArtistSelectArtistConnector.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
items: PropTypes.arrayOf(PropTypes.object),
|
||||
selectedSeries: PropTypes.object,
|
||||
isSelected: PropTypes.bool,
|
||||
queueLookupSeries: PropTypes.func.isRequired,
|
||||
setImportSeriesValue: PropTypes.func.isRequired
|
||||
setImportArtistValue: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportSeriesSelectSeriesConnector);
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportArtistSelectArtistConnector);
|
30
frontend/src/AddArtist/ImportArtist/ImportArtist.js
Normal file
30
frontend/src/AddArtist/ImportArtist/ImportArtist.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Route } from 'react-router-dom';
|
||||
import Switch from 'Components/Router/Switch';
|
||||
import ImportArtistSelectFolderConnector from 'AddArtist/ImportArtist/SelectFolder/ImportArtistSelectFolderConnector';
|
||||
import ImportArtistConnector from 'AddArtist/ImportArtist/Import/ImportArtistConnector';
|
||||
|
||||
class ImportArtist extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Switch>
|
||||
<Route
|
||||
exact={true}
|
||||
path="/add/import"
|
||||
component={ImportArtistSelectFolderConnector}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/add/import/:rootFolderId"
|
||||
component={ImportArtistConnector}
|
||||
/>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ImportArtist;
|
|
@ -6,9 +6,9 @@ import IconButton from 'Components/Link/IconButton';
|
|||
import Link from 'Components/Link/Link';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import styles from './ImportSeriesRootFolderRow.css';
|
||||
import styles from './ImportArtistRootFolderRow.css';
|
||||
|
||||
function ImportSeriesRootFolderRow(props) {
|
||||
function ImportArtistRootFolderRow(props) {
|
||||
const {
|
||||
id,
|
||||
path,
|
||||
|
@ -48,7 +48,7 @@ function ImportSeriesRootFolderRow(props) {
|
|||
);
|
||||
}
|
||||
|
||||
ImportSeriesRootFolderRow.propTypes = {
|
||||
ImportArtistRootFolderRow.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
freeSpace: PropTypes.number.isRequired,
|
||||
|
@ -56,9 +56,9 @@ ImportSeriesRootFolderRow.propTypes = {
|
|||
onDeletePress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
ImportSeriesRootFolderRow.defaultProps = {
|
||||
ImportArtistRootFolderRow.defaultProps = {
|
||||
freeSpace: 0,
|
||||
unmappedFolders: []
|
||||
};
|
||||
|
||||
export default ImportSeriesRootFolderRow;
|
||||
export default ImportArtistRootFolderRow;
|
|
@ -3,7 +3,7 @@ import React, { Component } from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { deleteRootFolder } from 'Store/Actions/rootFolderActions';
|
||||
import ImportSeriesRootFolderRow from './ImportSeriesRootFolderRow';
|
||||
import ImportArtistRootFolderRow from './ImportArtistRootFolderRow';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
|
@ -18,7 +18,7 @@ const mapDispatchToProps = {
|
|||
deleteRootFolder
|
||||
};
|
||||
|
||||
class ImportSeriesRootFolderRowConnector extends Component {
|
||||
class ImportArtistRootFolderRowConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
@ -32,7 +32,7 @@ class ImportSeriesRootFolderRowConnector extends Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<ImportSeriesRootFolderRow
|
||||
<ImportArtistRootFolderRow
|
||||
{...this.props}
|
||||
onDeletePress={this.onDeletePress}
|
||||
/>
|
||||
|
@ -40,9 +40,9 @@ class ImportSeriesRootFolderRowConnector extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
ImportSeriesRootFolderRowConnector.propTypes = {
|
||||
ImportArtistRootFolderRowConnector.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
deleteRootFolder: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportSeriesRootFolderRowConnector);
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportArtistRootFolderRowConnector);
|
|
@ -10,8 +10,8 @@ import PageContent from 'Components/Page/PageContent';
|
|||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import ImportSeriesRootFolderRowConnector from './ImportSeriesRootFolderRowConnector';
|
||||
import styles from './ImportSeriesSelectFolder.css';
|
||||
import ImportArtistRootFolderRowConnector from './ImportArtistRootFolderRowConnector';
|
||||
import styles from './ImportArtistSelectFolder.css';
|
||||
|
||||
const rootFolderColumns = [
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ const rootFolderColumns = [
|
|||
}
|
||||
];
|
||||
|
||||
class ImportSeriesSelectFolder extends Component {
|
||||
class ImportArtistSelectFolder extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -75,7 +75,7 @@ class ImportSeriesSelectFolder extends Component {
|
|||
} = this.props;
|
||||
|
||||
return (
|
||||
<PageContent title="Import Series">
|
||||
<PageContent title="Import Artist">
|
||||
<PageContentBodyConnector>
|
||||
{
|
||||
isFetching && !isPopulated &&
|
||||
|
@ -91,17 +91,14 @@ class ImportSeriesSelectFolder extends Component {
|
|||
!error && isPopulated &&
|
||||
<div>
|
||||
<div className={styles.header}>
|
||||
Import series you already have
|
||||
Import artist(s) you already have
|
||||
</div>
|
||||
|
||||
<div className={styles.tips}>
|
||||
Some tips to ensure the import goes smoothly:
|
||||
<ul>
|
||||
<li className={styles.tip}>
|
||||
Make sure your files include the quality in the name. eg. <span className={styles.code}>episode.s02e15.bluray.mkv</span>
|
||||
</li>
|
||||
<li className={styles.tip}>
|
||||
Point Sonarr to the folder containing all of your tv shows not a specific one. eg. <span className={styles.code}>"\tv shows\"</span> and not <span className={styles.code}>"\tv shows\the simpsons\"</span>
|
||||
Point Lidarr to the folder containing all of your music not a specific artist. eg. <span className={styles.code}>"\music\"</span> and not <span className={styles.code}>"\music\alien ant farm\"</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -119,7 +116,7 @@ class ImportSeriesSelectFolder extends Component {
|
|||
{
|
||||
items.map((rootFolder) => {
|
||||
return (
|
||||
<ImportSeriesRootFolderRowConnector
|
||||
<ImportArtistRootFolderRowConnector
|
||||
key={rootFolder.id}
|
||||
id={rootFolder.id}
|
||||
path={rootFolder.path}
|
||||
|
@ -176,7 +173,7 @@ class ImportSeriesSelectFolder extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
ImportSeriesSelectFolder.propTypes = {
|
||||
ImportArtistSelectFolder.propTypes = {
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
isPopulated: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
|
@ -185,4 +182,4 @@ ImportSeriesSelectFolder.propTypes = {
|
|||
onDeleteRootFolderPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default ImportSeriesSelectFolder;
|
||||
export default ImportArtistSelectFolder;
|
|
@ -6,7 +6,7 @@ import { createSelector } from 'reselect';
|
|||
import { push } from 'react-router-redux';
|
||||
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
|
||||
import { fetchRootFolders, addRootFolder, deleteRootFolder } from 'Store/Actions/rootFolderActions';
|
||||
import ImportSeriesSelectFolder from './ImportSeriesSelectFolder';
|
||||
import ImportArtistSelectFolder from './ImportArtistSelectFolder';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
|
@ -24,7 +24,7 @@ const mapDispatchToProps = {
|
|||
push
|
||||
};
|
||||
|
||||
class ImportSeriesSelectFolderConnector extends Component {
|
||||
class ImportArtistSelectFolderConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
@ -65,7 +65,7 @@ class ImportSeriesSelectFolderConnector extends Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<ImportSeriesSelectFolder
|
||||
<ImportArtistSelectFolder
|
||||
{...this.props}
|
||||
onNewRootFolderSelect={this.onNewRootFolderSelect}
|
||||
onDeleteRootFolderPress={this.onDeleteRootFolderPress}
|
||||
|
@ -74,7 +74,7 @@ class ImportSeriesSelectFolderConnector extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
ImportSeriesSelectFolderConnector.propTypes = {
|
||||
ImportArtistSelectFolderConnector.propTypes = {
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
saveError: PropTypes.object,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
|
@ -84,4 +84,4 @@ ImportSeriesSelectFolderConnector.propTypes = {
|
|||
push: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportSeriesSelectFolderConnector);
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportArtistSelectFolderConnector);
|
|
@ -1,44 +0,0 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { queueLookupSeries, setImportSeriesValue } from 'Store/Actions/importSeriesActions';
|
||||
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
|
||||
import ImportSeriesTable from './ImportSeriesTable';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.addSeries,
|
||||
(state) => state.importSeries,
|
||||
(state) => state.app.dimensions,
|
||||
createAllSeriesSelector(),
|
||||
(addSeries, importSeries, dimensions, allSeries) => {
|
||||
return {
|
||||
defaultMonitor: addSeries.defaults.monitor,
|
||||
defaultQualityProfileId: addSeries.defaults.qualityProfileId,
|
||||
defaultLanguageProfileId: addSeries.defaults.languageProfileId,
|
||||
defaultSeriesType: addSeries.defaults.seriesType,
|
||||
defaultSeasonFolder: addSeries.defaults.seasonFolder,
|
||||
items: importSeries.items,
|
||||
isSmallScreen: dimensions.isSmallScreen,
|
||||
allSeries
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createMapDispatchToProps(dispatch, props) {
|
||||
return {
|
||||
onSeriesLookup(name, path) {
|
||||
dispatch(queueLookupSeries({
|
||||
name,
|
||||
path,
|
||||
term: name
|
||||
}));
|
||||
},
|
||||
|
||||
onSetImportSeriesValue(values) {
|
||||
dispatch(setImportSeriesValue(values));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps, createMapDispatchToProps)(ImportSeriesTable);
|
|
@ -1,52 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Link from 'Components/Link/Link';
|
||||
import ImportSeriesTitle from './ImportSeriesTitle';
|
||||
import styles from './ImportSeriesSearchResult.css';
|
||||
|
||||
class ImportSeriesSearchResult extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onPress = () => {
|
||||
this.props.onPress(this.props.tvdbId);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
title,
|
||||
year,
|
||||
network,
|
||||
isExistingSeries
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Link
|
||||
className={styles.series}
|
||||
onPress={this.onPress}
|
||||
>
|
||||
<ImportSeriesTitle
|
||||
title={title}
|
||||
year={year}
|
||||
network={network}
|
||||
isExistingSeries={isExistingSeries}
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImportSeriesSearchResult.propTypes = {
|
||||
tvdbId: PropTypes.number.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
year: PropTypes.number.isRequired,
|
||||
network: PropTypes.string,
|
||||
isExistingSeries: PropTypes.bool.isRequired,
|
||||
onPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default ImportSeriesSearchResult;
|
|
@ -1,17 +0,0 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createExistingSeriesSelector from 'Store/Selectors/createExistingSeriesSelector';
|
||||
import ImportSeriesSearchResult from './ImportSeriesSearchResult';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createExistingSeriesSelector(),
|
||||
(isExistingSeries) => {
|
||||
return {
|
||||
isExistingSeries
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps)(ImportSeriesSearchResult);
|
|
@ -1,50 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import Label from 'Components/Label';
|
||||
import styles from './ImportSeriesTitle.css';
|
||||
|
||||
function ImportSeriesTitle(props) {
|
||||
const {
|
||||
title,
|
||||
year,
|
||||
network,
|
||||
isExistingSeries
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div className={styles.titleContainer}>
|
||||
<div className={styles.title}>
|
||||
{title}
|
||||
|
||||
{
|
||||
!title.contains(year) &&
|
||||
<span className={styles.year}>({year})</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
{
|
||||
!!network &&
|
||||
<Label>{network}</Label>
|
||||
}
|
||||
|
||||
{
|
||||
isExistingSeries &&
|
||||
<Label
|
||||
kind={kinds.WARNING}
|
||||
>
|
||||
Existing
|
||||
</Label>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ImportSeriesTitle.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
year: PropTypes.number.isRequired,
|
||||
network: PropTypes.string,
|
||||
isExistingSeries: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
export default ImportSeriesTitle;
|
|
@ -1,30 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Route } from 'react-router-dom';
|
||||
import Switch from 'Components/Router/Switch';
|
||||
import ImportSeriesSelectFolderConnector from 'AddArtist/ImportSeries/SelectFolder/ImportSeriesSelectFolderConnector';
|
||||
import ImportSeriesConnector from 'AddArtist/ImportSeries/Import/ImportSeriesConnector';
|
||||
|
||||
class ImportSeries extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Switch>
|
||||
<Route
|
||||
exact={true}
|
||||
path="/add/import"
|
||||
component={ImportSeriesSelectFolderConnector}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/add/import/:rootFolderId"
|
||||
component={ImportSeriesConnector}
|
||||
/>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ImportSeries;
|
|
@ -1,46 +0,0 @@
|
|||
import React from 'react';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
|
||||
function SeriesMonitoringOptionsPopoverContent() {
|
||||
return (
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
title="All Episodes"
|
||||
data="Monitor all episodes except specials"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Future Episodes"
|
||||
data="Monitor episodes that have not aired yet"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Missing Episodes"
|
||||
data="Monitor episodes that do not have files or have not aired yet"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Existing Episodes"
|
||||
data="Monitor episodes that have files or have not aired yet"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="First Season"
|
||||
data="Monitor all episodes of the first season. All other seasons will be ignored"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Latest Season"
|
||||
data="Monitor all episodes of the latest season and future seasons"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="None"
|
||||
data="No episodes will be monitored."
|
||||
/>
|
||||
</DescriptionList>
|
||||
);
|
||||
}
|
||||
|
||||
export default SeriesMonitoringOptionsPopoverContent;
|
|
@ -1,26 +0,0 @@
|
|||
import React from 'react';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
|
||||
function SeriesTypePopoverContent() {
|
||||
return (
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
title="Anime"
|
||||
data="Episodes released using an absolute episode number"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Daily"
|
||||
data="Episodes released daily or less frequently that use year-month-day (2017-05-25)"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Standard"
|
||||
data="Episodes released with SxxEyy pattern"
|
||||
/>
|
||||
</DescriptionList>
|
||||
);
|
||||
}
|
||||
|
||||
export default SeriesTypePopoverContent;
|
Loading…
Add table
Add a link
Reference in a new issue