Added MassEdit for series editing.

This commit is contained in:
Mark McDowall 2012-01-19 23:50:45 -08:00
parent 906b5d12cd
commit e885fadc59
6 changed files with 303 additions and 0 deletions

View File

@ -706,5 +706,80 @@ namespace NzbDrone.Core.Test.ProviderTests
//Assert
series.Should().HaveCount(1);
}
[Test]
public void UpdateFromMassEdit_should_only_update_certain_values()
{
WithRealDb();
var newQualityProfileId = 10;
var newMonitored = false;
var newSeasonFolder = false;
var fakeQuality = Builder<QualityProfile>.CreateNew().Build();
var fakeSeries = Builder<Series>.CreateListOfSize(1)
.All()
.With(e => e.QualityProfileId = fakeQuality.QualityProfileId)
.With(e => e.Monitored = true)
.With(e => e.SeasonFolder = true)
.With(s => s.Title = "It's Always Sunny")
.Build();
Db.InsertMany(fakeSeries);
Db.Insert(fakeQuality);
fakeSeries[0].QualityProfileId = newQualityProfileId;
fakeSeries[0].Monitored = newMonitored;
fakeSeries[0].SeasonFolder = newSeasonFolder;
//Act
Mocker.Resolve<SeriesProvider>().UpdateFromMassEdit(fakeSeries);
//Assert
var result = Db.Fetch<Series>();
result.Count.Should().Be(1);
result.First().QualityProfileId.Should().Be(newQualityProfileId);
result.First().Monitored.Should().Be(newMonitored);
result.First().SeasonFolder.Should().Be(newSeasonFolder);
}
[Test]
public void UpdateFromMassEdit_should_only_update_changed_values()
{
WithRealDb();
var newQualityProfileId = 10;
var newMonitored = false;
var newSeasonFolder = false;
var monitored = true;
var seasonFolder = true;
var fakeQuality = Builder<QualityProfile>.CreateNew().Build();
var fakeSeries = Builder<Series>.CreateListOfSize(2)
.All()
.With(e => e.QualityProfileId = fakeQuality.QualityProfileId)
.With(e => e.Monitored = monitored)
.With(e => e.SeasonFolder = seasonFolder)
.With(s => s.Title = "It's Always Sunny")
.Build();
Db.InsertMany(fakeSeries);
Db.Insert(fakeQuality);
fakeSeries[0].QualityProfileId = newQualityProfileId;
fakeSeries[0].Monitored = newMonitored;
fakeSeries[0].SeasonFolder = newSeasonFolder;
//Act
Mocker.Resolve<SeriesProvider>().UpdateFromMassEdit(fakeSeries);
//Assert
var result = Db.Fetch<Series>();
result.Count.Should().Be(2);
result.First().QualityProfileId.Should().Be(newQualityProfileId);
result.First().Monitored.Should().Be(newMonitored);
result.First().SeasonFolder.Should().Be(newSeasonFolder);
result.Last().QualityProfileId.Should().Be(fakeQuality.QualityProfileId);
result.Last().Monitored.Should().Be(monitored);
result.Last().SeasonFolder.Should().Be(seasonFolder);
}
}
}

View File

@ -198,6 +198,23 @@ namespace NzbDrone.Core.Providers
return series;
}
public virtual void UpdateFromMassEdit(IList<Series> editedSeries)
{
var allSeries = GetAllSeries();
foreach(var series in allSeries)
{
//Only update parameters that can be changed in MassEdit
var edited = editedSeries.Single(s => s.SeriesId == series.SeriesId);
series.QualityProfileId = edited.QualityProfileId;
series.Monitored = edited.Monitored;
series.SeasonFolder = edited.SeasonFolder;
series.Path = edited.Path;
}
_database.UpdateMany(allSeries);
}
/// <summary>
/// Cleans up the AirsTime Component from TheTVDB since it can be garbage that comes in.
/// </summary>

View File

