From 354105cf0803b7b154d4453b324205b13e67eaee Mon Sep 17 00:00:00 2001 From: Leonardo Galli Date: Tue, 11 Sep 2018 14:35:15 +0200 Subject: [PATCH] Fixed: Issue with custom formats when profile was saved with non existing formats. Also you now don't have to refresh your browser for them to appear / disappear. --- src/NzbDrone.Api/Profiles/ProfileModule.cs | 17 +++++++++++++- .../Converters/CustomFormatIntConverter.cs | 6 +++++ .../CustomFormats/CustomFormatCollection.js | 22 ++++++++++++++++++- src/UI/Settings/Profile/ProfileLayout.js | 6 +++++ src/UI/vent.js | 3 ++- 5 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/NzbDrone.Api/Profiles/ProfileModule.cs b/src/NzbDrone.Api/Profiles/ProfileModule.cs index e5803db20..2802a03fc 100644 --- a/src/NzbDrone.Api/Profiles/ProfileModule.cs +++ b/src/NzbDrone.Api/Profiles/ProfileModule.cs @@ -1,5 +1,8 @@ using System.Collections.Generic; +using System.Linq; using FluentValidation; +using NzbDrone.Common.Extensions; +using NzbDrone.Core.CustomFormats; using NzbDrone.Core.Profiles; using NzbDrone.Core.Validation; @@ -8,14 +11,26 @@ namespace NzbDrone.Api.Profiles public class ProfileModule : NzbDroneRestModule { private readonly IProfileService _profileService; + private readonly ICustomFormatService _formatService; - public ProfileModule(IProfileService profileService) + public ProfileModule(IProfileService profileService, ICustomFormatService formatService) { _profileService = profileService; + _formatService = formatService; SharedValidator.RuleFor(c => c.Name).NotEmpty(); SharedValidator.RuleFor(c => c.Cutoff).NotNull(); SharedValidator.RuleFor(c => c.Items).MustHaveAllowedQuality(); SharedValidator.RuleFor(c => c.Language).ValidLanguage(); + SharedValidator.RuleFor(c => c.FormatItems).Must(items => + { + var all = _formatService.All().Select(f => f.Id).ToList(); + all.Add(CustomFormat.None.Id); + var ids = items.Select(i => i.Id); + + return all.Except(ids).Empty(); + }).WithMessage("All Custom Formats and no extra ones need to be present inside your Profile! Try refreshing your browser."); + SharedValidator.RuleFor(c => c.FormatCutoff) + .Must(c => _formatService.All().Select(f => f.Id).Contains(c.Id) || c.Id == CustomFormat.None.Id).WithMessage("The Custom Format Cutoff must be a valid Custom Format! Try refreshing your browser."); GetResourceAll = GetAll; GetResourceById = GetById; diff --git a/src/NzbDrone.Core/Datastore/Converters/CustomFormatIntConverter.cs b/src/NzbDrone.Core/Datastore/Converters/CustomFormatIntConverter.cs index 44015f18b..3875371b9 100644 --- a/src/NzbDrone.Core/Datastore/Converters/CustomFormatIntConverter.cs +++ b/src/NzbDrone.Core/Datastore/Converters/CustomFormatIntConverter.cs @@ -48,6 +48,12 @@ namespace NzbDrone.Core.Datastore.Converters } var quality = (CustomFormat) clrValue; + + if (CustomFormatService.AllCustomFormats?.ContainsKey(quality.Id) == false) + { + //throw new Exception("Attempted to save an unknown custom format! Make sure you do not have stale custom formats lying around!"); + } + return quality.Id; } diff --git a/src/UI/Settings/CustomFormats/CustomFormatCollection.js b/src/UI/Settings/CustomFormats/CustomFormatCollection.js index ce0ea4310..644330d9c 100644 --- a/src/UI/Settings/CustomFormats/CustomFormatCollection.js +++ b/src/UI/Settings/CustomFormats/CustomFormatCollection.js @@ -1,8 +1,28 @@ var Backbone = require('backbone'); var IndexerModel = require('./CustomFormatModel'); +var vent = require('vent'); + module.exports = Backbone.Collection.extend({ model : IndexerModel, - url : window.NzbDrone.ApiRoot + '/customformat' + url : window.NzbDrone.ApiRoot + '/customformat', + + sync : function(method, model, options) { + vent.trigger(vent.Events.CustomFormatsChanged, {method : method}); + + Backbone.Collection.prototype.sync.apply(this, arguments); + }, + + add : function(model, options) { + vent.trigger(vent.Events.CustomFormatsChanged, {options : options}); + + Backbone.Collection.prototype.add.apply(this, arguments); + }, + + remove : function(model, options) { + vent.trigger(vent.Events.CustomFormatsChanged, {options : options}); + + Backbone.Collection.prototype.remove.apply(this, arguments); + } }); diff --git a/src/UI/Settings/Profile/ProfileLayout.js b/src/UI/Settings/Profile/ProfileLayout.js index d8f226271..23d36f7cd 100644 --- a/src/UI/Settings/Profile/ProfileLayout.js +++ b/src/UI/Settings/Profile/ProfileLayout.js @@ -5,6 +5,8 @@ var DelayProfileLayout = require('./Delay/DelayProfileLayout'); var DelayProfileCollection = require('./Delay/DelayProfileCollection'); var LanguageCollection = require('./Language/LanguageCollection'); +var vent = require('vent'); + module.exports = Marionette.Layout.extend({ template : 'Settings/Profile/ProfileLayoutTemplate', @@ -17,6 +19,10 @@ module.exports = Marionette.Layout.extend({ this.settings = options.settings; ProfileCollection.fetch(); + vent.on(vent.Events.CustomFormatsChanged, function(options) { + ProfileCollection.fetch(); + }); + this.delayProfileCollection = new DelayProfileCollection(); this.delayProfileCollection.fetch(); }, diff --git a/src/UI/vent.js b/src/UI/vent.js index 41328e784..baeeb2f70 100644 --- a/src/UI/vent.js +++ b/src/UI/vent.js @@ -7,7 +7,8 @@ vent.Events = { MovieDeleted : 'movie:deleted', CommandComplete : 'command:complete', ServerUpdated : 'server:updated', - EpisodeFileDeleted : 'episodefile:deleted' + EpisodeFileDeleted : 'episodefile:deleted', + CustomFormatsChanged : 'customformat:changed' }; vent.Commands = {