mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-10-29 23:12:39 +01:00
New: 'Seasons Monitored Status' Custom Filter to replace 'Has Unmonitored Season'
Closes #6896
This commit is contained in:
parent
a80f5b794b
commit
6dd85a5af9
@ -13,6 +13,7 @@ import LanguageFilterBuilderRowValue from './LanguageFilterBuilderRowValue';
|
||||
import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue';
|
||||
import QualityFilterBuilderRowValueConnector from './QualityFilterBuilderRowValueConnector';
|
||||
import QualityProfileFilterBuilderRowValueConnector from './QualityProfileFilterBuilderRowValueConnector';
|
||||
import SeasonsMonitoredStatusFilterBuilderRowValue from './SeasonsMonitoredStatusFilterBuilderRowValue';
|
||||
import SeriesFilterBuilderRowValue from './SeriesFilterBuilderRowValue';
|
||||
import SeriesStatusFilterBuilderRowValue from './SeriesStatusFilterBuilderRowValue';
|
||||
import SeriesTypeFilterBuilderRowValue from './SeriesTypeFilterBuilderRowValue';
|
||||
@ -79,6 +80,9 @@ function getRowValueConnector(selectedFilterBuilderProp) {
|
||||
case filterBuilderValueTypes.QUALITY_PROFILE:
|
||||
return QualityProfileFilterBuilderRowValueConnector;
|
||||
|
||||
case filterBuilderValueTypes.SEASONS_MONITORED_STATUS:
|
||||
return SeasonsMonitoredStatusFilterBuilderRowValue;
|
||||
|
||||
case filterBuilderValueTypes.SERIES:
|
||||
return SeriesFilterBuilderRowValue;
|
||||
|
||||
|
@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import FilterBuilderRowValue from './FilterBuilderRowValue';
|
||||
|
||||
const seasonsMonitoredStatusList = [
|
||||
{
|
||||
id: 'all',
|
||||
get name() {
|
||||
return translate('SeasonsMonitoredAll');
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'partial',
|
||||
get name() {
|
||||
return translate('SeasonsMonitoredPartial');
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'none',
|
||||
get name() {
|
||||
return translate('SeasonsMonitoredNone');
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
function SeasonsMonitoredStatusFilterBuilderRowValue(props) {
|
||||
return (
|
||||
<FilterBuilderRowValue
|
||||
tagList={seasonsMonitoredStatusList}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default SeasonsMonitoredStatusFilterBuilderRowValue;
|
@ -8,6 +8,7 @@ export const LANGUAGE = 'language';
|
||||
export const PROTOCOL = 'protocol';
|
||||
export const QUALITY = 'quality';
|
||||
export const QUALITY_PROFILE = 'qualityProfile';
|
||||
export const SEASONS_MONITORED_STATUS = 'seasonsMonitoredStatus';
|
||||
export const SERIES = 'series';
|
||||
export const SERIES_STATUS = 'seriesStatus';
|
||||
export const SERIES_TYPES = 'seriesType';
|
||||
|
@ -202,20 +202,33 @@ export const filterPredicates = {
|
||||
return predicate(hasMissingSeason, filterValue);
|
||||
},
|
||||
|
||||
hasUnmonitoredSeason: function(item, filterValue, type) {
|
||||
seasonsMonitoredStatus: function(item, filterValue, type) {
|
||||
const predicate = filterTypePredicates[type];
|
||||
const { seasons = [] } = item;
|
||||
|
||||
const hasUnmonitoredSeason = seasons.some((season) => {
|
||||
const {
|
||||
seasonNumber,
|
||||
monitored
|
||||
} = season;
|
||||
const { monitoredCount, unmonitoredCount } = seasons.reduce((acc, { seasonNumber, monitored }) => {
|
||||
if (seasonNumber <= 0) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return seasonNumber > 0 && !monitored;
|
||||
});
|
||||
if (monitored) {
|
||||
acc.monitoredCount++;
|
||||
} else {
|
||||
acc.unmonitoredCount++;
|
||||
}
|
||||
|
||||
return predicate(hasUnmonitoredSeason, filterValue);
|
||||
return acc;
|
||||
}, { monitoredCount: 0, unmonitoredCount: 0 });
|
||||
|
||||
let seasonsMonitoredStatus = 'partial';
|
||||
|
||||
if (monitoredCount === 0) {
|
||||
seasonsMonitoredStatus = 'none';
|
||||
} else if (unmonitoredCount === 0) {
|
||||
seasonsMonitoredStatus = 'all';
|
||||
}
|
||||
|
||||
return predicate(seasonsMonitoredStatus, filterValue);
|
||||
}
|
||||
};
|
||||
|
||||
@ -383,10 +396,10 @@ export const filterBuilderProps = [
|
||||
valueType: filterBuilderValueTypes.BOOL
|
||||
},
|
||||
{
|
||||
name: 'hasUnmonitoredSeason',
|
||||
label: () => translate('HasUnmonitoredSeason'),
|
||||
name: 'seasonsMonitoredStatus',
|
||||
label: () => translate('SeasonsMonitoredStatus'),
|
||||
type: filterBuilderTypes.EXACT,
|
||||
valueType: filterBuilderValueTypes.BOOL
|
||||
valueType: filterBuilderValueTypes.SEASONS_MONITORED_STATUS
|
||||
},
|
||||
{
|
||||
name: 'year',
|
||||
|
@ -0,0 +1,372 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore.Migration
|
||||
{
|
||||
[TestFixture]
|
||||
public class add_monitored_seasons_filterFixture : MigrationTest<add_monitored_seasons_filter>
|
||||
{
|
||||
[Test]
|
||||
public void equal_both_becomes_equal_every_option()
|
||||
{
|
||||
var filter = new FilterSettings210
|
||||
{
|
||||
key = "hasUnmonitoredSeason",
|
||||
value = new List<object> { true, false },
|
||||
type = "equal"
|
||||
};
|
||||
|
||||
var filtersJson = new List<FilterSettings210> { filter };
|
||||
|
||||
var filtersString = filtersJson.ToJson();
|
||||
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("CustomFilters").Row(new
|
||||
{
|
||||
Id = 1,
|
||||
Type = "series",
|
||||
Label = "Is Both",
|
||||
Filters = filtersString
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<FilterDefinition210>("SELECT * FROM \"CustomFilters\"");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().Type.Should().Be("series");
|
||||
items.First().Label.Should().Be("Is Both");
|
||||
|
||||
var filters = JsonConvert.DeserializeObject<List<FilterSettings210>>(items.First().Filters);
|
||||
filters[0].key.Should().Be("seasonsMonitoredStatus");
|
||||
filters[0].value.Should().BeEquivalentTo(new List<object> { "all", "partial", "none" });
|
||||
filters[0].type.Should().Be("equal");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void notEqual_both_becomes_notEqual_every_option()
|
||||
{
|
||||
var filter = new FilterSettings210
|
||||
{
|
||||
key = "hasUnmonitoredSeason",
|
||||
value = new List<object> { true, false },
|
||||
type = "notEqual"
|
||||
};
|
||||
|
||||
var filtersJson = new List<FilterSettings210> { filter };
|
||||
|
||||
var filtersString = filtersJson.ToJson();
|
||||
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("CustomFilters").Row(new
|
||||
{
|
||||
Id = 1,
|
||||
Type = "series",
|
||||
Label = "Is Both",
|
||||
Filters = filtersString
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<FilterDefinition210>("SELECT * FROM \"CustomFilters\"");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().Type.Should().Be("series");
|
||||
items.First().Label.Should().Be("Is Both");
|
||||
|
||||
var filters = JsonConvert.DeserializeObject<List<FilterSettings210>>(items.First().Filters);
|
||||
filters[0].key.Should().Be("seasonsMonitoredStatus");
|
||||
filters[0].value.Should().BeEquivalentTo(new List<object> { "all", "partial", "none" });
|
||||
filters[0].type.Should().Be("notEqual");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void equal_true_becomes_notEqual_all()
|
||||
{
|
||||
var filter = new FilterSettings210
|
||||
{
|
||||
key = "hasUnmonitoredSeason",
|
||||
value = new List<object> { true },
|
||||
type = "equal"
|
||||
};
|
||||
|
||||
var filtersJson = new List<FilterSettings210> { filter };
|
||||
|
||||
var filtersString = filtersJson.ToJson();
|
||||
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("CustomFilters").Row(new
|
||||
{
|
||||
Id = 1,
|
||||
Type = "series",
|
||||
Label = "Is Both",
|
||||
Filters = filtersString
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<FilterDefinition210>("SELECT * FROM \"CustomFilters\"");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().Type.Should().Be("series");
|
||||
items.First().Label.Should().Be("Is Both");
|
||||
|
||||
var filters = JsonConvert.DeserializeObject<List<FilterSettings210>>(items.First().Filters);
|
||||
filters[0].key.Should().Be("seasonsMonitoredStatus");
|
||||
filters[0].value.Should().BeEquivalentTo(new List<object> { "all" });
|
||||
filters[0].type.Should().Be("notEqual");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void notEqual_true_becomes_equal_all()
|
||||
{
|
||||
var filter = new FilterSettings210
|
||||
{
|
||||
key = "hasUnmonitoredSeason",
|
||||
value = new List<object> { true },
|
||||
type = "notEqual"
|
||||
};
|
||||
|
||||
var filtersJson = new List<FilterSettings210> { filter };
|
||||
|
||||
var filtersString = filtersJson.ToJson();
|
||||
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("CustomFilters").Row(new
|
||||
{
|
||||
Id = 1,
|
||||
Type = "series",
|
||||
Label = "Is Both",
|
||||
Filters = filtersString
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<FilterDefinition210>("SELECT * FROM \"CustomFilters\"");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().Type.Should().Be("series");
|
||||
items.First().Label.Should().Be("Is Both");
|
||||
|
||||
var filters = JsonConvert.DeserializeObject<List<FilterSettings210>>(items.First().Filters);
|
||||
filters[0].key.Should().Be("seasonsMonitoredStatus");
|
||||
filters[0].value.Should().BeEquivalentTo(new List<object> { "all" });
|
||||
filters[0].type.Should().Be("equal");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void equal_false_becomes_equal_all()
|
||||
{
|
||||
var filter = new FilterSettings210
|
||||
{
|
||||
key = "hasUnmonitoredSeason",
|
||||
value = new List<object> { false },
|
||||
type = "equal"
|
||||
};
|
||||
|
||||
var filtersJson = new List<FilterSettings210> { filter };
|
||||
|
||||
var filtersString = filtersJson.ToJson();
|
||||
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("CustomFilters").Row(new
|
||||
{
|
||||
Id = 1,
|
||||
Type = "series",
|
||||
Label = "Is Both",
|
||||
Filters = filtersString
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<FilterDefinition210>("SELECT * FROM \"CustomFilters\"");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().Type.Should().Be("series");
|
||||
items.First().Label.Should().Be("Is Both");
|
||||
|
||||
var filters = JsonConvert.DeserializeObject<List<FilterSettings210>>(items.First().Filters);
|
||||
filters[0].key.Should().Be("seasonsMonitoredStatus");
|
||||
filters[0].value.Should().BeEquivalentTo(new List<object> { "all" });
|
||||
filters[0].type.Should().Be("equal");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void notEqual_false_becomes_notEqual_all()
|
||||
{
|
||||
var filter = new FilterSettings210
|
||||
{
|
||||
key = "hasUnmonitoredSeason",
|
||||
value = new List<object> { false },
|
||||
type = "notEqual"
|
||||
};
|
||||
|
||||
var filtersJson = new List<FilterSettings210> { filter };
|
||||
|
||||
var filtersString = filtersJson.ToJson();
|
||||
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("CustomFilters").Row(new
|
||||
{
|
||||
Id = 1,
|
||||
Type = "series",
|
||||
Label = "Is Both",
|
||||
Filters = filtersString
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<FilterDefinition210>("SELECT * FROM \"CustomFilters\"");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().Type.Should().Be("series");
|
||||
items.First().Label.Should().Be("Is Both");
|
||||
|
||||
var filters = JsonConvert.DeserializeObject<List<FilterSettings210>>(items.First().Filters);
|
||||
filters[0].key.Should().Be("seasonsMonitoredStatus");
|
||||
filters[0].value.Should().BeEquivalentTo(new List<object> { "all" });
|
||||
filters[0].type.Should().Be("notEqual");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void missing_hasUnmonitored_unchanged()
|
||||
{
|
||||
var filter = new FilterSettings210
|
||||
{
|
||||
key = "monitored",
|
||||
value = new List<object> { false },
|
||||
type = "equal"
|
||||
};
|
||||
|
||||
var filtersJson = new List<FilterSettings210> { filter };
|
||||
|
||||
var filtersString = filtersJson.ToJson();
|
||||
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("CustomFilters").Row(new
|
||||
{
|
||||
Id = 1,
|
||||
Type = "series",
|
||||
Label = "Is Both",
|
||||
Filters = filtersString
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<FilterDefinition210>("SELECT * FROM \"CustomFilters\"");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().Type.Should().Be("series");
|
||||
items.First().Label.Should().Be("Is Both");
|
||||
|
||||
var filters = JsonConvert.DeserializeObject<List<FilterSettings210>>(items.First().Filters);
|
||||
filters[0].key.Should().Be("monitored");
|
||||
filters[0].value.Should().BeEquivalentTo(new List<object> { false });
|
||||
filters[0].type.Should().Be("equal");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void has_hasUnmonitored_not_in_first_entry()
|
||||
{
|
||||
var filter1 = new FilterSettings210
|
||||
{
|
||||
key = "monitored",
|
||||
value = new List<object> { false },
|
||||
type = "equal"
|
||||
};
|
||||
var filter2 = new FilterSettings210
|
||||
{
|
||||
key = "hasUnmonitoredSeason",
|
||||
value = new List<object> { true },
|
||||
type = "equal"
|
||||
};
|
||||
|
||||
var filtersJson = new List<FilterSettings210> { filter1, filter2 };
|
||||
|
||||
var filtersString = filtersJson.ToJson();
|
||||
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("CustomFilters").Row(new
|
||||
{
|
||||
Id = 1,
|
||||
Type = "series",
|
||||
Label = "Is Both",
|
||||
Filters = filtersString
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<FilterDefinition210>("SELECT * FROM \"CustomFilters\"");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().Type.Should().Be("series");
|
||||
items.First().Label.Should().Be("Is Both");
|
||||
|
||||
var filters = JsonConvert.DeserializeObject<List<FilterSettings210>>(items.First().Filters);
|
||||
filters[0].key.Should().Be("monitored");
|
||||
filters[0].value.Should().BeEquivalentTo(new List<object> { false });
|
||||
filters[0].type.Should().Be("equal");
|
||||
filters[1].key.Should().Be("seasonsMonitoredStatus");
|
||||
filters[1].value.Should().BeEquivalentTo(new List<object> { "all" });
|
||||
filters[1].type.Should().Be("notEqual");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void has_umonitored_is_empty()
|
||||
{
|
||||
var filter = new FilterSettings210
|
||||
{
|
||||
key = "hasUnmonitoredSeason",
|
||||
value = new List<object> { },
|
||||
type = "equal"
|
||||
};
|
||||
|
||||
var filtersJson = new List<FilterSettings210> { filter };
|
||||
|
||||
var filtersString = filtersJson.ToJson();
|
||||
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("CustomFilters").Row(new
|
||||
{
|
||||
Id = 1,
|
||||
Type = "series",
|
||||
Label = "Is Both",
|
||||
Filters = filtersString
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query<FilterDefinition210>("SELECT * FROM \"CustomFilters\"");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().Type.Should().Be("series");
|
||||
items.First().Label.Should().Be("Is Both");
|
||||
|
||||
var filters = JsonConvert.DeserializeObject<List<FilterSettings210>>(items.First().Filters);
|
||||
filters[0].key.Should().Be("seasonsMonitoredStatus");
|
||||
filters[0].value.Should().BeEquivalentTo(new List<object> { });
|
||||
filters[0].type.Should().Be("equal");
|
||||
}
|
||||
}
|
||||
|
||||
public class FilterDefinition210
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string Filters { get; set; }
|
||||
}
|
||||
|
||||
public class FilterSettings210
|
||||
{
|
||||
public string key { get; set; }
|
||||
public List<object> value { get; set; }
|
||||
public string type { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using Dapper;
|
||||
using FluentMigrator;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(210)]
|
||||
public class add_monitored_seasons_filter : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(ChangeHasUnmonitoredSeason);
|
||||
}
|
||||
|
||||
private void ChangeHasUnmonitoredSeason(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
var updated = new List<object>();
|
||||
using (var getUnmonitoredSeasonFilter = conn.CreateCommand())
|
||||
{
|
||||
getUnmonitoredSeasonFilter.Transaction = tran;
|
||||
getUnmonitoredSeasonFilter.CommandText = "SELECT \"Id\", \"Filters\" FROM \"CustomFilters\" WHERE \"Type\" = 'series'";
|
||||
|
||||
using (var reader = getUnmonitoredSeasonFilter.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = reader.GetInt32(0);
|
||||
var filters = JArray.Parse(reader.GetString(1));
|
||||
|
||||
foreach (var filter in filters)
|
||||
{
|
||||
if (filter["key"]?.ToString() == "hasUnmonitoredSeason")
|
||||
{
|
||||
var value = filter["value"].ToString();
|
||||
var type = filter["type"].ToString();
|
||||
|
||||
filter["key"] = "seasonsMonitoredStatus";
|
||||
|
||||
if (value.Contains("true") && value.Contains("false"))
|
||||
{
|
||||
filter["value"] = new JArray("all", "partial", "none");
|
||||
}
|
||||
else if (value.Contains("true"))
|
||||
{
|
||||
filter["type"] = type == "equal" ? "notEqual" : "equal";
|
||||
filter["value"] = new JArray("all");
|
||||
}
|
||||
else if (value.Contains("false"))
|
||||
{
|
||||
filter["value"] = new JArray("all");
|
||||
}
|
||||
else
|
||||
{
|
||||
filter["value"] = new JArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updated.Add(new
|
||||
{
|
||||
Filters = filters.ToJson(),
|
||||
Id = id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var updateSql = "UPDATE \"CustomFilters\" SET \"Filters\" = @Filters WHERE \"Id\" = @Id";
|
||||
conn.Execute(updateSql, updated, transaction: tran);
|
||||
}
|
||||
}
|
||||
}
|
@ -1784,6 +1784,10 @@
|
||||
"SeasonPremiere": "Season Premiere",
|
||||
"SeasonPremieresOnly": "Season Premieres Only",
|
||||
"Seasons": "Seasons",
|
||||
"SeasonsMonitoredAll": "All",
|
||||
"SeasonsMonitoredPartial": "Partial",
|
||||
"SeasonsMonitoredNone": "None",
|
||||
"SeasonsMonitoredStatus": "Seasons Monitored",
|
||||
"SecretToken": "Secret Token",
|
||||
"Security": "Security",
|
||||
"Seeders": "Seeders",
|
||||
|
Loading…
Reference in New Issue
Block a user