Fixed the search bar

pull/3539/head
Jamie Rees 5 years ago
parent 4cd4a1ef50
commit 3ca0aebfd6

@ -18,7 +18,8 @@ import {
} from "primeng/primeng"; } from "primeng/primeng";
import { import {
MatButtonModule, MatNativeDateModule, MatIconModule, MatSidenavModule, MatListModule, MatToolbarModule, MatAutocompleteModule, MatCheckboxModule, MatSnackBarModule MatButtonModule, MatNativeDateModule, MatIconModule, MatSidenavModule, MatListModule, MatToolbarModule, MatAutocompleteModule, MatCheckboxModule, MatSnackBarModule,
MatProgressSpinnerModule
} from '@angular/material'; } from '@angular/material';
import { MatCardModule, MatInputModule, MatTabsModule, MatSlideToggleModule } from "@angular/material"; import { MatCardModule, MatInputModule, MatTabsModule, MatSlideToggleModule } from "@angular/material";
@ -129,6 +130,7 @@ export function JwtTokenGetter() {
CardsFreeModule, CardsFreeModule,
OverlayModule, OverlayModule,
MatCheckboxModule, MatCheckboxModule,
MatProgressSpinnerModule,
MDBBootstrapModule.forRoot(), MDBBootstrapModule.forRoot(),
JwtModule.forRoot({ JwtModule.forRoot({
config: { config: {

@ -1,62 +1,59 @@
<mat-sidenav-container *ngIf="showNav" class="sidenav-container"> <mat-sidenav-container *ngIf="showNav" class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport="true" <mat-sidenav #drawer class="sidenav" fixedInViewport="true" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'" [mode]="(isHandset$ | async) ? 'over' : 'side'" [opened]="!(isHandset$ | async)">
[attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'" [mode]="(isHandset$ | async) ? 'over' : 'side'" <mat-toolbar>{{applicationName}}</mat-toolbar>
[opened]="!(isHandset$ | async)"> <mat-nav-list>
<mat-toolbar>{{applicationName}}</mat-toolbar> <span *ngFor="let nav of navItems">
<mat-nav-list>
<span *ngFor="let nav of navItems">
<a *ngIf="nav.requiresAdmin && isAdmin || !nav.requiresAdmin" mat-list-item [routerLink]="nav.link" <a *ngIf="nav.requiresAdmin && isAdmin || !nav.requiresAdmin" mat-list-item [routerLink]="nav.link"
[routerLinkActive]="getTheme()"> [routerLinkActive]="getTheme()">
<mat-icon aria-label="Side nav toggle icon">{{nav.icon}}</mat-icon> <mat-icon aria-label="Side nav toggle icon">{{nav.icon}}</mat-icon>
&nbsp;{{nav.name | translate}} &nbsp;{{nav.name | translate}}
</a> </span> </a> </span>
<a class="bottom-nav-link" mat-list-item <a class="bottom-nav-link" mat-list-item [routerLinkActive]="theme === 'dark' ? 'active-list-item-dark' : 'active-list-item'" aria-label="Toggle sidenav" (click)="logOut();">
[routerLinkActive]="theme === 'dark' ? 'active-list-item-dark' : 'active-list-item'" aria-label="Toggle sidenav" <mat-icon aria-label="Side nav toggle icon">exit_to_app</mat-icon>
(click)="logOut();"> {{ 'NavigationBar.Logout' | translate }}
<mat-icon aria-label="Side nav toggle icon">exit_to_app</mat-icon> </a>
{{ 'NavigationBar.Logout' | translate }}
</a>
</mat-nav-list> </mat-nav-list>
</mat-sidenav> </mat-sidenav>
<mat-sidenav-content> <mat-sidenav-content>
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()" <button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()" *ngIf="isHandset$ | async">
*ngIf="isHandset$ | async">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon> <mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button> </button>
<div class="col-md-10 offset-md-1 col-10"> <div class="col-md-10 offset-md-1 col-10">
<span class="middle justify-content-center align-items-center"> <span class="middle justify-content-center align-items-center">
<!-- Search Bar --> <!-- Search Bar -->
<div style="width: 50%;">
<app-nav-search></app-nav-search> <app-nav-search></app-nav-search>
</div>
</span> </span>
</div> </div>
<div class="col-1"> <div class="col-1">
<div class="float-right"> <div class="float-right">
<a mat-list-item (click)="switchTheme()"> <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 === '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> <mat-icon *ngIf="theme === 'light'" aria-label="Side nav toggle icon">brightness_4</mat-icon>
</a> </a>
</div> </div>
</div> </div>
</mat-toolbar> </mat-toolbar>
<!-- Page --> <!-- Page -->
<ng-container *ngTemplateOutlet="template"></ng-container> <ng-container *ngTemplateOutlet="template"></ng-container>
</mat-sidenav-content> </mat-sidenav-content>
</mat-sidenav-container> </mat-sidenav-container>
<div *ngIf="!showNav"> <div *ngIf="!showNav">
<ng-container *ngTemplateOutlet="template"></ng-container> <ng-container *ngTemplateOutlet="template"></ng-container>
</div> </div>
<ng-template #template> <ng-template #template>
<router-outlet> </router-outlet> <router-outlet> </router-outlet>
</ng-template> </ng-template>

@ -1,30 +1,42 @@
<input class="form-control quater-width search-bar" type="text" [(ngModel)]="selectedItem" <!-- <input class="form-control quater-width search-bar" type="text" [(ngModel)]="selectedItem" placeholder="{{'NavigationBar.Search' | translate}}"
placeholder="{{'NavigationBar.Search' | translate}}" aria-label="Search" [ngbTypeahead]="searchModel" aria-label="Search" [ngbTypeahead]="searchModel" [resultFormatter]="formatter" [inputFormatter]="formatter" [resultTemplate]="template" (selectItem)="selected($event)">
[resultFormatter]="formatter" [inputFormatter]="formatter" [resultTemplate]="template" (selectItem)="selected($event)">
<ng-template #template let-result="result"> <ng-template #template let-result="result">
<div *ngIf="result.mediaType === 'movie'">
<i class="fa fa-film"></i> &nbsp; </ng-template> -->
<span >{{result.title}}</span>
</div> <form [formGroup]='searchForm'>
<div *ngIf="result.mediaType === 'tv'"> <mat-form-field floatLabel="never" style="width: 100%;">
<i class="fa fa-tv"></i> &nbsp; <input matInput placeholder="{{'NavigationBar.Search' | translate}}" [matAutocomplete]="auto" formControlName='input'>
</mat-form-field>
<span>{{result.title}}</span>
</div> <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> &nbsp;
<span>{{result.title}}</span>
</div>
<div *ngIf="result.mediaType === 'tv'">
<i class="fa fa-tv"></i> &nbsp;
<span>{{result.title}}</span>
</div>
<div *ngIf="result.mediaType === 'Artist'">
<i class="fa fa-music"></i> &nbsp;
<div *ngIf="result.mediaType === 'Artist'"> <span>{{result.title}}</span>
<i class="fa fa-music"></i> &nbsp; </div>
<span>{{result.title}}</span>
</div>
<div *ngIf="result.mediaType === 'person'"> <div *ngIf="result.mediaType === 'person'">
<i class="fa fa-user"></i> &nbsp; <i class="fa fa-user"></i> &nbsp;
<span >{{result.title}}</span> <span>{{result.title}}</span>
</div> </div>
<!-- Collection --> </mat-option>
<!-- <i class="fa fa-file-video-o" aria-hidden="true"></i> --> </ng-container>
</ng-template> </mat-autocomplete>
</form>

@ -1,49 +1,32 @@
$ombi-primary:#3f3f3f; $ombi-primary:#3f3f3f;
$ombi-primary-darker:#2b2b2b; $ombi-primary-darker:#2b2b2b;
$ombi-accent: #258a6d; $ombi-accent: #258a6d;
@media (max-width: 767px) { @media (max-width: 767px) {
.quater-width { .quater-width {
width: 15em !important; width: 15em !important;
} }
} }
.quater-width { .quater-width {
width: 25em; width: 25em;
} }
.autocomplete-img { .autocomplete-img {
vertical-align: middle; vertical-align: middle;
height: 63px; height: 63px;
} }
.mat-option { .mat-option {
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
padding: 0px 5px; 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;
} }
.search-bar { .search-bar {
background-color: $ombi-primary-darker; background-color: $ombi-primary-darker;
border: solid 1px $ombi-primary-darker; border: solid 1px $ombi-primary-darker;
} }
.search-bar:focus { .search-bar:focus {
background-color: white; background-color: white;
} }

@ -1,56 +1,78 @@
import { Component } from '@angular/core'; import { Component, OnInit } from "@angular/core";
import { Observable } from 'rxjs'; import { Observable } from "rxjs";
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators'; import {
debounceTime,
distinctUntilChanged,
switchMap,
tap,
finalize,
} from "rxjs/operators";
import { SearchV2Service } from '../services/searchV2.service'; import { empty, of } from "rxjs";
import { IMultiSearchResult } from '../interfaces'; import { SearchV2Service } from "../services/searchV2.service";
import { Router } from '@angular/router'; import { IMultiSearchResult } from "../interfaces";
import { NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; import { Router } from "@angular/router";
import { NgbTypeaheadSelectItemEvent } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, FormBuilder } from "@angular/forms";
import { MatAutocompleteSelectedEvent } from "@angular/material";
@Component({ @Component({
selector: 'app-nav-search', selector: "app-nav-search",
templateUrl: './nav-search.component.html', templateUrl: "./nav-search.component.html",
styleUrls: ['./nav-search.component.scss'] 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 searchForm: FormGroup;
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)
)
)
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) { public selected(event: MatAutocompleteSelectedEvent) {
if (event.item.mediaType == "movie") { const val = event.option.value as IMultiSearchResult;
this.router.navigate([`details/movie/${event.item.id}`]); if (val.mediaType == "movie") {
return; this.router.navigate([`details/movie/${val.id}`]);
} else if (event.item.mediaType == "tv") { return;
this.router.navigate([`details/tv/${event.item.id}/true`]); } else if (val.mediaType == "tv") {
return; this.router.navigate([`details/tv/${val.id}/true`]);
} else if (event.item.mediaType == "person") { return;
this.router.navigate([`discover/actor/${event.item.id}`]); } else if (val.mediaType == "person") {
return; this.router.navigate([`discover/actor/${val.id}`]);
} else if (event.item.mediaType == "Artist") { return;
this.router.navigate([`details/artist/${event.item.id}`]); } else if (val.mediaType == "Artist") {
return; this.router.navigate([`details/artist/${val.id}`]);
} return;
} }
}
displayFn(result: IMultiSearchResult) {
if (result) { return result.title; }
}
} }

Loading…
Cancel
Save