From 6dd85a5af931509b950ac418781fcb1521d2b08d Mon Sep 17 00:00:00 2001
From: jbstark <33739840+jbstark@users.noreply.github.com>
Date: Sun, 28 Jul 2024 16:57:22 -0700
Subject: [PATCH] New: 'Seasons Monitored Status' Custom Filter to replace 'Has
Unmonitored Season'
Closes #6896
---
.../Filter/Builder/FilterBuilderRow.js | 4 +
...onsMonitoredStatusFilterBuilderRowValue.js | 35 ++
.../Helpers/Props/filterBuilderValueTypes.js | 1 +
frontend/src/Store/Actions/seriesActions.js | 37 +-
...210_add_monitored_seasons_filterFixture.cs | 372 ++++++++++++++++++
.../210_add_monitored_seasons_filter.cs | 76 ++++
src/NzbDrone.Core/Localization/Core/en.json | 4 +
7 files changed, 517 insertions(+), 12 deletions(-)
create mode 100644 frontend/src/Components/Filter/Builder/SeasonsMonitoredStatusFilterBuilderRowValue.js
create mode 100644 src/NzbDrone.Core.Test/Datastore/Migration/210_add_monitored_seasons_filterFixture.cs
create mode 100644 src/NzbDrone.Core/Datastore/Migration/210_add_monitored_seasons_filter.cs
diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRow.js b/frontend/src/Components/Filter/Builder/FilterBuilderRow.js
index 46a38a258..e12f8c40f 100644
--- a/frontend/src/Components/Filter/Builder/FilterBuilderRow.js
+++ b/frontend/src/Components/Filter/Builder/FilterBuilderRow.js
@@ -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;
diff --git a/frontend/src/Components/Filter/Builder/SeasonsMonitoredStatusFilterBuilderRowValue.js b/frontend/src/Components/Filter/Builder/SeasonsMonitoredStatusFilterBuilderRowValue.js
new file mode 100644
index 000000000..b84260e3c
--- /dev/null
+++ b/frontend/src/Components/Filter/Builder/SeasonsMonitoredStatusFilterBuilderRowValue.js
@@ -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 (
+
+ );
+}
+
+export default SeasonsMonitoredStatusFilterBuilderRowValue;
diff --git a/frontend/src/Helpers/Props/filterBuilderValueTypes.js b/frontend/src/Helpers/Props/filterBuilderValueTypes.js
index 1f4227779..d9a5d58c7 100644
--- a/frontend/src/Helpers/Props/filterBuilderValueTypes.js
+++ b/frontend/src/Helpers/Props/filterBuilderValueTypes.js
@@ -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';
diff --git a/frontend/src/Store/Actions/seriesActions.js b/frontend/src/Store/Actions/seriesActions.js
index 3aa9b7237..c18104065 100644
--- a/frontend/src/Store/Actions/seriesActions.js
+++ b/frontend/src/Store/Actions/seriesActions.js
@@ -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',
diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/210_add_monitored_seasons_filterFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/210_add_monitored_seasons_filterFixture.cs
new file mode 100644
index 000000000..94bd7fb68
--- /dev/null
+++ b/src/NzbDrone.Core.Test/Datastore/Migration/210_add_monitored_seasons_filterFixture.cs
@@ -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
+ {
+ [Test]
+ public void equal_both_becomes_equal_every_option()
+ {
+ var filter = new FilterSettings210
+ {
+ key = "hasUnmonitoredSeason",
+ value = new List