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
This commit is contained in:
Mark McDowall 2014-07-09 22:59:23 -07:00
parent 86936303dd
commit 25abeb8c9c
12 changed files with 108 additions and 14 deletions

View File

@ -8,6 +8,7 @@ using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Tv.Events;
namespace NzbDrone.Core.DataAugmentation.Scene namespace NzbDrone.Core.DataAugmentation.Scene
{ {
@ -21,6 +22,7 @@ namespace NzbDrone.Core.DataAugmentation.Scene
public class SceneMappingService : ISceneMappingService, public class SceneMappingService : ISceneMappingService,
IHandleAsync<ApplicationStartedEvent>, IHandleAsync<ApplicationStartedEvent>,
IHandle<SeriesRefreshStartingEvent>,
IExecute<UpdateSceneMappingCommand> IExecute<UpdateSceneMappingCommand>
{ {
private readonly ISceneMappingRepository _repository; private readonly ISceneMappingRepository _repository;
@ -80,9 +82,6 @@ namespace NzbDrone.Core.DataAugmentation.Scene
public Nullable<Int32> GetSeasonNumber(string title) public Nullable<Int32> 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()); var mapping = _gettvdbIdCache.Find(title.CleanSeriesTitle());
if (mapping == null) if (mapping == null)
@ -155,6 +154,11 @@ namespace NzbDrone.Core.DataAugmentation.Scene
UpdateMappings(); UpdateMappings();
} }
public void Handle(SeriesRefreshStartingEvent message)
{
UpdateMappings();
}
public void Execute(UpdateSceneMappingCommand message) public void Execute(UpdateSceneMappingCommand message)
{ {
UpdateMappings(); UpdateMappings();

View File

@ -595,6 +595,7 @@
<Compile Include="Tv\Commands\RefreshSeriesCommand.cs" /> <Compile Include="Tv\Commands\RefreshSeriesCommand.cs" />
<Compile Include="Tv\Ratings.cs" /> <Compile Include="Tv\Ratings.cs" />
<Compile Include="Tv\RefreshEpisodeService.cs" /> <Compile Include="Tv\RefreshEpisodeService.cs" />
<Compile Include="Tv\SeriesEditedService.cs" />
<Compile Include="Tv\SeriesRepository.cs" /> <Compile Include="Tv\SeriesRepository.cs" />
<Compile Include="Qualities\QualityModel.cs" /> <Compile Include="Qualities\QualityModel.cs" />
<Compile Include="Download\Clients\Sabnzbd\SabnzbdHistoryItem.cs" /> <Compile Include="Download\Clients\Sabnzbd\SabnzbdHistoryItem.cs" />

View File

@ -5,10 +5,12 @@ namespace NzbDrone.Core.Tv.Events
public class SeriesEditedEvent : IEvent public class SeriesEditedEvent : IEvent
{ {
public Series Series { get; private set; } public Series Series { get; private set; }
public Series OldSeries { get; private set; }
public SeriesEditedEvent(Series series) public SeriesEditedEvent(Series series, Series oldSeries)
{ {
Series = series; Series = series;
OldSeries = oldSeries;
} }
} }
} }

View File

@ -6,7 +6,6 @@ using NLog;
using NzbDrone.Core.DataAugmentation.DailySeries; using NzbDrone.Core.DataAugmentation.DailySeries;
using NzbDrone.Core.Instrumentation.Extensions; using NzbDrone.Core.Instrumentation.Extensions;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.Commands;
using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.MetadataSource; using NzbDrone.Core.MetadataSource;

View File

@ -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<SeriesEditedEvent>
{
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));
}
}
}
}

View File

@ -191,7 +191,7 @@ namespace NzbDrone.Core.Tv
} }
var updatedSeries = _seriesRepository.Update(series); var updatedSeries = _seriesRepository.Update(series);
_eventAggregator.PublishEvent(new SeriesEditedEvent(updatedSeries)); _eventAggregator.PublishEvent(new SeriesEditedEvent(updatedSeries, storedSeries));
return updatedSeries; return updatedSeries;
} }

View File

