mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-11-03 19:17:16 -05:00 
			
		
		
		
	Implementing the browse all page with custom sorts
This commit is contained in:
		
							parent
							
								
									281f0e2024
								
							
						
					
					
						commit
						7e77e804b6
					
				@ -6,17 +6,23 @@ import {NotFoundComponent} from './not-found/not-found.component';
 | 
				
			|||||||
import {PlayerComponent} from "./pages/player/player.component";
 | 
					import {PlayerComponent} from "./pages/player/player.component";
 | 
				
			||||||
import {SearchComponent} from "./pages/search/search.component";
 | 
					import {SearchComponent} from "./pages/search/search.component";
 | 
				
			||||||
import {CollectionResolverService} from "./services/resolvers/collection-resolver.service";
 | 
					import {CollectionResolverService} from "./services/resolvers/collection-resolver.service";
 | 
				
			||||||
import {LibraryResolverService} from './services/resolvers/library-resolver.service';
 | 
					import {PageResolver} from './services/resolvers/library-resolver.service';
 | 
				
			||||||
import {PeopleResolverService} from "./services/resolvers/people-resolver.service";
 | 
					import {PeopleResolverService} from "./services/resolvers/people-resolver.service";
 | 
				
			||||||
import {SearchResolverService} from "./services/resolvers/search-resolver.service";
 | 
					import {SearchResolverService} from "./services/resolvers/search-resolver.service";
 | 
				
			||||||
import {ShowResolverService} from './services/resolvers/show-resolver.service';
 | 
					import {ShowResolverService} from './services/resolvers/show-resolver.service';
 | 
				
			||||||
import {StreamResolverService} from "./services/resolvers/stream-resolver.service";
 | 
					import {StreamResolverService} from "./services/resolvers/stream-resolver.service";
 | 
				
			||||||
import {ShowDetailsComponent} from './pages/show-details/show-details.component';
 | 
					import {ShowDetailsComponent} from './pages/show-details/show-details.component';
 | 
				
			||||||