@ -9,6 +9,7 @@ using NzbDrone.Core.Helpers;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Web.Models;
using Telerik.Web.Mvc;
@ -148,6 +149,40 @@ namespace NzbDrone.Web.Controllers
return View(model);
}
public ActionResult MassEdit()
{
var profiles = _qualityProvider.All();
ViewData["QualityProfiles"] = profiles;
//Create the select lists
var masterProfiles = profiles.ToList();
masterProfiles.Insert(0, new QualityProfile {QualityProfileId = -10, Name = "Unchanged"});
ViewData["MasterProfileSelectList"] = new SelectList(masterProfiles, "QualityProfileId", "Name");
ViewData["BoolSelectList"] = new SelectList(new List<KeyValuePair<int, string>>
{
new KeyValuePair<int, string>(-10, "Unchanged"),
new KeyValuePair<int, string>(1, "True"),
new KeyValuePair<int, string>(0, "False")
}, "Key", "Value"
);
var series = _seriesProvider.GetAllSeries().OrderBy(o => SortHelper.SkipArticles(o.Title));
return View(series);
}
[HttpPost]
public JsonResult SaveMassEdit(List<Series> series)
{
//Save edits
if (series == null || series.Count == 0)
return JsonNotificationResult.Opps("Invalid post data");
_seriesProvider.UpdateFromMassEdit(series);
return JsonNotificationResult.Info("Series Mass Edit Saved");
}
private List<SeriesModel> GetSeriesModels(IList<Series> seriesInDb)
{
var series = seriesInDb.Select(s => new SeriesModel

View File

@ -523,6 +523,12 @@
<ItemGroup>
<Content Include="Views\Settings\Misc.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Series\MassEdit.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Series\SeriesItem.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -0,0 +1,147 @@
@using NzbDrone.Web.Helpers
@model IEnumerable<NzbDrone.Core.Repository.Series>
@{ViewBag.Title = "NzbDrone";}
@section HeaderContent
{
@Html.IncludeCss("Settings.css")
<style>
.checkboxColumn {
width: 95px;
text-align: center;
}
.masterControls {
margin-top: 10px;
overflow: hidden;
}
.buttons {
width: 600px;
text-align: center;
}
table input[type="text"], table select {
margin: 2px 5px 2px 5px;
}
table {
width: 100%;
border-width: 1px;
border-spacing: 2px;
border-style: none;
border-color: white;
border-collapse: collapse;
background-color: white;
}
table th {
border-width: 1px;
padding: 2px;
border-style: inset;
border-color: #EEEEEE;
background-color: white;
-moz-border-radius: ;
}
table td {
border-width: 1px;
padding: 2px;
border-style: inset;
border-color: #EEEEEE;
background-color: white;
-moz-border-radius: ;
}
</style>
}
@using (Html.BeginForm("SaveMassEdit", "Series", FormMethod.Post, new { id = "MassEdit", name = "MassEdit" }))
{
<table>
<tr>
<th>@Html.CheckBox("editToggleMaster", false, new { @class = "editToggleMaster" })</th>
<th>Title</th>
<th>Quality</th>
<th class="checkboxColumn">Monitored</th>
<th class="checkboxColumn">Season Folder</th>
<th>Path</th>
</tr>
@foreach (var series in Model)
{
Html.RenderPartial("SeriesItem", series);
}
</table>
<div class="masterControls">
<div id="stylized" style="border-color: transparent;">
<div class="settingsForm">
<label class="labelClass">Quality Profile
<span class="small">Which Quality Profile should NzbDrone use to download episodes?</span>
</label>
@Html.DropDownList("masterQualitySelector", (SelectList)ViewData["MasterProfileSelectList"], new { @class = "inputClass" })
<label class="labelClass">Monitored
<span class="small">Should NzbDrone download episodes for this series?</span>
</label>
@Html.DropDownList("masterMonitored", (SelectList)ViewData["BoolSelectList"], new { @class = "inputClass" })
<label class="labelClass">Use Season Folder
<span class="small">Should downloaded episodes be stored in season folders?</span>
</label>
@Html.DropDownList("masterSeasonFolder", (SelectList)ViewData["BoolSelectList"], new { @class = "inputClass" })
</div>
</div>
</div>
<div class="buttons">
<button id="updateSelected" title="Update the selected series with the settings above">Update Selected</button>
<button type="submit" class="save_button" disabled="disabled" title="Commit the settings from your series above to the database">
Save Changes</button>
</div>
}
@section Scripts
{
<script>
$('.editToggleMaster').live('change', function () {
var toggle = $(this).prop('checked');
$('.editToggle').each(function () {
$(this).prop('checked', toggle);
});
});
$('#updateSelected').live('click', function () {
//Find selected values
var profileId = $('#masterQualitySelector').val();
var monitored = $('#masterMonitored').val();
var seasonFolder = $('#masterSeasonFolder').val();
var selected = $('.editToggle:checked');
selected.each(function() {
if (profileId != -10) {
$(this).parent('td').parent('.seriesEditRow').find('.quality').val(profileId);
}
if (monitored != -10) {
var monitoredBool = true;
if (monitored != 1)
monitoredBool = false;
$(this).parent('td').parent('.seriesEditRow').find('.monitored').prop('checked', monitoredBool);
}
if (seasonFolder != -10) {
var seasonFolderBool = true;
if (seasonFolder != 1)
seasonFolderBool = false;
$(this).parent('td').parent('.seriesEditRow').find('.seasonFolder').prop('checked', seasonFolderBool);
}
});
});
//Update all checked rows
</script>
}

View File

@ -0,0 +1,23 @@
@model NzbDrone.Core.Repository.Series
@using NzbDrone.Core.Repository.Quality
@using NzbDrone.Web.Helpers
@{
Layout = null;
}
@*SeriesId, Title, Quality, Monitored, Use Season Folder, Root Directory/Path*, Backlog Toggle*@
@using (Html.BeginCollectionItem("series"))
{
var idClean = ViewData.TemplateInfo.HtmlFieldPrefix.Replace('[', '_').Replace(']', '_');
<tr class="seriesEditRow">
@Html.HiddenFor(m => m.SeriesId)
<td>@Html.CheckBox("editToggle", false, new {@class = "editToggle"})</td>
<td>@Model.Title</td>
<td>@Html.DropDownListFor(m => m.QualityProfileId, new SelectList((List<QualityProfile>)ViewData["QualityProfiles"], "QualityProfileId", "Name", Model.QualityProfileId), new { @class = "quality" })</td>
<td class="checkboxColumn">@Html.CheckBoxFor(m => m.Monitored, new {@class = "seriesCheckbox monitored"})</td>
<td class="checkboxColumn">@Html.CheckBoxFor(m => m.SeasonFolder, new {@class = "seriesCheckbox seasonFolder"})</td>
<td>@Html.TextBoxFor(m => m.Path)</td>
</tr>
}