@ -42,10 +42,11 @@ define(
}, },
events: { events: {
'click .x-add' : '_addSeries', 'click .x-add' : '_addSeries',
'change .x-quality-profile': '_qualityProfileChanged', 'change .x-quality-profile' : '_qualityProfileChanged',
'change .x-root-folder' : '_rootFolderChanged', 'change .x-root-folder' : '_rootFolderChanged',
'change .x-season-folder' : '_seasonFolderChanged' 'change .x-season-folder' : '_seasonFolderChanged',
'change .x-series-type' : '_seriesTypeChanged'
}, },
initialize: function () { initialize: function () {
@ -67,6 +68,7 @@ define(
var defaultQuality = Config.getValue(Config.Keys.DefaultQualityProfileId); var defaultQuality = Config.getValue(Config.Keys.DefaultQualityProfileId);
var defaultRoot = Config.getValue(Config.Keys.DefaultRootFolderId); var defaultRoot = Config.getValue(Config.Keys.DefaultRootFolderId);
var useSeasonFolder = Config.getValueBoolean(Config.Keys.UseSeasonFolder, true); var useSeasonFolder = Config.getValueBoolean(Config.Keys.UseSeasonFolder, true);
var defaultSeriesType = Config.getValueBoolean(Config.Keys.DefaultSeriesType, true);
if (QualityProfiles.get(defaultQuality)) { if (QualityProfiles.get(defaultQuality)) {
this.ui.qualityProfile.val(defaultQuality); this.ui.qualityProfile.val(defaultQuality);
@ -77,6 +79,7 @@ define(
} }
this.ui.seasonFolder.prop('checked', useSeasonFolder); this.ui.seasonFolder.prop('checked', useSeasonFolder);
this.ui.rootFolder.val(defaultSeriesType);
var minSeasonNotZero = _.min(_.reject(this.model.get('seasons'), { seasonNumber: 0 }), 'seasonNumber'); var minSeasonNotZero = _.min(_.reject(this.model.get('seasons'), { seasonNumber: 0 }), 'seasonNumber');
@ -117,6 +120,10 @@ define(
else if (options.key === Config.Keys.UseSeasonFolder) { else if (options.key === Config.Keys.UseSeasonFolder) {
this.ui.seasonFolder.prop('checked', options.value); this.ui.seasonFolder.prop('checked', options.value);
} }
else if (options.key === Config.Keys.DefaultSeriesType) {
this.ui.seriesType.val(options.value);
}
}, },
_qualityProfileChanged: function () { _qualityProfileChanged: function () {
@ -139,6 +146,10 @@ define(
} }
}, },
_seriesTypeChanged: function () {
Config.setValue(Config.Keys.DefaultSeriesType, this.ui.seriesType.val());
},
_setRootFolder: function (options) { _setRootFolder: function (options) {
vent.trigger(vent.Commands.CloseModalCommand); vent.trigger(vent.Commands.CloseModalCommand);
this.ui.rootFolder.val(options.model.id); this.ui.rootFolder.val(options.model.id);

View File

@ -172,3 +172,12 @@ td.delete-episode-file-cell {
.backup-type-cell { .backup-type-cell {
width : 20px; width : 20px;
} }
.table>tbody>tr>td, .table>thead>tr>th {
&.episode-warning-cell {
width : 1px;
padding-left : 0px;
padding-right : 0px;
}
}

View File

@ -8,10 +8,11 @@ define(
ConfigUpdatedEvent: 'ConfigUpdatedEvent' ConfigUpdatedEvent: 'ConfigUpdatedEvent'
}, },
Keys : { Keys : {
DefaultQualityProfileId: 'DefaultQualityProfileId', DefaultQualityProfileId : 'DefaultQualityProfileId',
DefaultRootFolderId : 'DefaultRootFolderId', DefaultRootFolderId : 'DefaultRootFolderId',
UseSeasonFolder : 'UseSeasonFolder', UseSeasonFolder : 'UseSeasonFolder',
AdvancedSettings : 'advancedSettings' DefaultSeriesType : 'DefaultSeriesType',
AdvancedSettings : 'advancedSettings'
}, },
getValueBoolean: function (key, defaultValue) { getValueBoolean: function (key, defaultValue) {

View File

@ -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('<i class="icon-nd-form-warning" title="Episode does not have an absolute episode number"></i>');
}
}
this.delegateEvents();
return this;
}
});
});

View File

@ -10,6 +10,7 @@ define(
'Cells/EpisodeStatusCell', 'Cells/EpisodeStatusCell',
'Cells/EpisodeActionsCell', 'Cells/EpisodeActionsCell',
'Series/Details/EpisodeNumberCell', 'Series/Details/EpisodeNumberCell',
'Series/Details/EpisodeWarningCell',
'Commands/CommandController', 'Commands/CommandController',
'moment', 'moment',
'underscore', 'underscore',
@ -23,6 +24,7 @@ define(
EpisodeStatusCell, EpisodeStatusCell,
EpisodeActionsCell, EpisodeActionsCell,
EpisodeNumberCell, EpisodeNumberCell,
EpisodeWarningCell,
CommandController, CommandController,
Moment, Moment,
_, _,
@ -64,6 +66,13 @@ define(
label: '#', label: '#',
cell : EpisodeNumberCell cell : EpisodeNumberCell
}, },
{
name : 'this',
label : '',
cell : EpisodeWarningCell,
sortable : false,
className : 'episode-warning-cell'
},
{ {
name : 'this', name : 'this',
label : 'Title', label : 'Title',

View File

@ -35,6 +35,10 @@ define(
//Do we need this? //Do we need this?
this.$el.addClass(column.get('name')); this.$el.addClass(column.get('name'));
if (column.has('className')) {
this.$el.addClass(column.get('className'));
}
this.delegateEvents(); this.delegateEvents();
this.direction(column.get('direction')); this.direction(column.get('direction'));