mirror of https://github.com/Radarr/Radarr
Added: Ability to delete multiple movies at once via the movie editor.
This commit is contained in:
parent
8de87bb516
commit
fb53fc68a9
|
@ -1,7 +1,10 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
|
using Nancy.Responses;
|
||||||
using NzbDrone.Api.Extensions;
|
using NzbDrone.Api.Extensions;
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Movie
|
namespace NzbDrone.Api.Movie
|
||||||
|
@ -15,6 +18,7 @@ namespace NzbDrone.Api.Movie
|
||||||
{
|
{
|
||||||
_movieService = movieService;
|
_movieService = movieService;
|
||||||
Put["/"] = Movie => SaveAll();
|
Put["/"] = Movie => SaveAll();
|
||||||
|
Put["/delete"] = Movie => DeleteSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response SaveAll()
|
private Response SaveAll()
|
||||||
|
@ -27,5 +31,33 @@ namespace NzbDrone.Api.Movie
|
||||||
.ToResource()
|
.ToResource()
|
||||||
.AsResponse(HttpStatusCode.Accepted);
|
.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<List<int>>();
|
||||||
|
|
||||||
|
foreach (var id in ids)
|
||||||
|
{
|
||||||
|
_movieService.DeleteMovie(id, deleteFiles, addExclusion);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response
|
||||||
|
{
|
||||||
|
StatusCode = HttpStatusCode.Accepted
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,6 +309,10 @@
|
||||||
.fa-icon-color(@brand-danger);
|
.fa-icon-color(@brand-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-radarr-delete-white {
|
||||||
|
.fa-icon-content(@fa-var-remove);
|
||||||
|
}
|
||||||
|
|
||||||
.icon-sonarr-ignore {
|
.icon-sonarr-ignore {
|
||||||
.fa-icon-content(@fa-var-eye-slash);
|
.fa-icon-content(@fa-var-eye-slash);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="close">×</button>
|
||||||
|
<h3>Delete {{removeCount}} Titles</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body delete-series-modal">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="form-horizontal">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">Delete all files</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<div class="input-group">
|
||||||
|
<label class="checkbox toggle well">
|
||||||
|
<input type="checkbox" class="x-delete-files">
|
||||||
|
<p>
|
||||||
|
<span>Yes</span>
|
||||||
|
<span>No</span>
|
||||||
|
</p>
|
||||||
|
<div class="btn slide-button btn-danger"></div>
|
||||||
|
</label>
|
||||||
|
<span class="help-inline-checkbox">
|
||||||
|
<i class="icon-sonarr-form-info" title="Do you want to delete all files from disk?"></i>
|
||||||
|
<i class="icon-sonarr-form-warning" title="This option is irreversible, use with extreme caution!"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-offset-1 col-md-5 delete-files-info x-delete-files-info">
|
||||||
|
{{fileCount}} movie file(s) will be deleted
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">Exclude movies from auto list import?</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<div class="input-group">
|
||||||
|
<label class="checkbox toggle well">
|
||||||
|
<input type="checkbox" class="x-add-exclusion">
|
||||||
|
<p>
|
||||||
|
<span>Yes</span>
|
||||||
|
<span>No</span>
|
||||||
|
</p>
|
||||||
|
<div class="btn slide-button btn-danger"></div>
|
||||||
|
</label>
|
||||||
|
<span class="help-inline-checkbox">
|
||||||
|
<i class="icon-sonarr-form-info" title="Do you want to prevent these movies from being read during automatic list syncing?"></i>
|
||||||
|
<i class="icon-sonarr-form-info" title="Movies can be removed from the exclusions list via the lists tab in settings."></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<span class="indicator x-indicator">
|
||||||
|
<i class="icon-sonarr-spinner fa-spin" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
<button class="btn" data-dismiss="modal">Cancel</button>
|
||||||
|
<button class="btn btn-danger x-confirm-delete">Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -13,6 +13,7 @@ var ToolbarLayout = require('../../Shared/Toolbar/ToolbarLayout');
|
||||||
var FooterView = require('./MovieEditorFooterView');
|
var FooterView = require('./MovieEditorFooterView');
|
||||||
var GridPager = require('../../Shared/Grid/Pager');
|
var GridPager = require('../../Shared/Grid/Pager');
|
||||||
require('../../Mixins/backbone.signalr.mixin');
|
require('../../Mixins/backbone.signalr.mixin');
|
||||||
|
var DeleteSelectedView = require('./Delete/DeleteSelectedView');
|
||||||
var Config = require('../../Config');
|
var Config = require('../../Config');
|
||||||
|
|
||||||
window.shownOnce = false;
|
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() {
|
initialize : function() {
|
||||||
|
|
||||||
this.movieCollection = MoviesCollection.clone();
|
this.movieCollection = MoviesCollection.clone();
|
||||||
|
@ -106,6 +93,26 @@ module.exports = Marionette.Layout.extend({
|
||||||
this.listenTo(this.movieCollection.fullCollection, 'sync', function() {
|
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() {
|
//this.listenTo(FullMovieCollection, 'save', function() {
|
||||||
// window.alert('Done Saving');
|
// window.alert('Done Saving');
|
||||||
//});
|
//});
|
||||||
|
@ -230,5 +237,12 @@ module.exports = Marionette.Layout.extend({
|
||||||
_setFilter : function(buttonContext) {
|
_setFilter : function(buttonContext) {
|
||||||
var mode = buttonContext.model.get('key');
|
var mode = buttonContext.model.get('key');
|
||||||
this.movieCollection.setFilterMode(mode);
|
this.movieCollection.setFilterMode(mode);
|
||||||
|
},
|
||||||
|
|
||||||
|
_deleteSelected: function() {
|
||||||
|
var selected = FullMovieCollection.where({ selected : true });
|
||||||
|
var updateFilesMoviesView = new DeleteSelectedView({ movies : selected });
|
||||||
|
|
||||||
|
vent.trigger(vent.Commands.OpenModalCommand, updateFilesMoviesView);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue