Add Existing Series works, UI shows TVDB Name and Path so you can check before adding to DB.

pull/3113/head
markus101 14 years ago
parent 64a1b2d28d
commit 48b89abfeb

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Model
{
public class SeriesMappingModel
{
public string Path { get; set; }
public int TvDbId { get; set; }
}
}

@ -174,6 +174,7 @@
<Compile Include="Model\NzbInfoModel.cs" />
<Compile Include="Model\NzbSiteModel.cs" />
<Compile Include="Model\SabnzbdPriorityType.cs" />
<Compile Include="Model\SeriesMappingModel.cs" />
<Compile Include="Providers\ExternalNotificationProvider.cs" />
<Compile Include="Providers\HistoryProvider.cs" />
<Compile Include="Providers\IExtenalNotificationProvider.cs" />

@ -19,6 +19,7 @@ namespace NzbDrone.Core.Providers
/// <returns>Whether or not the show is monitored</returns>
bool IsMonitored(long id);
TvdbSeries MapPathToSeries(string path);
TvdbSeries MapPathToSeries(int tvDbId);
void AddSeries(string path, TvdbSeries series);
Series FindSeries(string cleanTitle);
bool QualityWanted(int seriesId, QualityTypes quality);

@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
using NzbDrone.Core.Model;
namespace NzbDrone.Core.Providers
{
public interface ISyncProvider
{
bool BeginSyncUnmappedFolders(List<string> paths);
bool BeginSyncUnmappedFolders(List<SeriesMappingModel> unmapped);
List<String> GetUnmappedFolders(string path);
}
}

