moved rootdir to eloquera
This commit is contained in:
parent
0155de4d92
commit
9e4bb278ef
|
@ -3,17 +3,18 @@ using Nancy;
|
|||
using NzbDrone.Api.Extentions;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
|
||||
namespace NzbDrone.Api.RootFolders
|
||||
{
|
||||
public class RootDirModule : NzbDroneApiModule
|
||||
{
|
||||
private readonly RootDirProvider _rootDirProvider;
|
||||
private readonly RootFolderService _rootFolderService;
|
||||
|
||||
public RootDirModule(RootDirProvider rootDirProvider)
|
||||
public RootDirModule(RootFolderService rootFolderService)
|
||||
: base("//rootdir")
|
||||
{
|
||||
_rootDirProvider = rootDirProvider;
|
||||
_rootFolderService = rootFolderService;
|
||||
|
||||
Get["/"] = x => GetRootFolders();
|
||||
Post["/"] = x => AddRootFolder();
|
||||
|
@ -22,18 +23,18 @@ namespace NzbDrone.Api.RootFolders
|
|||
|
||||
private Response AddRootFolder()
|
||||
{
|
||||
var dir = _rootDirProvider.Add(Request.Body.FromJson<RootDir>());
|
||||
var dir = _rootFolderService.Add(Request.Body.FromJson<RootDir>());
|
||||
return dir.AsResponse(HttpStatusCode.Created);
|
||||
}
|
||||
|
||||
private Response GetRootFolders()
|
||||
{
|
||||
return _rootDirProvider.AllWithFreeSpace().AsResponse();
|
||||
return _rootFolderService.All().AsResponse();
|
||||
}
|
||||
|
||||
private Response DeleteRootFolder(int folderId)
|
||||
{
|
||||
_rootDirProvider.Remove(folderId);
|
||||
_rootFolderService.Remove(folderId);
|
||||
return new Response { StatusCode = HttpStatusCode.OK };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,7 +107,15 @@ namespace NzbDrone.Common
|
|||
{
|
||||
get
|
||||
{
|
||||
return new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName;
|
||||
var path = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName;
|
||||
|
||||
if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.Windows),
|
||||
StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
path = Directory.GetCurrentDirectory();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace NzbDrone.Common
|
|||
{
|
||||
private const string WEB_FOLDER = "NzbDrone.Web\\";
|
||||
private const string APP_DATA = "App_Data\\";
|
||||
private const string WEB_BIN = "bin\\";
|
||||
public const string IIS_FOLDER = "IISExpress";
|
||||
public const string IIS_EXE = "iisexpress.exe";
|
||||
|
||||
|
@ -70,6 +71,11 @@ namespace NzbDrone.Common
|
|||
return Path.Combine(environmentProvider.GetWebRoot(), APP_DATA);
|
||||
}
|
||||
|
||||
public static string GetWebBinPath(this EnvironmentProvider environmentProvider)
|
||||
{
|
||||
return Path.Combine(environmentProvider.GetWebRoot(), WEB_BIN);
|
||||
}
|
||||
|
||||
public static string GetNlogConfigPath(this EnvironmentProvider environmentProvider)
|
||||
{
|
||||
return Path.Combine(environmentProvider.GetWebRoot(), LOG_CONFIG_FILE);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Linq;
|
||||
using Eloquera.Client;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
|
@ -82,6 +83,19 @@ namespace NzbDrone.Core.Test.Datastore
|
|||
Db.Insert(testSeries);
|
||||
testSeries.Id.Should().NotBe(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_read_unknow_type()
|
||||
{
|
||||
Db.AsQueryable<UnKnowType>().ToList().Should().BeEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UnKnowType
|
||||
{
|
||||
[ID]
|
||||
public string Id;
|
||||
public string Field1 { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Test.Framework
|
||||
|
@ -23,11 +24,11 @@ namespace NzbDrone.Core.Test.Framework
|
|||
{
|
||||
if (memory)
|
||||
{
|
||||
_db = new EloqueraDbFactory().CreateMemoryDb();
|
||||
_db = new EloqueraDbFactory(new EnvironmentProvider()).CreateMemoryDb();
|
||||
}
|
||||
else
|
||||
{
|
||||
_db = new EloqueraDbFactory().Create(Guid.NewGuid().ToString());
|
||||
_db = new EloqueraDbFactory(new EnvironmentProvider()).Create();
|
||||
}
|
||||
|
||||
Mocker.SetConstant(Db);
|
||||
|
|
|
@ -28,6 +28,32 @@ namespace NzbDrone.Core.Test.Framework
|
|||
|
||||
}
|
||||
|
||||
public abstract class CoreTest<TSubject> : CoreTest
|
||||
{
|
||||
private TSubject _subject;
|
||||
|
||||
|
||||
protected TSubject Subject
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_subject == null)
|
||||
{
|
||||
_subject = Mocker.Resolve<TSubject>();
|
||||
}
|
||||
|
||||
return _subject;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void InitiateSubject()
|
||||
{
|
||||
_subject = Mocker.Resolve<TSubject>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract class SqlCeTest : CoreTest
|
||||
{
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
</Reference>
|
||||
<Reference Include="Eloquera.Server">
|
||||
<HintPath>..\packages\EloqueraDB.5.0.0\lib\net40\Eloquera.Server.exe</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
|
||||
|
|
|
@ -31,5 +31,6 @@
|
|||
<RegularExpression>NzbDrone\.Core\.Test\.Integeration\.ServiceIntegerationFixture\..*</RegularExpression>
|
||||
</RegexTestSelector>
|
||||
</IgnoredTests>
|
||||
<AdditionalFilesToInclude>..\NzbDrone.Core\bin\Debug\Eloquera.Server.exe</AdditionalFilesToInclude>
|
||||
<HiddenWarnings>PostBuildEventDisabled</HiddenWarnings>
|
||||
</ProjectConfiguration>
|
|
@ -12,6 +12,7 @@ using NzbDrone.Common;
|
|||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Providers.Core;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Test.Common.AutoMoq;
|
||||
|
@ -38,7 +39,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests
|
|||
.Setup(s => s.FreeDiskSpace(new DirectoryInfo(@"C:\")))
|
||||
.Returns(123456);
|
||||
|
||||
var result = Mocker.Resolve<RootDirProvider>().FreeSpaceOnDrives();
|
||||
var result = Mocker.Resolve<RootFolderService>().FreeSpaceOnDrives();
|
||||
|
||||
result.Should().HaveCount(1);
|
||||
}
|
||||
|
@ -59,7 +60,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests
|
|||
.Setup(s => s.FreeDiskSpace(new DirectoryInfo(@"C:\")))
|
||||
.Returns(123456);
|
||||
|
||||
var result = Mocker.Resolve<RootDirProvider>().FreeSpaceOnDrives();
|
||||
var result = Mocker.Resolve<RootFolderService>().FreeSpaceOnDrives();
|
||||
|
||||
result.Should().HaveCount(1);
|
||||
}
|
||||
|
@ -84,7 +85,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests
|
|||
.Setup(s => s.FreeDiskSpace(It.IsAny<DirectoryInfo>()))
|
||||
.Returns(123456);
|
||||
|
||||
var result = Mocker.Resolve<RootDirProvider>().FreeSpaceOnDrives();
|
||||
var result = Mocker.Resolve<RootFolderService>().FreeSpaceOnDrives();
|
||||
|
||||
result.Should().HaveCount(2);
|
||||
}
|
||||
|
@ -104,7 +105,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests
|
|||
.Setup(s => s.FreeDiskSpace(It.IsAny<DirectoryInfo>()))
|
||||
.Throws(new DirectoryNotFoundException());
|
||||
|
||||
var result = Mocker.Resolve<RootDirProvider>().FreeSpaceOnDrives();
|
||||
var result = Mocker.Resolve<RootFolderService>().FreeSpaceOnDrives();
|
||||
|
||||
result.Should().HaveCount(0);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// ReSharper disable RedundantUsingDirective
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
|
@ -11,6 +12,7 @@ using NzbDrone.Common;
|
|||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Providers.Core;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common.AutoMoq;
|
||||
|
||||
|
@ -18,7 +20,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests
|
|||
{
|
||||
[TestFixture]
|
||||
// ReSharper disable InconsistentNaming
|
||||
public class RootDirProviderFixture : SqlCeTest
|
||||
public class RootDirProviderFixture : CoreTest<RootFolderService>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
|
@ -35,32 +37,15 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests
|
|||
.Returns(false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetRootDir_should_return_all_existing_roots()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
Db.Insert(new RootDir { Path = @"C:\TV" });
|
||||
Db.Insert(new RootDir { Path = @"C:\TV2" });
|
||||
|
||||
var result = Mocker.Resolve<RootDirProvider>().GetAll();
|
||||
result.Should().HaveCount(2);
|
||||
}
|
||||
|
||||
[TestCase("D:\\TV Shows\\")]
|
||||
[TestCase("//server//folder")]
|
||||
public void should_be_able_to_add_root_dir(string path)
|
||||
{
|
||||
WithRealDb();
|
||||
var root = new RootDir { Path = path };
|
||||
Subject.Add(root);
|
||||
|
||||
//Act
|
||||
var rootDirProvider = Mocker.Resolve<RootDirProvider>();
|
||||
rootDirProvider.Add(new RootDir { Path = path });
|
||||
|
||||
//Assert
|
||||
var rootDirs = rootDirProvider.GetAll();
|
||||
rootDirs.Should().HaveCount(1);
|
||||
rootDirs.First().Path.Should().Be(path);
|
||||
Mocker.GetMock<IRootFolderRepository>().Verify(c => c.Add(root), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -68,34 +53,25 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests
|
|||
{
|
||||
WithNoneExistingFolder();
|
||||
|
||||
var rootDirProvider = Mocker.Resolve<RootDirProvider>();
|
||||
Assert.Throws<DirectoryNotFoundException>(() => rootDirProvider.Add(new RootDir { Path = "C:\\TEST" }));
|
||||
Assert.Throws<DirectoryNotFoundException>(() => Subject.Add(new RootDir { Path = "C:\\TEST" }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_remove_root_dir()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
//Act
|
||||
var rootDirProvider = Mocker.Resolve<RootDirProvider>();
|
||||
rootDirProvider.Add(new RootDir { Path = @"C:\TV" });
|
||||
rootDirProvider.Add(new RootDir { Path = @"C:\TV2" });
|
||||
rootDirProvider.Remove(1);
|
||||
|
||||
//Assert
|
||||
var rootDirs = rootDirProvider.GetAll();
|
||||
rootDirs.Should().HaveCount(1);
|
||||
Subject.Remove(1);
|
||||
Mocker.GetMock<IRootFolderRepository>().Verify(c => c.Delete(1), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void None_existing_folder_returns_empty_list()
|
||||
{
|
||||
WithNoneExistingFolder();
|
||||
|
||||
Mocker.GetMock<IRootFolderRepository>().Setup(c => c.All()).Returns(new List<RootDir>());
|
||||
|
||||
const string path = "d:\\bad folder";
|
||||
|
||||
var result = Mocker.Resolve<RootDirProvider>().GetUnmappedFolders(path);
|
||||
var result = Subject.GetUnmappedFolders(path);
|
||||
|
||||
result.Should().NotBeNull();
|
||||
result.Should().BeEmpty();
|
||||
|
@ -105,7 +81,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests
|
|||
[Test]
|
||||
public void GetUnmappedFolders_throw_on_empty_folders()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Mocker.Resolve<RootDirProvider>().GetUnmappedFolders(""));
|
||||
Assert.Throws<ArgumentException>(() => Mocker.Resolve<RootFolderService>().GetUnmappedFolders(""));
|
||||
}
|
||||
|
||||
[TestCase("")]
|
||||
|
@ -114,19 +90,17 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests
|
|||
public void invalid_folder_path_throws_on_add(string path)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
Mocker.Resolve<RootDirProvider>().Add(new RootDir { Id = 0, Path = path })
|
||||
Mocker.Resolve<RootFolderService>().Add(new RootDir { Id = 0, Path = path })
|
||||
);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void adding_duplicated_root_folder_should_throw()
|
||||
{
|
||||
WithRealDb();
|
||||
Mocker.GetMock<IRootFolderRepository>().Setup(c => c.All()).Returns(new List<RootDir> { new RootDir { Path = "C:\\TV" } });
|
||||
|
||||
//Act
|
||||
var rootDirProvider = Mocker.Resolve<RootDirProvider>();
|
||||
rootDirProvider.Add(new RootDir { Path = @"C:\TV" });
|
||||
Assert.Throws<InvalidOperationException>(() => rootDirProvider.Add(new RootDir { Path = @"C:\TV" }));
|
||||
Subject.Add(new RootDir { Path = @"C:\TV" });
|
||||
Assert.Throws<InvalidOperationException>(() => Subject.Add(new RootDir { Path = @"C:\TV" }));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -82,8 +82,7 @@ namespace NzbDrone.Core
|
|||
|
||||
container.Register(c =>
|
||||
{
|
||||
var env = c.Resolve<EnvironmentProvider>();
|
||||
return c.Resolve<EloqueraDbFactory>().Create(env.GetElqMainDbPath());
|
||||
return c.Resolve<EloqueraDbFactory>().Create();
|
||||
}).As<EloqueraDb>().SingleInstance();
|
||||
|
||||
container.RegisterType<DatabaseTarget>().WithParameter(ResolvedParameter.ForNamed<IDatabase>("DatabaseTarget"));
|
||||
|
|
|
@ -43,12 +43,12 @@ namespace NzbDrone.Core.Datastore
|
|||
}
|
||||
|
||||
|
||||
public void Delete<T>(T obj)
|
||||
public void Delete<T>(T obj) where T : new()
|
||||
{
|
||||
_db.Delete(obj);
|
||||
}
|
||||
|
||||
public void DeleteMany<T>(IEnumerable<T> objects)
|
||||
public void DeleteMany<T>(IEnumerable<T> objects) where T: new()
|
||||
{
|
||||
foreach (var o in objects)
|
||||
{
|
||||
|
|
|
@ -2,27 +2,52 @@
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using Eloquera.Client;
|
||||
using NzbDrone.Common;
|
||||
|
||||
namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public class EloqueraDbFactory
|
||||
{
|
||||
public EloqueraDb CreateMemoryDb()
|
||||
private readonly EnvironmentProvider _environmentProvider;
|
||||
|
||||
private readonly string dllPath;
|
||||
|
||||
public EloqueraDbFactory(EnvironmentProvider environmentProvider)
|
||||
{
|
||||
return InternalCreate("server=(local);password=;options=inmemory;",Guid.NewGuid().ToString());
|
||||
_environmentProvider = environmentProvider;
|
||||
dllPath = _environmentProvider.GetWebBinPath();// this is the path where Eloquera dlls live.
|
||||
}
|
||||
|
||||
public EloqueraDb Create(string dbPath)
|
||||
public EloqueraDb CreateMemoryDb()
|
||||
{
|
||||
var file = new FileInfo(dbPath).Name;
|
||||
return InternalCreate(string.Format("server=(local);database={0};usedatapath={1};password=;", file, dbPath),file);
|
||||
return InternalCreate("server=(local);password=;options=inmemory;uselocalpath=" + dllPath, Guid.NewGuid().ToString());
|
||||
}
|
||||
|
||||
public EloqueraDb Create(string dbPath = null)
|
||||
{
|
||||
if (dbPath == null)
|
||||
{
|
||||
dbPath = _environmentProvider.GetElqMainDbPath();
|
||||
}
|
||||
|
||||
var file = new FileInfo(dbPath);
|
||||
|
||||
return InternalCreate(string.Format("server=(local);password=;usedatapath={0};uselocalpath={1}", file.Directory.FullName, dllPath), file.Name);
|
||||
}
|
||||
|
||||
private EloqueraDb InternalCreate(string connectionString, string databaseName)
|
||||
{
|
||||
var db = new DB(connectionString);
|
||||
db.CreateDatabase(databaseName);
|
||||
db.OpenDatabase(databaseName);
|
||||
try
|
||||
{
|
||||
db.OpenDatabase(databaseName);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
db.CreateDatabase(databaseName);
|
||||
db.OpenDatabase(databaseName);
|
||||
}
|
||||
|
||||
return new EloqueraDb(db);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
using System.Collections.Generic;
|
||||
using Migrator.Framework;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migrations
|
||||
{
|
||||
[Migration(20130203)]
|
||||
public class Migration20130203 : NzbDroneMigration
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
var objectDb = GetObjectDb();
|
||||
|
||||
|
||||
var rootFolderRepo = new RootFolderRepository(objectDb);
|
||||
|
||||
|
||||
using (var dataReader = Database.ExecuteQuery("SELECT * from RootDirs"))
|
||||
{
|
||||
var dirs = new List<RootDir>();
|
||||
while (dataReader.Read())
|
||||
{
|
||||
var rootFolder = new RootDir { Path = dataReader["Path"].ToString() };
|
||||
dirs.Add(rootFolder);
|
||||
}
|
||||
objectDb.InsertMany(dirs);
|
||||
}
|
||||
//Database.RemoveTable("RootDirs");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Data.SqlServerCe;
|
||||
using System.Linq;
|
||||
using Migrator.Framework;
|
||||
using NzbDrone.Common;
|
||||
|
@ -32,6 +33,14 @@ namespace NzbDrone.Core.Datastore.Migrations
|
|||
}
|
||||
}
|
||||
|
||||
protected EloqueraDb GetObjectDb()
|
||||
{
|
||||
|
||||
var sqlCeConnection = new SqlCeConnection(Database.ConnectionString);
|
||||
|
||||
var eqPath = sqlCeConnection.Database.Replace(".sdf", ".eq");
|
||||
return new EloqueraDbFactory(new EnvironmentProvider()).Create(eqPath);
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
|
|
|
@ -9,37 +9,37 @@ namespace NzbDrone.Core.Datastore
|
|||
{
|
||||
public class MigrationsHelper
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
|
||||
public static void Run(string connetionString, bool trace)
|
||||
public static void Run(string connectionString, bool trace)
|
||||
{
|
||||
EnsureDatabase(connetionString);
|
||||
EnsureDatabase(connectionString);
|
||||
|
||||
Logger.Trace("Preparing to run database migration");
|
||||
logger.Trace("Preparing to run database migration");
|
||||
|
||||
try
|
||||
{
|
||||
Migrator.Migrator migrator;
|
||||
if (trace)
|
||||
{
|
||||
migrator = new Migrator.Migrator("sqlserverce", connetionString, Assembly.GetAssembly(typeof(MigrationsHelper)), true, new MigrationLogger());
|
||||
migrator = new Migrator.Migrator("sqlserverce", connectionString, Assembly.GetAssembly(typeof(MigrationsHelper)), true, new MigrationLogger());
|
||||
}
|
||||
else
|
||||
{
|
||||
migrator = new Migrator.Migrator("sqlserverce", connetionString, Assembly.GetAssembly(typeof(MigrationsHelper)));
|
||||
migrator = new Migrator.Migrator("sqlserverce", connectionString, Assembly.GetAssembly(typeof(MigrationsHelper)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
migrator.MigrateToLastVersion();
|
||||
Logger.Info("Database migration completed");
|
||||
logger.Info("Database migration completed");
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.FatalException("An error has occurred while migrating database", e);
|
||||
logger.FatalException("An error has occurred while migrating database", e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,6 +237,7 @@
|
|||
<Compile Include="Datastore\MigrationLogger.cs" />
|
||||
<Compile Include="Datastore\MigrationsHelper.cs" />
|
||||
<Compile Include="Datastore\CustomeMapper.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20130203.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20121226.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20121218.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20121209.cs" />
|
||||
|
@ -536,7 +537,7 @@
|
|||
<Compile Include="Providers\ReferenceDataProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Providers\RootDirProvider.cs">
|
||||
<Compile Include="RootFolders\RootFolderService.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Providers\SceneMappingProvider.cs">
|
||||
|
@ -599,6 +600,7 @@
|
|||
<Compile Include="Repository\Series.cs" />
|
||||
<Compile Include="CentralDispatch.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RootFolders\RootFolderRepository.cs" />
|
||||
<Compile Include="Tvdb\Tvdb.cs" />
|
||||
<Compile Include="Tvdb\Tvdb.Sync.cs" />
|
||||
<Compile Include="Tvdb\TvdbActor.cs" />
|
||||
|
|
|
@ -3,9 +3,21 @@ using PetaPoco;
|
|||
|
||||
namespace NzbDrone.Core.Repository
|
||||
{
|
||||
public interface IRootDir
|
||||
{
|
||||
int Id { get; set; }
|
||||
string Path { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
ulong FreeSpace { get; set; }
|
||||
|
||||
[Ignore]
|
||||
List<string> UnmappedFolders { get; set; }
|
||||
}
|
||||
|
||||
[TableName("RootDirs")]
|
||||
[PrimaryKey("Id", autoIncrement = true)]
|
||||
public class RootDir
|
||||
public class RootDir : IRootDir
|
||||
{
|
||||
public virtual int Id { get; set; }
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Repository;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Core.RootFolders
|
||||
{
|
||||
public interface IRootFolderRepository
|
||||
{
|
||||
List<RootDir> All();
|
||||
RootDir Get(int rootFolderId);
|
||||
RootDir Add(RootDir rootFolder);
|
||||
void Delete(int rootFolderId);
|
||||
}
|
||||
|
||||
public class RootFolderRepository : IRootFolderRepository
|
||||
{
|
||||
private readonly EloqueraDb _db;
|
||||
|
||||
public RootFolderRepository(EloqueraDb db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
||||
public List<RootDir> All()
|
||||
{
|
||||
return _db.AsQueryable<RootDir>().ToList();
|
||||
}
|
||||
|
||||
public RootDir Get(int rootFolderId)
|
||||
{
|
||||
return _db.AsQueryable<RootDir>().Single(c => c.Id == rootFolderId);
|
||||
}
|
||||
|
||||
public RootDir Add(RootDir rootFolder)
|
||||
{
|
||||
return _db.Insert(rootFolder);
|
||||
}
|
||||
|
||||
public void Delete(int rootFolderId)
|
||||
{
|
||||
_db.Delete(Get(rootFolderId));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +1,40 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Repository;
|
||||
using PetaPoco;
|
||||
|
||||
namespace NzbDrone.Core.Providers
|
||||
namespace NzbDrone.Core.RootFolders
|
||||
{
|
||||
public class RootDirProvider
|
||||
public interface IRootFolderService
|
||||
{
|
||||
List<RootDir> All();
|
||||
RootDir Add(RootDir rootDir);
|
||||
void Remove(int rootDirId);
|
||||
List<String> GetUnmappedFolders(string path);
|
||||
Dictionary<string, ulong> FreeSpaceOnDrives();
|
||||
}
|
||||
|
||||
public class RootFolderService : IRootFolderService
|
||||
{
|
||||
private readonly IDatabase _database;
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
private readonly IRootFolderRepository _rootFolderRepository;
|
||||
private readonly DiskProvider _diskProvider;
|
||||
private readonly SeriesProvider _seriesProvider;
|
||||
|
||||
public RootDirProvider(IDatabase database, SeriesProvider seriesProvider, DiskProvider diskProvider)
|
||||
public RootFolderService(IRootFolderRepository rootFolderRepository, SeriesProvider seriesProvider, DiskProvider diskProvider)
|
||||
{
|
||||
_database = database;
|
||||
_rootFolderRepository = rootFolderRepository;
|
||||
_diskProvider = diskProvider;
|
||||
_seriesProvider = seriesProvider;
|
||||
}
|
||||
|
||||
public virtual List<RootDir> GetAll()
|
||||
public virtual List<RootDir> All()
|
||||
{
|
||||
return _database.Fetch<RootDir>();
|
||||
return _rootFolderRepository.All();
|
||||
}
|
||||
|
||||
public virtual RootDir Add(RootDir rootDir)
|
||||
|
@ -35,20 +45,19 @@ namespace NzbDrone.Core.Providers
|
|||
if (!_diskProvider.FolderExists(rootDir.Path))
|
||||
throw new DirectoryNotFoundException("Can't add root directory that doesn't exist.");
|
||||
|
||||
if (GetAll().Exists(r => DiskProvider.PathEquals(r.Path, rootDir.Path)))
|
||||
if (All().Exists(r => DiskProvider.PathEquals(r.Path, rootDir.Path)))
|
||||
throw new InvalidOperationException("Root directory already exist.");
|
||||
|
||||
var id = _database.Insert(rootDir);
|
||||
rootDir.Id = Convert.ToInt32(id);
|
||||
_rootFolderRepository.Add(rootDir);
|
||||
|
||||
rootDir.FreeSpace = _diskProvider.FreeDiskSpace(new DirectoryInfo(rootDir.Path));
|
||||
rootDir.UnmappedFolders = GetUnmappedFolders(rootDir.Path);
|
||||
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
public virtual void Remove(int rootDirId)
|
||||
{
|
||||
_database.Delete<RootDir>(rootDirId);
|
||||
_rootFolderRepository.Delete(rootDirId);
|
||||
}
|
||||
|
||||
public virtual List<String> GetUnmappedFolders(string path)
|
||||
|
@ -77,24 +86,12 @@ namespace NzbDrone.Core.Providers
|
|||
return results;
|
||||
}
|
||||
|
||||
public virtual List<RootDir> AllWithFreeSpace()
|
||||
{
|
||||
var rootDirs = GetAll();
|
||||
|
||||
foreach (var rootDir in rootDirs)
|
||||
{
|
||||
rootDir.FreeSpace = _diskProvider.FreeDiskSpace(new DirectoryInfo(rootDir.Path));
|
||||
rootDir.UnmappedFolders = GetUnmappedFolders(rootDir.Path);
|
||||
}
|
||||
|
||||
return rootDirs;
|
||||
}
|
||||
|
||||
public virtual Dictionary<string, ulong> FreeSpaceOnDrives()
|
||||
{
|
||||
var freeSpace = new Dictionary<string, ulong>();
|
||||
|
||||
var rootDirs = GetAll();
|
||||
var rootDirs = All();
|
||||
|
||||
foreach (var rootDir in rootDirs)
|
||||
{
|
|
@ -14,7 +14,7 @@
|
|||
<RootNamespace>NzbDrone.Services.Api</RootNamespace>
|
||||
<AssemblyName>NzbDrone.Services.Api</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<UseIISExpress>false</UseIISExpress>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
|
@ -150,9 +150,9 @@
|
|||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>0</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>1306</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:14615/</IISUrl>
|
||||
<IISUrl>http://localhost/NzbDrone.Services.Api</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
|
Binary file not shown.
|
@ -1,188 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Jobs;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Providers.Core;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Web.Filters;
|
||||
using NzbDrone.Web.Models;
|
||||
using TvdbLib.Exceptions;
|
||||
|
||||
namespace NzbDrone.Web.Controllers
|
||||
{
|
||||
public class AddSeriesController : Controller
|
||||
{
|
||||
private readonly ConfigProvider _configProvider;
|
||||
private readonly QualityProvider _qualityProvider;
|
||||
private readonly RootDirProvider _rootFolderProvider;
|
||||
private readonly SeriesProvider _seriesProvider;
|
||||
private readonly JobProvider _jobProvider;
|
||||
private readonly TvDbProvider _tvDbProvider;
|
||||
private readonly DiskProvider _diskProvider;
|
||||
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public AddSeriesController(RootDirProvider rootFolderProvider,
|
||||
ConfigProvider configProvider,
|
||||
QualityProvider qualityProvider, TvDbProvider tvDbProvider,
|
||||
SeriesProvider seriesProvider, JobProvider jobProvider,
|
||||
DiskProvider diskProvider)
|
||||
{
|
||||
|
||||
_rootFolderProvider = rootFolderProvider;
|
||||
_configProvider = configProvider;
|
||||
_qualityProvider = qualityProvider;
|
||||
_tvDbProvider = tvDbProvider;
|
||||
_seriesProvider = seriesProvider;
|
||||
_jobProvider = jobProvider;
|
||||
_diskProvider = diskProvider;
|
||||
}
|
||||
|
||||
public ActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public ActionResult AddNew()
|
||||
{
|
||||
ViewData["RootDirs"] = _rootFolderProvider.GetAll().Select(c => c.Path).OrderBy(e => e).ToList();
|
||||
|
||||
var defaultQuality = _configProvider.DefaultQualityProfile;
|
||||
var qualityProfiles = _qualityProvider.All();
|
||||
|
||||
ViewData["qualityProfiles"] = new SelectList(
|
||||
qualityProfiles,
|
||||
"QualityProfileId",
|
||||
"Name",
|
||||
defaultQuality);
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
public ActionResult ExistingSeries()
|
||||
{
|
||||
var result = new ExistingSeriesModel();
|
||||
|
||||
var unmappedList = new List<String>();
|
||||
|
||||
foreach (var folder in _rootFolderProvider.GetAll())
|
||||
{
|
||||
unmappedList.AddRange(_rootFolderProvider.GetUnmappedFolders(folder.Path));
|
||||
}
|
||||
|
||||
result.ExistingSeries = new List<Tuple<string, string, int>>();
|
||||
|
||||
foreach (var folder in unmappedList)
|
||||
{
|
||||
var foldername = new DirectoryInfo(folder).Name;
|
||||
|
||||
try
|
||||
{
|
||||
var tvdbResult = _tvDbProvider.SearchSeries(foldername).FirstOrDefault();
|
||||
|
||||
var title = String.Empty;
|
||||
var seriesId = 0;
|
||||
if (tvdbResult != null)
|
||||
{
|
||||
title = tvdbResult.SeriesName;
|
||||
seriesId = tvdbResult.id;
|
||||
}
|
||||
|
||||
result.ExistingSeries.Add(new Tuple<string, string, int>(folder, title, seriesId));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.WarnException("Failed to connect to TheTVDB to search for: " + foldername, ex);
|
||||
return View();
|
||||
}
|
||||
}
|
||||
|
||||
var defaultQuality = Convert.ToInt32(_configProvider.DefaultQualityProfile);
|
||||
result.Quality = new SelectList(_qualityProvider.All(), "QualityProfileId", "Name", defaultQuality);
|
||||
|
||||
return View(result);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[JsonErrorFilter]
|
||||
public JsonResult AddNewSeries(string path, string seriesName, int seriesId, int qualityProfileId, string startDate)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path) || String.Equals(path, "null", StringComparison.InvariantCultureIgnoreCase))
|
||||
return JsonNotificationResult.Error("Couldn't add " + seriesName, "You need a valid root folder");
|
||||
|
||||
path = Path.Combine(path, MediaFileProvider.CleanFilename(seriesName));
|
||||
|
||||
//Create the folder for the new series
|
||||
//Use the created folder name when adding the series
|
||||
path = _diskProvider.CreateDirectory(path);
|
||||
|
||||
return AddExistingSeries(path, seriesName, seriesId, qualityProfileId, startDate);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[JsonErrorFilter]
|
||||
public JsonResult AddExistingSeries(string path, string seriesName, int seriesId, int qualityProfileId, string startDate)
|
||||
{
|
||||
if (seriesId == 0 || String.IsNullOrWhiteSpace(seriesName))
|
||||
return JsonNotificationResult.Error("Add Existing series failed.", "Invalid Series information");
|
||||
|
||||
DateTime? date = null;
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(startDate))
|
||||
date = DateTime.Parse(startDate, null, DateTimeStyles.RoundtripKind);
|
||||
|
||||
_seriesProvider.AddSeries(seriesName, path, seriesId, qualityProfileId, date);
|
||||
_jobProvider.QueueJob(typeof(ImportNewSeriesJob));
|
||||
|
||||
return JsonNotificationResult.Info(seriesName, "Was added successfully");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[JsonErrorFilter]
|
||||
public JsonResult LookupSeries(string term)
|
||||
{
|
||||
|
||||
return JsonNotificationResult.Info("Lookup Failed", "Unknown error while connecting to TheTVDB");
|
||||
|
||||
}
|
||||
|
||||
public ActionResult RootList()
|
||||
{
|
||||
IEnumerable<String> rootDir = _rootFolderProvider.GetAll().Select(c => c.Path).OrderBy(e => e);
|
||||
return PartialView("RootList", rootDir);
|
||||
}
|
||||
|
||||
public ActionResult RootDir()
|
||||
{
|
||||
return PartialView("RootDir");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[JsonErrorFilter]
|
||||
public JsonResult SaveRootDir(string path)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(path))
|
||||
JsonNotificationResult.Error("Can't add root folder", "Path can not be empty");
|
||||
|
||||
_rootFolderProvider.Add(new RootDir { Path = path });
|
||||
|
||||
return JsonNotificationResult.Info("Root Folder saved", "Root folder saved successfully.");
|
||||
}
|
||||
|
||||
[JsonErrorFilter]
|
||||
public JsonResult DeleteRootDir(string path)
|
||||
{
|
||||
|
||||
var id = _rootFolderProvider.GetAll().Where(c => c.Path == path).First().Id;
|
||||
_rootFolderProvider.Remove(id);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using System.Web.Mvc;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Web.Models;
|
||||
|
||||
namespace NzbDrone.Web.Controllers
|
||||
|
@ -8,12 +9,12 @@ namespace NzbDrone.Web.Controllers
|
|||
public class SharedController : Controller
|
||||
{
|
||||
private readonly EnvironmentProvider _environmentProvider;
|
||||
private readonly RootDirProvider _rootDirProvider;
|
||||
private readonly RootFolderService _rootFolderService;
|
||||
|
||||
public SharedController(EnvironmentProvider environmentProvider, RootDirProvider rootDirProvider)
|
||||
public SharedController(EnvironmentProvider environmentProvider, RootFolderService rootFolderService)
|
||||
{
|
||||
_environmentProvider = environmentProvider;
|
||||
_rootDirProvider = rootDirProvider;
|
||||
_rootFolderService = rootFolderService;
|
||||
}
|
||||
|
||||
public ActionResult Index()
|
||||
|
@ -32,7 +33,7 @@ namespace NzbDrone.Web.Controllers
|
|||
[OutputCache(Duration = 600)]
|
||||
public ActionResult FreeSpace()
|
||||
{
|
||||
var rootDirs = _rootDirProvider.FreeSpaceOnDrives();
|
||||
var rootDirs = _rootFolderService.FreeSpaceOnDrives();
|
||||
|
||||
return PartialView(rootDirs);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0"?>
|
||||
<Eloquera xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<Cache IndexCacheSize="10000"
|
||||
WriteThru="false"
|
||||
IndexCleanerPeriod="100"
|
||||
IndexCleanerBatchSize="100"
|
||||
CleanerPeriod="100"
|
||||
CleanerBatchSize="2000"
|
||||
CommitSequenceMaxLength="2000"
|
||||
ShallowReadThreshold="1000"
|
||||
ShallowReadAhead="1000"
|
||||
ReadAhead="20"
|
||||
SaturationThreshold="10000"
|
||||
MemoryFootPrint="60"/>
|
||||
<MemoryManager Mode="1" />
|
||||
<Server ServerPort="43962"
|
||||
Trace="true"
|
||||
InMemoryAllowed="true"
|
||||
Secure="false"
|
||||
AllowUsers=""
|
||||
AllowGroups="Everyone"
|
||||
SNMPAddress="net.tcp://localhost:8523/SNMP"
|
||||
AutoRecovery="false"
|
||||
NotificationsEnabled="false"
|
||||
VarSectorSize="40"
|
||||
IndexNodeSize="512"/>
|
||||
<SmartRuntime Smart="true"
|
||||
TypeUpdateAllowed="true"/>
|
||||
<UserLogin Enabled="false"
|
||||
PasswordHash="l+on1aCwDrcZ5bGlv+fyyIlYkbuFIOxZFlFwIGKlms0CCwoGn9TZvM0E3Uksjwx64+/yv8nsaUajWLz1kyKG7A==" />
|
||||
</Eloquera>
|
|
@ -17,7 +17,7 @@
|
|||
<MvcBuildViews>true</MvcBuildViews>
|
||||
<EnableUpdateable>false</EnableUpdateable>
|
||||
<TargetFrameworkProfile />
|
||||
<UseIISExpress>false</UseIISExpress>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
|
@ -26,6 +26,10 @@
|
|||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<JSLintSkip>\_backboneApp\JsLibraries\|\Scripts\</JSLintSkip>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -88,6 +92,17 @@
|
|||
<Reference Include="Dynamic">
|
||||
<HintPath>..\packages\DynamicQuery.1.0\lib\35\Dynamic.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Eloquera.Client, Version=5.0.0.0, Culture=neutral, PublicKeyToken=170cadcdba67be6c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\EloqueraDB.5.0.0\lib\net40\Eloquera.Client.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Eloquera.Common, Version=5.0.0.0, Culture=neutral, PublicKeyToken=170cadcdba67be6c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\EloqueraDB.5.0.0\lib\net40\Eloquera.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Eloquera.Server">
|
||||
<HintPath>..\packages\EloqueraDB.5.0.0\lib\net40\Eloquera.Server.exe</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="LowercaseRoutesMVC">
|
||||
<HintPath>..\packages\LowercaseRoutesMVC.1.0.3\lib\LowercaseRoutesMVC.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -341,7 +356,6 @@
|
|||
<Compile Include="Controllers\HealthController.cs" />
|
||||
<Compile Include="Controllers\HistoryController.cs" />
|
||||
<Compile Include="Controllers\LogController.cs" />
|
||||
<Compile Include="Controllers\AddSeriesController.cs" />
|
||||
<Compile Include="Controllers\MissingController.cs" />
|
||||
<Compile Include="Controllers\NotificationController.cs" />
|
||||
<Compile Include="Controllers\SeriesController.cs" />
|
||||
|
@ -401,6 +415,7 @@
|
|||
<Content Include="_backboneApp\Shared\NotificationView.js" />
|
||||
<Content Include="_backboneApp\Shared\SpinnerTemplate.html" />
|
||||
<Content Include="_backboneApp\Shared\SpinnerView.js" />
|
||||
<Content Include="Eloquera.config" />
|
||||
<None Include="_backboneApp\JsLibraries\jquery-1.8.2.intellisense.js" />
|
||||
<Content Include="_backboneApp\JsLibraries\backbone.collectionbinder.js" />
|
||||
<Content Include="_backboneApp\JsLibraries\backbone.debug.js" />
|
||||
|
@ -606,8 +621,6 @@
|
|||
<Content Include="Scripts\jquery.watermark.min.js" />
|
||||
<Content Include="Scripts\underscore.js" />
|
||||
<Content Include="Scripts\underscore.min.js" />
|
||||
<Content Include="Views\AddSeries\Index.cshtml" />
|
||||
<Content Include="Views\AddSeries\AddNew.cshtml" />
|
||||
<Content Include="Web.config">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
|
@ -624,7 +637,6 @@
|
|||
<Content Include="Views\Settings\Naming.cshtml" />
|
||||
<Content Include="Views\Settings\Notifications.cshtml" />
|
||||
<Content Include="Views\Settings\Quality.cshtml" />
|
||||
<Content Include="Views\AddSeries\RootDir.cshtml" />
|
||||
<Content Include="Views\Shared\_Layout.cshtml" />
|
||||
<Content Include="Views\Shared\Footer.cshtml" />
|
||||
<Content Include="Views\_ViewStart.cshtml" />
|
||||
|
@ -666,15 +678,9 @@
|
|||
<ItemGroup>
|
||||
<Content Include="Views\Missing\Index.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\AddSeries\ExistingSeries.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\System\PendingProcessing.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\AddSeries\RootList.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\Settings\System.cshtml" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
@using System.Collections
|
||||
@{ Layout = null; }
|
||||
<div>
|
||||
<div>
|
||||
<input id="newSeriesLookup" class="seriesLookup" type="text" style="width: 400px" />
|
||||
@Html.Hidden("newSeriesId", 0, new { @class = "seriesId" })
|
||||
</div>
|
||||
@Html.DropDownList("newSeriesPath", new SelectList((IList)ViewData["RootDirs"]), new { style = "width: 406px; margin-left: 0px;" })
|
||||
@Html.DropDownList("qualityList", (SelectList)ViewData["QualityProfiles"], new { @class = "qualitySelector" })
|
||||
@Html.TextBox("newStartDate", "", new { type = "date", @class = "jQuery-datepicker start-date", placeholder = "Custom Start Date", title = "Only download episodes that aired after the specified date" })
|
||||
<button id="saveNewSeries">
|
||||
Add</button>
|
||||
</div>
|
|
@ -1,44 +0,0 @@
|
|||
@using System.Collections
|
||||
@using NzbDrone.Web.Models
|
||||
@using System.Web.Mvc.Html
|
||||
@model ExistingSeriesModel
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
@if (Model == null)
|
||||
{
|
||||
<h2 style="color: tomato">
|
||||
Error searching TheTVDB, please try again later.
|
||||
</h2>
|
||||
}
|
||||
|
||||
else if (!Model.ExistingSeries.Any())
|
||||
{
|
||||
<h2 style="color: tomato">
|
||||
No series available. Try adding a new Root Folder.
|
||||
</h2>
|
||||
}
|
||||
else
|
||||
{
|
||||
@Html.DropDownList(Guid.NewGuid().ToString(), Model.Quality, new { @class = "qualitySelector masterQualitySelector" })
|
||||
|
||||
@Html.TextBox(Guid.NewGuid().ToString(), "", new { type="date", @class = "jQuery-datepicker start-date-master", placeholder = "Custom Start Date", title = "Only download episodes that aired after the specified date" })
|
||||
|
||||
foreach (var series in Model.ExistingSeries)
|
||||
{
|
||||
<div class="existingSeries">
|
||||
<span class="seriesPathValue">
|
||||
<label>@series.Item1</label>
|
||||
</span>
|
||||
<div class="existingSeriesContainer">
|
||||
<input class="seriesLookup" type="text" style="width: 400px;" value="@series.Item2" placeholder="Series Title" />
|
||||
@Html.Hidden("seriesId", series.Item3, new { @class = "seriesId" })
|
||||
@Html.DropDownList(Guid.NewGuid().ToString(), Model.Quality, new { @class = "qualitySelector" })
|
||||
@Html.TextBox(Guid.NewGuid().ToString(), "", new { type="date", @class = "jQuery-datepicker start-date", placeholder = "Custom Start Date", title = "Only download episodes that aired after the specified date" })
|
||||
<button class="addExistingButton">
|
||||
Add</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
@using NzbDrone.Web.Helpers
|
||||
@{ViewBag.Title = "Add Series";}
|
||||
|
||||
@section HeaderContent
|
||||
{
|
||||
<style>
|
||||
.existingSeries
|
||||
{
|
||||
border-color: #f2f2f2;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
background-color: #f2f2f2;
|
||||
margin: 0px 10px 10px 0px;
|
||||
padding: 5px;
|
||||
display: block;
|
||||
}
|
||||
.masterQualitySelector
|
||||
{
|
||||
left: 415px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.start-date-master {
|
||||
left: 430px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.seriesPathValue
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.existingSeriesContainer
|
||||
{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ui-autocomplete.seriesLookupResults {
|
||||
max-height: 180px;
|
||||
overflow-y: auto;
|
||||
/* prevent horizontal scrollbar */
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.tvDbLink {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.tvDbLink:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
input[type=date].start-date {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
|
||||
@{Html.RenderAction("RootDir");}
|
||||
<div class="jquery-accordion jquery-accordion-collapse-all" id="addSeriesAccordion">
|
||||
<h3>
|
||||
<a href="#">Add New Series</a></h3>
|
||||
<div id="addNewSeries">
|
||||
@{ Html.RenderAction("AddNew", "AddSeries"); }
|
||||
</div>
|
||||
<h3>
|
||||
<a href="#">Add Series Already on Disk</a></h3>
|
||||
<div id="existingSeries">
|
||||
<img src="../../Content/Images/ajax-loader.gif" />
|
||||
|
||||
@Ajax.RenderAction(
|
||||
"ExistingSeries",
|
||||
"AddSeries",
|
||||
null,
|
||||
new AjaxOptions { UpdateTargetId = "existingSeries", InsertionMode = InsertionMode.Replace }
|
||||
)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts
|
||||
{
|
||||
@Html.IncludeScript("NzbDrone/addSeries.js")
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).on('click', '.tvDbLink', function (event) {
|
||||
var url = $(this).attr('rel');
|
||||
window.open(url, 'thetvdb');
|
||||
event.preventDefault();
|
||||
});
|
||||
</script>
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<h2>
|
||||
Manage Root Folders
|
||||
</h2>
|
||||
<span>
|
||||
<input id="rootDirInput" class="folderLookup" type="text" style="width: 400px" />
|
||||
<button id="saveDir">
|
||||
Add</button>
|
||||
</span><span id="rootDirs">
|
||||
@{Html.RenderAction("RootList");}
|
||||
</span>
|
|
@ -1,16 +0,0 @@
|
|||
@model IEnumerable<String>
|
||||
@if (!Model.Any())
|
||||
{
|
||||
<div class="actionButton delete">
|
||||
<span>You have no root folders added.</span>
|
||||
</div>
|
||||
}
|
||||
@foreach (var root in Model)
|
||||
{
|
||||
<div class="actionButton delete">
|
||||
<div class="delete-root" data-path="@root">
|
||||
<i class="icon-remove icon-large"></i>
|
||||
</div>
|
||||
<span>@root</span>
|
||||
</div>
|
||||
}
|
|
@ -5,16 +5,16 @@
|
|||
{
|
||||
@Html.IncludeCss("Settings.css")
|
||||
}
|
||||
<style>
|
||||
<style>
|
||||
.progressbar {
|
||||
position:relative;
|
||||
width: 125px;
|
||||
position: relative;
|
||||
width: 125px;
|
||||
height: 20px;
|
||||
background-color: transparent;
|
||||
border: 1px solid #065EFE;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
|
||||
.progressbar-text {
|
||||
position: absolute;
|
||||
display: block;
|
||||
|
@ -27,33 +27,29 @@
|
|||
border: 1px solid #065EFE;
|
||||
}
|
||||
|
||||
.ui-progressbar-value .progressbar-text {
|
||||
position: relative;
|
||||
font-weight: normal;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ui-progressbar-value .progressbar-text {
|
||||
position: relative;
|
||||
font-weight: normal;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Set the row height so it won't resize when the progress bar is created */
|
||||
.seriesTable tr
|
||||
{
|
||||
.seriesTable tr {
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.commandsColumn, .statusColumn
|
||||
{
|
||||
|
||||
.commandsColumn, .statusColumn {
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ui-dialog-buttonpane .ui-dialog-buttonset .ui-delete-button
|
||||
{
|
||||
|
||||
.ui-dialog-buttonpane .ui-dialog-buttonset .ui-delete-button {
|
||||
margin-right: 445px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@section ActionMenu{
|
||||
<ul class="sub-menu">
|
||||
<li>@Html.ActionLink("Add Series", "Index", "AddSeries", null, new { Title = "Add a new or existing series" })</li>
|
||||
<li><a href="/v2#series/add">Add Series</a></li>
|
||||
<li>@Ajax.ActionLink("Start RSS Sync", "RssSync", "Command", null, null, new { Title = "Check for newly released downloads" })</li>
|
||||
<li>@Html.ActionLink("Series Editor", "Editor", "Series", null, new { Title = "Edit multiple series" })</li>
|
||||
</ul>
|
||||
|
@ -61,7 +57,7 @@
|
|||
|
||||
<table id="seriesGrid" class="dataTablesGrid hidden-grid">
|
||||
<thead>
|
||||
|
||||
|
||||
<tr>
|
||||
<th style="width: 10px">Status</th>
|
||||
<th style="width: auto">Title</th>
|
||||
|
@ -70,7 +66,7 @@
|
|||
<th style="width: 100px">Network</th>
|
||||
<th style="width: 140px">Next Airing</th>
|
||||
<th style="width: 100px">Episodes</th>
|
||||
|
||||
|
||||
@*Commands Column*@
|
||||
<th style="width: 80px"></th>
|
||||
</tr>
|
||||
|
@ -96,7 +92,7 @@
|
|||
@Html.IncludeScript("NzbDrone/series.js")
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
var pauseImage = '<i class="icon-pause grid-icon" title="Not Monitored"></i>';
|
||||
var stopImage = '<i class="icon-stop grid-icon" title="Ended"></i>';
|
||||
var playImage = '<i class="icon-play grid-icon" title="Continuing"></i>';
|
||||
|
@ -115,56 +111,60 @@
|
|||
"bInfo": false,
|
||||
"bAutoWidth": false,
|
||||
"bStateSave": true,
|
||||
"iCookieDuration": 60 * 60 *24 * 365, //1 year
|
||||
"iCookieDuration": 60 * 60 * 24 * 365, //1 year
|
||||
"aoColumns": [
|
||||
{ sWidth: '70px',
|
||||
"sClass": "statusColumn",
|
||||
"mDataProp": function (source, type, val) {
|
||||
// 'display' and 'filter' use our fancy naming
|
||||
if (type === 'display' || type === 'filter') {
|
||||
var monitored = source["Monitored"];
|
||||
var status = source["Status"];
|
||||
|
||||
if (!monitored) {
|
||||
return pauseImage;
|
||||
}
|
||||
|
||||
else {
|
||||
if (status === "Ended"){
|
||||
return stopImage;
|
||||
}
|
||||
|
||||
else {
|
||||
return playImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 'sort' and 'type' both just use the raw data
|
||||
return source["Status"];
|
||||
{
|
||||
sWidth: '70px',
|
||||
"sClass": "statusColumn",
|
||||
"mDataProp": function (source, type, val) {
|
||||
// 'display' and 'filter' use our fancy naming
|
||||
if (type === 'display' || type === 'filter') {
|
||||
var monitored = source["Monitored"];
|
||||
var status = source["Status"];
|
||||
|
||||
if (!monitored) {
|
||||
return pauseImage;
|
||||
}
|
||||
|
||||
else {
|
||||
if (status === "Ended") {
|
||||
return stopImage;
|
||||
}
|
||||
|
||||
else {
|
||||
return playImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 'sort' and 'type' both just use the raw data
|
||||
return source["Status"];
|
||||
}
|
||||
}, //Status
|
||||
{ sWidth: 'auto', "mDataProp": function (source, type, val) {
|
||||
// 'display' and 'filter' use our fancy naming
|
||||
if (type === 'display' || type === 'filter') {
|
||||
return "<a href='/series/details/" + source["SeriesId"] + "'>" + source["Title"] + "</a>";
|
||||
}
|
||||
// 'sort' and 'type' both just use the raw data
|
||||
return source["TitleSorter"];
|
||||
}
|
||||
{
|
||||
sWidth: 'auto', "mDataProp": function (source, type, val) {
|
||||
// 'display' and 'filter' use our fancy naming
|
||||
if (type === 'display' || type === 'filter') {
|
||||
return "<a href='/series/details/" + source["SeriesId"] + "'>" + source["Title"] + "</a>";
|
||||
}
|
||||
// 'sort' and 'type' both just use the raw data
|
||||
return source["TitleSorter"];
|
||||
}
|
||||
}, //Title
|
||||
{ sWidth: '100px', "mDataProp": "SeasonsCount" }, //Seasons
|
||||
{ sWidth: '100px', "mDataProp": "QualityProfileName", sClass: "qualityColumn" }, //Quality
|
||||
{ sWidth: '120px', "mDataProp": "Network" }, //Network
|
||||
{ sWidth: '120px', "mDataProp": function (source, type, val) {
|
||||
// 'display' and 'filter' use our fancy naming
|
||||
if (type === 'display' || type === 'filter') {
|
||||
return source["NextAiring"];
|
||||
}
|
||||
// 'sort' and 'type' both just use the raw data
|
||||
return source["NextAiringSorter"];
|
||||
}
|
||||
{
|
||||
sWidth: '120px', "mDataProp": function (source, type, val) {
|
||||
// 'display' and 'filter' use our fancy naming
|
||||
if (type === 'display' || type === 'filter') {
|
||||
return source["NextAiring"];
|
||||
}
|
||||
// 'sort' and 'type' both just use the raw data
|
||||
return source["NextAiringSorter"];
|
||||
}
|
||||
}, //Next Airing
|
||||
{ sWidth: '140px', "mDataProp": "Episodes", "bSortable": false, "fnRender": function (row) {
|
||||
{
|
||||
sWidth: '140px', "mDataProp": "Episodes", "bSortable": false, "fnRender": function (row) {
|
||||
var progress = 100;
|
||||
if (row.aData["EpisodeCount"] > 0)
|
||||
progress = row.aData["EpisodeFileCount"] / row.aData["EpisodeCount"] * 100;
|
||||
|
@ -188,16 +188,17 @@
|
|||
"<i class='icon-remove deleteButton gridAction' title = 'Delete Series' data-series-id='" + row.aData["SeriesId"] + "' data-series-title='" + row.aData["Title"] + "'></i>";
|
||||
}
|
||||
}, //Commands
|
||||
{ sWidth: '60px', "mDataProp": "Details", "bSortable": false, "bVisible": false, "fnRender": function (row) {
|
||||
var result = "<b>Airs Day of Week: </b>" + row.aData["AirsDayOfWeek"] + "<br/>" +
|
||||
"<b>Air Time: </b>" + row.aData["AirTime"] + "<br/>" +
|
||||
"<b>Overview: </b>" + row.aData["Overview"] + "<br/>";
|
||||
{
|
||||
sWidth: '60px', "mDataProp": "Details", "bSortable": false, "bVisible": false, "fnRender": function (row) {
|
||||
var result = "<b>Airs Day of Week: </b>" + row.aData["AirsDayOfWeek"] + "<br/>" +
|
||||
"<b>Air Time: </b>" + row.aData["AirTime"] + "<br/>" +
|
||||
"<b>Overview: </b>" + row.aData["Overview"] + "<br/>";
|
||||
return result;
|
||||
}
|
||||
} //Details
|
||||
],
|
||||
],
|
||||
"aaSorting": [[1, 'asc']],
|
||||
"fnCreatedRow": function( nRow, aData, iDataIndex ) {
|
||||
"fnCreatedRow": function (nRow, aData, iDataIndex) {
|
||||
$(nRow).attr('data-series-id', aData["SeriesId"].toString());
|
||||
},
|
||||
"oLanguage": {
|
||||
|
@ -205,25 +206,25 @@
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//After we delete a series do this...
|
||||
function afterDelete(seriesId) {
|
||||
var row = $('[data-series-id="' + seriesId + '"]');
|
||||
|
||||
|
||||
if ($(row).hasClass('details-opened')) {
|
||||
var nextRow = $(row).next('tr');
|
||||
if($(nextRow).children('.Details').length > 0) {
|
||||
if ($(nextRow).children('.Details').length > 0) {
|
||||
$(nextRow).hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$(row).hide();
|
||||
}
|
||||
|
||||
|
||||
//After we save do this...
|
||||
function afterSave() {
|
||||
updateStatus();
|
||||
|
||||
|
||||
//Update Quality
|
||||
var seriesId = $('#SeriesId').val();
|
||||
var quality = $('#QualityProfileId :selected').text();
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
|
||||
<div class="infoBox">It looks like you haven't added any series to NzbDrone. @Html.ActionLink("Click here to add one.", "Index", "AddSeries")</div>
|
||||
<div class="infoBox">It looks like you haven't added any series to NzbDrone. <a href="/v2#series/add">Click here to add one.</a></div>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<package id="DataTables.Mvc.Core" version="0.1.0.85" />
|
||||
<package id="DotlessClientOnly" version="1.3.1.0" targetFramework="net40" />
|
||||
<package id="DynamicQuery" version="1.0" />
|
||||
<package id="EloqueraDB" version="5.0.0" targetFramework="net40" />
|
||||
<package id="FontAwesome" version="2.0.2" targetFramework="net40" />
|
||||
<package id="jQuery" version="1.8.2" targetFramework="net40" />
|
||||
<package id="jQuery.Ajax.Unobtrusive" version="2.0.20710.0" targetFramework="net40" />
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<SolutionConfiguration>
|
||||
<FileVersion>1</FileVersion>
|
||||
<AutoEnableOnStartup>False</AutoEnableOnStartup>
|
||||
<AutoEnableOnStartup>True</AutoEnableOnStartup>
|
||||
<AllowParallelTestExecution>true</AllowParallelTestExecution>
|
||||
<AllowTestsToRunInParallelWithThemselves>true</AllowTestsToRunInParallelWithThemselves>
|
||||
<FrameworkUtilisationTypeForNUnit>UseDynamicAnalysis</FrameworkUtilisationTypeForNUnit>
|
||||
<FrameworkUtilisationTypeForGallio>Disabled</FrameworkUtilisationTypeForGallio>
|
||||
<FrameworkUtilisationTypeForMSpec>Disabled</FrameworkUtilisationTypeForMSpec>
|
||||
|
|
Loading…
Reference in New Issue