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,
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.IO;
using System.Web.Mvc;
using System.Linq;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Jobs;
@ -18,11 +20,13 @@ namespace NzbDrone.Web.Controllers
private readonly JobProvider _jobProvider;
private readonly SyncProvider _syncProvider;
private readonly TvDbProvider _tvDbProvider;
private readonly DiskProvider _diskProvider;
public AddSeriesController(SyncProvider syncProvider, RootDirProvider rootFolderProvider,
ConfigProvider configProvider,
QualityProvider qualityProvider, TvDbProvider tvDbProvider,
SeriesProvider seriesProvider, JobProvider jobProvider)
SeriesProvider seriesProvider, JobProvider jobProvider,
DiskProvider diskProvider)
{
_syncProvider = syncProvider;
_rootFolderProvider = rootFolderProvider;
@ -31,6 +35,7 @@ namespace NzbDrone.Web.Controllers
_tvDbProvider = tvDbProvider;
_seriesProvider = seriesProvider;
_jobProvider = jobProvider;
_diskProvider = diskProvider;
}
[HttpPost]
@ -42,25 +47,28 @@ namespace NzbDrone.Web.Controllers
public ActionResult AddNew()
{
ViewData["RootDirs"] = _rootFolderProvider.GetAll();
ViewData["DirSep"] = Path.DirectorySeparatorChar;
var rootDirs =_rootFolderProvider.GetAll().Select(r =>
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 selectList = new SelectList(profiles, "QualityProfileId", "Name");
var defaultQuality = Convert.ToInt32(_configProvider.DefaultQualityProfile);
var defaultQuality = _configProvider.DefaultQualityProfile;
var qualityProfiles = _qualityProvider.GetAllProfiles();
var model = new AddNewSeriesModel
{
DirectorySeparatorChar = Path.DirectorySeparatorChar.ToString(),
RootDirectories = _rootFolderProvider.GetAll(),
QualityProfileId = defaultQuality,
QualitySelectList = selectList
};
ViewData["quality"] = new SelectList(
qualityProfiles,
"QualityProfileId",
"Name",
defaultQuality);
return View(model);
return View();
}
public ActionResult AddExisting()
public ActionResult Add()
{
var unmappedList = new List<String>();
@ -98,6 +106,20 @@ namespace NzbDrone.Web.Controllers
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)
{
//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\AddExistingSeriesModel.cs" />
<Compile Include="Models\AddNewSeriesModel.cs" />
<Compile Include="Models\RootDirModel.cs" />
<Compile Include="Models\SabnzbdSettingsModel.cs" />
<Compile Include="Models\EpisodeSortingModel.cs" />
<Compile Include="Models\HistoryModel.cs" />
@ -662,7 +663,7 @@
<Content Include="Scripts\jquery-tgc-countdown-1.0.js" />
<Content Include="Scripts\jquery.simpledropdown.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\AddSeriesItem.cshtml" />
<Content Include="Web.config">
@ -870,6 +871,9 @@
<ItemGroup>
<Content Include="Views\Series\SingleSeason.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\AddSeries\Copy of AddNew.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.

@ -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
<script type="text/javascript">
jQuery(document).ready(function () {
$('#searchButton').attr('disabled', '');
});
</script>
@{
Layout = null;
}
@section MainContent{
<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>
<fieldset>
<legend>Root Directory</legend>
<div id="RootDirectories" class="rootDirectories" style="display: none">
<fieldset>
<legend>Root TV Folders</legend>
@{int d = 0;}
@{int d = 0;
@foreach (var dir in Model.RootDirectories)
{
@Html.RadioButton("selectedRootDir", dir.Path, d == 0, new {@class = "dirList examplePart", id = "dirRadio_" + d});
@Html.Label(dir.Path)
foreach (var dir in ViewData["RootDirs"] as List<RootDirModel>)
{
<div>
@Html.RadioButton("selectedRootDir", dir.CleanPath, d == 0, new { @class = "dirList examplePart", id = "dirRadio_" + d })
@Html.Label(dir.Path)
@{ d++; }
</div>
}
</fieldset>
<div id="example">
</div>
<button class="t.button" onclick="addSeries ()">
Add New Series</button>
</div>
<div id="addResult"></div>
<script type="text/javascript" language="javascript">
$('#new_series_id').bind('keydown', function (e) {
if (e.keyCode == 13) {
$('#searchButton').click();
}
});
function searchSeries() {
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() {
var checkedSeries = $("input[name='selectedSeries']:checked").val();
var checkedDir = $("input[name='selectedRootDir']:checked").val();
var id = "#" + checkedSeries + "_text";
var seriesName = $(id).val();
var qualityProfileId = $("#QualityProfileId").val();
$("#addResult").load('@Url.Action("AddSeries", "AddSeries")', {
dir: checkedDir,
seriesId: checkedSeries,
seriesName: seriesName,
qualityProfileId: qualityProfileId
});
}
//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);
</fieldset>
</div>
<br/>
<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>
<script type="text/javascript" language="javascript">
var addNewSeriesUrl = '@Url.Action("AddNewSeries", "AddSeries")';
function addNewSeries() {
var seriesComboBox = $("#seriesList_new").data("tComboBox");
var qualityComboBox = $("#qualityList_new").data("tDropDownList");
var path = $("input[name='selectedRootDir']:checked").val();
sendToServerNew(seriesComboBox.value(), path, seriesComboBox.text(), qualityComboBox.value());
}
function sendToServerNew(id, rootPath, seriesName, quality) {
$.ajax({
type: "POST",
url: addNewSeriesUrl,
data: jQuery.param({ rootPath: rootPath, seriesName: seriesName, seriesId: id, qualityProfileId: quality }),
error: function (req, status, error) {
alert("Sorry! We could not add " + path + " at this time. " + error);
},
success: function (){
//Clear the search box
$("#seriesList_new").data("tComboBox").text('');
//Close the Window!
closeAddNewSeries();
}
});
</script>
}
}
</script>

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

@ -1,58 +1 @@
<style>
#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>
Hello World
Loading…
Cancel
Save