Added the functionality for the Sonarr Profiles on the Admin page #2 resolved.
pull/13/head
tidusjar 8 years ago
parent 640e76e167
commit 24b2cd0a9c

@ -0,0 +1,38 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: ISonarrApi.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using PlexRequests.Api.Models.Sonarr;
namespace PlexRequests.Api.Interfaces
{
public interface ISonarrApi
{
List<SonarrProfile> GetProfiles(string apiKey, Uri baseUrl);
}
}

@ -48,6 +48,7 @@
<Compile Include="IApiRequest.cs" />
<Compile Include="ICouchPotatoApi.cs" />
<Compile Include="IPlexApi.cs" />
<Compile Include="ISonarrApi.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>

@ -0,0 +1,102 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace PlexRequests.Api {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class MockApiData {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal MockApiData() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PlexRequests.Api.MockApiData", typeof(MockApiData).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to [
/// {
/// &quot;name&quot;: &quot;SD&quot;,
/// &quot;cutoff&quot;: {
/// &quot;id&quot;: 1,
/// &quot;name&quot;: &quot;SDTV&quot;
/// },
/// &quot;items&quot;: [
/// {
/// &quot;quality&quot;: {
/// &quot;id&quot;: 1,
/// &quot;name&quot;: &quot;SDTV&quot;
/// },
/// &quot;allowed&quot;: true
/// },
/// {
/// &quot;quality&quot;: {
/// &quot;id&quot;: 8,
/// &quot;name&quot;: &quot;WEBDL-480p&quot;
/// },
/// &quot;allowed&quot;: true
/// },
/// {
/// &quot;quality&quot;: {
/// &quot;id&quot;: 2,
/// &quot;name&quot;: &quot;DVD&quot;
/// },
/// &quot;allowed&quot;: true
/// },
/// {
/// &quot;quality&quot;: { [rest of string was truncated]&quot;;.
/// </summary>
internal static string Sonarr_Profiles {
get {
return ResourceManager.GetString("Sonarr_Profiles", resourceCulture);
}
}
}
}

@ -0,0 +1,444 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Sonarr_Profiles" xml:space="preserve">
<value>[
{
"name": "SD",
"cutoff": {
"id": 1,
"name": "SDTV"
},
"items": [
{
"quality": {
"id": 1,
"name": "SDTV"
},
"allowed": true
},
{
"quality": {
"id": 8,
"name": "WEBDL-480p"
},
"allowed": true
},
{
"quality": {
"id": 2,
"name": "DVD"
},
"allowed": true
},
{
"quality": {
"id": 4,
"name": "HDTV-720p"
},
"allowed": false
},
{
"quality": {
"id": 9,
"name": "HDTV-1080p"
},
"allowed": false
},
{
"quality": {
"id": 10,
"name": "Raw-HD"
},
"allowed": false
},
{
"quality": {
"id": 5,
"name": "WEBDL-720p"
},
"allowed": false
},
{
"quality": {
"id": 6,
"name": "Bluray-720p"
},
"allowed": false
},
{
"quality": {
"id": 3,
"name": "WEBDL-1080p"
},
"allowed": false
},
{
"quality": {
"id": 7,
"name": "Bluray-1080p"
},
"allowed": false
}
],
"id": 1
},
{
"name": "HD 720p",
"cutoff": {
"id": 4,
"name": "HDTV-720p"
},
"items": [
{
"quality": {
"id": 1,
"name": "SDTV"
},
"allowed": false
},
{
"quality": {
"id": 8,
"name": "WEBDL-480p"
},
"allowed": false
},
{
"quality": {
"id": 2,
"name": "DVD"
},
"allowed": false
},
{
"quality": {
"id": 4,
"name": "HDTV-720p"
},
"allowed": true
},
{
"quality": {
"id": 9,
"name": "HDTV-1080p"
},
"allowed": false
},
{
"quality": {
"id": 10,
"name": "Raw-HD"
},
"allowed": false
},
{
"quality": {
"id": 5,
"name": "WEBDL-720p"
},
"allowed": true
},
{
"quality": {
"id": 6,
"name": "Bluray-720p"
},
"allowed": true
},
{
"quality": {
"id": 3,
"name": "WEBDL-1080p"
},
"allowed": false
},
{
"quality": {
"id": 7,
"name": "Bluray-1080p"
},
"allowed": false
}
],
"id": 2
},
{
"name": "HD 1080p",
"cutoff": {
"id": 9,
"name": "HDTV-1080p"
},
"items": [
{
"quality": {
"id": 1,
"name": "SDTV"
},
"allowed": false
},
{
"quality": {
"id": 8,
"name": "WEBDL-480p"
},
"allowed": false
},
{
"quality": {
"id": 2,
"name": "DVD"
},
"allowed": false
},
{
"quality": {
"id": 4,
"name": "HDTV-720p"
},
"allowed": false
},
{
"quality": {
"id": 9,
"name": "HDTV-1080p"
},
"allowed": true
},
{
"quality": {
"id": 10,
"name": "Raw-HD"
},
"allowed": false
},
{
"quality": {
"id": 5,
"name": "WEBDL-720p"
},
"allowed": false
},
{
"quality": {
"id": 6,
"name": "Bluray-720p"
},
"allowed": false
},
{
"quality": {
"id": 3,
"name": "WEBDL-1080p"
},
"allowed": true
},
{
"quality": {
"id": 7,
"name": "Bluray-1080p"
},
"allowed": true
}
],
"id": 3
},
{
"name": "HD - All",
"cutoff": {
"id": 4,
"name": "HDTV-720p"
},
"items": [
{
"quality": {
"id": 1,
"name": "SDTV"
},
"allowed": false
},
{
"quality": {
"id": 8,
"name": "WEBDL-480p"
},
"allowed": false
},
{
"quality": {
"id": 2,
"name": "DVD"
},
"allowed": false
},
{
"quality": {
"id": 4,
"name": "HDTV-720p"
},
"allowed": true
},
{
"quality": {
"id": 9,
"name": "HDTV-1080p"
},
"allowed": true
},
{
"quality": {
"id": 10,
"name": "Raw-HD"
},
"allowed": false
},
{
"quality": {
"id": 5,
"name": "WEBDL-720p"
},
"allowed": true
},
{
"quality": {
"id": 6,
"name": "Bluray-720p"
},
"allowed": true
},
{
"quality": {
"id": 3,
"name": "WEBDL-1080p"
},
"allowed": true
},
{
"quality": {
"id": 7,
"name": "Bluray-1080p"
},
"allowed": true
}
],
"id": 4
}
]</value>
</data>
</root>

