New: Option to search for upgrades when adding new series

Closes #712
This commit is contained in:
Mark McDowall 2020-09-09 00:58:55 -07:00
parent accf8d5c81
commit 5a42d2a36d
9 changed files with 87 additions and 25 deletions

View File

@ -25,23 +25,24 @@
margin-left: 8px;
}
.searchForMissingEpisodesLabelContainer {
.searchLabelContainer {
display: flex;
justify-content: flex-end;
margin-top: 2px;
}
.searchForMissingEpisodesLabel {
.searchLabel {
margin-right: 8px;
font-weight: normal;
}
.searchForMissingEpisodesContainer {
.searchInputContainer {
composes: container from '~Components/Form/CheckInput.css';
flex: 0 1 0;
}
.searchForMissingEpisodesInput {
.searchInput {
composes: input from '~Components/Form/CheckInput.css';
margin-top: 0;

View File

@ -31,7 +31,8 @@ class AddNewSeriesModalContent extends Component {
seriesType: props.initialSeriesType === seriesTypes.STANDARD ?
props.seriesType.value :
props.initialSeriesType,
searchForMissingEpisodes: false
searchForMissingEpisodes: false,
searchForCutoffUnmetEpisodes: false
};
}
@ -48,6 +49,10 @@ class AddNewSeriesModalContent extends Component {
this.setState({ searchForMissingEpisodes: value });
}
onSearchForCutoffUnmetEpisodesChange = ({ value }) => {
this.setState({ searchForCutoffUnmetEpisodes: value });
}
onQualityProfileIdChange = ({ value }) => {
this.props.onInputChange({ name: 'qualityProfileId', value: parseInt(value) });
}
@ -59,10 +64,15 @@ class AddNewSeriesModalContent extends Component {
onAddSeriesPress = () => {
const {
searchForMissingEpisodes,
searchForCutoffUnmetEpisodes,
seriesType
} = this.state;
this.props.onAddSeriesPress(searchForMissingEpisodes, seriesType);
this.props.onAddSeriesPress(
searchForMissingEpisodes,
searchForCutoffUnmetEpisodes,
seriesType
);
}
//
@ -91,6 +101,11 @@ class AddNewSeriesModalContent extends Component {
...otherProps
} = this.props;
const {
searchForMissingEpisodes,
searchForCutoffUnmetEpisodes
} = this.state;
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
@ -246,19 +261,35 @@ class AddNewSeriesModalContent extends Component {
</ModalBody>
<ModalFooter className={styles.modalFooter}>
<label className={styles.searchForMissingEpisodesLabelContainer}>
<span className={styles.searchForMissingEpisodesLabel}>
<div>
<label className={styles.searchLabelContainer}>
<span className={styles.searchLabel}>
Start search for missing episodes
</span>
</span>
<CheckInput
containerClassName={styles.searchForMissingEpisodesContainer}
className={styles.searchForMissingEpisodesInput}
name="searchForMissingEpisodes"
value={this.state.searchForMissingEpisodes}
onChange={this.onSearchForMissingEpisodesChange}
/>
</label>
<CheckInput
containerClassName={styles.searchInputContainer}
className={styles.searchInput}
name="searchForMissingEpisodes"
value={searchForMissingEpisodes}
onChange={this.onSearchForMissingEpisodesChange}
/>
</label>
<label className={styles.searchLabelContainer}>
<span className={styles.searchLabel}>
Start search for cutoff unmet episodes
</span>
<CheckInput
containerClassName={styles.searchInputContainer}
className={styles.searchInput}
name="searchForCutoffUnmetEpisodes"
value={searchForCutoffUnmetEpisodes}
onChange={this.onSearchForCutoffUnmetEpisodesChange}
/>
</label>
</div>
<SpinnerButton
className={styles.addButton}

View File

@ -55,7 +55,7 @@ class AddNewSeriesModalContentConnector extends Component {
this.props.setAddSeriesDefault({ [name]: value });
}
onAddSeriesPress = (searchForMissingEpisodes, seriesType) => {
onAddSeriesPress = (searchForMissingEpisodes, searchForCutoffUnmetEpisodes, seriesType) => {
const {
tvdbId,
rootFolderPath,
@ -75,7 +75,8 @@ class AddNewSeriesModalContentConnector extends Component {
seriesType,
seasonFolder: seasonFolder.value,
tags: tags.value,
searchForMissingEpisodes
searchForMissingEpisodes,
searchForCutoffUnmetEpisodes
});
}

View File

@ -8,12 +8,14 @@ function getNewSeries(series, payload) {
seriesType,
seasonFolder,
tags,
searchForMissingEpisodes = false
searchForMissingEpisodes = false,
searchForCutoffUnmetEpisodes = false
} = payload;
const addOptions = {
monitor,
searchForMissingEpisodes
searchForMissingEpisodes,
searchForCutoffUnmetEpisodes
};
series.addOptions = addOptions;

View File

@ -159,7 +159,8 @@ namespace NzbDrone.Core.IndexerSearch
if (message.SeriesId.HasValue)
{
pagingSpec.FilterExpressions.Add(v => v.SeriesId == message.SeriesId.Value);
var seriesId = message.SeriesId.Value;
pagingSpec.FilterExpressions.Add(v => v.SeriesId == seriesId);
}
if (monitored)

View File

@ -7,5 +7,14 @@ namespace NzbDrone.Core.IndexerSearch
public int SeriesId { get; set; }
public override bool SendUpdatesToClient => true;
public SeriesSearchCommand()
{
}
public SeriesSearchCommand(int seriesId)
{
SeriesId = seriesId;
}
}
}

View File

@ -3,5 +3,6 @@
public class AddSeriesOptions : MonitoringOptions
{
public bool SearchForMissingEpisodes { get; set; }
public bool SearchForCutoffUnmetEpisodes { get; set; }
}
}

View File

@ -206,7 +206,7 @@ namespace NzbDrone.Core.Tv
private SortBuilder<Episode> EpisodesWhereCutoffUnmetQuery(PagingSpec<Episode> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff, List<LanguagesBelowCutoff> languagesBelowCutoff, int startingSeasonNumber)
{
return Query.Join<Episode, Series>(JoinType.Inner, e => e.Series, (e, s) => e.SeriesId == s.Id)
.Join<Episode, EpisodeFile>(JoinType.Left, e => e.EpisodeFile, (e, s) => e.EpisodeFileId == s.Id)
.Join<Episode, EpisodeFile>(JoinType.Left, e => e.EpisodeFile, (e, f) => e.EpisodeFileId == f.Id)
.Where(pagingSpec.FilterExpressions.FirstOrDefault())
.AndWhere(e => e.EpisodeFileId != 0)
.AndWhere(e => e.SeasonNumber >= startingSeasonNumber)

View File

@ -40,9 +40,25 @@ namespace NzbDrone.Core.Tv
_logger.Info("[{0}] was recently added, performing post-add actions", series.Title);
_episodeMonitoredService.SetEpisodeMonitoredStatus(series, series.AddOptions);
if (series.AddOptions.SearchForMissingEpisodes)
// If both options are enabled search for the whole series, which will only include monitored episodes.
// This way multiple searches for the same season are skipped, though a season that can't be upgraded may be
// searched, but the logs will be more explicit.
if (series.AddOptions.SearchForMissingEpisodes && series.AddOptions.SearchForCutoffUnmetEpisodes)
{
_commandQueueManager.Push(new MissingEpisodeSearchCommand(series.Id));
_commandQueueManager.Push(new SeriesSearchCommand(series.Id));
}
else
{
if (series.AddOptions.SearchForMissingEpisodes)
{
_commandQueueManager.Push(new MissingEpisodeSearchCommand(series.Id));
}
if (series.AddOptions.SearchForCutoffUnmetEpisodes)
{
_commandQueueManager.Push(new CutoffUnmetEpisodeSearchCommand(series.Id));
}
}
series.AddOptions = null;