mirror of https://github.com/Radarr/Radarr
Merge branch 'markus101'
Conflicts: NzbDrone.Core/Providers/EpisodeProvider.cs
This commit is contained in:
commit
f819a24e65
|
@ -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,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>
|
|
@ -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>
|
||||
<fieldset>
|
||||
<legend>Root Directory</legend>
|
||||
|
||||
@{int d = 0;
|
||||
|
||||
<div id="result"></div>
|
||||
|
||||
<div id="RootDirectories" class="rootDirectories" style="display: none">
|
||||
<fieldset>
|
||||
<legend>Root TV Folders</legend>
|
||||
@{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>
|
||||
}
|
||||
</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>
|
||||
|
||||
<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();
|
||||
|
||||
sendToServerNew(seriesComboBox.value(), path, seriesComboBox.text(), qualityComboBox.value());
|
||||
}
|
||||
|
||||
$('#new_series_id').bind('keydown', function (e) {
|
||||
if (e.keyCode == 13) {
|
||||
$('#searchButton').click();
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
});
|
||||
</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…
Reference in New Issue