From 3328568bd2251e4f3ce51960344aa02e0d373012 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 27 Sep 2020 02:42:02 +0200 Subject: [PATCH] Cleaning up the dynamic routing between /api/items & /api/shows for the browse component --- src/app/app-routing.module.ts | 34 +++++---- .../items-grid/items-grid.component.ts | 69 ++++++++----------- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 3f3af45a..14ad3a71 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -27,30 +27,34 @@ const routes: Routes = [ {path: "browse", component: ItemsGridComponent, pathMatch: "full", resolve: {items: PageResolver.forResource("items", ItemsGridComponent.routeMapper)}, canLoad: [AuthGuard.forPermissions("read")], - canActivate: [AuthGuard.forPermissions("read")] + canActivate: [AuthGuard.forPermissions("read")], + runGuardsAndResolvers: "always" }, {path: "browse/:slug", component: ItemsGridComponent, resolve: {items: PageResolver.forResource("library/:slug/items", ItemsGridComponent.routeMapper)}, canLoad: [AuthGuard.forPermissions("read")], - canActivate: [AuthGuard.forPermissions("read")] + canActivate: [AuthGuard.forPermissions("read")], + runGuardsAndResolvers: "always" }, {path: "genre/:slug", component: ItemsGridComponent, pathMatch: "full", - resolve: {items: PageResolver.forResource("shows", ["genres", "studio"], "genres=ctn::slug")}, + resolve: {items: PageResolver.forResource("shows", ItemsGridComponent.routeMapper, "genres=ctn::slug")}, canLoad: [AuthGuard.forPermissions("read")], - canActivate: [AuthGuard.forPermissions("read")] + canActivate: [AuthGuard.forPermissions("read")], + runGuardsAndResolvers: "always" + }, + {path: "studio/:slug", component: ItemsGridComponent, pathMatch: "full", + resolve: {items: PageResolver.forResource("shows", ItemsGridComponent.routeMapper, "studio=:slug")}, + canLoad: [AuthGuard.forPermissions("read")], + canActivate: [AuthGuard.forPermissions("read")], + runGuardsAndResolvers: "always" }, - {path: "show/:slug", component: ShowDetailsComponent, - resolve: {show: ItemResolver.forResource("shows/:slug")}, - canLoad: [AuthGuard.forPermissions("read")], - canActivate: [AuthGuard.forPermissions("read")] - }, {path: "collection/:slug", component: CollectionComponent, resolve: { collection: ItemResolver.forResource("collections/:slug"), - shows: PageResolver.forResource("collections/:slug/shows") + shows: PageResolver.forResource("collections/:slug/shows", ItemsGridComponent.routeMapper) }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")] @@ -59,12 +63,18 @@ const routes: Routes = [ resolve: { collection: ItemResolver.forResource("people/:slug"), - shows: PageResolver.forResource("people/:slug/roles") + shows: PageResolver.forResource("people/:slug/roles", ItemsGridComponent.routeMapper) }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")] }, + {path: "show/:slug", component: ShowDetailsComponent, + resolve: {show: ItemResolver.forResource("shows/:slug")}, + canLoad: [AuthGuard.forPermissions("read")], + canActivate: [AuthGuard.forPermissions("read")] + }, + {path: "search/:query", component: SearchComponent, resolve: {items: ItemResolver.forResource("search/:query")}, canLoad: [AuthGuard.forPermissions("read")], @@ -77,7 +87,7 @@ const routes: Routes = [ canActivate: [AuthGuard.forPermissions("play")] }, - // TODO implement missing pages: /genre, /studio & an home page. + // TODO implement an home page. {path: "", pathMatch: 'full', redirectTo: "/browse"}, {path: "**", component: NotFoundComponent} diff --git a/src/app/components/items-grid/items-grid.component.ts b/src/app/components/items-grid/items-grid.component.ts index ff0bb8ed..47f9a77e 100644 --- a/src/app/components/items-grid/items-grid.component.ts +++ b/src/app/components/items-grid/items-grid.component.ts @@ -29,6 +29,8 @@ export class ItemsGridComponent implements OnInit sortKeys: string[] = ["title", "start year", "end year"] sortUp: boolean = true; + public static readonly showOnlyFilters: string[] = ["genres", "studio"] + public static readonly filters: string[] = [].concat(...ItemsGridComponent.showOnlyFilters) filters: {genres: Genre[], studio: Studio} = {genres: [], studio: null}; genres: Genre[] = []; studios: Studio[] = []; @@ -58,20 +60,31 @@ export class ItemsGridComponent implements OnInit }); } - // TODO need to put every filter available in one place (it is everywhere for now) - // TODO clean route change // TODO support dynamic switching between /genre & /browse & /whatever. + /* + * /browse -> /api/items | /api/shows + * /browse/:library -> /api/library/:slug/items | /api/library/:slug/shows + * /genre/:slug -> /api/shows + * /studio/:slug -> /api/shows + * + * /collection/:slug -> /api/collection/:slug/shows |> AS @Input + * /people/:slug -> /api/people/:slug/roles |> AS @Input + */ + static routeMapper(route: ActivatedRouteSnapshot, endpoint: string, query: [string, string][]): string { - const filter: string[] = ["genres", "studio"]; - let queryParams: [string, string][] = Object.entries(route.queryParams).filter(x => filter.includes(x[0])); + let queryParams: [string, string][] = Object.entries(route.queryParams) + .filter(x => ItemsGridComponent.filters.includes(x[0]) || x[0] == "sortBy"); if (query) queryParams.push(...query) - if (queryParams.length > 0) - endpoint = "shows"; - let params: string = '?' + queryParams.map(x => `${x[0]}=${x[1]}`).join('&'); + if (queryParams.some(x => ItemsGridComponent.showOnlyFilters.includes(x[0]))) + endpoint = endpoint.replace(/items?$/, "show"); + + let params: string = queryParams.length > 0 + ? '?' + queryParams.map(x => `${x[0]}=${x[1]}`).join('&') + : ""; return `api/${endpoint}${params}` } @@ -91,63 +104,36 @@ export class ItemsGridComponent implements OnInit addFilter(category: string, filter: IResource, isArray: boolean = true, isShowOnly: boolean = true) { - if (!this.complexFiltersEnabled) + if (!this.complexFiltersEnabled && isShowOnly) return; - let useShow: boolean; if (isArray) { if (this.filters[category].includes(filter)) - { this.filters[category].splice(this.filters[category].indexOf(filter), 1); - useShow = this.getFilterCount() != 0; - } else - { this.filters[category].push(filter); - useShow = true; - } } else { if (this.filters[category] == filter) - { this.filters[category] = null; - useShow = false; - } else - { this.filters[category] = filter; - useShow = filter != null; - } } - let url: URL = new URL(this.page.first); - if (isShowOnly) - { - url = useShow - ? new URL(this.page.changeType("shows")) - : new URL(this.page.changeType(this.defaultType)); - } - - let param: string; + let param: string = null; if (isArray && this.filters[category].length > 0) param = `ctn:${this.filters[category].map(x => x.slug).join(',')}`; else if (!isArray && this.filters[category] != null) param = filter.slug; - if (param != null) - url.searchParams.set(category, param); - else - url.searchParams.delete(category) this.router.navigate([], { relativeTo: this.route, queryParams: { [category]: param }, replaceUrl: true, queryParamsHandling: "merge" }); - this.client.get>(url.toString()) - .subscribe(x => this.page = Object.assign(new Page(), x)); } getThumb(slug: string) @@ -170,9 +156,12 @@ export class ItemsGridComponent implements OnInit this.sortType = type; this.sortUp = order; - let url: URL = new URL(this.page.first); - url.searchParams.set("sortBy", `${this.sortType.replace(/\s/g, "")}:${this.sortUp ? "asc" : "desc"}`); - this.client.get>(url.toString()) - .subscribe(x => this.page = Object.assign(new Page(), x)); + let param: string = `${this.sortType.replace(/\s/g, "")}:${this.sortUp ? "asc" : "desc"}`; + this.router.navigate([], { + relativeTo: this.route, + queryParams: { sortBy: param }, + replaceUrl: true, + queryParamsHandling: "merge" + }); } }