mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-12 11:15:43 +02:00
Add Existing Series works, UI shows TVDB Name and Path so you can check before adding to DB.
This commit is contained in:
parent
64a1b2d28d
commit
48b89abfeb
13
NzbDrone.Core/Model/SeriesMappingModel.cs
Normal file
13
NzbDrone.Core/Model/SeriesMappingModel.cs
Normal file
@ -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 @@ public interface ISeriesProvider
|
||||
/// <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 @@ public TvdbSeries MapPathToSeries(string path)
|
||||
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.Linq;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Model.Notification;
|
||||
|
||||
namespace NzbDrone.Core.Providers
|
||||
@ -19,7 +20,7 @@ public class SyncProvider : ISyncProvider
|
||||
|
||||
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 @@ public List<String> GetUnmappedFolders(string path)
|
||||
|
||||
#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 @@ public bool BeginSyncUnmappedFolders(List<string> paths)
|
||||
Priority = ThreadPriority.Lowest
|
||||
};
|
||||
|
||||
_syncList = paths;
|
||||
_syncList = unmapped;
|
||||
_seriesSyncThread.Start();
|
||||
}
|
||||
else
|
||||
@ -105,20 +106,20 @@ private void SyncUnmappedFolders()
|
||||
{
|
||||
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 @@ private void SyncUnmappedFolders()
|
||||
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 @@ public ActionResult Index()
|
||||
|
||||
public ActionResult Add()
|
||||
{
|
||||
return View(new AddSeriesModel());
|
||||
return View(new AddNewSeriesModel());
|
||||
}
|
||||
|
||||
public ActionResult AddExisting()
|
||||
@ -58,13 +62,6 @@ public ActionResult AddExisting()
|
||||
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 @@ public ActionResult _CustomBinding(GridCommand command, int seasonId)
|
||||
[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);
|
||||
|
||||
var seriesPaths = unmappedList.Select(c => new AddExistingSeriesModel
|
||||
{
|
||||
IsWanted = true,
|
||||
Path = c
|
||||
});
|
||||
//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(seriesPaths));
|
||||
return View(new GridModel(unmappedList));
|
||||
}
|
||||
|
||||
public ActionResult SyncSelectedSeries(List<String> checkedRecords)
|
||||
{
|
||||
|
||||
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});
|
||||
}
|
||||
|
||||
_syncProvider.BeginSyncUnmappedFolders(unmappedList);
|
||||
return Content("Sync Started for Selected Series");
|
||||
}
|
||||
|
||||
private IEnumerable<Episode> GetData(GridCommand command)
|
||||
|
@ -9,5 +9,7 @@ public class AddExistingSeriesModel
|
||||
{
|
||||
public bool IsWanted { get; set; }
|
||||
public string Path { get; set; }
|
||||
public int TvDbId { get; set; }
|
||||
public string TvDbName { get; set; }
|
||||
}
|
||||
}
|
@ -7,16 +7,12 @@
|
||||
|
||||
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...
|
||||
.Render();
|
||||
%>`
|
||||
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>
|
||||
|
32
NzbDrone.Web/Views/Series/AddNew.aspx
Normal file
32
NzbDrone.Web/Views/Series/AddNew.aspx
Normal file
@ -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…
Reference in New Issue
Block a user