diff --git a/frontend/src/app/components/game-detail-view/game-detail-view.component.html b/frontend/src/app/components/game-detail-view/game-detail-view.component.html
index 27dff99..b35200e 100644
--- a/frontend/src/app/components/game-detail-view/game-detail-view.component.html
+++ b/frontend/src/app/components/game-detail-view/game-detail-view.component.html
@@ -28,14 +28,14 @@
0">
Genres
- {{genre.name}}
+ {{genre.name}}
0">
Themes
- {{theme.name}}
+ {{theme.name}}
diff --git a/frontend/src/app/components/game-detail-view/game-detail-view.component.ts b/frontend/src/app/components/game-detail-view/game-detail-view.component.ts
index c641e4c..c7a92c8 100644
--- a/frontend/src/app/components/game-detail-view/game-detail-view.component.ts
+++ b/frontend/src/app/components/game-detail-view/game-detail-view.component.ts
@@ -1,9 +1,7 @@
-import { Component, OnInit } from '@angular/core';
-import {ActivatedRoute, Router} from "@angular/router";
+import {Component, OnInit} from '@angular/core';
+import {ActivatedRoute, Params, Router} from "@angular/router";
import {DetectedGameDto} from "../../models/dtos/DetectedGameDto";
import {GamesService} from "../../services/games.service";
-import {HttpErrorResponse} from "@angular/common/http";
-import {takeWhile} from "rxjs";
@Component({
selector: 'app-game-detail-view',
@@ -58,4 +56,10 @@ export class GameDetailViewComponent implements OnInit {
return bytes.toFixed(dp) + ' ' + units[u];
}
+ goToLibraryWithFilter(field: string, value: string) {
+ let params: Params = {};
+ params[field] = value;
+ this.router.navigate(['/library'], {queryParams: params});
+ }
+
}
diff --git a/frontend/src/app/components/library-overview/library-overview.component.html b/frontend/src/app/components/library-overview/library-overview.component.html
index 0fd6599..7501b07 100644
--- a/frontend/src/app/components/library-overview/library-overview.component.html
+++ b/frontend/src/app/components/library-overview/library-overview.component.html
@@ -54,7 +54,7 @@
-
+
Gamemodes
@@ -75,7 +75,7 @@
- 0">
+ 0" [expanded]="activeGenreFilters.length > 0">
Genres
@@ -87,7 +87,7 @@
- 0">
+ 0" [expanded]="activeThemeFilters.length > 0">
Themes
@@ -99,7 +99,7 @@
- 0">
+ 0" [expanded]="activePlayerPerspectiveFilters.length > 0">
Player Perspectives
diff --git a/frontend/src/app/components/library-overview/library-overview.component.ts b/frontend/src/app/components/library-overview/library-overview.component.ts
index c40b4f7..c7a556a 100644
--- a/frontend/src/app/components/library-overview/library-overview.component.ts
+++ b/frontend/src/app/components/library-overview/library-overview.component.ts
@@ -6,9 +6,8 @@ import {ThemeDto} from "../../models/dtos/ThemeDto";
import {firstValueFrom, forkJoin, Observable} from "rxjs";
import {SortDirection} from "@angular/material/sort";
import {PlayerPerspectiveDto} from "../../models/dtos/PlayerPerspectiveDto";
-import {ActivatedRoute, Params, Router} from "@angular/router";
+import {ActivatedRoute, ActivatedRouteSnapshot, Params, Router} from "@angular/router";
import {Location} from "@angular/common";
-import {HttpParams} from "@angular/common/http";
class SortOption {
title: string;
@@ -61,6 +60,7 @@ export class LibraryOverviewComponent implements AfterContentInit {
loading: boolean = true;
gameLibraryIsEmpty: boolean = false;
+ private previousStateParams: Params = {};
constructor(private gameServerService: GamesService,
private route: ActivatedRoute,
@@ -88,16 +88,15 @@ export class LibraryOverviewComponent implements AfterContentInit {
this.availableThemes = result[1];
this.availablePlayerPerspectives = result[2];
- this.route.queryParams.subscribe(params => {
- if (params['search'] !== undefined) this.searchTerm = params['search'];
- if (params['sort'] !== undefined) this.selectedSortOption = this.matchSelectedSortOptionFromParam(params['sort']);
- if (params['gamemodes'] !== undefined) this.setSelectedGamemodesFromParam(params['gamemodes']);
- if (params['genres'] !== undefined) this.activeGenreFilters = this.matchSelectedFilters(this.availableGenres, params['genres']);
- if (params['themes'] !== undefined) this.activeThemeFilters = this.matchSelectedFilters(this.availableThemes, params['themes']);
- if (params['playerPerspectives'] !== undefined) this.activePlayerPerspectiveFilters = this.matchSelectedFilters(this.availablePlayerPerspectives, params['playerPerspectives']);
+ this.previousStateParams = this.route.snapshot.queryParams;
+ if (this.previousStateParams['search'] !== undefined) this.searchTerm = this.previousStateParams['search'];
+ if (this.previousStateParams['sort'] !== undefined) this.selectedSortOption = this.matchSelectedSortOptionFromParam(this.previousStateParams['sort']);
+ if (this.previousStateParams['gamemodes'] !== undefined) this.setSelectedGamemodesFromParam(this.previousStateParams['gamemodes']);
+ if (this.previousStateParams['genres'] !== undefined) this.activeGenreFilters = this.matchSelectedFilters(this.availableGenres, this.previousStateParams['genres']);
+ if (this.previousStateParams['themes'] !== undefined) this.activeThemeFilters = this.matchSelectedFilters(this.availableThemes, this.previousStateParams['themes']);
+ if (this.previousStateParams['playerPerspectives'] !== undefined) this.activePlayerPerspectiveFilters = this.matchSelectedFilters(this.availablePlayerPerspectives, this.previousStateParams['playerPerspectives']);
- this.refreshLibraryView().then(() => this.loading = false);
- });
+ this.refreshLibraryView().then(() => this.loading = false);
});
}
);
@@ -199,25 +198,29 @@ export class LibraryOverviewComponent implements AfterContentInit {
}
private saveStateToRoute(): void {
- let stateParams: Params = {};
+ let newStateParams: Params = {};
- if (this.searchTerm.trim().length > 0) stateParams['search'] = this.searchTerm;
- if (this.selectedSortOption !== this.defaultSortOption) stateParams['sort'] = this.toParam(this.selectedSortOption);
- if (this.getActiveGameModesFilters().length > 0) stateParams['gamemodes'] = this.getActiveGameModesFilters().join(',');
- if (this.activeGenreFilters.length > 0) stateParams['genres'] = this.activeGenreFilters.join(',');
- if (this.activeThemeFilters.length > 0) stateParams['themes'] = this.activeThemeFilters.join(',');
- if (this.activePlayerPerspectiveFilters.length > 0) stateParams['playerPerspectives'] = this.activePlayerPerspectiveFilters.join(',');
+ if (this.searchTerm.trim().length > 0) newStateParams['search'] = this.searchTerm;
+ if (this.selectedSortOption !== this.defaultSortOption) newStateParams['sort'] = LibraryOverviewComponent.toParam(this.selectedSortOption);
+ if (this.getActiveGameModesFilters().length > 0) newStateParams['gamemodes'] = this.getActiveGameModesFilters().join(',');
+ if (this.activeGenreFilters.length > 0) newStateParams['genres'] = this.activeGenreFilters.join(',');
+ if (this.activeThemeFilters.length > 0) newStateParams['themes'] = this.activeThemeFilters.join(',');
+ if (this.activePlayerPerspectiveFilters.length > 0) newStateParams['playerPerspectives'] = this.activePlayerPerspectiveFilters.join(',');
- const url = this.router.createUrlTree([], {relativeTo: this.route, queryParams: stateParams}).toString();
- this.location.go(url);
+ // only update the route if it changed
+ if (JSON.stringify(this.previousStateParams) !== JSON.stringify(newStateParams)) {
+ const url = this.router.createUrlTree([], {relativeTo: this.route, queryParams: newStateParams}).toString();
+ this.previousStateParams = newStateParams;
+ this.location.go(url);
+ }
}
- private toParam(sortOption: SortOption): string {
+ private static toParam(sortOption: SortOption): string {
return `${sortOption.field}_${sortOption.direction}`;
}
private matchSelectedSortOptionFromParam(sortParam: string): SortOption {
- return this.sortOptions.find(s => sortParam === this.toParam(s)) ?? this.defaultSortOption;
+ return this.sortOptions.find(s => sortParam === LibraryOverviewComponent.toParam(s)) ?? this.defaultSortOption;
}
private matchSelectedFilters(options: any[], paramString: string): string[] {