mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-14 10:36:54 -07:00
!minor Poc'ing a new search page
This commit is contained in:
parent
f8054317ab
commit
989be6df6c
4 changed files with 322 additions and 0 deletions
|
@ -27,3 +27,7 @@
|
|||
requestProcessing: boolean;
|
||||
processed: boolean;
|
||||
}
|
||||
|
||||
export interface ISearchMovieResultContainer {
|
||||
movies: ISearchMovieResult[];
|
||||
}
|
||||
|
|
149
src/Ombi/ClientApp/app/search/moviesearchgrid.component.html
Normal file
149
src/Ombi/ClientApp/app/search/moviesearchgrid.component.html
Normal file
|
@ -0,0 +1,149 @@
|
|||
<!-- Movie tab -->
|
||||
<div role="tabpanel" class="tab-pane active" id="MoviesTab">
|
||||
<div class="input-group">
|
||||
<input id="search" type="text" class="form-control form-control-custom form-control-search form-control-withbuttons" (keyup)="search($event)">
|
||||
<div class="input-group-addon right-radius">
|
||||
<div class="btn-group">
|
||||
<a href="#" class="btn btn-sm btn-primary-outline dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
|
||||
Suggestions
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a (click)="popularMovies()">Popular Movies</a>
|
||||
</li>
|
||||
<li>
|
||||
<a (click)="upcomingMovies()">Upcoming Movies</a>
|
||||
</li>
|
||||
<li>
|
||||
<a (click)="topRatedMovies()">Top Rated Movies</a>
|
||||
</li>
|
||||
<li>
|
||||
<a (click)="nowPlayingMovies()">Now Playing Movies</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<i id="movieSearchButton" class="fa fa-search"></i>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<!-- Movie content -->
|
||||
<div id="movieList">
|
||||
<div *ngIf="searchApplied && movieResults?.length <= 0" class='no-search-results'>
|
||||
<i class='fa fa-film no-search-results-icon'></i>
|
||||
<div class='no-search-results-text'>Sorry, we didn't find any results!</div>
|
||||
</div>
|
||||
|
||||
<!--NEW-->
|
||||
<div *ngFor="let grid of movieResultGrid; let i = index">
|
||||
<div class="row">
|
||||
<div *ngFor="let r of grid.movies">
|
||||
<div class="col-md-3">
|
||||
|
||||
<img *ngIf="r.posterPath" class="img-responsive poster" src="https://image.tmdb.org/t/p/w150/{{r.posterPath}}"
|
||||
alt="poster">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--END NEW-->
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<hr/>
|
||||
<div *ngFor="let result of movieResults">
|
||||
<div class="row">
|
||||
<div id="imgDiv" class="col-sm-2">
|
||||
|
||||
|
||||
<img *ngIf="result.posterPath" class="img-responsive poster" src="https://image.tmdb.org/t/p/w150/{{result.posterPath}}"
|
||||
alt="poster">
|
||||
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div>
|
||||
<a href="https://www.themoviedb.org/movie/{{result.id}}/" target="_blank">
|
||||
<h4>{{result.title}} ({{result.releaseDate | date: 'yyyy'}})</h4>
|
||||
</a>
|
||||
|
||||
<span *ngIf="result.releaseDate" class="label label-info" target="_blank">Release Date: {{result.releaseDate | date: 'dd/MM/yyyy'}}</span>
|
||||
|
||||
<a *ngIf="result.homepage" href="{{result.homepage}}" target="_blank">
|
||||
<span class="label label-info">HomePage</span>
|
||||
</a>
|
||||
|
||||
<a *ngIf="result.trailer" href="{{result.trailer}}" target="_blank">
|
||||
<span class="label label-info">Trailer</span>
|
||||
</a>
|
||||
<span *ngIf="result.quality" class="label label-success">{{result.quality}}p</span>
|
||||
|
||||
<ng-template [ngIf]="result.available">
|
||||
<span class="label label-success">Available</span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="result.approved && !result.available">
|
||||
<span class="label label-info">Processing Request</span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="result.requested && !result.approved && !result.available">
|
||||
<span class="label label-warning">Pending Approval</span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="!result.requested && !result.available && !result.approved">
|
||||
<span class="label label-danger">Not Requested</span>
|
||||
</ng-template>
|
||||
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
<p style="font-size: 0.9rem !important">{{result.overview}}</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-2">
|
||||
|
||||
<div *ngIf="result.available">
|
||||
<button style="text-align: right" class="btn btn-success-outline disabled" disabled>
|
||||
<i class="fa fa-check"></i> Available</button>
|
||||
|
||||
<div *ngIf="result.plexUrl">
|
||||
<br/>
|
||||
<br/>
|
||||
<a style="text-align: right" class="btn btn-sm btn-primary-outline" href="{{result.plexUrl}}" target="_blank">
|
||||
<i class="fa fa-eye"></i> View In Plex</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!result.available">
|
||||
<div *ngIf="result.requested || result.approved; then requestedBtn else notRequestedBtn"></div>
|
||||
<ng-template #requestedBtn>
|
||||
<button style="text-align: right" class="btn btn-primary-outline disabled" [disabled]>
|
||||
<i class="fa fa-check"></i> Requested</button>
|
||||
</ng-template>
|
||||
<ng-template #notRequestedBtn>
|
||||
<button id="{{result.id}}" style="text-align: right" class="btn btn-primary-outline" (click)="request(result)">
|
||||
<i *ngIf="result.requestProcessing" class="fa fa-circle-o-notch fa-spin fa-fw"></i>
|
||||
<i *ngIf="!result.requestProcessing && !result.processed" class="fa fa-plus"></i>
|
||||
<i *ngIf="result.processed && !result.requestProcessing" class="fa fa-check"></i>Request</button>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div *ngIf="result.available">
|
||||
<a *ngIf="result.plexUrl" style="text-align: right" class="btn btn-sm btn-success-outline" href="{{result.plexUrl}}" target="_blank">
|
||||
<i class="fa fa-eye"></i> View On Plex</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<hr/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
167
src/Ombi/ClientApp/app/search/moviesearchgrid.component.ts
Normal file
167
src/Ombi/ClientApp/app/search/moviesearchgrid.component.ts
Normal file
|
@ -0,0 +1,167 @@
|
|||
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 { AuthService } from "../auth/auth.service";
|
||||
import { NotificationService, RequestService, SearchService } from "../services";
|
||||
|
||||
import { IRequestEngineResult, ISearchMovieResult, ISearchMovieResultContainer } from "../interfaces";
|
||||
|
||||
@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
|
||||
.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: "",
|
||||
requestAdded: 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(searchResult)
|
||||
.subscribe(x => {
|
||||
this.result = x;
|
||||
|
||||
if (this.result.requestAdded) {
|
||||
this.notificationService.success("Request Added",
|
||||
`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("Something went wrong", 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.upcomignMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtaInfo();
|
||||
});
|
||||
}
|
||||
|
||||
private getExtaInfo() {
|
||||
this.movieResults.forEach((val, index) => {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -6,6 +6,7 @@ import { RouterModule, Routes } from "@angular/router";
|
|||
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
|
||||
|
||||
import { MovieSearchComponent } from "./moviesearch.component";
|
||||
import { MovieSearchGridComponent } from "./moviesearchgrid.component";
|
||||
import { SearchComponent } from "./search.component";
|
||||
import { SeriesInformationComponent } from "./seriesinformation.component";
|
||||
import { TvSearchComponent } from "./tvsearch.component";
|
||||
|
@ -35,6 +36,7 @@ const routes: Routes = [
|
|||
MovieSearchComponent,
|
||||
TvSearchComponent,
|
||||
SeriesInformationComponent,
|
||||
MovieSearchGridComponent,
|
||||
],
|
||||
exports: [
|
||||
RouterModule,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue