Combined AddNew and AddExisting Series pages.

Fixed AddNew Series
pull/4/head
Mark McDowall 14 years ago
parent 6c7fa1674e
commit 463881843e

@ -55,5 +55,17 @@ namespace NzbDrone.Core.Helpers
return String.Format("{0} - S{1:00}E{2} - {3}", erm.SeriesName, erm.EpisodeFile.Episodes[0].SeasonNumber, return String.Format("{0} - S{1:00}E{2} - {3}", erm.SeriesName, erm.EpisodeFile.Episodes[0].SeasonNumber,
epNumberString, epNameString); epNumberString, epNameString);
} }
public static string CleanFilename(string name)
{
string result = name;
string[] badCharacters = {"\\", "/", "<", ">", "?", "*", ":", "|", "\""};
string[] goodCharacters = {"+", "+", "{", "}", "!", "@", "-", "#", "`"};
for (int i = 0; i < badCharacters.Length; i++)
result = result.Replace(badCharacters[i], goodCharacters[i]);
return result.Trim();
}
} }
} }

@ -2,6 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Web.Mvc; using System.Web.Mvc;
using System.Linq;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Jobs; using NzbDrone.Core.Providers.Jobs;
@ -18,11 +20,13 @@ namespace NzbDrone.Web.Controllers
private readonly JobProvider _jobProvider; private readonly JobProvider _jobProvider;
private readonly SyncProvider _syncProvider; private readonly SyncProvider _syncProvider;
private readonly TvDbProvider _tvDbProvider; private readonly TvDbProvider _tvDbProvider;
private readonly DiskProvider _diskProvider;
public AddSeriesController(SyncProvider syncProvider, RootDirProvider rootFolderProvider, public AddSeriesController(SyncProvider syncProvider, RootDirProvider rootFolderProvider,
ConfigProvider configProvider, ConfigProvider configProvider,
QualityProvider qualityProvider, TvDbProvider tvDbProvider, QualityProvider qualityProvider, TvDbProvider tvDbProvider,
SeriesProvider seriesProvider, JobProvider jobProvider) SeriesProvider seriesProvider, JobProvider jobProvider,
DiskProvider diskProvider)
{ {
_syncProvider = syncProvider; _syncProvider = syncProvider;
_rootFolderProvider = rootFolderProvider; _rootFolderProvider = rootFolderProvider;
@ -31,6 +35,7 @@ namespace NzbDrone.Web.Controllers
_tvDbProvider = tvDbProvider; _tvDbProvider = tvDbProvider;
_seriesProvider = seriesProvider; _seriesProvider = seriesProvider;
_jobProvider = jobProvider; _jobProvider = jobProvider;
_diskProvider = diskProvider;
} }
[HttpPost] [HttpPost]
@ -42,25 +47,28 @@ namespace NzbDrone.Web.Controllers
public ActionResult AddNew() public ActionResult AddNew()
{ {
ViewData["RootDirs"] = _rootFolderProvider.GetAll(); var rootDirs =_rootFolderProvider.GetAll().Select(r =>
ViewData["DirSep"] = Path.DirectorySeparatorChar; new RootDirModel
{
Path = r.Path,
CleanPath = r.Path.Replace(Path.DirectorySeparatorChar, '|').Replace(Path.VolumeSeparatorChar, '^').Replace('\'', '`')
}).ToList();
ViewData["RootDirs"] = rootDirs;
ViewData["DirSep"] = Path.DirectorySeparatorChar.ToString().Replace(Path.DirectorySeparatorChar, '|');
var profiles = _qualityProvider.GetAllProfiles(); var defaultQuality = _configProvider.DefaultQualityProfile;
var selectList = new SelectList(profiles, "QualityProfileId", "Name"); var qualityProfiles = _qualityProvider.GetAllProfiles();
var defaultQuality = Convert.ToInt32(_configProvider.DefaultQualityProfile);
var model = new AddNewSeriesModel ViewData["quality"] = new SelectList(
{ qualityProfiles,
DirectorySeparatorChar = Path.DirectorySeparatorChar.ToString(), "QualityProfileId",
RootDirectories = _rootFolderProvider.GetAll(), "Name",
QualityProfileId = defaultQuality, defaultQuality);
QualitySelectList = selectList
};
return View(model); return View();
} }
public ActionResult AddExisting() public ActionResult Add()
{ {
var unmappedList = new List<String>(); var unmappedList = new List<String>();
@ -98,6 +106,20 @@ namespace NzbDrone.Web.Controllers
return PartialView("AddSeriesItem", suggestions); return PartialView("AddSeriesItem", suggestions);
} }
[HttpPost]
public JsonResult AddNewSeries(string rootPath, string seriesName, int seriesId, int qualityProfileId)
{
var path = rootPath.Replace('|', Path.DirectorySeparatorChar).Replace('^', Path.VolumeSeparatorChar).Replace('`', '\'') +
Path.DirectorySeparatorChar + EpisodeRenameHelper.CleanFilename(seriesName);
//Create the folder for the new series and then Add it
_diskProvider.CreateDirectory(path);
_seriesProvider.AddSeries(path, seriesId, qualityProfileId);
ScanNewSeries();
return new JsonResult { Data = "ok" };
}
public JsonResult AddSeries(string path, int seriesId, int qualityProfileId) public JsonResult AddSeries(string path, int seriesId, int qualityProfileId)
{ {
//Get TVDB Series Name //Get TVDB Series Name

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace NzbDrone.Web.Models
{
public class RootDirModel
{
public string Path { get; set; }
public string CleanPath { get; set; }
}
}

@ -237,6 +237,7 @@
<Compile Include="Models\AddExistingManualModel.cs" /> <Compile Include="Models\AddExistingManualModel.cs" />
<Compile Include="Models\AddExistingSeriesModel.cs" /> <Compile Include="Models\AddExistingSeriesModel.cs" />
<Compile Include="Models\AddNewSeriesModel.cs" /> <Compile Include="Models\AddNewSeriesModel.cs" />
<Compile Include="Models\RootDirModel.cs" />
<Compile Include="Models\SabnzbdSettingsModel.cs" /> <Compile Include="Models\SabnzbdSettingsModel.cs" />
<Compile Include="Models\EpisodeSortingModel.cs" /> <Compile Include="Models\EpisodeSortingModel.cs" />
<Compile Include="Models\HistoryModel.cs" /> <Compile Include="Models\HistoryModel.cs" />
@ -662,7 +663,7 @@
<Content Include="Scripts\jquery-tgc-countdown-1.0.js" /> <Content Include="Scripts\jquery-tgc-countdown-1.0.js" />
<Content Include="Scripts\jquery.simpledropdown.js" /> <Content Include="Scripts\jquery.simpledropdown.js" />
<Content Include="Scripts\Notification.js" /> <Content Include="Scripts\Notification.js" />
<Content Include="Views\AddSeries\AddExisting.cshtml" /> <Content Include="Views\AddSeries\Add.cshtml" />
<Content Include="Views\AddSeries\AddNew.cshtml" /> <Content Include="Views\AddSeries\AddNew.cshtml" />
<Content Include="Views\AddSeries\AddSeriesItem.cshtml" /> <Content Include="Views\AddSeries\AddSeriesItem.cshtml" />
<Content Include="Web.config"> <Content Include="Web.config">
@ -870,6 +871,9 @@
<ItemGroup> <ItemGroup>
<Content Include="Views\Series\SingleSeason.cshtml" /> <Content Include="Views\Series\SingleSeason.cshtml" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="Views\AddSeries\Copy of AddNew.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.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. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

@ -0,0 +1,65 @@
@model IEnumerable<String>
<script type="text/javascript" src="../../Scripts/2011.1.315/telerik.window.min.js"></script>
@section TitleContent{
Add Existing Series
}
@section MainContent{
@{ Html.Telerik().Window()
.Name("Window")
.Title("Add New Series")
.Modal(true)
.Buttons(b => b.Close())
.Width(500)
.Height(200)
.Visible(false)
.Draggable(true)
.Resizable(resizing => resizing.Enabled(false))
.LoadContentFrom("AddNew", "AddSeries")
.Render();
}
@if (Model.Count() == 0)
{
@Html.DisplayText("No Series to Add");
}
@Html.DropDownList("masterDropbox", (SelectList) ViewData["qualities"],
new {style = "width: 100px;", id = "masterDropboxId"})
@Html.Telerik().DropDownList().Name("tester").BindTo((SelectList) ViewData["qualities"]).HtmlAttributes(
new {style = "width: 100px", @class = "qualityDropbox"})
<button onclick="openAddNewSeries(); return false;" class="listButton">Add New</button>
@foreach (var path in Model)
{
Html.RenderAction("RenderPartial", "AddSeries", new {path});
}
}
<script type="text/javascript">
function openAddNewSeries() {
var windowElement = $('#Window');
windowElement.data('tWindow').center().open();
};
function closeAddNewSeries() {
var window = $('#Window').data("tWindow");
window.close();
}
$("#masterDropboxId").change(function () {
var selectedQuality = $('#masterDropboxId').get(0).selectedIndex;
//$(".qualityDropbox").data("tComboBox").value(selectedQuality);
//$(".qualityDropbox").data("tDropDownList").val(selectedQuality);
var comboBox = $(".qualityDropbox").data("tDropDownList");
comboBox.select(selectedQuality);
});
</script>

@ -1,35 +0,0 @@
@model IEnumerable<String>
@section TitleContent{
Add Existing Series
}
@section MainContent{
@if (Model.Count() == 0)
{
@Html.DisplayText("No Series to Add");
}
@Html.DropDownList("masterDropbox", (SelectList) ViewData["qualities"],
new {style = "width: 100px;", id = "masterDropboxId"})
@Html.Telerik().DropDownList().Name("tester").BindTo((SelectList) ViewData["qualities"]).HtmlAttributes(
new {style = "width: 100px", @class = "qualityDropbox"})
@foreach (var path in Model)
{
Html.RenderAction("RenderPartial", "AddSeries", new {path});
}
<script type="text/javascript">
$("#masterDropboxId").change(function () {
var selectedQuality = $('#masterDropboxId').get(0).selectedIndex;
//$(".qualityDropbox").data("tComboBox").value(selectedQuality);
//$(".qualityDropbox").data("tDropDownList").val(selectedQuality);
var comboBox = $(".qualityDropbox").data("tDropDownList");
comboBox.select(selectedQuality);
});
</script>
}

@ -1,98 +1,67 @@
@model NzbDrone.Web.Models.AddNewSeriesModel @using NzbDrone.Web.Models
@model NzbDrone.Web.Models.AddNewSeriesModel
@section TitleContent{ @{
Add New Series Layout = null;
<script type="text/javascript">
jQuery(document).ready(function () {
$('#searchButton').attr('disabled', '');
});
</script>
} }
@section MainContent{ <div>
<div style="width: 60%">
<div style="display: inline">
@Html.Label("Enter a Series Name")
@Html.TextBox("new_series_name", String.Empty, new {id = "new_series_id"})
<button class="t.button" id="searchButton" disabled="disabled" onclick="searchSeries ()">
Search</button>
</div>
<div style="display: inline; float: right;">
@Html.LabelFor(m => m.QualityProfileId)
@Html.DropDownListFor(m => m.QualityProfileId, Model.QualitySelectList)
</div>
</div>
<div id="result"></div>
<div id="RootDirectories" class="rootDirectories" style="display: none">
<fieldset> <fieldset>
<legend>Root TV Folders</legend> <legend>Root Directory</legend>
@{int d = 0;}
@{int d = 0;
@foreach (var dir in Model.RootDirectories) foreach (var dir in ViewData["RootDirs"] as List<RootDirModel>)
{ {
@Html.RadioButton("selectedRootDir", dir.Path, d == 0, new {@class = "dirList examplePart", id = "dirRadio_" + d}); <div>
@Html.RadioButton("selectedRootDir", dir.CleanPath, d == 0, new { @class = "dirList examplePart", id = "dirRadio_" + d })
@Html.Label(dir.Path) @Html.Label(dir.Path)
@{ d++; }
</div>
}
} }
</fieldset> </fieldset>
<div id="example">
</div> </div>
<button class="t.button" onclick="addSeries ()"> <br/>
Add New Series</button> <div>
@{Html.Telerik().ComboBox()
.Name("seriesList_new")
.DataBinding(binding => binding.Ajax().Select("_textLookUp", "AddSeries").Delay(400))
.Filterable(f => f.FilterMode(AutoCompleteFilterMode.Contains))
.HighlightFirstMatch(true)
.HtmlAttributes(new { style = "width: 300px;" })
.Render();}
@Html.Telerik().DropDownList().Name("qualityList_new").BindTo((SelectList)ViewData["quality"]).HtmlAttributes(new { style = "width: 100px", @class = "qualityDropbox" })
<button class="listButton" onclick="addNewSeries()">
Add</button>
</div> </div>
<div id="addResult"></div>
<script type="text/javascript" language="javascript"> <script type="text/javascript" language="javascript">
var addNewSeriesUrl = '@Url.Action("AddNewSeries", "AddSeries")';
$('#new_series_id').bind('keydown', function (e) { function addNewSeries() {
if (e.keyCode == 13) { var seriesComboBox = $("#seriesList_new").data("tComboBox");
$('#searchButton').click(); var qualityComboBox = $("#qualityList_new").data("tDropDownList");
} var path = $("input[name='selectedRootDir']:checked").val();
});
function searchSeries() { sendToServerNew(seriesComboBox.value(), path, seriesComboBox.text(), qualityComboBox.value());
var seriesSearch = $('#new_series_id');
$("#result").text("Searching...");
$("#result").load('@Url.Action("SearchForSeries", "Series")', {
seriesName: seriesSearch.val()
});
document.getElementById('RootDirectories').style.display = 'inline';
} }
function addSeries() { function sendToServerNew(id, rootPath, seriesName, quality) {
var checkedSeries = $("input[name='selectedSeries']:checked").val(); $.ajax({
var checkedDir = $("input[name='selectedRootDir']:checked").val(); type: "POST",
var id = "#" + checkedSeries + "_text"; url: addNewSeriesUrl,
var seriesName = $(id).val(); data: jQuery.param({ rootPath: rootPath, seriesName: seriesName, seriesId: id, qualityProfileId: quality }),
var qualityProfileId = $("#QualityProfileId").val(); error: function (req, status, error) {
alert("Sorry! We could not add " + path + " at this time. " + error);
$("#addResult").load('@Url.Action("AddSeries", "AddSeries")', { },
dir: checkedDir, success: function (){
seriesId: checkedSeries, //Clear the search box
seriesName: seriesName, $("#seriesList_new").data("tComboBox").text('');
qualityProfileId: qualityProfileId
}); //Close the Window!
closeAddNewSeries();
} }
//Need to figure out how to use 'ViewData["DirSep"]' instead of hardcoding '\'
$(".examplePart").live("change", function () {
var dir = $("input[name='selectedRootDir']:checked").val();
var series = $("input[name='selectedSeries']:checked").val();
var id = "#" + series + "_text";
var seriesName = $(id).val();
var sep = "\\";
var str = "Target: " + dir + sep + seriesName;
$('#example').text(str);
}); });
</script>
} }
</script>

@ -2,16 +2,7 @@
@{Html.Telerik().Menu().Name("telerikGrid").Items(items => @{Html.Telerik().Menu().Name("telerikGrid").Items(items =>
{ {
items.Add().Text("Add Series") items.Add().Text("Add Series").Action<AddSeriesController>(c => c.Add());
.Items( items.Add().Text("Start RSS Sync").Action<SeriesController>(c => c.RssSync());
subItem => items.Add().Text("Rename All").Action<SeriesController>(c => c.RenameAll());
subItem.Add().Text("New Series").Action<AddSeriesController>(c => c.AddNew()))
.Items(
subItem =>
subItem.Add().Text("Existing Series").Action<AddSeriesController>(c => c.AddExisting()));
items.Add().Text("Start RSS Sync").Action<SeriesController>(
c => c.RssSync());
items.Add().Text("Rename All").Action<SeriesController>(
c => c.RenameAll());
}).Render();} }).Render();}

@ -1,58 +1 @@
<style> Hello World
#container {
width: 850px;
margin: auto;
}
.back
{
position:absolute;
top:0;left:0;
}
.wrap
{
width:550px;
height:390px;
position:relative;
margin:auto;
overflow:hidden;
}
.comment
{
position: absolute;
width: 550px;
height: auto;
top: 400px;
left: 0px;
letter-spacing: -1px;
color: white; font: 24px/45px Berlin Sans FB, Sans-Serif;
background: #4A4D4A;
padding: 10px;
filter:alpha(opacity=60);
-moz-opacity:0.6;
-khtml-opacity: 0.6;
opacity: 0.6;
line-height: 90%
}
</style>
<button onclick="overlay()">Click Me!</button>
<div class="wrap">
<img class="backer" src="../../Content/leopard.jpg" alt="image"/>
<span class="comment">
Loading...
</span>
</div>
<script type="text/javascript">
function overlay() {
$('.wrap').children('.comment').stop().css("top", "0px");
}
</script>
Loading…
Cancel
Save