From 25abeb8c9c267218f66e449fff9eab377615af42 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 9 Jul 2014 22:59:23 -0700 Subject: [PATCH] Various anime improvements Series type is persisted in the client New: Warning in UI if anime episode doesn't have an absolute episode number New: If series type is changed the series will be rescanned New: Update scene mappings when series is refreshed --- .../Scene/SceneMappingService.cs | 10 ++++--- src/NzbDrone.Core/NzbDrone.Core.csproj | 1 + .../Tv/Events/SeriesEditedEvent.cs | 4 ++- src/NzbDrone.Core/Tv/RefreshSeriesService.cs | 1 - src/NzbDrone.Core/Tv/SeriesEditedService.cs | 27 +++++++++++++++++++ src/NzbDrone.Core/Tv/SeriesService.cs | 2 +- src/UI/AddSeries/SearchResultView.js | 19 ++++++++++--- src/UI/Cells/cells.less | 9 +++++++ src/UI/Config.js | 9 ++++--- src/UI/Series/Details/EpisodeWarningCell.js | 27 +++++++++++++++++++ src/UI/Series/Details/SeasonLayout.js | 9 +++++++ src/UI/Shared/Grid/HeaderCell.js | 4 +++ 12 files changed, 108 insertions(+), 14 deletions(-) create mode 100644 src/NzbDrone.Core/Tv/SeriesEditedService.cs create mode 100644 src/UI/Series/Details/EpisodeWarningCell.js diff --git a/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs b/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs index 8da47ab05..fe112a3e0 100644 --- a/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs +++ b/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs @@ -8,6 +8,7 @@ using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Parser; using System.Collections.Generic; +using NzbDrone.Core.Tv.Events; namespace NzbDrone.Core.DataAugmentation.Scene { @@ -21,6 +22,7 @@ namespace NzbDrone.Core.DataAugmentation.Scene public class SceneMappingService : ISceneMappingService, IHandleAsync, + IHandle, IExecute { private readonly ISceneMappingRepository _repository; @@ -80,9 +82,6 @@ namespace NzbDrone.Core.DataAugmentation.Scene public Nullable GetSeasonNumber(string title) { - //TODO: we should be able to override xem aliases with ones from services - //Example Fairy Tail - Alias is assigned to season 2 (anidb), but we're still using tvdb for everything - var mapping = _gettvdbIdCache.Find(title.CleanSeriesTitle()); if (mapping == null) @@ -155,6 +154,11 @@ namespace NzbDrone.Core.DataAugmentation.Scene UpdateMappings(); } + public void Handle(SeriesRefreshStartingEvent message) + { + UpdateMappings(); + } + public void Execute(UpdateSceneMappingCommand message) { UpdateMappings(); diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index f78805864..4638cedc3 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -595,6 +595,7 @@ + diff --git a/src/NzbDrone.Core/Tv/Events/SeriesEditedEvent.cs b/src/NzbDrone.Core/Tv/Events/SeriesEditedEvent.cs index 33371a4e7..a37a6c902 100644 --- a/src/NzbDrone.Core/Tv/Events/SeriesEditedEvent.cs +++ b/src/NzbDrone.Core/Tv/Events/SeriesEditedEvent.cs @@ -5,10 +5,12 @@ namespace NzbDrone.Core.Tv.Events public class SeriesEditedEvent : IEvent { public Series Series { get; private set; } + public Series OldSeries { get; private set; } - public SeriesEditedEvent(Series series) + public SeriesEditedEvent(Series series, Series oldSeries) { Series = series; + OldSeries = oldSeries; } } } \ No newline at end of file diff --git a/src/NzbDrone.Core/Tv/RefreshSeriesService.cs b/src/NzbDrone.Core/Tv/RefreshSeriesService.cs index 04daacc3e..3dcc88731 100644 --- a/src/NzbDrone.Core/Tv/RefreshSeriesService.cs +++ b/src/NzbDrone.Core/Tv/RefreshSeriesService.cs @@ -6,7 +6,6 @@ using NLog; using NzbDrone.Core.DataAugmentation.DailySeries; using NzbDrone.Core.Instrumentation.Extensions; using NzbDrone.Core.MediaFiles; -using NzbDrone.Core.MediaFiles.Commands; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.MetadataSource; diff --git a/src/NzbDrone.Core/Tv/SeriesEditedService.cs b/src/NzbDrone.Core/Tv/SeriesEditedService.cs new file mode 100644 index 000000000..faa6d6e35 --- /dev/null +++ b/src/NzbDrone.Core/Tv/SeriesEditedService.cs @@ -0,0 +1,27 @@ +using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.Tv.Commands; +using NzbDrone.Core.Tv.Events; + +namespace NzbDrone.Core.Tv +{ + public class SeriesEditedService : IHandle + { + private readonly CommandExecutor _commandExecutor; + + public SeriesEditedService(CommandExecutor commandExecutor) + { + _commandExecutor = commandExecutor; + } + + public void Handle(SeriesEditedEvent message) + { + //TODO: Refresh if path has changed (also move files) + + if (message.Series.SeriesType != message.OldSeries.SeriesType) + { + _commandExecutor.PublishCommandAsync(new RefreshSeriesCommand(message.Series.Id)); + } + } + } +} diff --git a/src/NzbDrone.Core/Tv/SeriesService.cs b/src/NzbDrone.Core/Tv/SeriesService.cs index 234fc26c5..f48e900b7 100644 --- a/src/NzbDrone.Core/Tv/SeriesService.cs +++ b/src/NzbDrone.Core/Tv/SeriesService.cs @@ -191,7 +191,7 @@ namespace NzbDrone.Core.Tv } var updatedSeries = _seriesRepository.Update(series); - _eventAggregator.PublishEvent(new SeriesEditedEvent(updatedSeries)); + _eventAggregator.PublishEvent(new SeriesEditedEvent(updatedSeries, storedSeries)); return updatedSeries; } diff --git a/src/UI/AddSeries/SearchResultView.js b/src/UI/AddSeries/SearchResultView.js index 6ed91487b..cb9e80612 100644 --- a/src/UI/AddSeries/SearchResultView.js +++ b/src/UI/AddSeries/SearchResultView.js @@ -42,10 +42,11 @@ define( }, events: { - 'click .x-add' : '_addSeries', - 'change .x-quality-profile': '_qualityProfileChanged', - 'change .x-root-folder' : '_rootFolderChanged', - 'change .x-season-folder' : '_seasonFolderChanged' + 'click .x-add' : '_addSeries', + 'change .x-quality-profile' : '_qualityProfileChanged', + 'change .x-root-folder' : '_rootFolderChanged', + 'change .x-season-folder' : '_seasonFolderChanged', + 'change .x-series-type' : '_seriesTypeChanged' }, initialize: function () { @@ -67,6 +68,7 @@ define( var defaultQuality = Config.getValue(Config.Keys.DefaultQualityProfileId); var defaultRoot = Config.getValue(Config.Keys.DefaultRootFolderId); var useSeasonFolder = Config.getValueBoolean(Config.Keys.UseSeasonFolder, true); + var defaultSeriesType = Config.getValueBoolean(Config.Keys.DefaultSeriesType, true); if (QualityProfiles.get(defaultQuality)) { this.ui.qualityProfile.val(defaultQuality); @@ -77,6 +79,7 @@ define( } this.ui.seasonFolder.prop('checked', useSeasonFolder); + this.ui.rootFolder.val(defaultSeriesType); var minSeasonNotZero = _.min(_.reject(this.model.get('seasons'), { seasonNumber: 0 }), 'seasonNumber'); @@ -117,6 +120,10 @@ define( else if (options.key === Config.Keys.UseSeasonFolder) { this.ui.seasonFolder.prop('checked', options.value); } + + else if (options.key === Config.Keys.DefaultSeriesType) { + this.ui.seriesType.val(options.value); + } }, _qualityProfileChanged: function () { @@ -139,6 +146,10 @@ define( } }, + _seriesTypeChanged: function () { + Config.setValue(Config.Keys.DefaultSeriesType, this.ui.seriesType.val()); + }, + _setRootFolder: function (options) { vent.trigger(vent.Commands.CloseModalCommand); this.ui.rootFolder.val(options.model.id); diff --git a/src/UI/Cells/cells.less b/src/UI/Cells/cells.less index 98c5fbf3a..1a38b3865 100644 --- a/src/UI/Cells/cells.less +++ b/src/UI/Cells/cells.less @@ -172,3 +172,12 @@ td.delete-episode-file-cell { .backup-type-cell { width : 20px; } + +.table>tbody>tr>td, .table>thead>tr>th { + + &.episode-warning-cell { + width : 1px; + padding-left : 0px; + padding-right : 0px; + } +} diff --git a/src/UI/Config.js b/src/UI/Config.js index 9770265e7..245ac59ae 100644 --- a/src/UI/Config.js +++ b/src/UI/Config.js @@ -8,10 +8,11 @@ define( ConfigUpdatedEvent: 'ConfigUpdatedEvent' }, Keys : { - DefaultQualityProfileId: 'DefaultQualityProfileId', - DefaultRootFolderId : 'DefaultRootFolderId', - UseSeasonFolder : 'UseSeasonFolder', - AdvancedSettings : 'advancedSettings' + DefaultQualityProfileId : 'DefaultQualityProfileId', + DefaultRootFolderId : 'DefaultRootFolderId', + UseSeasonFolder : 'UseSeasonFolder', + DefaultSeriesType : 'DefaultSeriesType', + AdvancedSettings : 'advancedSettings' }, getValueBoolean: function (key, defaultValue) { diff --git a/src/UI/Series/Details/EpisodeWarningCell.js b/src/UI/Series/Details/EpisodeWarningCell.js new file mode 100644 index 000000000..ab80a9e4c --- /dev/null +++ b/src/UI/Series/Details/EpisodeWarningCell.js @@ -0,0 +1,27 @@ + 'use strict'; + +define( + [ + 'Cells/NzbDroneCell', + 'Series/SeriesCollection' + ], function (NzbDroneCell, SeriesCollection) { + return NzbDroneCell.extend({ + + className: 'episode-warning-cell', + + render: function () { + + this.$el.empty(); + + if (SeriesCollection.get(this.model.get('seriesId')).get('seriesType') === 'anime') { + + if (this.model.get('seasonNumber') > 0 && this.model.get('absoluteEpisodeNumber') === 0) { + this.$el.html(''); + } + } + + this.delegateEvents(); + return this; + } + }); + }); diff --git a/src/UI/Series/Details/SeasonLayout.js b/src/UI/Series/Details/SeasonLayout.js index 3fb874894..0a11225fb 100644 --- a/src/UI/Series/Details/SeasonLayout.js +++ b/src/UI/Series/Details/SeasonLayout.js @@ -10,6 +10,7 @@ define( 'Cells/EpisodeStatusCell', 'Cells/EpisodeActionsCell', 'Series/Details/EpisodeNumberCell', + 'Series/Details/EpisodeWarningCell', 'Commands/CommandController', 'moment', 'underscore', @@ -23,6 +24,7 @@ define( EpisodeStatusCell, EpisodeActionsCell, EpisodeNumberCell, + EpisodeWarningCell, CommandController, Moment, _, @@ -64,6 +66,13 @@ define( label: '#', cell : EpisodeNumberCell }, + { + name : 'this', + label : '', + cell : EpisodeWarningCell, + sortable : false, + className : 'episode-warning-cell' + }, { name : 'this', label : 'Title', diff --git a/src/UI/Shared/Grid/HeaderCell.js b/src/UI/Shared/Grid/HeaderCell.js index 7f0b71cde..b1ac56279 100644 --- a/src/UI/Shared/Grid/HeaderCell.js +++ b/src/UI/Shared/Grid/HeaderCell.js @@ -35,6 +35,10 @@ define( //Do we need this? this.$el.addClass(column.get('name')); + if (column.has('className')) { + this.$el.addClass(column.get('className')); + } + this.delegateEvents(); this.direction(column.get('direction'));