import {AuthGuard} from "./auth/misc/authenticated-guard.service";
 | 
					import {AuthGuard} from "./auth/misc/authenticated-guard.service";
 | 
				
			||||||
 | 
					import {LibraryItem} from "../models/library-item";
 | 
				
			||||||
 | 
					import {CrudApi, LibraryItemService, LibraryService} from "./services/api.service";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const routes: Routes = [
 | 
					const routes: Routes = [
 | 
				
			||||||
	{path: "browse", component: LibraryItemGridComponent, pathMatch: "full", resolve: { shows: LibraryResolverService }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")]},
 | 
						{path: "browse", component: LibraryItemGridComponent, pathMatch: "full",
 | 
				
			||||||
	{path: "browse/:library-slug", component: LibraryItemGridComponent, resolve: { shows: LibraryResolverService }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")]},
 | 
							resolve: { items: PageResolver.forResource<LibraryItem>("items") },
 | 
				
			||||||
 | 
							canLoad: [AuthGuard.forPermissions("read")],
 | 
				
			||||||
 | 
							canActivate: [AuthGuard.forPermissions("read")]
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{path: "browse/:library-slug", component: LibraryItemGridComponent, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")]},
 | 
				
			||||||
	{path: "show/:show-slug", component: ShowDetailsComponent, resolve: { show: ShowResolverService }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")]},
 | 
						{path: "show/:show-slug", component: ShowDetailsComponent, resolve: { show: ShowResolverService }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")]},
 | 
				
			||||||
	{path: "collection/:collection-slug", component: CollectionComponent, resolve: { collection: CollectionResolverService }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")]},
 | 
						{path: "collection/:collection-slug", component: CollectionComponent, resolve: { collection: CollectionResolverService }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")]},
 | 
				
			||||||
	{path: "people/:people-slug", component: CollectionComponent, resolve: { collection: PeopleResolverService }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")]},
 | 
						{path: "people/:people-slug", component: CollectionComponent, resolve: { collection: PeopleResolverService }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")]},
 | 
				
			||||||
@ -32,7 +38,9 @@ const routes: Routes = [
 | 
				
			|||||||
		})],
 | 
							})],
 | 
				
			||||||
	exports: [RouterModule],
 | 
						exports: [RouterModule],
 | 
				
			||||||
	providers: [
 | 
						providers: [
 | 
				
			||||||
		LibraryResolverService,
 | 
							LibraryService,
 | 
				
			||||||
 | 
							LibraryItemService,
 | 
				
			||||||
 | 
							PageResolver.resolvers,
 | 
				
			||||||
		ShowResolverService,
 | 
							ShowResolverService,
 | 
				
			||||||
		CollectionResolverService,
 | 
							CollectionResolverService,
 | 
				
			||||||
		PeopleResolverService,
 | 
							PeopleResolverService,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,13 @@
 | 
				
			|||||||
import { Component } from '@angular/core';
 | 
					import {Component} from '@angular/core';
 | 
				
			||||||
import { HttpClient } from '@angular/common/http';
 | 
					import {Event, Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError} from '@angular/router';
 | 
				
			||||||
import { Event, Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router';
 | 
					import {Location} from "@angular/common";
 | 
				
			||||||
import * as $ from "jquery";
 | 
					 | 
				
			||||||
import { Location } from "@angular/common";
 | 
					 | 
				
			||||||
import {MatDialog} from "@angular/material/dialog";
 | 
					import {MatDialog} from "@angular/material/dialog";
 | 
				
			||||||
import {Account} from "../models/account";
 | 
					import {Account} from "../models/account";
 | 
				
			||||||
import {AccountComponent} from "./auth/account/account.component";
 | 
					import {AccountComponent} from "./auth/account/account.component";
 | 
				
			||||||
import {AuthService} from "./auth/auth.service";
 | 
					import {AuthService} from "./auth/auth.service";
 | 
				
			||||||
import {Library} from "../models/library";
 | 
					import {Library} from "../models/library";
 | 
				
			||||||
import {Page} from "../models/page";
 | 
					import {LibraryService} from "./services/api.service";
 | 
				
			||||||
 | 
					import * as $ from "jquery";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
	selector: 'app-root',
 | 
						selector: 'app-root',
 | 
				
			||||||
@ -20,13 +19,13 @@ export class AppComponent
 | 
				
			|||||||
	libraries: Library[];
 | 
						libraries: Library[];
 | 
				
			||||||
	isLoading: boolean = false;
 | 
						isLoading: boolean = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	constructor(private http: HttpClient,
 | 
						constructor(private libraryService: LibraryService,
 | 
				
			||||||
	            private router: Router,
 | 
						            private router: Router,
 | 
				
			||||||
	            private location: Location,
 | 
						            private location: Location,
 | 
				
			||||||
	            public authManager: AuthService,
 | 
						            public authManager: AuthService,
 | 
				
			||||||
	            public dialog: MatDialog)
 | 
						            public dialog: MatDialog)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		http.get<Page<Library>>("api/libraries").subscribe(result =>
 | 
							libraryService.getAll().subscribe(result =>
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			this.libraries = result.items;
 | 
								this.libraries = result.items;
 | 
				
			||||||
		}, error => console.error(error));
 | 
							}, error => console.error(error));
 | 
				
			||||||
 | 
				
			|||||||
@ -3,28 +3,32 @@
 | 
				
			|||||||
		<mat-icon>filter_list</mat-icon>
 | 
							<mat-icon>filter_list</mat-icon>
 | 
				
			||||||
	</button>
 | 
						</button>
 | 
				
			||||||
	<button mat-button matTooltipPosition="below" matTooltip="Sort" [matMenuTriggerFor]="sortMenu">
 | 
						<button mat-button matTooltipPosition="below" matTooltip="Sort" [matMenuTriggerFor]="sortMenu">
 | 
				
			||||||
		<mat-icon>sort</mat-icon> Sort by {{this.sortType}} <i *ngIf="this.sortUp" class="material-icons arrow">arrow_upward</i><i *ngIf="!this.sortUp" class="material-icons arrow">arrow_downward</i>
 | 
							<mat-icon>sort</mat-icon> Sort by {{this.sortType}}
 | 
				
			||||||
 | 
							<i *ngIf="this.sortUp" class="material-icons arrow">arrow_upward</i>
 | 
				
			||||||
 | 
							<i *ngIf="!this.sortUp" class="material-icons arrow">arrow_downward</i>
 | 
				
			||||||
	</button>
 | 
						</button>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<mat-menu #sortMenu="matMenu">
 | 
					<mat-menu #sortMenu="matMenu">
 | 
				
			||||||
	<div *ngFor="let type of this.sortTypes">
 | 
						<div *ngFor="let type of this.sortKeys">
 | 
				
			||||||
		<button *ngIf="type != this.sortType; else elseBlock;" mat-menu-item (click)="sort(type, true)">
 | 
							<button *ngIf="type != this.sortType; else elseBlock;" mat-menu-item (click)="sort(type, true)">
 | 
				
			||||||
			Sort by {{type}}
 | 
								Sort by {{type}}
 | 
				
			||||||
		</button>
 | 
							</button>
 | 
				
			||||||
		<ng-template #elseBlock>
 | 
							<ng-template #elseBlock>
 | 
				
			||||||
			<button mat-menu-item (click)="sort(type, !this.sortUp)">
 | 
								<button mat-menu-item (click)="sort(type, !this.sortUp)">
 | 
				
			||||||
				Sort by {{type}} <i *ngIf="!this.sortUp" class="material-icons arrow">arrow_upward</i><i *ngIf="this.sortUp" class="material-icons arrow">arrow_downward</i>
 | 
									Sort by {{type}}
 | 
				
			||||||
 | 
									<i *ngIf="!this.sortUp" class="material-icons arrow">arrow_upward</i>
 | 
				
			||||||
 | 
									<i *ngIf="this.sortUp" class="material-icons arrow">arrow_downward</i>
 | 
				
			||||||
			</button>
 | 
								</button>
 | 
				
			||||||
		</ng-template>
 | 
							</ng-template>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</mat-menu>
 | 
					</mat-menu>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="container-fluid justify-content-center">
 | 
					<div class="container-fluid justify-content-center">
 | 
				
			||||||
	<a class="show" *ngFor="let show of this.shows" [href]="getLink(show)" [routerLink]="getLink(show)">
 | 
						<a class="show" *ngFor="let item of this.page.items" [href]="getLink(item)" [routerLink]="getLink(item)">
 | 
				
			||||||
		<div matRipple [style.background-image]="getThumb(show.slug)" > </div>
 | 
							<div matRipple [style.background-image]="getThumb(item.slug)" > </div>
 | 
				
			||||||
		<p class="title">{{show.title}}</p>
 | 
							<p class="title">{{item.title}}</p>
 | 
				
			||||||
		<p class="date" *ngIf="show.endYear && show.startYear != show.endYear; else elseBlock">{{show.startYear}} - {{show.endYear}}</p>
 | 
							<p class="date" *ngIf="item.endYear && item.startYear != item.endYear; else elseBlock">{{item.startYear}} - {{item.endYear}}</p>
 | 
				
			||||||
		<ng-template #elseBlock><p class="date">{{show.startYear}}</p></ng-template>
 | 
							<ng-template #elseBlock><p class="date">{{item.startYear}}</p></ng-template>
 | 
				
			||||||
	</a>
 | 
						</a>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,9 @@
 | 
				
			|||||||
import { Component, OnInit, Input } from '@angular/core';
 | 
					import {Component, Input} from '@angular/core';
 | 
				
			||||||
import { ActivatedRoute } from '@angular/router';
 | 
					import {ActivatedRoute} from '@angular/router';
 | 
				
			||||||
import { DomSanitizer } from '@angular/platform-browser';
 | 
					import {DomSanitizer} from '@angular/platform-browser';
 | 
				
			||||||
import { Show } from "../../../models/show";
 | 
					import {ItemType, LibraryItem} from "../../../models/library-item";
 | 
				
			||||||
 | 
					import {Page} from "../../../models/page";
 | 
				
			||||||
 | 
					import {LibraryItemService} from "../../services/api.service";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
	selector: 'app-browse',
 | 
						selector: 'app-browse',
 | 
				
			||||||
@ -10,18 +12,17 @@ import { Show } from "../../../models/show";
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class LibraryItemGridComponent
 | 
					export class LibraryItemGridComponent
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	@Input() shows: Show[];
 | 
						@Input() page: Page<LibraryItem>;
 | 
				
			||||||
	@Input() sortEnabled: boolean = true;
 | 
						@Input() sortEnabled: boolean = true;
 | 
				
			||||||
	sortType: string = "title";
 | 
						sortType: string = "title";
 | 
				
			||||||
 | 
						sortKeys: string[] = ["title", "start year", "end year", "status", "type"]
 | 
				
			||||||
	sortUp: boolean = true;
 | 
						sortUp: boolean = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sortTypes: string[] = ["title", "release date"];
 | 
						constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer, private items: LibraryItemService)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		this.route.data.subscribe((data) =>
 | 
							this.route.data.subscribe((data) =>
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			this.shows = data.shows;
 | 
								this.page = data.items;
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -30,9 +31,9 @@ export class LibraryItemGridComponent
 | 
				
			|||||||
		return this.sanitizer.bypassSecurityTrustStyle("url(/poster/" + slug + ")");
 | 
							return this.sanitizer.bypassSecurityTrustStyle("url(/poster/" + slug + ")");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	getLink(show: Show)
 | 
						getLink(show: LibraryItem)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (show.isCollection)
 | 
							if (show.type == ItemType.Collection)
 | 
				
			||||||
			return "/collection/" + show.slug;
 | 
								return "/collection/" + show.slug;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			return "/show/" + show.slug;
 | 
								return "/show/" + show.slug;
 | 
				
			||||||
@ -43,19 +44,7 @@ export class LibraryItemGridComponent
 | 
				
			|||||||
		this.sortType = type;
 | 
							this.sortType = type;
 | 
				
			||||||
		this.sortUp = order;
 | 
							this.sortUp = order;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (type == this.sortTypes[0])
 | 
							this.items.getAll({sort: `${this.sortType.replace(/\s/g, "")}:${this.sortUp ? "asc" : "desc"}`})
 | 
				
			||||||
		{
 | 
								.subscribe(x => this.page = x);
 | 
				
			||||||
			if (order)
 | 
					 | 
				
			||||||
				this.shows.sort((a, b) => { if (a.title < b.title) return -1; else if (a.title > b.title) return 1; return 0; });
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				this.shows.sort((a, b) => { if (a.title < b.title) return 1; else if (a.title > b.title) return -1; return 0; });
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (type == this.sortTypes[1])
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (order)
 | 
					 | 
				
			||||||
				this.shows.sort((a, b) => a.startYear - b.startYear);
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				this.shows.sort((a, b) => b.startYear - a.startYear);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										77
									
								
								src/app/services/api.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/app/services/api.service.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					import {Injectable} from "@angular/core";
 | 
				
			||||||
 | 
					import {HttpClient} from "@angular/common/http";
 | 
				
			||||||
 | 
					import {Observable} from "rxjs"
 | 
				
			||||||
 | 
					import {map} from "rxjs/operators"
 | 
				
			||||||
 | 
					import {Page} from "../../models/page";
 | 
				
			||||||
 | 
					import {IResource} from "../../models/resources/resource";
 | 
				
			||||||
 | 
					import {Library} from "../../models/library";
 | 
				
			||||||
 | 
					import {LibraryItem} from "../../models/library-item";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CrudApi<T extends IResource>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						constructor(private client: HttpClient, private route: string) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						get(id: number | string): Observable<T>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return this.client.get<T>(`/api/${this.route}/${id}`);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						getAll(args: {sort: string} = null): Observable<Page<T>>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							let params: string = "?";
 | 
				
			||||||
 | 
							if (args && args.sort)
 | 
				
			||||||
 | 
								params += "sortBy=" + args.sort;
 | 
				
			||||||
 | 
							if (params == "?")
 | 
				
			||||||
 | 
								params = "";
 | 
				
			||||||
 | 
							return this.client.get<Page<T>>(`/api/${this.route}${params}`);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						loadNext(page: Page<T>): Observable<Page<T>>
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
						    if (page.next == null)
 | 
				
			||||||
 | 
						    	return;
 | 
				
			||||||
 | 
							return this.client.get<Page<T>>(page.next).pipe(map(x =>
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								x.items = page.items.concat(x.items);
 | 
				
			||||||
 | 
								x.count += page.count;
 | 
				
			||||||
 | 
								return x;
 | 
				
			||||||
 | 
							}));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						create(item: T): Observable<T>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return this.client.post<T>(`/api/${this.route}`, item);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						edit(item: T): Observable<T>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return this.client.put<T>(`/api/${this.route}`, item);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						delete(item: T): Observable<T>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return this.client.delete<T>(`/api/${this.route}/${item.slug}`);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Injectable({
 | 
				
			||||||
 | 
						providedIn: 'root'
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class LibraryService extends CrudApi<Library>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						constructor(client: HttpClient)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							super(client, "libraries");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Injectable({
 | 
				
			||||||
 | 
						providedIn: 'root'
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class LibraryItemService extends CrudApi<LibraryItem>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						constructor(client: HttpClient)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							super(client, "items");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,48 +0,0 @@
 | 
				
			|||||||
import {Injectable} from "@angular/core";
 | 
					 | 
				
			||||||
import {HttpClient} from "@angular/common/http";
 | 
					 | 
				
			||||||
import {Observable} from "rxjs"
 | 
					 | 
				
			||||||
import {Page} from "../../models/page";
 | 
					 | 
				
			||||||
import {IResource} from "../../models/resources/resource";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class CrudApi<T extends IResource>
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  constructor(private client: HttpClient, private route: string) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  get(id: number | string): Observable<T>
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    return this.client.get<T>(`/api/${this.route}/${id}`);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  getAll(id: number | string): Observable<Page<T>>
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    return this.client.get<Page<T>>(`/api/${this.route}`);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  create(item: T): Observable<T>
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    return this.client.post<T>(`/api/${this.route}`, item);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  edit(item: T): Observable<T>
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    return this.client.put<T>(`/api/${this.route}`, item);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delete(item: T): Observable<T>
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    return this.client.delete<T>(`/api/${this.route}/${item.slug}`);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Injectable({
 | 
					 | 
				
			||||||
	providedIn: 'root'
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
export class LibraryService
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	constructor() { }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	get()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -4,42 +4,36 @@ import { MatSnackBar } from '@angular/material/snack-bar';
 | 
				
			|||||||
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';
 | 
					import { ActivatedRouteSnapshot, Resolve } from '@angular/router';
 | 
				
			||||||
import { EMPTY, Observable } from 'rxjs';
 | 
					import { EMPTY, Observable } from 'rxjs';
 | 
				
			||||||
import { catchError } from 'rxjs/operators';
 | 
					import { catchError } from 'rxjs/operators';
 | 
				
			||||||
import { Show } from "../../../models/show";
 | 
					import {Page} from "../../../models/page";
 | 
				
			||||||
 | 
					import {IResource} from "../../../models/resources/resource";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
export class LibraryResolverService implements Resolve<Show[]>
 | 
					export class PageResolver
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
 | 
						public static resolvers: any[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	resolve(route: ActivatedRouteSnapshot): Show[] | Observable<Show[]> | Promise<Show[]>
 | 
						static forResource<T extends IResource>(resource: string)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		let slug: string = route.paramMap.get("library-slug");
 | 
							@Injectable()
 | 
				
			||||||
 | 
							class Resolver<T> implements Resolve<Page<T>>
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (slug == null)
 | 
								resolve(route: ActivatedRouteSnapshot): Page<T> | Observable<Page<T>> | Promise<Page<T>>
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return this.http.get<Show[]>("api/shows").pipe(catchError((error: HttpErrorResponse) =>
 | 
					 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				console.log(error.status + " - " + error.message);
 | 
									return this.http.get<Page<T>>(`api/${resource}`).pipe(catchError((error: HttpErrorResponse) =>
 | 
				
			||||||
				this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
 | 
					 | 
				
			||||||
				return EMPTY;
 | 
					 | 
				
			||||||
			}));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return this.http.get<Show[]>("api/libraries/" + slug).pipe(catchError((error: HttpErrorResponse) =>
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				console.log(error.status + " - " + error.message);
 | 
					 | 
				
			||||||
				if (error.status == 404)
 | 
					 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					this.snackBar.open("Library \"" + slug + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
 | 
										console.log(error.status + " - " + error.message);
 | 
				
			||||||
				}
 | 
										this.snackBar.open(`An unknown error occurred: ${error.message}.`, null, {
 | 
				
			||||||
				else
 | 
											horizontalPosition: "left",
 | 
				
			||||||
				{
 | 
											panelClass: ['snackError'],
 | 
				
			||||||
					this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
 | 
											duration: 2500 }
 | 
				
			||||||
				}
 | 
										);
 | 
				
			||||||
				return EMPTY;
 | 
										return EMPTY;
 | 
				
			||||||
			}));
 | 
									}));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							PageResolver.resolvers.push(Resolver);
 | 
				
			||||||
 | 
							return Resolver;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,20 +1,20 @@
 | 
				
			|||||||
enum ItemType
 | 
					import {IResource} from "./resources/resource";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export enum ItemType
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Show,
 | 
						Show,
 | 
				
			||||||
	Movie,
 | 
						Movie,
 | 
				
			||||||
	Collection
 | 
						Collection
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface LibraryItem
 | 
					export interface LibraryItem extends IResource
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ID: number
 | 
						title: string
 | 
				
			||||||
	Slug: string
 | 
						overview: string
 | 
				
			||||||
	Title: string
 | 
						status: string
 | 
				
			||||||
	Overview: string
 | 
						trailerUrl: string
 | 
				
			||||||
	Status: string
 | 
						startYear: number
 | 
				
			||||||
	TrailerUrl: string
 | 
						endYear: number
 | 
				
			||||||
	StartYear: number
 | 
						poster: string
 | 
				
			||||||
	EndYear: number
 | 
						type: ItemType
 | 
				
			||||||
	Poster: string
 | 
					 | 
				
			||||||
	Type: ItemType
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1,4 +1,6 @@
 | 
				
			|||||||
export interface Library
 | 
					import {IResource} from "./resources/resource";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface Library extends IResource
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	id: number;
 | 
						id: number;
 | 
				
			||||||
	slug: string;
 | 
						slug: string;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user