mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-12 11:15:43 +02:00
Manage multiple Tv Root Folders in Settings/General.
Start of AddExisting.
This commit is contained in:
parent
2e9dd7f1ff
commit
2871723bfe
@ -66,25 +66,25 @@ public void Test_Parse_Success(string postTitle, string title)
|
||||
//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<ISeriesProvider>().To<SeriesProvider>();
|
||||
kernel.Bind<IDiskProvider>().ToConstant(MockLib.GetStandardDisk(0, 0));
|
||||
kernel.Bind<IConfigProvider>().ToConstant(MockLib.StandardConfig);
|
||||
// kernel.Bind<ISeriesProvider>().To<SeriesProvider>();
|
||||
// kernel.Bind<IDiskProvider>().ToConstant(MockLib.GetStandardDisk(0, 0));
|
||||
// kernel.Bind<IConfigProvider>().ToConstant(MockLib.StandardConfig);
|
||||
|
||||
var seriesController = kernel.Get<ISeriesProvider>();
|
||||
// var seriesController = kernel.Get<ISeriesProvider>();
|
||||
|
||||
//Act
|
||||
var unmappedFolder = seriesController.GetUnmappedFolders();
|
||||
// //Act
|
||||
// var unmappedFolder = seriesController.GetUnmappedFolders();
|
||||
|
||||
//Assert
|
||||
Assert.AreElementsEqualIgnoringOrder(MockLib.StandardSeries, unmappedFolder.Values);
|
||||
}
|
||||
// //Assert
|
||||
// Assert.AreElementsEqualIgnoringOrder(MockLib.StandardSeries, unmappedFolder.Values);
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ public static void BindKernel()
|
||||
_kernel.Bind<IHttpProvider>().To<HttpProvider>();
|
||||
_kernel.Bind<IHistoryProvider>().To<HistoryProvider>();
|
||||
_kernel.Bind<IQualityProvider>().To<QualityProvider>();
|
||||
_kernel.Bind<IRootDirProvider>().To<RootDirProvider>();
|
||||
_kernel.Bind<IExtenalNotificationProvider>().To<ExternalNotificationProvider>();
|
||||
_kernel.Bind<IXbmcProvider>().To<XbmcProvider>();
|
||||
_kernel.Bind<IConfigProvider>().To<ConfigProvider>().InSingletonScope();
|
||||
|
@ -183,6 +183,7 @@
|
||||
<Compile Include="Providers\IPostProcessingProvider.cs" />
|
||||
<Compile Include="Providers\IQualityProvider.cs" />
|
||||
<Compile Include="Providers\IRenameProvider.cs" />
|
||||
<Compile Include="Providers\IRootDirProvider.cs" />
|
||||
<Compile Include="Providers\IRssSyncProvider.cs" />
|
||||
<Compile Include="Providers\IRssProvider.cs" />
|
||||
<Compile Include="Providers\ITimerProvider.cs" />
|
||||
@ -190,6 +191,7 @@
|
||||
<Compile Include="Providers\PostProcessingProvider.cs" />
|
||||
<Compile Include="Providers\QualityProvider.cs" />
|
||||
<Compile Include="Providers\RenameProvider.cs" />
|
||||
<Compile Include="Providers\RootDirProvider.cs" />
|
||||
<Compile Include="Providers\RssSyncProvider.cs" />
|
||||
<Compile Include="Providers\RssProvider.cs" />
|
||||
<Compile Include="Providers\TimerProvider.cs" />
|
||||
@ -229,6 +231,7 @@
|
||||
<Compile Include="Repository\Indexer.cs" />
|
||||
<Compile Include="Repository\Config.cs" />
|
||||
<Compile Include="Repository\Quality\QualityProfile.cs" />
|
||||
<Compile Include="Repository\RootDir.cs" />
|
||||
<Compile Include="Repository\Season.cs" />
|
||||
<Compile Include="Repository\Quality\QualityTypes.cs" />
|
||||
<Compile Include="Repository\Series.cs" />
|
||||
|
16
NzbDrone.Core/Providers/IRootDirProvider.cs
Normal file
16
NzbDrone.Core/Providers/IRootDirProvider.cs
Normal file
@ -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<RootDir> GetAll();
|
||||
void Add(RootDir rootDir);
|
||||
void Remove(int rootDirId);
|
||||
void Update(RootDir rootDir);
|
||||
}
|
||||
}
|
@ -18,13 +18,12 @@ public interface ISeriesProvider
|
||||
/// <param name="id">The TVDB ID of the series</param>
|
||||
/// <returns>Whether or not the show is monitored</returns>
|
||||
bool IsMonitored(long id);
|
||||
|
||||
TvdbSeries MapPathToSeries(string path);
|
||||
void AddSeries(string path, TvdbSeries series);
|
||||
Dictionary<Guid, String> GetUnmappedFolders();
|
||||
Series FindSeries(string cleanTitle);
|
||||
bool QualityWanted(int seriesId, QualityTypes quality);
|
||||
void UpdateSeries(Series series);
|
||||
void DeleteSeries(int seriesId);
|
||||
bool SeriesPathExists(string cleanPath);
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Providers
|
||||
{
|
||||
public interface ISyncProvider
|
||||
{
|
||||
void SyncUnmappedFolders();
|
||||
void BeginSyncUnmappedFolders();
|
||||
bool BeginSyncUnmappedFolders(List<string> paths);
|
||||
List<String> GetUnmappedFolders(string path);
|
||||
}
|
||||
}
|
43
NzbDrone.Core/Providers/RootDirProvider.cs
Normal file
43
NzbDrone.Core/Providers/RootDirProvider.cs
Normal file
@ -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<RootDir> GetAll()
|
||||
{
|
||||
return _sonioRepo.All<RootDir>().ToList();
|
||||
}
|
||||
|
||||
public void Add(RootDir rootDir)
|
||||
{
|
||||
_sonioRepo.Add(rootDir);
|
||||
}
|
||||
|
||||
public void Remove(int rootDirId)
|
||||
{
|
||||
_sonioRepo.Delete<RootDir>(rootDirId);
|
||||
}
|
||||
|
||||
public void Update(RootDir rootDir)
|
||||
{
|
||||
_sonioRepo.Update(rootDir);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -65,26 +65,6 @@ public bool QualityWanted(int seriesId, QualityTypes quality)
|
||||
return profile.Allowed.Contains(quality);
|
||||
}
|
||||
|
||||
public Dictionary<Guid, String> 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<Guid, String>();
|
||||
foreach (string seriesFolder in _diskProvider.GetDirectories(_config.SeriesRoot))
|
||||
{
|
||||
var cleanPath = Parser.NormalizePath(new DirectoryInfo(seriesFolder).FullName);
|
||||
if (!_sonioRepo.Exists<Series>(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 @@ public void DeleteSeries(int seriesId)
|
||||
_sonioRepo.Delete<Series>(seriesId);
|
||||
}
|
||||
|
||||
public bool SeriesPathExists(string cleanPath)
|
||||
{
|
||||
if (_sonioRepo.Exists<Series>(s => s.Path == cleanPath))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Static Helpers
|
||||
|
@ -3,7 +3,6 @@
|
||||
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 @@ public class SyncProvider : ISyncProvider
|
||||
private readonly IEpisodeProvider _episodeProvider;
|
||||
private readonly IMediaFileProvider _mediaFileProvider;
|
||||
private readonly INotificationProvider _notificationProvider;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
|
||||
private ProgressNotification _seriesSyncNotification;
|
||||
private Thread _seriesSyncThread;
|
||||
private List<string> _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<String> 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<String>();
|
||||
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<string> paths)
|
||||
{
|
||||
Logger.Debug("User has request series folder scan");
|
||||
if (_seriesSyncThread == null || !_seriesSyncThread.IsAlive)
|
||||
@ -42,15 +74,22 @@ public void BeginSyncUnmappedFolders()
|
||||
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 @@ public void SyncUnmappedFolders()
|
||||
{
|
||||
_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 @@ public void SyncUnmappedFolders()
|
||||
_episodeProvider.RefreshEpisodeInfo(mappedSeries.Id);
|
||||
_seriesSyncNotification.CurrentStatus = String.Format("{0}: finding episodes on disk...", mappedSeries.SeriesName);
|
||||
_mediaFileProvider.Scan(_seriesProvider.GetSeries(mappedSeries.Id));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
18
NzbDrone.Core/Repository/RootDir.cs
Normal file
18
NzbDrone.Core/Repository/RootDir.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ public class SeriesController : Controller
|
||||
private readonly IQualityProvider _qualityProvider;
|
||||
private readonly IMediaFileProvider _mediaFileProvider;
|
||||
private readonly IRenameProvider _renameProvider;
|
||||
private readonly IRootDirProvider _rootDirProvider;
|
||||
|
||||
//
|
||||
// GET: /Series/
|
||||
@ -29,7 +30,7 @@ public class SeriesController : Controller
|
||||
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 @@ public SeriesController(ISyncProvider syncProvider, ISeriesProvider seriesProvid
|
||||
_qualityProvider = qualityProvider;
|
||||
_mediaFileProvider = mediaFileProvider;
|
||||
_renameProvider = renameProvider;
|
||||
_rootDirProvider = rootDirProvider;
|
||||
}
|
||||
|
||||
public ActionResult Index()
|
||||
@ -51,9 +53,15 @@ public ActionResult Add()
|
||||
return View(new AddSeriesModel());
|
||||
}
|
||||
|
||||
public ActionResult Sync()
|
||||
public ActionResult AddExisting()
|
||||
{
|
||||
_syncProvider.BeginSyncUnmappedFolders();
|
||||
return View();
|
||||
}
|
||||
|
||||
public ActionResult Sync(List<String> paths)
|
||||
{
|
||||
//Todo: Make this do something...
|
||||
_syncProvider.BeginSyncUnmappedFolders(paths);
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
@ -63,9 +71,9 @@ public ActionResult RssSync()
|
||||
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 @@ public ActionResult _CustomBinding(GridCommand command, int seasonId)
|
||||
Total = data.Count()
|
||||
});
|
||||
}
|
||||
|
||||
[GridAction]
|
||||
public ActionResult _AjaxUnmappedFoldersGrid()
|
||||
{
|
||||
var unmappedList = new List<String>();
|
||||
|
||||
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<Episode> GetData(GridCommand command)
|
||||
{
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
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 @@ public class SettingsController : Controller
|
||||
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 @@ public ActionResult Index(string viewName)
|
||||
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<RootDir>()
|
||||
});
|
||||
}
|
||||
|
||||
@ -185,6 +187,11 @@ public ViewResult AddUserProfile()
|
||||
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 @@ public QualityModel GetUpdatedProfileList()
|
||||
[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);
|
||||
}
|
||||
|
||||
|
13
NzbDrone.Web/Models/AddExistingSeriesModel.cs
Normal file
13
NzbDrone.Web/Models/AddExistingSeriesModel.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
@ -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<RootDir> Directories { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -86,6 +86,7 @@
|
||||
<Compile Include="Helpers\HtmlPrefixScopeExtensions.cs" />
|
||||
<Compile Include="Helpers\IsCurrentActionHelper.cs" />
|
||||
<Compile Include="Models\AccountModels.cs" />
|
||||
<Compile Include="Models\AddExistingSeriesModel.cs" />
|
||||
<Compile Include="Models\AddSeriesModel.cs" />
|
||||
<Compile Include="Models\DownloadSettingsModel.cs" />
|
||||
<Compile Include="Models\EpisodeSortingModel.cs" />
|
||||
@ -271,6 +272,7 @@
|
||||
<Content Include="Scripts\Notification.js" />
|
||||
<Content Include="Views\Home\Test.aspx" />
|
||||
<Content Include="Views\Log\Index.aspx" />
|
||||
<Content Include="Views\Series\AddExisting.aspx" />
|
||||
<Content Include="Views\Series\Details.aspx" />
|
||||
<Content Include="Views\Series\Edit.aspx" />
|
||||
<Content Include="Views\Series\EpisodeDetail.ascx" />
|
||||
@ -278,6 +280,7 @@
|
||||
<Content Include="Views\Series\SubMenu.ascx" />
|
||||
<Content Include="Views\Series\Unmapped.aspx" />
|
||||
<Content Include="Views\Series\Add.aspx" />
|
||||
<Content Include="Views\Settings\RootDir.ascx" />
|
||||
<Content Include="Views\Settings\Notifications.ascx" />
|
||||
<Content Include="Views\Settings\Downloads.ascx" />
|
||||
<Content Include="Views\Settings\EpisodeSorting.ascx" />
|
||||
|
@ -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...
|
||||
//
|
||||
|
||||
</asp:Content>
|
35
NzbDrone.Web/Views/Series/AddExisting.aspx
Normal file
35
NzbDrone.Web/Views/Series/AddExisting.aspx
Normal file
@ -0,0 +1,35 @@
|
||||
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
|
||||
|
||||
<%@ Import Namespace="Telerik.Web.Mvc.UI" %>
|
||||
<%@ Import Namespace="NzbDrone.Web.Models" %>
|
||||
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
|
||||
Add Existing Series
|
||||
</asp:Content>
|
||||
<asp:Content ID="Menu" ContentPlaceHolderID="ActionMenu" runat="server">
|
||||
<%
|
||||
Html.RenderPartial("SubMenu");
|
||||
%>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
|
||||
|
||||
//Get AJAX listing of unmapped directories
|
||||
|
||||
<%
|
||||
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();
|
||||
%>`
|
||||
|
||||
</asp:Content>
|
@ -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");
|
||||
|
@ -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.") %>
|
||||
<fieldset>
|
||||
<fieldset>
|
||||
<legend>General</legend>
|
||||
|
||||
<div class="editor-label">
|
||||
<%= Html.LabelFor(model => model.TvFolder) %>
|
||||
<div style="padding-top: 10px;">
|
||||
<div style="padding-left: 7px; margin-bottom: 5px;">
|
||||
<a id="addItem" style="text-decoration:none;" href="<%: Url.Action("AddRootDir", "Settings") %>">
|
||||
<img src="../../Content/Images/Plus.png" alt="Add New Profile" />
|
||||
<h4 style="margin-left: 3px; display: inline; color: Black;">Add New Root Directory</h4></a>
|
||||
</div>
|
||||
|
||||
<div id="root-dirs">
|
||||
<%foreach (var item in Model.Directories) { %>
|
||||
<% Html.RenderPartial("RootDir", item); %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="editor-field">
|
||||
<%= Html.TextBoxFor(model => model.TvFolder) %>
|
||||
<%= Html.ValidationMessageFor(model => model.TvFolder) %>
|
||||
</div>
|
||||
|
||||
|
||||
<p>
|
||||
<input type="submit" id="save_button" value="Save" disabled="disabled" />
|
||||
</p>
|
||||
</fieldset>
|
||||
<% } Html.EndForm();%>
|
||||
<div id="result"></div>
|
||||
<div id="result"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
$("#addItem").click(function () {
|
||||
$.ajax({
|
||||
url: this.href,
|
||||
cache: false,
|
||||
success: function (html) { $("#root-dirs").append(html); }
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
$("a.deleteRow").live("click", function () {
|
||||
$(this).parents("div.rootDirSection:first").remove();
|
||||
return false;
|
||||
});
|
||||
|
||||
$(".defaultCheckbox").live("change", function () {
|
||||
var checked = $(this).attr('checked');
|
||||
|
||||
if (checked) {
|
||||
var thisOne = this;
|
||||
$(".defaultCheckbox").attr('checked', false);
|
||||
$(this).attr('checked', true);
|
||||
}
|
||||
|
||||
//Don't let the user uncheck a checkbox (Like a radio button)
|
||||
else {
|
||||
$(this).attr('checked', true);
|
||||
}
|
||||
});
|
||||
</script>
|
36
NzbDrone.Web/Views/Settings/RootDir.ascx
Normal file
36
NzbDrone.Web/Views/Settings/RootDir.ascx
Normal file
@ -0,0 +1,36 @@
|
||||
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<NzbDrone.Core.Repository.RootDir>" %>
|
||||
<%@ Import Namespace="NzbDrone.Web.Helpers" %>
|
||||
|
||||
<% using (Html.BeginCollectionItem("Directories"))
|
||||
{ %>
|
||||
|
||||
<%
|
||||
var idClean = ViewData.TemplateInfo.HtmlFieldPrefix.Replace('[', '_').Replace(']', '_');
|
||||
//string sortable1 = String.Format("{0}_sortable1", idClean);
|
||||
%>
|
||||
|
||||
<style type="text/css">
|
||||
.root_dir_text { width:300px; }
|
||||
</style>
|
||||
|
||||
<div class="rootDirSection">
|
||||
|
||||
<fieldset style="width:350px; height:16px; margin:0px; margin-top: 0px; border-color:#CCCCCD; -khtml-border-radius:8px; border-radius:8px; -moz-border-radius:8px; -webkit-border-radius:8px;">
|
||||
|
||||
<div>
|
||||
<%: Html.CheckBoxFor(m => m.Default, new { @class = "defaultCheckbox" }) %>
|
||||
<%: Html.TextBoxFor(m => m.Path, new { @class="root_dir_text" }) %>
|
||||
<a href="#" class="deleteRow"><img src="../../Content/Images/X.png" alt="Delete"/></a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%: Html.ValidationMessageFor(m => m.Path) %>
|
||||
</div>
|
||||
|
||||
<div class="hiddenProfileDetails">
|
||||
<%= Html.TextBoxFor(x => x.RootDirId, new { @style = "display:none" })%>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
<% } %>
|
@ -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);
|
||||
%>
|
||||
|
||||
<style type="text/css">
|
||||
@ -24,7 +26,6 @@
|
||||
.sortable1 li.ui-state-highlight, .sortable2 li.ui-state-highlight { background: #fbf5d0; border-color: #065EFE; }
|
||||
.removeDiv { float: left; display:block; }
|
||||
.ui-state-highlight { height: 1.5em; line-height: 1.2em; }
|
||||
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -53,7 +54,7 @@
|
||||
<fieldset style="width:275px; margin:5px; margin-top: 0px; border-color:#CCCCCD">
|
||||
|
||||
<div id="qualityHeader" style="padding-bottom: 5px; margin: 0px;">
|
||||
<h2 style="display:inline; padding-right: 4px; margin-left: 4px;"><%= Html.DisplayTextFor(m => m.Name) %></h2>
|
||||
<h2 style="display:inline; padding-right: 4px; margin-left: 4px;" id="<%= title %>"><%= Html.DisplayTextFor(m => m.Name) %></h2>
|
||||
<a href="#" class="deleteRow"><img src="../../Content/Images/X.png" alt="Delete" /></a>
|
||||
</div>
|
||||
|
||||
@ -115,4 +116,12 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$("#<%: nameBox %>").keyup(function () {
|
||||
var value = $(this).val();
|
||||
$("#<%= title %>").text(value);
|
||||
}).keyup();
|
||||
</script>
|
||||
|
||||
<% } %>
|
Loading…
Reference in New Issue
Block a user