mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-16 02:02:55 -07:00
Merge branch 'develop' of https://github.com/tidusjar/ombi into develop
This commit is contained in:
commit
58af83959e
104 changed files with 2319 additions and 17403 deletions
25
build.cake
25
build.cake
|
@ -1,10 +1,10 @@
|
|||
|
||||
#tool "nuget:?package=GitVersion.CommandLine"
|
||||
#addin "Cake.Gulp"
|
||||
#addin "nuget:?package=Cake.Npm&version=0.13.0"
|
||||
#addin "SharpZipLib"
|
||||
#addin nuget:?package=Cake.Compression&version=0.1.4
|
||||
#addin "Cake.Incubator"
|
||||
#addin "Cake.Yarn"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ARGUMENTS
|
||||
|
@ -122,36 +122,19 @@ Task("SetVersionInfo")
|
|||
|
||||
Task("NPM")
|
||||
.Does(() => {
|
||||
var settings = new NpmInstallSettings {
|
||||
LogLevel = NpmLogLevel.Silent,
|
||||
WorkingDirectory = webProjDir,
|
||||
Production = true
|
||||
};
|
||||
|
||||
NpmInstall(settings);
|
||||
Yarn.FromPath(webProjDir).Install();
|
||||
});
|
||||
|
||||
Task("Gulp Publish")
|
||||
.IsDependentOn("NPM")
|
||||
.Does(() => {
|
||||
|
||||
var runScriptSettings = new NpmRunScriptSettings {
|
||||
ScriptName="publish",
|
||||
WorkingDirectory = webProjDir,
|
||||
};
|
||||
|
||||
NpmRunScript(runScriptSettings);
|
||||
Yarn.FromPath(webProjDir).RunScript("publish");
|
||||
});
|
||||
|
||||
Task("TSLint")
|
||||
.Does(() =>
|
||||
{
|
||||
var settings = new NpmRunScriptSettings {
|
||||
WorkingDirectory = webProjDir,
|
||||
ScriptName = "lint"
|
||||
};
|
||||
|
||||
NpmRunScript(settings);
|
||||
Yarn.FromPath(webProjDir).RunScript("lint");
|
||||
});
|
||||
|
||||
Task("PrePublish")
|
||||
|
|
|
@ -29,7 +29,10 @@ namespace Ombi.Core.Tests.Rule.Search
|
|||
{
|
||||
ProviderId = "123"
|
||||
});
|
||||
var search = new SearchMovieViewModel();
|
||||
var search = new SearchMovieViewModel()
|
||||
{
|
||||
TheMovieDbId = "123",
|
||||
};
|
||||
var result = await Rule.Execute(search);
|
||||
|
||||
Assert.True(result.Success);
|
||||
|
|
|
@ -15,9 +15,7 @@ namespace Ombi.Core.Engine.Interfaces
|
|||
Task<RequestEngineResult> DenyChildRequest(int requestId);
|
||||
Task<RequestsViewModel<TvRequests>> GetRequestsLite(int count, int position, OrderFilterModel type);
|
||||
Task<IEnumerable<TvRequests>> SearchTvRequest(string search);
|
||||
Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> SearchTvRequestTree(string search);
|
||||
Task<TvRequests> UpdateTvRequest(TvRequests request);
|
||||
Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> GetRequestsTreeNode(int count, int position);
|
||||
Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId);
|
||||
Task<ChildRequests> UpdateChildRequest(ChildRequests request);
|
||||
Task RemoveTvChild(int requestId);
|
||||
|
|
|
@ -7,16 +7,10 @@ namespace Ombi.Core.Engine.Interfaces
|
|||
public interface ITvSearchEngine
|
||||
{
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Search(string searchTerm);
|
||||
Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> SearchTreeNode(string searchTerm);
|
||||
Task<TreeNode<SearchTvShowViewModel>> GetShowInformationTreeNode(int tvdbid);
|
||||
Task<SearchTvShowViewModel> GetShowInformation(int tvdbid);
|
||||
Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> PopularTree();
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Popular();
|
||||
Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> AnticipatedTree();
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Anticipated();
|
||||
Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> MostWatchesTree();
|
||||
Task<IEnumerable<SearchTvShowViewModel>> MostWatches();
|
||||
Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> TrendingTree();
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Trending();
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Core.Engine
|
||||
{
|
||||
|
||||
public class TreeNode<T>
|
||||
{
|
||||
public string Label { get; set; }
|
||||
public T Data { get; set; }
|
||||
public List<TreeNode<T>> Children { get; set; }
|
||||
public bool Leaf { get; set; }
|
||||
public bool Expanded { get; set; }
|
||||
}
|
||||
|
||||
public class TreeNode<T,U>
|
||||
{
|
||||
public string Label { get; set; }
|
||||
public T Data { get; set; }
|
||||
public List<TreeNode<U>> Children { get; set; }
|
||||
public bool Leaf { get; set; }
|
||||
public bool Expanded { get; set; }
|
||||
}
|
||||
}
|
|
@ -202,38 +202,6 @@ namespace Ombi.Core.Engine
|
|||
Collection = allRequests
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> GetRequestsTreeNode(int count, int position)
|
||||
{
|
||||
var shouldHide = await HideFromOtherUsers();
|
||||
List<TvRequests> allRequests;
|
||||
if (shouldHide.Hide)
|
||||
{
|
||||
allRequests = await TvRepository.Get(shouldHide.UserId)
|
||||
.Include(x => x.ChildRequests)
|
||||
.ThenInclude(x => x.SeasonRequests)
|
||||
.ThenInclude(x => x.Episodes)
|
||||
.Where(x => x.ChildRequests.Any())
|
||||
.OrderByDescending(x => x.ChildRequests.Max(y => y.RequestedDate))
|
||||
.Skip(position).Take(count).ToListAsync();
|
||||
|
||||
FilterChildren(allRequests, shouldHide);
|
||||
}
|
||||
else
|
||||
{
|
||||
allRequests = await TvRepository.Get()
|
||||
.Include(x => x.ChildRequests)
|
||||
.ThenInclude(x => x.SeasonRequests)
|
||||
.ThenInclude(x => x.Episodes)
|
||||
.Where(x => x.ChildRequests.Any())
|
||||
.OrderByDescending(x => x.ChildRequests.Max(y => y.RequestedDate))
|
||||
.Skip(position).Take(count).ToListAsync();
|
||||
}
|
||||
|
||||
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
|
||||
return ParseIntoTreeNode(allRequests);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TvRequests>> GetRequests()
|
||||
{
|
||||
var shouldHide = await HideFromOtherUsers();
|
||||
|
@ -360,23 +328,6 @@ namespace Ombi.Core.Engine
|
|||
return results;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> SearchTvRequestTree(string search)
|
||||
{
|
||||
var shouldHide = await HideFromOtherUsers();
|
||||
IQueryable<TvRequests> allRequests;
|
||||
if (shouldHide.Hide)
|
||||
{
|
||||
allRequests = TvRepository.Get(shouldHide.UserId);
|
||||
}
|
||||
else
|
||||
{
|
||||
allRequests = TvRepository.Get();
|
||||
}
|
||||
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
|
||||
results.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
|
||||
return ParseIntoTreeNode(results);
|
||||
}
|
||||
|
||||
public async Task<TvRequests> UpdateTvRequest(TvRequests request)
|
||||
{
|
||||
await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username);
|
||||
|
@ -596,28 +547,6 @@ namespace Ombi.Core.Engine
|
|||
return await AfterRequest(model.ChildRequests.FirstOrDefault());
|
||||
}
|
||||
|
||||
private static List<TreeNode<TvRequests, List<ChildRequests>>> ParseIntoTreeNode(IEnumerable<TvRequests> result)
|
||||
{
|
||||
var node = new List<TreeNode<TvRequests, List<ChildRequests>>>();
|
||||
|
||||
foreach (var value in result)
|
||||
{
|
||||
node.Add(new TreeNode<TvRequests, List<ChildRequests>>
|
||||
{
|
||||
Data = value,
|
||||
Children = new List<TreeNode<List<ChildRequests>>>
|
||||
{
|
||||
new TreeNode<List<ChildRequests>>
|
||||
{
|
||||
Data = SortEpisodes(value.ChildRequests),
|
||||
Leaf = true
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
private static List<ChildRequests> SortEpisodes(List<ChildRequests> items)
|
||||
{
|
||||
foreach (var value in items)
|
||||
|
|
|
@ -59,11 +59,6 @@ namespace Ombi.Core.Engine
|
|||
return null;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> SearchTreeNode(string searchTerm)
|
||||
{
|
||||
var result = await Search(searchTerm);
|
||||
return result.Select(ParseIntoTreeNode).ToList();
|
||||
}
|
||||
public async Task<SearchTvShowViewModel> GetShowInformation(int tvdbid)
|
||||
{
|
||||
var show = await TvMazeApi.ShowLookupByTheTvDbId(tvdbid);
|
||||
|
@ -116,19 +111,6 @@ namespace Ombi.Core.Engine
|
|||
return await ProcessResult(mapped);
|
||||
}
|
||||
|
||||
public async Task<TreeNode<SearchTvShowViewModel>> GetShowInformationTreeNode(int tvdbid)
|
||||
{
|
||||
var result = await GetShowInformation(tvdbid);
|
||||
return ParseIntoTreeNode(result);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> PopularTree()
|
||||
{
|
||||
var result = await Cache.GetOrAdd(CacheKeys.PopularTv, async () => await TraktApi.GetPopularShows(), DateTime.Now.AddHours(12));
|
||||
var processed = await ProcessResults(result);
|
||||
return processed.Select(ParseIntoTreeNode).ToList();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> Popular()
|
||||
{
|
||||
var result = await Cache.GetOrAdd(CacheKeys.PopularTv, async () => await TraktApi.GetPopularShows(), DateTime.Now.AddHours(12));
|
||||
|
@ -136,12 +118,6 @@ namespace Ombi.Core.Engine
|
|||
return processed;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> AnticipatedTree()
|
||||
{
|
||||
var result = await Cache.GetOrAdd(CacheKeys.AnticipatedTv, async () => await TraktApi.GetAnticipatedShows(), DateTime.Now.AddHours(12));
|
||||
var processed = await ProcessResults(result);
|
||||
return processed.Select(ParseIntoTreeNode).ToList();
|
||||
}
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> Anticipated()
|
||||
{
|
||||
|
||||
|
@ -150,12 +126,6 @@ namespace Ombi.Core.Engine
|
|||
return processed;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> MostWatchesTree()
|
||||
{
|
||||
var result = await Cache.GetOrAdd(CacheKeys.MostWatchesTv, async () => await TraktApi.GetMostWatchesShows(), DateTime.Now.AddHours(12));
|
||||
var processed = await ProcessResults(result);
|
||||
return processed.Select(ParseIntoTreeNode).ToList();
|
||||
}
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> MostWatches()
|
||||
{
|
||||
var result = await Cache.GetOrAdd(CacheKeys.MostWatchesTv, async () => await TraktApi.GetMostWatchesShows(), DateTime.Now.AddHours(12));
|
||||
|
@ -163,13 +133,6 @@ namespace Ombi.Core.Engine
|
|||
return processed;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> TrendingTree()
|
||||
{
|
||||
var result = await Cache.GetOrAdd(CacheKeys.TrendingTv, async () => await TraktApi.GetTrendingShows(), DateTime.Now.AddHours(12));
|
||||
var processed = await ProcessResults(result);
|
||||
return processed.Select(ParseIntoTreeNode).ToList();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> Trending()
|
||||
{
|
||||
var result = await Cache.GetOrAdd(CacheKeys.TrendingTv, async () => await TraktApi.GetTrendingShows(), DateTime.Now.AddHours(12));
|
||||
|
@ -177,22 +140,6 @@ namespace Ombi.Core.Engine
|
|||
return processed;
|
||||
}
|
||||
|
||||
private static TreeNode<SearchTvShowViewModel> ParseIntoTreeNode(SearchTvShowViewModel result)
|
||||
{
|
||||
return new TreeNode<SearchTvShowViewModel>
|
||||
{
|
||||
Data = result,
|
||||
Children = new List<TreeNode<SearchTvShowViewModel>>
|
||||
{
|
||||
new TreeNode<SearchTvShowViewModel>
|
||||
{
|
||||
Data = result, Leaf = true
|
||||
}
|
||||
},
|
||||
Leaf = false
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<SearchTvShowViewModel>> ProcessResults<T>(IEnumerable<T> items)
|
||||
{
|
||||
var retVal = new List<SearchTvShowViewModel>();
|
||||
|
|
23
src/Ombi/.gitignore
vendored
23
src/Ombi/.gitignore
vendored
|
@ -1,23 +1,10 @@
|
|||
/wwwroot/css/**
|
||||
/wwwroot/fonts/**
|
||||
/wwwroot/lib/**
|
||||
/wwwroot/maps/**
|
||||
/wwwroot/dist/**
|
||||
/wwwroot/*.js.map
|
||||
/wwwroot/*.js
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/bower_components
|
||||
|
||||
# misc
|
||||
node_modules
|
||||
bin
|
||||
obj
|
||||
wwwroot/dist
|
||||
*.log
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage/*
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
testem.log
|
||||
#/typings
|
||||
/systemjs.config.js*
|
||||
/Logs/**
|
||||
**.db
|
||||
|
|
15
src/Ombi/.vscode/tasks.json
vendored
15
src/Ombi/.vscode/tasks.json
vendored
|
@ -4,7 +4,7 @@
|
|||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"taskName": "restore",
|
||||
"label": "restore",
|
||||
"command": "npm",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
|
@ -14,7 +14,16 @@
|
|||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"taskName": "build",
|
||||
"label": "clean",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"clean"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
|
@ -27,7 +36,7 @@
|
|||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"taskName": "lint",
|
||||
"label": "lint",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { animate, style, transition, trigger } from "@angular/animations";
|
||||
import { AnimationEntryMetadata } from "@angular/core";
|
||||
import { AnimationTriggerMetadata } from "@angular/animations";
|
||||
|
||||
export const fadeInOutAnimation: AnimationEntryMetadata = trigger("fadeInOut", [
|
||||
export const fadeInOutAnimation: AnimationTriggerMetadata = trigger("fadeInOut", [
|
||||
transition(":enter", [ // :enter is alias to 'void => *'
|
||||
style({ opacity: 0 }),
|
||||
animate(1000, style({ opacity: 1 })),
|
||||
|
|
|
@ -40,7 +40,7 @@ export class AppComponent implements OnInit {
|
|||
__webpack_public_path__ = base + "/dist/";
|
||||
}
|
||||
|
||||
this.translate.addLangs(["en", "de", "fr","da","es","it","nl","sv","no", "pl", "pt"]);
|
||||
this.translate.addLangs(["en", "de", "fr", "da", "es", "it", "nl", "sv", "no", "pl", "pt"]);
|
||||
// this language will be used as a fallback when a translation isn't found in the current language
|
||||
this.translate.setDefaultLang("en");
|
||||
|
||||
|
@ -88,8 +88,8 @@ export class AppComponent implements OnInit {
|
|||
|
||||
public openMobileApp(event: any) {
|
||||
event.preventDefault();
|
||||
if(!this.customizationSettings.applicationUrl) {
|
||||
this.notificationService.warning("Mobile","Please ask your admin to setup the Application URL!");
|
||||
if (!this.customizationSettings.applicationUrl) {
|
||||
this.notificationService.warning("Mobile", "Please ask your admin to setup the Application URL!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import {CommonModule, PlatformLocation} from "@angular/common";
|
||||
import {HttpClient, HttpClientModule} from "@angular/common/http";
|
||||
import {NgModule} from "@angular/core";
|
||||
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
|
||||
import {HttpModule} from "@angular/http";
|
||||
import {MatButtonModule, MatCardModule, MatInputModule, MatTabsModule} from "@angular/material";
|
||||
import {BrowserModule} from "@angular/platform-browser";
|
||||
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
|
||||
import {RouterModule, Routes} from "@angular/router";
|
||||
import { CommonModule, PlatformLocation } from "@angular/common";
|
||||
import { HttpClient, HttpClientModule } from "@angular/common/http";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { HttpModule } from "@angular/http";
|
||||
import { MatButtonModule, MatCardModule, MatInputModule, MatTabsModule } from "@angular/material";
|
||||
import { BrowserModule } from "@angular/platform-browser";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import { JwtModule } from "@auth0/angular-jwt";
|
||||
|
||||
|
@ -15,7 +15,7 @@ import { TranslateLoader, TranslateModule } from "@ngx-translate/core";
|
|||
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
|
||||
import { CookieService } from "ng2-cookies";
|
||||
import { GrowlModule } from "primeng/components/growl/growl";
|
||||
import { ButtonModule, CaptchaModule, ConfirmationService, ConfirmDialogModule, DataTableModule,DialogModule, SharedModule, SidebarModule, TooltipModule } from "primeng/primeng";
|
||||
import { ButtonModule, CaptchaModule, ConfirmationService, ConfirmDialogModule, DataTableModule, DialogModule, SharedModule, SidebarModule, TooltipModule } from "primeng/primeng";
|
||||
|
||||
// Components
|
||||
import { AppComponent } from "./app.component";
|
||||
|
@ -67,6 +67,14 @@ export function HttpLoaderFactory(http: HttpClient, platformLocation: PlatformLo
|
|||
return new TranslateHttpLoader(http, "/translations/", `.json?v=${version}`);
|
||||
}
|
||||
|
||||
export function JwtTokenGetter() {
|
||||
const token = localStorage.getItem("id_token");
|
||||
if (!token) {
|
||||
return "";
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot(routes),
|
||||
|
@ -92,13 +100,7 @@ export function HttpLoaderFactory(http: HttpClient, platformLocation: PlatformLo
|
|||
CommonModule,
|
||||
JwtModule.forRoot({
|
||||
config: {
|
||||
tokenGetter: () => {
|
||||
const token = localStorage.getItem("id_token");
|
||||
if (!token) {
|
||||
return "";
|
||||
}
|
||||
return token;
|
||||
},
|
||||
tokenGetter: JwtTokenGetter,
|
||||
},
|
||||
}),
|
||||
TranslateModule.forRoot({
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { JwtHelperService } from "@auth0/angular-jwt";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ServiceHelpers } from "../services";
|
||||
import { ILocalUser, IUserLogin } from "./IUserLogin";
|
||||
|
@ -53,9 +53,9 @@ export class AuthService extends ServiceHelpers {
|
|||
} else {
|
||||
u.roles.push(roles);
|
||||
}
|
||||
return <ILocalUser>u;
|
||||
return <ILocalUser> u;
|
||||
}
|
||||
return <ILocalUser>{};
|
||||
return <ILocalUser> { };
|
||||
}
|
||||
|
||||
public hasRole(role: string): boolean {
|
||||
|
|
|
@ -11,7 +11,7 @@ export class CookieComponent implements OnInit {
|
|||
|
||||
public ngOnInit() {
|
||||
const cookie = this.cookieService.getAll();
|
||||
if(cookie.Auth) {
|
||||
if (cookie.Auth) {
|
||||
const jwtVal = cookie.Auth;
|
||||
localStorage.setItem("id_token", jwtVal);
|
||||
this.router.navigate(["search"]);
|
||||
|
|
|
@ -71,6 +71,10 @@ export interface ITvRequests {
|
|||
status: string;
|
||||
childRequests: IChildRequests[];
|
||||
qualityOverride: number;
|
||||
background: any;
|
||||
totalSeasons: number;
|
||||
tvDbId: number;
|
||||
open: boolean; // THIS IS FOR THE UI
|
||||
|
||||
// For UI display
|
||||
qualityOverrideTitle: string;
|
||||
|
|
|
@ -28,8 +28,16 @@ export interface ISearchTvResult {
|
|||
available: boolean;
|
||||
plexUrl: string;
|
||||
embyUrl: string;
|
||||
quality: string;
|
||||
firstSeason: boolean;
|
||||
latestSeason: boolean;
|
||||
theTvDbId: string;
|
||||
subscribed: boolean;
|
||||
showSubscribe: boolean;
|
||||
fullyAvailable: boolean;
|
||||
partlyAvailable: boolean;
|
||||
background: any;
|
||||
open: boolean; // THIS IS FOR THE UI
|
||||
}
|
||||
|
||||
export interface ITvRequestViewModel {
|
||||
|
|
|
@ -63,8 +63,8 @@ export class IssueDetailsComponent implements OnInit {
|
|||
issueCategoryId: x.issueCategoryId,
|
||||
subject: x.subject,
|
||||
description: x.description,
|
||||
status:x.status,
|
||||
resolvedDate:x.resolvedDate,
|
||||
status: x.status,
|
||||
resolvedDate: x.resolvedDate,
|
||||
title: x.title,
|
||||
requestType: x.requestType,
|
||||
requestId: x.requestId,
|
||||
|
@ -117,7 +117,7 @@ export class IssueDetailsComponent implements OnInit {
|
|||
|
||||
} else {
|
||||
this.imageService.getTvBackground(Number(issue.providerId)).subscribe(x => {
|
||||
if(x) {
|
||||
if (x) {
|
||||
this.backgroundPath = this.sanitizer.bypassSecurityTrustStyle
|
||||
("url(" + x + ")");
|
||||
}
|
||||
|
|
|
@ -61,5 +61,4 @@ export class IssuesComponent implements OnInit {
|
|||
this.resolvedIssues = x;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ export class LoginComponent implements OnDestroy, OnInit {
|
|||
public loginWithOmbi: boolean;
|
||||
|
||||
public get appName(): string {
|
||||
if(this.customizationSettings.applicationName) {
|
||||
if (this.customizationSettings.applicationName) {
|
||||
return this.customizationSettings.applicationName;
|
||||
} else {
|
||||
return "Ombi";
|
||||
|
@ -72,7 +72,7 @@ export class LoginComponent implements OnDestroy, OnInit {
|
|||
}
|
||||
});
|
||||
|
||||
if(authService.loggedIn()) {
|
||||
if (authService.loggedIn()) {
|
||||
this.router.navigate(["search"]);
|
||||
}
|
||||
}
|
||||
|
@ -103,9 +103,9 @@ export class LoginComponent implements OnDestroy, OnInit {
|
|||
return;
|
||||
}
|
||||
const value = form.value;
|
||||
const user = { password: value.password, username: value.username, rememberMe: value.rememberMe, usePlexOAuth: false, plexTvPin: { id: 0, code: ""} };
|
||||
const user = { password: value.password, username: value.username, rememberMe: value.rememberMe, usePlexOAuth: false, plexTvPin: { id: 0, code: "" } };
|
||||
this.authService.requiresPassword(user).subscribe(x => {
|
||||
if(x && this.authenticationSettings.allowNoPassword) {
|
||||
if (x && this.authenticationSettings.allowNoPassword) {
|
||||
// Looks like this user requires a password
|
||||
this.authenticationSettings.allowNoPassword = false;
|
||||
return;
|
||||
|
@ -125,9 +125,9 @@ export class LoginComponent implements OnDestroy, OnInit {
|
|||
}
|
||||
|
||||
public oauth() {
|
||||
this.plexTv.GetPin(this.clientId, this.appName).subscribe(pin => {
|
||||
this.plexTv.GetPin(this.clientId, this.appName).subscribe((pin: any) => {
|
||||
|
||||
this.authService.login({usePlexOAuth: true, password:"",rememberMe:true,username:"", plexTvPin: pin}).subscribe(x => {
|
||||
this.authService.login({ usePlexOAuth: true, password: "", rememberMe: true, username: "", plexTvPin: pin }).subscribe(x => {
|
||||
if (window.frameElement) {
|
||||
// in frame
|
||||
window.open(x.url, "_blank");
|
||||
|
|
|
@ -16,7 +16,6 @@ export class LoginOAuthComponent implements OnInit {
|
|||
this.route.params
|
||||
.subscribe((params: any) => {
|
||||
this.pin = params.pin;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -26,7 +25,7 @@ export class LoginOAuthComponent implements OnInit {
|
|||
|
||||
public auth() {
|
||||
this.authService.oAuth(this.pin).subscribe(x => {
|
||||
if(x.access_token) {
|
||||
if (x.access_token) {
|
||||
localStorage.setItem("id_token", x.access_token);
|
||||
|
||||
if (this.authService.loggedIn()) {
|
||||
|
@ -34,13 +33,12 @@ export class LoginOAuthComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if(x.errorMessage) {
|
||||
if (x.errorMessage) {
|
||||
this.error = x.errorMessage;
|
||||
}
|
||||
|
||||
}, err => {
|
||||
this.notify.error(err.statusText);
|
||||
|
||||
this.router.navigate(["login"]);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms";
|
|||
import { DomSanitizer } from "@angular/platform-browser";
|
||||
|
||||
import { ICustomizationSettings } from "../interfaces";
|
||||
import { IdentityService, ImageService,NotificationService, SettingsService } from "../services";
|
||||
import { IdentityService, ImageService, NotificationService, SettingsService } from "../services";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./resetpassword.component.html",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { NguCarousel } from "@ngu/carousel";
|
||||
import { NguCarouselConfig } from "@ngu/carousel";
|
||||
|
||||
import { ImageService, RecentlyAddedService } from "../services";
|
||||
import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "./../interfaces";
|
||||
|
@ -43,7 +43,7 @@ export class RecentlyAddedComponent implements OnInit {
|
|||
public groupTv: boolean = false;
|
||||
|
||||
// https://github.com/sheikalthaf/ngu-carousel
|
||||
public carouselTile: NguCarousel;
|
||||
public carouselTile: NguCarouselConfig;
|
||||
|
||||
constructor(private recentlyAddedService: RecentlyAddedService,
|
||||
private imageService: ImageService) {}
|
||||
|
@ -67,10 +67,10 @@ export class RecentlyAddedComponent implements OnInit {
|
|||
}
|
||||
|
||||
public close() {
|
||||
if(this.range.length < 2) {
|
||||
if (this.range.length < 2) {
|
||||
return;
|
||||
}
|
||||
if(!this.range[1]) {
|
||||
if (!this.range[1]) {
|
||||
// If we do not have a second date then just set it to now
|
||||
this.range[1] = new Date();
|
||||
}
|
||||
|
@ -82,13 +82,13 @@ export class RecentlyAddedComponent implements OnInit {
|
|||
}
|
||||
|
||||
private getShows() {
|
||||
if(this.groupTv) {
|
||||
if (this.groupTv) {
|
||||
this.recentlyAddedService.getRecentlyAddedTvGrouped().subscribe(x => {
|
||||
this.tv = x;
|
||||
|
||||
this.tv.forEach((t) => {
|
||||
this.imageService.getTvPoster(t.tvDbId).subscribe(p => {
|
||||
if(p) {
|
||||
if (p) {
|
||||
t.posterPath = p;
|
||||
}
|
||||
});
|
||||
|
@ -100,7 +100,7 @@ export class RecentlyAddedComponent implements OnInit {
|
|||
|
||||
this.tv.forEach((t) => {
|
||||
this.imageService.getTvPoster(t.tvDbId).subscribe(p => {
|
||||
if(p) {
|
||||
if (p) {
|
||||
t.posterPath = p;
|
||||
}
|
||||
});
|
||||
|
@ -114,11 +114,11 @@ export class RecentlyAddedComponent implements OnInit {
|
|||
this.movies = x;
|
||||
|
||||
this.movies.forEach((movie) => {
|
||||
if(movie.theMovieDbId) {
|
||||
if (movie.theMovieDbId) {
|
||||
this.imageService.getMoviePoster(movie.theMovieDbId).subscribe(p => {
|
||||
movie.posterPath = p;
|
||||
});
|
||||
} else if(movie.imdbId) {
|
||||
} else if (movie.imdbId) {
|
||||
this.imageService.getMoviePoster(movie.imdbId).subscribe(p => {
|
||||
movie.posterPath = p;
|
||||
});
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
|
||||
|
||||
<div>
|
||||
|
||||
|
||||
<div *ngFor="let request of movieRequests">
|
||||
<div class="row">
|
||||
<div class="myBg backdrop" [style.background-image]="request.backgroundPath"></div>
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
import { DomSanitizer } from "@angular/platform-browser";
|
||||
import "rxjs/add/operator/debounceTime";
|
||||
import "rxjs/add/operator/distinctUntilChanged";
|
||||
import "rxjs/add/operator/map";
|
||||
import { Subject } from "rxjs/Subject";
|
||||
import { Subject } from "rxjs";
|
||||
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
|
||||
|
||||
import { AuthService } from "../auth/auth.service";
|
||||
import { NotificationService, RadarrService, RequestService } from "../services";
|
||||
|
||||
import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces";
|
||||
import { NotificationService, RadarrService, RequestService } from "../services";
|
||||
|
||||
@Component({
|
||||
selector: "movie-requests",
|
||||
|
@ -45,16 +42,17 @@ export class MovieRequestsComponent implements OnInit {
|
|||
private currentlyLoaded: number;
|
||||
private amountToLoad: number;
|
||||
|
||||
constructor(private requestService: RequestService,
|
||||
constructor(
|
||||
private requestService: RequestService,
|
||||
private auth: AuthService,
|
||||
private notificationService: NotificationService,
|
||||
private radarrService: RadarrService,
|
||||
private sanitizer: DomSanitizer,
|
||||
private readonly platformLocation: PlatformLocation) {
|
||||
this.searchChanged
|
||||
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
||||
.distinctUntilChanged() // only emit if value is different from previous value
|
||||
.subscribe(x => {
|
||||
this.searchChanged.pipe(
|
||||
debounceTime(600), // Wait Xms after the last event before emitting last event
|
||||
distinctUntilChanged(), // only emit if value is different from previous value
|
||||
).subscribe(x => {
|
||||
this.searchText = x as string;
|
||||
if (this.searchText === "") {
|
||||
this.resetSearch();
|
||||
|
@ -102,7 +100,7 @@ export class MovieRequestsComponent implements OnInit {
|
|||
public changeAvailability(request: IMovieRequests, available: boolean) {
|
||||
request.available = available;
|
||||
|
||||
if(available) {
|
||||
if (available) {
|
||||
this.requestService.markMovieAvailable({ id: request.id }).subscribe(x => {
|
||||
if (x.result) {
|
||||
this.notificationService.success(
|
||||
|
@ -241,7 +239,7 @@ export class MovieRequestsComponent implements OnInit {
|
|||
this.requestService.getMovieRequests(amountToLoad, currentlyLoaded, this.orderType, this.filter)
|
||||
.subscribe(x => {
|
||||
this.setOverrides(x.collection);
|
||||
if(!this.movieRequests) {
|
||||
if (!this.movieRequests) {
|
||||
this.movieRequests = [];
|
||||
}
|
||||
this.movieRequests = x.collection;
|
||||
|
|
|
@ -4,7 +4,7 @@ import { IChildRequests } from "../interfaces";
|
|||
import { NotificationService, RequestService } from "../services";
|
||||
|
||||
@Component({
|
||||
selector:"tvrequests-children",
|
||||
selector: "tvrequests-children",
|
||||
templateUrl: "./tvrequest-children.component.html",
|
||||
})
|
||||
export class TvRequestChildrenComponent {
|
||||
|
@ -26,12 +26,12 @@ export class TvRequestChildrenComponent {
|
|||
|
||||
public changeAvailability(request: IChildRequests, available: boolean) {
|
||||
request.available = available;
|
||||
request.seasonRequests.forEach((season)=> {
|
||||
season.episodes.forEach((ep)=> {
|
||||
request.seasonRequests.forEach((season) => {
|
||||
season.episodes.forEach((ep) => {
|
||||
ep.available = available;
|
||||
});
|
||||
});
|
||||
if(available) {
|
||||
if (available) {
|
||||
this.requestService.markTvAvailable({ id: request.id }).subscribe(x => {
|
||||
if (x.result) {
|
||||
this.notificationService.success(
|
||||
|
|
|
@ -4,59 +4,41 @@
|
|||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<!--TODO: I believe this +1 is causing off by one error skipping loading of tv shows
|
||||
When removed and scrolling very slowly everything works as expected, however
|
||||
if you scroll really quickly then you start getting duplicates of movies
|
||||
since it's async and some subsequent results return first and then incrementer
|
||||
is increased so you see movies which had already been gotten show up...
|
||||
|
||||
Removing infinte-scroll and setting max to 1000 till we work out some sort of fix
|
||||
|
||||
-->
|
||||
<!--<div infinite-scroll
|
||||
[infiniteScrollDistance]="1"
|
||||
[infiniteScrollThrottle]="100"
|
||||
(scrolled)="loadMore()">-->
|
||||
<div>
|
||||
<p-treeTable [value]="tvRequests">
|
||||
|
||||
<p-column>
|
||||
<ng-template let-col let-node="rowData" pTemplate="header">
|
||||
Results
|
||||
</ng-template>
|
||||
<ng-template let-col let-node="rowData" pTemplate="body">
|
||||
<div>
|
||||
<div *ngFor="let node of tvRequests.collection">
|
||||
<!--This is the section that holds the parent level results set-->
|
||||
<div *ngIf="!node.leaf">
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="myBg backdrop" [style.background-image]="node?.data?.background"></div>
|
||||
<div class="myBg backdrop" [style.background-image]="node?.background"></div>
|
||||
<div class="tint" style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%);"></div>
|
||||
|
||||
<div class="col-sm-2 small-padding" >
|
||||
<div class="col-sm-2 small-padding">
|
||||
|
||||
<img class="img-responsive poster" src="{{node.data.posterPath || null}}" alt="poster">
|
||||
<img class="img-responsive poster" src="{{node.posterPath || null}}" alt="poster">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-sm-5 small-padding">
|
||||
<div>
|
||||
<a href="http://www.imdb.com/title/{{node.data.imdbId}}/" target="_blank">
|
||||
<h4 class="request-title">{{node.data.title}} ({{node.data.releaseDate | date: 'yyyy'}})</h4>
|
||||
<a href="http://www.imdb.com/title/{{node.imdbId}}/" target="_blank">
|
||||
<h4 class="request-title">{{node.title}} ({{node.releaseDate | date: 'yyyy'}})</h4>
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<span>Status: </span>
|
||||
<span class="label label-success">{{node.data.status}}</span>
|
||||
<span class="label label-success">{{node.status}}</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div>Release Date: {{node.data.releaseDate | date}}</div>
|
||||
<div>Release Date: {{node.releaseDate | date}}</div>
|
||||
<div *ngIf="isAdmin">
|
||||
<div *ngIf="node.data.qualityOverrideTitle" class="quality-override">{{ 'Requests.QualityOverride' | translate }}
|
||||
<span>{{node.data.qualityOverrideTitle}} </span>
|
||||
<div *ngIf="node.qualityOverrideTitle" class="quality-override">{{ 'Requests.QualityOverride' | translate }}
|
||||
<span>{{node.qualityOverrideTitle}} </span>
|
||||
</div>
|
||||
<div *ngIf="node.data.rootPathOverrideTitle" class="root-override">{{ 'Requests.RootFolderOverride' | translate }}
|
||||
<span>{{node.data.rootPathOverrideTitle}} </span>
|
||||
<div *ngIf="node.rootPathOverrideTitle" class="root-override">{{ 'Requests.RootFolderOverride' | translate }}
|
||||
<span>{{node.rootPathOverrideTitle}} </span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -64,7 +46,8 @@
|
|||
</div>
|
||||
<div class="col-sm-3 col-sm-push-3 small-padding">
|
||||
|
||||
<button style="text-align: right" class="btn btn-sm btn-success-outline" (click)="openClosestTab($event)"><i class="fa fa-plus"></i> View</button>
|
||||
<button style="text-align: right" class="btn btn-sm btn-success-outline" (click)="openClosestTab(node,$event)">
|
||||
<i class="fa fa-plus"></i> View</button>
|
||||
<div *ngIf="isAdmin">
|
||||
<!--Sonarr Root Folder-->
|
||||
<div *ngIf="sonarrRootFolders" class="btn-group btn-split" id="rootFolderBtn">
|
||||
|
@ -77,7 +60,7 @@
|
|||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li *ngFor="let folder of sonarrRootFolders">
|
||||
<a href="#" (click)="selectRootFolder(node.data, folder, $event)">{{folder.path}}</a>
|
||||
<a href="#" (click)="selectRootFolder(node, folder, $event)">{{folder.path}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -93,35 +76,39 @@
|
|||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li *ngFor="let profile of sonarrProfiles">
|
||||
<a href="#" (click)="selectQualityProfile(node.data, profile, $event)">{{profile.name}}</a>
|
||||
<a href="#" (click)="selectQualityProfile(node, profile, $event)">{{profile.name}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issueBtn">
|
||||
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<button 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> {{ 'Requests.ReportIssue' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li *ngFor="let cat of issueCategories"><a [routerLink]="" (click)="reportIssue(cat, node.data)">{{cat.value}}</a></li>
|
||||
<li *ngFor="let cat of issueCategories">
|
||||
<a [routerLink]="" (click)="reportIssue(cat, node)">{{cat.value}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--This is the section that holds the child seasons if they want to specify specific episodes-->
|
||||
<div *ngIf="node.leaf">
|
||||
<tvrequests-children [childRequests]="node.data" [isAdmin] ="isAdmin"
|
||||
(requestDeleted)="childRequestDeleted($event)"></tvrequests-children>
|
||||
<div *ngIf="node.open">
|
||||
<tvrequests-children [childRequests]="node.childRequests" [isAdmin]="isAdmin" (requestDeleted)="childRequestDeleted($event)"></tvrequests-children>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</div>
|
||||
</ng-template>
|
||||
</p-column>
|
||||
</p-treeTable>
|
||||
|
||||
<p-paginator [rows]="10" [totalRecords]="totalTv" (onPageChange)="paginate($event)"></p-paginator>
|
||||
</div>
|
||||
|
||||
<issue-report [movie]="false" [visible]="issuesBarVisible" [title]="issueRequest?.title"
|
||||
[issueCategory]="issueCategorySelected" [id]="issueRequest?.id" [providerId]="issueProviderId" (visibleChange)="issuesBarVisible = $event;"></issue-report>
|
||||
<issue-report [movie]="false" [visible]="issuesBarVisible" [title]="issueRequest?.title" [issueCategory]="issueCategorySelected"
|
||||
[id]="issueRequest?.id" [providerId]="issueProviderId" (visibleChange)="issuesBarVisible = $event;"></issue-report>
|
|
@ -1,21 +1,13 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
import { DomSanitizer } from "@angular/platform-browser";
|
||||
import "rxjs/add/operator/debounceTime";
|
||||
import "rxjs/add/operator/distinctUntilChanged";
|
||||
import "rxjs/add/operator/map";
|
||||
import { Subject } from "rxjs/Subject";
|
||||
import { ImageService } from "./../services/image.service";
|
||||
|
||||
import "rxjs/add/operator/debounceTime";
|
||||
import "rxjs/add/operator/distinctUntilChanged";
|
||||
import "rxjs/add/operator/map";
|
||||
import { Subject } from "rxjs";
|
||||
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
|
||||
|
||||
import { AuthService } from "../auth/auth.service";
|
||||
import { FilterType, IIssueCategory, IPagenator, IRequestsViewModel, ISonarrProfile, ISonarrRootFolder, ITvRequests, OrderType } from "../interfaces";
|
||||
import { NotificationService, RequestService, SonarrService } from "../services";
|
||||
|
||||
import { TreeNode } from "primeng/primeng";
|
||||
import { IIssueCategory, IPagenator, ISonarrProfile, ISonarrRootFolder, ITvRequests } from "../interfaces";
|
||||
import { ImageService } from "./../services/image.service";
|
||||
|
||||
@Component({
|
||||
selector: "tv-requests",
|
||||
|
@ -24,7 +16,7 @@ import { IIssueCategory, IPagenator, ISonarrProfile, ISonarrRootFolder, ITvRequ
|
|||
})
|
||||
export class TvRequestsComponent implements OnInit {
|
||||
|
||||
public tvRequests: TreeNode[];
|
||||
public tvRequests: IRequestsViewModel<ITvRequests>;
|
||||
public searchChanged = new Subject<string>();
|
||||
public searchText: string;
|
||||
public isAdmin: boolean;
|
||||
|
@ -46,27 +38,28 @@ export class TvRequestsComponent implements OnInit {
|
|||
private currentlyLoaded: number;
|
||||
private amountToLoad: number;
|
||||
|
||||
constructor(private requestService: RequestService,
|
||||
constructor(
|
||||
private requestService: RequestService,
|
||||
private auth: AuthService,
|
||||
private sanitizer: DomSanitizer,
|
||||
private imageService: ImageService,
|
||||
private sonarrService: SonarrService,
|
||||
private notificationService: NotificationService,
|
||||
private readonly platformLocation: PlatformLocation) {
|
||||
this.searchChanged
|
||||
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
||||
.distinctUntilChanged() // only emit if value is different from previous value
|
||||
.subscribe(x => {
|
||||
this.searchChanged.pipe(
|
||||
debounceTime(600), // Wait Xms after the last event before emitting last event
|
||||
distinctUntilChanged(), // only emit if value is different from previous value
|
||||
).subscribe(x => {
|
||||
this.searchText = x as string;
|
||||
if (this.searchText === "") {
|
||||
this.resetSearch();
|
||||
return;
|
||||
}
|
||||
this.requestService.searchTvRequestsTree(this.searchText)
|
||||
this.requestService.searchTvRequests(this.searchText)
|
||||
.subscribe(m => {
|
||||
this.tvRequests = m;
|
||||
this.tvRequests.forEach((val) => this.loadBackdrop(val));
|
||||
this.tvRequests.forEach((val) => this.setOverride(val.data));
|
||||
this.tvRequests.collection = m;
|
||||
this.tvRequests.collection.forEach((val) => this.loadBackdrop(val));
|
||||
this.tvRequests.collection.forEach((val) => this.setOverride(val));
|
||||
});
|
||||
});
|
||||
this.defaultPoster = "../../../images/default_tv_poster.png";
|
||||
|
@ -76,47 +69,15 @@ export class TvRequestsComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
public openClosestTab(el: any) {
|
||||
const rowclass = "undefined ng-star-inserted";
|
||||
el = el.toElement || el.relatedTarget || el.target || el.srcElement;
|
||||
|
||||
if (el.nodeName === "BUTTON") {
|
||||
|
||||
const isButtonAlreadyActive = el.parentElement.querySelector(".active");
|
||||
// if a Button already has Class: .active
|
||||
if (isButtonAlreadyActive) {
|
||||
isButtonAlreadyActive.classList.remove("active");
|
||||
} else {
|
||||
el.className += " active";
|
||||
}
|
||||
}
|
||||
|
||||
while (el.className !== rowclass) {
|
||||
// Increment the loop to the parent node until we find the row we need
|
||||
el = el.parentNode;
|
||||
}
|
||||
// At this point, the while loop has stopped and `el` represents the element that has
|
||||
// the class you specified
|
||||
|
||||
// Then we loop through the children to find the caret which we want to click
|
||||
const caretright = "fa-caret-right";
|
||||
const caretdown = "fa-caret-down";
|
||||
for (const value of el.children) {
|
||||
// the caret from the ui has 2 class selectors depending on if expanded or not
|
||||
// we search for both since we want to still toggle the clicking
|
||||
if (value.className.includes(caretright) || value.className.includes(caretdown)) {
|
||||
// Then we tell JS to click the element even though we hid it from the UI
|
||||
value.click();
|
||||
//Break from loop since we no longer need to continue looking
|
||||
break;
|
||||
}
|
||||
}
|
||||
public openClosestTab(node: ITvRequests,el: any) {
|
||||
el.preventDefault();
|
||||
node.open = !node.open;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
this.amountToLoad = 10;
|
||||
this.currentlyLoaded = 10;
|
||||
this.tvRequests = [];
|
||||
this.tvRequests = {collection:[], total:0};
|
||||
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
|
||||
|
||||
this.loadInit();
|
||||
|
@ -125,7 +86,7 @@ export class TvRequestsComponent implements OnInit {
|
|||
public paginate(event: IPagenator) {
|
||||
const skipAmount = event.first;
|
||||
|
||||
this.requestService.getTvRequestsTree(this.amountToLoad, skipAmount)
|
||||
this.requestService.getTvRequests(this.amountToLoad, skipAmount, OrderType.RequestedDateDesc, FilterType.None, FilterType.None)
|
||||
.subscribe(x => {
|
||||
this.tvRequests = x;
|
||||
this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad;
|
||||
|
@ -204,17 +165,17 @@ export class TvRequestsComponent implements OnInit {
|
|||
|
||||
private loadInit() {
|
||||
this.requestService.getTotalTv().subscribe(x => this.totalTv = x);
|
||||
this.requestService.getTvRequestsTree(this.amountToLoad, 0)
|
||||
this.requestService.getTvRequests(this.amountToLoad, 0, OrderType.RequestedDateDesc, FilterType.None, FilterType.None)
|
||||
.subscribe(x => {
|
||||
this.tvRequests = x;
|
||||
this.tvRequests.forEach((val, index) => {
|
||||
this.tvRequests.collection.forEach((val, index) => {
|
||||
this.setDefaults(val);
|
||||
this.loadBackdrop(val);
|
||||
this.setOverride(val.data);
|
||||
this.setOverride(val);
|
||||
});
|
||||
});
|
||||
|
||||
if(this.isAdmin) {
|
||||
if (this.isAdmin) {
|
||||
this.sonarrService.getQualityProfilesWithoutSettings()
|
||||
.subscribe(x => this.sonarrProfiles = x);
|
||||
|
||||
|
@ -228,20 +189,20 @@ export class TvRequestsComponent implements OnInit {
|
|||
this.loadInit();
|
||||
}
|
||||
|
||||
private setDefaults(val: any) {
|
||||
if (val.data.posterPath === null) {
|
||||
val.data.posterPath = this.defaultPoster;
|
||||
private setDefaults(val: ITvRequests) {
|
||||
if (val.posterPath === null) {
|
||||
val.posterPath = this.defaultPoster;
|
||||
}
|
||||
}
|
||||
|
||||
private loadBackdrop(val: TreeNode): void {
|
||||
if (val.data.background != null) {
|
||||
val.data.background = this.sanitizer.bypassSecurityTrustStyle
|
||||
("url(https://image.tmdb.org/t/p/w1280" + val.data.background + ")");
|
||||
private loadBackdrop(val: ITvRequests): void {
|
||||
if (val.background != null) {
|
||||
val.background = this.sanitizer.bypassSecurityTrustStyle
|
||||
("url(https://image.tmdb.org/t/p/w1280" + val.background + ")");
|
||||
} else {
|
||||
this.imageService.getTvBanner(val.data.tvDbId).subscribe(x => {
|
||||
if(x) {
|
||||
val.data.background = this.sanitizer.bypassSecurityTrustStyle
|
||||
this.imageService.getTvBanner(val.tvDbId).subscribe(x => {
|
||||
if (x) {
|
||||
val.background = this.sanitizer.bypassSecurityTrustStyle
|
||||
("url(" + x + ")");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
import { DomSanitizer } from "@angular/platform-browser";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
import "rxjs/add/operator/debounceTime";
|
||||
import "rxjs/add/operator/distinctUntilChanged";
|
||||
import "rxjs/add/operator/map";
|
||||
import { Subject } from "rxjs/Subject";
|
||||
import { Subject } from "rxjs";
|
||||
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
|
||||
|
||||
import { AuthService } from "../auth/auth.service";
|
||||
import { IIssueCategory, IRequestEngineResult, ISearchMovieResult } from "../interfaces";
|
||||
|
@ -32,15 +30,16 @@ export class MovieSearchComponent implements OnInit {
|
|||
public issueCategorySelected: IIssueCategory;
|
||||
public defaultPoster: string;
|
||||
|
||||
constructor(private searchService: SearchService, private requestService: RequestService,
|
||||
constructor(
|
||||
private searchService: SearchService, private requestService: RequestService,
|
||||
private notificationService: NotificationService, private authService: AuthService,
|
||||
private readonly translate: TranslateService, private sanitizer: DomSanitizer,
|
||||
private readonly platformLocation: PlatformLocation) {
|
||||
|
||||
this.searchChanged
|
||||
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
||||
.distinctUntilChanged() // only emit if value is different from previous value
|
||||
.subscribe(x => {
|
||||
this.searchChanged.pipe(
|
||||
debounceTime(600), // Wait Xms after the last event before emitting last event
|
||||
distinctUntilChanged(), // only emit if value is different from previous value
|
||||
).subscribe(x => {
|
||||
this.searchText = x as string;
|
||||
if (this.searchText === "") {
|
||||
this.clearResults();
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import "rxjs/add/operator/debounceTime";
|
||||
import "rxjs/add/operator/distinctUntilChanged";
|
||||
import "rxjs/add/operator/map";
|
||||
import { Subject } from "rxjs/Subject";
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { Subject } from "rxjs";
|
||||
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
|
||||
|
||||
import { AuthService } from "../auth/auth.service";
|
||||
import { NotificationService, RequestService, SearchService } from "../services";
|
||||
|
||||
import { IRequestEngineResult, ISearchMovieResult, ISearchMovieResultContainer } from "../interfaces";
|
||||
import { NotificationService, RequestService, SearchService } from "../services";
|
||||
|
||||
@Component({
|
||||
selector: "movie-search-grid",
|
||||
|
@ -22,13 +19,14 @@ export class MovieSearchGridComponent implements OnInit {
|
|||
public result: IRequestEngineResult;
|
||||
public searchApplied = false;
|
||||
|
||||
constructor(private searchService: SearchService, private requestService: RequestService,
|
||||
constructor(
|
||||
private searchService: SearchService, private requestService: RequestService,
|
||||
private notificationService: NotificationService, private authService: AuthService) {
|
||||
|
||||
this.searchChanged
|
||||
.debounceTime(600) // Wait Xms afterthe last event before emitting last event
|
||||
.distinctUntilChanged() // only emit if value is different from previous value
|
||||
.subscribe(x => {
|
||||
this.searchChanged.pipe(
|
||||
debounceTime(600), // Wait Xms afterthe last event before emitting last event
|
||||
distinctUntilChanged(), // only emit if value is different from previous value
|
||||
).subscribe(x => {
|
||||
this.searchText = x as string;
|
||||
if (this.searchText === "") {
|
||||
this.clearResults();
|
||||
|
@ -67,7 +65,7 @@ export class MovieSearchGridComponent implements OnInit {
|
|||
}
|
||||
|
||||
try {
|
||||
this.requestService.requestMovie({ theMovieDbId : searchResult.id})
|
||||
this.requestService.requestMovie({ theMovieDbId: searchResult.id })
|
||||
.subscribe(x => {
|
||||
this.result = x;
|
||||
|
||||
|
@ -149,15 +147,14 @@ export class MovieSearchGridComponent implements OnInit {
|
|||
}
|
||||
|
||||
private processGrid(movies: ISearchMovieResult[]) {
|
||||
let container = <ISearchMovieResultContainer>{ movies: [] };
|
||||
let container = <ISearchMovieResultContainer> { movies: [] };
|
||||
movies.forEach((movie, i) => {
|
||||
i++;
|
||||
if((i % 4) === 0) {
|
||||
if ((i % 4) === 0) {
|
||||
container.movies.push(movie);
|
||||
this.movieResultGrid.push(container);
|
||||
container = <ISearchMovieResultContainer>{ movies: [] };
|
||||
container = <ISearchMovieResultContainer> { movies: [] };
|
||||
} else {
|
||||
|
||||
container.movies.push(movie);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { Component, Input, OnInit} from "@angular/core";
|
||||
import "rxjs/add/operator/takeUntil";
|
||||
|
||||
import { NotificationService } from "../services";
|
||||
import { RequestService } from "../services";
|
||||
|
@ -39,20 +38,20 @@ export class SeriesInformationComponent implements OnInit {
|
|||
});
|
||||
});
|
||||
|
||||
if(!selected) {
|
||||
if (!selected) {
|
||||
this.notificationService.error("You need to select some episodes!");
|
||||
return;
|
||||
}
|
||||
|
||||
this.series.requested = true;
|
||||
|
||||
const viewModel = <ITvRequestViewModel>{ firstSeason: this.series.firstSeason, latestSeason: this.series.latestSeason, requestAll: this.series.requestAll, tvDbId: this.series.id};
|
||||
const viewModel = <ITvRequestViewModel> { firstSeason: this.series.firstSeason, latestSeason: this.series.latestSeason, requestAll: this.series.requestAll, tvDbId: this.series.id};
|
||||
viewModel.seasons = [];
|
||||
this.series.seasonRequests.forEach((season) => {
|
||||
const seasonsViewModel = <ISeasonsViewModel>{seasonNumber: season.seasonNumber, episodes: []};
|
||||
const seasonsViewModel = <ISeasonsViewModel> {seasonNumber: season.seasonNumber, episodes: []};
|
||||
season.episodes.forEach(ep => {
|
||||
if(!this.series.latestSeason || !this.series.requestAll || !this.series.firstSeason) {
|
||||
if(ep.selected) {
|
||||
if (!this.series.latestSeason || !this.series.requestAll || !this.series.firstSeason) {
|
||||
if (ep.selected) {
|
||||
seasonsViewModel.episodes.push({episodeNumber: ep.episodeNumber});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,46 +42,46 @@
|
|||
<i class='fa fa-film no-search-results-icon'></i>
|
||||
<div class='no-search-results-text'>{{ 'Search.NoResults' | translate }}</div>
|
||||
</div>
|
||||
<p-treeTable [value]="tvResults">
|
||||
<p-column>
|
||||
<ng-template let-col let-node="rowData" pTemplate="header">
|
||||
{{ 'Search.TvShows.Results' | translate }}
|
||||
</ng-template>
|
||||
<ng-template let-col let-node="rowData" pTemplate="body">
|
||||
<div *ngIf="tvResults" >
|
||||
<div *ngFor="let node of tvResults">
|
||||
<!--This is the section that holds the parent level search results set-->
|
||||
<div *ngIf="!node.leaf">
|
||||
<div class="row" >
|
||||
<div *ngIf="node">
|
||||
<div class="row">
|
||||
|
||||
<div class="myBg backdrop" [style.background-image]="node?.data?.background"></div>
|
||||
<div class="myBg backdrop" [style.background-image]="node?.background"></div>
|
||||
<div class="tint" style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%);"></div>
|
||||
<div class="col-sm-2 small-padding">
|
||||
|
||||
<img *ngIf="node?.data?.banner" class="img-responsive poster" width="150" [src]="node.data.banner" alt="poster">
|
||||
<img *ngIf="node.banner" class="img-responsive poster" width="150" [src]="node.banner" alt="poster">
|
||||
|
||||
</div>
|
||||
<div class="col-sm-8 small-padding">
|
||||
<div>
|
||||
|
||||
<a *ngIf="node.data.imdbId" href="{{node.data.imdbId}}" target="_blank">
|
||||
<h4>{{node.data.title}} ({{node.data.firstAired | date: 'yyyy'}})</h4>
|
||||
<a *ngIf="node.imdbId" href="{{node.imdbId}}" target="_blank">
|
||||
<h4>{{node.title}} ({{node.firstAired | date: 'yyyy'}})</h4>
|
||||
|
||||
</a>
|
||||
<span class="tags">
|
||||
<a *ngIf="node.data.homepage" id="homepageLabel" href="{{node.data.homepage}}" target="_blank"><span class="label label-info" >{{ 'Search.Movies.HomePage' | translate }}</span></a>
|
||||
<a *ngIf="node.homepage" id="homepageLabel" href="{{node.homepage}}" target="_blank">
|
||||
<span class="label label-info">{{ 'Search.Movies.HomePage' | translate }}</span>
|
||||
</a>
|
||||
|
||||
<a *ngIf="node.data.trailer" id="trailerLabel" href="{{node.data.trailer}}" target="_blank"><span class="label label-info">{{ 'Search.Movies.Trailer' | translate }}</span></a>
|
||||
<a *ngIf="node.trailer" id="trailerLabel" href="{{node.trailer}}" target="_blank">
|
||||
<span class="label label-info">{{ 'Search.Movies.Trailer' | translate }}</span>
|
||||
</a>
|
||||
|
||||
<span *ngIf="node.data.status" class="label label-primary" id="statusLabel" target="_blank">{{node.data.status}}</span>
|
||||
<span *ngIf="node.status" class="label label-primary" id="statusLabel" target="_blank">{{node.status}}</span>
|
||||
|
||||
|
||||
<span *ngIf="node.data.firstAired" class="label label-info" target="_blank" id="airDateLabel">{{ 'Search.TvShows.AirDate' | translate }} {{node.data.firstAired | date: 'dd/MM/yyyy'}}</span>
|
||||
<span *ngIf="node.firstAired" class="label label-info" target="_blank" id="airDateLabel">{{ 'Search.TvShows.AirDate' | translate }} {{node.firstAired | date: 'dd/MM/yyyy'}}</span>
|
||||
|
||||
<span *ngIf="node.data.network" class="label label-info" id="networkLabel" target="_blank">{{node.data.network}}</span>
|
||||
<span *ngIf="node.network" class="label label-info" id="networkLabel" target="_blank">{{node.network}}</span>
|
||||
|
||||
|
||||
<span *ngIf="node.data.available" class="label label-success" id="availableLabel">{{ 'Common.Available' | translate }}</span>
|
||||
<span *ngIf="node.available" class="label label-success" id="availableLabel">{{ 'Common.Available' | translate }}</span>
|
||||
|
||||
<span *ngIf="node.data.partlyAvailable" class="label label-warning" id="partiallyAvailableLabel">{{ 'Common.PartlyAvailable' | translate }}</span>
|
||||
<span *ngIf="node.partlyAvailable" class="label label-warning" id="partiallyAvailableLabel">{{ 'Common.PartlyAvailable' | translate }}</span>
|
||||
|
||||
|
||||
|
||||
|
@ -90,47 +90,45 @@
|
|||
<br />
|
||||
<br />
|
||||
</div>
|
||||
<p class="tv-overview">{{node.data.overview}}</p>
|
||||
<p class="tv-overview">{{node.overview}}</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-2 small-padding">
|
||||
<div *ngIf="!node.data.fullyAvailable" class="dropdown">
|
||||
<div *ngIf="!node.fullyAvailable" class="dropdown">
|
||||
<button class="btn btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<i class="fa fa-plus"></i> {{ 'Common.Request' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li>
|
||||
<a href="#" (click)="allSeasons(node.data, $event)">{{ 'Search.TvShows.AllSeasons' | translate }}</a>
|
||||
<a href="#" (click)="allSeasons(node, $event)">{{ 'Search.TvShows.AllSeasons' | translate }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" (click)="firstSeason(node.data, $event)">{{ 'Search.TvShows.FirstSeason' | translate }}</a>
|
||||
<a href="#" (click)="firstSeason(node, $event)">{{ 'Search.TvShows.FirstSeason' | translate }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" (click)="latestSeason(node.data, $event)">{{ 'Search.TvShows.LatestSeason' | translate }}</a>
|
||||
<a href="#" (click)="latestSeason(node, $event)">{{ 'Search.TvShows.LatestSeason' | translate }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" (click)="openClosestTab($event)">{{ 'Search.TvShows.Select' | translate }}</a>
|
||||
<a href="#" (click)="openClosestTab(node, $event)">{{ 'Search.TvShows.Select' | translate }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div *ngIf="node.data.fullyAvailable">
|
||||
<div *ngIf="node.fullyAvailable">
|
||||
<button style="text-align: right" class="btn btn-success-outline disabled" disabled>
|
||||
<i class="fa fa-check"></i> {{ 'Common.Available' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<br />
|
||||
<div *ngIf="node.data.plexUrl && node.data.available">
|
||||
<a style="text-align: right" class="btn btn-sm btn-success-outline" href="{{node.data.plexUrl}}"
|
||||
target="_blank">
|
||||
<div *ngIf="node.plexUrl && node.available">
|
||||
<a style="text-align: right" class="btn btn-sm btn-success-outline" href="{{node.plexUrl}}" target="_blank">
|
||||
<i class="fa fa-eye"></i> {{ 'Search.ViewOnPlex' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
<div *ngIf="node.data.embyUrl && node.data.available">
|
||||
<a style="text-align: right" id="embybtn" class="btn btn-sm btn-success-outline" href="{{node.data.embyUrl}}"
|
||||
target="_blank">
|
||||
<div *ngIf="node.embyUrl && node.available">
|
||||
<a style="text-align: right" id="embybtn" class="btn btn-sm btn-success-outline" href="{{node.embyUrl}}" target="_blank">
|
||||
<i class="fa fa-eye"></i> {{ 'Search.ViewOnEmby' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
|
@ -142,11 +140,11 @@
|
|||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li *ngFor="let cat of issueCategories">
|
||||
<a [routerLink]="" (click)="reportIssue(cat, node.data)">{{cat.value}}</a>
|
||||
<a [routerLink]="" (click)="reportIssue(cat, node)">{{cat.value}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div *ngIf="!node.data.available">
|
||||
<div *ngIf="!node.available">
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
|
@ -156,15 +154,13 @@
|
|||
</div>
|
||||
</div>
|
||||
<!--This is the section that holds the child seasons if they want to specify specific episodes-->
|
||||
<div *ngIf="node.leaf">
|
||||
<seriesinformation [seriesId]="node.data.id"></seriesinformation>
|
||||
<div *ngIf="node.open">
|
||||
<seriesinformation [seriesId]="node.id"></seriesinformation>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
</ng-template>
|
||||
</p-column>
|
||||
</p-treeTable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
import { DomSanitizer } from "@angular/platform-browser";
|
||||
import { Subject } from "rxjs/Subject";
|
||||
import { Subject } from "rxjs";
|
||||
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
|
||||
|
||||
import { AuthService } from "../auth/auth.service";
|
||||
import { IIssueCategory, IRequestEngineResult, ISearchTvResult, ISeasonsViewModel, ITvRequestViewModel } from "../interfaces";
|
||||
import { ImageService, NotificationService, RequestService, SearchService } from "../services";
|
||||
|
||||
import { TreeNode } from "primeng/primeng";
|
||||
import { IRequestEngineResult } from "../interfaces";
|
||||
import { IIssueCategory, ISearchTvResult, ISeasonsViewModel, ITvRequestViewModel } from "../interfaces";
|
||||
|
||||
@Component({
|
||||
selector: "tv-search",
|
||||
templateUrl: "./tvsearch.component.html",
|
||||
|
@ -19,7 +17,7 @@ export class TvSearchComponent implements OnInit {
|
|||
|
||||
public searchText: string;
|
||||
public searchChanged = new Subject<string>();
|
||||
public tvResults: TreeNode[];
|
||||
public tvResults: ISearchTvResult[];
|
||||
public result: IRequestEngineResult;
|
||||
public searchApplied = false;
|
||||
public defaultPoster: string;
|
||||
|
@ -32,21 +30,22 @@ export class TvSearchComponent implements OnInit {
|
|||
public issueProviderId: string;
|
||||
public issueCategorySelected: IIssueCategory;
|
||||
|
||||
constructor(private searchService: SearchService, private requestService: RequestService,
|
||||
constructor(
|
||||
private searchService: SearchService, private requestService: RequestService,
|
||||
private notificationService: NotificationService, private authService: AuthService,
|
||||
private imageService: ImageService, private sanitizer: DomSanitizer,
|
||||
private readonly platformLocation: PlatformLocation) {
|
||||
|
||||
this.searchChanged
|
||||
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
||||
.distinctUntilChanged() // only emit if value is different from previous value
|
||||
.subscribe(x => {
|
||||
this.searchChanged.pipe(
|
||||
debounceTime(600), // Wait Xms after the last event before emitting last event
|
||||
distinctUntilChanged(), // only emit if value is different from previous value
|
||||
).subscribe(x => {
|
||||
this.searchText = x as string;
|
||||
if (this.searchText === "") {
|
||||
this.clearResults();
|
||||
return;
|
||||
}
|
||||
this.searchService.searchTvTreeNode(this.searchText)
|
||||
this.searchService.searchTv(this.searchText)
|
||||
.subscribe(x => {
|
||||
this.tvResults = x;
|
||||
this.searchApplied = true;
|
||||
|
@ -55,34 +54,13 @@ export class TvSearchComponent implements OnInit {
|
|||
});
|
||||
this.defaultPoster = "../../../images/default_tv_poster.png";
|
||||
const base = this.platformLocation.getBaseHrefFromDOM();
|
||||
if(base) {
|
||||
if (base) {
|
||||
this.defaultPoster = "../../.." + base + "/images/default_tv_poster.png";
|
||||
}
|
||||
}
|
||||
public openClosestTab(el: any) {
|
||||
public openClosestTab(node: ISearchTvResult,el: any) {
|
||||
el.preventDefault();
|
||||
const rowclass = "undefined ng-star-inserted";
|
||||
el = el.toElement || el.relatedTarget || el.target;
|
||||
while (el.className !== rowclass) {
|
||||
// Increment the loop to the parent node until we find the row we need
|
||||
el = el.parentNode;
|
||||
}
|
||||
// At this point, the while loop has stopped and `el` represents the element that has
|
||||
// the class you specified
|
||||
|
||||
// Then we loop through the children to find the caret which we want to click
|
||||
const caretright = "fa-caret-right";
|
||||
const caretdown = "fa-caret-down";
|
||||
for (const value of el.children) {
|
||||
// the caret from the ui has 2 class selectors depending on if expanded or not
|
||||
// we search for both since we want to still toggle the clicking
|
||||
if (value.className.includes(caretright) || value.className.includes(caretdown)) {
|
||||
// Then we tell JS to click the element even though we hid it from the UI
|
||||
value.click();
|
||||
//Break from loop since we no longer need to continue looking
|
||||
break;
|
||||
}
|
||||
}
|
||||
node.open = !node.open;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
|
@ -91,7 +69,7 @@ export class TvSearchComponent implements OnInit {
|
|||
this.result = {
|
||||
message: "",
|
||||
result: false,
|
||||
errorMessage:"",
|
||||
errorMessage: "",
|
||||
};
|
||||
this.popularShows();
|
||||
}
|
||||
|
@ -138,16 +116,16 @@ export class TvSearchComponent implements OnInit {
|
|||
|
||||
public getExtraInfo() {
|
||||
this.tvResults.forEach((val, index) => {
|
||||
this.imageService.getTvBanner(val.data.id).subscribe(x => {
|
||||
if(x) {
|
||||
val.data.background = this.sanitizer.
|
||||
this.imageService.getTvBanner(val.id).subscribe(x => {
|
||||
if (x) {
|
||||
val.background = this.sanitizer.
|
||||
bypassSecurityTrustStyle
|
||||
("url(" + x + ")");
|
||||
}
|
||||
});
|
||||
this.searchService.getShowInformationTreeNode(val.data.id)
|
||||
this.searchService.getShowInformation(val.id)
|
||||
.subscribe(x => {
|
||||
if (x.data) {
|
||||
if (x) {
|
||||
this.setDefaults(x);
|
||||
this.updateItem(val, x);
|
||||
} else {
|
||||
|
@ -166,14 +144,14 @@ export class TvSearchComponent implements OnInit {
|
|||
searchResult.approved = true;
|
||||
}
|
||||
|
||||
const viewModel = <ITvRequestViewModel>{ firstSeason: searchResult.firstSeason, latestSeason: searchResult.latestSeason, requestAll: searchResult.requestAll, tvDbId: searchResult.id};
|
||||
const viewModel = <ITvRequestViewModel> { firstSeason: searchResult.firstSeason, latestSeason: searchResult.latestSeason, requestAll: searchResult.requestAll, tvDbId: searchResult.id };
|
||||
viewModel.seasons = [];
|
||||
searchResult.seasonRequests.forEach((season) => {
|
||||
const seasonsViewModel = <ISeasonsViewModel>{seasonNumber: season.seasonNumber, episodes: []};
|
||||
const seasonsViewModel = <ISeasonsViewModel> { seasonNumber: season.seasonNumber, episodes: [] };
|
||||
season.episodes.forEach(ep => {
|
||||
if(!searchResult.latestSeason || !searchResult.requestAll || !searchResult.firstSeason) {
|
||||
if(ep.requested) {
|
||||
seasonsViewModel.episodes.push({episodeNumber: ep.episodeNumber});
|
||||
if (!searchResult.latestSeason || !searchResult.requestAll || !searchResult.firstSeason) {
|
||||
if (ep.requested) {
|
||||
seasonsViewModel.episodes.push({ episodeNumber: ep.episodeNumber });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -223,29 +201,29 @@ export class TvSearchComponent implements OnInit {
|
|||
this.issueProviderId = req.id.toString();
|
||||
}
|
||||
|
||||
private updateItem(key: TreeNode, updated: TreeNode) {
|
||||
private updateItem(key: ISearchTvResult, updated: ISearchTvResult) {
|
||||
const index = this.tvResults.indexOf(key, 0);
|
||||
if (index > -1) {
|
||||
// Update certain properties, otherwise we will loose some data
|
||||
this.tvResults[index].data.title = updated.data.title;
|
||||
this.tvResults[index].data.banner = updated.data.banner;
|
||||
this.tvResults[index].data.imdbId = updated.data.imdbId;
|
||||
this.tvResults[index].data.seasonRequests = updated.data.seasonRequests;
|
||||
this.tvResults[index].data.seriesId = updated.data.seriesId;
|
||||
this.tvResults[index].data.fullyAvailable = updated.data.fullyAvailable;
|
||||
this.tvResults[index].data.backdrop = updated.data.backdrop;
|
||||
this.tvResults[index].title = updated.title;
|
||||
this.tvResults[index].banner = updated.banner;
|
||||
this.tvResults[index].imdbId = updated.imdbId;
|
||||
this.tvResults[index].seasonRequests = updated.seasonRequests;
|
||||
this.tvResults[index].seriesId = updated.seriesId;
|
||||
this.tvResults[index].fullyAvailable = updated.fullyAvailable;
|
||||
this.tvResults[index].background = updated.banner;
|
||||
}
|
||||
}
|
||||
|
||||
private setDefaults(x: any) {
|
||||
if (x.data.banner === null) {
|
||||
x.data.banner = this.defaultPoster;
|
||||
private setDefaults(x: ISearchTvResult) {
|
||||
if (x.banner === null) {
|
||||
x.banner = this.defaultPoster;
|
||||
}
|
||||
|
||||
if (x.data.imdbId === null) {
|
||||
x.data.imdbId = "https://www.tvmaze.com/shows/" + x.data.seriesId;
|
||||
if (x.imdbId === null) {
|
||||
x.imdbId = "https://www.tvmaze.com/shows/" + x.seriesId;
|
||||
} else {
|
||||
x.data.imdbId = "http://www.imdb.com/title/" + x.data.imdbId + "/";
|
||||
x.imdbId = "http://www.imdb.com/title/" + x.imdbId + "/";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ServiceHelpers } from "../service.helpers";
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ServiceHelpers } from "../service.helpers";
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ServiceHelpers } from "../service.helpers";
|
||||
|
||||
import { IPlexAuthentication, IPlexLibResponse, IPlexOAuthViewModel,IPlexServer, IPlexServerViewModel, IUsersModel } from "../../interfaces";
|
||||
import { IPlexAuthentication, IPlexLibResponse, IPlexOAuthViewModel, IPlexServer, IPlexServerViewModel, IUsersModel } from "../../interfaces";
|
||||
|
||||
@Injectable()
|
||||
export class PlexService extends ServiceHelpers {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ServiceHelpers } from "../service.helpers";
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { HttpClient, HttpHeaders } from "@angular/common/http";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { IPlexPin } from "../../interfaces";
|
||||
|
||||
|
@ -10,11 +10,10 @@ import { IPlexPin } from "../../interfaces";
|
|||
export class PlexTvService {
|
||||
|
||||
constructor(private http: HttpClient, public platformLocation: PlatformLocation) {
|
||||
|
||||
}
|
||||
|
||||
public GetPin(clientId: string, applicationName: string): Observable<IPlexPin> {
|
||||
const headers = new HttpHeaders({"Content-Type":"application/json",
|
||||
const headers = new HttpHeaders({"Content-Type": "application/json",
|
||||
"X-Plex-Client-Identifier": clientId,
|
||||
"X-Plex-Product": applicationName,
|
||||
"X-Plex-Version": "3",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { IRadarrProfile, IRadarrRootFolder } from "../../interfaces";
|
||||
import { IRadarrSettings } from "../../interfaces";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ISonarrSettings } from "../../interfaces";
|
||||
import { ISonarrProfile, ISonarrRootFolder } from "../../interfaces";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ServiceHelpers } from "../service.helpers";
|
||||
|
||||
|
@ -37,6 +37,7 @@ export class TesterService extends ServiceHelpers {
|
|||
public pushbulletTest(settings: IPushbulletNotificationSettings): Observable<boolean> {
|
||||
return this.http.post<boolean>(`${this.url}pushbullet`, JSON.stringify(settings), {headers: this.headers});
|
||||
}
|
||||
|
||||
public pushoverTest(settings: IPushoverNotificationSettings): Observable<boolean> {
|
||||
return this.http.post<boolean>(`${this.url}pushover`, JSON.stringify(settings), {headers: this.headers});
|
||||
}
|
||||
|
@ -80,9 +81,11 @@ export class TesterService extends ServiceHelpers {
|
|||
public sickrageTest(settings: ISickRageSettings): Observable<boolean> {
|
||||
return this.http.post<boolean>(`${this.url}sickrage`, JSON.stringify(settings), {headers: this.headers});
|
||||
}
|
||||
|
||||
public newsletterTest(settings: INewsletterNotificationSettings): Observable<boolean> {
|
||||
return this.http.post<boolean>(`${this.url}newsletter`, JSON.stringify(settings), {headers: this.headers});
|
||||
}
|
||||
|
||||
public mobileNotificationTest(settings: IMobileNotificationTestSettings): Observable<boolean> {
|
||||
return this.http.post<boolean>(`${this.url}mobile`, JSON.stringify(settings), {headers: this.headers});
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ICheckbox, ICreateWizardUser, IIdentityResult, IResetPasswordToken, IUpdateLocalUser, IUser, IWizardUserResult } from "../interfaces";
|
||||
import { ServiceHelpers } from "./service.helpers";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { IIssueCategory, IIssueComments,IIssueCount, IIssues, IIssuesChat, INewIssueComments, IssueStatus, IUpdateStatus } from "../interfaces";
|
||||
import { IIssueCategory, IIssueComments, IIssueCount, IIssues, IIssuesChat, INewIssueComments, IssueStatus, IUpdateStatus } from "../interfaces";
|
||||
import { ServiceHelpers } from "./service.helpers";
|
||||
|
||||
@Injectable()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ServiceHelpers } from "./service.helpers";
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { IMobileUsersViewModel } from "./../interfaces";
|
||||
import { ServiceHelpers } from "./service.helpers";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { IMassEmailModel } from "./../interfaces";
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "./../interfaces";
|
||||
import { ServiceHelpers } from "./service.helpers";
|
||||
|
@ -19,6 +19,7 @@ export class RecentlyAddedService extends ServiceHelpers {
|
|||
public getRecentlyAddedTv(): Observable<IRecentlyAddedTvShows[]> {
|
||||
return this.http.get<IRecentlyAddedTvShows[]>(`${this. url}tv/`, {headers: this.headers});
|
||||
}
|
||||
|
||||
public getRecentlyAddedTvGrouped(): Observable<IRecentlyAddedTvShows[]> {
|
||||
return this.http.get<IRecentlyAddedTvShows[]>(`${this.url}tv/grouped`, {headers: this.headers});
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { TreeNode } from "primeng/primeng";
|
||||
import { IRequestEngineResult } from "../interfaces";
|
||||
import { IChildRequests, IFilter, IMovieRequestModel, IMovieRequests, IMovieUpdateModel, IRequestsViewModel, ITvRequests,ITvUpdateModel, OrderType } from "../interfaces";
|
||||
import { FilterType, IChildRequests, IFilter, IMovieRequestModel, IMovieRequests, IMovieUpdateModel, IRequestEngineResult, IRequestsViewModel, ITvRequests, ITvUpdateModel, OrderType } from "../interfaces";
|
||||
import { ITvRequestViewModel } from "../interfaces";
|
||||
import { ServiceHelpers } from "./service.helpers";
|
||||
|
||||
|
@ -64,8 +63,8 @@ export class RequestService extends ServiceHelpers {
|
|||
return this.http.put<IMovieRequests>(`${this.url}movie/`, JSON.stringify(request), {headers: this.headers});
|
||||
}
|
||||
|
||||
public getTvRequests(count: number, position: number): Observable<ITvRequests[]> {
|
||||
return this.http.get<ITvRequests[]>(`${this.url}tv/${count}/${position}`, {headers: this.headers});
|
||||
public getTvRequests(count: number, position: number, order: OrderType, status: FilterType, availability: FilterType): Observable<IRequestsViewModel<ITvRequests>> {
|
||||
return this.http.get<IRequestsViewModel<ITvRequests>>(`${this.url}tv/${count}/${position}/${order}/${status}/${availability}`, {headers: this.headers});
|
||||
}
|
||||
|
||||
public getTvRequestsTree(count: number, position: number): Observable<TreeNode[]> {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { TreeNode } from "primeng/primeng";
|
||||
import { ISearchMovieResult } from "../interfaces";
|
||||
|
@ -56,16 +56,16 @@ export class SearchService extends ServiceHelpers {
|
|||
return this.http.get<ISearchTvResult>(`${this.url}/Tv/info/${theTvDbId}`, {headers: this.headers});
|
||||
}
|
||||
|
||||
public popularTv(): Observable<TreeNode[]> {
|
||||
return this.http.get<TreeNode[]>(`${this.url}/Tv/popular/tree`, {headers: this.headers});
|
||||
public popularTv(): Observable<ISearchTvResult[]> {
|
||||
return this.http.get<ISearchTvResult[]>(`${this.url}/Tv/popular`, {headers: this.headers});
|
||||
}
|
||||
public mostWatchedTv(): Observable<TreeNode[]> {
|
||||
return this.http.get<TreeNode[]>(`${this.url}/Tv/mostwatched/tree`, {headers: this.headers});
|
||||
public mostWatchedTv(): Observable<ISearchTvResult[]> {
|
||||
return this.http.get<ISearchTvResult[]>(`${this.url}/Tv/mostwatched`, {headers: this.headers});
|
||||
}
|
||||
public anticipatedTv(): Observable<TreeNode[]> {
|
||||
return this.http.get<TreeNode[]>(`${this.url}/Tv/anticipated/tree`, {headers: this.headers});
|
||||
public anticipatedTv(): Observable<ISearchTvResult[]> {
|
||||
return this.http.get<ISearchTvResult[]>(`${this.url}/Tv/anticipated`, {headers: this.headers});
|
||||
}
|
||||
public trendingTv(): Observable<TreeNode[]> {
|
||||
return this.http.get<TreeNode[]>(`${this.url}/Tv/trending/tree`, {headers: this.headers});
|
||||
public trendingTv(): Observable<ISearchTvResult[]> {
|
||||
return this.http.get<ISearchTvResult[]>(`${this.url}/Tv/trending`, {headers: this.headers});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { HttpClient, HttpHeaders } from "@angular/common/http";
|
||||
import "rxjs/add/observable/throw";
|
||||
|
||||
export class ServiceHelpers {
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import {
|
||||
IAbout,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ServiceHelpers } from "./service.helpers";
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@ export class CustomizationComponent implements OnInit {
|
|||
return item.fullName === this.settings.presetThemeName;
|
||||
})[0];
|
||||
|
||||
if(existingTheme) {
|
||||
if (existingTheme) {
|
||||
const index = this.themes.indexOf(existingTheme, 0);
|
||||
if (index > -1) {
|
||||
this.themes.splice(index, 1);
|
||||
}
|
||||
}
|
||||
if(x.hasPresetTheme) {
|
||||
if (x.hasPresetTheme) {
|
||||
this.themes.unshift({displayName: x.presetThemeDisplayName, fullName: x.presetThemeName, url: existingTheme.url, version: x.presetThemeVersion});
|
||||
this.themes.unshift({displayName: "None", fullName: "None", url: "", version: ""});
|
||||
} else {
|
||||
|
@ -45,8 +45,8 @@ export class CustomizationComponent implements OnInit {
|
|||
public save() {
|
||||
|
||||
this.settingsService.verifyUrl(this.settings.applicationUrl).subscribe(x => {
|
||||
if(this.settings.applicationUrl) {
|
||||
if(!x) {
|
||||
if (this.settings.applicationUrl) {
|
||||
if (!x) {
|
||||
this.notificationService.error(`The URL "${this.settings.applicationUrl}" is not valid. Please format it correctly e.g. http://www.google.com/`);
|
||||
return;
|
||||
}
|
||||
|
@ -64,16 +64,16 @@ export class CustomizationComponent implements OnInit {
|
|||
}
|
||||
|
||||
public dropDownChange(event: any): void {
|
||||
const selectedThemeFullName = <string>event.target.value;
|
||||
const selectedThemeFullName = <string> event.target.value;
|
||||
const selectedTheme = this.themes.filter((val) => {
|
||||
return val.fullName === selectedThemeFullName;
|
||||
})[0];
|
||||
|
||||
if(selectedTheme.fullName === this.settings.presetThemeName) {
|
||||
if (selectedTheme.fullName === this.settings.presetThemeName) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(selectedTheme.fullName === "None" || selectedTheme.fullName === "-1") {
|
||||
if (selectedTheme.fullName === "None" || selectedTheme.fullName === "-1") {
|
||||
this.settings.presetThemeName = "";
|
||||
this.settings.presetThemeContent = "";
|
||||
return;
|
||||
|
|
|
@ -39,7 +39,7 @@ export class DiscordComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
const settings = <IDiscordNotifcationSettings>form.value;
|
||||
const settings = <IDiscordNotifcationSettings> form.value;
|
||||
settings.notificationTemplates = this.templates;
|
||||
|
||||
this.settingsService.saveDiscordNotificationSettings(settings).subscribe(x => {
|
||||
|
|
|
@ -54,7 +54,7 @@ export class EmailNotificationComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
const settings = <IEmailNotificationSettings>form.value;
|
||||
const settings = <IEmailNotificationSettings> form.value;
|
||||
settings.notificationTemplates = this.templates;
|
||||
|
||||
this.settingsService.saveEmailNotificationSettings(settings).subscribe(x => {
|
||||
|
|
|
@ -29,7 +29,7 @@ export class MattermostComponent implements OnInit {
|
|||
username: [x.username],
|
||||
webhookUrl: [x.webhookUrl, [Validators.required]],
|
||||
channel: [x.channel],
|
||||
iconUrl:[x.iconUrl],
|
||||
iconUrl: [x.iconUrl],
|
||||
|
||||
});
|
||||
});
|
||||
|
@ -41,7 +41,7 @@ export class MattermostComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
const settings = <IMattermostNotifcationSettings>form.value;
|
||||
const settings = <IMattermostNotifcationSettings> form.value;
|
||||
settings.notificationTemplates = this.templates;
|
||||
|
||||
this.settingsService.saveMattermostNotificationSettings(settings).subscribe(x => {
|
||||
|
|
|
@ -32,9 +32,9 @@ export class MobileComponent implements OnInit {
|
|||
});
|
||||
|
||||
this.mobileService.getUserDeviceList().subscribe(x => {
|
||||
if(x.length <= 0) {
|
||||
if (x.length <= 0) {
|
||||
this.userList = [];
|
||||
this.userList.push({username:"None",devices:0, userId:""});
|
||||
this.userList.push({username: "None", devices: 0, userId: ""});
|
||||
} else {
|
||||
this.userList = x;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ export class MobileComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
const settings = <IMobileNotifcationSettings>form.value;
|
||||
const settings = <IMobileNotifcationSettings> form.value;
|
||||
settings.notificationTemplates = this.templates;
|
||||
|
||||
this.settingsService.saveMobileNotificationSettings(settings).subscribe(x => {
|
||||
|
@ -65,8 +65,8 @@ export class MobileComponent implements OnInit {
|
|||
this.notificationService.error("Please check your entered values");
|
||||
return;
|
||||
}
|
||||
if(!this.testUserId) {
|
||||
this.notificationService.warning("Warning","Please select a user to send the test notification");
|
||||
if (!this.testUserId) {
|
||||
this.notificationService.warning("Warning", "Please select a user to send the test notification");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,10 +51,10 @@ export class NewsletterComponent implements OnInit {
|
|||
}
|
||||
public addEmail() {
|
||||
|
||||
if(this.emailToAdd) {
|
||||
if (this.emailToAdd) {
|
||||
const emailRegex = "[a-zA-Z0-9.-_]{1,}@[a-zA-Z.-]{2,}[.]{1}[a-zA-Z]{2,}";
|
||||
const match = this.emailToAdd.match(emailRegex)!;
|
||||
if(match && match.length > 0) {
|
||||
if (match && match.length > 0) {
|
||||
this.settings.externalEmails.push(this.emailToAdd);
|
||||
this.emailToAdd = "";
|
||||
} else {
|
||||
|
|
|
@ -37,7 +37,7 @@ export class PushbulletComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
const settings = <IPushbulletNotificationSettings>form.value;
|
||||
const settings = <IPushbulletNotificationSettings> form.value;
|
||||
settings.notificationTemplates = this.templates;
|
||||
|
||||
this.settingsService.savePushbulletNotificationSettings(settings).subscribe(x => {
|
||||
|
|
|
@ -37,7 +37,7 @@ export class PushoverComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
const settings = <IPushoverNotificationSettings>form.value;
|
||||
const settings = <IPushoverNotificationSettings> form.value;
|
||||
settings.notificationTemplates = this.templates;
|
||||
|
||||
this.settingsService.savePushoverNotificationSettings(settings).subscribe(x => {
|
||||
|
|
|
@ -41,7 +41,7 @@ export class SlackComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
const settings = <ISlackNotificationSettings>form.value;
|
||||
const settings = <ISlackNotificationSettings> form.value;
|
||||
if (settings.iconEmoji && settings.iconUrl) {
|
||||
|
||||
this.notificationService.error("You cannot have a Emoji icon and a URL icon");
|
||||
|
@ -65,7 +65,7 @@ export class SlackComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
const settings = <ISlackNotificationSettings>form.value;
|
||||
const settings = <ISlackNotificationSettings> form.value;
|
||||
if (settings.iconEmoji && settings.iconUrl) {
|
||||
|
||||
this.notificationService.error("You cannot have a Emoji icon and a URL icon");
|
||||
|
|
|
@ -40,7 +40,7 @@ export class TelegramComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
const settings = <ITelegramNotifcationSettings>form.value;
|
||||
const settings = <ITelegramNotifcationSettings> form.value;
|
||||
settings.notificationTemplates = this.templates;
|
||||
|
||||
this.settingsService.saveTelegramNotificationSettings(settings).subscribe(x => {
|
||||
|
|
|
@ -41,9 +41,9 @@ export class OmbiComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
const result = <IOmbiSettings>form.value;
|
||||
if(result.baseUrl && result.baseUrl.length > 0) {
|
||||
if(!result.baseUrl.startsWith("/")) {
|
||||
const result = <IOmbiSettings> form.value;
|
||||
if (result.baseUrl && result.baseUrl.length > 0) {
|
||||
if (!result.baseUrl.startsWith("/")) {
|
||||
this.notificationService.error("Please ensure your base url starts with a '/'");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import "rxjs/add/operator/takeUntil";
|
||||
import { Subject } from "rxjs/Subject";
|
||||
|
||||
import { IPlexServerResponse, IPlexServerViewModel } from "../../interfaces";
|
||||
import { IPlexLibrariesSettings, IPlexServer, IPlexSettings } from "../../interfaces";
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { Subject } from "rxjs";
|
||||
import { takeUntil } from "rxjs/operators";
|
||||
|
||||
import { IPlexLibrariesSettings, IPlexServer, IPlexServerResponse, IPlexServerViewModel, IPlexSettings } from "../../interfaces";
|
||||
import { JobService, NotificationService, PlexService, SettingsService, TesterService } from "../../services";
|
||||
|
||||
@Component({
|
||||
|
@ -21,7 +19,8 @@ export class PlexComponent implements OnInit, OnDestroy {
|
|||
|
||||
private subscriptions = new Subject<void>();
|
||||
|
||||
constructor(private settingsService: SettingsService,
|
||||
constructor(
|
||||
private settingsService: SettingsService,
|
||||
private notificationService: NotificationService,
|
||||
private plexService: PlexService,
|
||||
private testerService: TesterService,
|
||||
|
@ -34,9 +33,9 @@ export class PlexComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
public requestServers(server: IPlexServer) {
|
||||
this.plexService.getServers(this.username, this.password)
|
||||
.takeUntil(this.subscriptions)
|
||||
.subscribe(x => {
|
||||
this.plexService.getServers(this.username, this.password).pipe(
|
||||
takeUntil(this.subscriptions),
|
||||
).subscribe(x => {
|
||||
if (x.success) {
|
||||
this.loadedServers = x;
|
||||
this.serversButton = true;
|
||||
|
@ -72,7 +71,7 @@ export class PlexComponent implements OnInit, OnDestroy {
|
|||
if (this.settings.servers == null) {
|
||||
this.settings.servers = [];
|
||||
}
|
||||
this.settings.servers.push(<IPlexServer>{ name: "New*", id: Math.floor(Math.random() * (99999 - 0 + 1) + 1) });
|
||||
this.settings.servers.push(<IPlexServer> { name: "New*", id: Math.floor(Math.random() * (99999 - 0 + 1) + 1) });
|
||||
|
||||
}
|
||||
|
||||
|
@ -120,7 +119,7 @@ export class PlexComponent implements OnInit, OnDestroy {
|
|||
|
||||
public runCacher(): void {
|
||||
this.jobService.runPlexCacher().subscribe(x => {
|
||||
if(x) {
|
||||
if (x) {
|
||||
this.notificationService.success("Triggered the Plex Full Sync");
|
||||
}
|
||||
});
|
||||
|
@ -128,7 +127,7 @@ export class PlexComponent implements OnInit, OnDestroy {
|
|||
|
||||
public runRecentlyAddedCacher(): void {
|
||||
this.jobService.runPlexRecentlyAddedCacher().subscribe(x => {
|
||||
if(x) {
|
||||
if (x) {
|
||||
this.notificationService.success("Triggered the Plex Recently Added Sync");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -93,7 +93,7 @@ export class RadarrComponent implements OnInit {
|
|||
this.notificationService.error("Please check your entered values");
|
||||
return;
|
||||
}
|
||||
const settings = <IRadarrSettings>form.value;
|
||||
const settings = <IRadarrSettings> form.value;
|
||||
this.testerService.radarrTest(settings).subscribe(x => {
|
||||
if (x === true) {
|
||||
this.notificationService.success("Successfully connected to Radarr!");
|
||||
|
@ -108,12 +108,12 @@ public onSubmit(form: FormGroup) {
|
|||
this.notificationService.error("Please check your entered values");
|
||||
return;
|
||||
}
|
||||
if(form.controls.defaultQualityProfile.value === "-1" || form.controls.defaultRootPath.value === "Please Select") {
|
||||
if (form.controls.defaultQualityProfile.value === "-1" || form.controls.defaultRootPath.value === "Please Select") {
|
||||
this.notificationService.error("Please check your entered values");
|
||||
return;
|
||||
}
|
||||
|
||||
const settings = <IRadarrSettings>form.value;
|
||||
const settings = <IRadarrSettings> form.value;
|
||||
this.settingsService.saveRadarr(settings).subscribe(x => {
|
||||
if (x) {
|
||||
this.notificationService.success("Successfully saved Radarr settings");
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import { CommonModule } from "@angular/common";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
import { NgbAccordionModule, NgbModule } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { ClipboardModule } from "ngx-clipboard/dist";
|
||||
import { ClipboardModule } from "ngx-clipboard";
|
||||
|
||||
import { AuthGuard } from "../auth/auth.guard";
|
||||
import { AuthService } from "../auth/auth.service";
|
||||
import { CouchPotatoService, EmbyService, IssuesService, JobService, MobileService, NotificationMessageService, PlexService, RadarrService,
|
||||
SonarrService, TesterService, ValidationService } from "../services";
|
||||
import {
|
||||
CouchPotatoService, EmbyService, IssuesService, JobService, MobileService, NotificationMessageService, PlexService, RadarrService,
|
||||
SonarrService, TesterService, ValidationService,
|
||||
} from "../services";
|
||||
|
||||
import { PipeModule } from "../pipes/pipe.module";
|
||||
import { AboutComponent } from "./about/about.component";
|
||||
|
|
|
@ -40,7 +40,7 @@ export class SickRageComponent implements OnInit {
|
|||
this.notificationService.error("Please check your entered values");
|
||||
return;
|
||||
}
|
||||
const settings = <ISickRageSettings>form.value;
|
||||
const settings = <ISickRageSettings> form.value;
|
||||
this.testerService.sickrageTest(settings).subscribe(x => {
|
||||
if (x) {
|
||||
this.notificationService.success("Successfully connected to SickRage!");
|
||||
|
|
|
@ -93,7 +93,7 @@ export class SonarrComponent implements OnInit {
|
|||
this.notificationService.error("Please check your entered values");
|
||||
return;
|
||||
}
|
||||
const settings = <ISonarrSettings>form.value;
|
||||
const settings = <ISonarrSettings> form.value;
|
||||
this.testerService.sonarrTest(settings).subscribe(x => {
|
||||
if (x) {
|
||||
this.notificationService.success("Successfully connected to Sonarr!");
|
||||
|
@ -108,13 +108,13 @@ export class SonarrComponent implements OnInit {
|
|||
this.notificationService.error("Please check your entered values");
|
||||
return;
|
||||
}
|
||||
if(form.controls.defaultQualityProfile) {
|
||||
if(form.controls.defaultQualityProfile.value === "-1") {
|
||||
if (form.controls.defaultQualityProfile) {
|
||||
if (form.controls.defaultQualityProfile.value === "-1") {
|
||||
this.notificationService.error("Please check your entered values");
|
||||
}
|
||||
}
|
||||
if(form.controls.defaultRootPath) {
|
||||
if(form.controls.defaultRootPath.value === "Please Select") {
|
||||
if (form.controls.defaultRootPath) {
|
||||
if (form.controls.defaultRootPath.value === "Please Select") {
|
||||
this.notificationService.error("Please check your entered values");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ export class UpdateDetailsComponent implements OnInit {
|
|||
this.identityService.getUser().subscribe(x => {
|
||||
const localUser = x as IUpdateLocalUser;
|
||||
this.form = this.fb.group({
|
||||
id:[localUser.id],
|
||||
id: [localUser.id],
|
||||
username: [localUser.userName],
|
||||
emailAddress: [localUser.emailAddress, [Validators.email]],
|
||||
confirmNewPassword: [localUser.confirmNewPassword],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
import { ICheckbox, ICustomizationSettings, IEmailNotificationSettings,IUser } from "../interfaces";
|
||||
import { ICheckbox, ICustomizationSettings, IEmailNotificationSettings, IUser } from "../interfaces";
|
||||
import { IdentityService, NotificationService, SettingsService } from "../services";
|
||||
|
||||
@Component({
|
||||
|
@ -21,9 +21,9 @@ export class UserManagementComponent implements OnInit {
|
|||
public bulkMovieLimit?: number;
|
||||
public bulkEpisodeLimit?: number;
|
||||
|
||||
constructor(private readonly identityService: IdentityService,
|
||||
private readonly settingsService: SettingsService,
|
||||
private readonly notificationService: NotificationService) { }
|
||||
constructor(private identityService: IdentityService,
|
||||
private settingsService: SettingsService,
|
||||
private notificationService: NotificationService) { }
|
||||
|
||||
public ngOnInit() {
|
||||
this.users = [];
|
||||
|
@ -37,7 +37,7 @@ export class UserManagementComponent implements OnInit {
|
|||
}
|
||||
|
||||
public welcomeEmail(user: IUser) {
|
||||
if(!user.emailAddress) {
|
||||
if (!user.emailAddress) {
|
||||
this.notificationService.error("The user needs an email address.");
|
||||
return;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ export class UserManagementComponent implements OnInit {
|
|||
this.notificationService.error("Email Notifications are not setup, cannot send welcome email");
|
||||
return;
|
||||
}
|
||||
if(!this.emailSettings.notificationTemplates.some(x => {
|
||||
if (!this.emailSettings.notificationTemplates.some(x => {
|
||||
return x.enabled && x.notificationType === 8;
|
||||
})) {
|
||||
this.notificationService.error("The Welcome Email template is not enabled in the Email Setings");
|
||||
|
@ -74,20 +74,20 @@ export class UserManagementComponent implements OnInit {
|
|||
});
|
||||
|
||||
this.users.forEach(x => {
|
||||
if(!x.checked) {
|
||||
if (!x.checked) {
|
||||
return;
|
||||
}
|
||||
if(anyRoles) {
|
||||
if (anyRoles) {
|
||||
x.claims = this.availableClaims;
|
||||
}
|
||||
if(this.bulkEpisodeLimit) {
|
||||
if (this.bulkEpisodeLimit) {
|
||||
x.episodeRequestLimit = this.bulkEpisodeLimit;
|
||||
}
|
||||
if(this.bulkMovieLimit) {
|
||||
if (this.bulkMovieLimit) {
|
||||
x.movieRequestLimit = this.bulkMovieLimit;
|
||||
}
|
||||
this.identityService.updateUser(x).subscribe(y => {
|
||||
if(!y.successful) {
|
||||
if (!y.successful) {
|
||||
this.notificationService.error(`Could not update user ${x.userName}. Reason ${y.errors[0]}`);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ import { IEmbySettings } from "../../interfaces";
|
|||
})
|
||||
export class EmbyComponent implements OnInit {
|
||||
|
||||
private embySettings: IEmbySettings;
|
||||
public embySettings: IEmbySettings;
|
||||
|
||||
constructor(private embyService: EmbyService,
|
||||
private router: Router,
|
||||
|
@ -21,7 +21,7 @@ export class EmbyComponent implements OnInit {
|
|||
public ngOnInit() {
|
||||
this.embySettings = {
|
||||
servers: [],
|
||||
id:0,
|
||||
id: 0,
|
||||
enable: true,
|
||||
};
|
||||
this.embySettings.servers.push({
|
||||
|
|
|
@ -50,9 +50,9 @@ export class PlexComponent implements OnInit {
|
|||
}
|
||||
|
||||
public oauth() {
|
||||
this.plexTv.GetPin(this.clientId, "Ombi").subscribe(pin => {
|
||||
this.plexService.oAuth({wizard: true, pin}).subscribe(x => {
|
||||
if(x.url) {
|
||||
this.plexTv.GetPin(this.clientId, "Ombi").subscribe((pin: any) => {
|
||||
this.plexService.oAuth({ wizard: true, pin }).subscribe(x => {
|
||||
if (x.url) {
|
||||
window.location.href = x.url;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ export class PlexOAuthComponent implements OnInit {
|
|||
|
||||
public ngOnInit(): void {
|
||||
this.plexOauth.oAuth(this.pinId).subscribe(x => {
|
||||
if(!x.accessToken) {
|
||||
if (!x.accessToken) {
|
||||
return;
|
||||
// RETURN
|
||||
}
|
||||
|
@ -50,5 +50,4 @@ export class PlexOAuthComponent implements OnInit {
|
|||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
import "rxjs/add/operator/catch";
|
||||
import "rxjs/add/operator/map";
|
|
@ -1,5 +1,6 @@
|
|||
import * as Pace from "pace-progress";
|
||||
// Main
|
||||
|
||||
import * as Pace from "pace-progress";
|
||||
Pace.start();
|
||||
|
||||
import "bootstrap/dist/js/bootstrap";
|
||||
|
@ -11,8 +12,6 @@ import "./polyfills";
|
|||
|
||||
import "hammerjs";
|
||||
|
||||
import "./imports";
|
||||
|
||||
import { enableProdMode } from "@angular/core";
|
||||
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
|
||||
import { AppModule } from "./app/app.module";
|
||||
|
@ -29,7 +28,9 @@ if (module.hot) {
|
|||
oldRootElem.parentNode.insertBefore(newRootElem, oldRootElem);
|
||||
oldRootElem.parentNode.removeChild(oldRootElem);
|
||||
}
|
||||
if (modulePromise) {
|
||||
modulePromise.then(appModule => appModule.destroy());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
enableProdMode();
|
||||
|
|
|
@ -9,6 +9,7 @@ declare var module: any;
|
|||
|
||||
if (module.hot) {
|
||||
Error.stackTraceLimit = Infinity;
|
||||
// tslint:disable:no-var-requires
|
||||
|
||||
// tslint:disable-next-line
|
||||
require("zone.js/dist/long-stack-trace-zone");
|
||||
}
|
||||
|
|
|
@ -24,3 +24,7 @@ $bg-colour-disabled: #252424;
|
|||
background: $primary-colour !important;
|
||||
color: white;
|
||||
}*/
|
||||
|
||||
.label {
|
||||
margin: 3px;
|
||||
}
|
|
@ -883,11 +883,6 @@ textarea {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.ui-treetable-toggler.fa.fa-fw.ui-clickable.fa-caret-right,
|
||||
.ui-treetable-toggler.fa.fa-fw.ui-clickable.fa-caret-down {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ui-state-highlight {
|
||||
background: $primary-colour;
|
||||
}
|
||||
|
@ -900,15 +895,6 @@ textarea {
|
|||
border: 1px solid $form-color-lighter;
|
||||
}
|
||||
|
||||
.ui-treetable tfoot td, .ui-treetable th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ui-treetable tbody td {
|
||||
white-space: inherit;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
table a:not(.btn) {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
|
@ -153,18 +153,6 @@ namespace Ombi.Controllers
|
|||
return await MovieRequestEngine.DenyMovieById(model.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tv requests.
|
||||
/// </summary>
|
||||
/// <param name="count">The count of items you want to return.</param>
|
||||
/// <param name="position">The position.</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/{count:int}/{position:int}/tree")]
|
||||
public async Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> GetTvRequestsTree(int count, int position)
|
||||
{
|
||||
return await TvRequestEngine.GetRequestsTreeNode(count, position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total amount of TV requests.
|
||||
/// </summary>
|
||||
|
@ -267,17 +255,6 @@ namespace Ombi.Controllers
|
|||
return await TvRequestEngine.SearchTvRequest(searchTerm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a specific tv request
|
||||
/// </summary>
|
||||
/// <param name="searchTerm">The search term.</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/search/{searchTerm}/tree")]
|
||||
public async Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> SearchTvTree(string searchTerm)
|
||||
{
|
||||
return await TvRequestEngine.SearchTvRequestTree(searchTerm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the a specific tv request
|
||||
/// </summary>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
@ -127,31 +126,6 @@ namespace Ombi.Controllers
|
|||
return await TvEngine.Search(searchTerm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a Tv Show.
|
||||
/// </summary>
|
||||
/// <param name="searchTerm">The search term.</param>
|
||||
/// <remarks>We use TvMaze as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/{searchTerm}/tree")]
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> SearchTvTreeNode(string searchTerm)
|
||||
{
|
||||
return await TvEngine.SearchTreeNode(searchTerm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets extra show information.
|
||||
/// </summary>
|
||||
/// <param name="tvdbId">The TVDB identifier.</param>
|
||||
/// <remarks>We use TvMaze as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/info/{tvdbId}/tree")]
|
||||
public async Task<TreeNode<SearchTvShowViewModel>> GetShowInfoTreeNode(int tvdbId)
|
||||
{
|
||||
if (tvdbId == 0) return new TreeNode<SearchTvShowViewModel>();
|
||||
return await TvEngine.GetShowInformationTreeNode(tvdbId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets extra show information.
|
||||
/// </summary>
|
||||
|
@ -164,17 +138,6 @@ namespace Ombi.Controllers
|
|||
return await TvEngine.GetShowInformation(tvdbId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Popular Tv Shows
|
||||
/// </summary>
|
||||
/// <remarks>We use Trakt.tv as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/popular/tree")]
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> PopularTvTree()
|
||||
{
|
||||
return await TvEngine.PopularTree();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Popular Tv Shows
|
||||
/// </summary>
|
||||
|
@ -186,18 +149,6 @@ namespace Ombi.Controllers
|
|||
return await TvEngine.Popular();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns most Anticiplateds tv shows.
|
||||
/// </summary>
|
||||
/// <remarks>We use Trakt.tv as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/anticipated/tree")]
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> AnticipatedTvTree()
|
||||
{
|
||||
return await TvEngine.AnticipatedTree();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns most Anticiplateds tv shows.
|
||||
/// </summary>
|
||||
|
@ -209,16 +160,6 @@ namespace Ombi.Controllers
|
|||
return await TvEngine.Anticipated();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Most watched shows.
|
||||
/// </summary>
|
||||
/// <remarks>We use Trakt.tv as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/mostwatched/tree")]
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> MostWatchedTree()
|
||||
{
|
||||
return await TvEngine.MostWatchesTree();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Most watched shows.
|
||||
|
@ -231,17 +172,6 @@ namespace Ombi.Controllers
|
|||
return await TvEngine.MostWatches();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns trending shows
|
||||
/// </summary>
|
||||
/// <remarks>We use Trakt.tv as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/trending/tree")]
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> TrendingTree()
|
||||
{
|
||||
return await TvEngine.TrendingTree();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns trending shows
|
||||
/// </summary>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<Project ToolsVersion="15.0" Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RuntimeIdentifiers>win10-x64;win10-x86;osx-x64;ubuntu-x64;debian.8-x64;centos.7-x64;linux-x64;linux-arm;linux-arm64;</RuntimeIdentifiers>
|
||||
|
@ -9,6 +8,7 @@
|
|||
<FileVersion>$(SemVer)</FileVersion>
|
||||
<Version>$(FullVer)</Version>
|
||||
<PackageVersion></PackageVersion>
|
||||
<TypeScriptToolsVersion>2.8</TypeScriptToolsVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ServerGarbageCollection>false</ServerGarbageCollection>
|
||||
|
@ -24,10 +24,6 @@
|
|||
<DefineConstants>TRACE;RELEASE;NETCOREAPP2_0</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="NpmCommandsDebug" Condition="'$(Configuration)'=='Debug'" AfterTargets="Build">
|
||||
<Exec Command="npm run-script vendor" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Files not to show in IDE -->
|
||||
<Compile Remove="Logs\**" />
|
||||
|
@ -46,7 +42,17 @@
|
|||
<None Remove="Styles\**" />
|
||||
<None Remove="wwwroot\dist\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="NpmCommandsDebug" Condition="'$(Configuration)'=='Debug'" AfterTargets="Build">
|
||||
<Exec Command="npm run vendor" />
|
||||
</Target>
|
||||
<!-- Disabled as run by CI once for many different runtime builds
|
||||
<Target Name="NpmCommandsRelease" Condition="'$(Configuration)'=='Release'" AfterTargets="Build">
|
||||
<Exec Command="npm run publish" />
|
||||
</Target>
|
||||
-->
|
||||
<Target Name="NpmCommandsClean" AfterTargets="Clean">
|
||||
<Exec Command="npm run clean" />
|
||||
</Target>
|
||||
<Target Name="RunWebpack" AfterTargets="ComputeFilesToPublish">
|
||||
<ItemGroup>
|
||||
<DistFiles Include="wwwroot\dist\**" />
|
||||
|
@ -56,8 +62,6 @@
|
|||
</ResolvedFileToPublish>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="6.1.1" />
|
||||
<PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
|
||||
|
@ -94,18 +98,4 @@
|
|||
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.Api.TheMovieDb.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Updater\Ombi.Updater.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="wwwroot\loading.css" />
|
||||
<None Include="wwwroot\translations\*.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="ClientApp\app\animations\fadeinout.ts" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<TypeScriptCompile Include="ClientApp\app\animations\fadeinout.ts" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -156,7 +156,12 @@ namespace Ombi
|
|||
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
|
||||
{
|
||||
HotModuleReplacement = true,
|
||||
ConfigFile = "webpack.dev.js"
|
||||
ConfigFile = "webpack.config.ts",
|
||||
|
||||
//EnvParam = new
|
||||
//{
|
||||
// aot = true // can't use AOT with HMR currently https://github.com/angular/angular-cli/issues/6347
|
||||
//}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -71,8 +71,8 @@
|
|||
<meta name="smartbanner:button-url-apple" content="https://itunes.apple.com/us/genre/ios/id36?mt=8">
|
||||
<meta name="smartbanner:button-url-google" content="https://play.google.com/store">
|
||||
<meta name="smartbanner:enabled-platforms" content="android,ios">e.com/store/apps/details?id=com.tidusjar.Ombi">
|
||||
<meta name="smartbanner:enabled-platforms" content="android,ios">
|
||||
<!-- End SmartBanner configuration -->*@
|
||||
<meta name="smartbanner:enabled-platforms" content="android,ios">
|
||||
<!-- End SmartBanner configuration -->*@
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="description" content="Ombi, media request tool">
|
||||
|
@ -98,8 +98,10 @@
|
|||
|
||||
<link rel="stylesheet" href="~/loading.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="~/dist/vendor.css" asp-append-version="true" />
|
||||
<environment include="Development">
|
||||
<script src="~/dist/vendor.js" asp-append-version="true" defer></script>
|
||||
<script src="~/dist/main.js" asp-append-version="true" defer></script>
|
||||
</environment>
|
||||
<script src="~/dist/app.js" asp-append-version="true" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
@{
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const gulp = require('gulp');
|
||||
const run = require('gulp-run');
|
||||
const runSequence = require('run-sequence');
|
||||
const del = require('del');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const gulp = require("gulp");
|
||||
const run = require("gulp-run");
|
||||
const runSequence = require("run-sequence");
|
||||
const del = require("del");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
const outputDir = './wwwroot/dist';
|
||||
const outputDir = "./wwwroot/dist";
|
||||
global.aot = true;
|
||||
|
||||
function getEnvOptions() {
|
||||
var options = [];
|
||||
const options = [];
|
||||
if (global.prod) {
|
||||
options.push('--env.prod');
|
||||
options.push("--env.prod");
|
||||
}
|
||||
if (global.analyse) {
|
||||
options.push('--env.analyse');
|
||||
options.push("--env.analyse");
|
||||
}
|
||||
if (global.aot) {
|
||||
options.push("--env.aot");
|
||||
}
|
||||
if (options.length > 0) {
|
||||
return " " + options.join(" ");
|
||||
|
@ -24,12 +28,12 @@ function getEnvOptions() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function webpack(vendor) {
|
||||
return run(`webpack --config webpack.config${vendor ? '.vendor' : ''}.ts${getEnvOptions()}`).exec();
|
||||
function webpack(type) {
|
||||
// 'webpack' instead of direct path can cause https://github.com/angular/angular-cli/issues/6417
|
||||
return run(`node node_modules\\webpack\\bin\\webpack.js --config webpack.config${type ? `.${type}` : ""}.ts${getEnvOptions()}`).exec();
|
||||
}
|
||||
|
||||
gulp.task('vendor', () => {
|
||||
gulp.task("vendor", () => {
|
||||
let build = false;
|
||||
const vendorPath = path.join(outputDir, "vendor.js");
|
||||
const vendorExists = fs.existsSync(vendorPath);
|
||||
|
@ -37,44 +41,47 @@ gulp.task('vendor', () => {
|
|||
const vendorStat = fs.statSync(vendorPath);
|
||||
const packageStat = fs.statSync("package.json");
|
||||
const vendorConfigStat = fs.statSync("webpack.config.vendor.ts");
|
||||
const commonConfigStat = fs.statSync("webpack.config.common.ts");
|
||||
if (packageStat.mtime > vendorStat.mtime) {
|
||||
build = true;
|
||||
}
|
||||
if (vendorConfigStat.mtime > vendorStat.mtime) {
|
||||
build = true;
|
||||
}
|
||||
if (commonConfigStat.mtime > vendorStat.mtime) {
|
||||
build = true;
|
||||
}
|
||||
} else {
|
||||
build = true;
|
||||
}
|
||||
if (build) {
|
||||
return webpack(true);
|
||||
return webpack("vendor");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
gulp.task('vendor_force', () => {
|
||||
return webpack(true);
|
||||
gulp.task("vendor_force", () => {
|
||||
return webpack("vendor");
|
||||
})
|
||||
|
||||
gulp.task('main', () => {
|
||||
gulp.task("main", () => {
|
||||
return webpack()
|
||||
});
|
||||
|
||||
gulp.task('prod_var', () => {
|
||||
gulp.task("prod_var", () => {
|
||||
global.prod = true;
|
||||
})
|
||||
|
||||
gulp.task('analyse_var', () => {
|
||||
gulp.task("analyse_var", () => {
|
||||
global.analyse = true;
|
||||
})
|
||||
|
||||
gulp.task('clean', () => {
|
||||
gulp.task("clean", () => {
|
||||
del.sync(outputDir, { force: true });
|
||||
});
|
||||
|
||||
|
||||
gulp.task('lint', () => run("npm run lint").exec());
|
||||
gulp.task('build', callback => runSequence('vendor', 'main', callback));
|
||||
gulp.task('analyse', callback => runSequence('analyse_var', 'build'));
|
||||
gulp.task('full', callback => runSequence('clean', 'build'));
|
||||
gulp.task('publish', callback => runSequence('prod_var', 'build'));
|
||||
gulp.task("lint", () => run("npm run lint").exec());
|
||||
gulp.task("lint_fix", () => run("npm run lint -- --fix").exec());
|
||||
gulp.task("build", callback => runSequence("vendor", "main", callback));
|
||||
gulp.task("analyse", callback => runSequence("analyse_var", "clean", "build", callback));
|
||||
gulp.task("full", callback => runSequence("clean", "build", callback));
|
||||
gulp.task("publish", callback => runSequence("prod_var", "full", callback));
|
13399
src/Ombi/package-lock.json
generated
13399
src/Ombi/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,94 +1,93 @@
|
|||
{
|
||||
"name": "ombi",
|
||||
"version": "2.6.0",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"vendor": "gulp vendor",
|
||||
"main": "gulp main",
|
||||
"lint": "tslint -p .",
|
||||
"publish": "gulp publish",
|
||||
"lint": "tslint ClientApp/**/*.ts",
|
||||
"restore": "dotnet restore && npm install"
|
||||
"restore": "dotnet restore && yarn install",
|
||||
"clean": "gulp clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^5.2.5",
|
||||
"@angular/cdk": "^5.2.1",
|
||||
"@angular/common": "^5.2.5",
|
||||
"@angular/compiler": "^5.2.5",
|
||||
"@angular/core": "^5.2.5",
|
||||
"@angular/forms": "^5.2.5",
|
||||
"@angular/http": "^5.2.5",
|
||||
"@angular/material": "^5.2.1",
|
||||
"@angular/platform-browser": "^5.2.5",
|
||||
"@angular/platform-browser-dynamic": "^5.2.5",
|
||||
"@angular/platform-server": "^5.2.5",
|
||||
"@angular/router": "^5.2.5",
|
||||
"@auth0/angular-jwt": "1.0.0-beta.9",
|
||||
"@ng-bootstrap/ng-bootstrap": "^1.0.0",
|
||||
"@ngu/carousel": "^1.4.8",
|
||||
"@ngx-translate/core": "^8.0.0",
|
||||
"@ngx-translate/http-loader": "^2.0.1",
|
||||
"@types/core-js": "^0.9.46",
|
||||
"@types/extract-text-webpack-plugin": "^3.0.1",
|
||||
"@types/intro.js": "^2.4.3",
|
||||
"@types/node": "^8.9.4",
|
||||
"@types/webpack": "^3.8.7",
|
||||
"angular-router-loader": "^0.8.2",
|
||||
"angular2-moment": "^1.8.0",
|
||||
"@angular/animations": "^6.0.7",
|
||||
"@angular/cdk": "^6.3.1",
|
||||
"@angular/common": "^6.0.7",
|
||||
"@angular/compiler": "^6.0.7",
|
||||
"@angular/compiler-cli": "^6.0.7",
|
||||
"@angular/core": "^6.0.7",
|
||||
"@angular/forms": "^6.0.7",
|
||||
"@angular/http": "^6.0.7",
|
||||
"@angular/material": "^6.3.1",
|
||||
"@angular/platform-browser": "^6.0.7",
|
||||
"@angular/platform-browser-dynamic": "^6.0.7",
|
||||
"@angular/platform-server": "^6.0.7",
|
||||
"@angular/router": "^6.0.7",
|
||||
"@auth0/angular-jwt": "^2.0.0",
|
||||
"@ng-bootstrap/ng-bootstrap": "^2.2.0",
|
||||
"@ngtools/webpack": "^6.1.0-beta.2",
|
||||
"@ngu/carousel": "^1.4.9-beta-2",
|
||||
"@ngx-translate/core": "^10.0.2",
|
||||
"@ngx-translate/http-loader": "^3.0.1",
|
||||
"@types/core-js": "^2.5.0",
|
||||
"@types/mini-css-extract-plugin": "^0.2.0",
|
||||
"@types/node": "^10.5.1",
|
||||
"@types/webpack": "^4.4.4",
|
||||
"@types/webpack-bundle-analyzer": "^2.9.2",
|
||||
"@types/webpack-merge": "^4.1.3",
|
||||
"angular-router-loader": "^0.8.5",
|
||||
"angular2-template-loader": "^0.6.2",
|
||||
"aspnet-webpack": "^2.0.3",
|
||||
"awesome-typescript-loader": "^3.4.1",
|
||||
"aspnet-webpack": "^3.0.0",
|
||||
"awesome-typescript-loader": "^5.2.0",
|
||||
"bootstrap": "3.3.7",
|
||||
"bootswatch": "3.3.7",
|
||||
"core-js": "^2.5.3",
|
||||
"css": "^2.2.1",
|
||||
"css-loader": "^0.28.9",
|
||||
"copy-webpack-plugin": "^4.5.2",
|
||||
"core-js": "^2.5.7",
|
||||
"css": "^2.2.3",
|
||||
"css-loader": "^0.28.11",
|
||||
"del": "^3.0.0",
|
||||
"event-source-polyfill": "^0.0.11",
|
||||
"expose-loader": "^0.7.4",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^1.1.6",
|
||||
"event-source-polyfill": "^0.0.12",
|
||||
"expose-loader": "^0.7.5",
|
||||
"file-loader": "^1.1.11",
|
||||
"font-awesome": "^4.7.0",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-run": "^1.7.1",
|
||||
"hammerjs": "^2.0.8",
|
||||
"html-loader": "0.5.1",
|
||||
"html-loader": "^0.5.5",
|
||||
"jquery": "^3.3.1",
|
||||
"mini-css-extract-plugin": "^0.4.1",
|
||||
"moment": "^2.22.2",
|
||||
"ng2-cookies": "^1.0.12",
|
||||
"ngx-clipboard": "8.1.1",
|
||||
"ngx-infinite-scroll": "^0.6.1",
|
||||
"ngx-clipboard": "^11.1.1",
|
||||
"ngx-infinite-scroll": "^6.0.1",
|
||||
"ngx-moment": "^3.0.1",
|
||||
"ngx-order-pipe": "^2.0.1",
|
||||
"node-sass": "^4.7.2",
|
||||
"npm": "^5.6.0",
|
||||
"node-sass": "^4.9.0",
|
||||
"pace-progress": "^1.0.2",
|
||||
"primeng": "5.0.2",
|
||||
"reflect-metadata": "0.1.10",
|
||||
"primeng": "^6.0.0",
|
||||
"raw-loader": "^0.5.1",
|
||||
"reflect-metadata": "^0.1.12",
|
||||
"run-sequence": "^2.2.1",
|
||||
"rxjs": "5.5.2",
|
||||
"sass-loader": "^6.0.6",
|
||||
"style-loader": "^0.19.1",
|
||||
"rxjs": "^6.2.1",
|
||||
"sass-loader": "^7.0.3",
|
||||
"style-loader": "^0.21.0",
|
||||
"to-string-loader": "^1.1.5",
|
||||
"ts-node": "^3.3.0",
|
||||
"tslint": "^5.9.1",
|
||||
"tslint-language-service": "^0.9.8",
|
||||
"typescript": "^2.7.1",
|
||||
"uglify-es": "^3.3.10",
|
||||
"uglifyjs-webpack-plugin": "^1.1.8",
|
||||
"url-loader": "^0.6.2",
|
||||
"webpack": "^3.11.0",
|
||||
"webpack-bundle-analyzer": "^2.10.0",
|
||||
"webpack-hot-middleware": "^2.21.0",
|
||||
"zone.js": "^0.8.20"
|
||||
"ts-node": "^7.0.0",
|
||||
"tslint": "^5.10.0",
|
||||
"tslint-language-service": "^0.9.9",
|
||||
"typescript": "2.7.2",
|
||||
"uglify-es": "^3.3.9",
|
||||
"uglifyjs-webpack-plugin": "^1.2.7",
|
||||
"url-loader": "^1.0.1",
|
||||
"webpack": "^4.14.0",
|
||||
"webpack-bundle-analyzer": "^2.13.1",
|
||||
"webpack-cli": "^3.0.8",
|
||||
"webpack-dev-middleware": "^3.1.3",
|
||||
"webpack-hot-middleware": "^2.22.2",
|
||||
"webpack-merge": "^4.1.3",
|
||||
"zone.js": "^0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "4.0.4",
|
||||
"@types/jasmine": "2.6.2",
|
||||
"chai": "4.1.2",
|
||||
"jasmine-core": "2.8.0",
|
||||
"karma": "1.7.1",
|
||||
"karma-chai": "0.1.0",
|
||||
"karma-chrome-launcher": "2.2.0",
|
||||
"karma-cli": "1.0.1",
|
||||
"karma-jasmine": "1.1.0",
|
||||
"karma-webpack": "2.0.5"
|
||||
"resolutions": {
|
||||
"@types/tapable": "1.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"es6",
|
||||
"es2017",
|
||||
"dom"
|
||||
],
|
||||
"moduleResolution": "node",
|
||||
|
@ -27,11 +27,15 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"bin",
|
||||
"node_modules"
|
||||
"include": [
|
||||
"ClientApp/**/*",
|
||||
"typings/**/*",
|
||||
"webpack.config.*"
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"preserveWhitespaces": false
|
||||
}
|
||||
"preserveWhitespaces": false,
|
||||
"genDir": "./ClientApp/app/ngfactory",
|
||||
"entryModule": "ClientApp/app/app.module#AppModule"
|
||||
},
|
||||
"compileOnSave": false
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
],
|
||||
"max-line-length": [
|
||||
true,
|
||||
200
|
||||
250
|
||||
],
|
||||
"arrow-parens": false,
|
||||
"radix": false,
|
||||
|
@ -16,22 +16,33 @@
|
|||
"indent": [
|
||||
false
|
||||
],
|
||||
"whitespace": [
|
||||
false
|
||||
],
|
||||
"no-unused-expression": [
|
||||
true,
|
||||
"allow-new"
|
||||
],
|
||||
"no-trailing-whitespace": [
|
||||
false
|
||||
],
|
||||
"max-classes-per-file": [
|
||||
false
|
||||
],
|
||||
"no-shadowed-variable": false,
|
||||
"comment-format": [
|
||||
false
|
||||
],
|
||||
"no-namespace": [
|
||||
false
|
||||
],
|
||||
"no-internal-module": [
|
||||
false
|
||||
],
|
||||
"whitespace": [
|
||||
false,
|
||||
"check-branch",
|
||||
"check-decl",
|
||||
"check-operator",
|
||||
"check-separator",
|
||||
"check-type"
|
||||
],
|
||||
"no-trailing-whitespace":[
|
||||
false
|
||||
]
|
||||
}
|
||||
}
|
4
src/Ombi/typings/globals.d.ts
vendored
Normal file
4
src/Ombi/typings/globals.d.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
// Globals
|
||||
|
||||
declare module "pace-progress";
|
||||
declare var __webpack_public_path__: any;
|
12
src/Ombi/typings/globals/globals.d.ts
vendored
12
src/Ombi/typings/globals/globals.d.ts
vendored
|
@ -1,12 +0,0 @@
|
|||
// Globals
|
||||
|
||||
declare var module: any;
|
||||
declare var require: any;
|
||||
declare var localStorage: any;
|
||||
declare var introJs: any;
|
||||
|
||||
declare var __webpack_public_path__: any;
|
||||
|
||||
declare module "pace-progress";
|
||||
declare module "webpack-bundle-analyzer";
|
||||
declare module "uglifyjs-webpack-plugin";
|
2
src/Ombi/typings/index.d.ts
vendored
2
src/Ombi/typings/index.d.ts
vendored
|
@ -1 +1 @@
|
|||
/// <reference path="globals/globals.d.ts" />
|
||||
/// <reference path="globals.d.ts" />
|
||||
|
|
83
src/Ombi/webpack.config.common.ts
Normal file
83
src/Ombi/webpack.config.common.ts
Normal file
|
@ -0,0 +1,83 @@
|
|||
import { AngularCompilerPlugin } from "@ngtools/webpack";
|
||||
import * as MiniCssExtractPlugin from "mini-css-extract-plugin";
|
||||
import * as path from "path";
|
||||
import { Configuration, ContextReplacementPlugin, ProvidePlugin } from "webpack";
|
||||
import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";
|
||||
|
||||
export const outputDir = "./wwwroot/dist";
|
||||
|
||||
export function isProd(env: any) {
|
||||
return env && env.prod as boolean;
|
||||
}
|
||||
|
||||
export function isAOT(env: any) {
|
||||
return env && env.aot as boolean;
|
||||
}
|
||||
|
||||
export const WebpackCommonConfig = (env: any, type: string) => {
|
||||
const prod = isProd(env);
|
||||
const aot = isAOT(env);
|
||||
const vendor = type === "vendor";
|
||||
console.log(`${prod ? "Production" : "Dev"} ${type} build`);
|
||||
console.log(`Output directory: ${outputDir}`);
|
||||
console.log(`${aot ? "Using" : "Not using"} AOT compiler`);
|
||||
const analyse = env && env.analyse as boolean;
|
||||
if (analyse) { console.log("Analysing build"); }
|
||||
const cssLoader = prod ? "css-loader?minimize" : "css-loader";
|
||||
const bundleConfig: Configuration = {
|
||||
mode: prod ? "production" : "development",
|
||||
resolve: {
|
||||
extensions: [".ts", ".js"],
|
||||
alias: {
|
||||
pace: "pace-progress",
|
||||
},
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(outputDir),
|
||||
filename: "[name].js",
|
||||
chunkFilename: "[id].chunk.js",
|
||||
publicPath: "/dist/",
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{ test: /\.ts$/, loader: aot ? "@ngtools/webpack" : ["awesome-typescript-loader?silent=true", "angular2-template-loader", "angular-router-loader"] },
|
||||
{ test: /\.html$/, use: "html-loader?minimize=false" },
|
||||
{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, cssLoader] },
|
||||
{ test: /\.scss$/, exclude: /ClientApp/, use: [MiniCssExtractPlugin.loader, cssLoader, "sass-loader"] },
|
||||
{ test: /\.scss$/, include: /ClientApp(\\|\/)app/, use: ["to-string-loader", cssLoader, "sass-loader"] },
|
||||
{ test: /\.scss$/, include: /ClientApp(\\|\/)styles/, use: ["style-loader", cssLoader, "sass-loader"] },
|
||||
{ test: /\.(png|jpg|jpeg|gif|woff|woff2|eot|ttf|svg)(\?|$)/, use: "url-loader?limit=8192" },
|
||||
{ test: /[\/\\]@angular[\/\\].+\.js$/, parser: { system: true } }, // ignore System.import warnings https://github.com/angular/angular/issues/21560
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "[name].css",
|
||||
}),
|
||||
new ProvidePlugin({ $: "jquery", jQuery: "jquery", Hammer: "hammerjs/hammer" }), // Global identifiers
|
||||
].concat(aot && !vendor ? [
|
||||
new AngularCompilerPlugin({
|
||||
mainPath: "./ClientApp/main.ts",
|
||||
tsConfigPath: "./tsconfig.json",
|
||||
skipCodeGeneration: false,
|
||||
compilerOptions: {
|
||||
noEmit: false,
|
||||
},
|
||||
}),
|
||||
] : [
|
||||
// AOT chunk splitting does not work while this is active but doesn't seem to be needed under AOT anyway https://github.com/angular/angular-cli/issues/4431
|
||||
new ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)/, path.join(__dirname, "./ClientApp")), // Workaround for https://github.com/angular/angular/issues/14898
|
||||
]).concat(analyse ? [
|
||||
new BundleAnalyzerPlugin({
|
||||
analyzerMode: "static",
|
||||
reportFilename: `${type}.html`,
|
||||
openAnalyzer: false,
|
||||
}),
|
||||
] : []),
|
||||
node: {
|
||||
fs: "empty",
|
||||
},
|
||||
};
|
||||
|
||||
return bundleConfig;
|
||||
};
|
|
@ -1,59 +1,26 @@
|
|||
import { CheckerPlugin } from "awesome-typescript-loader";
|
||||
import * as path from "path";
|
||||
import * as UglifyJSPlugin from "uglifyjs-webpack-plugin";
|
||||
import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";
|
||||
import { Configuration, DllReferencePlugin } from "webpack";
|
||||
import * as webpackMerge from "webpack-merge";
|
||||
|
||||
import * as webpack from "webpack";
|
||||
import { isAOT, isProd, outputDir, WebpackCommonConfig } from "./webpack.config.common";
|
||||
|
||||
module.exports = (env: any) => {
|
||||
// const prod = env && env.prod as boolean;
|
||||
const prod = true;
|
||||
console.log(prod ? "Production" : "Dev" + " main build");
|
||||
const analyse = env && env.analyse as boolean;
|
||||
if (analyse) { console.log("Analysing build"); }
|
||||
const cssLoader = prod ? "css-loader?-url&minimize" : "css-loader?-url";
|
||||
const outputDir = "./wwwroot/dist";
|
||||
const bundleConfig: webpack.Configuration = {
|
||||
entry: { main: "./ClientApp/main.ts" },
|
||||
stats: { modules: false },
|
||||
context: __dirname,
|
||||
resolve: { extensions: [".ts", ".js"] },
|
||||
const prod = isProd(env);
|
||||
const aot = isAOT(env);
|
||||
if (!prod && aot) { console.warn("Vendor dll bundle will not be used as AOT is enabled"); }
|
||||
const bundleConfig: Configuration = webpackMerge(WebpackCommonConfig(env, "main"), {
|
||||
entry: {
|
||||
app: "./ClientApp/main.ts",
|
||||
},
|
||||
devtool: prod ? "source-map" : "eval-source-map",
|
||||
output: {
|
||||
filename: "[name].js",
|
||||
chunkFilename: "[id].[chunkhash].js",
|
||||
publicPath: "/dist/",
|
||||
path: path.join(__dirname, outputDir),
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{ test: /\.ts$/, include: /ClientApp/, use: ["awesome-typescript-loader?silent=true", "angular2-template-loader", "angular-router-loader"] },
|
||||
{ test: /\.html$/, use: "html-loader?minimize=false" },
|
||||
{ test: /\.css$/, use: ["to-string-loader", cssLoader] },
|
||||
{ test: /\.scss$/, include: /ClientApp(\\|\/)app/, use: ["to-string-loader", cssLoader, "sass-loader"] },
|
||||
{ test: /\.scss$/, include: /ClientApp(\\|\/)styles/, use: ["style-loader", cssLoader, "sass-loader"] },
|
||||
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: "url-loader?limit=25000" },
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new CheckerPlugin(),
|
||||
new webpack.DllReferencePlugin({
|
||||
plugins: prod || aot ? [] : [
|
||||
// AOT chunk splitting does not work while this is active https://github.com/angular/angular-cli/issues/4565
|
||||
new DllReferencePlugin({
|
||||
context: __dirname,
|
||||
manifest: require(path.join(__dirname, outputDir, "vendor-manifest.json")),
|
||||
}),
|
||||
].concat(prod ? [
|
||||
// Plugins that apply in production builds only
|
||||
new UglifyJSPlugin({ sourceMap: true }),
|
||||
] : [
|
||||
// Plugins that apply in development builds only
|
||||
]).concat(analyse ? [
|
||||
new BundleAnalyzerPlugin({
|
||||
analyzerMode: "static",
|
||||
reportFilename: "main.html",
|
||||
openAnalyzer: false,
|
||||
}),
|
||||
] : []),
|
||||
};
|
||||
],
|
||||
});
|
||||
|
||||
return bundleConfig;
|
||||
};
|
||||
|
|
|
@ -1,41 +1,25 @@
|
|||
import * as ExtractTextPlugin from "extract-text-webpack-plugin";
|
||||
import * as path from "path";
|
||||
import * as UglifyJSPlugin from "uglifyjs-webpack-plugin";
|
||||
import * as webpack from "webpack";
|
||||
import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";
|
||||
import * as webpackMerge from "webpack-merge";
|
||||
import { isProd, outputDir, WebpackCommonConfig } from "./webpack.config.common";
|
||||
|
||||
module.exports = (env: any) => {
|
||||
const extractCSS = new ExtractTextPlugin("vendor.css");
|
||||
const prod = env && env.prod as boolean;
|
||||
console.log(prod ? "Production" : "Dev" + " vendor build");
|
||||
const analyse = env && env.analyse as boolean;
|
||||
if (analyse) { console.log("Analysing build"); }
|
||||
const outputDir = "./wwwroot/dist";
|
||||
const bundleConfig = {
|
||||
stats: { modules: false },
|
||||
resolve: {
|
||||
extensions: [".js"],
|
||||
alias: {
|
||||
pace: "pace-progress",
|
||||
},
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{ test: /\.(png|woff|woff2|eot|ttf|svg|gif)(\?|$)/, use: "url-loader?limit=100000" },
|
||||
{ test: /\.css(\?|$)/, use: extractCSS.extract({ use: prod ? "css-loader?minimize" : "css-loader" }) },
|
||||
{ test: /\.scss(\?|$)/, use: extractCSS.extract({ use: [prod ? "css-loader?minimize" : "css-loader", "sass-loader"] }) },
|
||||
],
|
||||
const prod = isProd(env);
|
||||
const bundleConfig = webpackMerge(WebpackCommonConfig(env, "vendor"), {
|
||||
output: {
|
||||
library: "[name]_[hash]",
|
||||
},
|
||||
entry: {
|
||||
vendor: [
|
||||
vendor: (<string[]>[ // add any vendor styles here e.g. bootstrap/dist/css/bootstrap.min.css
|
||||
"pace-progress/themes/orange/pace-theme-flash.css",
|
||||
"primeng/resources/primeng.min.css",
|
||||
"@angular/material/prebuilt-themes/deeppurple-amber.css",
|
||||
"font-awesome/scss/font-awesome.scss",
|
||||
"bootswatch/superhero/bootstrap.min.css",
|
||||
|
||||
]).concat(prod ? [] : [ // used to speed up dev launch time
|
||||
"@angular/animations",
|
||||
"@angular/common",
|
||||
"@angular/common/http",
|
||||
"@angular/compiler",
|
||||
"@angular/core",
|
||||
"@angular/forms",
|
||||
|
@ -67,41 +51,14 @@ module.exports = (env: any) => {
|
|||
"@ngx-translate/core",
|
||||
"@ngx-translate/http-loader",
|
||||
"ngx-order-pipe",
|
||||
//"smartbanner.js/dist/smartbanner.js",
|
||||
//"smartbanner.js/dist/smartbanner.css",
|
||||
],
|
||||
]),
|
||||
},
|
||||
output: {
|
||||
publicPath: "/dist/",
|
||||
filename: "[name].js",
|
||||
library: "[name]_[hash]",
|
||||
path: path.join(__dirname, outputDir),
|
||||
},
|
||||
node: {
|
||||
fs: "empty",
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery", Hammer: "hammerjs/hammer" }), // Global identifiers
|
||||
new webpack.ContextReplacementPlugin(/\@angular(\\|\/)core(\\|\/)esm5/, path.join(__dirname, "./client")), // Workaround for https://github.com/angular/angular/issues/20357
|
||||
new webpack.ContextReplacementPlugin(/\@angular\b.*\b(bundles|linker)/, path.join(__dirname, "./ClientApp")), // Workaround for https://github.com/angular/angular/issues/11580
|
||||
new webpack.ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)@angular/, path.join(__dirname, "./ClientApp")), // Workaround for https://github.com/angular/angular/issues/14898
|
||||
extractCSS,
|
||||
plugins: prod ? [] : [
|
||||
new webpack.DllPlugin({
|
||||
path: path.join(__dirname, outputDir, "[name]-manifest.json"),
|
||||
name: "[name]_[hash]",
|
||||
}),
|
||||
].concat(prod ? [
|
||||
// Plugins that apply in production builds only
|
||||
new UglifyJSPlugin(),
|
||||
] : [
|
||||
// Plugins that apply in development builds only
|
||||
]).concat(analyse ? [
|
||||
new BundleAnalyzerPlugin({
|
||||
analyzerMode: "static",
|
||||
reportFilename: "vendor.html",
|
||||
openAnalyzer: false,
|
||||
}),
|
||||
] : []),
|
||||
};
|
||||
],
|
||||
});
|
||||
return bundleConfig;
|
||||
};
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
// https://github.com/aspnet/JavaScriptServices/issues/1046
|
||||
|
||||
require('ts-node/register')
|
||||
module.exports = require("./webpack.config.ts");
|
|
@ -1,171 +1,171 @@
|
|||
{
|
||||
"Login": {
|
||||
"SignInButton": "Sign in",
|
||||
"UsernamePlaceholder": "Username",
|
||||
"PasswordPlaceholder": "Password",
|
||||
"RememberMe": "Remember Me",
|
||||
"ForgottenPassword": "Forgot your password?",
|
||||
"SignInButton": "Zaloguj się",
|
||||
"UsernamePlaceholder": "Nazwa użytkownika",
|
||||
"PasswordPlaceholder": "Hasło",
|
||||
"RememberMe": "Zapamiętaj mnie",
|
||||
"ForgottenPassword": "Nie pamiętasz hasła?",
|
||||
"Errors": {
|
||||
"IncorrectCredentials": "Incorrect username or password"
|
||||
"IncorrectCredentials": "Nieprawidłowa nazwa użytkownika lub hasło"
|
||||
}
|
||||
},
|
||||
"Common": {
|
||||
"ContinueButton": "Continue",
|
||||
"Available": "Available",
|
||||
"NotAvailable": "Not Available",
|
||||
"ProcessingRequest": "Processing Request",
|
||||
"PendingApproval": "Pending Approval",
|
||||
"RequestDenied": "Request Denied",
|
||||
"NotRequested": "Not Requested",
|
||||
"Requested": "Requested",
|
||||
"Request": "Request",
|
||||
"Denied": "Denied",
|
||||
"Approve": "Approve",
|
||||
"PartlyAvailable": "Partly Available",
|
||||
"ContinueButton": "Dalej",
|
||||
"Available": "Dostępny",
|
||||
"NotAvailable": "Niedostępny",
|
||||
"ProcessingRequest": "Przetwarzanie zgłoszenia",
|
||||
"PendingApproval": "Oczekujące na zatwierdzenie",
|
||||
"RequestDenied": "Zgłoszenie odrzucone",
|
||||
"NotRequested": "Nie zgłoszone",
|
||||
"Requested": "Zgłoszone",
|
||||
"Request": "Zgłoszenie",
|
||||
"Denied": "Odrzucone",
|
||||
"Approve": "Zatwierdź",
|
||||
"PartlyAvailable": "Dostępne częściowo",
|
||||
"Errors": {
|
||||
"Validation": "Please check your entered values"
|
||||
"Validation": "Sprawdź wprowadzone dane"
|
||||
}
|
||||
},
|
||||
"PasswordReset": {
|
||||
"EmailAddressPlaceholder": "Email Address",
|
||||
"ResetPasswordButton": "Reset Password"
|
||||
"EmailAddressPlaceholder": "Adres e-mail",
|
||||
"ResetPasswordButton": "Zresetuj hasło"
|
||||
},
|
||||
"LandingPage": {
|
||||
"OnlineHeading": "Currently Online",
|
||||
"OnlineParagraph": "The media server is currently online",
|
||||
"PartiallyOnlineHeading": "Partially Online",
|
||||
"PartiallyOnlineParagraph": "The media server is partially online.",
|
||||
"MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.",
|
||||
"SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.",
|
||||
"OfflineHeading": "Currently Offline",
|
||||
"OfflineParagraph": "The media server is currently offline.",
|
||||
"CheckPageForUpdates": "Check this page for continuous site updates."
|
||||
"OnlineHeading": "Dostępny",
|
||||
"OnlineParagraph": "Serwer mediów jest dostępny",
|
||||
"PartiallyOnlineHeading": "Dostępny częściowo",
|
||||
"PartiallyOnlineParagraph": "Serwer mediów jest dostępny częściowo.",
|
||||
"MultipleServersUnavailable": "{{serversUnavailable}} serwerów spośród {{totalServers}} jest niedostępnych.",
|
||||
"SingleServerUnavailable": "Jeden serwer spośród {{totalServers}} jest niedostępny.",
|
||||
"OfflineHeading": "Niedostępny",
|
||||
"OfflineParagraph": "Serwer mediów jest niedostępny.",
|
||||
"CheckPageForUpdates": "Tutaj znajdziesz aktualizacje dotyczące tej strony."
|
||||
},
|
||||
"NavigationBar": {
|
||||
"Search": "Search",
|
||||
"Requests": "Requests",
|
||||
"UserManagement": "User Management",
|
||||
"Issues": "Issues",
|
||||
"Donate": "Donate!",
|
||||
"DonateLibraryMaintainer": "Donate to Library Maintainer",
|
||||
"DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)",
|
||||
"UpdateAvailableTooltip": "Update Available!",
|
||||
"Settings": "Settings",
|
||||
"Welcome": "Welcome {{username}}",
|
||||
"UpdateDetails": "Update Details",
|
||||
"Logout": "Logout",
|
||||
"Search": "Szukaj",
|
||||
"Requests": "Zgłoszenia",
|
||||
"UserManagement": "Zarządzanie użytkownikami",
|
||||
"Issues": "Problemy",
|
||||
"Donate": "Wesprzyj!",
|
||||
"DonateLibraryMaintainer": "Wesprzyj właściciela biblioteki",
|
||||
"DonateTooltip": "W ten sposób przekonuję moją żonę by spędzać mój wolny czas rozwijając Ombi ;)",
|
||||
"UpdateAvailableTooltip": "Dostępna aktualizacja!",
|
||||
"Settings": "Ustawienia",
|
||||
"Welcome": "Witaj {{username}}",
|
||||
"UpdateDetails": "Podaj szczegóły",
|
||||
"Logout": "Wyloguj",
|
||||
"Language": {
|
||||
"English": "English",
|
||||
"French": "French",
|
||||
"Spanish": "Spanish",
|
||||
"German": "German",
|
||||
"Italian": "Italian",
|
||||
"Danish": "Danish",
|
||||
"Dutch": "Dutch",
|
||||
"Norwegian": "Norwegian",
|
||||
"BrazillianPortuguese": "Brazillian Portuguese",
|
||||
"Polish": "Polish"
|
||||
"English": "Angielski",
|
||||
"French": "Francuski",
|
||||
"Spanish": "Hiszpański",
|
||||
"German": "Niemiecki",
|
||||
"Italian": "Włoski",
|
||||
"Danish": "Duński",
|
||||
"Dutch": "Holenderski",
|
||||
"Norwegian": "Norweski",
|
||||
"BrazillianPortuguese": "Brazylijski portugalski",
|
||||
"Polish": "Polski"
|
||||
},
|
||||
"OpenMobileApp": "Open Mobile App",
|
||||
"RecentlyAdded": "Recently Added"
|
||||
"OpenMobileApp": "Otwórz aplikację mobilną",
|
||||
"RecentlyAdded": "Ostatnio dodane"
|
||||
},
|
||||
"Search": {
|
||||
"Title": "Search",
|
||||
"Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!",
|
||||
"MoviesTab": "Movies",
|
||||
"TvTab": "TV Shows",
|
||||
"Suggestions": "Suggestions",
|
||||
"NoResults": "Sorry, we didn't find any results!",
|
||||
"DigitalDate": "Digital Release: {{date}}",
|
||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||
"ViewOnPlex": "View On Plex",
|
||||
"ViewOnEmby": "View On Emby",
|
||||
"RequestAdded": "Request for {{title}} has been added successfully",
|
||||
"Similar": "Similar",
|
||||
"Title": "Szukaj",
|
||||
"Paragraph": "Chcesz obejrzeć coś, co nie jest obecnie dostępne? Żaden problem, po prostu wyszukaj poniżej i dodaj zgłoszenie!",
|
||||
"MoviesTab": "Filmy",
|
||||
"TvTab": "Seriale",
|
||||
"Suggestions": "Sugestie",
|
||||
"NoResults": "Niestety nic nie znaleziono!",
|
||||
"DigitalDate": "Wydanie cyfrowe: {{date}}",
|
||||
"TheatricalRelease": "Premiera kinowa: {{date}}",
|
||||
"ViewOnPlex": "Obejrzyj w Plex",
|
||||
"ViewOnEmby": "Obejrzyj na Emby",
|
||||
"RequestAdded": "Zgłoszenie dla {{title}} zostało dodane",
|
||||
"Similar": "Podobne",
|
||||
"Movies": {
|
||||
"PopularMovies": "Popular Movies",
|
||||
"UpcomingMovies": "Upcoming Movies",
|
||||
"TopRatedMovies": "Top Rated Movies",
|
||||
"NowPlayingMovies": "Now Playing Movies",
|
||||
"HomePage": "Home Page",
|
||||
"Trailer": "Trailer"
|
||||
"PopularMovies": "Popularne filmy",
|
||||
"UpcomingMovies": "Wkrótce w kinach",
|
||||
"TopRatedMovies": "Najwyżej oceniane filmy",
|
||||
"NowPlayingMovies": "W kinach",
|
||||
"HomePage": "Strona główna",
|
||||
"Trailer": "Zwiastun"
|
||||
},
|
||||
"TvShows": {
|
||||
"Popular": "Popular",
|
||||
"Trending": "Trending",
|
||||
"MostWatched": "Most Watched",
|
||||
"MostAnticipated": "Most Anticipated",
|
||||
"Results": "Results",
|
||||
"AirDate": "Air Date:",
|
||||
"AllSeasons": "All Seasons",
|
||||
"FirstSeason": "First Season",
|
||||
"LatestSeason": "Latest Season",
|
||||
"Select": "Select ...",
|
||||
"SubmitRequest": "Submit Request",
|
||||
"Season": "Season: {{seasonNumber}}",
|
||||
"SelectAllInSeason": "Select All in Season {{seasonNumber}}"
|
||||
"Popular": "Popularne",
|
||||
"Trending": "Zyskujące popularność",
|
||||
"MostWatched": "Najczęściej oglądane",
|
||||
"MostAnticipated": "Najbardziej oczekiwane",
|
||||
"Results": "Wyniki",
|
||||
"AirDate": "Data emisji:",
|
||||
"AllSeasons": "Wszystkie sezony",
|
||||
"FirstSeason": "Pierwszy sezon",
|
||||
"LatestSeason": "Najnowszy sezon",
|
||||
"Select": "Wybierz…",
|
||||
"SubmitRequest": "Dodaj zgłoszenie",
|
||||
"Season": "Sezon: {{seasonNumber}}",
|
||||
"SelectAllInSeason": "Wybierz wszystkie w sezonie {{seasonNumber}}"
|
||||
}
|
||||
},
|
||||
"Requests": {
|
||||
"Title": "Requests",
|
||||
"Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.",
|
||||
"MoviesTab": "Movies",
|
||||
"TvTab": "TV Shows",
|
||||
"RequestedBy": "Requested By:",
|
||||
"Status": "Status:",
|
||||
"RequestStatus": "Request status:",
|
||||
"Denied": " Denied:",
|
||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||
"TheatricalReleaseSort": "Theatrical Release",
|
||||
"DigitalRelease": "Digital Release: {{date}}",
|
||||
"RequestDate": "Request Date:",
|
||||
"QualityOverride": "Quality Override:",
|
||||
"RootFolderOverride": "Root Folder Override:",
|
||||
"ChangeRootFolder": "Root Folder",
|
||||
"ChangeQualityProfile": "Quality Profile",
|
||||
"MarkUnavailable": "Mark Unavailable",
|
||||
"MarkAvailable": "Mark Available",
|
||||
"Remove": "Remove",
|
||||
"Deny": "Deny",
|
||||
"Season": "Season:",
|
||||
"GridTitle": "Title",
|
||||
"AirDate": "AirDate",
|
||||
"GridStatus": "Status",
|
||||
"ReportIssue": "Report Issue",
|
||||
"Filter": "Filter",
|
||||
"Sort": "Sort",
|
||||
"SeasonNumberHeading": "Season: {seasonNumber}",
|
||||
"SortTitleAsc": "Title ▲",
|
||||
"SortTitleDesc": "Title ▼",
|
||||
"SortRequestDateAsc": "Request Date ▲",
|
||||
"SortRequestDateDesc": "Request Date ▼",
|
||||
"SortStatusAsc": "Status ▲",
|
||||
"SortStatusDesc": "Status ▼"
|
||||
"Title": "Zgłoszenia",
|
||||
"Paragraph": "Poniżej są twoje i wszystkie inne zgłoszenia, a także ich status akceptacji i pobierania.",
|
||||
"MoviesTab": "Filmy",
|
||||
"TvTab": "Seriale",
|
||||
"RequestedBy": "Zgłoszone przez:",
|
||||
"Status": "Stan:",
|
||||
"RequestStatus": "Stan zgłoszenia:",
|
||||
"Denied": "Odrzucono:",
|
||||
"TheatricalRelease": "Premiera kinowa: {{date}}",
|
||||
"TheatricalReleaseSort": "Premiera kinowa",
|
||||
"DigitalRelease": "Wydanie cyfrowe: {{date}}",
|
||||
"RequestDate": "Data zgłoszenia:",
|
||||
"QualityOverride": "Wymuszenie jakości:",
|
||||
"RootFolderOverride": "Wymuszenie folderu głównego:",
|
||||
"ChangeRootFolder": "Folder główny",
|
||||
"ChangeQualityProfile": "Wybór jakości",
|
||||
"MarkUnavailable": "Oznacz jako niedostępne",
|
||||
"MarkAvailable": "Oznacz jako dostępne",
|
||||
"Remove": "Usuń",
|
||||
"Deny": "Odrzuć",
|
||||
"Season": "Sezon:",
|
||||
"GridTitle": "Tytuł",
|
||||
"AirDate": "Data emisji",
|
||||
"GridStatus": "Stan",
|
||||
"ReportIssue": "Zgłoś problem",
|
||||
"Filter": "Filtr",
|
||||
"Sort": "Sortowanie",
|
||||
"SeasonNumberHeading": "Sezon: {seasonNumber}",
|
||||
"SortTitleAsc": "Tytuł ▲",
|
||||
"SortTitleDesc": "Tytuł ▼",
|
||||
"SortRequestDateAsc": "Data zgłoszenia ▲",
|
||||
"SortRequestDateDesc": "Data zgłoszenia ▼",
|
||||
"SortStatusAsc": "Stan ▲",
|
||||
"SortStatusDesc": "Stan ▼"
|
||||
},
|
||||
"Issues": {
|
||||
"Title": "Issues",
|
||||
"PendingTitle": "Pending Issues",
|
||||
"InProgressTitle": "In Progress Issues",
|
||||
"ResolvedTitle": "Resolved Issues",
|
||||
"ColumnTitle": "Title",
|
||||
"Category": "Category",
|
||||
"Status": "Status",
|
||||
"Details": "Details",
|
||||
"Description": "Description",
|
||||
"NoComments": "No Comments!",
|
||||
"MarkInProgress": "Mark In Progress",
|
||||
"MarkResolved": "Mark Resolved",
|
||||
"SendMessageButton": "Send",
|
||||
"Subject": "Subject",
|
||||
"Comments": "Comments",
|
||||
"WriteMessagePlaceholder": "Write your message here...",
|
||||
"ReportedBy": "Reported By"
|
||||
"Title": "Problemy",
|
||||
"PendingTitle": "Oczekujące problemy",
|
||||
"InProgressTitle": "Problemy w trakcie",
|
||||
"ResolvedTitle": "Problemy rozwiązane",
|
||||
"ColumnTitle": "Tytuł",
|
||||
"Category": "Kategoria",
|
||||
"Status": "Stan",
|
||||
"Details": "Szczegóły",
|
||||
"Description": "Opis",
|
||||
"NoComments": "Brak komentarzy!",
|
||||
"MarkInProgress": "Oznacz jako \"w trakcie\"",
|
||||
"MarkResolved": "Oznacz jako rozwiązane",
|
||||
"SendMessageButton": "Wyślij",
|
||||
"Subject": "Temat",
|
||||
"Comments": "Komentarze",
|
||||
"WriteMessagePlaceholder": "Tutaj wpisz swoją wiadomość…",
|
||||
"ReportedBy": "Zgłoszone przez"
|
||||
},
|
||||
"Filter": {
|
||||
"ClearFilter": "Clear Filter",
|
||||
"FilterHeaderAvailability": "Availability",
|
||||
"FilterHeaderRequestStatus": "Status",
|
||||
"Approved": "Approved",
|
||||
"PendingApproval": "Pending Approval"
|
||||
"ClearFilter": "Wyczyść fltr",
|
||||
"FilterHeaderAvailability": "Dostępność",
|
||||
"FilterHeaderRequestStatus": "Stan",
|
||||
"Approved": "Zatwierdzone",
|
||||
"PendingApproval": "Oczekujące na zatwierdzenie"
|
||||
}
|
||||
}
|
|
@ -1,171 +1,171 @@
|
|||
{
|
||||
"Login": {
|
||||
"SignInButton": "Sign in",
|
||||
"UsernamePlaceholder": "Username",
|
||||
"PasswordPlaceholder": "Password",
|
||||
"RememberMe": "Remember Me",
|
||||
"ForgottenPassword": "Forgot your password?",
|
||||
"SignInButton": "Registrar",
|
||||
"UsernamePlaceholder": "Nome de usuário",
|
||||
"PasswordPlaceholder": "Senha",
|
||||
"RememberMe": "Lembre-se de mim",
|
||||
"ForgottenPassword": "Esqueceu sua senha?",
|
||||
"Errors": {
|
||||
"IncorrectCredentials": "Incorrect username or password"
|
||||
"IncorrectCredentials": "Nome de usuário ou senha incorretos"
|
||||
}
|
||||
},
|
||||
"Common": {
|
||||
"ContinueButton": "Continue",
|
||||
"Available": "Available",
|
||||
"NotAvailable": "Not Available",
|
||||
"ProcessingRequest": "Processing Request",
|
||||
"PendingApproval": "Pending Approval",
|
||||
"RequestDenied": "Request Denied",
|
||||
"NotRequested": "Not Requested",
|
||||
"Requested": "Requested",
|
||||
"Request": "Request",
|
||||
"Denied": "Denied",
|
||||
"Approve": "Approve",
|
||||
"PartlyAvailable": "Partly Available",
|
||||
"ContinueButton": "Continuar",
|
||||
"Available": "Disponível",
|
||||
"NotAvailable": "Inisponível",
|
||||
"ProcessingRequest": "Processando Solicitação",
|
||||
"PendingApproval": "Aprovação Pendente",
|
||||
"RequestDenied": "Solicitação Negada",
|
||||
"NotRequested": "Não Solicitado",
|
||||
"Requested": "Solicitado",
|
||||
"Request": "Solicitar",
|
||||
"Denied": "Negado",
|
||||
"Approve": "Aprovar",
|
||||
"PartlyAvailable": "Parcialmente Disponível",
|
||||
"Errors": {
|
||||
"Validation": "Please check your entered values"
|
||||
"Validation": "Por favor, verifique os dados inseridos"
|
||||
}
|
||||
},
|
||||
"PasswordReset": {
|
||||
"EmailAddressPlaceholder": "Email Address",
|
||||
"ResetPasswordButton": "Reset Password"
|
||||
"EmailAddressPlaceholder": "Endereço de e-mail",
|
||||
"ResetPasswordButton": "Redefinir Senha"
|
||||
},
|
||||
"LandingPage": {
|
||||
"OnlineHeading": "Currently Online",
|
||||
"OnlineParagraph": "The media server is currently online",
|
||||
"PartiallyOnlineHeading": "Partially Online",
|
||||
"PartiallyOnlineParagraph": "The media server is partially online.",
|
||||
"MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.",
|
||||
"SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.",
|
||||
"OfflineHeading": "Currently Offline",
|
||||
"OfflineParagraph": "The media server is currently offline.",
|
||||
"CheckPageForUpdates": "Check this page for continuous site updates."
|
||||
"OnlineHeading": "Online Agora",
|
||||
"OnlineParagraph": "O servidor de mídia está atualmente online",
|
||||
"PartiallyOnlineHeading": "Parcialmente Online",
|
||||
"PartiallyOnlineParagraph": "O servidor de mídia está parcialmente online.",
|
||||
"MultipleServersUnavailable": "Existem {{serversUnavailable}} servidores offline em um total de {{totalServers}}.",
|
||||
"SingleServerUnavailable": "Existe {{serversUnavailable}} servidor offline em um total de {{totalServers}}.",
|
||||
"OfflineHeading": "Offline Agora",
|
||||
"OfflineParagraph": "O servidor de mídia está atualmente offline.",
|
||||
"CheckPageForUpdates": "Verifique esta página para atualizações contínuas do site."
|
||||
},
|
||||
"NavigationBar": {
|
||||
"Search": "Search",
|
||||
"Requests": "Requests",
|
||||
"UserManagement": "User Management",
|
||||
"Issues": "Issues",
|
||||
"Donate": "Donate!",
|
||||
"DonateLibraryMaintainer": "Donate to Library Maintainer",
|
||||
"DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)",
|
||||
"UpdateAvailableTooltip": "Update Available!",
|
||||
"Settings": "Settings",
|
||||
"Welcome": "Welcome {{username}}",
|
||||
"UpdateDetails": "Update Details",
|
||||
"Logout": "Logout",
|
||||
"Search": "Pesquisar",
|
||||
"Requests": "Solicitações",
|
||||
"UserManagement": "Gerenciador de Usuário",
|
||||
"Issues": "Problemas",
|
||||
"Donate": "Fazer uma doação!",
|
||||
"DonateLibraryMaintainer": "Doar para o Dono da Biblioteca",
|
||||
"DonateTooltip": "É assim que eu convenço a minha mulher a deixar-me passar o meu tempo livre desenvolvendo Ombi;)",
|
||||
"UpdateAvailableTooltip": "Atualização Disponível!",
|
||||
"Settings": "Configurações",
|
||||
"Welcome": "Bem-vindo, {{username}}",
|
||||
"UpdateDetails": "Detalhes da Atualização",
|
||||
"Logout": "Sair",
|
||||
"Language": {
|
||||
"English": "English",
|
||||
"French": "French",
|
||||
"Spanish": "Spanish",
|
||||
"German": "German",
|
||||
"Italian": "Italian",
|
||||
"Danish": "Danish",
|
||||
"Dutch": "Dutch",
|
||||
"Norwegian": "Norwegian",
|
||||
"BrazillianPortuguese": "Brazillian Portuguese",
|
||||
"Polish": "Polish"
|
||||
"English": "Inglês",
|
||||
"French": "Francês",
|
||||
"Spanish": "Espanhol",
|
||||
"German": "Alemão",
|
||||
"Italian": "Italiano",
|
||||
"Danish": "Dinamarquês",
|
||||
"Dutch": "Holandês",
|
||||
"Norwegian": "Norueguês",
|
||||
"BrazillianPortuguese": "Português (Brasil)",
|
||||
"Polish": "Polonês"
|
||||
},
|
||||
"OpenMobileApp": "Open Mobile App",
|
||||
"RecentlyAdded": "Recently Added"
|
||||
"OpenMobileApp": "Abrir aplicativo do celular",
|
||||
"RecentlyAdded": "Recentemente adicionado"
|
||||
},
|
||||
"Search": {
|
||||
"Title": "Search",
|
||||
"Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!",
|
||||
"MoviesTab": "Movies",
|
||||
"TvTab": "TV Shows",
|
||||
"Suggestions": "Suggestions",
|
||||
"NoResults": "Sorry, we didn't find any results!",
|
||||
"DigitalDate": "Digital Release: {{date}}",
|
||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||
"ViewOnPlex": "View On Plex",
|
||||
"ViewOnEmby": "View On Emby",
|
||||
"RequestAdded": "Request for {{title}} has been added successfully",
|
||||
"Similar": "Similar",
|
||||
"Title": "Pesquisar",
|
||||
"Paragraph": "Quer assistir a algo que não está disponível? Não há problema, basta procurar abaixo e solicitar!",
|
||||
"MoviesTab": "Filmes",
|
||||
"TvTab": "Séries",
|
||||
"Suggestions": "Sugestões",
|
||||
"NoResults": "Desculpe, não encontramos nenhum resultado!",
|
||||
"DigitalDate": "Lançamento digital: {{date}}",
|
||||
"TheatricalRelease": "Lançamento nos Cinemas: {{date}}",
|
||||
"ViewOnPlex": "Assistir no Plex",
|
||||
"ViewOnEmby": "Assistir no Emby",
|
||||
"RequestAdded": "Pedido de {{title}} foi adicionado com sucesso",
|
||||
"Similar": "Semelhante",
|
||||
"Movies": {
|
||||
"PopularMovies": "Popular Movies",
|
||||
"UpcomingMovies": "Upcoming Movies",
|
||||
"TopRatedMovies": "Top Rated Movies",
|
||||
"NowPlayingMovies": "Now Playing Movies",
|
||||
"PopularMovies": "Filmes populares",
|
||||
"UpcomingMovies": "Próximos filmes",
|
||||
"TopRatedMovies": "Filmes mais votados",
|
||||
"NowPlayingMovies": "Filmes em cartazes",
|
||||
"HomePage": "Home Page",
|
||||
"Trailer": "Trailer"
|
||||
},
|
||||
"TvShows": {
|
||||
"Popular": "Popular",
|
||||
"Trending": "Trending",
|
||||
"MostWatched": "Most Watched",
|
||||
"MostAnticipated": "Most Anticipated",
|
||||
"Results": "Results",
|
||||
"AirDate": "Air Date:",
|
||||
"AllSeasons": "All Seasons",
|
||||
"FirstSeason": "First Season",
|
||||
"LatestSeason": "Latest Season",
|
||||
"Select": "Select ...",
|
||||
"SubmitRequest": "Submit Request",
|
||||
"Season": "Season: {{seasonNumber}}",
|
||||
"SelectAllInSeason": "Select All in Season {{seasonNumber}}"
|
||||
"Trending": "Mais populares",
|
||||
"MostWatched": "Mais assistidos",
|
||||
"MostAnticipated": "Mais esperados",
|
||||
"Results": "Resultados",
|
||||
"AirDate": "Data de exibição:",
|
||||
"AllSeasons": "Todas as temporadas",
|
||||
"FirstSeason": "Primeira temporada",
|
||||
"LatestSeason": "Última temporada",
|
||||
"Select": "Selecione...",
|
||||
"SubmitRequest": "Enviar solicitação",
|
||||
"Season": "Temporada: {{seasonNumber}}",
|
||||
"SelectAllInSeason": "Selecione tudo na temporada {{seasonNumber}}"
|
||||
}
|
||||
},
|
||||
"Requests": {
|
||||
"Title": "Requests",
|
||||
"Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.",
|
||||
"MoviesTab": "Movies",
|
||||
"TvTab": "TV Shows",
|
||||
"RequestedBy": "Requested By:",
|
||||
"Title": "Solicitações",
|
||||
"Paragraph": "Abaixo, você pode ver o seu e todos os outros pedidos, bem como o seu download e status de aprovação.",
|
||||
"MoviesTab": "Filmes",
|
||||
"TvTab": "Séries",
|
||||
"RequestedBy": "Solicitado por:",
|
||||
"Status": "Status:",
|
||||
"RequestStatus": "Request status:",
|
||||
"Denied": " Denied:",
|
||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||
"TheatricalReleaseSort": "Theatrical Release",
|
||||
"DigitalRelease": "Digital Release: {{date}}",
|
||||
"RequestDate": "Request Date:",
|
||||
"QualityOverride": "Quality Override:",
|
||||
"RootFolderOverride": "Root Folder Override:",
|
||||
"ChangeRootFolder": "Root Folder",
|
||||
"ChangeQualityProfile": "Quality Profile",
|
||||
"MarkUnavailable": "Mark Unavailable",
|
||||
"MarkAvailable": "Mark Available",
|
||||
"Remove": "Remove",
|
||||
"Deny": "Deny",
|
||||
"Season": "Season:",
|
||||
"GridTitle": "Title",
|
||||
"AirDate": "AirDate",
|
||||
"RequestStatus": "Status da solicitação:",
|
||||
"Denied": " Negados:",
|
||||
"TheatricalRelease": "Lançamento nos Cinemas: {{date}}",
|
||||
"TheatricalReleaseSort": "Lançamento nos Cinemas",
|
||||
"DigitalRelease": "Lançamento digital: {{date}}",
|
||||
"RequestDate": "Data da Solicitação:",
|
||||
"QualityOverride": "Substituição de qualidade:",
|
||||
"RootFolderOverride": "Substituição da pasta raiz:",
|
||||
"ChangeRootFolder": "Pasta raiz",
|
||||
"ChangeQualityProfile": "Perfil de qualidade",
|
||||
"MarkUnavailable": "Marcar como Indisponível",
|
||||
"MarkAvailable": "Marcar como Disponível",
|
||||
"Remove": "Remover",
|
||||
"Deny": "Negar",
|
||||
"Season": "Temporada:",
|
||||
"GridTitle": "Título",
|
||||
"AirDate": "Data de exibição",
|
||||
"GridStatus": "Status",
|
||||
"ReportIssue": "Report Issue",
|
||||
"Filter": "Filter",
|
||||
"Sort": "Sort",
|
||||
"SeasonNumberHeading": "Season: {seasonNumber}",
|
||||
"SortTitleAsc": "Title ▲",
|
||||
"SortTitleDesc": "Title ▼",
|
||||
"SortRequestDateAsc": "Request Date ▲",
|
||||
"SortRequestDateDesc": "Request Date ▼",
|
||||
"ReportIssue": "Relatar Problema",
|
||||
"Filter": "Filtro",
|
||||
"Sort": "Ordenar por",
|
||||
"SeasonNumberHeading": "Temporada: {seasonNumber}",
|
||||
"SortTitleAsc": "Título ▲",
|
||||
"SortTitleDesc": "Título ▼",
|
||||
"SortRequestDateAsc": "Data da Solicitação",
|
||||
"SortRequestDateDesc": "Data da Solicitação",
|
||||
"SortStatusAsc": "Status ▲",
|
||||
"SortStatusDesc": "Status ▼"
|
||||
},
|
||||
"Issues": {
|
||||
"Title": "Issues",
|
||||
"PendingTitle": "Pending Issues",
|
||||
"InProgressTitle": "In Progress Issues",
|
||||
"ResolvedTitle": "Resolved Issues",
|
||||
"ColumnTitle": "Title",
|
||||
"Category": "Category",
|
||||
"Title": "Problemas",
|
||||
"PendingTitle": "Problemas pendentes",
|
||||
"InProgressTitle": "Resolvendo Problemas",
|
||||
"ResolvedTitle": "Problemas Resolvidos",
|
||||
"ColumnTitle": "Título",
|
||||
"Category": "Categoria",
|
||||
"Status": "Status",
|
||||
"Details": "Details",
|
||||
"Description": "Description",
|
||||
"NoComments": "No Comments!",
|
||||
"MarkInProgress": "Mark In Progress",
|
||||
"MarkResolved": "Mark Resolved",
|
||||
"SendMessageButton": "Send",
|
||||
"Subject": "Subject",
|
||||
"Comments": "Comments",
|
||||
"WriteMessagePlaceholder": "Write your message here...",
|
||||
"ReportedBy": "Reported By"
|
||||
"Details": "Detalhes",
|
||||
"Description": "Descrição",
|
||||
"NoComments": "Sem Comentários!",
|
||||
"MarkInProgress": "Marcar como em andamento",
|
||||
"MarkResolved": "Marcar como resolvido",
|
||||
"SendMessageButton": "Enviar",
|
||||
"Subject": "Assunto",
|
||||
"Comments": "Comentários",
|
||||
"WriteMessagePlaceholder": "Escreva sua mensagem aqui...",
|
||||
"ReportedBy": "Reportado por"
|
||||
},
|
||||
"Filter": {
|
||||
"ClearFilter": "Clear Filter",
|
||||
"FilterHeaderAvailability": "Availability",
|
||||
"ClearFilter": "Limpar Filtro",
|
||||
"FilterHeaderAvailability": "Disponibilidade",
|
||||
"FilterHeaderRequestStatus": "Status",
|
||||
"Approved": "Approved",
|
||||
"PendingApproval": "Pending Approval"
|
||||
"Approved": "Aprovado",
|
||||
"PendingApproval": "Aprovação Pendente"
|
||||
}
|
||||
}
|
3325
src/Ombi/yarn.lock
3325
src/Ombi/yarn.lock
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue