diff --git a/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs b/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs
new file mode 100644
index 000000000..d80aed440
--- /dev/null
+++ b/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs
@@ -0,0 +1,45 @@
+using FluentAssertions;
+using NUnit.Framework;
+using NzbDrone.Api.ClientSchema;
+using NzbDrone.Test.Common;
+
+namespace NzbDrone.Api.Test.ClientSchemaTests
+{
+ [TestFixture]
+ public class SchemaBuilderFixture : TestBase
+ {
+ [Test]
+ public void should_return_field_for_every_property()
+ {
+ var schema = SchemaBuilder.GenerateSchema(new TestModel());
+ schema.Should().HaveCount(2);
+ }
+
+
+ [Test]
+ public void schema_should_have_proper_fields()
+ {
+ var model = new TestModel
+ {
+ FirstName = "Bob",
+ LastName = "Poop"
+ };
+
+ var schema = SchemaBuilder.GenerateSchema(model);
+
+ schema.Should().Contain(c => c.Order == 1 && c.Name == "LastName" && c.Label == "Last Name" && c.HelpText == "Your Last Name" && c.Value == "Poop");
+ schema.Should().Contain(c => c.Order == 0 && c.Name == "FirstName" && c.Label == "First Name" && c.HelpText == "Your First Name" && c.Value == "Bob");
+ }
+
+ }
+
+
+ public class TestModel
+ {
+ [FieldDefinition(0, Label = "First Name", HelpText = "Your First Name")]
+ public string FirstName { get; set; }
+
+ [FieldDefinition(1, Label = "Last Name", HelpText = "Your Last Name")]
+ public string LastName { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Api.Test/NzbDrone.Api.Test.csproj b/NzbDrone.Api.Test/NzbDrone.Api.Test.csproj
index 0c884e4f9..476e0707d 100644
--- a/NzbDrone.Api.Test/NzbDrone.Api.Test.csproj
+++ b/NzbDrone.Api.Test/NzbDrone.Api.Test.csproj
@@ -72,6 +72,7 @@
+
diff --git a/NzbDrone.Api/ClientSchema/Field.cs b/NzbDrone.Api/ClientSchema/Field.cs
new file mode 100644
index 000000000..2fe6388fe
--- /dev/null
+++ b/NzbDrone.Api/ClientSchema/Field.cs
@@ -0,0 +1,11 @@
+namespace NzbDrone.Api.ClientSchema
+{
+ public class Field
+ {
+ public int Order { get; set; }
+ public string Name { get; set; }
+ public string Label { get; set; }
+ public string HelpText { get; set; }
+ public string Value { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Api/ClientSchema/FieldDefinitionAttribute.cs b/NzbDrone.Api/ClientSchema/FieldDefinitionAttribute.cs
new file mode 100644
index 000000000..1c1c06699
--- /dev/null
+++ b/NzbDrone.Api/ClientSchema/FieldDefinitionAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace NzbDrone.Api.ClientSchema
+{
+ [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
+ public class FieldDefinitionAttribute : Attribute
+ {
+
+ public FieldDefinitionAttribute(int order)
+ {
+ Order = order;
+ }
+
+ public int Order { get; private set; }
+ public string Label { get; set; }
+ public string HelpText { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Api/ClientSchema/SchemaBuilder.cs b/NzbDrone.Api/ClientSchema/SchemaBuilder.cs
new file mode 100644
index 000000000..8be6507b6
--- /dev/null
+++ b/NzbDrone.Api/ClientSchema/SchemaBuilder.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+using NzbDrone.Common.Reflection;
+
+namespace NzbDrone.Api.ClientSchema
+{
+ public static class SchemaBuilder
+ {
+ public static List GenerateSchema(object model)
+ {
+ var properties = model.GetType().GetSimpleProperties();
+
+ var result = new List(properties.Count);
+
+ foreach (var propertyInfo in properties)
+ {
+ var fieldAttribute = propertyInfo.GetAttribute();
+
+ var field = new Field()
+ {
+ Name = propertyInfo.Name,
+ Label = fieldAttribute.Label,
+ HelpText = fieldAttribute.HelpText,
+ Order = fieldAttribute.Order,
+
+ };
+
+ var value = propertyInfo.GetValue(model, null);
+ if (value != null)
+ {
+ field.Value = value.ToString();
+ }
+
+ result.Add(field);
+ }
+
+ return result;
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Api/Indexers/IndexerModule.cs b/NzbDrone.Api/Indexers/IndexerModule.cs
index 537771cb7..5931efbab 100644
--- a/NzbDrone.Api/Indexers/IndexerModule.cs
+++ b/NzbDrone.Api/Indexers/IndexerModule.cs
@@ -1,5 +1,7 @@
using System.Collections.Generic;
+using NzbDrone.Api.ClientSchema;
using NzbDrone.Core.Indexers;
+using Omu.ValueInjecter;
namespace NzbDrone.Api.Indexers
{
@@ -15,7 +17,18 @@ namespace NzbDrone.Api.Indexers
private List GetAll()
{
- return ApplyToList(_indexerService.All);
+ var indexers = _indexerService.All();
+
+ var result = new List(indexers.Count);
+
+ foreach (var indexerDefinition in indexers)
+ {
+ var resource = new IndexerResource();
+ resource.InjectFrom(indexerDefinition);
+ resource.Fields = SchemaBuilder.GenerateSchema(indexerDefinition.Settings);
+ }
+
+ return result;
}
}
}
\ No newline at end of file
diff --git a/NzbDrone.Api/Indexers/IndexerResource.cs b/NzbDrone.Api/Indexers/IndexerResource.cs
index fadce1a5e..0274e0658 100644
--- a/NzbDrone.Api/Indexers/IndexerResource.cs
+++ b/NzbDrone.Api/Indexers/IndexerResource.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using NzbDrone.Api.ClientSchema;
using NzbDrone.Api.REST;
namespace NzbDrone.Api.Indexers
@@ -7,6 +9,7 @@ namespace NzbDrone.Api.Indexers
{
public Boolean Enable { get; set; }
public String Name { get; set; }
- public String Settings { get; set; }
+
+ public List Fields { get; set; }
}
}
\ No newline at end of file
diff --git a/NzbDrone.Api/NzbDrone.Api.csproj b/NzbDrone.Api/NzbDrone.Api.csproj
index 5af7f8900..631f29021 100644
--- a/NzbDrone.Api/NzbDrone.Api.csproj
+++ b/NzbDrone.Api/NzbDrone.Api.csproj
@@ -84,6 +84,9 @@
+
+
+
diff --git a/NzbDrone.Common/Reflection/ReflectionExtensions.cs b/NzbDrone.Common/Reflection/ReflectionExtensions.cs
index 5f8474e7b..d772f5765 100644
--- a/NzbDrone.Common/Reflection/ReflectionExtensions.cs
+++ b/NzbDrone.Common/Reflection/ReflectionExtensions.cs
@@ -45,5 +45,16 @@ namespace NzbDrone.Common.Reflection
return propertyInfo.CanWrite && propertyInfo.GetSetMethod(false) != null;
}
+ public static T GetAttribute(this MemberInfo member, bool isRequired = true) where T : Attribute
+ {
+ var attribute = member.GetCustomAttributes(typeof(T), false).SingleOrDefault();
+
+ if (attribute == null && isRequired)
+ {
+ throw new ArgumentException(String.Format("The {0} attribute must be defined on member {1}", typeof(T).Name, member.Name));
+ }
+
+ return (T)attribute;
+ }
}
}
\ No newline at end of file
diff --git a/UI/Settings/Indexers/CollectionView.js b/UI/Settings/Indexers/CollectionView.js
index 51023fc28..76a9ca9ce 100644
--- a/UI/Settings/Indexers/CollectionView.js
+++ b/UI/Settings/Indexers/CollectionView.js
@@ -1,10 +1,8 @@
'use strict';
-
-define(['app', 'Settings/Indexers/ItemView'], function (app) {
-
+define(['app', 'Settings/Indexers/ItemView'], function () {
NzbDrone.Settings.Indexers.CollectionView = Backbone.Marionette.CompositeView.extend({
itemView : NzbDrone.Settings.Indexers.ItemView,
itemViewContainer : '#x-indexers',
template : 'Settings/Indexers/CollectionTemplate'
});
-});
\ No newline at end of file
+});
diff --git a/UI/Settings/Indexers/Model.js b/UI/Settings/Indexers/Model.js
index f1cf3792a..aa8592e0d 100644
--- a/UI/Settings/Indexers/Model.js
+++ b/UI/Settings/Indexers/Model.js
@@ -1,13 +1,5 @@
"use strict";
-define(['app'], function (app) {
+define(['app'], function () {
NzbDrone.Settings.Indexers.Model = Backbone.DeepModel.extend({
- mutators: {
- fields: function () {
- return [
- { key: 'username', title: 'Username', helpText: 'HALP!', value: 'mark', index: 0 },
- { key: 'apiKey', title: 'API Key', helpText: 'HALP!', value: '', index: 1 }
- ];
- }
- }
});
});