mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-13 18:16:55 -07:00
Added the ability to filter the main search bar
This commit is contained in:
parent
1eae6647db
commit
7ba63a33ce
13 changed files with 132 additions and 36 deletions
|
@ -8,6 +8,6 @@ namespace Ombi.Core.Engine.V2
|
|||
{
|
||||
public interface IMultiSearchEngine
|
||||
{
|
||||
Task<List<MultiSearchResult>> MultiSearch(string searchTerm, CancellationToken cancellationToken);
|
||||
Task<List<MultiSearchResult>> MultiSearch(string searchTerm, MultiSearchFilter filter, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ namespace Ombi.Core.Engine.V2
|
|||
private readonly IMusicBrainzApi _musicApi;
|
||||
|
||||
|
||||
public async Task<List<MultiSearchResult>> MultiSearch(string searchTerm, CancellationToken cancellationToken)
|
||||
public async Task<List<MultiSearchResult>> MultiSearch(string searchTerm, MultiSearchFilter filter, CancellationToken cancellationToken)
|
||||
{
|
||||
var lang = await DefaultLanguageCode(null);
|
||||
var model = new List<MultiSearchResult>();
|
||||
|
@ -44,7 +44,7 @@ namespace Ombi.Core.Engine.V2
|
|||
var movieDbData = (await _movieDbApi.MultiSearch(searchTerm, lang, cancellationToken)).results;
|
||||
|
||||
var lidarrSettings = await _lidarrSettings.GetSettingsAsync();
|
||||
if (lidarrSettings.Enabled)
|
||||
if (lidarrSettings.Enabled && filter.Music)
|
||||
{
|
||||
var artistResult = await _musicApi.SearchArtist(searchTerm);
|
||||
foreach (var artist in artistResult)
|
||||
|
@ -66,7 +66,7 @@ namespace Ombi.Core.Engine.V2
|
|||
Poster = multiSearch.poster_path
|
||||
};
|
||||
|
||||
if (multiSearch.media_type.Equals("movie", StringComparison.InvariantCultureIgnoreCase))
|
||||
if (multiSearch.media_type.Equals("movie", StringComparison.InvariantCultureIgnoreCase) && filter.Movies)
|
||||
{
|
||||
if (multiSearch.release_date.HasValue() && DateTime.TryParse(multiSearch.release_date, out var releaseDate))
|
||||
{
|
||||
|
@ -78,7 +78,7 @@ namespace Ombi.Core.Engine.V2
|
|||
}
|
||||
}
|
||||
|
||||
if (multiSearch.media_type.Equals("tv", StringComparison.InvariantCultureIgnoreCase))
|
||||
else if (multiSearch.media_type.Equals("tv", StringComparison.InvariantCultureIgnoreCase) && filter.TvShows)
|
||||
{
|
||||
if (multiSearch.release_date.HasValue() && DateTime.TryParse(multiSearch.release_date, out var releaseDate))
|
||||
{
|
||||
|
@ -89,11 +89,14 @@ namespace Ombi.Core.Engine.V2
|
|||
result.Title = multiSearch.name;
|
||||
}
|
||||
}
|
||||
|
||||
if (multiSearch.media_type.Equals("person", StringComparison.InvariantCultureIgnoreCase))
|
||||
else if (multiSearch.media_type.Equals("person", StringComparison.InvariantCultureIgnoreCase) && filter.People)
|
||||
{
|
||||
result.Title = multiSearch.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.Id = multiSearch.id.ToString();
|
||||
model.Add(result);
|
||||
|
|
14
src/Ombi.Core/Models/Search/V2/MultiSearchFilter.cs
Normal file
14
src/Ombi.Core/Models/Search/V2/MultiSearchFilter.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Ombi.Core.Models.Search.V2
|
||||
{
|
||||
public class MultiSearchFilter
|
||||
{
|
||||
public bool Movies { get; set; }
|
||||
public bool TvShows { get; set; }
|
||||
public bool Music { get; set; }
|
||||
public bool People { get; set; }
|
||||
}
|
||||
}
|
|
@ -64,6 +64,7 @@ import { NavSearchComponent } from "./my-nav/nav-search.component";
|
|||
import { OverlayModule } from "@angular/cdk/overlay";
|
||||
import { StorageService } from "./shared/storage/storage-service";
|
||||
import { SignalRNotificationService } from "./services/signlarnotification.service";
|
||||
import { MatMenuModule } from "@angular/material/menu";
|
||||
const routes: Routes = [
|
||||
{ path: "*", component: PageNotFoundComponent },
|
||||
{ path: "", redirectTo: "/discover", pathMatch: "full" },
|
||||
|
@ -126,6 +127,7 @@ export function JwtTokenGetter() {
|
|||
NavbarModule,
|
||||
MatCardModule,
|
||||
MatTooltipModule,
|
||||
MatMenuModule,
|
||||
MatInputModule,
|
||||
MatTabsModule,
|
||||
ReactiveFormsModule,
|
||||
|
|
7
src/Ombi/ClientApp/src/app/my-nav/SearchFilter.ts
Normal file
7
src/Ombi/ClientApp/src/app/my-nav/SearchFilter.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
export class SearchFilter {
|
||||
movies: boolean;
|
||||
tvShows: boolean;
|
||||
music: boolean;
|
||||
people: boolean;
|
||||
}
|
|
@ -49,17 +49,28 @@
|
|||
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
|
||||
</button>
|
||||
|
||||
<div class="col-10">
|
||||
<div class="col-8 col-lg-10">
|
||||
<span class="justify-content-center align-items-center">
|
||||
<!-- Search Bar -->
|
||||
<div>
|
||||
<app-nav-search></app-nav-search>
|
||||
<app-nav-search [filter]="searchFilter"></app-nav-search>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<button mat-icon-button [matMenuTriggerFor]="filterMenu"><mat-icon>filter_alt</mat-icon></button>
|
||||
<mat-menu #filterMenu="matMenu" yPosition="below" class="smaller-panel">
|
||||
<mat-slide-toggle class="mat-menu-item slide-menu" [checked]="searchFilter.movies" (click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.Movie)">{{ 'NavigationBar.Filter.Movies' | translate}}</mat-slide-toggle>
|
||||
<mat-slide-toggle class="mat-menu-item slide-menu" [checked]="searchFilter.tvShows" (click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.TvShow)">{{ 'NavigationBar.Filter.TvShows' | translate}}</mat-slide-toggle>
|
||||
<mat-slide-toggle class="mat-menu-item slide-menu" [checked]="searchFilter.music" (click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.Music)">{{ 'NavigationBar.Filter.Music' | translate}}</mat-slide-toggle>
|
||||
<mat-slide-toggle class="mat-menu-item slide-menu" [checked]="searchFilter.people" (click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.People)">{{ 'NavigationBar.Filter.People' | translate}}</mat-slide-toggle>
|
||||
</mat-menu>
|
||||
</div>
|
||||
|
||||
</mat-toolbar>
|
||||
|
||||
|
||||
|
||||
<!-- Page -->
|
||||
<ng-container *ngTemplateOutlet="template"></ng-container>
|
||||
|
||||
|
|
|
@ -55,6 +55,13 @@
|
|||
font-weight:500;
|
||||
}
|
||||
|
||||
.slide-menu {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::ng-deep .smaller-panel {
|
||||
max-width: 170px !important;
|
||||
}
|
||||
|
||||
.mat-drawer-content {
|
||||
position: relative;
|
||||
|
|
|
@ -5,6 +5,15 @@ import { map } from 'rxjs/operators';
|
|||
import { INavBar } from '../interfaces/ICommon';
|
||||
import { StorageService } from '../shared/storage/storage-service';
|
||||
import { SettingsService } from '../services';
|
||||
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
|
||||
import { SearchFilter } from './SearchFilter';
|
||||
|
||||
export enum SearchFilterType {
|
||||
Movie = 1,
|
||||
TvShow = 2,
|
||||
Music = 3,
|
||||
People = 4
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-my-nav',
|
||||
|
@ -27,6 +36,8 @@ export class MyNavComponent implements OnInit {
|
|||
public theme: string;
|
||||
public issuesEnabled: boolean = false;
|
||||
public navItems: INavBar[];
|
||||
public searchFilter: SearchFilter;
|
||||
public SearchFilterType = SearchFilterType;
|
||||
|
||||
constructor(private breakpointObserver: BreakpointObserver,
|
||||
private settingsService: SettingsService,
|
||||
|
@ -35,12 +46,23 @@ export class MyNavComponent implements OnInit {
|
|||
|
||||
public async ngOnInit() {
|
||||
|
||||
this.searchFilter = {
|
||||
movies: true,
|
||||
music: false,
|
||||
people: false,
|
||||
tvShows: true
|
||||
}
|
||||
|
||||
this.issuesEnabled = await this.settingsService.issueEnabled().toPromise();
|
||||
const customizationSettings = await this.settingsService.getCustomization().toPromise();
|
||||
console.log("issues enabled: " + this.issuesEnabled);
|
||||
this.theme = this.store.get("theme");
|
||||
if(!this.theme) {
|
||||
this.store.save("theme","dark");
|
||||
if (!this.theme) {
|
||||
this.store.save("theme", "dark");
|
||||
}
|
||||
var filter = this.store.get("searchFilter");
|
||||
if (filter) {
|
||||
this.searchFilter = Object.assign(new SearchFilter(), JSON.parse(filter));
|
||||
}
|
||||
this.navItems = [
|
||||
{ name: "NavigationBar.Discover", icon: "find_replace", link: "/discover", requiresAdmin: false, enabled: true, faIcon: null },
|
||||
|
@ -73,4 +95,22 @@ export class MyNavComponent implements OnInit {
|
|||
this.themeChange.emit(newTheme);
|
||||
}
|
||||
}
|
||||
|
||||
public changeFilter(event: MatSlideToggleChange, searchFilterType: SearchFilterType) {
|
||||
switch (searchFilterType) {
|
||||
case SearchFilterType.Movie:
|
||||
this.searchFilter.movies = event.checked;
|
||||
break;
|
||||
case SearchFilterType.TvShow:
|
||||
this.searchFilter.tvShows = event.checked;
|
||||
break;
|
||||
case SearchFilterType.Music:
|
||||
this.searchFilter.music = event.checked;
|
||||
break;
|
||||
case SearchFilterType.People:
|
||||
this.searchFilter.people = event.checked;
|
||||
break;
|
||||
}
|
||||
this.store.save("searchFilter", JSON.stringify(this.searchFilter));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
import { Observable } from "rxjs";
|
||||
import {
|
||||
debounceTime,
|
||||
|
@ -14,6 +14,7 @@ import { IMultiSearchResult } from "../interfaces";
|
|||
import { Router } from "@angular/router";
|
||||
import { FormGroup, FormBuilder } from "@angular/forms";
|
||||
import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete";
|
||||
import { SearchFilter } from "./SearchFilter";
|
||||
|
||||
@Component({
|
||||
selector: "app-nav-search",
|
||||
|
@ -21,6 +22,7 @@ import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete";
|
|||
styleUrls: ["./nav-search.component.scss"],
|
||||
})
|
||||
export class NavSearchComponent implements OnInit {
|
||||
@Input() public filter: SearchFilter;
|
||||
public selectedItem: string;
|
||||
public results: IMultiSearchResult[];
|
||||
public searching = false;
|
||||
|
@ -46,7 +48,7 @@ export class NavSearchComponent implements OnInit {
|
|||
switchMap((value: string) => {
|
||||
if (value) {
|
||||
return this.searchService
|
||||
.multiSearch(value)
|
||||
.multiSearch(value, this.filter)
|
||||
.pipe(finalize(() => (this.searching = false)));
|
||||
}
|
||||
return empty().pipe(finalize(() => (this.searching = false)));
|
||||
|
|
|
@ -10,6 +10,7 @@ import { ServiceHelpers } from "./service.helpers";
|
|||
import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2";
|
||||
import { ISearchTvResultV2, IMovieCollectionsViewModel, IActorCredits } from "../interfaces/ISearchTvResultV2";
|
||||
import { IArtistSearchResult, IAlbumArt } from "../interfaces/IMusicSearchResultV2";
|
||||
import { SearchFilter } from "../my-nav/SearchFilter";
|
||||
|
||||
@Injectable()
|
||||
export class SearchV2Service extends ServiceHelpers {
|
||||
|
@ -17,8 +18,8 @@ export class SearchV2Service extends ServiceHelpers {
|
|||
super(http, "/api/v2/search", href);
|
||||
}
|
||||
|
||||
public multiSearch(searchTerm: string): Observable<IMultiSearchResult[]> {
|
||||
return this.http.get<IMultiSearchResult[]>(`${this.url}/multi/${searchTerm}`);
|
||||
public multiSearch(searchTerm: string, filter: SearchFilter): Observable<IMultiSearchResult[]> {
|
||||
return this.http.post<IMultiSearchResult[]>(`${this.url}/multi/${searchTerm}`, filter);
|
||||
}
|
||||
public getFullMovieDetails(theMovieDbId: number): Observable<ISearchMovieResultV2> {
|
||||
return this.http.get<ISearchMovieResultV2>(`${this.url}/Movie/${theMovieDbId}`);
|
||||
|
|
|
@ -21,6 +21,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|||
import { MatSortModule } from '@angular/material/sort';
|
||||
import { MatStepperModule } from '@angular/material/stepper';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import {MatMenuModule} from '@angular/material/menu';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatTreeModule } from '@angular/material/tree';
|
||||
|
@ -57,6 +58,7 @@ import { EpisodeRequestComponent } from "./episode-request/episode-request.compo
|
|||
MatNativeDateModule,
|
||||
MatChipsModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
MatSidenavModule,
|
||||
MatListModule,
|
||||
MatToolbarModule,
|
||||
|
@ -71,7 +73,6 @@ import { EpisodeRequestComponent } from "./episode-request/episode-request.compo
|
|||
MatTreeModule,
|
||||
MatStepperModule,
|
||||
MatSnackBarModule,
|
||||
MatSlideToggleModule,
|
||||
],
|
||||
entryComponents: [
|
||||
EpisodeRequestComponent
|
||||
|
@ -95,6 +96,7 @@ import { EpisodeRequestComponent } from "./episode-request/episode-request.compo
|
|||
MatButtonModule,
|
||||
MatNativeDateModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
MatSnackBarModule,
|
||||
MatSidenavModule,
|
||||
MatSelectModule,
|
||||
|
|
|
@ -44,11 +44,12 @@ namespace Ombi.Controllers.V2
|
|||
/// Show information using the MovieDbId.</remarks>
|
||||
/// <param name="searchTerm">The search you want, this can be for a movie or TV show e.g. Star Wars will return
|
||||
/// all Star Wars movies and Star Wars Rebels the TV Sho</param>
|
||||
/// <param name="filter">Filter for the search</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("multi/{searchTerm}")]
|
||||
public async Task<List<MultiSearchResult>> MultiSearch(string searchTerm)
|
||||
[HttpPost("multi/{searchTerm}")]
|
||||
public async Task<List<MultiSearchResult>> MultiSearch(string searchTerm, [FromBody] MultiSearchFilter filter)
|
||||
{
|
||||
return await _multiSearchEngine.MultiSearch(searchTerm, Request.HttpContext.RequestAborted);
|
||||
return await _multiSearchEngine.MultiSearch(searchTerm, filter, Request.HttpContext.RequestAborted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -69,7 +69,13 @@
|
|||
"Calendar": "Calendar",
|
||||
"UserPreferences": "Preferences",
|
||||
"FeatureSuggestion":"Feature Suggestion",
|
||||
"FeatureSuggestionTooltip":"Have a great new idea? Suggest it here!"
|
||||
"FeatureSuggestionTooltip":"Have a great new idea? Suggest it here!",
|
||||
"Filter": {
|
||||
"Movies":"Movies",
|
||||
"TvShows":"TV Shows",
|
||||
"Music":"Music",
|
||||
"People":"People"
|
||||
}
|
||||
},
|
||||
"Search": {
|
||||
"Title": "Search",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue