Merge branch 'markus101'

Conflicts:
	NzbDrone.Core/Providers/EpisodeProvider.cs
This commit is contained in:
kay.one 2011-05-28 12:55:51 -07:00
commit f819a24e65
9 changed files with 198 additions and 209 deletions

View File

@ -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();
}
} }
} }

View File

@ -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
var profiles = _qualityProvider.GetAllProfiles();
var selectList = new SelectList(profiles, "QualityProfileId", "Name");
var defaultQuality = Convert.ToInt32(_configProvider.DefaultQualityProfile);
var model = new AddNewSeriesModel
{ {
DirectorySeparatorChar = Path.DirectorySeparatorChar.ToString(), Path = r.Path,
RootDirectories = _rootFolderProvider.GetAll(), CleanPath = r.Path.Replace(Path.DirectorySeparatorChar, '|').Replace(Path.VolumeSeparatorChar, '^').Replace('\'', '`')
QualityProfileId = defaultQuality, }).ToList();
QualitySelectList = selectList ViewData["RootDirs"] = rootDirs;
}; ViewData["DirSep"] = Path.DirectorySeparatorChar.ToString().Replace(Path.DirectorySeparatorChar, '|');
return View(model); var defaultQuality = _configProvider.DefaultQualityProfile;
var qualityProfiles = _qualityProvider.GetAllProfiles();
ViewData["quality"] = new SelectList(
qualityProfiles,
"QualityProfileId",
"Name",
defaultQuality);
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

View File

@ -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; }
}
}

View File

@ -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.

View File

@ -0,0 +1,70 @@
@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.Telerik().DropDownList().Name("masterDropbox").BindTo((SelectList) ViewData["qualities"]).HtmlAttributes(
new {style = "width: 100px; margin-left:5px;"}).ClientEvents(events => events.OnChange("masterChanged"))
<button onclick="openAddNewSeries(); return false;" class="listButton" style="margin-left:210px">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();
}
function masterChanged() {
var masterQuality = $('#masterDropbox').data("tDropDownList").value();
var qualityDropbox = $(".qualityDropbox");
qualityDropbox.each(function () {
var child = $(this).children("[id^='qualityList']");
var comboBox = child.data("tDropDownList");
comboBox.value(masterQuality);
});
}
function testValue() {
var comboBox = $('#qualityList_tester').data("tDropDownList");
comboBox.value('2');
}
</script>

View File

@ -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>
}

View File

@ -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;}
@foreach (var dir in Model.RootDirectories) @{int d = 0;
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> <br/>
<button class="t.button" onclick="addSeries ()"> <div>
Add New Series</button> @{Html.Telerik().ComboBox()
</div> .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 id="addResult"></div> <script type="text/javascript" language="javascript">
var addNewSeriesUrl = '@Url.Action("AddNewSeries", "AddSeries")';
<script type="text/javascript" language="javascript"> function addNewSeries() {
var seriesComboBox = $("#seriesList_new").data("tComboBox");
var qualityComboBox = $("#qualityList_new").data("tDropDownList");
var path = $("input[name='selectedRootDir']:checked").val();
$('#new_series_id').bind('keydown', function (e) { sendToServerNew(seriesComboBox.value(), path, seriesComboBox.text(), qualityComboBox.value());
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() { 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);
},
success: function (){
//Clear the search box
$("#seriesList_new").data("tComboBox").text('');
$("#addResult").load('@Url.Action("AddSeries", "AddSeries")', { //Close the Window!
dir: checkedDir, closeAddNewSeries();
seriesId: checkedSeries, }
seriesName: seriesName,
qualityProfileId: qualityProfileId
}); });
} }
</script>
//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>
}

View File

@ -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();}

View File

@ -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>