mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-17 17:14:18 +02:00
Translate fields on the backend
(cherry picked from commit 48b12f5b00429a7cd218d23f0544641b0da62a06)
This commit is contained in:
@@ -41,6 +41,23 @@ namespace NzbDrone.Core.Annotations
|
|||||||
public string Hint { get; set; }
|
public string Hint { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
|
||||||
|
public class FieldTokenAttribute : Attribute
|
||||||
|
{
|
||||||
|
public FieldTokenAttribute(TokenField field, string label = "", string token = "", object value = null)
|
||||||
|
{
|
||||||
|
Label = label;
|
||||||
|
Field = field;
|
||||||
|
Token = token;
|
||||||
|
Value = value?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Label { get; set; }
|
||||||
|
public TokenField Field { get; set; }
|
||||||
|
public string Token { get; set; }
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class FieldSelectOption
|
public class FieldSelectOption
|
||||||
{
|
{
|
||||||
public int Value { get; set; }
|
public int Value { get; set; }
|
||||||
@@ -82,4 +99,11 @@ namespace NzbDrone.Core.Annotations
|
|||||||
ApiKey,
|
ApiKey,
|
||||||
UserName
|
UserName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum TokenField
|
||||||
|
{
|
||||||
|
Label,
|
||||||
|
HelpText,
|
||||||
|
HelpTextWarning
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ using NzbDrone.Common.Instrumentation;
|
|||||||
using NzbDrone.Common.Instrumentation.Extensions;
|
using NzbDrone.Common.Instrumentation.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Datastore.Extensions;
|
using NzbDrone.Core.Datastore.Extensions;
|
||||||
|
using Prowlarr.Http.ClientSchema;
|
||||||
using PostgresOptions = NzbDrone.Core.Datastore.PostgresOptions;
|
using PostgresOptions = NzbDrone.Core.Datastore.PostgresOptions;
|
||||||
|
|
||||||
namespace NzbDrone.Host
|
namespace NzbDrone.Host
|
||||||
@@ -147,6 +148,8 @@ namespace NzbDrone.Host
|
|||||||
.AddNzbDroneLogger()
|
.AddNzbDroneLogger()
|
||||||
.AddDatabase()
|
.AddDatabase()
|
||||||
.AddStartupContext(context);
|
.AddStartupContext(context);
|
||||||
|
|
||||||
|
SchemaBuilder.Initialize(c);
|
||||||
})
|
})
|
||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using Prowlarr.Api.V1.Indexers;
|
using System.Collections.Generic;
|
||||||
|
using Prowlarr.Api.V1.Indexers;
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
|
|
||||||
namespace NzbDrone.Integration.Test.Client
|
namespace NzbDrone.Integration.Test.Client
|
||||||
@@ -9,5 +10,11 @@ namespace NzbDrone.Integration.Test.Client
|
|||||||
: base(restClient, apiKey)
|
: base(restClient, apiKey)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<IndexerResource> Schema()
|
||||||
|
{
|
||||||
|
var request = BuildRequest("/schema");
|
||||||
|
return Get<List<IndexerResource>>(request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
using NzbDrone.Core.Indexers.Definitions.FileList;
|
using NzbDrone.Core.Indexers.Newznab;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
using NzbDrone.Test.Common.Datastore;
|
using NzbDrone.Test.Common.Datastore;
|
||||||
using Prowlarr.Http.ClientSchema;
|
|
||||||
|
|
||||||
namespace NzbDrone.Integration.Test
|
namespace NzbDrone.Integration.Test
|
||||||
{
|
{
|
||||||
@@ -49,16 +50,19 @@ namespace NzbDrone.Integration.Test
|
|||||||
{
|
{
|
||||||
WaitForCompletion(() => Tasks.All().SelectList(x => x.TaskName).Contains("CheckHealth"), 20000);
|
WaitForCompletion(() => Tasks.All().SelectList(x => x.TaskName).Contains("CheckHealth"), 20000);
|
||||||
|
|
||||||
Indexers.Post(new Prowlarr.Api.V1.Indexers.IndexerResource
|
var indexer = Indexers.Schema().FirstOrDefault(i => i.Implementation == nameof(Newznab));
|
||||||
|
|
||||||
|
if (indexer == null)
|
||||||
{
|
{
|
||||||
Enable = false,
|
throw new NullReferenceException("Expected valid indexer schema, found null");
|
||||||
ConfigContract = nameof(FileListSettings),
|
}
|
||||||
Implementation = nameof(FileList),
|
|
||||||
Name = "NewznabTest",
|
indexer.Enable = false;
|
||||||
Protocol = Core.Indexers.DownloadProtocol.Usenet,
|
indexer.ConfigContract = nameof(NewznabSettings);
|
||||||
AppProfileId = 1,
|
indexer.Implementation = nameof(Newznab);
|
||||||
Fields = SchemaBuilder.ToSchema(new FileListSettings())
|
indexer.Name = "NewznabTest";
|
||||||
});
|
indexer.Protocol = Core.Indexers.DownloadProtocol.Usenet;
|
||||||
|
indexer.AppProfileId = 1;
|
||||||
|
|
||||||
// Change Console Log Level to Debug so we get more details.
|
// Change Console Log Level to Debug so we get more details.
|
||||||
var config = HostConfig.Get(1);
|
var config = HostConfig.Get(1);
|
||||||
|
@@ -23,6 +23,8 @@ namespace NzbDrone.Test.Common.AutoMoq
|
|||||||
SetupAutoMoqer(CreateTestContainer(new Container()));
|
SetupAutoMoqer(CreateTestContainer(new Container()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IContainer Container => _container;
|
||||||
|
|
||||||
public virtual T Resolve<T>()
|
public virtual T Resolve<T>()
|
||||||
{
|
{
|
||||||
var result = _container.Resolve<T>();
|
var result = _container.Resolve<T>();
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
using Prowlarr.Http.ClientSchema;
|
using Prowlarr.Http.ClientSchema;
|
||||||
|
|
||||||
@@ -9,6 +12,16 @@ namespace NzbDrone.Api.Test.ClientSchemaTests
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class SchemaBuilderFixture : TestBase
|
public class SchemaBuilderFixture : TestBase
|
||||||
{
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<ILocalizationService>()
|
||||||
|
.Setup(s => s.GetLocalizedString(It.IsAny<string>(), It.IsAny<Dictionary<string, object>>()))
|
||||||
|
.Returns<string, Dictionary<string, object>>((s, d) => s);
|
||||||
|
|
||||||
|
SchemaBuilder.Initialize(Mocker.Container);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_field_for_every_property()
|
public void should_return_field_for_every_property()
|
||||||
{
|
{
|
||||||
|
@@ -3,17 +3,25 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using DryIoc;
|
||||||
using NzbDrone.Common.EnsureThat;
|
using NzbDrone.Common.EnsureThat;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Reflection;
|
using NzbDrone.Common.Reflection;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
|
|
||||||
namespace Prowlarr.Http.ClientSchema
|
namespace Prowlarr.Http.ClientSchema
|
||||||
{
|
{
|
||||||
public static class SchemaBuilder
|
public static class SchemaBuilder
|
||||||
{
|
{
|
||||||
private static Dictionary<Type, FieldMapping[]> _mappings = new Dictionary<Type, FieldMapping[]>();
|
private static Dictionary<Type, FieldMapping[]> _mappings = new Dictionary<Type, FieldMapping[]>();
|
||||||
|
private static ILocalizationService _localizationService;
|
||||||
|
|
||||||
|
public static void Initialize(IContainer container)
|
||||||
|
{
|
||||||
|
_localizationService = container.Resolve<ILocalizationService>();
|
||||||
|
}
|
||||||
|
|
||||||
public static List<Field> ToSchema(object model)
|
public static List<Field> ToSchema(object model)
|
||||||
{
|
{
|
||||||
@@ -93,13 +101,27 @@ namespace Prowlarr.Http.ClientSchema
|
|||||||
if (propertyInfo.PropertyType.IsSimpleType())
|
if (propertyInfo.PropertyType.IsSimpleType())
|
||||||
{
|
{
|
||||||
var fieldAttribute = property.Item2;
|
var fieldAttribute = property.Item2;
|
||||||
|
|
||||||
|
var label = fieldAttribute.Label.IsNotNullOrWhiteSpace()
|
||||||
|
? _localizationService.GetLocalizedString(fieldAttribute.Label,
|
||||||
|
GetTokens(type, fieldAttribute.Label, TokenField.Label))
|
||||||
|
: fieldAttribute.Label;
|
||||||
|
var helpText = fieldAttribute.HelpText.IsNotNullOrWhiteSpace()
|
||||||
|
? _localizationService.GetLocalizedString(fieldAttribute.HelpText,
|
||||||
|
GetTokens(type, fieldAttribute.Label, TokenField.HelpText))
|
||||||
|
: fieldAttribute.HelpText;
|
||||||
|
var helpTextWarning = fieldAttribute.HelpTextWarning.IsNotNullOrWhiteSpace()
|
||||||
|
? _localizationService.GetLocalizedString(fieldAttribute.HelpTextWarning,
|
||||||
|
GetTokens(type, fieldAttribute.Label, TokenField.HelpTextWarning))
|
||||||
|
: fieldAttribute.HelpTextWarning;
|
||||||
|
|
||||||
var field = new Field
|
var field = new Field
|
||||||
{
|
{
|
||||||
Name = prefix + GetCamelCaseName(propertyInfo.Name),
|
Name = prefix + GetCamelCaseName(propertyInfo.Name),
|
||||||
Label = fieldAttribute.Label,
|
Label = label,
|
||||||
Unit = fieldAttribute.Unit,
|
Unit = fieldAttribute.Unit,
|
||||||
HelpText = fieldAttribute.HelpText,
|
HelpText = helpText,
|
||||||
HelpTextWarning = fieldAttribute.HelpTextWarning,
|
HelpTextWarning = helpTextWarning,
|
||||||
HelpLink = fieldAttribute.HelpLink,
|
HelpLink = fieldAttribute.HelpLink,
|
||||||
Order = fieldAttribute.Order,
|
Order = fieldAttribute.Order,
|
||||||
Advanced = fieldAttribute.Advanced,
|
Advanced = fieldAttribute.Advanced,
|
||||||
@@ -158,6 +180,24 @@ namespace Prowlarr.Http.ClientSchema
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Dictionary<string, object> GetTokens(Type type, string label, TokenField field)
|
||||||
|
{
|
||||||
|
var tokens = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
foreach (var propertyInfo in type.GetProperties())
|
||||||
|
{
|
||||||
|
foreach (var attribute in propertyInfo.GetCustomAttributes(true))
|
||||||
|
{
|
||||||
|
if (attribute is FieldTokenAttribute fieldTokenAttribute && fieldTokenAttribute.Field == field && fieldTokenAttribute.Label == label)
|
||||||
|
{
|
||||||
|
tokens.Add(fieldTokenAttribute.Token, fieldTokenAttribute.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
private static List<SelectOption> GetSelectOptions(Type selectOptions)
|
private static List<SelectOption> GetSelectOptions(Type selectOptions)
|
||||||
{
|
{
|
||||||
if (selectOptions.IsEnum)
|
if (selectOptions.IsEnum)
|
||||||
|
Reference in New Issue
Block a user