mirror of https://github.com/Ombi-app/Ombi
parent
dd48149ad9
commit
d5e85ffdac
@ -0,0 +1,47 @@
|
||||
name: 'Chromatic'
|
||||
|
||||
# Event for the workflow
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
# List of jobs
|
||||
jobs:
|
||||
storybook-build:
|
||||
# Operating System
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: NodeModules Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node_modules-${{ hashFiles('**/yarn.lock') }}
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: ./src/Ombi/ClientApp
|
||||
run: yarn
|
||||
|
||||
- name: Publish to Chromatic
|
||||
if: github.ref != 'refs/heads/master'
|
||||
uses: chromaui/action@v1
|
||||
with:
|
||||
projectToken: 7c47e1a1a4bd
|
||||
exitZeroOnChanges: true
|
||||
workingDir: ./src/Ombi/ClientApp
|
||||
buildScriptName: storybookbuild
|
||||
exitOnceUploaded: true
|
||||
|
||||
- name: Publish to Chromatic and auto accept changes
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: chromaui/action@v1
|
||||
with:
|
||||
projectToken: 7c47e1a1a4bd
|
||||
autoAcceptChanges: true # 👈 Option to accept all changes
|
||||
workingDir: ./src/Ombi/ClientApp
|
||||
buildScriptName: storybookbuild
|
||||
exitOnceUploaded: true
|
@ -0,0 +1,16 @@
|
||||
module.exports = {
|
||||
"stories": [
|
||||
"../src/**/*.stories.mdx",
|
||||
"../src/**/*.stories.@(js|jsx|ts|tsx)"
|
||||
],
|
||||
"addons": [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-interactions"
|
||||
],
|
||||
"framework": "@storybook/angular",
|
||||
"core": {
|
||||
"builder": "@storybook/builder-webpack5"
|
||||
},
|
||||
"staticDirs": ['../../wwwroot/images']
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<style>
|
||||
.test-class {
|
||||
background-color: purple;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,14 @@
|
||||
import { setCompodocJson } from "@storybook/addon-docs/angular";
|
||||
import docJson from "../documentation.json";
|
||||
setCompodocJson(docJson);
|
||||
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/,
|
||||
},
|
||||
},
|
||||
docs: { inlineStories: true },
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"extends": "../src/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"typeRoots": [
|
||||
"../node_modules/@typings"
|
||||
],
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"exclude": [
|
||||
"../src/test.ts",
|
||||
"../src/**/*.spec.ts",
|
||||
"../projects/**/*.spec.ts"
|
||||
],
|
||||
"include": [
|
||||
"../src/**/*",
|
||||
"../projects/**/*"
|
||||
],
|
||||
"files": [
|
||||
"./typings.d.ts"
|
||||
]
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
declare module '*.md' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
{
|
||||
"pipes": [],
|
||||
"interfaces": [],
|
||||
"injectables": [],
|
||||
"guards": [],
|
||||
"interceptors": [],
|
||||
"classes": [],
|
||||
"directives": [],
|
||||
"components": [],
|
||||
"modules": [],
|
||||
"miscellaneous": [],
|
||||
"routes": [],
|
||||
"coverage": {
|
||||
"count": 0,
|
||||
"status": "low",
|
||||
"files": []
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
// also exported from '@storybook/angular' if you can deal with breaking changes in 6.1
|
||||
import { APP_BASE_HREF } from '@angular/common';
|
||||
import { Story, Meta, moduleMetadata } from '@storybook/angular';
|
||||
import { RequestType } from '../../interfaces';
|
||||
import { ImageComponent } from './image.component';
|
||||
|
||||
// More on default export: https://storybook.js.org/docs/angular/writing-stories/introduction#default-export
|
||||
export default {
|
||||
title: 'Image Component',
|
||||
component: ImageComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
providers: [
|
||||
{
|
||||
provide: APP_BASE_HREF,
|
||||
useValue: ""
|
||||
},
|
||||
]
|
||||
})
|
||||
]
|
||||
} as Meta;
|
||||
|
||||
// More on component templates: https://storybook.js.org/docs/angular/writing-stories/introduction#using-args
|
||||
const Template: Story<ImageComponent> = (args: ImageComponent) => ({
|
||||
props: args,
|
||||
});
|
||||
|
||||
export const Primary = Template.bind({});
|
||||
// More on args: https://storybook.js.org/docs/angular/writing-stories/args
|
||||
Primary.args = {
|
||||
src: 'https://ombi.io/img/logo-orange-small.png',
|
||||
type: RequestType.movie
|
||||
};
|
||||
|
||||
export const ClassApplied = Template.bind({});
|
||||
ClassApplied.args = {
|
||||
src: 'https://ombi.io/img/logo-orange-small.png',
|
||||
type: RequestType.movie,
|
||||
class: 'test-class'
|
||||
};
|
||||
|
||||
export const StyleApplied = Template.bind({});
|
||||
StyleApplied.args = {
|
||||
src: 'https://ombi.io/img/logo-orange-small.png',
|
||||
type: RequestType.movie,
|
||||
style: 'background-color: red;'
|
||||
};
|
||||
|
||||
export const IdApplied = Template.bind({});
|
||||
IdApplied.args = {
|
||||
src: 'https://ombi.io/img/logo-orange-small.png',
|
||||
type: RequestType.movie,
|
||||
id: 'testId123'
|
||||
};
|
||||
|
||||
// export const InvalidMovieImage = Template.bind({});
|
||||
// InvalidMovieImage.args = {
|
||||
// src: 'https://httpstat.us/429',
|
||||
// type: RequestType.movie,
|
||||
// id: 'testId123'
|
||||
// };
|
||||
|
||||
// export const InvalidTvImage = Template.bind({});
|
||||
// InvalidTvImage.args = {
|
||||
// src: 'https://httpstat.us/429',
|
||||
// type: RequestType.tvShow,
|
||||
// };
|
||||
|
||||
// export const InvalidMusicImage = Template.bind({});
|
||||
// InvalidMusicImage.args = {
|
||||
// src: 'https://httpstat.us/429',
|
||||
// type: RequestType.album,
|
||||
// };
|
@ -1,275 +0,0 @@
|
||||
import { PlatformLocation, APP_BASE_HREF } from "@angular/common";
|
||||
import { Component, Input, OnInit, Inject } from "@angular/core";
|
||||
import { DomSanitizer } from "@angular/platform-browser";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
import { Subject } from "rxjs";
|
||||
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
|
||||
|
||||
import { AuthService } from "../auth/auth.service";
|
||||
import { IIssueCategory, ILanguageRefine, IRequestEngineResult, ISearchMovieResult } from "../interfaces";
|
||||
import { NotificationService, RequestService, SearchService, SettingsService } from "../services";
|
||||
|
||||
import * as languageData from "../../other/iso-lang.json";
|
||||
|
||||
@Component({
|
||||
selector: "movie-search",
|
||||
templateUrl: "./moviesearch.component.html",
|
||||
styleUrls: ["./search.component.scss"],
|
||||
})
|
||||
export class MovieSearchComponent implements OnInit {
|
||||
|
||||
public searchText: string;
|
||||
public searchChanged: Subject<string> = new Subject<string>();
|
||||
public movieRequested: Subject<void> = new Subject<void>();
|
||||
public movieResults: ISearchMovieResult[];
|
||||
public result: IRequestEngineResult;
|
||||
|
||||
public searchApplied = false;
|
||||
public refineSearchEnabled = false;
|
||||
public searchYear?: number;
|
||||
public actorSearch: boolean;
|
||||
public selectedLanguage: string;
|
||||
public langauges: ILanguageRefine[];
|
||||
|
||||
@Input() public issueCategories: IIssueCategory[];
|
||||
@Input() public issuesEnabled: boolean;
|
||||
public issuesBarVisible = false;
|
||||
public issueRequestTitle: string;
|
||||
public issueRequestId: number;
|
||||
public issueProviderId: string;
|
||||
public issueCategorySelected: IIssueCategory;
|
||||
public defaultPoster: string;
|
||||
private href: string;
|
||||
|
||||
constructor(
|
||||
private searchService: SearchService, private requestService: RequestService,
|
||||
private notificationService: NotificationService, private authService: AuthService,
|
||||
private readonly translate: TranslateService, private sanitizer: DomSanitizer,
|
||||
@Inject(APP_BASE_HREF) href:string, private settingsService: SettingsService) {
|
||||
this.href= href;
|
||||
this.langauges = <ILanguageRefine[]><any>languageData;
|
||||
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;
|
||||
this.runSearch();
|
||||
});
|
||||
this.defaultPoster = "../../../images/default_movie_poster.png";
|
||||
const base = this.href;
|
||||
if (base) {
|
||||
this.defaultPoster = "../../.." + base + "/images/default_movie_poster.png";
|
||||
}
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
this.searchText = "";
|
||||
this.movieResults = [];
|
||||
this.result = {
|
||||
message: "",
|
||||
result: false,
|
||||
errorMessage: "",
|
||||
};
|
||||
this.settingsService.getDefaultLanguage().subscribe(x => this.selectedLanguage = x);
|
||||
this.popularMovies();
|
||||
}
|
||||
|
||||
public search(text: any) {
|
||||
this.searchChanged.next(text.target.value);
|
||||
}
|
||||
|
||||
public request(searchResult: ISearchMovieResult) {
|
||||
searchResult.requested = true;
|
||||
searchResult.requestProcessing = true;
|
||||
searchResult.showSubscribe = false;
|
||||
if (this.authService.hasRole("admin") || this.authService.hasRole("AutoApproveMovie")) {
|
||||
searchResult.approved = true;
|
||||
}
|
||||
|
||||
try {
|
||||
const language = this.selectedLanguage && this.selectedLanguage.length > 0 ? this.selectedLanguage : "en";
|
||||
this.requestService.requestMovie({ theMovieDbId: searchResult.id, languageCode: language })
|
||||
.subscribe(x => {
|
||||
this.result = x;
|
||||
if (this.result.result) {
|
||||
this.movieRequested.next();
|
||||
this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => {
|
||||
this.notificationService.success(x);
|
||||
searchResult.processed = true;
|
||||
});
|
||||
} else {
|
||||
if (this.result.errorMessage && this.result.message) {
|
||||
this.notificationService.warning("Request Added", `${this.result.message} - ${this.result.errorMessage}`);
|
||||
} else {
|
||||
this.notificationService.warning("Request Added", this.result.message ? this.result.message : this.result.errorMessage);
|
||||
}
|
||||
searchResult.requested = false;
|
||||
searchResult.approved = false;
|
||||
searchResult.processed = false;
|
||||
searchResult.requestProcessing = false;
|
||||
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
searchResult.processed = false;
|
||||
searchResult.requestProcessing = false;
|
||||
this.notificationService.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public popularMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.popularMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
public nowPlayingMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.nowPlayingMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
public topRatedMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.topRatedMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
public upcomingMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.upcomingMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
|
||||
public reportIssue(catId: IIssueCategory, req: ISearchMovieResult) {
|
||||
this.issueRequestId = req.id;
|
||||
const releaseDate = new Date(req.releaseDate);
|
||||
this.issueRequestTitle = req.title + ` (${releaseDate.getFullYear()})`;
|
||||
this.issueCategorySelected = catId;
|
||||
this.issuesBarVisible = true;
|
||||
this.issueProviderId = req.id.toString();
|
||||
}
|
||||
|
||||
public similarMovies(theMovieDbId: number) {
|
||||
this.clearResults();
|
||||
const lang = this.selectedLanguage && this.selectedLanguage.length > 0 ? this.selectedLanguage : "";
|
||||
this.searchService.similarMovies(theMovieDbId, lang)
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
|
||||
public subscribe(r: ISearchMovieResult) {
|
||||
r.subscribed = true;
|
||||
this.requestService.subscribeToMovie(r.requestId)
|
||||
.subscribe(x => {
|
||||
this.notificationService.success(`Subscribed To Movie ${r.title}!`);
|
||||
});
|
||||
}
|
||||
|
||||
public unSubscribe(r: ISearchMovieResult) {
|
||||
r.subscribed = false;
|
||||
this.requestService.unSubscribeToMovie(r.requestId)
|
||||
.subscribe(x => {
|
||||
this.notificationService.success("Unsubscribed Movie!");
|
||||
});
|
||||
}
|
||||
|
||||
public refineOpen() {
|
||||
this.refineSearchEnabled = !this.refineSearchEnabled;
|
||||
if (!this.refineSearchEnabled) {
|
||||
this.searchYear = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public applyRefinedSearch() {
|
||||
this.runSearch();
|
||||
}
|
||||
|
||||
private getExtraInfo() {
|
||||
|
||||
this.movieResults.forEach((val, index) => {
|
||||
if (val.posterPath === null) {
|
||||
val.posterPath = this.defaultPoster;
|
||||
} else {
|
||||
val.posterPath = "https://image.tmdb.org/t/p/w300/" + val.posterPath;
|
||||
}
|
||||
val.background = this.sanitizer.bypassSecurityTrustStyle
|
||||
("url(" + "https://image.tmdb.org/t/p/w1280" + val.backdropPath + ")");
|
||||
|
||||
if (this.applyRefinedSearch) {
|
||||
this.searchService.getMovieInformationWithRefined(val.id, this.selectedLanguage)
|
||||
.subscribe(m => {
|
||||
this.updateItem(val, m);
|
||||
});
|
||||
} else {
|
||||
this.searchService.getMovieInformation(val.id)
|
||||
.subscribe(m => {
|
||||
this.updateItem(val, m);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private updateItem(key: ISearchMovieResult, updated: ISearchMovieResult) {
|
||||
const index = this.movieResults.indexOf(key, 0);
|
||||
if (index > -1) {
|
||||
const copy = { ...this.movieResults[index] };
|
||||
this.movieResults[index] = updated;
|
||||
this.movieResults[index].background = copy.background;
|
||||
this.movieResults[index].posterPath = copy.posterPath;
|
||||
}
|
||||
}
|
||||
private clearResults() {
|
||||
this.movieResults = [];
|
||||
this.searchApplied = false;
|
||||
}
|
||||
|
||||
private runSearch() {
|
||||
if (this.searchText === "") {
|
||||
this.clearResults();
|
||||
return;
|
||||
}
|
||||
if (this.refineOpen) {
|
||||
if (!this.actorSearch) {
|
||||
this.searchService.searchMovieWithRefined(this.searchText, this.searchYear, this.selectedLanguage)
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.searchApplied = true;
|
||||
// Now let's load some extra info including IMDB Id
|
||||
// This way the search is fast at displaying results.
|
||||
this.getExtraInfo();
|
||||
});
|
||||
} else {
|
||||
this.searchService.searchMovieByActor(this.searchText, this.selectedLanguage)
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.searchApplied = true;
|
||||
// Now let's load some extra info including IMDB Id
|
||||
// This way the search is fast at displaying results.
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.searchService.searchMovie(this.searchText)
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.searchApplied = true;
|
||||
// Now let's load some extra info including IMDB Id
|
||||
// This way the search is fast at displaying results.
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { Subject } from "rxjs";
|
||||
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
|
||||
|
||||
import { AuthService } from "../auth/auth.service";
|
||||
import { IRequestEngineResult, ISearchMovieResult, ISearchMovieResultContainer } from "../interfaces";
|
||||
import { NotificationService, RequestService, SearchService } from "../services";
|
||||
|
||||
@Component({
|
||||
selector: "movie-search-grid",
|
||||
templateUrl: "./moviesearchgrid.component.html",
|
||||
})
|
||||
export class MovieSearchGridComponent implements OnInit {
|
||||
|
||||
public searchText: string;
|
||||
public searchChanged: Subject<string> = new Subject<string>();
|
||||
public movieResults: ISearchMovieResult[];
|
||||
public movieResultGrid: ISearchMovieResultContainer[] = [];
|
||||
public result: IRequestEngineResult;
|
||||
public searchApplied = false;
|
||||
|
||||
constructor(
|
||||
private searchService: SearchService, private requestService: RequestService,
|
||||
private notificationService: NotificationService, private authService: AuthService) {
|
||||
|
||||
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();
|
||||
return;
|
||||
}
|
||||
this.searchService.searchMovie(this.searchText)
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.searchApplied = true;
|
||||
// Now let's load some exta info including IMDBId
|
||||
// This way the search is fast at displaying results.
|
||||
this.getExtaInfo();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
this.searchText = "";
|
||||
this.movieResults = [];
|
||||
this.result = {
|
||||
message: "",
|
||||
result: false,
|
||||
errorMessage: "",
|
||||
};
|
||||
}
|
||||
|
||||
public search(text: any) {
|
||||
this.searchChanged.next(text.target.value);
|
||||
}
|
||||
|
||||
public request(searchResult: ISearchMovieResult) {
|
||||
searchResult.requested = true;
|
||||
searchResult.requestProcessing = true;
|
||||
if (this.authService.hasRole("admin") || this.authService.hasRole("AutoApproveMovie")) {
|
||||
searchResult.approved = true;
|
||||
}
|
||||
|
||||
try {
|
||||
this.requestService.requestMovie({ theMovieDbId: searchResult.id, languageCode: "en" })
|
||||
.subscribe(x => {
|
||||
this.result = x;
|
||||
|
||||
if (this.result.result) {
|
||||
this.notificationService.success(
|
||||
`Request for ${searchResult.title} has been added successfully`);
|
||||
searchResult.processed = true;
|
||||
} else {
|
||||
if (this.result.errorMessage && this.result.message) {
|
||||
this.notificationService.warning("Request Added", `${this.result.message} - ${this.result.errorMessage}`);
|
||||
} else {
|
||||
this.notificationService.warning("Request Added", this.result.message ? this.result.message : this.result.errorMessage);
|
||||
}
|
||||
searchResult.requested = false;
|
||||
searchResult.approved = false;
|
||||
searchResult.processed = false;
|
||||
searchResult.requestProcessing = false;
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
searchResult.processed = false;
|
||||
searchResult.requestProcessing = false;
|
||||
this.notificationService.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public popularMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.popularMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.processGrid(x);
|
||||
this.getExtaInfo();
|
||||
});
|
||||
}
|
||||
public nowPlayingMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.nowPlayingMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtaInfo();
|
||||
});
|
||||
}
|
||||
public topRatedMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.topRatedMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtaInfo();
|
||||
});
|
||||
}
|
||||
public upcomingMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.upcomingMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtaInfo();
|
||||
});
|
||||
}
|
||||
|
||||
private getExtaInfo() {
|
||||
this.movieResults.forEach((val) => {
|
||||
this.searchService.getMovieInformation(val.id)
|
||||
.subscribe(m => this.updateItem(val, m));
|
||||
});
|
||||
}
|
||||
|
||||
private updateItem(key: ISearchMovieResult, updated: ISearchMovieResult) {
|
||||
const index = this.movieResults.indexOf(key, 0);
|
||||
if (index > -1) {
|
||||
this.movieResults[index] = updated;
|
||||
}
|
||||
}
|
||||
|
||||
private clearResults() {
|
||||
this.movieResults = [];
|
||||
this.searchApplied = false;
|
||||
}
|
||||
|
||||
private processGrid(movies: ISearchMovieResult[]) {
|
||||
let container = <ISearchMovieResultContainer> { movies: [] };
|
||||
movies.forEach((movie, i) => {
|
||||
i++;
|
||||
if ((i % 4) === 0) {
|
||||
container.movies.push(movie);
|
||||
this.movieResultGrid.push(container);
|
||||
container = <ISearchMovieResultContainer> { movies: [] };
|
||||
} else {
|
||||
container.movies.push(movie);
|
||||
}
|
||||
});
|
||||
this.movieResultGrid.push(container);
|
||||
}
|
||||
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
<div class="row">
|
||||
<!--Backdrop-->
|
||||
<div class="album-bg backdrop" [style.background-image]="result.background"></div>
|
||||
<div class="album-tint" style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%);"></div>
|
||||
|
||||
<!--Album Art-->
|
||||
<div class="col-sm-12 small-padding">
|
||||
<img *ngIf="result.disk" class="img-responsive poster album-cover" src="{{result.disk}}" alt="poster">
|
||||
</div>
|
||||
|
||||
<!--Artist Title-->
|
||||
<div class="col-sm-12 small-padding">
|
||||
<div>
|
||||
<h4>
|
||||
<a href="" target="_blank">
|
||||
{{result.title | truncate: 36}}
|
||||
</a>
|
||||
|
||||
</h4>
|
||||
<h5>
|
||||
<a href="" (click)="selectArtist($event, result.foreignArtistId)">
|
||||
{{result.artistName}}
|
||||
</a>
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<!--Tags-->
|
||||
<div>
|
||||
<span class="tags">
|
||||
<!-- <span *ngIf="result.releaseDate" class="label label-info" id="releaseDateLabel" target="_blank">{{ 'Search.TheatricalRelease' | translate: {date: result.releaseDate | date: 'mediumDate'} }}</span>
|
||||
<span *ngIf="result.digitalReleaseDate" class="label label-info" id="releaseDateLabel" target="_blank">{{ 'Search.DigitalDate' | translate: {date: result.digitalReleaseDate | date: 'mediumDate'} }}</span>
|
||||
|
||||
<a *ngIf="result.homepage" href="{{result.homepage}}" id="homePageLabel" target="_blank"><span class="label label-info" [translate]="'Search.Movies.HomePage'"></span></a>
|
||||
|
||||
<a *ngIf="result.trailer" href="{{result.trailer}}" id="trailerLabel" target="_blank"><span class="label label-info" [translate]="'Search.Movies.Trailer'"></span></a> -->
|
||||
<ng-template [ngIf]="!result.requested && !result.fullyAvailable && !result.approved">
|
||||
<span class="label label-danger" id="notRequestedLabel" [translate]="'Common.NotRequested'"></span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="result.fullyAvailable">
|
||||
<span class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="result.partiallyAvailable">
|
||||
<span class="label label-info" id="availableLabel" [translate]="'Common.PartiallyAvailable'"></span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="result.monitored && !result.fullyAvailable">
|
||||
<span class="label label-info" id="processingRequestLabel" [translate]="'Common.Monitored'"></span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="result.requested && !result.approved && !result.partiallyAvailable">
|
||||
<span class="label label-warning" id="pendingApprovalLabel" [translate]="'Common.PendingApproval'"></span>
|
||||
</ng-template>
|
||||
|
||||
<ng-template [ngIf]="result.approved && !result.fullyAvailable"><span class="label label-info" id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span></ng-template>
|
||||
|
||||
|
||||
|
||||
<ng-template [ngIf]="result.releaseDate">
|
||||
<span class="label label-info" id="availableLabel">Release Date: {{result.releaseDate | amLocal | amUserLocale | amDateFormat: 'L'}}</span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="result.rating">
|
||||
<span class="label label-info" id="availableLabel">{{result.rating}}/10</span>
|
||||
</ng-template>
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Buttons-->
|
||||
<div class="col-sm-12 small-padding">
|
||||
<!-- <div class="row" *ngIf="result.requested">
|
||||
<div class="col-md-2 col-md-push-10">
|
||||
|
||||
<a *ngIf="result.showSubscribe && !result.subscribed" style="color:white" (click)="subscribe(result)" pTooltip="Subscribe for notifications"> <i class="fas fa-rss"></i></a>
|
||||
<a *ngIf="result.showSubscribe && result.subscribed" style="color:red" (click)="unSubscribe(result)" pTooltip="Unsubscribe notification"> <i class="fas fa-rss"></i></a>
|
||||
</div>
|
||||
</div> -->
|
||||
<div *ngIf="result.fullyAvailable">
|
||||
<button style="text-align: right" class="btn btn-success-outline disabled" disabled>
|
||||
<i class="fas fa-check"></i> {{ 'Common.Available' | translate }}</button>
|
||||
</div>
|
||||
<div *ngIf="!result.fullyAvailable">
|
||||
<div *ngIf="result.requested || result.approved || result.monitored; then requestedBtn else notRequestedBtn"></div>
|
||||
<ng-template #requestedBtn>
|
||||
<button style="text-align: right" class="btn btn-primary-outline disabled" [disabled]>
|
||||
<i class="fas fa-check"></i> {{ 'Common.Requested' | translate }}</button>
|
||||
</ng-template>
|
||||
<ng-template #notRequestedBtn>
|
||||
<button style="text-align: right" class="btn btn-primary-outline" (click)="request(result)">
|
||||
<i *ngIf="result.requestProcessing" class="fas fa-circle-notch fa-spin fa-fw"></i>
|
||||
<i *ngIf="!result.requestProcessing && !result.processed" class="fas fa-plus"></i>
|
||||
<i *ngIf="result.processed && !result.requestProcessing" class="fas fa-check"></i> {{ 'Common.Request'
|
||||
| translate }}</button>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="dropdown" *ngIf="(result.partiallyAvailable || result.fullyAvailable) && issueCategories && issuesEnabled">
|
||||
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="true">
|
||||
<i class="fas fa-plus"></i> Report Issue
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li *ngFor="let cat of issueCategories"><a [routerLink]="" (click)="reportIssue(cat, result)">{{cat.value}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<issue-report [movie]="true" [visible]="issuesBarVisible" (visibleChange)="issuesBarVisible = $event;" [title]="issueRequestTitle"
|
||||
[issueCategory]="issueCategorySelected" [id]="issueRequestId" [providerId]="issueProviderId"></issue-report>
|
@ -1,91 +0,0 @@
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
import { Subject } from "rxjs";
|
||||
import { AuthService } from "../../auth/auth.service";
|
||||
import { IIssueCategory, IRequestEngineResult } from "../../interfaces";
|
||||
import { ISearchAlbumResult } from "../../interfaces/ISearchMusicResult";
|
||||
import { NotificationService, RequestService } from "../../services";
|
||||
|
||||
@Component({
|
||||
selector: "album-search",
|
||||
templateUrl: "./albumsearch.component.html",
|
||||
})
|
||||
export class AlbumSearchComponent {
|
||||
|
||||
@Input() public result: ISearchAlbumResult;
|
||||
public engineResult: IRequestEngineResult;
|
||||
@Input() public defaultPoster: string;
|
||||
|
||||
@Input() public issueCategories: IIssueCategory[];
|
||||
@Input() public issuesEnabled: boolean;
|
||||
|
||||
@Input() public musicRequested: Subject<void>;
|
||||
public issuesBarVisible = false;
|
||||
public issueRequestTitle: string;
|
||||
public issueRequestId: number;
|
||||
public issueProviderId: string;
|
||||
public issueCategorySelected: IIssueCategory;
|
||||
|
||||
@Output() public setSearch = new EventEmitter<string>();
|
||||
|
||||
constructor(
|
||||
private requestService: RequestService,
|
||||
private notificationService: NotificationService, private authService: AuthService,
|
||||
private readonly translate: TranslateService) {
|
||||
}
|
||||
|
||||
public selectArtist(event: Event, artistId: string) {
|
||||
event.preventDefault();
|
||||
this.setSearch.emit(artistId);
|
||||
}
|
||||
|
||||
public reportIssue(catId: IIssueCategory, req: ISearchAlbumResult) {
|
||||
this.issueRequestId = req.id;
|
||||
this.issueRequestTitle = req.title + `(${req.releaseDate.getFullYear})`;
|
||||
this.issueCategorySelected = catId;
|
||||
this.issuesBarVisible = true;
|
||||
this.issueProviderId = req.id.toString();
|
||||
}
|
||||
|
||||
public request(searchResult: ISearchAlbumResult) {
|
||||
searchResult.requested = true;
|
||||
searchResult.requestProcessing = true;
|
||||
searchResult.showSubscribe = false;
|
||||
if (this.authService.hasRole("admin") || this.authService.hasRole("AutoApproveMusic")) {
|
||||
searchResult.approved = true;
|
||||
}
|
||||
|
||||
try {
|
||||
this.requestService.requestAlbum({ foreignAlbumId: searchResult.foreignAlbumId })
|
||||
.subscribe(x => {
|
||||
|
||||
this.engineResult = x;
|
||||
|
||||
if (this.engineResult.result) {
|
||||
this.musicRequested.next();
|
||||
this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => {
|
||||
this.notificationService.success(x);
|
||||
searchResult.processed = true;
|
||||
});
|
||||
} else {
|
||||
if (this.engineResult.errorMessage && this.engineResult.message) {
|
||||
this.notificationService.warning("Request Added", `${this.engineResult.message} - ${this.engineResult.errorMessage}`);
|
||||
} else {
|
||||
this.notificationService.warning("Request Added", this.engineResult.message ? this.engineResult.message : this.engineResult.errorMessage);
|
||||
}
|
||||
searchResult.requested = false;
|
||||
searchResult.approved = false;
|
||||
searchResult.processed = false;
|
||||
searchResult.requestProcessing = false;
|
||||
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
searchResult.processed = false;
|
||||
searchResult.requestProcessing = false;
|
||||
this.notificationService.error(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
<div class="row">
|
||||
|
||||
<div class="myBg backdrop" [style.background-image]="result.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-3 small-padding">
|
||||
<img *ngIf="result.poster" class="img-responsive poster artist-cover" src="{{result.poster}}" alt="poster">
|
||||
|
||||
</div>
|
||||
<div class="col-sm-7 small-padding">
|
||||
<div>
|
||||
<a href="" target="_blank">
|
||||
<h4>{{result.artistName}}</h4>
|
||||
</a>
|
||||
<span class="tags">
|
||||
<!-- <span *ngIf="result.releaseDate" class="label label-info" id="releaseDateLabel" target="_blank">{{ 'Search.TheatricalRelease' | translate: {date: result.releaseDate | date: 'mediumDate'} }}</span>
|
||||
<span *ngIf="result.digitalReleaseDate" class="label label-info" id="releaseDateLabel" target="_blank">{{ 'Search.DigitalDate' | translate: {date: result.digitalReleaseDate | date: 'mediumDate'} }}</span>
|
||||
|
||||
<a *ngIf="result.homepage" href="{{result.homepage}}" id="homePageLabel" target="_blank"><span class="label label-info" [translate]="'Search.Movies.HomePage'"></span></a>
|
||||
|
||||
<a *ngIf="result.trailer" href="{{result.trailer}}" id="trailerLabel" target="_blank"><span class="label label-info" [translate]="'Search.Movies.Trailer'"></span></a> -->
|
||||
|
||||
<ng-template [ngIf]="result.artistType">
|
||||
<span class="label label-info" id="artistType">{{result.artistType}}</span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="result.disambiguation">
|
||||
<span class="label label-info" id="disambiguation">{{result.disambiguation}}</span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="result.monitored">
|
||||
<span class="label label-info" id="disambiguation">Monitored</span>
|
||||
</ng-template>
|
||||
</span>
|
||||
|
||||
<br/>
|
||||
</div>
|
||||
<p style="font-size: 0.9rem !important">{{result.overview | truncate: 350 }}</p>
|
||||
|
||||
<div class="row">
|
||||
<a id="infoTags" *ngFor="let link of result.links" href="{{link.url}}" target="_blank" class="label label-primary">
|
||||
|
||||
{{link.name}}
|
||||
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2 small-padding">
|
||||
<div class="row" *ngIf="result.requested">
|
||||
<div class="col-md-2 col-md-push-10">
|
||||
|
||||
<!-- <a *ngIf="result.showSubscribe && !result.subscribed" style="color:white" (click)="subscribe(result)" pTooltip="Subscribe for notifications"> <i class="fas fa-rss"></i></a>
|
||||
<a *ngIf="result.showSubscribe && result.subscribed" style="color:red" (click)="unSubscribe(result)" pTooltip="Unsubscribe notification"> <i class="fas fa-rss"></i></a> -->
|
||||
</div>
|
||||
</div>
|
||||
<button style="text-align: right" class="btn btn-info-outline" [disabled]="searchingAlbums" (click)="viewAllAlbums()">
|
||||
<i class="far fa-eye"></i> View Albums</button>
|
||||
|
||||
</div>
|
||||
<!-- <button style="text-align: right" class="btn btn-sm btn-info-outline" (click)="similarMovies(result.id)"> <i class="far fa-eye"></i> {{ 'Search.Similar' | translate }}</button> -->
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
@ -1,27 +0,0 @@
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
|
||||
import { ISearchAlbumResult, ISearchArtistResult } from "../../interfaces/ISearchMusicResult";
|
||||
import { SearchService } from "../../services";
|
||||
|
||||
@Component({
|
||||
selector: "artist-search",
|
||||
templateUrl: "./artistsearch.component.html",
|
||||
})
|
||||
export class ArtistSearchComponent {
|
||||
|
||||
@Input() public result: ISearchArtistResult;
|
||||
@Input() public defaultPoster: string;
|
||||
public searchingAlbums: boolean;
|
||||
|
||||
@Output() public viewAlbumsResult = new EventEmitter<ISearchAlbumResult[]>();
|
||||
|
||||
constructor(private searchService: SearchService) {
|
||||
}
|
||||
|
||||
public viewAllAlbums() {
|
||||
this.searchingAlbums = true;
|
||||
this.searchService.getAlbumsForArtist(this.result.forignArtistId).subscribe(x => {
|
||||
this.viewAlbumsResult.emit(x);
|
||||
});
|
||||
}
|
||||
}
|
@ -1,149 +0,0 @@
|
||||
import { PlatformLocation, APP_BASE_HREF } from "@angular/common";
|
||||
import { Component, Input, OnInit, Inject } from "@angular/core";
|
||||
import { DomSanitizer } from "@angular/platform-browser";
|
||||
import { Subject } from "rxjs";
|
||||
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
|
||||
import { IIssueCategory, IRequestEngineResult } from "../../interfaces";
|
||||
import { ISearchAlbumResult, ISearchArtistResult } from "../../interfaces/ISearchMusicResult";
|
||||
import { SearchService } from "../../services";
|
||||
|
||||
@Component({
|
||||
selector: "music-search",
|
||||
templateUrl: "./musicsearch.component.html",
|
||||
})
|
||||
export class MusicSearchComponent implements OnInit {
|
||||
|
||||
public searchText: string;
|
||||
public searchChanged: Subject<string> = new Subject<string>();
|
||||
public artistResult: ISearchArtistResult[];
|
||||
public albumResult: ISearchAlbumResult[];
|
||||
public result: IRequestEngineResult;
|
||||
public searchApplied = false;
|
||||
public searchAlbum: boolean = true;
|
||||
|
||||
public musicRequested: Subject<void> = new Subject<void>();
|
||||
@Input() public issueCategories: IIssueCategory[];
|
||||
@Input() public issuesEnabled: boolean;
|
||||
public issuesBarVisible = false;
|
||||
public issueRequestTitle: string;
|
||||
public issueRequestId: number;
|
||||
public issueProviderId: string;
|
||||
public issueCategorySelected: IIssueCategory;
|
||||
public defaultPoster: string;
|
||||
|
||||
private href: string;
|
||||
constructor(
|
||||
private searchService: SearchService, private sanitizer: DomSanitizer,
|
||||
@Inject(APP_BASE_HREF) href:string) {
|
||||
this.href = href;
|
||||
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 === "") {
|
||||
if(this.searchAlbum) {
|
||||
this.clearAlbumResults();
|
||||
} else {
|
||||
this.clearArtistResults();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if(this.searchAlbum) {
|
||||
if(!this.searchText) {
|
||||
this.searchText = "iowa"; // REMOVE
|
||||
}
|
||||
this.searchService.searchAlbum(this.searchText)
|
||||
.subscribe(x => {
|
||||
this.albumResult = x;
|
||||
this.searchApplied = true;
|
||||
this.setAlbumBackground();
|
||||
});
|
||||
} else {
|
||||
this.searchService.searchArtist(this.searchText)
|
||||
.subscribe(x => {
|
||||
this.artistResult = x;
|
||||
this.searchApplied = true;
|
||||
this.setArtistBackground();
|
||||
});
|
||||
}
|
||||
});
|
||||
this.defaultPoster = "../../../images/default-music-placeholder.png";
|
||||
const base = this.href;
|
||||
if (base) {
|
||||
this.defaultPoster = "../../.." + base + "/images/default-music-placeholder.png";
|
||||
}
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
this.searchText = "";
|
||||
this.artistResult = [];
|
||||
this.result = {
|
||||
message: "",
|
||||
result: false,
|
||||
errorMessage: "",
|
||||
};
|
||||
}
|
||||
|
||||
public search(text: any) {
|
||||
this.searchChanged.next(text.target.value);
|
||||
}
|
||||
|
||||
public searchMode(val: boolean) {
|
||||
this.searchAlbum = val;
|
||||
if(val) {
|
||||
// Album
|
||||
this.clearArtistResults();
|
||||
} else {
|
||||
this.clearAlbumResults();
|
||||
}
|
||||
}
|
||||
|
||||
public setArtistSearch(artistId: string) {
|
||||
this.searchAlbum = false;
|
||||
this.clearAlbumResults();
|
||||
this.searchChanged.next(`lidarr:${artistId}`);
|
||||
}
|
||||
|
||||
public viewAlbumsForArtist(albums: ISearchAlbumResult[]) {
|
||||
this.clearArtistResults();
|
||||
this.searchAlbum = true;
|
||||
this.albumResult = albums;
|
||||
this.setAlbumBackground();
|
||||
}
|
||||
|
||||
private clearArtistResults() {
|
||||
this.artistResult = [];
|
||||
this.searchApplied = false;
|
||||
}
|
||||
|
||||
private clearAlbumResults() {
|
||||
this.albumResult = [];
|
||||
this.searchApplied = false;
|
||||
}
|
||||
|
||||
private setArtistBackground() {
|
||||
this.artistResult.forEach((val, index) => {
|
||||
if (val.poster === null) {
|
||||
val.poster = this.defaultPoster;
|
||||
}
|
||||
val.background = this.sanitizer.bypassSecurityTrustStyle
|
||||
("url(" + val.banner + ")");
|
||||
});
|
||||
}
|
||||
|
||||
private setAlbumBackground() {
|
||||
this.albumResult.forEach((val, index) => {
|
||||
if (val.disk === null) {
|
||||
if(val.cover === null) {
|
||||
val.disk = this.defaultPoster;
|
||||
} else {
|
||||
val.disk = val.cover;
|
||||
}
|
||||
}
|
||||
val.background = this.sanitizer.bypassSecurityTrustStyle
|
||||
("url(" + val.cover + ")");
|
||||
});
|
||||
}
|
||||
}
|
@ -1,238 +0,0 @@
|
||||
import { PlatformLocation, APP_BASE_HREF } from "@angular/common";
|
||||
import { Component, Input, OnInit, Inject } from "@angular/core";
|
||||
import { DomSanitizer } from "@angular/platform-browser";
|
||||
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";
|
||||
|
||||
@Component({
|
||||
selector: "tv-search",
|
||||
templateUrl: "./tvsearch.component.html",
|
||||
styleUrls: ["./../requests/tvrequests.component.scss"],
|
||||
})
|
||||
export class TvSearchComponent implements OnInit {
|
||||
|
||||
public searchText: string;
|
||||
public searchChanged = new Subject<string>();
|
||||
public tvResults: ISearchTvResult[];
|
||||
public tvRequested: Subject<void> = new Subject<void>();
|
||||
public result: IRequestEngineResult;
|
||||
public searchApplied = false;
|
||||
public defaultPoster: string;
|
||||
|
||||
@Input() public issueCategories: IIssueCategory[];
|
||||
@Input() public issuesEnabled: boolean;
|
||||
public issuesBarVisible = false;
|
||||
public issueRequestTitle: string;
|
||||
public issueRequestId: number;
|
||||
public issueProviderId: string;
|
||||
public issueCategorySelected: IIssueCategory;
|
||||
private href: string;
|
||||
|
||||
constructor(
|
||||
private searchService: SearchService, private requestService: RequestService,
|
||||
private notificationService: NotificationService, private authService: AuthService,
|
||||
private imageService: ImageService, private sanitizer: DomSanitizer,
|
||||
@Inject(APP_BASE_HREF) href:string) {
|
||||
this.href = href;
|
||||
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.searchTv(this.searchText)
|
||||
.subscribe(x => {
|
||||
this.tvResults = x;
|
||||
this.searchApplied = true;
|
||||
this.getExtraInfo();
|
||||
});
|
||||
});
|
||||
this.defaultPoster = "../../../images/default_tv_poster.png";
|
||||
const base = this.href;
|
||||
if (base) {
|
||||
this.defaultPoster = "../../.." + base + "/images/default_tv_poster.png";
|
||||
}
|
||||
}
|
||||
public openClosestTab(node: ISearchTvResult,el: any) {
|
||||
el.preventDefault();
|
||||
node.open = !node.open;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
this.searchText = "";
|
||||
this.tvResults = [];
|
||||
this.result = {
|
||||
message: "",
|
||||
result: false,
|
||||
errorMessage: "",
|
||||
};
|
||||
this.popularShows();
|
||||
}
|
||||
|
||||
public search(text: any) {
|
||||
this.searchChanged.next(text.target.value);
|
||||
}
|
||||
|
||||
public popularShows() {
|
||||
this.clearResults();
|
||||
this.searchService.popularTv()
|
||||
.subscribe(x => {
|
||||
this.tvResults = x;
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
|
||||
public trendingShows() {
|
||||
this.clearResults();
|
||||
this.searchService.trendingTv()
|
||||
.subscribe(x => {
|
||||
this.tvResults = x;
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
|
||||
public mostWatchedShows() {
|
||||
this.clearResults();
|
||||
this.searchService.mostWatchedTv()
|
||||
.subscribe(x => {
|
||||
this.tvResults = x;
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
|
||||
public anticipatedShows() {
|
||||
this.clearResults();
|
||||
this.searchService.anticipatedTv()
|
||||
.subscribe(x => {
|
||||
this.tvResults = x;
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
|
||||
public getExtraInfo() {
|
||||
this.tvResults.forEach((val, index) => {
|
||||
this.imageService.getTvBanner(val.id).subscribe(x => {
|
||||
if (x) {
|
||||
val.background = this.sanitizer.
|
||||
bypassSecurityTrustStyle
|
||||
("url(" + x + ")");
|
||||
}
|
||||
});
|
||||
this.searchService.getShowInformation(val.id)
|
||||
.subscribe(x => {
|
||||
if (x) {
|
||||
this.setDefaults(x);
|
||||
this.updateItem(val, x);
|
||||
} else {
|
||||
const index = this.tvResults.indexOf(val, 0);
|
||||
if (index > -1) {
|
||||
this.tvResults.splice(index, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public request(searchResult: ISearchTvResult) {
|
||||
searchResult.requested = true;
|
||||
if (this.authService.hasRole("admin") || this.authService.hasRole("AutoApproveMovie")) {
|
||||
searchResult.approved = true;
|
||||
}
|
||||
|
||||
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: [] };
|
||||
season.episodes.forEach(ep => {
|
||||
if (!searchResult.latestSeason || !searchResult.requestAll || !searchResult.firstSeason) {
|
||||
if (ep.requested) {
|
||||
seasonsViewModel.episodes.push({ episodeNumber: ep.episodeNumber });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
viewModel.seasons.push(seasonsViewModel);
|
||||
});
|
||||
|
||||
this.requestService.requestTv(viewModel)
|
||||
.subscribe(x => {
|
||||
this.tvRequested.next();
|
||||
this.result = x;
|
||||
if (this.result.result) {
|
||||
this.notificationService.success(
|
||||
`Request for ${searchResult.title} has been added successfully`);
|
||||
} else {
|
||||
if (this.result.errorMessage && this.result.message) {
|
||||
this.notificationService.warning("Request Added", `${this.result.message} - ${this.result.errorMessage}`);
|
||||
} else {
|
||||
this.notificationService.warning("Request Added", this.result.message ? this.result.message : this.result.errorMessage);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public allSeasons(searchResult: ISearchTvResult, event: any) {
|
||||
event.preventDefault();
|
||||
searchResult.requestAll = true;
|
||||
this.request(searchResult);
|
||||
}
|
||||
|
||||
public firstSeason(searchResult: ISearchTvResult, event: any) {
|
||||
event.preventDefault();
|
||||
searchResult.firstSeason = true;
|
||||
this.request(searchResult);
|
||||
}
|
||||
|
||||
public latestSeason(searchResult: ISearchTvResult, event: any) {
|
||||
event.preventDefault();
|
||||
searchResult.latestSeason = true;
|
||||
this.request(searchResult);
|
||||
}
|
||||
|
||||
public reportIssue(catId: IIssueCategory, req: ISearchTvResult) {
|
||||
this.issueRequestId = req.id;
|
||||
const firstAiredDate = new Date(req.firstAired);
|
||||
this.issueRequestTitle = req.title + ` (${firstAiredDate.getFullYear()})`;
|
||||
this.issueCategorySelected = catId;
|
||||
this.issuesBarVisible = true;
|
||||
this.issueProviderId = req.id.toString();
|
||||
}
|
||||
|
||||
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].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: ISearchTvResult) {
|
||||
if (x.banner === null) {
|
||||
x.banner = this.defaultPoster;
|
||||
}
|
||||
|
||||
if (x.imdbId === null) {
|
||||
x.imdbId = "https://www.tvmaze.com/shows/" + x.seriesId;
|
||||
} else {
|
||||
x.imdbId = "http://www.imdb.com/title/" + x.imdbId + "/";
|
||||
}
|
||||
}
|
||||
|
||||
private clearResults() {
|
||||
this.tvResults = [];
|
||||
this.searchApplied = false;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue