Translate fields on the backend

(cherry picked from commit 48b12f5b00429a7cd218d23f0544641b0da62a06)
pull/1968/head
Stevie Robinson 6 months ago committed by Bogdan
parent ae1bc8366c
commit cb98b10468

@ -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)

Loading…
Cancel
Save