diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 34bdfd45..fd0658b6 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,7 +1,7 @@ import {NgModule} from '@angular/core'; import {RouterModule, Routes} from '@angular/router'; import {ItemsGridComponent} from './components/items-grid/items-grid.component'; -import {NotFoundComponent} from './not-found/not-found.component'; +import {NotFoundComponent} from './pages/not-found/not-found.component'; import {PageResolver} from './services/resolvers/page-resolver.service'; import {ShowDetailsComponent} from './pages/show-details/show-details.component'; import {AuthGuard} from "./auth/misc/authenticated-guard.service"; @@ -18,7 +18,8 @@ import {Show} from "../models/show"; import {ItemResolver} from "./services/resolvers/item-resolver.service"; import {CollectionComponent} from "./pages/collection/collection.component"; import {Collection} from "../models/collection"; -import {People} from "../models/people"; +import {SearchComponent} from "./pages/search/search.component"; +import {SearchResult} from "../models/search-result"; const routes: Routes = [ {path: "browse", component: ItemsGridComponent, pathMatch: "full", @@ -55,8 +56,14 @@ const routes: Routes = [ canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")] }, + + {path: "search/:query", component: SearchComponent, + resolve: { items: ItemResolver.forResource("search/:query") }, + canLoad: [AuthGuard.forPermissions("read")], + canActivate: [AuthGuard.forPermissions("read")] + }, + // {path: "watch/:item", component: PlayerComponent, resolve: { item: StreamResolverService }, canLoad: [AuthGuard.forPermissions("play")], canActivate: [AuthGuard.forPermissions("play")]}, - // {path: "search/:query", component: SearchComponent, resolve: { items: SearchResolverService }, canLoad: [AuthGuard.forPermissions("read")], canActivate: [AuthGuard.forPermissions("read")]}, // TODO implement missing pages: /genre, /studio & an home page. {path: "**", component: NotFoundComponent} ]; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 475addbd..cb84ddd6 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,31 +1,30 @@ import {HttpClientModule} from '@angular/common/http'; import {NgModule} from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCardModule } from '@angular/material/card'; -import { MatRippleModule } from '@angular/material/core'; -import { MatIconModule } from '@angular/material/icon'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatProgressBarModule } from '@angular/material/progress-bar'; -import { MatSelectModule } from '@angular/material/select'; -import { MatSliderModule } from '@angular/material/slider'; -import { MatSnackBarModule } from '@angular/material/snack-bar'; -import { MatTooltipModule } from '@angular/material/tooltip'; -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { ItemsGridComponent } from './components/items-grid/items-grid.component'; -import { CollectionComponent } from './pages/collection/collection.component'; -import { EpisodesListComponent } from './components/episodes-list/episodes-list.component'; -import { NotFoundComponent } from './not-found/not-found.component'; -import { PeopleListComponent } from './components/people-list/people-list.component'; -import { PlayerComponent } from './pages/player/player.component'; -import { SearchComponent } from './pages/search/search.component'; -import { ShowDetailsComponent } from './pages/show-details/show-details.component'; -import { ShowsListComponent } from './components/shows-list/shows-list.component'; +import {MatButtonModule} from '@angular/material/button'; +import {MatCardModule} from '@angular/material/card'; +import {MatRippleModule} from '@angular/material/core'; +import {MatIconModule} from '@angular/material/icon'; +import {MatMenuModule} from '@angular/material/menu'; +import {MatProgressBarModule} from '@angular/material/progress-bar'; +import {MatSelectModule} from '@angular/material/select'; +import {MatSliderModule} from '@angular/material/slider'; +import {MatSnackBarModule} from '@angular/material/snack-bar'; +import {MatTooltipModule} from '@angular/material/tooltip'; +import {BrowserModule} from '@angular/platform-browser'; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {AppRoutingModule} from './app-routing.module'; +import {AppComponent} from './app.component'; +import {ItemsGridComponent} from './components/items-grid/items-grid.component'; +import {CollectionComponent} from './pages/collection/collection.component'; +import {EpisodesListComponent} from './components/episodes-list/episodes-list.component'; +import {NotFoundComponent} from './pages/not-found/not-found.component'; +import {PeopleListComponent} from './components/people-list/people-list.component'; +import {PlayerComponent} from './pages/player/player.component'; +import {SearchComponent} from './pages/search/search.component'; +import {ShowDetailsComponent} from './pages/show-details/show-details.component'; import {FormsModule, ReactiveFormsModule} from "@angular/forms"; -import { MatInputModule } from "@angular/material/input"; -import { MatFormFieldModule } from "@angular/material/form-field"; +import {MatInputModule} from "@angular/material/input"; +import {MatFormFieldModule} from "@angular/material/form-field"; import {MatTabsModule} from "@angular/material/tabs"; import {PasswordValidator} from "./misc/password-validator"; import {MatCheckboxModule} from "@angular/material/checkbox"; @@ -34,12 +33,11 @@ import {FallbackDirective} from "./misc/fallback.directive"; import {AuthModule} from "./auth/auth.module"; import {AuthRoutingModule} from "./auth/auth-routing.module"; import {TrailerDialogComponent} from './pages/trailer-dialog/trailer-dialog.component'; -import {CollectionsListComponent} from "./collection-list/collections-list.component"; +import {ItemsListComponent} from "./components/items-list/items-list.component"; import {MetadataEditComponent} from './pages/metadata-edit/metadata-edit.component'; import {MatChipsModule} from "@angular/material/chips"; import {MatAutocompleteModule} from "@angular/material/autocomplete"; import {MatExpansionModule} from "@angular/material/expansion"; -import {ShowGridComponent} from './components/show-grid/show-grid.component'; import {InfiniteScrollModule} from "ngx-infinite-scroll"; @@ -54,13 +52,11 @@ import {InfiniteScrollModule} from "ngx-infinite-scroll"; CollectionComponent, SearchComponent, PeopleListComponent, - ShowsListComponent, PasswordValidator, FallbackDirective, TrailerDialogComponent, - CollectionsListComponent, + ItemsListComponent, MetadataEditComponent, - ShowGridComponent ], imports: [ BrowserModule, diff --git a/src/app/collection-list/collections-list.component.html b/src/app/collection-list/collections-list.component.html deleted file mode 100644 index 682e4daf..00000000 --- a/src/app/collection-list/collections-list.component.html +++ /dev/null @@ -1,10 +0,0 @@ -
- - - -
diff --git a/src/app/collection-list/collections-list.component.scss b/src/app/collection-list/collections-list.component.scss deleted file mode 100644 index 9aecbf4a..00000000 --- a/src/app/collection-list/collections-list.component.scss +++ /dev/null @@ -1,142 +0,0 @@ -@import "~bootstrap/scss/functions"; -@import "~bootstrap/scss/variables"; -@import "~bootstrap/scss/mixins/breakpoints"; - -.collections-container -{ - display: flex; - padding-left: 15px; - padding-right: 15px; - overflow-x: auto; - min-width: 100%; - flex-shrink: 0; - flex-direction: row; - - &::-webkit-scrollbar - { - height: 4px; - background: transparent; - } - - &::-webkit-scrollbar-thumb - { - background-color: #999; - border-radius: 90px; - - &:host-context(.hoverEnabled) &:hover - { - background-color: rgb(134, 127, 127); - } - } -} - -.collection -{ - width: 33%; - min-width: 120px; - max-width: 200px; - list-style: none; - padding: .5em; - text-decoration: none; - color: inherit; - outline: none; - flex-shrink: 0; - flex-grow: 0; - - @include media-breakpoint-up(sm) - { - width: 25%; - } - - @include media-breakpoint-up(md) - { - width: 20%; - padding: 1em; - } - - @include media-breakpoint-up(lg) - { - width: 18%; - } - - @include media-breakpoint-up(xl) - { - width: 15%; - } - - - &:focus, &:hover - { - > div - { - outline: solid var(--accentColor); - } - - > .title - { - text-decoration: underline; - } - } - - > div - { - width: 100%; - height: 0; - padding-top: 147.0588%; - background-size: cover; - background-color: #333333; - } - - > p - { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - text-align: center; - margin-bottom: 0px; - opacity: 1; - } - - &:host-context(.hoverEnabled) &:hover - { - cursor: pointer; - } -} - -.scroll-row -{ - position: relative; - - &:host-context(.hoverEnabled) &:hover - { - .scrollBtn - { - display: block; - } - } -} - -.scrollBtn -{ - padding: 0; - outline: none; - min-width: 0; - position: absolute; - top: 30%; - bottom: 40%; - display: none; - - &.leftBtn - { - left: 0; - padding-left: 10px; - padding-right: 2px; - } - - &.rightBtn - { - right: 0; - padding-right: 10px; - padding-left: 2px; - } -} diff --git a/src/app/collection-list/collections-list.component.ts b/src/app/collection-list/collections-list.component.ts deleted file mode 100644 index 1851e0db..00000000 --- a/src/app/collection-list/collections-list.component.ts +++ /dev/null @@ -1,50 +0,0 @@ -import {Component, ElementRef, Input, ViewChild} from "@angular/core"; -import {Collection} from "../../models/collection"; -import {MatButton} from "@angular/material/button"; -import {DomSanitizer} from "@angular/platform-browser"; - -@Component({ - selector: 'app-collections-list', - templateUrl: './collections-list.component.html', - styleUrls: ['./collections-list.component.scss'] -}) -export class CollectionsListComponent -{ - @Input() collections: Collection[]; - @ViewChild("scrollView", {static: true}) private scrollView: ElementRef; - @ViewChild("leftBtn", {static: false}) private leftBtn: MatButton; - @ViewChild("rightBtn", {static: false}) private rightBtn: MatButton; - - constructor(private sanitizer: DomSanitizer) - { - } - - scrollLeft() - { - let scroll: number = this.scrollView.nativeElement.offsetWidth * 0.80; - this.scrollView.nativeElement.scrollBy({top: 0, left: -scroll, behavior: "smooth"}); - } - - scrollRight() - { - let scroll: number = this.scrollView.nativeElement.offsetWidth * 0.80; - this.scrollView.nativeElement.scrollBy({top: 0, left: scroll, behavior: "smooth"}); - } - - onScroll() - { - if (this.scrollView.nativeElement.scrollLeft <= 0) - this.leftBtn._elementRef.nativeElement.classList.add("d-none"); - else - this.leftBtn._elementRef.nativeElement.classList.remove("d-none"); - if (this.scrollView.nativeElement.scrollLeft >= this.scrollView.nativeElement.scrollWidth - this.scrollView.nativeElement.clientWidth) - this.rightBtn._elementRef.nativeElement.classList.add("d-none"); - else - this.rightBtn._elementRef.nativeElement.classList.remove("d-none"); - } - - getThumb(slug: string) - { - return this.sanitizer.bypassSecurityTrustStyle("url(/poster/" + slug + ")"); - } -} \ No newline at end of file diff --git a/src/app/components/items-grid/items-grid.component.html b/src/app/components/items-grid/items-grid.component.html index e0fc168c..91067f22 100644 --- a/src/app/components/items-grid/items-grid.component.html +++ b/src/app/components/items-grid/items-grid.component.html @@ -27,7 +27,7 @@
-

{{item.title}}

+

{{item.title ? item.title : item.name}}

{{getDate(item)}}

diff --git a/src/app/components/items-grid/items-grid.component.scss b/src/app/components/items-grid/items-grid.component.scss index 2cd1034f..e7d1bc87 100644 --- a/src/app/components/items-grid/items-grid.component.scss +++ b/src/app/components/items-grid/items-grid.component.scss @@ -79,7 +79,7 @@ button overflow: hidden; text-overflow: ellipsis; text-align: center; - margin-bottom: 0px; + margin-bottom: 0; opacity: 1; &.date diff --git a/src/app/components/items-grid/items-grid.component.ts b/src/app/components/items-grid/items-grid.component.ts index 094598ff..94dbdb58 100644 --- a/src/app/components/items-grid/items-grid.component.ts +++ b/src/app/components/items-grid/items-grid.component.ts @@ -1,10 +1,12 @@ import {Component, Input} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {DomSanitizer} from '@angular/platform-browser'; -import {ItemType, LibraryItem} from "../../../models/library-item"; +import {LibraryItem} from "../../../models/library-item"; import {Page} from "../../../models/page"; import {HttpClient} from "@angular/common/http"; import {Show, ShowRole} from "../../../models/show"; +import {Collection} from "../../../models/collection"; +import {ItemsUtils} from "../../misc/items-utils"; @Component({ selector: 'app-items', @@ -13,7 +15,7 @@ import {Show, ShowRole} from "../../../models/show"; }) export class ItemsGridComponent { - @Input() page: Page; + @Input() page: Page; @Input() sortEnabled: boolean = true; sortType: string = "title"; sortKeys: string[] = ["title", "start year", "end year"] @@ -34,12 +36,14 @@ export class ItemsGridComponent return this.sanitizer.bypassSecurityTrustStyle("url(/poster/" + slug + ")"); } - getLink(item: LibraryItem | Show | ShowRole) + getDate(item: LibraryItem | Show | ShowRole | Collection) { - if ("type" in item && item.type == ItemType.Collection) - return "/collection/" + item.slug; - else - return "/show/" + item.slug; + return ItemsUtils.getDate(item); + } + + getLink(item: LibraryItem | Show | ShowRole | Collection) + { + return ItemsUtils.getLink(item); } sort(type: string, order: boolean) @@ -52,20 +56,4 @@ export class ItemsGridComponent this.client.get>(url.toString()) .subscribe(x => this.page = Object.assign(new Page(), x)); } - - getDate(item: LibraryItem | Show | ShowRole): string - { - if ("role" in item && item.role) - { - if ("type" in item && item.type) - return `as ${item.role} (${item.type})`; - return `as ${item.role}`; - } - if ("type" in item && item.type && typeof item.type == "string") - return item.type; - - if (item.endYear && item.startYear != item.endYear) - return `${item.startYear} - ${item.endYear}` - return item.startYear?.toString(); - } } diff --git a/src/app/components/items-list/items-list.component.html b/src/app/components/items-list/items-list.component.html new file mode 100644 index 00000000..c100a352 --- /dev/null +++ b/src/app/components/items-list/items-list.component.html @@ -0,0 +1,11 @@ + diff --git a/src/app/components/shows-list/shows-list.component.scss b/src/app/components/items-list/items-list.component.scss similarity index 95% rename from src/app/components/shows-list/shows-list.component.scss rename to src/app/components/items-list/items-list.component.scss index 9ec122f5..6ff45961 100644 --- a/src/app/components/shows-list/shows-list.component.scss +++ b/src/app/components/items-list/items-list.component.scss @@ -2,7 +2,7 @@ @import "../../../../node_modules/bootstrap/scss/variables"; @import "../../../../node_modules/bootstrap/scss/mixins/breakpoints"; -.shows-container +.container { display: flex; padding-left: 15px; @@ -11,6 +11,8 @@ min-width: 100%; flex-shrink: 0; flex-direction: row; + scrollbar-width: thin; + scrollbar-color: #999 transparent; &::-webkit-scrollbar { @@ -30,7 +32,7 @@ } } -.show +.item { width: 33%; min-width: 120px; @@ -93,7 +95,7 @@ overflow: hidden; text-overflow: ellipsis; text-align: center; - margin-bottom: 0px; + margin-bottom: 0; opacity: 1; &.date diff --git a/src/app/components/items-list/items-list.component.ts b/src/app/components/items-list/items-list.component.ts new file mode 100644 index 00000000..ef049521 --- /dev/null +++ b/src/app/components/items-list/items-list.component.ts @@ -0,0 +1,39 @@ +import {Component, Input} from "@angular/core"; +import {Collection} from "../../../models/collection"; +import {DomSanitizer} from "@angular/platform-browser"; +import {HorizontalScroller} from "../../misc/horizontal-scroller"; +import {Page} from "../../../models/page"; +import {HttpClient} from "@angular/common/http"; +import {Show, ShowRole} from "../../../models/show"; +import {LibraryItem} from "../../../models/library-item"; +import {ItemsUtils} from "../../misc/items-utils"; + +@Component({ + selector: 'app-items-list', + templateUrl: './items-list.component.html', + styleUrls: ['./items-list.component.scss'] +}) +export class ItemsListComponent extends HorizontalScroller +{ + @Input() items: Page; + + constructor(private sanitizer: DomSanitizer, public client: HttpClient) + { + super(); + } + + getThumb(slug: string) + { + return this.sanitizer.bypassSecurityTrustStyle("url(/poster/" + slug + ")"); + } + + getDate(item: LibraryItem | Show | ShowRole | Collection) + { + return ItemsUtils.getDate(item); + } + + getLink(item: LibraryItem | Show | ShowRole | Collection) + { + return ItemsUtils.getLink(item); + } +} \ No newline at end of file diff --git a/src/app/components/show-grid/show-grid.component.html b/src/app/components/show-grid/show-grid.component.html deleted file mode 100644 index 1826ecb6..00000000 --- a/src/app/components/show-grid/show-grid.component.html +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/src/app/components/show-grid/show-grid.component.scss b/src/app/components/show-grid/show-grid.component.scss deleted file mode 100644 index 074f9c31..00000000 --- a/src/app/components/show-grid/show-grid.component.scss +++ /dev/null @@ -1,144 +0,0 @@ -@import "../../../../node_modules/bootstrap/scss/functions"; -@import "../../../../node_modules/bootstrap/scss/variables"; -@import "../../../../node_modules/bootstrap/scss/mixins/breakpoints"; - -button -{ - outline: none; -} - -.arrow -{ - font-size: 12px; -} - -.container-fluid -{ - display: flex; - flex-wrap: wrap; -} - -.show-container -{ - width: 100%; - min-width: 300px; - list-style: none; - padding: .5em; - - @include media-breakpoint-up(lg) - { - width: 50%; - } - - @include media-breakpoint-up(xl) - { - width: 33%; - } -} - -.show -{ - padding: 0; - - > a - { - text-decoration: none; - color: inherit; - outline: none; - position: relative; - - &:focus, &:hover - { - - > .data > .title - { - text-decoration: underline; - } - } - - > .thumb - { - width: 33%; - - > div - { - width: 100%; - height: 0; - padding-top: 147.0588%; - background-size: cover; - background-color: #333333; - } - } - - > .data - { - width: 67%; - padding: .5rem; - position: absolute; - top: 0; - bottom: 0; - right: 0; - - > p:not(.overview) - { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - text-align: center; - margin-bottom: 0; - opacity: 1; - display: inline-block; - - &.date - { - opacity: 0.8; - font-size: 0.8em; - padding-left: 1rem; - } - } - - > .overview - { - overflow-y: auto; - height: calc(100% - 4rem); - text-align: justify; - padding-right: .5rem; - margin-bottom: 0; - } - - &:host-context(.hoverEnabled) &:hover - { - cursor: pointer; - } - } - } -} - - -.provider -{ - display: inline-block; - width: 2.5rem; - height: 2.5rem; - margin: .25rem; - - > a - { - width: 2.5rem; - height: 2.5rem; - position: relative; - display: inline-block; - - > img - { - position: absolute; - top: 0; - bottom: 0; - right: 0; - left: 0; - margin: auto; - max-width: 2.5rem; - max-height: 2.5rem; - } - } -} \ No newline at end of file diff --git a/src/app/components/show-grid/show-grid.component.ts b/src/app/components/show-grid/show-grid.component.ts deleted file mode 100644 index 2d65b410..00000000 --- a/src/app/components/show-grid/show-grid.component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {AfterViewInit, Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; -import {Show} from "../../../models/show"; -import {DomSanitizer} from "@angular/platform-browser"; - -@Component({ - selector: 'app-show-grid', - templateUrl: './show-grid.component.html', - styleUrls: ['./show-grid.component.scss'] -}) -export class ShowGridComponent -{ - @Input() shows: Show[] - @Input() externalShows: boolean = false; - @Output() clickCallback: EventEmitter = new EventEmitter(); - - constructor(private sanitizer: DomSanitizer) { } - - getThumb(show: Show) - { - return this.sanitizer.bypassSecurityTrustStyle(`url(${show.poster})`); - } - - getLink(show: Show) - { - if (this.externalShows) - return null; - return `/show/${show.slug}`; - } -} diff --git a/src/app/components/shows-list/shows-list.component.html b/src/app/components/shows-list/shows-list.component.html deleted file mode 100644 index 5a50a1fe..00000000 --- a/src/app/components/shows-list/shows-list.component.html +++ /dev/null @@ -1,12 +0,0 @@ - diff --git a/src/app/components/shows-list/shows-list.component.ts b/src/app/components/shows-list/shows-list.component.ts deleted file mode 100644 index 1bbd818b..00000000 --- a/src/app/components/shows-list/shows-list.component.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Component, ElementRef, Input, ViewChild } from '@angular/core'; -import { MatButton } from "@angular/material/button"; -import { DomSanitizer } from "@angular/platform-browser"; -import { Show } from "../../../models/show"; - -@Component({ - selector: 'app-shows-list', - templateUrl: './shows-list.component.html', - styleUrls: ['./shows-list.component.scss'] -}) -export class ShowsListComponent -{ - @Input() shows: Show[]; - @ViewChild("scrollView", { static: true }) private scrollView: ElementRef; - @ViewChild("leftBtn", { static: false }) private leftBtn: MatButton; - @ViewChild("rightBtn", { static: false }) private rightBtn: MatButton; - - constructor(private sanitizer: DomSanitizer) { } - - scrollLeft() - { - let scroll: number = this.scrollView.nativeElement.offsetWidth * 0.80; - this.scrollView.nativeElement.scrollBy({ top: 0, left: -scroll, behavior: "smooth" }); - } - - scrollRight() - { - let scroll: number = this.scrollView.nativeElement.offsetWidth * 0.80; - this.scrollView.nativeElement.scrollBy({ top: 0, left: scroll, behavior: "smooth" }); - } - - onScroll() - { - if (this.scrollView.nativeElement.scrollLeft <= 0) - this.leftBtn._elementRef.nativeElement.classList.add("d-none"); - else - this.leftBtn._elementRef.nativeElement.classList.remove("d-none"); - if (this.scrollView.nativeElement.scrollLeft >= this.scrollView.nativeElement.scrollWidth - this.scrollView.nativeElement.clientWidth) - this.rightBtn._elementRef.nativeElement.classList.add("d-none"); - else - this.rightBtn._elementRef.nativeElement.classList.remove("d-none"); - } - - getThumb(slug: string) - { - return this.sanitizer.bypassSecurityTrustStyle("url(/poster/" + slug + ")"); - } -} diff --git a/src/app/misc/horizontal-scroller.ts b/src/app/misc/horizontal-scroller.ts index f9e675c3..ea25efd3 100644 --- a/src/app/misc/horizontal-scroller.ts +++ b/src/app/misc/horizontal-scroller.ts @@ -6,7 +6,7 @@ export class HorizontalScroller @ViewChild("scrollView", { static: true }) private scrollView: ElementRef; @ViewChild("leftBtn", { static: false }) private leftBtn: MatButton; @ViewChild("rightBtn", { static: false }) private rightBtn: MatButton; - @ViewChild("itemsDom", { static: false }) private items: ElementRef; + @ViewChild("itemsDom", { static: false }) private itemsDom: ElementRef; scrollLeft() { @@ -22,7 +22,7 @@ export class HorizontalScroller roundScroll(offset: number): number { - let itemSize: number = this.items.nativeElement.scrollWidth; + let itemSize: number = this.itemsDom.nativeElement.scrollWidth; offset = Math.round(offset / itemSize) * itemSize; if (offset == 0) diff --git a/src/app/misc/items-utils.ts b/src/app/misc/items-utils.ts new file mode 100644 index 00000000..c342cbe8 --- /dev/null +++ b/src/app/misc/items-utils.ts @@ -0,0 +1,30 @@ +import {ItemType, LibraryItem} from "../../models/library-item"; +import {Show, ShowRole} from "../../models/show"; +import {Collection} from "../../models/collection"; + +export class ItemsUtils +{ + static getLink(item: LibraryItem | Show | ShowRole | Collection): string + { + if ("type" in item && item.type == ItemType.Collection) + return "/collection/" + item.slug; + else + return "/show/" + item.slug; + } + + static getDate(item: LibraryItem | Show | ShowRole | Collection): string + { + if ("role" in item && item.role) + { + if ("type" in item && item.type) + return `as ${item.role} (${item.type})`; + return `as ${item.role}`; + } + if ("type" in item && item.type && typeof item.type == "string") + return item.type; + + if (item.endYear && item.startYear != item.endYear) + return `${item.startYear} - ${item.endYear}` + return item.startYear?.toString(); + } +} \ No newline at end of file diff --git a/src/app/not-found/not-found.component.html b/src/app/pages/not-found/not-found.component.html similarity index 100% rename from src/app/not-found/not-found.component.html rename to src/app/pages/not-found/not-found.component.html diff --git a/src/app/not-found/not-found.component.scss b/src/app/pages/not-found/not-found.component.scss similarity index 100% rename from src/app/not-found/not-found.component.scss rename to src/app/pages/not-found/not-found.component.scss diff --git a/src/app/not-found/not-found.component.ts b/src/app/pages/not-found/not-found.component.ts similarity index 100% rename from src/app/not-found/not-found.component.ts rename to src/app/pages/not-found/not-found.component.ts diff --git a/src/app/pages/search/search.component.html b/src/app/pages/search/search.component.html index fd55ce73..bc377445 100644 --- a/src/app/pages/search/search.component.html +++ b/src/app/pages/search/search.component.html @@ -1,16 +1,16 @@

Collections

- +

Shows

- +

Episodes

- +

People

- + diff --git a/src/app/pages/search/search.component.ts b/src/app/pages/search/search.component.ts index 9f039bda..c6c081b6 100644 --- a/src/app/pages/search/search.component.ts +++ b/src/app/pages/search/search.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit, OnDestroy } from '@angular/core'; import { ActivatedRoute } from "@angular/router"; import { SearchResult } from "../../../models/search-result"; import { Title } from "@angular/platform-browser"; +import {Page} from "../../../models/page"; @Component({ selector: 'app-search', @@ -36,4 +37,9 @@ export class SearchComponent implements OnInit, OnDestroy searchBar.classList.remove("searching"); searchBar.value = ""; } + + AsPage(collection: T[]): Page + { + return new Page({this: "", items: collection, next: null, count: collection.length}); + } } diff --git a/src/app/services/resolvers/collection-resolver.service.ts b/src/app/services/resolvers/collection-resolver.service.ts deleted file mode 100644 index b4bb2c1b..00000000 --- a/src/app/services/resolvers/collection-resolver.service.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { MatSnackBar } from '@angular/material/snack-bar'; -import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; -import { EMPTY, Observable } from 'rxjs'; -import { catchError } from 'rxjs/operators' -import { Collection } from "../../../models/collection"; - -@Injectable({ - providedIn: 'root' -}) -export class CollectionResolverService implements Resolve -{ - constructor(private http: HttpClient, private snackBar: MatSnackBar) { } - - resolve(route: ActivatedRouteSnapshot): Collection | Observable | Promise - { - let collection: string = route.paramMap.get("collection-slug"); - return this.http.get("api/collection/" + collection).pipe(catchError((error: HttpErrorResponse) => - { - console.log(error.status + " - " + error.message); - if (error.status == 404) - { - this.snackBar.open("Collection \"" + collection + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 }); - } - else - { - this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 }); - } - return EMPTY; - })); - } -} diff --git a/src/app/services/resolvers/item-resolver.service.ts b/src/app/services/resolvers/item-resolver.service.ts index e815ef00..10f1f758 100644 --- a/src/app/services/resolvers/item-resolver.service.ts +++ b/src/app/services/resolvers/item-resolver.service.ts @@ -4,14 +4,13 @@ import {MatSnackBar} from '@angular/material/snack-bar'; import {ActivatedRouteSnapshot, Resolve} from '@angular/router'; import {Observable, EMPTY} from 'rxjs'; import {catchError} from 'rxjs/operators'; -import {IResource} from "../../../models/resources/resource"; @Injectable() export class ItemResolver { public static resolvers: any[] = []; - static forResource(resource: string) + static forResource(resource: string) { @Injectable() class Resolver implements Resolve @@ -28,12 +27,23 @@ export class ItemResolver .pipe( catchError((error: HttpErrorResponse) => { - console.log(error.status + " - " + error.message); - this.snackBar.open(`An unknown error occurred: ${error.message}.`, null, { - horizontalPosition: "left", - panelClass: ['snackError'], - duration: 2500 - }); + if (error.status == 404) + { + this.snackBar.open(`Item not found.`, null, { + horizontalPosition: "left", + panelClass: ['snackError'], + duration: 2500 + }); + } + else + { + console.log(error.status + " - " + error.message); + this.snackBar.open(`An unknown error occurred: ${error.message}.`, null, { + horizontalPosition: "left", + panelClass: ['snackError'], + duration: 2500 + }); + } return EMPTY; })); } diff --git a/src/app/services/resolvers/people-resolver.service.ts b/src/app/services/resolvers/people-resolver.service.ts deleted file mode 100644 index b43b3bd5..00000000 --- a/src/app/services/resolvers/people-resolver.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { MatSnackBar } from '@angular/material/snack-bar'; -import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; -import { EMPTY, Observable } from 'rxjs'; -import { catchError } from 'rxjs/operators'; -import { Collection } from "../../../models/collection"; -import { People } from "../../../models/people"; - -@Injectable({ - providedIn: 'root' -}) -export class PeopleResolverService implements Resolve -{ - constructor(private http: HttpClient, private snackBar: MatSnackBar) { } - - resolve(route: ActivatedRouteSnapshot): Collection | Observable | Promise - { - let people: string = route.paramMap.get("people-slug"); - return this.http.get("api/people/" + people).pipe(catchError((error: HttpErrorResponse) => - { - console.log(error.status + " - " + error.message); - if (error.status == 404) - { - this.snackBar.open("People \"" + people + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 }); - } - else - { - this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 }); - } - return EMPTY; - })); - } -} diff --git a/src/app/services/resolvers/show-resolver.service.ts b/src/app/services/resolvers/show-resolver.service.ts deleted file mode 100644 index c240cbb5..00000000 --- a/src/app/services/resolvers/show-resolver.service.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { MatSnackBar } from '@angular/material/snack-bar'; -import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; -import { EMPTY, Observable } from 'rxjs'; -import { catchError } from 'rxjs/operators'; -import { Show } from "../../../models/show"; - -@Injectable() -export class ShowResolverService implements Resolve -{ - constructor(private http: HttpClient, private snackBar: MatSnackBar) { } - - resolve(route: ActivatedRouteSnapshot): Show | Observable | Promise - { - let slug: string = route.paramMap.get("show-slug"); - return this.http.get("api/shows/" + slug).pipe(catchError((error: HttpErrorResponse) => - { - console.log(error.status + " - " + error.message); - if (error.status == 404) - this.snackBar.open("Show \"" + slug + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 }); - else - this.snackBar.open("An unknown error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 }); - return EMPTY; - })); - } -} diff --git a/src/models/page.ts b/src/models/page.ts index e10589c8..1a19b859 100644 --- a/src/models/page.ts +++ b/src/models/page.ts @@ -8,7 +8,10 @@ export class Page count: number items: T[] - constructor() {} + constructor(init?:Partial>) + { + Object.assign(this, init); + } loadNext(client: HttpClient) { diff --git a/src/models/search-result.ts b/src/models/search-result.ts index 6416fea5..cc903fcf 100644 --- a/src/models/search-result.ts +++ b/src/models/search-result.ts @@ -12,6 +12,6 @@ export interface SearchResult shows: Show[]; episodes: Episode[]; people: People[]; - genrwes: Genre[]; + genres: Genre[]; studios: Studio[]; }