mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-14 02:26:55 -07:00
parent
05bdfcd550
commit
55f1309140
41 changed files with 494 additions and 261 deletions
|
@ -24,36 +24,29 @@ namespace PlexRequests.Core.Migration
|
|||
var con = Db.DbConnection();
|
||||
var versions = GetMigrations();
|
||||
|
||||
var dbVersion = con.GetVersionInfo().OrderByDescending(x => x.Version).FirstOrDefault();
|
||||
if (dbVersion == null)
|
||||
{
|
||||
dbVersion = new TableCreation.VersionInfo { Version = 0 };
|
||||
}
|
||||
var dbVersion = con.GetVersionInfo().OrderByDescending(x => x.Version).FirstOrDefault() ??
|
||||
new TableCreation.VersionInfo { Version = 0 };
|
||||
foreach (var v in versions)
|
||||
{
|
||||
#if !DEBUG
|
||||
if (v.Value.Version > dbVersion.Version)
|
||||
{
|
||||
// Assuming only one constructor
|
||||
var ctor = v.Key.GetConstructors().FirstOrDefault();
|
||||
var dependencies = new List<object>();
|
||||
#endif
|
||||
// Assuming only one constructor
|
||||
var ctor = v.Key.GetConstructors().FirstOrDefault();
|
||||
var dependencies = ctor.GetParameters().Select(param => Kernel.Get(param.ParameterType)).ToList();
|
||||
|
||||
foreach (var param in ctor.GetParameters())
|
||||
{
|
||||
var dep = Kernel.Get(param.ParameterType);
|
||||
dependencies.Add(dep);
|
||||
}
|
||||
var method = v.Key.GetMethod("Start");
|
||||
if (method != null)
|
||||
{
|
||||
var classInstance = Activator.CreateInstance(v.Key, dependencies.Any() ? dependencies.ToArray() : null);
|
||||
var parametersArray = new object[] { Db.DbConnection() };
|
||||
|
||||
var method = v.Key.GetMethod("Start");
|
||||
if (method != null)
|
||||
{
|
||||
object result = null;
|
||||
var classInstance = Activator.CreateInstance(v.Key, dependencies.Any() ? dependencies.ToArray() : null);
|
||||
|
||||
var parametersArray = new object[] { Db.DbConnection() };
|
||||
|
||||
method.Invoke(classInstance, parametersArray);
|
||||
}
|
||||
method.Invoke(classInstance, parametersArray);
|
||||
}
|
||||
#if !DEBUG
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,10 @@
|
|||
|
||||
using System;
|
||||
using System.Data;
|
||||
using NLog;
|
||||
using System.Linq;
|
||||
using PlexRequests.Core.SettingModels;
|
||||
using PlexRequests.Helpers;
|
||||
using PlexRequests.Helpers.Permissions;
|
||||
using PlexRequests.Store;
|
||||
using PlexRequests.Store.Repository;
|
||||
|
@ -37,14 +40,16 @@ namespace PlexRequests.Core.Migration.Migrations
|
|||
[Migration(11000, "v1.10.0.0")]
|
||||
public class Version1100 : BaseMigration, IMigration
|
||||
{
|
||||
public Version1100(IUserRepository userRepo, IRequestService requestService)
|
||||
public Version1100(IUserRepository userRepo, IRequestService requestService, ISettingsService<LogSettings> log)
|
||||
{
|
||||
UserRepo = userRepo;
|
||||
RequestService = requestService;
|
||||
Log = log;
|
||||
}
|
||||
public int Version => 11000;
|
||||
private IUserRepository UserRepo { get; }
|
||||
private IRequestService RequestService { get; }
|
||||
private ISettingsService<LogSettings> Log { get; }
|
||||
|
||||
public void Start(IDbConnection con)
|
||||
{
|
||||
|
@ -52,22 +57,25 @@ namespace PlexRequests.Core.Migration.Migrations
|
|||
|
||||
// Update the current admin permissions set
|
||||
UpdateAdmin();
|
||||
|
||||
|
||||
ResetLogLevel();
|
||||
UpdateSchema(con, Version);
|
||||
}
|
||||
|
||||
private void ResetLogLevel()
|
||||
{
|
||||
var logSettings = Log.GetSettings();
|
||||
logSettings.Level = LogLevel.Error.Ordinal;
|
||||
Log.SaveSettings(logSettings);
|
||||
|
||||
LoggingHelper.ReconfigureLogLevel(LogLevel.FromOrdinal(logSettings.Level));
|
||||
}
|
||||
|
||||
private void UpdateDb(IDbConnection con)
|
||||
{
|
||||
// Create the two new columns
|
||||
con.AlterTable("Users", "ADD", "Permissions", true, "INTEGER");
|
||||
con.AlterTable("Users", "ADD", "Features", true, "INTEGER");
|
||||
|
||||
// Add the new 'running' item into the scheduled jobs so we can check if the cachers are running
|
||||
con.AlterTable("ScheduledJobs", "ADD", "Running", true, "INTEGER");
|
||||
|
||||
|
||||
|
||||
//https://image.tmdb.org/t/p/w150/https://image.tmdb.org/t/p/w150//aqhAqttDq7zgsTaBHtCD8wmTk6k.jpg
|
||||
|
||||
// UI = https://image.tmdb.org/t/p/w150/{{posterPath}}
|
||||
|
|
|
@ -45,6 +45,10 @@
|
|||
<Reference Include="Ninject">
|
||||
<HintPath>..\packages\Ninject.3.2.0.0\lib\net45-full\Ninject.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.3.11\lib\net45\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Quartz, Version=2.3.3.0, Culture=neutral, PublicKeyToken=f6b8c98a402cc8a4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Quartz.2.3.3\lib\net40\Quartz.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
<packages>
|
||||
<package id="Common.Logging" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Common.Logging.Core" version="3.0.0" targetFramework="net45" />
|
||||
<package id="NLog" version="4.3.11" targetFramework="net45" />
|
||||
<package id="Quartz" version="2.3.3" targetFramework="net45" />
|
||||
</packages>
|
|
@ -61,51 +61,12 @@ namespace PlexRequests.Core
|
|||
TableCreation.Vacuum(Db.DbConnection());
|
||||
}
|
||||
|
||||
|
||||
// The below code is obsolete, we should use PlexRequests.Core.Migrations.MigrationRunner
|
||||
var version = CheckSchema();
|
||||
if (version > 0)
|
||||
{
|
||||
if (version > 1899 && version <= 1900)
|
||||
{
|
||||
MigrateToVersion1900();
|
||||
}
|
||||
|
||||
if(version > 1899 && version <= 1910)
|
||||
{
|
||||
MigrateToVersion1910();
|
||||
}
|
||||
}
|
||||
// Add the new 'running' item into the scheduled jobs so we can check if the cachers are running
|
||||
Db.DbConnection().AlterTable("ScheduledJobs", "ADD", "Running", true, "INTEGER");
|
||||
|
||||
return Db.DbConnection().ConnectionString;
|
||||
}
|
||||
|
||||
public static string ConnectionString => Db.DbConnection().ConnectionString;
|
||||
|
||||
|
||||
private int CheckSchema()
|
||||
{
|
||||
var productVersion = AssemblyHelper.GetProductVersion();
|
||||
var trimStatus = new Regex("[^0-9]", RegexOptions.Compiled).Replace(productVersion, string.Empty).PadRight(4, '0');
|
||||
var version = int.Parse(trimStatus);
|
||||
|
||||
var connection = Db.DbConnection();
|
||||
var schema = connection.GetSchemaVersion();
|
||||
if (schema == null)
|
||||
{
|
||||
connection.CreateSchema(version); // Set the default.
|
||||
schema = connection.GetSchemaVersion();
|
||||
}
|
||||
if (version > schema.SchemaVersion)
|
||||
{
|
||||
Db.DbConnection().UpdateSchemaVersion(version);
|
||||
schema = connection.GetSchemaVersion();
|
||||
}
|
||||
version = schema.SchemaVersion;
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
private void CreateDefaultSettingsPage(string baseUrl)
|
||||
{
|
||||
var defaultSettings = new PlexRequestSettings
|
||||
|
@ -148,7 +109,6 @@ namespace PlexRequests.Core
|
|||
Task.Run(() => { CacheSonarrQualityProfiles(mc); });
|
||||
Task.Run(() => { CacheCouchPotatoQualityProfiles(mc); });
|
||||
// we don't need to cache sickrage profiles, those are static
|
||||
// TODO: cache headphones profiles?
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
@ -156,12 +116,12 @@ namespace PlexRequests.Core
|
|||
}
|
||||
}
|
||||
|
||||
private void CacheSonarrQualityProfiles(MemoryCacheProvider cacheProvider)
|
||||
private void CacheSonarrQualityProfiles(ICacheProvider cacheProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.Info("Executing GetSettings call to Sonarr for quality profiles");
|
||||
var sonarrSettingsService = new SettingsServiceV2<SonarrSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), new MemoryCacheProvider()));
|
||||
var sonarrSettingsService = new SettingsServiceV2<SonarrSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), cacheProvider));
|
||||
var sonarrSettings = sonarrSettingsService.GetSettings();
|
||||
if (sonarrSettings.Enabled)
|
||||
{
|
||||
|
@ -178,12 +138,12 @@ namespace PlexRequests.Core
|
|||
}
|
||||
}
|
||||
|
||||
private void CacheCouchPotatoQualityProfiles(MemoryCacheProvider cacheProvider)
|
||||
private void CacheCouchPotatoQualityProfiles(ICacheProvider cacheProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.Info("Executing GetSettings call to CouchPotato for quality profiles");
|
||||
var cpSettingsService = new SettingsServiceV2<CouchPotatoSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), new MemoryCacheProvider()));
|
||||
var cpSettingsService = new SettingsServiceV2<CouchPotatoSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), cacheProvider));
|
||||
var cpSettings = cpSettingsService.GetSettings();
|
||||
if (cpSettings.Enabled)
|
||||
{
|
||||
|
@ -199,102 +159,5 @@ namespace PlexRequests.Core
|
|||
Log.Error(ex, "Failed to cache CouchPotato quality profiles!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Migrates to version 1.9.
|
||||
/// Move the Plex auth token to the new field.
|
||||
/// Reconfigure the log level
|
||||
/// Set the wizard flag to true if we already have settings
|
||||
/// </summary>
|
||||
public void MigrateToVersion1900()
|
||||
{
|
||||
// Need to change the Plex Token location
|
||||
var authSettings = new SettingsServiceV2<AuthenticationSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
|
||||
var auth = authSettings.GetSettings();
|
||||
var plexSettings = new SettingsServiceV2<PlexSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
|
||||
|
||||
if (auth != null)
|
||||
{
|
||||
//If we have an authToken we do not need to go through the setup
|
||||
if (!string.IsNullOrEmpty(auth.OldPlexAuthToken))
|
||||
{
|
||||
var prServuce = new SettingsServiceV2<PlexRequestSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
|
||||
var settings = prServuce.GetSettings();
|
||||
settings.Wizard = true;
|
||||
prServuce.SaveSettings(settings);
|
||||
}
|
||||
|
||||
// Clear out the old token and save it to the new field
|
||||
var currentSettings = plexSettings.GetSettings();
|
||||
if (!string.IsNullOrEmpty(auth.OldPlexAuthToken))
|
||||
{
|
||||
currentSettings.PlexAuthToken = auth.OldPlexAuthToken;
|
||||
plexSettings.SaveSettings(currentSettings);
|
||||
|
||||
// Clear out the old value
|
||||
auth.OldPlexAuthToken = string.Empty;
|
||||
authSettings.SaveSettings(auth);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Set the log level
|
||||
try
|
||||
{
|
||||
var settingsService = new SettingsServiceV2<LogSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
|
||||
var logSettings = settingsService.GetSettings();
|
||||
logSettings.Level = LogLevel.Error.Ordinal;
|
||||
settingsService.SaveSettings(logSettings);
|
||||
|
||||
LoggingHelper.ReconfigureLogLevel(LogLevel.FromOrdinal(logSettings.Level));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
|
||||
|
||||
// Enable analytics;
|
||||
try
|
||||
{
|
||||
|
||||
var prSettings = new SettingsServiceV2<PlexRequestSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
|
||||
var settings = prSettings.GetSettings();
|
||||
settings.CollectAnalyticData = true;
|
||||
var updated = prSettings.SaveSettings(settings);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Migrates to version1910.
|
||||
/// </summary>
|
||||
public void MigrateToVersion1910()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the new machine Identifier
|
||||
var settings = new SettingsServiceV2<PlexSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
|
||||
var plex = settings.GetSettings();
|
||||
if (!string.IsNullOrEmpty(plex.PlexAuthToken))
|
||||
{
|
||||
var api = new PlexApi(new ApiRequest());
|
||||
var server = api.GetServer(plex.PlexAuthToken); // Get the server info
|
||||
plex.MachineIdentifier = server.Server.FirstOrDefault(x => x.AccessToken == plex.PlexAuthToken)?.MachineIdentifier;
|
||||
|
||||
settings.SaveSettings(plex); // Save the new settings
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ namespace PlexRequests.Services.Jobs
|
|||
var settings = CpSettings.GetSettings();
|
||||
if (settings.Enabled)
|
||||
{
|
||||
Job.SetRunning(true, JobNames.CpCacher);
|
||||
Log.Trace("Getting all movies from CouchPotato");
|
||||
try
|
||||
{
|
||||
|
@ -109,7 +110,6 @@ namespace PlexRequests.Services.Jobs
|
|||
|
||||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
Job.SetRunning(true, JobNames.CpCacher);
|
||||
Queued();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,6 @@ namespace PlexRequests.Services.Jobs
|
|||
Log.Debug("Validation of the plex settings failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
var libraries = CachedLibraries(plexSettings, true); //force setting the cache (10 min intervals via scheduler)
|
||||
|
||||
if (libraries == null || !libraries.Any())
|
||||
|
@ -156,9 +155,6 @@ namespace PlexRequests.Services.Jobs
|
|||
NotificationEngine.NotifyUsers(modifiedModel, plexSettings.PlexAuthToken, NotificationType.RequestAvailable);
|
||||
RequestService.BatchUpdate(modifiedModel);
|
||||
}
|
||||
|
||||
Job.Record(JobNames.PlexChecker);
|
||||
Job.SetRunning(false, JobNames.CpCacher);
|
||||
}
|
||||
|
||||
public List<PlexMovie> GetPlexMovies()
|
||||
|
@ -504,7 +500,7 @@ namespace PlexRequests.Services.Jobs
|
|||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
|
||||
Job.SetRunning(true, JobNames.CpCacher);
|
||||
Job.SetRunning(true, JobNames.PlexChecker);
|
||||
try
|
||||
{
|
||||
CheckAndUpdateAll();
|
||||
|
@ -513,6 +509,11 @@ namespace PlexRequests.Services.Jobs
|
|||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Job.Record(JobNames.PlexChecker);
|
||||
Job.SetRunning(false, JobNames.PlexChecker);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -145,7 +145,7 @@ namespace PlexRequests.Services.Jobs
|
|||
|
||||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
Job.SetRunning(true, JobNames.CpCacher);
|
||||
|
||||
try
|
||||
{
|
||||
var s = Plex.GetSettings();
|
||||
|
@ -163,6 +163,7 @@ namespace PlexRequests.Services.Jobs
|
|||
return;
|
||||
}
|
||||
}
|
||||
Job.SetRunning(true, JobNames.EpisodeCacher);
|
||||
CacheEpisodes(s);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -172,7 +173,7 @@ namespace PlexRequests.Services.Jobs
|
|||
finally
|
||||
{
|
||||
Job.Record(JobNames.EpisodeCacher);
|
||||
Job.SetRunning(false, JobNames.CpCacher);
|
||||
Job.SetRunning(false, JobNames.EpisodeCacher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,8 +78,6 @@ namespace PlexRequests.Services.Jobs
|
|||
|
||||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
|
||||
JobRecord.SetRunning(true, JobNames.CpCacher);
|
||||
try
|
||||
{
|
||||
var settings = NewsletterSettings.GetSettings();
|
||||
|
@ -87,7 +85,7 @@ namespace PlexRequests.Services.Jobs
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JobRecord.SetRunning(true, JobNames.RecentlyAddedEmail);
|
||||
Start(settings);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -97,7 +95,7 @@ namespace PlexRequests.Services.Jobs
|
|||
finally
|
||||
{
|
||||
JobRecord.Record(JobNames.RecentlyAddedEmail);
|
||||
JobRecord.SetRunning(false, JobNames.CpCacher);
|
||||
JobRecord.SetRunning(false, JobNames.RecentlyAddedEmail);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,7 +262,8 @@ namespace PlexRequests.Services.Jobs
|
|||
{
|
||||
foreach (var user in users.User)
|
||||
{
|
||||
message.Bcc.Add(new MailboxAddress(user.Username, user.Email));
|
||||
if (user.Email != null)
|
||||
message.Bcc.Add(new MailboxAddress(user.Username, user.Email));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,12 +58,14 @@ namespace PlexRequests.Services.Jobs
|
|||
|
||||
public void Queued()
|
||||
{
|
||||
Job.SetRunning(true, JobNames.CpCacher);
|
||||
Log.Trace("Getting the settings");
|
||||
|
||||
var settings = SrSettings.GetSettings();
|
||||
if (settings.Enabled)
|
||||
{
|
||||
|
||||
Job.SetRunning(true, JobNames.SrCacher);
|
||||
|
||||
Log.Trace("Getting all shows from SickRage");
|
||||
try
|
||||
{
|
||||
|
@ -80,7 +82,7 @@ namespace PlexRequests.Services.Jobs
|
|||
finally
|
||||
{
|
||||
Job.Record(JobNames.SrCacher);
|
||||
Job.SetRunning(false, JobNames.CpCacher);
|
||||
Job.SetRunning(false, JobNames.SrCacher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,10 +62,10 @@ namespace PlexRequests.Services.Jobs
|
|||
|
||||
public void Queued()
|
||||
{
|
||||
Job.SetRunning(true, JobNames.CpCacher);
|
||||
var settings = SonarrSettings.GetSettings();
|
||||
if (settings.Enabled)
|
||||
{
|
||||
Job.SetRunning(true, JobNames.SonarrCacher);
|
||||
try
|
||||
{
|
||||
var series = SonarrApi.GetSeries(settings.ApiKey, settings.FullUri);
|
||||
|
@ -81,7 +81,7 @@ namespace PlexRequests.Services.Jobs
|
|||
finally
|
||||
{
|
||||
Job.Record(JobNames.SonarrCacher);
|
||||
Job.SetRunning(false, JobNames.CpCacher);
|
||||
Job.SetRunning(false, JobNames.SonarrCacher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,3 +182,9 @@ button.list-group-item:focus {
|
|||
#sidebar-wrapper {
|
||||
background: #252424; }
|
||||
|
||||
#cacherRunning {
|
||||
background-color: #333333;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
padding: 3px 0; }
|
||||
|
||||
|
|
2
PlexRequests.UI/Content/Themes/plex.min.css
vendored
2
PlexRequests.UI/Content/Themes/plex.min.css
vendored
|
@ -1 +1 @@
|
|||
.form-control-custom{background-color:#333 !important;}.form-control-custom-disabled{background-color:#252424 !important;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background:#df691a;}.scroll-top-wrapper{background-color:#333;}.scroll-top-wrapper:hover{background-color:#df691a;}body{font-family:Open Sans Regular,Helvetica Neue,Helvetica,Arial,sans-serif;color:#eee;background-color:#1f1f1f;}.table-striped>tbody>tr:nth-of-type(odd){background-color:#333;}.table-hover>tbody>tr:hover{background-color:#282828;}fieldset{padding:15px;}legend{border-bottom:1px solid #333;}.form-control{color:#fefefe;background-color:#333;}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{margin-left:-0;}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:-15px;}.dropdown-menu{background-color:#282828;}.dropdown-menu .divider{background-color:#333;}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#333;}.input-group-addon{background-color:#333;}.nav>li>a:hover,.nav>li>a:focus{background-color:#df691a;}.nav-tabs>li>a:hover{border-color:#df691a #df691a transparent;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background-color:#df691a;border:1px solid #df691a;}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #df691a;}.navbar-default{background-color:#0a0a0a;}.navbar-default .navbar-brand{color:#df691a;}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#f0ad4e;background-color:#282828;}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{background-color:#282828;}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#df691a;color:#fff;}.pagination>li>a,.pagination>li>span{background-color:#282828;}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#333;}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#fefefe;background-color:#333;}.list-group-item{background-color:#282828;}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{background-color:#333;}.input-addon,.input-group-addon{color:#df691a;}.modal-header,.modal-footer{background-color:#282828;}.modal-content{position:relative;background-color:#282828;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:0;}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:300;color:#ebebeb;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#333;border-radius:10px;}.bootstrap-datetimepicker-widget.dropdown-menu{background-color:#333;}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after{border-bottom:6px solid #333 !important;}#sidebar-wrapper{background:#252424;}
|
||||
.form-control-custom{background-color:#333 !important;}.form-control-custom-disabled{background-color:#252424 !important;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background:#df691a;}.scroll-top-wrapper{background-color:#333;}.scroll-top-wrapper:hover{background-color:#df691a;}body{font-family:Open Sans Regular,Helvetica Neue,Helvetica,Arial,sans-serif;color:#eee;background-color:#1f1f1f;}.table-striped>tbody>tr:nth-of-type(odd){background-color:#333;}.table-hover>tbody>tr:hover{background-color:#282828;}fieldset{padding:15px;}legend{border-bottom:1px solid #333;}.form-control{color:#fefefe;background-color:#333;}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{margin-left:-0;}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:-15px;}.dropdown-menu{background-color:#282828;}.dropdown-menu .divider{background-color:#333;}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#333;}.input-group-addon{background-color:#333;}.nav>li>a:hover,.nav>li>a:focus{background-color:#df691a;}.nav-tabs>li>a:hover{border-color:#df691a #df691a transparent;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background-color:#df691a;border:1px solid #df691a;}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #df691a;}.navbar-default{background-color:#0a0a0a;}.navbar-default .navbar-brand{color:#df691a;}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#f0ad4e;background-color:#282828;}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{background-color:#282828;}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#df691a;color:#fff;}.pagination>li>a,.pagination>li>span{background-color:#282828;}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#333;}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#fefefe;background-color:#333;}.list-group-item{background-color:#282828;}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{background-color:#333;}.input-addon,.input-group-addon{color:#df691a;}.modal-header,.modal-footer{background-color:#282828;}.modal-content{position:relative;background-color:#282828;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:0;}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:300;color:#ebebeb;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#333;border-radius:10px;}.bootstrap-datetimepicker-widget.dropdown-menu{background-color:#333;}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after{border-bottom:6px solid #333 !important;}#sidebar-wrapper{background:#252424;}#cacherRunning{background-color:#333;text-align:center;font-size:15px;padding:3px 0;}
|
|
@ -228,3 +228,10 @@ button.list-group-item:focus {
|
|||
#sidebar-wrapper {
|
||||
background: $bg-colour-disabled;
|
||||
}
|
||||
|
||||
#cacherRunning {
|
||||
background-color: $bg-colour;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
padding: 3px 0;
|
||||
}
|
6
PlexRequests.UI/Content/base.css
vendored
6
PlexRequests.UI/Content/base.css
vendored
|
@ -257,6 +257,12 @@ label {
|
|||
font-size: 15px;
|
||||
padding: 3px 0; }
|
||||
|
||||
#cacherRunning {
|
||||
background-color: #4e5d6c;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
padding: 3px 0; }
|
||||
|
||||
.checkbox label {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
|
|
2
PlexRequests.UI/Content/base.min.css
vendored
2
PlexRequests.UI/Content/base.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -327,6 +327,13 @@ $border-radius: 10px;
|
|||
padding: 3px 0;
|
||||
}
|
||||
|
||||
#cacherRunning {
|
||||
background-color: $form-color;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
.checkbox label {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
// ************************************************************************/
|
||||
#endregion
|
||||
|
||||
using Nancy;
|
||||
using Nancy.Linker;
|
||||
using Nancy.Security;
|
||||
using Nancy.ViewEngines.Razor;
|
||||
using Ninject;
|
||||
|
@ -41,22 +43,37 @@ namespace PlexRequests.UI.Helpers
|
|||
get
|
||||
{
|
||||
var userRepo = ServiceLocator.Instance.Resolve<IUserRepository>();
|
||||
return _security ?? (_security = new SecurityExtensions(userRepo, null));
|
||||
var linker = ServiceLocator.Instance.Resolve<IResourceLinker>();
|
||||
return _security ?? (_security = new SecurityExtensions(userRepo, null, linker));
|
||||
}
|
||||
}
|
||||
|
||||
private static SecurityExtensions _security;
|
||||
|
||||
|
||||
public static bool HasAnyPermission(this HtmlHelpers helper, int permission)
|
||||
public static bool HasAnyPermission(this HtmlHelpers helper, int permission, bool authenticated = true)
|
||||
{
|
||||
return helper.CurrentUser.IsAuthenticated()
|
||||
&& Security.HasPermissions(helper.CurrentUser, (Permissions) permission);
|
||||
if (authenticated)
|
||||
{
|
||||
return helper.CurrentUser.IsAuthenticated()
|
||||
&& Security.HasPermissions(helper.CurrentUser, (Permissions) permission);
|
||||
}
|
||||
return Security.HasPermissions(helper.CurrentUser, (Permissions)permission);
|
||||
}
|
||||
|
||||
public static bool DoesNotHavePermission(this HtmlHelpers helper, int permission)
|
||||
{
|
||||
return Security.DoesNotHavePermissions(permission, helper.CurrentUser);
|
||||
}
|
||||
|
||||
public static bool IsAdmin(this HtmlHelpers helper, bool isAuthenticated = true)
|
||||
{
|
||||
return HasAnyPermission(helper, (int) Permissions.Administrator, isAuthenticated);
|
||||
}
|
||||
|
||||
public static bool IsLoggedIn(this HtmlHelpers helper, NancyContext context)
|
||||
{
|
||||
return Security.IsLoggedIn(context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,6 +30,8 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using Nancy;
|
||||
using Nancy.Extensions;
|
||||
using Nancy.Linker;
|
||||
using Nancy.Responses;
|
||||
using Nancy.Security;
|
||||
using Ninject;
|
||||
using PlexRequests.Helpers.Permissions;
|
||||
|
@ -40,14 +42,16 @@ namespace PlexRequests.UI.Helpers
|
|||
{
|
||||
public class SecurityExtensions
|
||||
{
|
||||
public SecurityExtensions(IUserRepository userRepository, NancyModule context)
|
||||
public SecurityExtensions(IUserRepository userRepository, NancyModule context, IResourceLinker linker)
|
||||
{
|
||||
UserRepository = userRepository;
|
||||
Module = context;
|
||||
Linker = linker;
|
||||
}
|
||||
|
||||
private IUserRepository UserRepository { get; }
|
||||
private NancyModule Module { get; }
|
||||
private IResourceLinker Linker { get; }
|
||||
|
||||
public bool IsLoggedIn(NancyContext context)
|
||||
{
|
||||
|
@ -117,7 +121,7 @@ namespace PlexRequests.UI.Helpers
|
|||
if (dbUser == null) return false;
|
||||
|
||||
var permissions = (Permissions)dbUser.Permissions;
|
||||
var result = permissions.HasFlag((Permissions)perm);
|
||||
var result = permissions.HasFlag(perm);
|
||||
return !result;
|
||||
}
|
||||
|
||||
|
@ -134,10 +138,11 @@ namespace PlexRequests.UI.Helpers
|
|||
return result;
|
||||
}
|
||||
|
||||
public void HasPermissionsResponse(Permissions perm)
|
||||
public Response HasPermissionsRedirect(Permissions perm, NancyContext context, string routeName, HttpStatusCode code)
|
||||
{
|
||||
Module.AddBeforeHookOrExecute(
|
||||
ForbiddenIfNot(ctx =>
|
||||
var url = Linker.BuildRelativeUri(context, routeName);
|
||||
|
||||
var response = ForbiddenIfNot(ctx =>
|
||||
{
|
||||
if (ctx.CurrentUser == null) return false;
|
||||
|
||||
|
@ -145,13 +150,24 @@ namespace PlexRequests.UI.Helpers
|
|||
|
||||
if (dbUser == null) return false;
|
||||
|
||||
var permissions = (Permissions)dbUser.Permissions;
|
||||
var permissions = (Permissions) dbUser.Permissions;
|
||||
var result = permissions.HasFlag(perm);
|
||||
return result;
|
||||
}), "Requires Claims");
|
||||
});
|
||||
|
||||
var r = response(context);
|
||||
return r.StatusCode == code
|
||||
? new RedirectResponse(url.ToString())
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
public Response AdminLoginRedirect(Permissions perm, NancyContext context)
|
||||
{
|
||||
// This will redirect us to the Login Page if we don't have the correct permission passed in (e.g. Admin with Http 403 status code).
|
||||
return HasPermissionsRedirect(perm, context, "LocalLogin", HttpStatusCode.Forbidden);
|
||||
}
|
||||
|
||||
// BELOW IS A COPY FROM THE SecurityHooks CLASS!
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -66,6 +66,7 @@ using PlexRequests.UI.Helpers;
|
|||
using PlexRequests.UI.Models;
|
||||
using Quartz;
|
||||
using Action = PlexRequests.Helpers.Analytics.Action;
|
||||
using HttpStatusCode = Nancy.HttpStatusCode;
|
||||
|
||||
namespace PlexRequests.UI.Modules
|
||||
{
|
||||
|
@ -154,7 +155,7 @@ namespace PlexRequests.UI.Modules
|
|||
NotifySettings = notifyService;
|
||||
RecentlyAdded = recentlyAdded;
|
||||
|
||||
Security.HasPermissionsResponse(Permissions.Administrator);
|
||||
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||
|
||||
Get["/"] = _ => Admin();
|
||||
|
||||
|
@ -826,13 +827,11 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(result
|
||||
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Newsletter!" }
|
||||
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Response CreateApiKey()
|
||||
{
|
||||
Security.HasPermissionsResponse(Permissions.Administrator);
|
||||
|
||||
Analytics.TrackEventAsync(Category.Admin, Action.Create, "Created API Key", Username, CookieHelper.GetAnalyticClientId(Cookies));
|
||||
var apiKey = Guid.NewGuid().ToString("N");
|
||||
var settings = PrService.GetSettings();
|
||||
|
@ -978,11 +977,11 @@ namespace PlexRequests.UI.Modules
|
|||
if (!isValid)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message =
|
||||
{
|
||||
Result = false,
|
||||
Message =
|
||||
$"CRON {settings.RecentlyAddedCron} is not valid. Please ensure you are using a valid CRON."
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
var result = await ScheduledJobSettings.SaveSettingsAsync(settings);
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace PlexRequests.UI.Modules.Admin
|
|||
Cache = cache;
|
||||
RequestQueue = requestQueue;
|
||||
|
||||
Security.HasPermissionsResponse(Permissions.Administrator);
|
||||
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||
|
||||
Get["Index", "/faultqueue"] = x => Index();
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace PlexRequests.UI.Modules.Admin
|
|||
Cache = cache;
|
||||
SystemSettings = ss;
|
||||
|
||||
Security.HasPermissionsResponse(Permissions.Administrator);
|
||||
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||
|
||||
Get["/status", true] = async (x, ct) => await Status();
|
||||
Post["/save", true] = async (x, ct) => await Save();
|
||||
|
|
|
@ -30,6 +30,7 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
|
||||
using Nancy;
|
||||
using Nancy.Linker;
|
||||
using Nancy.Security;
|
||||
using Ninject;
|
||||
using PlexRequests.Core;
|
||||
|
@ -151,14 +152,14 @@ namespace PlexRequests.UI.Modules
|
|||
get
|
||||
{
|
||||
var userRepo = ServiceLocator.Instance.Resolve<IUserRepository>();
|
||||
return _security ?? (_security = new SecurityExtensions(userRepo, this));
|
||||
var linker = ServiceLocator.Instance.Resolve<IResourceLinker>();
|
||||
return _security ?? (_security = new SecurityExtensions(userRepo, this, linker));
|
||||
}
|
||||
}
|
||||
|
||||
private SecurityExtensions _security;
|
||||
|
||||
|
||||
|
||||
protected bool LoggedIn => Context?.CurrentUser != null;
|
||||
|
||||
protected string Culture { get; set; }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2016 Jamie Rees
|
||||
// File: UpdateCheckerModule.cs
|
||||
// File: LayoutModule.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -25,6 +25,7 @@
|
|||
// ************************************************************************/
|
||||
#endregion
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Nancy;
|
||||
|
@ -35,24 +36,29 @@ using PlexRequests.Core;
|
|||
using PlexRequests.Core.SettingModels;
|
||||
using PlexRequests.Core.StatusChecker;
|
||||
using PlexRequests.Helpers;
|
||||
using PlexRequests.Services.Interfaces;
|
||||
using PlexRequests.Services.Jobs;
|
||||
using PlexRequests.UI.Models;
|
||||
|
||||
namespace PlexRequests.UI.Modules
|
||||
{
|
||||
public class UpdateCheckerModule : BaseAuthModule
|
||||
public class LayoutModule : BaseAuthModule
|
||||
{
|
||||
public UpdateCheckerModule(ICacheProvider provider, ISettingsService<PlexRequestSettings> pr, ISettingsService<SystemSettings> settings) : base("updatechecker", pr)
|
||||
public LayoutModule(ICacheProvider provider, ISettingsService<PlexRequestSettings> pr, ISettingsService<SystemSettings> settings, IJobRecord rec) : base("layout", pr)
|
||||
{
|
||||
Cache = provider;
|
||||
SystemSettings = settings;
|
||||
Job = rec;
|
||||
|
||||
Get["/", true] = async (x,ct) => await CheckLatestVersion();
|
||||
Get["/cacher", true] = async (x,ct) => await CacherRunning();
|
||||
}
|
||||
|
||||
private ICacheProvider Cache { get; }
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
private ISettingsService<SystemSettings> SystemSettings { get; }
|
||||
private IJobRecord Job { get; }
|
||||
|
||||
private async Task<Response> CheckLatestVersion()
|
||||
{
|
||||
|
@ -79,5 +85,35 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(new JsonUpdateAvailableModel { UpdateAvailable = false });
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Response> CacherRunning()
|
||||
{
|
||||
try
|
||||
{
|
||||
var jobs = await Job.GetJobsAsync();
|
||||
|
||||
// Check to see if any are running
|
||||
var runningJobs = jobs.Where(x => x.Running);
|
||||
|
||||
// We only want the cachers
|
||||
var cacherJobs = runningJobs.Where(x =>
|
||||
x.Name.Equals(JobNames.CpCacher)
|
||||
|| x.Name.Equals(JobNames.EpisodeCacher)
|
||||
|| x.Name.Equals(JobNames.PlexChecker)
|
||||
|| x.Name.Equals(JobNames.SonarrCacher)
|
||||
|| x.Name.Equals(JobNames.SrCacher));
|
||||
|
||||
|
||||
return Response.AsJson(cacherJobs.Any()
|
||||
? new { CurrentlyRunning = true, IsAdmin}
|
||||
: new { CurrentlyRunning = false, IsAdmin });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warn("Exception Thrown when attempting to check the status");
|
||||
Log.Warn(e);
|
||||
return Response.AsJson(new { CurrentlyRunning = false, IsAdmin });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -52,7 +52,7 @@ namespace PlexRequests.UI.Modules
|
|||
: base(pr)
|
||||
{
|
||||
UserMapper = m;
|
||||
Get["/login"] = _ =>
|
||||
Get["LocalLogin","/login"] = _ =>
|
||||
{
|
||||
if (LoggedIn)
|
||||
{
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace PlexRequests.UI.Modules
|
|||
{
|
||||
Session["TempMessage"] = Resources.UI.UserLogin_IncorrectUserPass;
|
||||
var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
|
||||
return Response.AsRedirect(uri.ToString()); // TODO Check this
|
||||
return Response.AsRedirect(uri.ToString());
|
||||
}
|
||||
|
||||
var authenticated = false;
|
||||
|
@ -112,7 +112,7 @@ namespace PlexRequests.UI.Modules
|
|||
Log.Debug("User is in denied list, not allowing them to authenticate");
|
||||
Session["TempMessage"] = Resources.UI.UserLogin_IncorrectUserPass;
|
||||
var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
|
||||
return Response.AsRedirect(uri.ToString()); // TODO Check this
|
||||
return Response.AsRedirect(uri.ToString());
|
||||
}
|
||||
|
||||
var password = string.Empty;
|
||||
|
@ -178,7 +178,7 @@ namespace PlexRequests.UI.Modules
|
|||
{
|
||||
var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
|
||||
Session["TempMessage"] = Resources.UI.UserLogin_IncorrectUserPass;
|
||||
return Response.AsRedirect(uri.ToString()); // TODO Check this
|
||||
return Response.AsRedirect(uri.ToString());
|
||||
}
|
||||
|
||||
var landingSettings = await LandingPageSettings.GetSettingsAsync();
|
||||
|
@ -192,7 +192,7 @@ namespace PlexRequests.UI.Modules
|
|||
}
|
||||
}
|
||||
var retVal = Linker.BuildRelativeUri(Context, "SearchIndex");
|
||||
return Response.AsRedirect(retVal.ToString()); // TODO Check this
|
||||
return Response.AsRedirect(retVal.ToString());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -258,7 +258,7 @@
|
|||
<Compile Include="Modules\IssuesModule.cs" />
|
||||
<Compile Include="Modules\LandingPageModule.cs" />
|
||||
<Compile Include="Modules\RequestsBetaModule.cs" />
|
||||
<Compile Include="Modules\UpdateCheckerModule.cs" />
|
||||
<Compile Include="Modules\LayoutModule.cs" />
|
||||
<Compile Include="Modules\UserWizardModule.cs" />
|
||||
<Compile Include="NinjectModules\ApiModule.cs" />
|
||||
<Compile Include="NinjectModules\ConfigurationModule.cs" />
|
||||
|
@ -747,6 +747,7 @@
|
|||
<EmbeddedResource Include="Resources\UI.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>UI1.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\UI.sv.resx" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -459,4 +459,34 @@
|
|||
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
|
||||
<value>Der er ingen oplysninger om udgivelsesdatoen</value>
|
||||
</data>
|
||||
<data name="Search_ViewInPlex" xml:space="preserve">
|
||||
<value>Udsigt I Plex</value>
|
||||
</data>
|
||||
<data name="Custom_Donation_Default" xml:space="preserve">
|
||||
<value>Doner til Bibliotek vedligeholder</value>
|
||||
</data>
|
||||
<data name="Search_Available_on_plex" xml:space="preserve">
|
||||
<value>Tilgængelig på</value>
|
||||
</data>
|
||||
<data name="Search_Movie_Status" xml:space="preserve">
|
||||
<value>Movie status</value>
|
||||
</data>
|
||||
<data name="Search_Not_Requested_Yet" xml:space="preserve">
|
||||
<value>Ikke anmodet endnu</value>
|
||||
</data>
|
||||
<data name="Search_Pending_approval" xml:space="preserve">
|
||||
<value>Afventer godkendelse</value>
|
||||
</data>
|
||||
<data name="Search_Processing_Request" xml:space="preserve">
|
||||
<value>Behandler forespørgsel</value>
|
||||
</data>
|
||||
<data name="Search_Request_denied" xml:space="preserve">
|
||||
<value>Anmodning afvist!</value>
|
||||
</data>
|
||||
<data name="Search_TV_Show_Status" xml:space="preserve">
|
||||
<value>Tv-show status!</value>
|
||||
</data>
|
||||
<data name="Layout_CacherRunning" xml:space="preserve">
|
||||
<value>En baggrund proces kører i øjeblikket, så der kan være nogle uventede problemer. Dette bør ikke tage for lang tid.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -459,4 +459,34 @@
|
|||
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
|
||||
<value>Es gibt noch keine Informationen für diesen Release-Termin</value>
|
||||
</data>
|
||||
<data name="Search_ViewInPlex" xml:space="preserve">
|
||||
<value>Ansicht In Plex</value>
|
||||
</data>
|
||||
<data name="Custom_Donation_Default" xml:space="preserve">
|
||||
<value>Spenden zur Bibliothek Maintainer</value>
|
||||
</data>
|
||||
<data name="Search_Available_on_plex" xml:space="preserve">
|
||||
<value>Verfügbar auf Plex</value>
|
||||
</data>
|
||||
<data name="Search_Movie_Status" xml:space="preserve">
|
||||
<value>Film-Status!</value>
|
||||
</data>
|
||||
<data name="Search_Not_Requested_Yet" xml:space="preserve">
|
||||
<value>Noch nicht heraus!</value>
|
||||
</data>
|
||||
<data name="Search_Pending_approval" xml:space="preserve">
|
||||
<value>Genehmigung ausstehend</value>
|
||||
</data>
|
||||
<data name="Search_Processing_Request" xml:space="preserve">
|
||||
<value>Die Verarbeitung Anfrage</value>
|
||||
</data>
|
||||
<data name="Search_Request_denied" xml:space="preserve">
|
||||
<value>Anfrage verweigert.</value>
|
||||
</data>
|
||||
<data name="Search_TV_Show_Status" xml:space="preserve">
|
||||
<value>TV-Show-Status</value>
|
||||
</data>
|
||||
<data name="Layout_CacherRunning" xml:space="preserve">
|
||||
<value>Ein Hintergrundprozess gerade läuft, so könnte es einige unerwartete Verhalten sein. Dies sollte nicht zu lange dauern.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -459,4 +459,31 @@
|
|||
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
|
||||
<value>No hay información disponible para la fecha de lanzamiento</value>
|
||||
</data>
|
||||
<data name="Custom_Donation_Default" xml:space="preserve">
|
||||
<value>Donar a la biblioteca Mantenedor</value>
|
||||
</data>
|
||||
<data name="Search_Available_on_plex" xml:space="preserve">
|
||||
<value>Disponible en Plex</value>
|
||||
</data>
|
||||
<data name="Search_Movie_Status" xml:space="preserve">
|
||||
<value>estado de película</value>
|
||||
</data>
|
||||
<data name="Search_Not_Requested_Yet" xml:space="preserve">
|
||||
<value>No solicitado</value>
|
||||
</data>
|
||||
<data name="Search_Pending_approval" xml:space="preserve">
|
||||
<value>PENDIENTES DE APROBACIÓN</value>
|
||||
</data>
|
||||
<data name="Search_Processing_Request" xml:space="preserve">
|
||||
<value>solicitud de procesamiento</value>
|
||||
</data>
|
||||
<data name="Search_Request_denied" xml:space="preserve">
|
||||
<value>Solicitud denegada</value>
|
||||
</data>
|
||||
<data name="Search_TV_Show_Status" xml:space="preserve">
|
||||
<value>estado de programa de televisión</value>
|
||||
</data>
|
||||
<data name="Layout_CacherRunning" xml:space="preserve">
|
||||
<value>Un proceso en segundo plano se está ejecutando actualmente, por lo que podría ser un comportamiento inesperado. Esto no debería tomar mucho tiempo.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -459,4 +459,34 @@
|
|||
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
|
||||
<value>Il n'y a pas d'information disponible pour la date de sortie</value>
|
||||
</data>
|
||||
<data name="Search_ViewInPlex" xml:space="preserve">
|
||||
<value>Voir Dans Plex</value>
|
||||
</data>
|
||||
<data name="Custom_Donation_Default" xml:space="preserve">
|
||||
<value>Faire un don à la bibliothèque mainteneur!</value>
|
||||
</data>
|
||||
<data name="Search_Available_on_plex" xml:space="preserve">
|
||||
<value>Disponible sur Plex</value>
|
||||
</data>
|
||||
<data name="Search_Movie_Status" xml:space="preserve">
|
||||
<value>le statut de film</value>
|
||||
</data>
|
||||
<data name="Search_Not_Requested_Yet" xml:space="preserve">
|
||||
<value>Pas encore demandé</value>
|
||||
</data>
|
||||
<data name="Search_Pending_approval" xml:space="preserve">
|
||||
<value>En attente de validation</value>
|
||||
</data>
|
||||
<data name="Search_Processing_Request" xml:space="preserve">
|
||||
<value>Traitement de la demande</value>
|
||||
</data>
|
||||
<data name="Search_Request_denied" xml:space="preserve">
|
||||
<value>Requête refusée</value>
|
||||
</data>
|
||||
<data name="Search_TV_Show_Status" xml:space="preserve">
|
||||
<value>TV show status</value>
|
||||
</data>
|
||||
<data name="Layout_CacherRunning" xml:space="preserve">
|
||||
<value>Un processus d'arrière-plan est en cours d'exécution, de sorte qu'il pourrait y avoir des comportements inattendus. Cela ne devrait pas prendre trop de temps.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -459,4 +459,34 @@
|
|||
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
|
||||
<value>Non ci sono informazioni disponibili per la data di uscita</value>
|
||||
</data>
|
||||
<data name="Search_ViewInPlex" xml:space="preserve">
|
||||
<value>Guarda In Plex</value>
|
||||
</data>
|
||||
<data name="Custom_Donation_Default" xml:space="preserve">
|
||||
<value>Donare alla libreria Maintainer</value>
|
||||
</data>
|
||||
<data name="Search_Available_on_plex" xml:space="preserve">
|
||||
<value>Disponibile su Plex</value>
|
||||
</data>
|
||||
<data name="Search_Movie_Status" xml:space="preserve">
|
||||
<value>lo stato di film</value>
|
||||
</data>
|
||||
<data name="Search_Not_Requested_Yet" xml:space="preserve">
|
||||
<value>Non ancora richiesto</value>
|
||||
</data>
|
||||
<data name="Search_Pending_approval" xml:space="preserve">
|
||||
<value>Approvazione in sospeso</value>
|
||||
</data>
|
||||
<data name="Search_Processing_Request" xml:space="preserve">
|
||||
<value>Elaborazione richiesta</value>
|
||||
</data>
|
||||
<data name="Search_Request_denied" xml:space="preserve">
|
||||
<value>Richiesta negata</value>
|
||||
</data>
|
||||
<data name="Search_TV_Show_Status" xml:space="preserve">
|
||||
<value>Show televisivo di stato</value>
|
||||
</data>
|
||||
<data name="Layout_CacherRunning" xml:space="preserve">
|
||||
<value>Un processo in background è in esecuzione, quindi ci potrebbero essere alcuni comportamenti imprevisti. Questo non dovrebbe richiedere troppo tempo.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -459,4 +459,34 @@
|
|||
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
|
||||
<value>Er is geen informatie beschikbaar voor de release datum</value>
|
||||
</data>
|
||||
<data name="Search_ViewInPlex" xml:space="preserve">
|
||||
<value>Bekijk In Plex</value>
|
||||
</data>
|
||||
<data name="Custom_Donation_Default" xml:space="preserve">
|
||||
<value>Doneer aan Library Maintainer</value>
|
||||
</data>
|
||||
<data name="Search_Available_on_plex" xml:space="preserve">
|
||||
<value>Beschikbaar vanaf</value>
|
||||
</data>
|
||||
<data name="Search_Movie_Status" xml:space="preserve">
|
||||
<value>Movie-status!</value>
|
||||
</data>
|
||||
<data name="Search_Not_Requested_Yet" xml:space="preserve">
|
||||
<value>Nog niet gevraagd</value>
|
||||
</data>
|
||||
<data name="Search_Pending_approval" xml:space="preserve">
|
||||
<value>Wacht op goedkeuring</value>
|
||||
</data>
|
||||
<data name="Search_Processing_Request" xml:space="preserve">
|
||||
<value>Verwerking verzoek...</value>
|
||||
</data>
|
||||
<data name="Search_Request_denied" xml:space="preserve">
|
||||
<value>Aanvraag afgewezen</value>
|
||||
</data>
|
||||
<data name="Search_TV_Show_Status" xml:space="preserve">
|
||||
<value>TV-show-status</value>
|
||||
</data>
|
||||
<data name="Layout_CacherRunning" xml:space="preserve">
|
||||
<value>Een achtergrond taak is momenteel actief, dus er misschien een onverwachte gedrag. Dit moet niet te lang duren.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -459,4 +459,31 @@
|
|||
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
|
||||
<value>Não há informações disponíveis para a data de lançamento</value>
|
||||
</data>
|
||||
<data name="Search_ViewInPlex" xml:space="preserve">
|
||||
<value>Ver Em Plex</value>
|
||||
</data>
|
||||
<data name="Custom_Donation_Default" xml:space="preserve">
|
||||
<value>Doações para Biblioteca Mantenedor</value>
|
||||
</data>
|
||||
<data name="Search_Available_on_plex" xml:space="preserve">
|
||||
<value>Disponível em Plex</value>
|
||||
</data>
|
||||
<data name="Search_Movie_Status" xml:space="preserve">
|
||||
<value>status de filme</value>
|
||||
</data>
|
||||
<data name="Search_Not_Requested_Yet" xml:space="preserve">
|
||||
<value>Não solicitada ainda</value>
|
||||
</data>
|
||||
<data name="Search_Pending_approval" xml:space="preserve">
|
||||
<value>B – P/ Aprovação</value>
|
||||
</data>
|
||||
<data name="Search_Processing_Request" xml:space="preserve">
|
||||
<value>Processando solicitação...</value>
|
||||
</data>
|
||||
<data name="Search_Request_denied" xml:space="preserve">
|
||||
<value>Solicitação negada.</value>
|
||||
</data>
|
||||
<data name="Search_TV_Show_Status" xml:space="preserve">
|
||||
<value>Programa de TV status</value>
|
||||
</data>
|
||||
</root>
|
|
@ -467,4 +467,7 @@
|
|||
<data name="Search_TV_Show_Status" xml:space="preserve">
|
||||
<value>TV show status</value>
|
||||
</data>
|
||||
<data name="Layout_CacherRunning" xml:space="preserve">
|
||||
<value>A background process is currently running, so there might be some unexpected behavior. This shouldn't take too long.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -459,4 +459,34 @@
|
|||
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
|
||||
<value>Det finns ingen information tillgänglig för release datum</value>
|
||||
</data>
|
||||
<data name="Search_ViewInPlex" xml:space="preserve">
|
||||
<value>Vy I Plex</value>
|
||||
</data>
|
||||
<data name="Custom_Donation_Default" xml:space="preserve">
|
||||
<value>Donera till bibliotek Ansvarig</value>
|
||||
</data>
|
||||
<data name="Search_Available_on_plex" xml:space="preserve">
|
||||
<value>Tillgänglig den</value>
|
||||
</data>
|
||||
<data name="Search_Movie_Status" xml:space="preserve">
|
||||
<value>Film status</value>
|
||||
</data>
|
||||
<data name="Search_Not_Requested_Yet" xml:space="preserve">
|
||||
<value>Inte Begärd ännu</value>
|
||||
</data>
|
||||
<data name="Search_Pending_approval" xml:space="preserve">
|
||||
<value>Väntar på godkännande</value>
|
||||
</data>
|
||||
<data name="Search_Processing_Request" xml:space="preserve">
|
||||
<value>Bearbetning förfrågan</value>
|
||||
</data>
|
||||
<data name="Search_Request_denied" xml:space="preserve">
|
||||
<value>Förfrågan nekad</value>
|
||||
</data>
|
||||
<data name="Search_TV_Show_Status" xml:space="preserve">
|
||||
<value>Visa status</value>
|
||||
</data>
|
||||
<data name="Layout_CacherRunning" xml:space="preserve">
|
||||
<value>En bakgrundsprocess är igång, så det kan finnas några oväntade beteende. Detta bör inte ta alltför lång tid.</value>
|
||||
</data>
|
||||
</root>
|
9
PlexRequests.UI/Resources/UI1.Designer.cs
generated
9
PlexRequests.UI/Resources/UI1.Designer.cs
generated
|
@ -222,6 +222,15 @@ namespace PlexRequests.UI.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A background process is currently running, so there might be some unexpected behavior. This shouldn't take too long..
|
||||
/// </summary>
|
||||
public static string Layout_CacherRunning {
|
||||
get {
|
||||
return ResourceManager.GetString("Layout_CacherRunning", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Change Password.
|
||||
/// </summary>
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace PlexRequests.UI.Validators
|
|||
RuleFor(x => x.BaseUrl).NotEqual("login", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'login' as this is reserved by the application.");
|
||||
RuleFor(x => x.BaseUrl).NotEqual("test", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'test' as this is reserved by the application.");
|
||||
RuleFor(x => x.BaseUrl).NotEqual("approval", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'approval' as this is reserved by the application.");
|
||||
RuleFor(x => x.BaseUrl).NotEqual("updatechecker", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'updatechecker' as this is reserved by the application.");
|
||||
RuleFor(x => x.BaseUrl).NotEqual("layout", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'layout' as this is reserved by the application.");
|
||||
RuleFor(x => x.BaseUrl).NotEqual("usermanagement", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'usermanagement' as this is reserved by the application.");
|
||||
RuleFor(x => x.BaseUrl).NotEqual("api", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'api' as this is reserved by the application.");
|
||||
RuleFor(x => x.BaseUrl).NotEqual("landing", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'landing' as this is reserved by the application.");
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
$(function () {
|
||||
|
||||
// Check for update
|
||||
var url = createBaseUrl(urlBase, '/updatechecker');
|
||||
var url = createBaseUrl(urlBase, '/layout');
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
|
@ -20,7 +20,7 @@
|
|||
var status = createBaseUrl(urlBase, '/admin/status');
|
||||
$('#updateAvailable').html("<i class='fa fa-cloud-download' aria-hidden='true'></i> @UI.Layout_UpdateAvailablePart1 <a style='color: white' href='" + status + "'>@UI.Layout_UpdateAvailablePart2</a>");
|
||||
$('#updateAvailable').removeAttr("hidden");
|
||||
$('body').addClass('update-available');
|
||||
//$('body').addClass('update-available');
|
||||
}
|
||||
},
|
||||
error: function (e) {
|
||||
|
@ -29,6 +29,7 @@
|
|||
});
|
||||
// End Check for update
|
||||
|
||||
checkCacheInProgress();
|
||||
|
||||
// Scroller
|
||||
$(document).on('scroll', function () {
|
||||
|
@ -43,9 +44,6 @@
|
|||
$('.scroll-top-wrapper').on('click', scrollToTop);
|
||||
// End Scroller
|
||||
|
||||
|
||||
|
||||
|
||||
// Get Issue count
|
||||
var issueUrl = createBaseUrl(urlBase, '/issues/issuecount');
|
||||
$.ajax({
|
||||
|
@ -66,6 +64,8 @@
|
|||
// End issue count
|
||||
|
||||
|
||||
|
||||
|
||||
$('#donate').click(function () {
|
||||
ga('send', 'event', 'Navbar', 'Donate', 'Donate Clicked');
|
||||
});
|
||||
|
@ -80,4 +80,23 @@
|
|||
offsetTop = offset.top;
|
||||
$('html, body').animate({ scrollTop: offsetTop }, 500, 'linear');
|
||||
}
|
||||
|
||||
function checkCacheInProgress() {
|
||||
|
||||
var url = createBaseUrl(urlBase, '/layout/cacher');
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
if (response.currentlyRunning) {
|
||||
$('#cacherRunning').html("@UI.Layout_CacherRunning");
|
||||
$('#cacherRunning').removeAttr("hidden");
|
||||
}
|
||||
},
|
||||
error: function (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -35,21 +35,21 @@
|
|||
@Html.GetNavbarUrl(Context, "/search", UI.Layout_Search, "search")
|
||||
@Html.GetNavbarUrl(Context, "/requests", UI.Layout_Requests, "plus-circle")
|
||||
@Html.GetNavbarUrl(Context, "/issues", UI.Layout_Issues, "exclamation", "<span id=\"issueCount\"></span>")
|
||||
@if (Context.CurrentUser.IsAuthenticated()) // TODO replace with IsAdmin
|
||||
@*@if (Context.CurrentUser.IsAuthenticated()) // TODO replace with IsAdmin*@
|
||||
@if (Html.IsAdmin())
|
||||
{
|
||||
<li><a id="donate" href="https://www.paypal.me/PlexRequestsNet" target="_blank"><i class="fa fa-heart" style="color: red"></i> @UI.Layout_Donate</a></li>
|
||||
}
|
||||
<li id="customDonate" style="display: none"><a id="customDonateHref" href="https://www.paypal.me/PlexRequestsNet" target="_blank"><i class="fa fa-heart" style="color: yellow;"></i> <span id="donationText">@UI.Custom_Donation_Default</span></a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
||||
|
||||
@if (!Context.CurrentUser.IsAuthenticated() && Context.Request.Session[SessionKeys.UsernameKey] == null) // TODO replace with IsAdmin
|
||||
@*@if (!Context.CurrentUser.IsAuthenticated() && Context.Request.Session[SessionKeys.UsernameKey] == null) // TODO replace with IsAdmin*@
|
||||
@if (!Html.IsLoggedIn(Context))
|
||||
{
|
||||
|
||||
<li><a href="@url/login?redirect=@Context.Request.Path"><i class="fa fa-user"></i> @UI.Layout_Admin</a></li>
|
||||
}
|
||||
@if (Context.CurrentUser.IsAuthenticated()) // TODO replace with IsAdmin
|
||||
@*@if (Context.CurrentUser.IsAuthenticated()) // TODO replace with IsAdmin*@
|
||||
@if (Html.IsAdmin())
|
||||
{
|
||||
<li><a>@UI.Layout_Welcome @Context.Request.Session[SessionKeys.UsernameKey]</a></li>
|
||||
<li class="dropdown">
|
||||
|
@ -63,7 +63,8 @@
|
|||
</ul>
|
||||
</li>
|
||||
}
|
||||
@if (Context.Request.Session[SessionKeys.UsernameKey] != null && !Context.CurrentUser.IsAuthenticated())
|
||||
@*@if (Context.Request.Session[SessionKeys.UsernameKey] != null && !Context.CurrentUser.IsAuthenticated())*@
|
||||
else if (Html.IsLoggedIn(Context)) // Logged in but not admin
|
||||
{
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-user"></i> @UI.Layout_Welcome @Context.Request.Session[SessionKeys.UsernameKey] <span class="caret"></span></a>
|
||||
|
@ -77,19 +78,19 @@
|
|||
}
|
||||
<li class="dropdown">
|
||||
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-language" aria-hidden="true"><span class="caret"></span></i></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="@url/culture?l=en&u=@Context.Request.Path">@UI.Layout_English</a></li>
|
||||
<li><a href="@url/culture?l=fr&u=@Context.Request.Path">@UI.Layout_French</a></li>
|
||||
<li><a href="@url/culture?l=nl&u=@Context.Request.Path">@UI.Layout_Dutch</a></li>
|
||||
<li><a href="@url/culture?l=es&u=@Context.Request.Path">@UI.Layout_Spanish</a></li>
|
||||
<li><a href="@url/culture?l=de&u=@Context.Request.Path">@UI.Layout_German</a></li>
|
||||
<li><a href="@url/culture?l=da&u=@Context.Request.Path">@UI.Layout_Danish</a></li>
|
||||
<li><a href="@url/culture?l=pt&u=@Context.Request.Path">@UI.Layout_Portuguese</a></li>
|
||||
<li><a href="@url/culture?l=sv&u=@Context.Request.Path">@UI.Layout_Swedish</a></li>
|
||||
<li><a href="@url/culture?l=it&u=@Context.Request.Path">@UI.Layout_Italian</a></li>
|
||||
</ul>
|
||||
<li/>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-language" aria-hidden="true"><span class="caret"></span></i></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="@url/culture?l=en&u=@Context.Request.Path">@UI.Layout_English</a></li>
|
||||
<li><a href="@url/culture?l=fr&u=@Context.Request.Path">@UI.Layout_French</a></li>
|
||||
<li><a href="@url/culture?l=nl&u=@Context.Request.Path">@UI.Layout_Dutch</a></li>
|
||||
<li><a href="@url/culture?l=es&u=@Context.Request.Path">@UI.Layout_Spanish</a></li>
|
||||
<li><a href="@url/culture?l=de&u=@Context.Request.Path">@UI.Layout_German</a></li>
|
||||
<li><a href="@url/culture?l=da&u=@Context.Request.Path">@UI.Layout_Danish</a></li>
|
||||
<li><a href="@url/culture?l=pt&u=@Context.Request.Path">@UI.Layout_Portuguese</a></li>
|
||||
<li><a href="@url/culture?l=sv&u=@Context.Request.Path">@UI.Layout_Swedish</a></li>
|
||||
<li><a href="@url/culture?l=it&u=@Context.Request.Path">@UI.Layout_Italian</a></li>
|
||||
</ul>
|
||||
<li />
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -104,16 +105,17 @@
|
|||
var donateLink = $("#customDonateHref");
|
||||
var donationText = $("#donationText");
|
||||
donateLink.attr("href", result.url);
|
||||
if(result.message) {
|
||||
if (result.message) {
|
||||
donationText.text(result.message);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
error: function (xhr, status, error) {
|
||||
console.log("error " + error);
|
||||
$("#customDonate").hide();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<div id="updateAvailable" hidden="hidden"></div>
|
||||
<div id="cacherRunning" hidden="hidden"></div>
|
||||
</nav>
|
|
@ -16,8 +16,6 @@
|
|||
<i class="fa fa-2x fa-arrow-circle-up"></i>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@*@MiniProfiler.RenderIncludes()*@
|
||||
</body>
|
||||
|
||||
@Html.GetInformationalVersion()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue