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\NzbInfoModel.cs" />
<Compile Include="Model\NzbSiteModel.cs" /> <Compile Include="Model\NzbSiteModel.cs" />
<Compile Include="Model\SabnzbdPriorityType.cs" /> <Compile Include="Model\SabnzbdPriorityType.cs" />
<Compile Include="Model\SeriesMappingModel.cs" />
<Compile Include="Providers\ExternalNotificationProvider.cs" /> <Compile Include="Providers\ExternalNotificationProvider.cs" />
<Compile Include="Providers\HistoryProvider.cs" /> <Compile Include="Providers\HistoryProvider.cs" />
<Compile Include="Providers\IExtenalNotificationProvider.cs" /> <Compile Include="Providers\IExtenalNotificationProvider.cs" />

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

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

@ -76,6 +76,11 @@ namespace NzbDrone.Core.Providers
return _tvDb.GetSeries(searchResults.Id, false); return _tvDb.GetSeries(searchResults.Id, false);
} }
public TvdbSeries MapPathToSeries(int tvDbId)
{
return _tvDb.GetSeries(tvDbId, false);
}
public void AddSeries(string path, TvdbSeries series) public void AddSeries(string path, TvdbSeries series)
{ {
Logger.Info("Adding Series [{0}]:{1} Path: {2}", series.Id, series.SeriesName, path); 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.Linq;
using System.Threading; using System.Threading;
using NLog; using NLog;
using NzbDrone.Core.Model;
using NzbDrone.Core.Model.Notification; using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
@ -19,7 +20,7 @@ namespace NzbDrone.Core.Providers
private ProgressNotification _seriesSyncNotification; private ProgressNotification _seriesSyncNotification;
private Thread _seriesSyncThread; private Thread _seriesSyncThread;
private List<string> _syncList; private List<SeriesMappingModel> _syncList;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
@ -62,7 +63,7 @@ namespace NzbDrone.Core.Providers
#endregion #endregion
public bool BeginSyncUnmappedFolders(List<string> paths) public bool BeginSyncUnmappedFolders(List<SeriesMappingModel> unmapped)
{ {
Logger.Debug("User has request series folder scan"); Logger.Debug("User has request series folder scan");
if (_seriesSyncThread == null || !_seriesSyncThread.IsAlive) if (_seriesSyncThread == null || !_seriesSyncThread.IsAlive)
@ -74,7 +75,7 @@ namespace NzbDrone.Core.Providers
Priority = ThreadPriority.Lowest Priority = ThreadPriority.Lowest
}; };
_syncList = paths; _syncList = unmapped;
_seriesSyncThread.Start(); _seriesSyncThread.Start();
} }
else else
@ -105,20 +106,20 @@ namespace NzbDrone.Core.Providers
{ {
try 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); Logger.Debug("Folder '{0}' is mapped in the database. Skipping.'", seriesFolder);
continue; continue;
} }
Logger.Debug("Folder '{0}' isn't mapped in the database. Trying to map it.'", seriesFolder); 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) 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 else
{ {
@ -126,7 +127,7 @@ namespace NzbDrone.Core.Providers
if (_seriesProvider.GetSeries(mappedSeries.Id) == null) if (_seriesProvider.GetSeries(mappedSeries.Id) == null)
{ {
_seriesSyncNotification.CurrentStatus = String.Format("{0}: downloading series info...", mappedSeries.SeriesName); _seriesSyncNotification.CurrentStatus = String.Format("{0}: downloading series info...", mappedSeries.SeriesName);
_seriesProvider.AddSeries(seriesFolder, mappedSeries); _seriesProvider.AddSeries(seriesFolder.Path, mappedSeries);
_episodeProvider.RefreshEpisodeInfo(mappedSeries.Id); _episodeProvider.RefreshEpisodeInfo(mappedSeries.Id);
_seriesSyncNotification.CurrentStatus = String.Format("{0}: finding episodes on disk...", mappedSeries.SeriesName); _seriesSyncNotification.CurrentStatus = String.Format("{0}: finding episodes on disk...", mappedSeries.SeriesName);
_mediaFileProvider.Scan(_seriesProvider.GetSeries(mappedSeries.Id)); _mediaFileProvider.Scan(_seriesProvider.GetSeries(mappedSeries.Id));

@ -1,14 +1,18 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Web; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using NzbDrone.Web.Models; using NzbDrone.Web.Models;
using Telerik.Web.Mvc; using Telerik.Web.Mvc;
using TvdbLib.Data;
using EpisodeModel = NzbDrone.Web.Models.EpisodeModel;
namespace NzbDrone.Web.Controllers namespace NzbDrone.Web.Controllers
{ {
@ -50,7 +54,7 @@ namespace NzbDrone.Web.Controllers
public ActionResult Add() public ActionResult Add()
{ {
return View(new AddSeriesModel()); return View(new AddNewSeriesModel());
} }
public ActionResult AddExisting() public ActionResult AddExisting()
@ -58,13 +62,6 @@ namespace NzbDrone.Web.Controllers
return View(); return View();
} }
public ActionResult Sync(List<String> paths)
{
//Todo: Make this do something...
_syncProvider.BeginSyncUnmappedFolders(paths);
return RedirectToAction("Index");
}
public ActionResult RssSync() public ActionResult RssSync()
{ {
_rssSyncProvider.Begin(); _rssSyncProvider.Begin();
@ -115,18 +112,52 @@ namespace NzbDrone.Web.Controllers
[GridAction] [GridAction]
public ActionResult _AjaxUnmappedFoldersGrid() public ActionResult _AjaxUnmappedFoldersGrid()
{ {
var unmappedList = new List<String>(); var unmappedList = new List<AddExistingSeriesModel>();
foreach (var folder in _rootDirProvider.GetAll()) 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 var unmappedList = new List<SeriesMappingModel>();
{
IsWanted = true, foreach (var checkedRecord in checkedRecords)
Path = c {
}); 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) private IEnumerable<Episode> GetData(GridCommand command)

@ -9,5 +9,7 @@ namespace NzbDrone.Web.Models
{ {
public bool IsWanted { get; set; } public bool IsWanted { get; set; }
public string Path { 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 namespace NzbDrone.Web.Models
{ {
public class AddSeriesModel public class AddNewSeriesModel
{ {
[Required(ErrorMessage = "Please enter a series name")]
[DataType(DataType.Text)] [DataType(DataType.Text)]
[DisplayName("Single Series Path")] [DisplayName("Single Series Path")]
[DisplayFormat(ConvertEmptyStringToNull = false)] [DisplayFormat(ConvertEmptyStringToNull = false)]
public string SingleSeries { get; set; } public string SeriesName { get; set; }
[DataType(DataType.Text)]
[DisplayName("Series Root Path")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string SeriesRoot { get; set; }
} }
} }

@ -70,6 +70,10 @@
<Reference Include="System.EnterpriseServices" /> <Reference Include="System.EnterpriseServices" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="Telerik.Web.Mvc, Version=2010.3.1318.235, Culture=neutral, PublicKeyToken=121fae78165ba3d4, processorArchitecture=MSIL" /> <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>
<ItemGroup> <ItemGroup>
<Compile Include="Controllers\AccountController.cs" /> <Compile Include="Controllers\AccountController.cs" />
@ -87,7 +91,7 @@
<Compile Include="Helpers\IsCurrentActionHelper.cs" /> <Compile Include="Helpers\IsCurrentActionHelper.cs" />
<Compile Include="Models\AccountModels.cs" /> <Compile Include="Models\AccountModels.cs" />
<Compile Include="Models\AddExistingSeriesModel.cs" /> <Compile Include="Models\AddExistingSeriesModel.cs" />
<Compile Include="Models\AddSeriesModel.cs" /> <Compile Include="Models\AddNewSeriesModel.cs" />
<Compile Include="Models\DownloadSettingsModel.cs" /> <Compile Include="Models\DownloadSettingsModel.cs" />
<Compile Include="Models\EpisodeSortingModel.cs" /> <Compile Include="Models\EpisodeSortingModel.cs" />
<Compile Include="Models\IndexerSettingsModel.cs" /> <Compile Include="Models\IndexerSettingsModel.cs" />
@ -273,6 +277,7 @@
<Content Include="Views\Home\Test.aspx" /> <Content Include="Views\Home\Test.aspx" />
<Content Include="Views\Log\Index.aspx" /> <Content Include="Views\Log\Index.aspx" />
<Content Include="Views\Series\AddExisting.aspx" /> <Content Include="Views\Series\AddExisting.aspx" />
<Content Include="Views\Series\AddNew.aspx" />
<Content Include="Views\Series\Details.aspx" /> <Content Include="Views\Series\Details.aspx" />
<Content Include="Views\Series\Edit.aspx" /> <Content Include="Views\Series\Edit.aspx" />
<Content Include="Views\Series\EpisodeDetail.ascx" /> <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"> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Add Series Add Series

@ -12,24 +12,103 @@
%> %>
</asp:Content> </asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <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 //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") Html.Telerik().Grid<AddExistingSeriesModel>().Name("Unmapped_Series_Folders")
.Columns(columns => .TableHtmlAttributes(new { id = "UnmappedSeriesGrid" })
{ .Columns(columns =>
columns.Bound(c => c.IsWanted).Width(0).Title("Is Wanted?"); {
columns.Bound(c => c.Path); 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' />")
//.DetailView(detailView => detailView.Template(e => Html.RenderPartial("EpisodeDetail", e))) .HtmlAttributes(new { style = "text-align:center" });
//.DetailView(detailView => detailView.ClientTemplate("<div><#= Overview #></div>"))
//.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber).Descending()).Enabled(true)) columns.Bound(c => c.Path);
.Footer(false) columns.Bound(c => c.TvDbName);
.DataBinding(d => d.Ajax().Select("_AjaxUnmappedFoldersGrid", "Series")) })
//.EnableCustomBinding(true) .DataBinding(d => d.Ajax().Select("_AjaxUnmappedFoldersGrid", "Series"))
//.ClientEvents(e => e.OnDetailViewExpand("episodeDetailExpanded")) //Causes issues displaying the episode detail multiple times... .ClientEvents(events => events.OnRowDataBound("Grid_onRowDataBound"))
.Footer(false)
.Render(); .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> </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 => <% Html.Telerik().Menu().Name("telerikGrid").Items(items =>
{ {
items.Add().Text("View Unmapped Folders").Action("Unmapped", "Series"); 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("Start RSS Sync").Action("RssSync", "Series");
items.Add().Text("Rename All").Action("RenameAll", "Series"); items.Add().Text("Rename All").Action("RenameAll", "Series");
items.Add().Text("Add Series").Action("Add", "Series"); items.Add().Text("Add Series").Action("Add", "Series");

Loading…
Cancel
Save