@ -0,0 +1,46 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: MockSonarrApi.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using PlexRequests.Api.Interfaces;
using PlexRequests.Api.Models.Sonarr;
namespace PlexRequests.Api.Mocks
{
public class MockSonarrApi : ISonarrApi
{
public List<SonarrProfile> GetProfiles(string apiKey, Uri baseUrl)
{
var json = MockApiData.Sonarr_Profiles;
var obj = JsonConvert.DeserializeObject<List<SonarrProfile>>(json);
return obj;
}
}
}

@ -66,6 +66,12 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ApiRequest.cs" />
<Compile Include="MockApiData.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>MockApiData.resx</DependentUpon>
</Compile>
<Compile Include="Mocks\MockSonarrApi.cs" />
<Compile Include="SonarrApi.cs" />
<Compile Include="CouchPotatoApi.cs" />
<Compile Include="MovieBase.cs" />
@ -93,7 +99,12 @@
<Name>PlexRequests.Helpers</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<EmbeddedResource Include="MockApiData.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>MockApiData.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

@ -26,7 +26,6 @@
#endregion
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using NLog;
using PlexRequests.Api.Interfaces;
@ -35,7 +34,7 @@ using RestSharp;
namespace PlexRequests.Api
{
public class SonarrApi
public class SonarrApi : ISonarrApi
{
public SonarrApi()
{

@ -70,22 +70,12 @@ namespace PlexRequests.Helpers
if (val.StartsWith("http://", StringComparison.Ordinal))
{
var split = val.Split('/');
if (split.Length >= 4)
{
uri = new UriBuilder(Uri.UriSchemeHttp, split[2], port, "/" + split[3]);
}
else
uri = new UriBuilder(new Uri($"{val}:{port}"));
uri = split.Length >= 4 ? new UriBuilder(Uri.UriSchemeHttp, split[2], port, "/" + split[3]) : new UriBuilder(new Uri($"{val}:{port}"));
}
else if (val.StartsWith("https://", StringComparison.Ordinal))
{
var split = val.Split('/');
if (split.Length >= 4)
{
uri = new UriBuilder(Uri.UriSchemeHttps, split[2], port, "/" + split[3]);
}
else
uri = new UriBuilder(Uri.UriSchemeHttps, split[2], port);
uri = split.Length >= 4 ? new UriBuilder(Uri.UriSchemeHttps, split[2], port, "/" + split[3]) : new UriBuilder(Uri.UriSchemeHttps, split[2], port);
}
else
{

@ -38,6 +38,7 @@ using Nancy.TinyIoc;
using PlexRequests.Api;
using PlexRequests.Api.Interfaces;
using PlexRequests.Api.Mocks;
using PlexRequests.Core;
using PlexRequests.Core.SettingModels;
using PlexRequests.Helpers;
@ -79,6 +80,9 @@ namespace PlexRequests.UI
container.Register<ICouchPotatoApi, CouchPotatoApi>();
container.Register<ISonarrApi, SonarrApi>();
//container.Register<ISonarrApi, MockSonarrApi>();

@ -1,49 +1,122 @@
@media (min-width: 768px ) {
.row {
position: relative;
}
.bottom-align-text {
position: absolute;
bottom: 0;
right: 0;
}
}
@media (max-width: 48em) {
.home {
padding-top: 1rem;
}
}
@media (min-width: 48em) {
.home {
padding-top: 4rem;
}
}
.multiSelect {
background-color: #4e5d6c;
}
.form-control-custom {
background-color: #4e5d6c !important;
color: white !important;
}
h1 {
font-size: 3.5rem !important;
font-weight: 600 !important;
}
p {
font-size: 1.1rem !important;
}
label {
display: inline-block !important;
margin-bottom: .5rem !important;
font-size: 16px !important;
}
@media (min-width: 768px) {
.row {
position: relative; }
.bottom-align-text {
position: absolute;
bottom: 0;
right: 0; } }
@media (max-width: 48em) {
.home {
padding-top: 1rem; } }
@media (min-width: 48em) {
.home {
padding-top: 4rem; } }
.btn {
border-radius: 0.25rem !important; }
.multiSelect {
background-color: #4e5d6c; }
.form-control-custom {
background-color: #4e5d6c !important;
color: white !important; }
h1 {
font-size: 3.5rem !important;
font-weight: 600 !important; }
.request-title {
margin-top: 0 !important;
font-size: 1.9rem !important; }
p {
font-size: 1.1rem !important; }
label {
display: inline-block !important;
margin-bottom: 0.5rem !important;
font-size: 16px !important; }
.btn-danger-outline {
color: #d9534f !important;
background-color: transparent;
background-image: none;
border-color: #d9534f !important; }
.btn-danger-outline:focus,
.btn-danger-outline.focus,
.btn-danger-outline:active,
.btn-danger-outline.active,
.btn-danger-outline:hover,
.open > .btn-danger-outline.dropdown-toggle {
color: #fff !important;
background-color: #d9534f !important;
border-color: #d9534f !important; }
.btn-primary-outline {
color: #ff761b !important;
background-color: transparent;
background-image: none;
border-color: #ff761b !important; }
.btn-primary-outline:focus,
.btn-primary-outline.focus,
.btn-primary-outline:active,
.btn-primary-outline.active,
.btn-primary-outline:hover,
.open > .btn-primary-outline.dropdown-toggle {
color: #fff !important;
background-color: #df691a !important;
border-color: #df691a !important; }
.btn-info-outline {
color: #5bc0de !important;
background-color: transparent;
background-image: none;
border-color: #5bc0de !important; }
.btn-info-outline:focus,
.btn-info-outline.focus,
.btn-info-outline:active,
.btn-info-outline.active,
.btn-info-outline:hover,
.open > .btn-info-outline.dropdown-toggle {
color: #fff !important;
background-color: #5bc0de !important;
border-color: #5bc0de !important; }
.btn-warning-outline {
color: #f0ad4e !important;
background-color: transparent;
background-image: none;
border-color: #f0ad4e !important; }
.btn-warning-outline:focus,
.btn-warning-outline.focus,
.btn-warning-outline:active,
.btn-warning-outline.active,
.btn-warning-outline:hover,
.open > .btn-warning-outline.dropdown-toggle {
color: #fff !important;
background-color: #f0ad4e !important;
border-color: #f0ad4e !important; }
.btn-success-outline {
color: #5cb85c !important;
background-color: transparent;
background-image: none;
border-color: #5cb85c !important; }
.btn-success-outline:focus,
.btn-success-outline.focus,
.btn-success-outline:active,
.btn-success-outline.active,
.btn-success-outline:hover,
.open > .btn-success-outline.dropdown-toggle {
color: #fff !important;
background-color: #5cb85c !important;
border-color: #5cb85c !important; }

@ -0,0 +1 @@
@media(min-width:768px){.row{position:relative;}.bottom-align-text{position:absolute;bottom:0;right:0;}}@media(max-width:48em){.home{padding-top:1rem;}}@media(min-width:48em){.home{padding-top:4rem;}}.btn{border-radius:.25rem !important;}.multiSelect{background-color:#4e5d6c;}.form-control-custom{background-color:#4e5d6c !important;color:#fff !important;}h1{font-size:3.5rem !important;font-weight:600 !important;}.request-title{margin-top:0 !important;font-size:1.9rem !important;}p{font-size:1.1rem !important;}label{display:inline-block !important;margin-bottom:.5rem !important;font-size:16px !important;}.btn-danger-outline{color:#d9534f !important;background-color:transparent;background-image:none;border-color:#d9534f !important;}.btn-danger-outline:focus,.btn-danger-outline.focus,.btn-danger-outline:active,.btn-danger-outline.active,.btn-danger-outline:hover,.open>.btn-danger-outline.dropdown-toggle{color:#fff !important;background-color:#d9534f !important;border-color:#d9534f !important;}.btn-primary-outline{color:#ff761b !important;background-color:transparent;background-image:none;border-color:#ff761b !important;}.btn-primary-outline:focus,.btn-primary-outline.focus,.btn-primary-outline:active,.btn-primary-outline.active,.btn-primary-outline:hover,.open>.btn-primary-outline.dropdown-toggle{color:#fff !important;background-color:#df691a !important;border-color:#df691a !important;}.btn-info-outline{color:#5bc0de !important;background-color:transparent;background-image:none;border-color:#5bc0de !important;}.btn-info-outline:focus,.btn-info-outline.focus,.btn-info-outline:active,.btn-info-outline.active,.btn-info-outline:hover,.open>.btn-info-outline.dropdown-toggle{color:#fff !important;background-color:#5bc0de !important;border-color:#5bc0de !important;}.btn-warning-outline{color:#f0ad4e !important;background-color:transparent;background-image:none;border-color:#f0ad4e !important;}.btn-warning-outline:focus,.btn-warning-outline.focus,.btn-warning-outline:active,.btn-warning-outline.active,.btn-warning-outline:hover,.open>.btn-warning-outline.dropdown-toggle{color:#fff !important;background-color:#f0ad4e !important;border-color:#f0ad4e !important;}.btn-success-outline{color:#5cb85c !important;background-color:transparent;background-image:none;border-color:#5cb85c !important;}.btn-success-outline:focus,.btn-success-outline.focus,.btn-success-outline:active,.btn-success-outline.active,.btn-success-outline:hover,.open>.btn-success-outline.dropdown-toggle{color:#fff !important;background-color:#5cb85c !important;border-color:#5cb85c !important;}

@ -0,0 +1,159 @@
$form-color: #4e5d6c;
$primary-colour: #df691a;
$primary-colour-outline: #ff761b;
$info-colour: #5bc0de;
$warning-colour: #f0ad4e;
$danger-colour: #d9534f;
$success-colour: #5cb85c;
$i:
!important
;
@media (min-width: 768px ) {
.row {
position: relative;
}
.bottom-align-text {
position: absolute;
bottom: 0;
right: 0;
}
}
@media (max-width: 48em) {
.home {
padding-top: 1rem;
}
}
@media (min-width: 48em) {
.home {
padding-top: 4rem;
}
}
.btn {
border-radius: .25rem $i;
}
.multiSelect {
background-color: $form-color;
}
.form-control-custom {
background-color: $form-color $i;
color: white $i;
}
h1 {
font-size: 3.5rem $i;
font-weight: 600 $i;
}
.request-title {
margin-top: 0 $i;
font-size: 1.9rem $i;
}
p {
font-size: 1.1rem $i;
}
label {
display: inline-block $i;
margin-bottom: .5rem $i;
font-size: 16px $i;
}
.btn-danger-outline {
color: $danger-colour $i;
background-color: transparent;
background-image: none;
border-color: $danger-colour $i;
}
.btn-danger-outline:focus,
.btn-danger-outline.focus,
.btn-danger-outline:active,
.btn-danger-outline.active,
.btn-danger-outline:hover,
.open > .btn-danger-outline.dropdown-toggle {
color: #fff $i;
background-color: $danger-colour $i;
border-color: $danger-colour $i;
}
.btn-primary-outline {
color: $primary-colour-outline $i;
background-color: transparent;
background-image: none;
border-color: $primary-colour-outline $i;
}
.btn-primary-outline:focus,
.btn-primary-outline.focus,
.btn-primary-outline:active,
.btn-primary-outline.active,
.btn-primary-outline:hover,
.open > .btn-primary-outline.dropdown-toggle {
color: #fff $i;
background-color: $primary-colour $i;
border-color: $primary-colour $i;
}
.btn-info-outline {
color: $info-colour $i;
background-color: transparent;
background-image: none;
border-color: $info-colour $i;
}
.btn-info-outline:focus,
.btn-info-outline.focus,
.btn-info-outline:active,
.btn-info-outline.active,
.btn-info-outline:hover,
.open > .btn-info-outline.dropdown-toggle {
color: #fff $i;
background-color: $info-colour $i;
border-color: $info-colour $i;
}
.btn-warning-outline {
color: $warning-colour $i;
background-color: transparent;
background-image: none;
border-color: $warning-colour $i;
}
.btn-warning-outline:focus,
.btn-warning-outline.focus,
.btn-warning-outline:active,
.btn-warning-outline.active,
.btn-warning-outline:hover,
.open > .btn-warning-outline.dropdown-toggle {
color: #fff $i;
background-color: $warning-colour $i;
border-color: $warning-colour $i;
}
.btn-success-outline {
color: $success-colour $i;
background-color: transparent;
background-image: none;
border-color: $success-colour $i;
}
.btn-success-outline:focus,
.btn-success-outline.focus,
.btn-success-outline:active,
.btn-success-outline.active,
.btn-success-outline:hover,
.open > .btn-success-outline.dropdown-toggle {
color: #fff $i;
background-color: $success-colour $i;
border-color: $success-colour $i;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -208,8 +208,8 @@ function tvLoad() {
});
};
// Builds the request context.
function buildRequestContext(result, type) {
var context = {
posterPath: result.posterPath,
id: result.providerId,

@ -80,9 +80,9 @@ function sendRequestAjax(data, type, url, buttonId) {
generateNotify("Success!", "success");
$('#' + buttonId).html("<i class='fa fa-check'></i> Requested");
$('#' + buttonId).removeClass("btn-primary");
$('#' + buttonId).removeClass("btn-primary-outline");
$('#' + buttonId).removeAttr("data-toggle");
$('#' + buttonId).addClass("btn-success");
$('#' + buttonId).addClass("btn-success-outline");
} else {
generateNotify(response.message, "warning");
}

@ -36,6 +36,7 @@ using Nancy.Security;
using NLog;
using PlexRequests.Api;
using PlexRequests.Api.Interfaces;
using PlexRequests.Core;
using PlexRequests.Core.SettingModels;
using PlexRequests.Helpers;
@ -50,19 +51,22 @@ namespace PlexRequests.UI.Modules
private ISettingsService<AuthenticationSettings> AuthService { get; set; }
private ISettingsService<PlexSettings> PlexService { get; set; }
private ISettingsService<SonarrSettings> SonarrService { get; set; }
private ISonarrApi SonarrApi { get; set; }
private static Logger Log = LogManager.GetCurrentClassLogger();
public AdminModule(ISettingsService<PlexRequestSettings> rpService,
ISettingsService<CouchPotatoSettings> cpService,
ISettingsService<AuthenticationSettings> auth
, ISettingsService<PlexSettings> plex,
ISettingsService<SonarrSettings> sonarr ) : base("admin")
ISettingsService<SonarrSettings> sonarr,
ISonarrApi sonarrApi) : base("admin")
{
RpService = rpService;
CpService = cpService;
AuthService = auth;
PlexService = plex;
SonarrService = sonarr;
SonarrApi = sonarrApi;
#if !DEBUG
this.RequiresAuthentication();
@ -87,7 +91,7 @@ namespace PlexRequests.UI.Modules
Get["/sonarr"] = _ => Sonarr();
Post["/sonarr"] = _ => SaveSonarr();
Get["/sonarrprofiles"] = _ => GetSonarrQualityProfiles();
Post["/sonarrprofiles"] = _ => GetSonarrQualityProfiles();
}
private Negotiator Authentication()
@ -224,14 +228,13 @@ namespace PlexRequests.UI.Modules
var plexSettings = this.Bind<SonarrSettings>();
SonarrService.SaveSettings(plexSettings);
return Context.GetRedirect("~/admin/Sonarr");
return Response.AsJson(new JsonResponseModel { Result = true });
}
private Response GetSonarrQualityProfiles()
{
var settings = SonarrService.GetSettings();
var api = new SonarrApi();
var profiles = api.GetProfiles(settings.ApiKey, settings.FullUri);
var settings = this.Bind<SonarrSettings>();
var profiles = SonarrApi.GetProfiles(settings.ApiKey, settings.FullUri);
return Response.AsJson(profiles);
}

@ -158,9 +158,6 @@
<Content Include="Content\bootstrap.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\custom.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Compile Include="Jobs\PlexRegistry.cs" />
<Compile Include="Jobs\PlexTaskFactory.cs" />
<Compile Include="Models\JsonResponseModel.cs" />
@ -184,6 +181,13 @@
<Content Include="Content\bootstrap.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\custom.css">
<DependentUpon>custom.scss</DependentUpon>
</Content>
<Content Include="Content\custom.min.css">
<DependentUpon>custom.css</DependentUpon>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Content\favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
@ -196,7 +200,7 @@
<Content Include="Content\fonts\fontawesome-webfont.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\handlebars.js">
<Content Include="Content\handlebars.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\jquery-2.2.1.min.js">
@ -213,6 +217,11 @@
<Content Include="NLog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="compilerconfig.json" />
<None Include="compilerconfig.json.defaults">
<DependentUpon>compilerconfig.json</DependentUpon>
</None>
<None Include="Content\custom.scss" />
<None Include="NLog.xsd">
<SubType>Designer</SubType>
</None>

@ -48,11 +48,12 @@ namespace PlexRequests.UI
private static Logger Log = LogManager.GetCurrentClassLogger();
static void Main(string[] args)
{
Log.Trace("Getting assembly version");
WriteOutVersion();
var s = new Setup();
var connection = s.SetupDb();
s.SetupDb();
//ConfigureTargets(connection);

@ -58,7 +58,7 @@
</div>
<div class="form-group">
<div class="">
<button id="requestToken" class="btn btn-primary">Request Token <i class="fa fa-key"></i></button>
<button id="requestToken" class="btn btn-primary-outline-outline">Request Token <i class="fa fa-key"></i></button>
</div>
</div>
@ -73,7 +73,7 @@
<div class="form-group">
<div>
<button id="refreshUsers" class="btn btn-primary">Refresh Users</button>
<button id="refreshUsers" class="btn btn-primary-outline">Refresh Users</button>
</div>
</div>
@ -89,7 +89,7 @@
</div>
<div class="form-group">
<div>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="submit" class="btn btn-primary-outline">Submit</button>
</div>
</div>
</fieldset>

@ -43,7 +43,7 @@
<div class="form-group">
<div>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="submit" class="btn btn-primary-outline">Submit</button>
</div>
</div>
</fieldset>

@ -32,7 +32,7 @@
<div class="form-group">
<div>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="submit" class="btn btn-primary-outline">Submit</button>
</div>
</div>
</fieldset>

@ -81,7 +81,7 @@
</div>
<div class="form-group">
<div>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="submit" class="btn btn-primary-outline">Submit</button>
</div>
</div>
</fieldset>

@ -37,20 +37,22 @@
<input type="text" class="form-control form-control-custom " id="ApiKey" name="ApiKey" value="@Model.ApiKey">
</div>
</div>
<div class="form-group">
<label for="select" class="control-label">Quality Profiles</label>
<div>
<select class="form-control" id="select">
</select>
<button type="submit" id="getProfiles" class="btn btn-primary-outline">Get Quality Profiles</button>
</div>
</div>
<div class="form-group">
<label for="select" class="control-label">Quality Profiles</label>
<div id="profiles">
<select class="form-control" id="select"></select>
</div>
</div>
<div class="form-group">
<div>
<button type="submit" class="btn btn-primary">Submit</button>
<button id="save" type="submit" class="btn btn-primary-outline ">Submit</button>
</div>
</div>
</fieldset>
@ -62,16 +64,27 @@
<script>
$(function () {
@if (!string.IsNullOrEmpty(Model.QualityProfile))
{
<text>
var qualitySelected = @Model.QualityProfile;
var $form = $("#mainForm");
$.ajax({
type: "GET",
type: $form.prop("method"),
data: $form.serialize(),
url: "sonarrprofiles",
dataType: "json",
success: function (response) {
response.forEach(function (result) {
$("#select").append("<option>" + result.name + "</option>");
success: function(response) {
response.forEach(function(result) {
if (result.id == qualitySelected) {
$("#select").append("<option selected='selected' value='" + result.id + "'>" + result.name + "</option>");
} else {
$("#select").append("<option value='" + result.id + "'>" + result.name + "</option>");
}
});
},
error: function (e) {
error: function(e) {
console.log(e);
generateNotify("Something went wrong!", "danger");
}
@ -80,5 +93,71 @@
</text>
}
$('#save').click(function(e) {
e.preventDefault();
var qualityProfile = $("#profiles option:selected").val();
var $form = $("#mainForm");
var data = $form.serialize();
data = data + "&qualityProfile=" + qualityProfile;
$.ajax({
type: $form.prop("method"),
data: data,
url: $form.prop("action"),
dataType: "json",
success: function (response) {
if (response.result === true) {
generateNotify("Success!", "success");
} else {
generateNotify(response.message, "warning");
}
},
error: function (e) {
console.log(e);
generateNotify("Something went wrong!", "danger");
}
});
});
$('#getProfiles').click(function (e) {
e.preventDefault();
if (!$('#Ip').val()) {
generateNotify("Please enter a valid IP/Hostname.", "warning");
return;
}
if (!$('#portNumber').val()) {
generateNotify("Please enter a valid Port Number.", "warning");
return;
}
if (!$('#ApiKey').val()) {
generateNotify("Please enter a valid ApiKey.", "warning");
return;
}
var $form = $("#mainForm");
$.ajax({
type: $form.prop("method"),
data: $form.serialize(),
url: "sonarrprofiles",
dataType: "json",
success: function (response) {
response.forEach(function (result) {
$("#select").append("<option value='" + result.id + "'>" + result.name + "</option>");
});
},
error: function (e) {
console.log(e);
generateNotify("Something went wrong!", "danger");
}
});
});
})
</script>

@ -5,7 +5,7 @@
<br/>
Remember Me <input name="RememberMe" type="checkbox" value="True"/>
<br/>
<input class="btn btn-success" type="submit" value="Login"/>
<input class="btn btn-success-outline" type="submit" value="Login"/>
</form>
@if (!Model.AdminExists)
{

@ -4,7 +4,7 @@
Password <input class="form-control" name="Password" type="password" />
<br />
<br />
<input class="btn btn-success" type="submit" value="Create User" />
<input class="btn btn-success-outline" type="submit" value="Create User" />
</form>
@if (Model.Errored)
{

@ -4,7 +4,7 @@
<h4>Below you can see yours and all other requests, as well as their download and approval status.</h4>
@if (Context.CurrentUser.IsAuthenticated())
{
<button id="approveAll" class="btn btn-success" type="submit"><i class="fa fa-plus"></i> Approve All</button>
<button id="approveAll" class="btn btn-success-outline" type="submit"><i class="fa fa-plus"></i> Approve All</button>
<br/>
<br/>
}
@ -69,13 +69,13 @@
<div class="col-sm-5 ">
<div>
<a href="https://www.themoviedb.org/{{type}}/{{id}}">
<h4>{{title}} ({{year}})</h4>
<h4 class="request-title">{{title}} ({{year}})</h4>
</a>
<span class="label label-success">{{status}}</span>
</div>
<br />
<p>Release Date: {{releaseDate}}</p>
<p>
<div>Release Date: {{releaseDate}}</div>
<div>
Approved:
{{#if_eq approved false}}
<i id="{{requestId}}notapproved" class="fa fa-times"></i>
@ -83,8 +83,8 @@
{{#if_eq approved true}}
<i class="fa fa-check"></i>
{{/if_eq}}
</p>
<p>
</div>
<div>
Available
{{#if_eq available false}}
<i class="fa fa-times"></i>
@ -92,14 +92,14 @@
{{#if_eq available true}}
<i class="fa fa-check"></i>
{{/if_eq}}
</p>
<p>Requested By: {{requestedBy}}</p>
<p>Requested Date: {{requestedDate}}</p>
</div>
<div>Requested By: {{requestedBy}}</div>
<div>Requested Date: {{requestedDate}}</div>
<div id="issueArea">
{{#if otherMessage}}
<p>Message: {{otherMessage}}</p>
<div>Message: {{otherMessage}}</div>
{{else}}
<p>Issue: {{issues}}</p>
<div>Issue: {{issues}}</div>
{{/if}}
</div>
</div>
@ -110,24 +110,24 @@
{{#if_eq approved false}}
<form method="POST" action="/approval/approve" id="approve{{requestId}}">
<input name="requestId" type="text" value="{{requestId}}" hidden="hidden" />
<button id="{{requestId}}" custom-button="{{requestId}}" style="text-align: right" class="btn btn-success approve" type="submit"><i class="fa fa-plus"></i> Approve</button>
<button id="{{requestId}}" custom-button="{{requestId}}" style="text-align: right" class="btn btn-sm btn-success-outline approve" type="submit"><i class="fa fa-plus"></i> Approve</button>
</form>
{{/if_eq}}
<form method="POST" action="/requests/delete" id="delete{{requestId}}">
<input name="Id" type="text" value="{{requestId}}" hidden="hidden" />
<button id="{{requestId}}" style="text-align: right" class="btn btn-danger delete" type="submit"><i class="fa fa-plus"></i> Remove</button>
<button id="{{requestId}}" style="text-align: right" class="btn btn-sm btn-danger-outline delete" type="submit"><i class="fa fa-plus"></i> Remove</button>
</form>
<form method="POST" action="/requests/clearissues" id="clear{{requestId}}">
<input name="Id" type="text" value="{{requestId}}" hidden="hidden" />
<button id="{{requestId}}" style="text-align: right" class="btn btn-info clear" type="submit"><i class="fa fa-check"></i> Clear Issues</button>
<button id="{{requestId}}" style="text-align: right" class="btn btn-sm btn-info-outline clear" type="submit"><i class="fa fa-check"></i> Clear Issues</button>
</form>
{{/if_eq}}
<form method="POST" action="/requests/reportissue/" id="report{{requestId}}">
<input name="requestId" type="text" value="{{requestId}}" hidden="hidden" />
<div class="dropdown">
<button id="{{requestId}}" class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<button id="{{requestId}}" class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<i class="fa fa-plus"></i> Report Issue
<span class="caret"></span>
</button>
@ -161,7 +161,7 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary theSaveButton" data-dismiss="modal">Save changes</button>
<button type="button" class="btn btn-primary-outline theSaveButton" data-dismiss="modal">Save changes</button>
</div>
</form>
</div>

@ -86,11 +86,11 @@
<form method="POST" action="/search/request/{{type}}" id="form{{id}}">
<input name="{{type}}Id" type="text" value="{{id}}" hidden="hidden" />
{{#if_eq type "movie"}}
<button id="{{id}}" style="text-align: right" class="btn btn-primary requestMovie" type="submit"><i class="fa fa-plus"></i> Request</button>
<button id="{{id}}" style="text-align: right" class="btn btn-primary-outline requestMovie" type="submit"><i class="fa fa-plus"></i> Request</button>
{{/if_eq}}
{{#if_eq type "tv"}}
<div class="dropdown">
<button id="{{id}}" class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<button id="{{id}}" class="btn btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<i class="fa fa-plus"></i> Request
<span class="caret"></span>
</button>

@ -6,13 +6,13 @@
<head>
<title>Plex Requests</title>
<!-- Styles -->
<link rel="stylesheet" href="~/Content/custom.css" type="text/css"/>
<link rel="stylesheet" href="~/Content/custom.min.css" type="text/css"/>
<link rel="stylesheet" href="~/Content/bootstrap.css" type="text/css"/>
<link rel="stylesheet" href="~/Content/font-awesome.css" type="text/css"/>
<!-- Scripts -->
<script src="/Content/jquery-2.2.1.min.js"></script>
<script src="/Content/handlebars.js"></script>
<script src="/Content/handlebars.min.js"></script>
<script src="/Content/bootstrap.min.js"></script>
<script src="/Content/bootstrap-notify.min.js"></script>
<script src="/Content/site.js"></script>

@ -28,7 +28,7 @@
</div>
}
<br />
<button id="loginBtn" class="btn btn-success" type="submit"><i class="fa fa-user fa-fw"></i> Sign In</button>
<button id="loginBtn" class="btn btn-success-outline" type="submit"><i class="fa fa-user fa-fw"></i> Sign In</button>
</form>
</div>

@ -0,0 +1,6 @@
[
{
"outputFile": "Content/custom.css",
"inputFile": "Content/custom.scss"
}
]

@ -0,0 +1,49 @@
{
"compilers": {
"less": {
"autoPrefix": "",
"cssComb": "none",
"ieCompat": true,
"strictMath": false,
"strictUnits": false,
"relativeUrls": true,
"rootPath": "",
"sourceMapRoot": "",
"sourceMapBasePath": "",
"sourceMap": false
},
"sass": {
"includePath": "",
"indentType": "space",
"indentWidth": 2,
"outputStyle": "nested",
"Precision": 5,
"relativeUrls": true,
"sourceMapRoot": "",
"sourceMap": false
},
"stylus": {
"sourceMap": false
},
"babel": {
"sourceMap": false
},
"coffeescript": {
"bare": false,
"runtimeMode": "node",
"sourceMap": false
}
},
"minifiers": {
"css": {
"enabled": true,
"termSemicolons": true,
"gzip": false
},
"javascript": {
"enabled": true,
"termSemicolons": true,
"gzip": false
}
}
}

@ -19,6 +19,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
appveyor.yml = appveyor.yml
LICENSE = LICENSE
README.md = README.md
WE-Palette.css = WE-Palette.css
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlexRequests.Helpers", "PlexRequests.Helpers\PlexRequests.Helpers.csproj", "{1252336D-42A3-482A-804C-836E60173DFA}"

Loading…
Cancel
Save