@ -76,6 +76,11 @@ namespace NzbDrone.Core.Providers
return _tvDb.GetSeries(searchResults.Id, false);
}
public TvdbSeries MapPathToSeries(int tvDbId)
{
return _tvDb.GetSeries(tvDbId, false);
}
public void AddSeries(string path, TvdbSeries series)
{
Logger.Info("Adding Series [{0}]:{1} Path: {2}", series.Id, series.SeriesName, path);

@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using NLog;
using NzbDrone.Core.Model;
using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Providers
@ -19,7 +20,7 @@ namespace NzbDrone.Core.Providers
private ProgressNotification _seriesSyncNotification;
private Thread _seriesSyncThread;
private List<string> _syncList;
private List<SeriesMappingModel> _syncList;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
@ -62,7 +63,7 @@ namespace NzbDrone.Core.Providers
#endregion
public bool BeginSyncUnmappedFolders(List<string> paths)
public bool BeginSyncUnmappedFolders(List<SeriesMappingModel> unmapped)
{
Logger.Debug("User has request series folder scan");
if (_seriesSyncThread == null || !_seriesSyncThread.IsAlive)
@ -74,7 +75,7 @@ namespace NzbDrone.Core.Providers
Priority = ThreadPriority.Lowest
};
_syncList = paths;
_syncList = unmapped;
_seriesSyncThread.Start();
}
else
@ -105,20 +106,20 @@ namespace NzbDrone.Core.Providers
{
try
{
_seriesSyncNotification.CurrentStatus = String.Format("Searching For: {0}", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(new DirectoryInfo(seriesFolder).Name));
_seriesSyncNotification.CurrentStatus = String.Format("Searching For: {0}", new DirectoryInfo(seriesFolder.Path).Name);
if (_seriesProvider.SeriesPathExists(Parser.NormalizePath(seriesFolder)))
if (_seriesProvider.SeriesPathExists(Parser.NormalizePath(seriesFolder.Path)))
{
Logger.Debug("Folder '{0}' is mapped in the database. Skipping.'", seriesFolder);
continue;
}
Logger.Debug("Folder '{0}' isn't mapped in the database. Trying to map it.'", seriesFolder);
var mappedSeries = _seriesProvider.MapPathToSeries(seriesFolder);
var mappedSeries = _seriesProvider.MapPathToSeries(seriesFolder.TvDbId);
if (mappedSeries == null)
{
Logger.Warn("Unable to find a matching series for '{0}'", seriesFolder);
Logger.Warn("Invalid TVDB ID '{0}' Unable to map: '{1}'", seriesFolder.TvDbId, seriesFolder.Path);
}
else
{
@ -126,7 +127,7 @@ namespace NzbDrone.Core.Providers
if (_seriesProvider.GetSeries(mappedSeries.Id) == null)
{
_seriesSyncNotification.CurrentStatus = String.Format("{0}: downloading series info...", mappedSeries.SeriesName);
_seriesProvider.AddSeries(seriesFolder, mappedSeries);
_seriesProvider.AddSeries(seriesFolder.Path, mappedSeries);
_episodeProvider.RefreshEpisodeInfo(mappedSeries.Id);
_seriesSyncNotification.CurrentStatus = String.Format("{0}: finding episodes on disk...", mappedSeries.SeriesName);
_mediaFileProvider.Scan(_seriesProvider.GetSeries(mappedSeries.Id));

@ -1,14 +1,18 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Web.Models;
using Telerik.Web.Mvc;
using TvdbLib.Data;
using EpisodeModel = NzbDrone.Web.Models.EpisodeModel;
namespace NzbDrone.Web.Controllers
{
@ -50,7 +54,7 @@ namespace NzbDrone.Web.Controllers
public ActionResult Add()
{
return View(new AddSeriesModel());
return View(new AddNewSeriesModel());
}
public ActionResult AddExisting()
@ -58,13 +62,6 @@ namespace NzbDrone.Web.Controllers
return View();
}
public ActionResult Sync(List<String> paths)
{
//Todo: Make this do something...
_syncProvider.BeginSyncUnmappedFolders(paths);
return RedirectToAction("Index");
}
public ActionResult RssSync()
{
_rssSyncProvider.Begin();
@ -115,18 +112,52 @@ namespace NzbDrone.Web.Controllers
[GridAction]
public ActionResult _AjaxUnmappedFoldersGrid()
{
var unmappedList = new List<String>();
var unmappedList = new List<AddExistingSeriesModel>();
foreach (var folder in _rootDirProvider.GetAll())
unmappedList.AddRange(_syncProvider.GetUnmappedFolders(folder.Path));
{
foreach (var unmappedFolder in _syncProvider.GetUnmappedFolders(folder.Path))
{
var tvDbSeries = _seriesProvider.MapPathToSeries(unmappedFolder);
//We still want to show this series as unmapped, but we don't know what it will be when mapped
//Todo: Provide the user with a way to manually map a folder to a TvDb series (or make them rename the folder...)
if (tvDbSeries == null)
tvDbSeries = new TvdbSeries {Id = 0, SeriesName = String.Empty};
unmappedList.Add(new AddExistingSeriesModel
{
IsWanted = true,
Path = unmappedFolder,
TvDbId = tvDbSeries.Id,
TvDbName = tvDbSeries.SeriesName
});
}
}
return View(new GridModel(unmappedList));
}
public ActionResult SyncSelectedSeries(List<String> checkedRecords)
{
var seriesPaths = unmappedList.Select(c => new AddExistingSeriesModel
{
IsWanted = true,
Path = c
});
var unmappedList = new List<SeriesMappingModel>();
foreach (var checkedRecord in checkedRecords)
{
NameValueCollection nvc = HttpUtility.ParseQueryString(checkedRecord);
var path = HttpUtility.UrlDecode(nvc["path"]);
var tvDbId = Convert.ToInt32(HttpUtility.UrlDecode(nvc["tvdbid"]));
//If the TvDbId for this show is 0 then skip it... User made a mistake... They will have to manually map it
if (tvDbId < 1) continue;
unmappedList.Add(new SeriesMappingModel{Path = path, TvDbId = tvDbId});
}
return View(new GridModel(seriesPaths));
_syncProvider.BeginSyncUnmappedFolders(unmappedList);
return Content("Sync Started for Selected Series");
}
private IEnumerable<Episode> GetData(GridCommand command)

@ -9,5 +9,7 @@ namespace NzbDrone.Web.Models
{
public bool IsWanted { get; set; }
public string Path { get; set; }
public int TvDbId { get; set; }
public string TvDbName { get; set; }
}
}

@ -7,16 +7,12 @@ using System.Web;
namespace NzbDrone.Web.Models
{
public class AddSeriesModel
public class AddNewSeriesModel
{
[Required(ErrorMessage = "Please enter a series name")]
[DataType(DataType.Text)]
[DisplayName("Single Series Path")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string SingleSeries { get; set; }
[DataType(DataType.Text)]
[DisplayName("Series Root Path")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string SeriesRoot { get; set; }
public string SeriesName { get; set; }
}
}

@ -70,6 +70,10 @@
<Reference Include="System.EnterpriseServices" />
<Reference Include="System.Xml.Linq" />
<Reference Include="Telerik.Web.Mvc, Version=2010.3.1318.235, Culture=neutral, PublicKeyToken=121fae78165ba3d4, processorArchitecture=MSIL" />
<Reference Include="TvdbLib, Version=0.8.8.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\TvdbLib.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Controllers\AccountController.cs" />
@ -87,7 +91,7 @@
<Compile Include="Helpers\IsCurrentActionHelper.cs" />
<Compile Include="Models\AccountModels.cs" />
<Compile Include="Models\AddExistingSeriesModel.cs" />
<Compile Include="Models\AddSeriesModel.cs" />
<Compile Include="Models\AddNewSeriesModel.cs" />
<Compile Include="Models\DownloadSettingsModel.cs" />
<Compile Include="Models\EpisodeSortingModel.cs" />
<Compile Include="Models\IndexerSettingsModel.cs" />
@ -273,6 +277,7 @@
<Content Include="Views\Home\Test.aspx" />
<Content Include="Views\Log\Index.aspx" />
<Content Include="Views\Series\AddExisting.aspx" />
<Content Include="Views\Series\AddNew.aspx" />
<Content Include="Views\Series\Details.aspx" />
<Content Include="Views\Series\Edit.aspx" />
<Content Include="Views\Series\EpisodeDetail.ascx" />

@ -1,4 +1,4 @@
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NzbDrone.Web.Models.AddSeriesModel>" %>
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Add Series

@ -12,24 +12,103 @@
%>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<script type="text/javascript">
$(document).ready(function () {
$('#mastercheckbox').attr("checked", "checked");
});
function Grid_onRowDataBound(e) {
//the DOM element (<tr>) representing the row which is being databound
var row = e.row;
//the data item - JavaScript object.
var tvDbId = e.dataItem.TvDbId;
$(row).attr('id', 'row_' + tvDbId);
//var info = row.cells[1].text();
//row.cells[1].innerHTML = '<strong>' + dataItem + '</strong>';
//You can use the OnRowDataBound event to customize the way data is presented on the client-side
};
</script>
//Get AJAX listing of unmapped directories
//When getting unmapped, also do a quick lookup on TVDB to see which series we would map this to... Don't do the mapping though...
//ITvDbProvider.GetSeries(string title);
<%
Html.Telerik().Grid<AddExistingSeriesModel>().Name("Unmapped Series Folders")
.Columns(columns =>
{
columns.Bound(c => c.IsWanted).Width(0).Title("Is Wanted?");
columns.Bound(c => c.Path);
})
//.DetailView(detailView => detailView.Template(e => Html.RenderPartial("EpisodeDetail", e)))
//.DetailView(detailView => detailView.ClientTemplate("<div><#= Overview #></div>"))
//.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber).Descending()).Enabled(true))
.Footer(false)
.DataBinding(d => d.Ajax().Select("_AjaxUnmappedFoldersGrid", "Series"))
//.EnableCustomBinding(true)
//.ClientEvents(e => e.OnDetailViewExpand("episodeDetailExpanded")) //Causes issues displaying the episode detail multiple times...
Html.Telerik().Grid<AddExistingSeriesModel>().Name("Unmapped_Series_Folders")
.TableHtmlAttributes(new { id = "UnmappedSeriesGrid" })
.Columns(columns =>
{
columns.Bound(c => c.IsWanted).ClientTemplate("<input type='checkbox' name='<#= Path #>' class='checkedSeries' value='<#= TvDbId #>' checked='true'/>")
.Width(20).Title("<input id='mastercheckbox' type='checkbox' />")
.HtmlAttributes(new { style = "text-align:center" });
columns.Bound(c => c.Path);
columns.Bound(c => c.TvDbName);
})
.DataBinding(d => d.Ajax().Select("_AjaxUnmappedFoldersGrid", "Series"))
.ClientEvents(events => events.OnRowDataBound("Grid_onRowDataBound"))
.Footer(false)
.Render();
%>`
%>
<p>
<button class="t.button" onclick="syncSelected ()">Sync Selected Series</button>
</p>
<div id="result"></div>
<div id="tester"></div>
<script type="text/javascript" language="javascript">
// MasterCheckBox functionality
$('#mastercheckbox').click(function () {
if ($(this).attr('checked')) {
$('.checkedSeries').attr('checked', true);
} else {
$('.checkedSeries').attr('checked', false);
}
});
//Unchecking a 'normal' checkbox should clear the mastercheckbox as well
$(".checkedSeries").live("click", function () {
var numChkBoxes = $('.checkedSeries').length;
var numChkBoxesChecked = $('.checkedSeries:checked').length;
if (numChkBoxes == numChkBoxesChecked & numChkBoxes > 0) {
$('#mastercheckbox').attr('checked', true);
}
else {
$('#mastercheckbox').attr('checked', false);
}
});
//Sync for selected series
function syncSelected() {
var $checkedRecords = $('.checkedSeries:checked');
if ($checkedRecords.length < 1) {
alert("Check one or more series first");
return;
}
$("#result").load('<%=Url.Action("SyncSelectedSeries", "Series") %>', {
checkedRecords: $checkedRecords.map(function () { return jQuery.param({ path: this.name, tvdbid: this.value }) })
}
//this.window.location = '<%= Url.Action("Index", "Series") %>';
);
var grid = $('#UnmappedSeriesGrid').data('tGrid');
}
</script>
</asp:Content>

@ -0,0 +1,32 @@
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<AddNewSeriesModel>" %>
<%@ Import Namespace="NzbDrone.Web.Models" %>
<%@ Import Namespace="Telerik.Web.Mvc.UI" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Add New Series
</asp:Content>
<asp:Content ID="Menu" ContentPlaceHolderID="ActionMenu" runat="server">
<%
Html.RenderPartial("SubMenu");
%>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
//Add a new series
<%= Html.Label("Enter a Series Name") %>
<%= Html.TextBox("new_series_name", new { id="new_series_id" }) %>
//Browse Button??
//Auto-Complete?
//Search Button - Perform AJAX search for this Series on TVDB
//Return results with Radio Box + First Aired information, (link to TVDB too?) + Hidden ID text
User selects radio button and then presses add (or skips which clears results and #new_series_id)
Add, ask user to choose where to save the show in (used when sorting) then add the show... Possibly ask user to choose Quality Profile
</asp:Content>

@ -5,7 +5,6 @@
<% Html.Telerik().Menu().Name("telerikGrid").Items(items =>
{
items.Add().Text("View Unmapped Folders").Action("Unmapped", "Series");
items.Add().Text("Sync With Disk").Action("Sync", "Series", new { paths = "test" });
items.Add().Text("Start RSS Sync").Action("RssSync", "Series");
items.Add().Text("Rename All").Action("RenameAll", "Series");
items.Add().Text("Add Series").Action("Add", "Series");

Loading…
Cancel
Save