(cherry picked from commit c51ae664aa6e6f5330be67e68476af76c55352f5)pull/2804/head
parent
d0fd0024e3
commit
2318c43536
@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
function ArtistMonitorNewItemsOptionsPopoverContent() {
|
||||
return (
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
title={translate('AllAlbums')}
|
||||
data="Monitor all new albums"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title={translate('NewAlbums')}
|
||||
data="Monitor new albums released after the newest existing album"
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title={translate('None')}
|
||||
data="Don't monitor any new albums"
|
||||
/>
|
||||
</DescriptionList>
|
||||
);
|
||||
}
|
||||
|
||||
export default ArtistMonitorNewItemsOptionsPopoverContent;
|
@ -0,0 +1,149 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import Button from 'Components/Link/Button';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
const NO_CHANGE = 'noChange';
|
||||
|
||||
class MonitoringOptionsModalContent extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
monitor: NO_CHANGE
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const {
|
||||
isSaving,
|
||||
saveError
|
||||
} = prevProps;
|
||||
|
||||
if (prevProps.isSaving && !isSaving && !saveError) {
|
||||
this.setState({
|
||||
monitor: NO_CHANGE
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onInputChange = ({ name, value }) => {
|
||||
this.setState({ [name]: value });
|
||||
};
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onSavePress = () => {
|
||||
const {
|
||||
onSavePress,
|
||||
isSaving
|
||||
} = this.props;
|
||||
const {
|
||||
monitor
|
||||
} = this.state;
|
||||
|
||||
if (monitor !== NO_CHANGE) {
|
||||
onSavePress({ monitor });
|
||||
}
|
||||
|
||||
if (!isSaving) {
|
||||
this.onModalClose();
|
||||
}
|
||||
};
|
||||
|
||||
onModalClose = () => {
|
||||
this.props.onModalClose();
|
||||
};
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
isSaving,
|
||||
onInputChange,
|
||||
onModalClose,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
monitor
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
{translate('MonitorAlbum')}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<Alert kind={kinds.INFO}>
|
||||
<div>
|
||||
{translate('MonitorAlbumExistingOnlyWarning')}
|
||||
</div>
|
||||
</Alert>
|
||||
|
||||
<Form {...otherProps}>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Monitoring')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.MONITOR_ALBUMS_SELECT}
|
||||
name="monitor"
|
||||
value={monitor}
|
||||
includeNoChange={true}
|
||||
onChange={this.onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
{translate('Cancel')}
|
||||
</Button>
|
||||
|
||||
<SpinnerButton
|
||||
isSpinning={isSaving}
|
||||
onPress={this.onSavePress}
|
||||
>
|
||||
{translate('Save')}
|
||||
</SpinnerButton>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MonitoringOptionsModalContent.propTypes = {
|
||||
authorId: PropTypes.number.isRequired,
|
||||
saveError: PropTypes.object,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
onInputChange: PropTypes.func.isRequired,
|
||||
onSavePress: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
MonitoringOptionsModalContent.defaultProps = {
|
||||
isSaving: false
|
||||
};
|
||||
|
||||
export default MonitoringOptionsModalContent;
|
@ -0,0 +1,50 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import monitorNewItemsOptions from 'Utilities/Artist/monitorNewItemsOptions';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
function MonitorNewItemsSelectInput(props) {
|
||||
const {
|
||||
includeNoChange,
|
||||
includeMixed,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const values = [...monitorNewItemsOptions];
|
||||
|
||||
if (includeNoChange) {
|
||||
values.unshift({
|
||||
key: 'noChange',
|
||||
value: 'No Change',
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
||||
if (includeMixed) {
|
||||
values.unshift({
|
||||
key: 'mixed',
|
||||
value: '(Mixed)',
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<SelectInput
|
||||
values={values}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
MonitorNewItemsSelectInput.propTypes = {
|
||||
includeNoChange: PropTypes.bool.isRequired,
|
||||
includeMixed: PropTypes.bool.isRequired,
|
||||
onChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
MonitorNewItemsSelectInput.defaultProps = {
|
||||
includeNoChange: false,
|
||||
includeMixed: false
|
||||
};
|
||||
|
||||
export default MonitorNewItemsSelectInput;
|
@ -0,0 +1,7 @@
|
||||
const monitorNewItemsOptions = [
|
||||
{ key: 'all', value: 'All Albums' },
|
||||
{ key: 'none', value: 'None' },
|
||||
{ key: 'new', value: 'New' }
|
||||
];
|
||||
|
||||
export default monitorNewItemsOptions;
|
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.AlbumTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class MonitorNewAlbumServiceFixture : CoreTest<MonitorNewAlbumService>
|
||||
{
|
||||
private List<Album> _albums;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_albums = Builder<Album>.CreateListOfSize(4)
|
||||
.All()
|
||||
.With(e => e.Monitored = true)
|
||||
.With(e => e.ReleaseDate = DateTime.UtcNow.AddDays(-7))
|
||||
|
||||
//Future
|
||||
.TheFirst(1)
|
||||
.With(e => e.ReleaseDate = DateTime.UtcNow.AddDays(7))
|
||||
|
||||
//Future/TBA
|
||||
.TheNext(1)
|
||||
.With(e => e.ReleaseDate = null)
|
||||
.Build()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_monitor_with_all()
|
||||
{
|
||||
foreach (var album in _albums)
|
||||
{
|
||||
Subject.ShouldMonitorNewAlbum(album, _albums, NewItemMonitorTypes.All).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_monitor_with_none()
|
||||
{
|
||||
foreach (var album in _albums)
|
||||
{
|
||||
Subject.ShouldMonitorNewAlbum(album, _albums, NewItemMonitorTypes.None).Should().BeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_only_monitor_new_with_new()
|
||||
{
|
||||
Subject.ShouldMonitorNewAlbum(_albums[0], _albums, NewItemMonitorTypes.New).Should().BeTrue();
|
||||
|
||||
foreach (var album in _albums.Skip(1))
|
||||
{
|
||||
Subject.ShouldMonitorNewAlbum(album, _albums, NewItemMonitorTypes.New).Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(56)]
|
||||
public class AddNewItemMonitorType : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Artists").AddColumn("MonitorNewItems").AsInt32().WithDefaultValue(0);
|
||||
Alter.Table("RootFolders").AddColumn("DefaultNewItemMonitorOption").AsInt32().WithDefaultValue(0);
|
||||
Alter.Table("ImportLists").AddColumn("MonitorNewItems").AsInt32().WithDefaultValue(0);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public enum MonitorTypes
|
||||
{
|
||||
All,
|
||||
Future,
|
||||
Missing,
|
||||
Existing,
|
||||
Latest,
|
||||
First,
|
||||
None,
|
||||
Unknown
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public enum NewItemMonitorTypes
|
||||
{
|
||||
All,
|
||||
None,
|
||||
New
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public interface IMonitorNewAlbumService
|
||||
{
|
||||
bool ShouldMonitorNewAlbum(Album addedAlbum, List<Album> existingAlbums, NewItemMonitorTypes monitorNewItems);
|
||||
}
|
||||
|
||||
public class MonitorNewAlbumService : IMonitorNewAlbumService
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MonitorNewAlbumService(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public bool ShouldMonitorNewAlbum(Album addedAlbum, List<Album> existingAlbums, NewItemMonitorTypes monitorNewItems)
|
||||
{
|
||||
if (monitorNewItems == NewItemMonitorTypes.None)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (monitorNewItems == NewItemMonitorTypes.All)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (monitorNewItems == NewItemMonitorTypes.New)
|
||||
{
|
||||
var newest = existingAlbums.OrderByDescending(x => x.ReleaseDate ?? DateTime.MinValue).FirstOrDefault()?.ReleaseDate ?? DateTime.MinValue;
|
||||
|
||||
return (addedAlbum.ReleaseDate ?? DateTime.MinValue) >= newest;
|
||||
}
|
||||
|
||||
throw new NotImplementedException($"Unknown new item monitor type {monitorNewItems}");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue