mirror of https://github.com/Ombi-app/Ombi
parent
c0a4b20152
commit
33cefe1a62
@ -0,0 +1,52 @@
|
|||||||
|
.sidenav-container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenav {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenav .mat-toolbar {
|
||||||
|
background: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-toolbar.mat-primary {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.spacer {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 978px) {
|
||||||
|
.top-spacing {
|
||||||
|
padding-top: 10%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 979px) {
|
||||||
|
.top-spacing {
|
||||||
|
padding-top: 4%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-form {
|
||||||
|
min-width: 150px;
|
||||||
|
max-width: 500px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quater-width {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-img {
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 63px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-option {
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
padding: 0px 5px;
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<mat-sidenav-container class="sidenav-container">
|
||||||
|
<mat-sidenav #drawer class="sidenav" fixedInViewport="true" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
|
||||||
|
[mode]="(isHandset$ | async) ? 'over' : 'side'" [opened]="!(isHandset$ | async)">
|
||||||
|
<mat-toolbar>Ombi</mat-toolbar>
|
||||||
|
<mat-nav-list>
|
||||||
|
<a mat-list-item [routerLinkActive]="['active']" routerLink="/discover">Discover</a>
|
||||||
|
<a mat-list-item [routerLinkActive]="['active']" routerLink="/search">Search</a>
|
||||||
|
<a mat-list-item [routerLinkActive]="['active']" routerLink="/requests">Requests</a>
|
||||||
|
<a mat-list-item [routerLinkActive]="['active']" routerLink="/settings">Settings</a>
|
||||||
|
</mat-nav-list>
|
||||||
|
</mat-sidenav>
|
||||||
|
<mat-sidenav-content>
|
||||||
|
<mat-toolbar color="primary" class="sticky-header">
|
||||||
|
<button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()" *ngIf="isHandset$ | async">
|
||||||
|
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span class="spacer"></span>
|
||||||
|
<mat-form-field class="quater-width">
|
||||||
|
<input [(ngModel)]="searchText" (keyup)="search($event)" matInput [matAutocomplete]="auto">
|
||||||
|
<mat-autocomplete #auto="matAutocomplete">
|
||||||
|
<mat-option *ngFor="let option of searchResult" [value]="option">
|
||||||
|
<img src="https://image.tmdb.org/t/p/w300/{{option.poster_path}}" class="autocomplete-img" aria-hidden/>
|
||||||
|
<span *ngIf="option.media_type == 'tv'">
|
||||||
|
{{option.name}}
|
||||||
|
</span>
|
||||||
|
<span *ngIf="option.media_type == 'movie'">
|
||||||
|
{{option.title}}
|
||||||
|
</span>
|
||||||
|
</mat-option>
|
||||||
|
</mat-autocomplete>
|
||||||
|
</mat-form-field>
|
||||||
|
</mat-toolbar>
|
||||||
|
<!-- Add Content Here -->
|
||||||
|
<div [ngClass]="{'container top-spacing': showNav}">
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</div>
|
||||||
|
</mat-sidenav-content>
|
||||||
|
</mat-sidenav-container>
|
@ -0,0 +1,42 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
|
||||||
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
import { map, debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { SearchV2Service } from '../services/searchV2.service';
|
||||||
|
import { IMultiSearchResult } from '../interfaces';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-my-nav',
|
||||||
|
templateUrl: './my-nav.component.html',
|
||||||
|
styleUrls: ['./my-nav.component.css']
|
||||||
|
})
|
||||||
|
export class MyNavComponent {
|
||||||
|
|
||||||
|
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
|
||||||
|
.pipe(
|
||||||
|
map(result => result.matches)
|
||||||
|
);
|
||||||
|
|
||||||
|
@Input() public showNav: boolean;
|
||||||
|
public searchChanged: Subject<string> = new Subject<string>();
|
||||||
|
public searchText: string;
|
||||||
|
public searchResult: IMultiSearchResult[];
|
||||||
|
public option: IMultiSearchResult;
|
||||||
|
|
||||||
|
constructor(private breakpointObserver: BreakpointObserver,
|
||||||
|
private searchService: SearchV2Service) {
|
||||||
|
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.searchService.multiSearch(this.searchText).subscribe(x => this.searchResult = x)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public search(text: any) {
|
||||||
|
this.searchChanged.next(text.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,22 +0,0 @@
|
|||||||
<mat-sidenav-container class="sidenav-container">
|
|
||||||
<mat-sidenav #drawer class="sidenav" fixedInViewport="true" [attr.role]="isHandset ? 'dialog' : 'navigation'"
|
|
||||||
[mode]="(isHandset | async)!.matches ? 'over' : 'side'" [opened]="!(isHandset | async)!.matches">
|
|
||||||
<mat-toolbar color="primary">Ombi</mat-toolbar>
|
|
||||||
<mat-nav-list>
|
|
||||||
<a mat-list-item routerLink="/">Discover</a>
|
|
||||||
<a mat-list-item routerLink="/search">Search</a>
|
|
||||||
<a mat-list-item routerLink="/settings">Settings</a>
|
|
||||||
</mat-nav-list>
|
|
||||||
</mat-sidenav>
|
|
||||||
<mat-sidenav-content>
|
|
||||||
<mat-toolbar color="primary">
|
|
||||||
<button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()" *ngIf="(isHandset | async)!.matches">
|
|
||||||
<mat-icon aria-label="Side nav toggle icon"></mat-icon>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
|
|
||||||
<span class="example-fill-remaining-space"></span>
|
|
||||||
|
|
||||||
</mat-toolbar>
|
|
||||||
</mat-sidenav-content>
|
|
||||||
</mat-sidenav-container>
|
|
@ -1,17 +0,0 @@
|
|||||||
.sidenav-container {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidenav {
|
|
||||||
width: 200px;
|
|
||||||
box-shadow: 3px 0 6px rgba(0,0,0,.24);
|
|
||||||
}
|
|
||||||
.example-fill-remaining-space {
|
|
||||||
/* This fills the remaining space, by using flexbox.
|
|
||||||
Every toolbar row uses a flexbox row layout. */
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-spacing {
|
|
||||||
margin-right:2%;
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
import { BreakpointObserver, Breakpoints, BreakpointState } from "@angular/cdk/layout";
|
|
||||||
import { Component } from "@angular/core";
|
|
||||||
import { Observable } from "rxjs";
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: "app-nav",
|
|
||||||
templateUrl: "./nav.component.html",
|
|
||||||
styleUrls: ["./nav.component.scss"],
|
|
||||||
})
|
|
||||||
export class NavComponent {
|
|
||||||
public isHandset: Observable<BreakpointState> = this.breakpointObserver.observe(Breakpoints.HandsetPortrait);
|
|
||||||
|
|
||||||
constructor(private breakpointObserver: BreakpointObserver) {
|
|
||||||
// this.checkLogin();
|
|
||||||
// this.authService.userLoggedIn.subscribe(x => {
|
|
||||||
// this.checkLogin();
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,19 @@
|
|||||||
|
import { PlatformLocation } from "@angular/common";
|
||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
|
||||||
|
import { HttpClient } from "@angular/common/http";
|
||||||
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
|
import { IMultiSearchResult } from "../interfaces";
|
||||||
|
import { ServiceHelpers } from "./service.helpers";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SearchV2Service extends ServiceHelpers {
|
||||||
|
constructor(http: HttpClient, public platformLocation: PlatformLocation) {
|
||||||
|
super(http, "/api/v2/search", platformLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public multiSearch(searchTerm: string): Observable<IMultiSearchResult[]> {
|
||||||
|
return this.http.get<IMultiSearchResult[]>(`${this.url}/multi/${searchTerm}`);
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,14 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Ombi.Api.FanartTv;
|
|
||||||
using Ombi.Store.Repository;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Ombi.Api.TheMovieDb;
|
using Ombi.Api.FanartTv;
|
||||||
using Ombi.Config;
|
using Ombi.Config;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Repository;
|
||||||
|
|
||||||
namespace Ombi.Controllers
|
namespace Ombi.Controllers.V1
|
||||||
{
|
{
|
||||||
[ApiV1]
|
[ApiV1]
|
||||||
[Produces("application/json")]
|
[Produces("application/json")]
|
Loading…
Reference in new issue