mirror of https://github.com/Ombi-app/Ombi
Merge pull request #3787 from tidusjar/feature/discover-grid-view
Feature/discover grid viewpull/3798/head
commit
63dc3f619c
@ -0,0 +1,136 @@
|
||||
<!-- <div class="card-spacing" *ngIf="result">
|
||||
<mat-card class="mat-elevation-z8 dark-card grow">
|
||||
<a [routerLink]="result.type === RequestType.movie ? '/details/movie/' + result.id : '/details/tv/' + result.id">
|
||||
<img id="cardImage" mat-card-image src="{{result.posterPath}}" class="card-poster" [ngClass]="getStatusClass()" alt="{{result.title}}">
|
||||
</a>
|
||||
<mat-card-content>
|
||||
<h6 *ngIf="result.title.length <= 20">{{result.title}}</h6>
|
||||
<h6 *ngIf="result.title.length > 20" matTooltip="{{result.title}}">{{result.title | truncate:20}}</h6>
|
||||
<div class="fade-text">
|
||||
<small class="overview-text">{{result.overview | truncate: 75}}</small>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div> -->
|
||||
|
||||
|
||||
<div class="top-spacing">
|
||||
<mat-card class="mat-elevation-z8 dark-card">
|
||||
<div class="row main-container">
|
||||
<div class="col-2">
|
||||
<img src="{{result.posterPath}}" class="card-poster" alt="{{result.title}}">
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div class="row">
|
||||
<h1>{{result.title}}</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<mat-chip-list>
|
||||
<mat-chip *ngIf="result.available" class="available">
|
||||
{{'Common.Available' | translate}}
|
||||
</mat-chip>
|
||||
|
||||
<mat-chip *ngIf="result.approved && !result.available" class="approved">
|
||||
{{'Common.ProcessingRequest' | translate}}
|
||||
</mat-chip>
|
||||
|
||||
<mat-chip *ngIf="result.denied" class="denied">
|
||||
{{'Common.RequestDenied' | translate}}
|
||||
</mat-chip>
|
||||
|
||||
<mat-chip *ngIf="!result.approved && !result.available && !result.denied" class="requested">
|
||||
{{'Common.PendingApproval' | translate}}
|
||||
</mat-chip>
|
||||
<mat-chip *ngIf="movie && movie.plexUrl"> <a href="{{movie.plexUrl}}" target="_blank"><mat-icon style="color:white" matTooltip=" {{'Search.ViewOnPlex' | translate}}"
|
||||
>play_circle_outline</mat-icon></a></mat-chip>
|
||||
<mat-chip *ngIf="movie && movie.embyUrl"> <a href="{{movie.embyUrl}}" target="_blank"><mat-icon style="color:white" matTooltip=" {{'Search.ViewOnEmby' | translate}}"
|
||||
>play_circle_outline</mat-icon></a></mat-chip>
|
||||
|
||||
<mat-chip *ngIf="tv && tv.plexUrl"> <a href="{{tv.plexUrl}}" target="_blank"><mat-icon style="color:white" matTooltip=" {{'Search.ViewOnPlex' | translate}}"
|
||||
>play_circle_outline</mat-icon></a></mat-chip>
|
||||
<mat-chip *ngIf="tv &&tv.embyUrl"> <a href="{{movie.embyUrl}}" target="_blank"><mat-icon style="color:white" matTooltip=" {{'Search.ViewOnEmby' | translate}}"
|
||||
>play_circle_outline</mat-icon></a></mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<mat-chip-list class="top-spacing">
|
||||
<mat-chip *ngIf="movie && movie.productionCompanies[0]?.name">{{'Discovery.CardDetails.Studio' | translate}}: {{movie.productionCompanies[0].name}}</mat-chip>
|
||||
|
||||
<mat-chip *ngIf="tv && tv.network?.name">{{'Discovery.CardDetails.Network' | translate}}: {{tv.network.name}}</mat-chip>
|
||||
|
||||
<mat-chip *ngIf="movie && movie.credits?.crew[0]?.name">{{'Discovery.CardDetails.Director' | translate}}: {{movie.credits.crew[0].name}}</mat-chip>
|
||||
|
||||
<mat-chip *ngIf="tvCreator">Director: {{tvCreator}}</mat-chip>
|
||||
|
||||
<mat-chip *ngIf="movie">{{'Discovery.CardDetails.InCinemas' | translate}}: {{movie.releaseDate | amLocal | amDateFormat: 'LL'}}</mat-chip>
|
||||
|
||||
<mat-chip *ngIf="tv">{{'Discovery.CardDetails.FirstAired' | translate}}: {{tv.firstAired | amLocal | amDateFormat: 'LL'}}</mat-chip>
|
||||
|
||||
<mat-chip *ngIf="movie && movie.credits?.crew[1]?.name">{{'Discovery.CardDetails.Writer' | translate}}: {{movie.credits.crew[1].name}}</mat-chip>
|
||||
|
||||
<mat-chip *ngIf="tv">{{'Discovery.CardDetails.ExecProducer' | translate}}: {{tvProducer}}</mat-chip>
|
||||
|
||||
</mat-chip-list>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<p class="overview top-spacing">{{result.overview}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-2" >
|
||||
<div style="float:right;">
|
||||
<button mat-raised-button class="btn-green btn-spacing" (click)="openDetails()"> {{
|
||||
'Common.ViewDetails' | translate }}</button>
|
||||
<div *ngIf="movie">
|
||||
<button mat-raised-button class="btn-green btn-spacing" *ngIf="movie.available"> {{
|
||||
'Common.Available' | translate }}</button>
|
||||
<span *ngIf="!movie.available">
|
||||
<span *ngIf="movie.requested || movie.approved; then requestedBtn else notRequestedBtn"></span>
|
||||
<ng-template #requestedBtn>
|
||||
<button mat-raised-button class="btn-spacing btn-orange" [disabled]><i class="fa fa-check"></i>
|
||||
{{ 'Common.Requested' | translate }}</button>
|
||||
</ng-template>
|
||||
<ng-template #notRequestedBtn>
|
||||
<button mat-raised-button class="btn-spacing" color="primary" (click)="request()">
|
||||
<i *ngIf="movie.requestProcessing" class="fa fa-circle-o-notch fa-spin fa-fw"></i> <i
|
||||
*ngIf="!movie.requestProcessing && !movie.processed" class="fa fa-plus"></i>
|
||||
<i *ngIf="movie.processed && !movie.requestProcessing" class="fa fa-check"></i> {{
|
||||
'Common.Request' | translate }}</button>
|
||||
</ng-template>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div *ngIf="tv">
|
||||
|
||||
<div *ngIf="!tv.fullyAvailable" class="dropdown">
|
||||
<button mat-raised-button class="btn-orange btn-spacing" type="button" (click)="request()">
|
||||
<i class="fa fa-plus"></i>
|
||||
{{ 'Common.Request' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button *ngIf="tv.fullyAvailable" mat-raised-button class="btn-spacing" color="accent" [disabled]>
|
||||
<i class="fa fa-check"></i> {{'Common.Available' | translate }}</button>
|
||||
<button *ngIf="tv.partlyAvailable && !tv.fullyAvailable" mat-raised-button class="btn-spacing" color="accent"
|
||||
[disabled]>
|
||||
<i class="fa fa-check"></i> {{'Common.PartiallyAvailable' | translate }}</button>
|
||||
|
||||
<span *ngIf="tv.available">
|
||||
<a *ngIf="tv.plexUrl" mat-raised-button style="text-align: right" class="btn-spacing btn-greem"
|
||||
href="{{tv.plexUrl}}" target="_blank"><i class="fa fa-eye"></i> {{'Search.ViewOnPlex' |
|
||||
translate}}</a>
|
||||
<a *ngIf="tv.embyUrl" mat-raised-button class="btn-green btn-spacing" href="{{tv.embyUrl}}"
|
||||
target="_blank"><i class="fa fa-eye"></i> {{'Search.ViewOnEmby' |
|
||||
translate}}</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card>
|
||||
</div>
|
@ -0,0 +1,132 @@
|
||||
$ombi-primary:#3f3f3f;
|
||||
$card-background: #2b2b2b;
|
||||
|
||||
$blue: #1976D2;
|
||||
$pink: #C2185B;
|
||||
$green:#1DE9B6;
|
||||
$orange:#F57C00;
|
||||
|
||||
.btn-blue {
|
||||
background-color: $blue;
|
||||
}
|
||||
|
||||
.btn-pink {
|
||||
background-color: $pink;
|
||||
}
|
||||
|
||||
.btn-green {
|
||||
background-color: $green;
|
||||
}
|
||||
|
||||
.btn-orange {
|
||||
background-color: $orange;
|
||||
}
|
||||
|
||||
.btn-spacing {
|
||||
margin-top:10%;
|
||||
}
|
||||
|
||||
#cardImage {
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
height: 75%;
|
||||
}
|
||||
|
||||
.dark-card {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
// Changed height to 100% to make all cards the same height
|
||||
.top-spacing {
|
||||
margin-top: 1%;
|
||||
}
|
||||
|
||||
.card-poster {
|
||||
width: 100%;
|
||||
border-radius: 8px 0px 0px 8px;
|
||||
margin-top: -6.5%;
|
||||
margin-bottom: -6.6%;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
margin-left: -2%;
|
||||
}
|
||||
|
||||
|
||||
.rating {
|
||||
position: absolute;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
$border-width: 3px;
|
||||
|
||||
.available {
|
||||
background-color: #1DE9B6 !important;
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.approved {
|
||||
background-color: #ff5722 !important;
|
||||
}
|
||||
|
||||
.requested {
|
||||
background-color: #ffd740 !important;
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.denied {
|
||||
background-color: #C2185B !important;
|
||||
}
|
||||
|
||||
.notrequested {
|
||||
background-color: #303030 !important;
|
||||
}
|
||||
|
||||
.expand {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (min-width: 1025px) {
|
||||
|
||||
// Changed height to 100% to make all cards the same height
|
||||
.grow {
|
||||
transition: all .2s ease-in-out;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.grow:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep mat-dialog-container.mat-dialog-container {
|
||||
// background-color: $ombi-primary;
|
||||
// color: white;
|
||||
border-radius: 2%
|
||||
}
|
||||
|
||||
|
||||
/* Title adjust for the Discover page */
|
||||
.mat-card-content h6 {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-weight: 400;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
/* Summary adjust for Discover page */
|
||||
.small,
|
||||
small {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
@media (min-width: 2000px) {
|
||||
#cardImage {
|
||||
height: 80%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.overview {
|
||||
font-size: 1.2em;
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
import { Component, OnInit, Input } from "@angular/core";
|
||||
import { IDiscoverCardResult } from "../../interfaces";
|
||||
import { RequestType, ISearchTvResult, ISearchMovieResult, ISearchMovieResultContainer } from "../../../interfaces";
|
||||
import { RequestService, SearchV2Service } from "../../../services";
|
||||
import { MatDialog } from "@angular/material/dialog";
|
||||
import { ISearchTvResultV2 } from "../../../interfaces/ISearchTvResultV2";
|
||||
import { ISearchMovieResultV2 } from "../../../interfaces/ISearchMovieResultV2";
|
||||
import { EpisodeRequestComponent } from "../../../shared/episode-request/episode-request.component";
|
||||
import { MatSnackBar } from "@angular/material/snack-bar";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
@Component({
|
||||
selector: "discover-grid",
|
||||
templateUrl: "./discover-grid.component.html",
|
||||
styleUrls: ["./discover-grid.component.scss"],
|
||||
})
|
||||
export class DiscoverGridComponent implements OnInit {
|
||||
|
||||
@Input() public result: IDiscoverCardResult;
|
||||
public RequestType = RequestType;
|
||||
public requesting: boolean;
|
||||
|
||||
public tv: ISearchTvResultV2;
|
||||
public tvCreator: string;
|
||||
public tvProducer: string;
|
||||
public movie: ISearchMovieResultV2;
|
||||
|
||||
constructor(private searchService: SearchV2Service, private dialog: MatDialog,
|
||||
private requestService: RequestService, private notification: MatSnackBar,
|
||||
private router: Router) { }
|
||||
|
||||
public ngOnInit() {
|
||||
if (this.result.type == RequestType.tvShow) {
|
||||
this.getExtraTvInfo();
|
||||
}
|
||||
if (this.result.type == RequestType.movie) {
|
||||
this.getExtraMovieInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public async getExtraTvInfo() {
|
||||
this.tv = await this.searchService.getTvInfo(this.result.id);
|
||||
this.setTvDefaults(this.tv);
|
||||
this.updateTvItem(this.tv);
|
||||
const creator = this.tv.crew.filter(tv => {
|
||||
return tv.type === "Creator";
|
||||
})[0];
|
||||
if (creator && creator.person) {
|
||||
this.tvCreator = creator.person.name;
|
||||
}
|
||||
const crewResult = this.tv.crew.filter(tv => {
|
||||
return tv.type === "Executive Producer";
|
||||
})[0]
|
||||
if (crewResult && crewResult.person) {
|
||||
this.tvProducer = crewResult.person.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public openDetails() {
|
||||
if (this.result.type === RequestType.movie) {
|
||||
this.router.navigate(['/details/movie/', this.result.id]);
|
||||
} else if (this.result.type === RequestType.tvShow) {
|
||||
this.router.navigate(['/details/tv/', this.result.id]);
|
||||
}
|
||||
}
|
||||
|
||||
public getStatusClass(): string {
|
||||
if (this.result.available) {
|
||||
return "available";
|
||||
}
|
||||
if (this.result.approved) {
|
||||
return "approved";
|
||||
}
|
||||
if (this.result.requested) {
|
||||
return "requested";
|
||||
}
|
||||
return "notrequested";
|
||||
}
|
||||
|
||||
private getExtraMovieInfo() {
|
||||
// if (!this.result.imdbid) {
|
||||
this.searchService.getFullMovieDetails(this.result.id)
|
||||
.subscribe(m => {
|
||||
this.movie = m;
|
||||
this.updateMovieItem(m);
|
||||
});
|
||||
// }
|
||||
}
|
||||
|
||||
private updateMovieItem(updated: ISearchMovieResultV2) {
|
||||
this.result.url = "http://www.imdb.com/title/" + updated.imdbId + "/";
|
||||
this.result.available = updated.available;
|
||||
this.result.requested = updated.requested;
|
||||
this.result.requested = updated.requestProcessing;
|
||||
this.result.rating = updated.voteAverage;
|
||||
}
|
||||
|
||||
|
||||
private setTvDefaults(x: ISearchTvResultV2) {
|
||||
if (!x.imdbId) {
|
||||
x.imdbId = "https://www.tvmaze.com/shows/" + x.seriesId;
|
||||
} else {
|
||||
x.imdbId = "http://www.imdb.com/title/" + x.imdbId + "/";
|
||||
}
|
||||
}
|
||||
|
||||
private updateTvItem(updated: ISearchTvResultV2) {
|
||||
this.result.title = updated.title;
|
||||
this.result.id = updated.id;
|
||||
this.result.available = updated.fullyAvailable;
|
||||
this.result.posterPath = updated.banner;
|
||||
this.result.requested = updated.requested;
|
||||
this.result.url = updated.imdbId;
|
||||
}
|
||||
|
||||
public async request() {
|
||||
this.requesting = true;
|
||||
if (this.result.type === RequestType.movie) {
|
||||
const result = await this.requestService.requestMovie({ theMovieDbId: this.result.id, languageCode: "" }).toPromise();
|
||||
|
||||
if (result.result) {
|
||||
this.result.requested = true;
|
||||
this.notification.open(result.message, "Ok");
|
||||
} else {
|
||||
this.notification.open(result.errorMessage, "Ok");
|
||||
}
|
||||
} else if (this.result.type === RequestType.tvShow) {
|
||||
this.dialog.open(EpisodeRequestComponent, { width: "700px", data: this.tv, panelClass: 'modal-panel' })
|
||||
}
|
||||
this.requesting = false;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in new issue