mirror of https://github.com/Ombi-app/Ombi
parent
4cd4a1ef50
commit
3ca0aebfd6
@ -1,62 +1,59 @@
|
||||
<mat-sidenav-container *ngIf="showNav" 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>{{applicationName}}</mat-toolbar>
|
||||
<mat-nav-list>
|
||||
<span *ngFor="let nav of navItems">
|
||||
<mat-sidenav #drawer class="sidenav" fixedInViewport="true" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'" [mode]="(isHandset$ | async) ? 'over' : 'side'" [opened]="!(isHandset$ | async)">
|
||||
<mat-toolbar>{{applicationName}}</mat-toolbar>
|
||||
<mat-nav-list>
|
||||
<span *ngFor="let nav of navItems">
|
||||
<a *ngIf="nav.requiresAdmin && isAdmin || !nav.requiresAdmin" mat-list-item [routerLink]="nav.link"
|
||||
[routerLinkActive]="getTheme()">
|
||||
<mat-icon aria-label="Side nav toggle icon">{{nav.icon}}</mat-icon>
|
||||
{{nav.name | translate}}
|
||||
</a> </span>
|
||||
|
||||
<a class="bottom-nav-link" mat-list-item
|
||||
[routerLinkActive]="theme === 'dark' ? 'active-list-item-dark' : 'active-list-item'" aria-label="Toggle sidenav"
|
||||
(click)="logOut();">
|
||||
<mat-icon aria-label="Side nav toggle icon">exit_to_app</mat-icon>
|
||||
{{ 'NavigationBar.Logout' | translate }}
|
||||
</a>
|
||||
<a class="bottom-nav-link" mat-list-item [routerLinkActive]="theme === 'dark' ? 'active-list-item-dark' : 'active-list-item'" aria-label="Toggle sidenav" (click)="logOut();">
|
||||
<mat-icon aria-label="Side nav toggle icon">exit_to_app</mat-icon>
|
||||
{{ 'NavigationBar.Logout' | translate }}
|
||||
</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">
|
||||
</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">
|
||||
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
|
||||
</button>
|
||||
|
||||
<div class="col-md-10 offset-md-1 col-10">
|
||||
<span class="middle justify-content-center align-items-center">
|
||||
<div class="col-md-10 offset-md-1 col-10">
|
||||
<span class="middle justify-content-center align-items-center">
|
||||
<!-- Search Bar -->
|
||||
<div style="width: 50%;">
|
||||
<app-nav-search></app-nav-search>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<div class="float-right">
|
||||
<a mat-list-item (click)="switchTheme()">
|
||||
<mat-icon *ngIf="theme === 'dark'" aria-label="Side nav toggle icon">brightness_7</mat-icon>
|
||||
<mat-icon *ngIf="theme === 'light'" aria-label="Side nav toggle icon">brightness_4</mat-icon>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</mat-toolbar>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<div class="float-right">
|
||||
<a mat-list-item (click)="switchTheme()">
|
||||
<mat-icon *ngIf="theme === 'dark'" aria-label="Side nav toggle icon">brightness_7</mat-icon>
|
||||
<mat-icon *ngIf="theme === 'light'" aria-label="Side nav toggle icon">brightness_4</mat-icon>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</mat-toolbar>
|
||||
|
||||
<!-- Page -->
|
||||
<ng-container *ngTemplateOutlet="template"></ng-container>
|
||||
<!-- Page -->
|
||||
<ng-container *ngTemplateOutlet="template"></ng-container>
|
||||
|
||||
|
||||
</mat-sidenav-content>
|
||||
</mat-sidenav-content>
|
||||
</mat-sidenav-container>
|
||||
|
||||
<div *ngIf="!showNav">
|
||||
<ng-container *ngTemplateOutlet="template"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="template"></ng-container>
|
||||
</div>
|
||||
|
||||
<ng-template #template>
|
||||
<router-outlet> </router-outlet>
|
||||
<router-outlet> </router-outlet>
|
||||
</ng-template>
|
@ -1,30 +1,42 @@
|
||||
<input class="form-control quater-width search-bar" type="text" [(ngModel)]="selectedItem"
|
||||
placeholder="{{'NavigationBar.Search' | translate}}" aria-label="Search" [ngbTypeahead]="searchModel"
|
||||
[resultFormatter]="formatter" [inputFormatter]="formatter" [resultTemplate]="template" (selectItem)="selected($event)">
|
||||
<!-- <input class="form-control quater-width search-bar" type="text" [(ngModel)]="selectedItem" placeholder="{{'NavigationBar.Search' | translate}}"
|
||||
aria-label="Search" [ngbTypeahead]="searchModel" [resultFormatter]="formatter" [inputFormatter]="formatter" [resultTemplate]="template" (selectItem)="selected($event)">
|
||||
|
||||
|
||||
|
||||
<ng-template #template let-result="result">
|
||||
<div *ngIf="result.mediaType === 'movie'">
|
||||
<i class="fa fa-film"></i>
|
||||
<span >{{result.title}}</span>
|
||||
</div>
|
||||
<div *ngIf="result.mediaType === 'tv'">
|
||||
<i class="fa fa-tv"></i>
|
||||
|
||||
<span>{{result.title}}</span>
|
||||
</div>
|
||||
|
||||
</ng-template> -->
|
||||
|
||||
<form [formGroup]='searchForm'>
|
||||
<mat-form-field floatLabel="never" style="width: 100%;">
|
||||
<input matInput placeholder="{{'NavigationBar.Search' | translate}}" [matAutocomplete]="auto" formControlName='input'>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)" [displayWith]="displayFn">
|
||||
<mat-option *ngIf="searching" color="accent">
|
||||
<mat-spinner diameter="50"></mat-spinner>
|
||||
</mat-option>
|
||||
<ng-container *ngIf="!searching">
|
||||
<mat-option *ngFor="let result of results" [value]="result">
|
||||
<div *ngIf="result.mediaType === 'movie'">
|
||||
<i class="fa fa-film"></i>
|
||||
<span>{{result.title}}</span>
|
||||
</div>
|
||||
<div *ngIf="result.mediaType === 'tv'">
|
||||
<i class="fa fa-tv"></i>
|
||||
|
||||
<span>{{result.title}}</span>
|
||||
</div>
|
||||
|
||||
<div *ngIf="result.mediaType === 'Artist'">
|
||||
<i class="fa fa-music"></i>
|
||||
|
||||
<div *ngIf="result.mediaType === 'Artist'">
|
||||
<i class="fa fa-music"></i>
|
||||
|
||||
<span>{{result.title}}</span>
|
||||
</div>
|
||||
<span>{{result.title}}</span>
|
||||
</div>
|
||||
|
||||
<div *ngIf="result.mediaType === 'person'">
|
||||
<i class="fa fa-user"></i>
|
||||
<span >{{result.title}}</span>
|
||||
</div>
|
||||
<!-- Collection -->
|
||||
<!-- <i class="fa fa-file-video-o" aria-hidden="true"></i> -->
|
||||
</ng-template>
|
||||
<div *ngIf="result.mediaType === 'person'">
|
||||
<i class="fa fa-user"></i>
|
||||
<span>{{result.title}}</span>
|
||||
</div>
|
||||
</mat-option>
|
||||
</ng-container>
|
||||
</mat-autocomplete>
|
||||
</form>
|
@ -1,49 +1,32 @@
|
||||
$ombi-primary:#3f3f3f;
|
||||
$ombi-primary-darker:#2b2b2b;
|
||||
$ombi-accent: #258a6d;
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.quater-width {
|
||||
width: 15em !important;
|
||||
}
|
||||
.quater-width {
|
||||
width: 15em !important;
|
||||
}
|
||||
}
|
||||
|
||||
.quater-width {
|
||||
width: 25em;
|
||||
width: 25em;
|
||||
}
|
||||
|
||||
.autocomplete-img {
|
||||
vertical-align: middle;
|
||||
height: 63px;
|
||||
vertical-align: middle;
|
||||
height: 63px;
|
||||
}
|
||||
|
||||
.mat-option {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
::ng-deep ngb-typeahead-window.dropdown-menu {
|
||||
background-color: $ombi-primary;
|
||||
overflow: auto;
|
||||
height: 33em;
|
||||
}
|
||||
|
||||
::ng-deep ngb-typeahead-window button.dropdown-item {
|
||||
color: white;
|
||||
}
|
||||
|
||||
::ng-deep ngb-typeahead-window .dropdown-item.active,
|
||||
.dropdown-item:active {
|
||||
text-decoration: none;
|
||||
background-color: $ombi-accent;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
background-color: $ombi-primary-darker;
|
||||
border: solid 1px $ombi-primary-darker;
|
||||
background-color: $ombi-primary-darker;
|
||||
border: solid 1px $ombi-primary-darker;
|
||||
}
|
||||
|
||||
.search-bar:focus {
|
||||
background-color: white;
|
||||
}
|
||||
background-color: white;
|
||||
}
|
@ -1,56 +1,78 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { Observable } from "rxjs";
|
||||
import {
|
||||
debounceTime,
|
||||
distinctUntilChanged,
|
||||
switchMap,
|
||||
tap,
|
||||
finalize,
|
||||
} from "rxjs/operators";
|
||||
|
||||
import { SearchV2Service } from '../services/searchV2.service';
|
||||
import { IMultiSearchResult } from '../interfaces';
|
||||
import { Router } from '@angular/router';
|
||||
import { NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { empty, of } from "rxjs";
|
||||
import { SearchV2Service } from "../services/searchV2.service";
|
||||
import { IMultiSearchResult } from "../interfaces";
|
||||
import { Router } from "@angular/router";
|
||||
import { NgbTypeaheadSelectItemEvent } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { FormGroup, FormBuilder } from "@angular/forms";
|
||||
import { MatAutocompleteSelectedEvent } from "@angular/material";
|
||||
|
||||
@Component({
|
||||
selector: 'app-nav-search',
|
||||
templateUrl: './nav-search.component.html',
|
||||
styleUrls: ['./nav-search.component.scss']
|
||||
selector: "app-nav-search",
|
||||
templateUrl: "./nav-search.component.html",
|
||||
styleUrls: ["./nav-search.component.scss"],
|
||||
})
|
||||
export class NavSearchComponent {
|
||||
export class NavSearchComponent implements OnInit {
|
||||
public selectedItem: string;
|
||||
public results: IMultiSearchResult[];
|
||||
public searching = false;
|
||||
|
||||
public selectedItem: string;
|
||||
|
||||
public searching = false;
|
||||
public searchFailed = false;
|
||||
|
||||
public formatter = (result: IMultiSearchResult) => {
|
||||
return result.title;
|
||||
}
|
||||
|
||||
public searchModel = (text$: Observable<string>) =>
|
||||
text$.pipe(
|
||||
debounceTime(600),
|
||||
distinctUntilChanged(),
|
||||
switchMap(term => term.length < 2 ? []
|
||||
: this.searchService.multiSearch(term)
|
||||
)
|
||||
)
|
||||
public searchForm: FormGroup;
|
||||
|
||||
constructor(private searchService: SearchV2Service, private router: Router) {
|
||||
constructor(
|
||||
private searchService: SearchV2Service,
|
||||
private router: Router,
|
||||
private fb: FormBuilder
|
||||
) {}
|
||||
|
||||
}
|
||||
public async ngOnInit() {
|
||||
this.searchForm = this.fb.group({
|
||||
input: null,
|
||||
});
|
||||
|
||||
|
||||
this.searchForm
|
||||
.get("input")
|
||||
.valueChanges.pipe(
|
||||
debounceTime(600),
|
||||
tap(() => (this.searching = true)),
|
||||
switchMap((value: string) => {
|
||||
if (value) {
|
||||
return this.searchService
|
||||
.multiSearch(value)
|
||||
.pipe(finalize(() => (this.searching = false)));
|
||||
}
|
||||
return empty().pipe(finalize(() => (this.searching = false)));
|
||||
})
|
||||
)
|
||||
.subscribe((r) => (this.results = r));
|
||||
}
|
||||
|
||||
public selected(event: NgbTypeaheadSelectItemEvent) {
|
||||
if (event.item.mediaType == "movie") {
|
||||
this.router.navigate([`details/movie/${event.item.id}`]);
|
||||
return;
|
||||
} else if (event.item.mediaType == "tv") {
|
||||
this.router.navigate([`details/tv/${event.item.id}/true`]);
|
||||
return;
|
||||
} else if (event.item.mediaType == "person") {
|
||||
this.router.navigate([`discover/actor/${event.item.id}`]);
|
||||
return;
|
||||
} else if (event.item.mediaType == "Artist") {
|
||||
this.router.navigate([`details/artist/${event.item.id}`]);
|
||||
return;
|
||||
}
|
||||
public selected(event: MatAutocompleteSelectedEvent) {
|
||||
const val = event.option.value as IMultiSearchResult;
|
||||
if (val.mediaType == "movie") {
|
||||
this.router.navigate([`details/movie/${val.id}`]);
|
||||
return;
|
||||
} else if (val.mediaType == "tv") {
|
||||
this.router.navigate([`details/tv/${val.id}/true`]);
|
||||
return;
|
||||
} else if (val.mediaType == "person") {
|
||||
this.router.navigate([`discover/actor/${val.id}`]);
|
||||
return;
|
||||
} else if (val.mediaType == "Artist") {
|
||||
this.router.navigate([`details/artist/${val.id}`]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
displayFn(result: IMultiSearchResult) {
|
||||
if (result) { return result.title; }
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in new issue