From fb53fc68a9d7a79723232e7347dfe254cc6c32a7 Mon Sep 17 00:00:00 2001 From: Leonardo Galli Date: Sun, 20 Aug 2017 18:58:29 +0200 Subject: [PATCH] Added: Ability to delete multiple movies at once via the movie editor. --- src/NzbDrone.Api/Movies/MovieEditorModule.cs | 34 +++++++++- src/UI/Content/icons.less | 4 ++ .../Editor/Delete/DeleteSelectedTemplate.hbs | 63 +++++++++++++++++++ .../Editor/Delete/DeleteSelectedView.js | 60 ++++++++++++++++++ src/UI/Movies/Editor/MovieEditorLayout.js | 42 ++++++++----- 5 files changed, 188 insertions(+), 15 deletions(-) create mode 100644 src/UI/Movies/Editor/Delete/DeleteSelectedTemplate.hbs create mode 100644 src/UI/Movies/Editor/Delete/DeleteSelectedView.js diff --git a/src/NzbDrone.Api/Movies/MovieEditorModule.cs b/src/NzbDrone.Api/Movies/MovieEditorModule.cs index ca744a099..e83ab0520 100644 --- a/src/NzbDrone.Api/Movies/MovieEditorModule.cs +++ b/src/NzbDrone.Api/Movies/MovieEditorModule.cs @@ -1,7 +1,10 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Nancy; +using Nancy.Responses; using NzbDrone.Api.Extensions; +using NzbDrone.Api.REST; using NzbDrone.Core.Tv; namespace NzbDrone.Api.Movie @@ -15,6 +18,7 @@ namespace NzbDrone.Api.Movie { _movieService = movieService; Put["/"] = Movie => SaveAll(); + Put["/delete"] = Movie => DeleteSelected(); } private Response SaveAll() @@ -27,5 +31,33 @@ namespace NzbDrone.Api.Movie .ToResource() .AsResponse(HttpStatusCode.Accepted); } + + private Response DeleteSelected() + { + var deleteFiles = false; + var addExclusion = false; + var deleteFilesQuery = Request.Query.deleteFiles; + var addExclusionQuery = Request.Query.addExclusion; + + if (deleteFilesQuery.HasValue) + { + deleteFiles = Convert.ToBoolean(deleteFilesQuery.Value); + } + if (addExclusionQuery.HasValue) + { + addExclusion = Convert.ToBoolean(addExclusionQuery.Value); + } + var ids = Request.Body.FromJson>(); + + foreach (var id in ids) + { + _movieService.DeleteMovie(id, deleteFiles, addExclusion); + } + + return new Response + { + StatusCode = HttpStatusCode.Accepted + }; + } } } diff --git a/src/UI/Content/icons.less b/src/UI/Content/icons.less index fe5b57fa9..de2b281fd 100644 --- a/src/UI/Content/icons.less +++ b/src/UI/Content/icons.less @@ -309,6 +309,10 @@ .fa-icon-color(@brand-danger); } +.icon-radarr-delete-white { + .fa-icon-content(@fa-var-remove); +} + .icon-sonarr-ignore { .fa-icon-content(@fa-var-eye-slash); } diff --git a/src/UI/Movies/Editor/Delete/DeleteSelectedTemplate.hbs b/src/UI/Movies/Editor/Delete/DeleteSelectedTemplate.hbs new file mode 100644 index 000000000..f33b1ba9e --- /dev/null +++ b/src/UI/Movies/Editor/Delete/DeleteSelectedTemplate.hbs @@ -0,0 +1,63 @@ + diff --git a/src/UI/Movies/Editor/Delete/DeleteSelectedView.js b/src/UI/Movies/Editor/Delete/DeleteSelectedView.js new file mode 100644 index 000000000..9983b27d0 --- /dev/null +++ b/src/UI/Movies/Editor/Delete/DeleteSelectedView.js @@ -0,0 +1,60 @@ +var vent = require('vent'); +var Marionette = require('marionette'); +var Backbone = require('backbone'); + +module.exports = Marionette.ItemView.extend({ + template : 'Movies/Editor/Delete/DeleteSelectedTemplate', + + events : { + 'click .x-confirm-delete' : 'removeSeries', + 'change .x-delete-files' : 'changeDeletedFiles' + }, + + ui : { + deleteFiles : '.x-delete-files', + deleteFilesInfo : '.x-delete-files-info', + indicator : '.x-indicator', + addExclusion : '.x-add-exclusion' + }, + + initialize : function(options) { + this.movies = options.movies; + this.templateHelpers = { + removeCount : this.movies.length, + fileCount : _.filter(this.movies, function(m){ + return m.get("hasFile"); + }).length + }; + }, + + removeSeries : function() { + var self = this; + var deleteFiles = this.ui.deleteFiles.prop('checked'); + var addExclusion = this.ui.addExclusion.prop('checked'); + this.ui.indicator.show(); + var proxy = _.extend(new Backbone.Model(), { + id : '', + + url : window.NzbDrone.ApiRoot+'/movie/editor/delete?deleteFiles='+deleteFiles+'&addExclusion='+addExclusion, + + toJSON : function() { + return _.pluck(self.movies, "id"); + } + }); + + proxy.save().done(function() { + //vent.trigger(vent.Events.SeriesDeleted, { series : self.model }); + vent.trigger(vent.Commands.CloseModalCommand); + }); + }, + + changeDeletedFiles : function() { + var deleteFiles = this.ui.deleteFiles.prop('checked'); + + if (deleteFiles) { + this.ui.deleteFilesInfo.show(); + } else { + this.ui.deleteFilesInfo.hide(); + } + } +}); diff --git a/src/UI/Movies/Editor/MovieEditorLayout.js b/src/UI/Movies/Editor/MovieEditorLayout.js index 009250b3d..28d73c7ae 100644 --- a/src/UI/Movies/Editor/MovieEditorLayout.js +++ b/src/UI/Movies/Editor/MovieEditorLayout.js @@ -13,6 +13,7 @@ var ToolbarLayout = require('../../Shared/Toolbar/ToolbarLayout'); var FooterView = require('./MovieEditorFooterView'); var GridPager = require('../../Shared/Grid/Pager'); require('../../Mixins/backbone.signalr.mixin'); +var DeleteSelectedView = require('./Delete/DeleteSelectedView'); var Config = require('../../Config'); window.shownOnce = false; @@ -68,20 +69,6 @@ module.exports = Marionette.Layout.extend({ } ], - leftSideButtons : { - type : 'default', - storeState : false, - items : [ - { - title : 'Update Library', - icon : 'icon-sonarr-refresh', - command : 'refreshmovie', - successMessage : 'Library was updated!', - errorMessage : 'Library update failed!' - } - ] - }, - initialize : function() { this.movieCollection = MoviesCollection.clone(); @@ -106,6 +93,26 @@ module.exports = Marionette.Layout.extend({ this.listenTo(this.movieCollection.fullCollection, 'sync', function() { }); + + this.leftSideButtons = { + type : 'default', + storeState : false, + items : [ + { + title : 'Update Library', + icon : 'icon-sonarr-refresh', + command : 'refreshmovie', + successMessage : 'Library was updated!', + errorMessage : 'Library update failed!' + }, + { + title : 'Delete Selected', + icon : 'icon-radarr-delete-white', + className: 'btn-danger', + callback : this._deleteSelected + } + ] + }; //this.listenTo(FullMovieCollection, 'save', function() { // window.alert('Done Saving'); //}); @@ -230,5 +237,12 @@ module.exports = Marionette.Layout.extend({ _setFilter : function(buttonContext) { var mode = buttonContext.model.get('key'); this.movieCollection.setFilterMode(mode); + }, + + _deleteSelected: function() { + var selected = FullMovieCollection.where({ selected : true }); + var updateFilesMoviesView = new DeleteSelectedView({ movies : selected }); + + vent.trigger(vent.Commands.OpenModalCommand, updateFilesMoviesView); } });