mirror of
https://github.com/Jackett/Jackett.git
synced 2025-10-02 00:32:55 +02:00
Web UI development started
This commit is contained in:
@@ -1,6 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
|
||||
</startup>
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
|
@@ -4,21 +4,16 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Jackett
|
||||
{
|
||||
public class DataUrl
|
||||
{
|
||||
static Dictionary<string, string> ImageMimeTypes = new Dictionary<string, string>{
|
||||
{ ".jpg", "data:image/jpeg" },
|
||||
{ ".jpeg", "data:image/jpeg" },
|
||||
{ ".png", "data:image/png" },
|
||||
{ ".gif", "data:image/gif" }
|
||||
};
|
||||
|
||||
public static string ReadFileToDataUrl(string file)
|
||||
{
|
||||
string mime = ImageMimeTypes[Path.GetExtension(file)];
|
||||
string mime = MimeMapping.GetMimeMapping(file);
|
||||
return "data:" + mime + ";base64," + Convert.ToBase64String(File.ReadAllBytes(file));
|
||||
}
|
||||
|
||||
|
@@ -12,8 +12,7 @@ namespace Jackett
|
||||
{
|
||||
string DisplayName { get; }
|
||||
string DisplayDescription { get; }
|
||||
Uri SitLink { get; }
|
||||
|
||||
Uri SiteLink { get; }
|
||||
|
||||
// Retrieved for starting setup for the indexer via web API
|
||||
Task<ConfigurationData> GetConfigurationForSetup();
|
||||
|
@@ -13,30 +13,26 @@ namespace Jackett
|
||||
static string AppConfigDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
static string IndexerConfigDirectory = Path.Combine(AppConfigDirectory, "Indexers");
|
||||
|
||||
Dictionary<string, IndexerInterface> loadedIndexers;
|
||||
|
||||
Dictionary<string, Type> implementedIndexerTypes;
|
||||
public Dictionary<string, IndexerInterface> Indexers { get; private set; }
|
||||
|
||||
public IndexerManager()
|
||||
{
|
||||
loadedIndexers = new Dictionary<string, IndexerInterface>();
|
||||
Indexers = new Dictionary<string, IndexerInterface>();
|
||||
|
||||
implementedIndexerTypes = (AppDomain.CurrentDomain.GetAssemblies()
|
||||
var implementedIndexerTypes = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(s => s.GetTypes())
|
||||
.Where(p => typeof(IndexerInterface).IsAssignableFrom(p)))
|
||||
.ToDictionary(t => t.Name.ToLower());
|
||||
.Where(p => typeof(IndexerInterface).IsAssignableFrom(p) && !p.IsInterface)
|
||||
.ToArray();
|
||||
|
||||
|
||||
// TODO: initialize all indexers at start, read all saved config json files then fill their indexers
|
||||
foreach (var t in implementedIndexerTypes)
|
||||
{
|
||||
LoadIndexer(t);
|
||||
}
|
||||
}
|
||||
|
||||
IndexerInterface LoadIndexer(string name)
|
||||
IndexerInterface LoadIndexer(Type indexerType)
|
||||
{
|
||||
name = name.Trim().ToLower();
|
||||
|
||||
Type indexerType;
|
||||
if (!implementedIndexerTypes.TryGetValue(name, out indexerType))
|
||||
throw new Exception(string.Format("No indexer of type '{0}'", name));
|
||||
var name = indexerType.Name.Trim().ToLower();
|
||||
|
||||
IndexerInterface newIndexer = (IndexerInterface)Activator.CreateInstance(indexerType);
|
||||
|
||||
@@ -47,15 +43,15 @@ namespace Jackett
|
||||
newIndexer.LoadFromSavedConfiguration(jsonString);
|
||||
}
|
||||
|
||||
loadedIndexers.Add(name, newIndexer);
|
||||
Indexers.Add(name, newIndexer);
|
||||
return newIndexer;
|
||||
}
|
||||
|
||||
public IndexerInterface GetIndexer(string name)
|
||||
{
|
||||
IndexerInterface indexer;
|
||||
if (!loadedIndexers.TryGetValue(name, out indexer))
|
||||
indexer = LoadIndexer(name);
|
||||
if (!Indexers.TryGetValue(name, out indexer))
|
||||
throw new Exception(string.Format("No indexer with ID '{0}'", name));
|
||||
return indexer;
|
||||
}
|
||||
|
||||
|
@@ -60,7 +60,7 @@ namespace Jackett
|
||||
|
||||
public string DisplayName { get { return "BitMeTV.org"; } }
|
||||
public string DisplayDescription { get { return "TV Episode specialty tracker"; } }
|
||||
public Uri SitLink { get { return new Uri("https://bitmetv.org"); } }
|
||||
public Uri SiteLink { get { return new Uri("https://bitmetv.org"); } }
|
||||
|
||||
public bool IsConfigured { get; private set; }
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Jackett
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
var config = new BmtvConfig();
|
||||
config.LoadValuesFromJson(configJson["config"]);
|
||||
config.LoadValuesFromJson(configJson);
|
||||
|
||||
var pairs = new Dictionary<string, string>
|
||||
{
|
||||
|
@@ -11,8 +11,20 @@ namespace Jackett
|
||||
public class Freshon : IndexerInterface
|
||||
{
|
||||
|
||||
public string DisplayName { get; private set; }
|
||||
public string DisplayName
|
||||
{
|
||||
get { return "FreshOnTV"; }
|
||||
}
|
||||
|
||||
public string DisplayDescription
|
||||
{
|
||||
get { return "Our goal is to provide the latest stuff in the TV show domain"; }
|
||||
}
|
||||
|
||||
public Uri SiteLink
|
||||
{
|
||||
get { return new Uri("https://freshon.tv/"); }
|
||||
}
|
||||
|
||||
public Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
@@ -33,23 +45,12 @@ namespace Jackett
|
||||
|
||||
public bool IsConfigured
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public string DisplayDescription
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public Uri SitLink
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -51,7 +51,8 @@
|
||||
<Reference Include="CsQuery">
|
||||
<HintPath>..\packages\CsQuery.1.3.4\lib\net40\CsQuery.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
@@ -85,10 +86,14 @@
|
||||
<Compile Include="ResultPage.cs" />
|
||||
<Compile Include="Server.cs" />
|
||||
<Compile Include="TorznabQuery.cs" />
|
||||
<Compile Include="WebApi.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="WebContent\bootstrap\glyphicons-halflings-regular.woff">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\test.xml" />
|
||||
@@ -100,20 +105,32 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="WebContent\handlebars-v3.0.1.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="WebContent\logos\bitmetv.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="WebContent\logos\freshon.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="WebContent\bootstrap\bootstrap.min.css">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="WebContent\bootstrap\bootstrap.min.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="WebContent\common.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="WebContent\index.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="WebContent\jquery-2.1.3.min.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="WebContent\setup_indexer.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="WebContent\IndexerImages\bitmetv.jpg">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\validator_reply.xml" />
|
||||
</ItemGroup>
|
||||
|
@@ -14,23 +14,12 @@ namespace Jackett
|
||||
{
|
||||
HttpListener listener;
|
||||
IndexerManager indexerManager;
|
||||
|
||||
static string[] StaticFiles = Directory.EnumerateFiles("WebContent", "*", SearchOption.AllDirectories).Select(Path.GetFileName).ToArray();
|
||||
|
||||
enum WebApiMethod
|
||||
{
|
||||
GetConfigForm,
|
||||
ConfigureIndexer
|
||||
}
|
||||
static Dictionary<string, WebApiMethod> WebApiMethods = new Dictionary<string, WebApiMethod>
|
||||
{
|
||||
{ "get_config_form", WebApiMethod.GetConfigForm },
|
||||
{ "configure_indexer", WebApiMethod.ConfigureIndexer }
|
||||
};
|
||||
WebApi webApi;
|
||||
|
||||
public Server()
|
||||
{
|
||||
indexerManager = new IndexerManager();
|
||||
webApi = new WebApi(indexerManager);
|
||||
|
||||
listener = new HttpListener();
|
||||
listener.Prefixes.Add("http://*:9117/");
|
||||
@@ -42,7 +31,7 @@ namespace Jackett
|
||||
while (true)
|
||||
{
|
||||
var context = await listener.GetContextAsync();
|
||||
ProcessContext(context);
|
||||
ProcessHttpRequest(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,114 +41,10 @@ namespace Jackett
|
||||
listener.Abort();
|
||||
}
|
||||
|
||||
static Dictionary<string, string> MimeMapping = new Dictionary<string, string> {
|
||||
{ ".html", "text/html" },
|
||||
{ ".js", "application/javascript" }
|
||||
};
|
||||
|
||||
async void ServeStaticFile(HttpListenerContext context, string file)
|
||||
async void ProcessHttpRequest(HttpListenerContext context)
|
||||
{
|
||||
var contentFile = File.ReadAllBytes(Path.Combine("WebContent", file));
|
||||
|
||||
string contentType;
|
||||
MimeMapping.TryGetValue(Path.GetExtension(file), out contentType);
|
||||
|
||||
context.Response.ContentType = contentType;
|
||||
context.Response.StatusCode = (int)HttpStatusCode.OK;
|
||||
await context.Response.OutputStream.WriteAsync(contentFile, 0, contentFile.Length);
|
||||
context.Response.OutputStream.Close();
|
||||
}
|
||||
|
||||
async void ProcessWebApiRequest(HttpListenerContext context, WebApiMethod method)
|
||||
{
|
||||
var query = HttpUtility.ParseQueryString(context.Request.Url.Query);
|
||||
|
||||
string postData = await new StreamReader(context.Request.InputStream).ReadToEndAsync();
|
||||
JToken dataJson = JObject.Parse(postData);
|
||||
JToken jsonReply = new JObject();
|
||||
var indexerString = (string)dataJson["indexer"];
|
||||
IndexerInterface indexer;
|
||||
|
||||
try
|
||||
if (webApi.HandleRequest(context))
|
||||
{
|
||||
indexer = indexerManager.GetIndexer(indexerString);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
ReplyWithJson(context, jsonReply);
|
||||
return;
|
||||
}
|
||||
|
||||
context.Response.ContentType = "text/json";
|
||||
context.Response.StatusCode = (int)HttpStatusCode.OK;
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case WebApiMethod.GetConfigForm:
|
||||
try
|
||||
{
|
||||
var config = await indexer.GetConfigurationForSetup();
|
||||
jsonReply = config.ToJson();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
break;
|
||||
case WebApiMethod.ConfigureIndexer:
|
||||
try
|
||||
{
|
||||
await indexer.ApplyConfiguration(dataJson);
|
||||
await indexer.VerifyConnection();
|
||||
jsonReply["result"] = "success";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
if (ex is ExceptionWithConfigData)
|
||||
{
|
||||
jsonReply["config"] = ((ExceptionWithConfigData)ex).ConfigData.ToJson();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = "Invalid API method";
|
||||
break;
|
||||
}
|
||||
|
||||
ReplyWithJson(context, jsonReply);
|
||||
}
|
||||
|
||||
async void ReplyWithJson(HttpListenerContext context, JToken json)
|
||||
{
|
||||
byte[] jsonBytes = Encoding.UTF8.GetBytes(json.ToString());
|
||||
await context.Response.OutputStream.WriteAsync(jsonBytes, 0, jsonBytes.Length);
|
||||
context.Response.OutputStream.Close();
|
||||
}
|
||||
|
||||
async void ProcessContext(HttpListenerContext context)
|
||||
{
|
||||
Console.WriteLine(context.Request.Url.Query);
|
||||
|
||||
string path = context.Request.Url.AbsolutePath.TrimStart('/');
|
||||
if (path == "")
|
||||
path = "index.html";
|
||||
|
||||
if (Array.IndexOf(StaticFiles, path) > -1)
|
||||
{
|
||||
ServeStaticFile(context, path);
|
||||
return;
|
||||
}
|
||||
|
||||
WebApiMethod apiMethod;
|
||||
if (WebApiMethods.TryGetValue(path, out apiMethod))
|
||||
{
|
||||
ProcessWebApiRequest(context, apiMethod);
|
||||
return;
|
||||
}
|
||||
|
||||
|
164
src/Jackett/WebApi.cs
Normal file
164
src/Jackett/WebApi.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Jackett
|
||||
{
|
||||
public class WebApi
|
||||
{
|
||||
static string WebContentFolder = "WebContent";
|
||||
static string[] StaticFiles = Directory.EnumerateFiles(WebContentFolder, "*", SearchOption.AllDirectories).ToArray();
|
||||
|
||||
public enum WebApiMethod
|
||||
{
|
||||
GetConfigForm,
|
||||
ConfigureIndexer,
|
||||
GetIndexers
|
||||
}
|
||||
static Dictionary<string, WebApiMethod> WebApiMethods = new Dictionary<string, WebApiMethod>
|
||||
{
|
||||
{ "get_config_form", WebApiMethod.GetConfigForm },
|
||||
{ "configure_indexer", WebApiMethod.ConfigureIndexer },
|
||||
{ "get_indexers", WebApiMethod.GetIndexers }
|
||||
};
|
||||
|
||||
IndexerManager indexerManager;
|
||||
|
||||
public WebApi(IndexerManager indexerManager)
|
||||
{
|
||||
this.indexerManager = indexerManager;
|
||||
}
|
||||
|
||||
public bool HandleRequest(HttpListenerContext context)
|
||||
{
|
||||
string path = context.Request.Url.AbsolutePath.TrimStart('/');
|
||||
if (path == "")
|
||||
path = "index.html";
|
||||
|
||||
var sysPath = Path.Combine(WebContentFolder, path.Replace("/", Path.DirectorySeparatorChar.ToString()));
|
||||
if (Array.IndexOf(StaticFiles, sysPath) > -1)
|
||||
{
|
||||
ServeStaticFile(context, path);
|
||||
return true;
|
||||
}
|
||||
|
||||
WebApi.WebApiMethod apiMethod;
|
||||
if (WebApi.WebApiMethods.TryGetValue(path, out apiMethod))
|
||||
{
|
||||
ProcessWebApiRequest(context, apiMethod);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async void ServeStaticFile(HttpListenerContext context, string file)
|
||||
{
|
||||
var contentFile = File.ReadAllBytes(Path.Combine(WebContentFolder, file));
|
||||
context.Response.ContentType = MimeMapping.GetMimeMapping(file);
|
||||
context.Response.StatusCode = (int)HttpStatusCode.OK;
|
||||
await context.Response.OutputStream.WriteAsync(contentFile, 0, contentFile.Length);
|
||||
context.Response.OutputStream.Close();
|
||||
}
|
||||
|
||||
async Task<JToken> ReadPostDataJson(Stream stream)
|
||||
{
|
||||
string postData = await new StreamReader(stream).ReadToEndAsync();
|
||||
return JObject.Parse(postData);
|
||||
}
|
||||
|
||||
async void ProcessWebApiRequest(HttpListenerContext context, WebApiMethod method)
|
||||
{
|
||||
var query = HttpUtility.ParseQueryString(context.Request.Url.Query);
|
||||
|
||||
JToken jsonReply = new JObject();
|
||||
|
||||
context.Response.ContentType = "text/json";
|
||||
context.Response.StatusCode = (int)HttpStatusCode.OK;
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case WebApiMethod.GetConfigForm:
|
||||
try
|
||||
{
|
||||
var postData = await ReadPostDataJson(context.Request.InputStream);
|
||||
string indexerString = (string)postData["indexer"];
|
||||
var indexer = indexerManager.GetIndexer(indexerString);
|
||||
var config = await indexer.GetConfigurationForSetup();
|
||||
jsonReply["config"] = config.ToJson();
|
||||
jsonReply["result"] = "success";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
break;
|
||||
case WebApiMethod.ConfigureIndexer:
|
||||
try
|
||||
{
|
||||
var postData = await ReadPostDataJson(context.Request.InputStream);
|
||||
string indexerString = (string)postData["indexer"];
|
||||
var indexer = indexerManager.GetIndexer(indexerString);
|
||||
await indexer.ApplyConfiguration(postData["config"]);
|
||||
await indexer.VerifyConnection();
|
||||
jsonReply["result"] = "success";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
if (ex is ExceptionWithConfigData)
|
||||
{
|
||||
jsonReply["config"] = ((ExceptionWithConfigData)ex).ConfigData.ToJson();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WebApiMethod.GetIndexers:
|
||||
try
|
||||
{
|
||||
jsonReply["result"] = "success";
|
||||
JArray items = new JArray();
|
||||
foreach (var i in indexerManager.Indexers)
|
||||
{
|
||||
var indexer = i.Value;
|
||||
var item = new JObject();
|
||||
item["id"] = i.Key;
|
||||
item["display_name"] = indexer.DisplayName;
|
||||
item["display_description"] = indexer.DisplayDescription;
|
||||
item["is_configured"] = indexer.IsConfigured;
|
||||
item["site_link"] = indexer.SiteLink;
|
||||
items.Add(item);
|
||||
}
|
||||
jsonReply["items"] = items;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = "Invalid API method";
|
||||
break;
|
||||
}
|
||||
|
||||
ReplyWithJson(context, jsonReply);
|
||||
}
|
||||
|
||||
async void ReplyWithJson(HttpListenerContext context, JToken json)
|
||||
{
|
||||
byte[] jsonBytes = Encoding.UTF8.GetBytes(json.ToString());
|
||||
await context.Response.OutputStream.WriteAsync(jsonBytes, 0, jsonBytes.Length);
|
||||
context.Response.OutputStream.Close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 56 KiB |
5
src/Jackett/WebContent/bootstrap/bootstrap.min.css
vendored
Normal file
5
src/Jackett/WebContent/bootstrap/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/Jackett/WebContent/bootstrap/bootstrap.min.js
vendored
Normal file
7
src/Jackett/WebContent/bootstrap/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
3748
src/Jackett/WebContent/handlebars-v3.0.1.js
Normal file
3748
src/Jackett/WebContent/handlebars-v3.0.1.js
Normal file
File diff suppressed because one or more lines are too long
@@ -3,9 +3,42 @@
|
||||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title></title>
|
||||
<script src="jquery-2.1.3.min.js"></script>
|
||||
<script src="handlebars-v3.0.1.js"></script>
|
||||
<script src="bootstrap/bootstrap.min.js"></script>
|
||||
<link href="bootstrap/bootstrap.min.css" rel="stylesheet">
|
||||
<title>Jackett</title>
|
||||
<style>
|
||||
#templates {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
home
|
||||
<div class="container-fluid">
|
||||
<div id="indexers"></div>
|
||||
</div>
|
||||
|
||||
<div id="templates">
|
||||
<div class="indexer">
|
||||
<div class="indexer-name">{{name}}</div>
|
||||
<div class="indexer-description">{{description}}</div>
|
||||
<div class="indexer-link"><a href="{{link}}">{{link}}</a></div>
|
||||
<div class="indexer-configured">
|
||||
{{#if configured}}
|
||||
<span>Configred</span>
|
||||
{{else}}
|
||||
<span>Not configured</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
var indexerTemplate = Handlebars.compile($("#templates > .indexer").html());
|
||||
$('#indexers').append(indexerTemplate({ name: "n", description: "desc", link: "http://google.com", configured: true }));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
BIN
src/Jackett/WebContent/logos/bitmetv.png
Normal file
BIN
src/Jackett/WebContent/logos/bitmetv.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
BIN
src/Jackett/WebContent/logos/freshon.png
Normal file
BIN
src/Jackett/WebContent/logos/freshon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
@@ -20,7 +20,7 @@
|
||||
var urlParams = getUrlParams();
|
||||
|
||||
var jqxhr = $.post("get_config_form", JSON.stringify({ indexer: urlParams.indexer }), function (data) {
|
||||
populateForm(data);
|
||||
populateForm(data.config);
|
||||
})
|
||||
.fail(function () {
|
||||
alert("error");
|
||||
|
Reference in New Issue
Block a user