From 2871723bfe6fc16d9b0256c8407ccdece30220bb Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 8 Mar 2011 23:40:48 -0800 Subject: [PATCH] Manage multiple Tv Root Folders in Settings/General. Start of AddExisting. --- NzbDrone.Core.Test/SeriesProviderTest.cs | 28 ++++----- NzbDrone.Core/CentralDispatch.cs | 1 + NzbDrone.Core/NzbDrone.Core.csproj | 3 + NzbDrone.Core/Providers/IRootDirProvider.cs | 16 +++++ NzbDrone.Core/Providers/ISeriesProvider.cs | 3 +- NzbDrone.Core/Providers/ISyncProvider.cs | 7 ++- NzbDrone.Core/Providers/RootDirProvider.cs | 43 ++++++++++++++ NzbDrone.Core/Providers/SeriesProvider.cs | 28 +++------ NzbDrone.Core/Providers/SyncProvider.cs | 59 ++++++++++++++++--- NzbDrone.Core/Repository/RootDir.cs | 18 ++++++ NzbDrone.Web/Controllers/SeriesController.cs | 36 +++++++++-- .../Controllers/SettingsController.cs | 48 +++++++++++---- NzbDrone.Web/Models/AddExistingSeriesModel.cs | 13 ++++ NzbDrone.Web/Models/SettingsModels.cs | 19 +----- NzbDrone.Web/NzbDrone.Web.csproj | 3 + NzbDrone.Web/Views/Series/Add.aspx | 4 ++ NzbDrone.Web/Views/Series/AddExisting.aspx | 35 +++++++++++ NzbDrone.Web/Views/Series/SubMenu.ascx | 2 +- NzbDrone.Web/Views/Settings/General.ascx | 56 +++++++++++++++--- NzbDrone.Web/Views/Settings/RootDir.ascx | 36 +++++++++++ .../Views/Settings/UserProfileSection.ascx | 13 +++- 21 files changed, 381 insertions(+), 90 deletions(-) create mode 100644 NzbDrone.Core/Providers/IRootDirProvider.cs create mode 100644 NzbDrone.Core/Providers/RootDirProvider.cs create mode 100644 NzbDrone.Core/Repository/RootDir.cs create mode 100644 NzbDrone.Web/Models/AddExistingSeriesModel.cs create mode 100644 NzbDrone.Web/Views/Series/AddExisting.aspx create mode 100644 NzbDrone.Web/Views/Settings/RootDir.ascx diff --git a/NzbDrone.Core.Test/SeriesProviderTest.cs b/NzbDrone.Core.Test/SeriesProviderTest.cs index 1ffde78bf..12c7ae557 100644 --- a/NzbDrone.Core.Test/SeriesProviderTest.cs +++ b/NzbDrone.Core.Test/SeriesProviderTest.cs @@ -66,25 +66,25 @@ namespace NzbDrone.Core.Test //Assert.AreEqual(title, result, postTitle); } - [Test] - public void get_unmapped() - { - //Setup - var kernel = new MockingKernel(); + //[Test] + //public void get_unmapped() + //{ + // //Setup + // var kernel = new MockingKernel(); - kernel.Bind().To(); - kernel.Bind().ToConstant(MockLib.GetStandardDisk(0, 0)); - kernel.Bind().ToConstant(MockLib.StandardConfig); + // kernel.Bind().To(); + // kernel.Bind().ToConstant(MockLib.GetStandardDisk(0, 0)); + // kernel.Bind().ToConstant(MockLib.StandardConfig); - var seriesController = kernel.Get(); + // var seriesController = kernel.Get(); - //Act - var unmappedFolder = seriesController.GetUnmappedFolders(); + // //Act + // var unmappedFolder = seriesController.GetUnmappedFolders(); - //Assert - Assert.AreElementsEqualIgnoringOrder(MockLib.StandardSeries, unmappedFolder.Values); - } + // //Assert + // Assert.AreElementsEqualIgnoringOrder(MockLib.StandardSeries, unmappedFolder.Values); + //} } diff --git a/NzbDrone.Core/CentralDispatch.cs b/NzbDrone.Core/CentralDispatch.cs index 803097a05..8fa66af44 100644 --- a/NzbDrone.Core/CentralDispatch.cs +++ b/NzbDrone.Core/CentralDispatch.cs @@ -62,6 +62,7 @@ namespace NzbDrone.Core _kernel.Bind().To(); _kernel.Bind().To(); _kernel.Bind().To(); + _kernel.Bind().To(); _kernel.Bind().To(); _kernel.Bind().To(); _kernel.Bind().To().InSingletonScope(); diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 86709dc9d..08ac3e453 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -183,6 +183,7 @@ + @@ -190,6 +191,7 @@ + @@ -229,6 +231,7 @@ + diff --git a/NzbDrone.Core/Providers/IRootDirProvider.cs b/NzbDrone.Core/Providers/IRootDirProvider.cs new file mode 100644 index 000000000..13897c202 --- /dev/null +++ b/NzbDrone.Core/Providers/IRootDirProvider.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Repository; + +namespace NzbDrone.Core.Providers +{ + public interface IRootDirProvider + { + List GetAll(); + void Add(RootDir rootDir); + void Remove(int rootDirId); + void Update(RootDir rootDir); + } +} diff --git a/NzbDrone.Core/Providers/ISeriesProvider.cs b/NzbDrone.Core/Providers/ISeriesProvider.cs index ced49f977..88ea1fd12 100644 --- a/NzbDrone.Core/Providers/ISeriesProvider.cs +++ b/NzbDrone.Core/Providers/ISeriesProvider.cs @@ -18,13 +18,12 @@ namespace NzbDrone.Core.Providers /// The TVDB ID of the series /// Whether or not the show is monitored bool IsMonitored(long id); - TvdbSeries MapPathToSeries(string path); void AddSeries(string path, TvdbSeries series); - Dictionary GetUnmappedFolders(); Series FindSeries(string cleanTitle); bool QualityWanted(int seriesId, QualityTypes quality); void UpdateSeries(Series series); void DeleteSeries(int seriesId); + bool SeriesPathExists(string cleanPath); } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/ISyncProvider.cs b/NzbDrone.Core/Providers/ISyncProvider.cs index 4f35d39ee..ceec4ea3d 100644 --- a/NzbDrone.Core/Providers/ISyncProvider.cs +++ b/NzbDrone.Core/Providers/ISyncProvider.cs @@ -1,8 +1,11 @@ +using System; +using System.Collections.Generic; + namespace NzbDrone.Core.Providers { public interface ISyncProvider { - void SyncUnmappedFolders(); - void BeginSyncUnmappedFolders(); + bool BeginSyncUnmappedFolders(List paths); + List GetUnmappedFolders(string path); } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/RootDirProvider.cs b/NzbDrone.Core/Providers/RootDirProvider.cs new file mode 100644 index 000000000..d6154e275 --- /dev/null +++ b/NzbDrone.Core/Providers/RootDirProvider.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Repository; +using SubSonic.Repository; + +namespace NzbDrone.Core.Providers +{ + public class RootDirProvider : IRootDirProvider + { + private readonly IRepository _sonioRepo; + + public RootDirProvider(IRepository sonicRepo) + { + _sonioRepo = sonicRepo; + } + + #region IRootDirProvider + + public List GetAll() + { + return _sonioRepo.All().ToList(); + } + + public void Add(RootDir rootDir) + { + _sonioRepo.Add(rootDir); + } + + public void Remove(int rootDirId) + { + _sonioRepo.Delete(rootDirId); + } + + public void Update(RootDir rootDir) + { + _sonioRepo.Update(rootDir); + } + + #endregion + } +} diff --git a/NzbDrone.Core/Providers/SeriesProvider.cs b/NzbDrone.Core/Providers/SeriesProvider.cs index 05b01a370..c38aea801 100644 --- a/NzbDrone.Core/Providers/SeriesProvider.cs +++ b/NzbDrone.Core/Providers/SeriesProvider.cs @@ -65,26 +65,6 @@ namespace NzbDrone.Core.Providers return profile.Allowed.Contains(quality); } - public Dictionary GetUnmappedFolders() - { - Logger.Debug("Generating list of unmapped folders"); - if (String.IsNullOrEmpty(_config.SeriesRoot)) - throw new InvalidOperationException("TV Series folder is not configured yet."); - - var results = new Dictionary(); - foreach (string seriesFolder in _diskProvider.GetDirectories(_config.SeriesRoot)) - { - var cleanPath = Parser.NormalizePath(new DirectoryInfo(seriesFolder).FullName); - if (!_sonioRepo.Exists(s => s.Path == cleanPath)) - { - results.Add(Guid.NewGuid(), cleanPath); - } - } - - Logger.Debug("{0} unmapped folders detected.", results.Count); - return results; - } - public TvdbSeries MapPathToSeries(string path) { var seriesPath = new DirectoryInfo(path); @@ -149,6 +129,14 @@ namespace NzbDrone.Core.Providers _sonioRepo.Delete(seriesId); } + public bool SeriesPathExists(string cleanPath) + { + if (_sonioRepo.Exists(s => s.Path == cleanPath)) + return true; + + return false; + } + #endregion #region Static Helpers diff --git a/NzbDrone.Core/Providers/SyncProvider.cs b/NzbDrone.Core/Providers/SyncProvider.cs index d41831a3d..00c9b0959 100644 --- a/NzbDrone.Core/Providers/SyncProvider.cs +++ b/NzbDrone.Core/Providers/SyncProvider.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using System.Text; using System.Threading; using NLog; using NzbDrone.Core.Model.Notification; @@ -16,21 +15,54 @@ namespace NzbDrone.Core.Providers private readonly IEpisodeProvider _episodeProvider; private readonly IMediaFileProvider _mediaFileProvider; private readonly INotificationProvider _notificationProvider; + private readonly IDiskProvider _diskProvider; private ProgressNotification _seriesSyncNotification; private Thread _seriesSyncThread; + private List _syncList; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public SyncProvider(ISeriesProvider seriesProvider, IEpisodeProvider episodeProvider, IMediaFileProvider mediaFileProvider, INotificationProvider notificationProvider) + public SyncProvider(ISeriesProvider seriesProvider, IEpisodeProvider episodeProvider, + IMediaFileProvider mediaFileProvider, INotificationProvider notificationProvider, + IDiskProvider diskProvider) { _seriesProvider = seriesProvider; _episodeProvider = episodeProvider; _mediaFileProvider = mediaFileProvider; _notificationProvider = notificationProvider; + _diskProvider = diskProvider; } - public void BeginSyncUnmappedFolders() + #region ISyncProvider Members + + public List GetUnmappedFolders(string path) + { + Logger.Debug("Generating list of unmapped folders"); + if (String.IsNullOrEmpty(path)) + throw new InvalidOperationException("Invalid path provided"); + + if (!_diskProvider.FolderExists(path)) + { + Logger.Debug("Path supplied does not exist: {0}", path); + } + + var results = new List(); + foreach (string seriesFolder in _diskProvider.GetDirectories(path)) + { + var cleanPath = Parser.NormalizePath(new DirectoryInfo(seriesFolder).FullName); + + if (!_seriesProvider.SeriesPathExists(cleanPath)) + results.Add(cleanPath); + } + + Logger.Debug("{0} unmapped folders detected.", results.Count); + return results; + } + + #endregion + + public bool BeginSyncUnmappedFolders(List paths) { Logger.Debug("User has request series folder scan"); if (_seriesSyncThread == null || !_seriesSyncThread.IsAlive) @@ -42,15 +74,22 @@ namespace NzbDrone.Core.Providers Priority = ThreadPriority.Lowest }; + _syncList = paths; _seriesSyncThread.Start(); } else { Logger.Warn("Series folder scan already in progress. Ignoring request."); + + //return false if sync was already running, then we can tell the user to try again later + return false; } + + //return true if sync has started + return true; } - public void SyncUnmappedFolders() + private void SyncUnmappedFolders() { Logger.Info("Starting Series folder scan"); @@ -60,15 +99,20 @@ namespace NzbDrone.Core.Providers { _notificationProvider.Register(_seriesSyncNotification); _seriesSyncNotification.CurrentStatus = "Analysing Folder"; - var unmappedFolders = _seriesProvider.GetUnmappedFolders(); - _seriesSyncNotification.ProgressMax = unmappedFolders.Count; + _seriesSyncNotification.ProgressMax = _syncList.Count; - foreach (string seriesFolder in unmappedFolders.Values) + foreach (var seriesFolder in _syncList) { try { _seriesSyncNotification.CurrentStatus = String.Format("Searching For: {0}", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(new DirectoryInfo(seriesFolder).Name)); + if (_seriesProvider.SeriesPathExists(Parser.NormalizePath(seriesFolder))) + { + 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); @@ -86,7 +130,6 @@ namespace NzbDrone.Core.Providers _episodeProvider.RefreshEpisodeInfo(mappedSeries.Id); _seriesSyncNotification.CurrentStatus = String.Format("{0}: finding episodes on disk...", mappedSeries.SeriesName); _mediaFileProvider.Scan(_seriesProvider.GetSeries(mappedSeries.Id)); - } else { diff --git a/NzbDrone.Core/Repository/RootDir.cs b/NzbDrone.Core/Repository/RootDir.cs new file mode 100644 index 000000000..f10319e63 --- /dev/null +++ b/NzbDrone.Core/Repository/RootDir.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SubSonic.SqlGeneration.Schema; + +namespace NzbDrone.Core.Repository +{ + public class RootDir + { + [SubSonicPrimaryKey(true)] + public int RootDirId { get; set; } + + public string Path { get; set; } + + public bool Default { get; set; } + } +} diff --git a/NzbDrone.Web/Controllers/SeriesController.cs b/NzbDrone.Web/Controllers/SeriesController.cs index 95d3389d6..a429649cb 100644 --- a/NzbDrone.Web/Controllers/SeriesController.cs +++ b/NzbDrone.Web/Controllers/SeriesController.cs @@ -22,6 +22,7 @@ namespace NzbDrone.Web.Controllers private readonly IQualityProvider _qualityProvider; private readonly IMediaFileProvider _mediaFileProvider; private readonly IRenameProvider _renameProvider; + private readonly IRootDirProvider _rootDirProvider; // // GET: /Series/ @@ -29,7 +30,7 @@ namespace NzbDrone.Web.Controllers public SeriesController(ISyncProvider syncProvider, ISeriesProvider seriesProvider, IEpisodeProvider episodeProvider, IRssSyncProvider rssSyncProvider, IQualityProvider qualityProvider, IMediaFileProvider mediaFileProvider, - IRenameProvider renameProvider) + IRenameProvider renameProvider, IRootDirProvider rootDirProvider) { _seriesProvider = seriesProvider; _episodeProvider = episodeProvider; @@ -38,6 +39,7 @@ namespace NzbDrone.Web.Controllers _qualityProvider = qualityProvider; _mediaFileProvider = mediaFileProvider; _renameProvider = renameProvider; + _rootDirProvider = rootDirProvider; } public ActionResult Index() @@ -51,9 +53,15 @@ namespace NzbDrone.Web.Controllers return View(new AddSeriesModel()); } - public ActionResult Sync() + public ActionResult AddExisting() { - _syncProvider.BeginSyncUnmappedFolders(); + return View(); + } + + public ActionResult Sync(List paths) + { + //Todo: Make this do something... + _syncProvider.BeginSyncUnmappedFolders(paths); return RedirectToAction("Index"); } @@ -63,9 +71,9 @@ namespace NzbDrone.Web.Controllers return RedirectToAction("Index"); } - public ActionResult UnMapped() + public ActionResult UnMapped(string path) { - return View(_seriesProvider.GetUnmappedFolders().Select(c => new MappingModel() { Id = 1, Path = c.Value }).ToList()); + return View(_syncProvider.GetUnmappedFolders(path).Select(c => new MappingModel() { Id = 1, Path = c }).ToList()); } public ActionResult LoadEpisodes(int seriesId) @@ -103,6 +111,24 @@ namespace NzbDrone.Web.Controllers Total = data.Count() }); } + + [GridAction] + public ActionResult _AjaxUnmappedFoldersGrid() + { + var unmappedList = new List(); + + foreach (var folder in _rootDirProvider.GetAll()) + unmappedList.AddRange(_syncProvider.GetUnmappedFolders(folder.Path)); + + var seriesPaths = unmappedList.Select(c => new AddExistingSeriesModel + { + IsWanted = true, + Path = c + }); + + return View(new GridModel(seriesPaths)); + } + private IEnumerable GetData(GridCommand command) { diff --git a/NzbDrone.Web/Controllers/SettingsController.cs b/NzbDrone.Web/Controllers/SettingsController.cs index d8d33676c..97dab51fd 100644 --- a/NzbDrone.Web/Controllers/SettingsController.cs +++ b/NzbDrone.Web/Controllers/SettingsController.cs @@ -9,6 +9,7 @@ using NzbDrone.Core; using NzbDrone.Core.Helpers; using NzbDrone.Core.Model; using NzbDrone.Core.Providers; +using NzbDrone.Core.Repository; using NzbDrone.Core.Repository.Quality; using NzbDrone.Web.Models; @@ -20,15 +21,19 @@ namespace NzbDrone.Web.Controllers private IConfigProvider _configProvider; private IIndexerProvider _indexerProvider; private IQualityProvider _qualityProvider; + private IRootDirProvider _rootDirProvider; + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private string _settingsSaved = "Settings Saved."; private string _settingsFailed = "Error Saving Settings, please fix any errors"; - public SettingsController(IConfigProvider configProvider, IIndexerProvider indexerProvider, IQualityProvider qualityProvider) + public SettingsController(IConfigProvider configProvider, IIndexerProvider indexerProvider, + IQualityProvider qualityProvider, IRootDirProvider rootDirProvider) { _configProvider = configProvider; _indexerProvider = indexerProvider; _qualityProvider = qualityProvider; + _rootDirProvider = rootDirProvider; } public ActionResult Index(string viewName) @@ -37,21 +42,18 @@ namespace NzbDrone.Web.Controllers ViewData["viewName"] = viewName; else - ViewData["viewName"] = "General"; + return RedirectToAction("General"); - return View("Index", new SettingsModel - { - TvFolder = _configProvider.SeriesRoot - }); + return View("Index"); } public ActionResult General() { ViewData["viewName"] = "General"; + return View("Index", new SettingsModel { - TvFolder = _configProvider.SeriesRoot, - Quality = Convert.ToInt32(_configProvider.GetValue("Quality", "1", true)), + Directories = new List() }); } @@ -185,6 +187,11 @@ namespace NzbDrone.Web.Controllers return View("UserProfileSection", new QualityProfile { Name = "New Profile", UserProfile = true }); } + public ViewResult AddRootDir() + { + return View("RootDir", new RootDir { Default = false }); + } + public ActionResult SubMenu() { return PartialView(); @@ -202,9 +209,30 @@ namespace NzbDrone.Web.Controllers [HttpPost] public ActionResult SaveGeneral(SettingsModel data) { - if (ModelState.IsValid) + if (data.Directories.Count > 0) { - _configProvider.SeriesRoot = data.TvFolder; + //If the Javascript was beaten we need to return an error + if (!data.Directories.Exists(d => d.Default)) + return Content(_settingsFailed); + + var currentRootDirs = _rootDirProvider.GetAll(); + + foreach (var currentRootDir in currentRootDirs) + { + var closureRootDir = currentRootDir; + if (!data.Directories.Exists(d => d.RootDirId == closureRootDir.RootDirId)) + _rootDirProvider.Remove(closureRootDir.RootDirId); + } + + foreach (var dir in data.Directories) + { + if (dir.RootDirId == 0) + _rootDirProvider.Add(dir); + + else + _rootDirProvider.Update(dir); + } + return Content(_settingsSaved); } diff --git a/NzbDrone.Web/Models/AddExistingSeriesModel.cs b/NzbDrone.Web/Models/AddExistingSeriesModel.cs new file mode 100644 index 000000000..ecb0b0b46 --- /dev/null +++ b/NzbDrone.Web/Models/AddExistingSeriesModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace NzbDrone.Web.Models +{ + public class AddExistingSeriesModel + { + public bool IsWanted { get; set; } + public string Path { get; set; } + } +} \ No newline at end of file diff --git a/NzbDrone.Web/Models/SettingsModels.cs b/NzbDrone.Web/Models/SettingsModels.cs index b773ecfc2..441b1c8ed 100644 --- a/NzbDrone.Web/Models/SettingsModels.cs +++ b/NzbDrone.Web/Models/SettingsModels.cs @@ -10,22 +10,7 @@ namespace NzbDrone.Web.Models public class SettingsModel { - - [DataType(DataType.Text)] - [Required(ErrorMessage = "Please enter a valid TV path")] - [DisplayName("TV Folder")] - public String TvFolder - { - get; - set; - } - - [DataType(DataType.Text)] - [DisplayName("Initial Quality")] - public int Quality - { - get; - set; - } + [DisplayName("TV Series Root Folder(s)")] + public List Directories { get; set; } } } diff --git a/NzbDrone.Web/NzbDrone.Web.csproj b/NzbDrone.Web/NzbDrone.Web.csproj index f1b0cf6bb..30317fca1 100644 --- a/NzbDrone.Web/NzbDrone.Web.csproj +++ b/NzbDrone.Web/NzbDrone.Web.csproj @@ -86,6 +86,7 @@ + @@ -271,6 +272,7 @@ + @@ -278,6 +280,7 @@ + diff --git a/NzbDrone.Web/Views/Series/Add.aspx b/NzbDrone.Web/Views/Series/Add.aspx index 505cad78d..66535023f 100644 --- a/NzbDrone.Web/Views/Series/Add.aspx +++ b/NzbDrone.Web/Views/Series/Add.aspx @@ -15,4 +15,8 @@ //Add Existing + //Ask user for existing TV Root Folder... + //Get list of unmapped folders and allow the user to check off the ones they want to add... + // + \ No newline at end of file diff --git a/NzbDrone.Web/Views/Series/AddExisting.aspx b/NzbDrone.Web/Views/Series/AddExisting.aspx new file mode 100644 index 000000000..5da2116a1 --- /dev/null +++ b/NzbDrone.Web/Views/Series/AddExisting.aspx @@ -0,0 +1,35 @@ +<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> + +<%@ Import Namespace="Telerik.Web.Mvc.UI" %> +<%@ Import Namespace="NzbDrone.Web.Models" %> + + + Add Existing Series + + + <% + Html.RenderPartial("SubMenu"); + %> + + + + //Get AJAX listing of unmapped directories + + <% + Html.Telerik().Grid().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("
<#= Overview #>
")) + //.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(); + %>` + +
diff --git a/NzbDrone.Web/Views/Series/SubMenu.ascx b/NzbDrone.Web/Views/Series/SubMenu.ascx index 65dc63cf7..887e9cf00 100644 --- a/NzbDrone.Web/Views/Series/SubMenu.ascx +++ b/NzbDrone.Web/Views/Series/SubMenu.ascx @@ -5,7 +5,7 @@ <% 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"); + 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"); diff --git a/NzbDrone.Web/Views/Settings/General.ascx b/NzbDrone.Web/Views/Settings/General.ascx index e78e00d41..bb63c61b4 100644 --- a/NzbDrone.Web/Views/Settings/General.ascx +++ b/NzbDrone.Web/Views/Settings/General.ascx @@ -27,20 +27,58 @@ <% using (Html.BeginForm("SaveGeneral", "Settings", FormMethod.Post, new { id = "form", name = "form" })) {%> <%: Html.ValidationSummary(true, "Unable to save your settings. Please correct the errors and try again.") %> -
+
General -
- <%= Html.LabelFor(model => model.TvFolder) %> -
-
- <%= Html.TextBoxFor(model => model.TvFolder) %> - <%= Html.ValidationMessageFor(model => model.TvFolder) %> +
+ + +
+ <%foreach (var item in Model.Directories) { %> + <% Html.RenderPartial("RootDir", item); %> + <% } %> +
- +

<% } Html.EndForm();%> -
\ No newline at end of file +
+ + \ No newline at end of file diff --git a/NzbDrone.Web/Views/Settings/RootDir.ascx b/NzbDrone.Web/Views/Settings/RootDir.ascx new file mode 100644 index 000000000..fdc518ee4 --- /dev/null +++ b/NzbDrone.Web/Views/Settings/RootDir.ascx @@ -0,0 +1,36 @@ +<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> +<%@ Import Namespace="NzbDrone.Web.Helpers" %> + +<% using (Html.BeginCollectionItem("Directories")) + { %> + + <% + var idClean = ViewData.TemplateInfo.HtmlFieldPrefix.Replace('[', '_').Replace(']', '_'); + //string sortable1 = String.Format("{0}_sortable1", idClean); + %> + + + +
+ +
+ +
+ <%: Html.CheckBoxFor(m => m.Default, new { @class = "defaultCheckbox" }) %> + <%: Html.TextBoxFor(m => m.Path, new { @class="root_dir_text" }) %> + Delete +
+ +
+ <%: Html.ValidationMessageFor(m => m.Path) %> +
+ +
+ <%= Html.TextBoxFor(x => x.RootDirId, new { @style = "display:none" })%> +
+ +
+
+<% } %> \ No newline at end of file diff --git a/NzbDrone.Web/Views/Settings/UserProfileSection.ascx b/NzbDrone.Web/Views/Settings/UserProfileSection.ascx index ed31bdc98..31a4132e0 100644 --- a/NzbDrone.Web/Views/Settings/UserProfileSection.ascx +++ b/NzbDrone.Web/Views/Settings/UserProfileSection.ascx @@ -12,6 +12,8 @@ string sortable2 = String.Format("{0}_sortable2", idClean); string allowedStringName = String.Format("{0}_AllowedString", idClean); string connectedSortable = String.Format("connected{0}", idClean); + string title = String.Format("{0}_Title", idClean); + string nameBox = String.Format("{0}_Name", idClean); %> + <% } %> \ No newline at end of file