Cleaning up navigation height & edit page

This commit is contained in:
Zoe Roux 2020-10-31 22:57:16 +01:00
parent 3de2e74ecf
commit f764d8bbae
14 changed files with 153 additions and 84 deletions

View File

@ -38,7 +38,10 @@
"./node_modules/jquery/dist/jquery.min.js",
"./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
"./node_modules/hls.js/dist/hls.js"
]
],
"stylePreprocessorOptions": {
"includePaths": ["src"]
}
},
"configurations": {
"production": {

View File

@ -1,4 +1,4 @@
<header id="nav" style="height: 68px;">
<header id="nav">
<div class="fixed-top">
<nav id="toolbar" class="navbar navbar-dark bg-secondary">
<a class="navbar-brand nav-item ml-3" routerLink="/">
@ -7,7 +7,7 @@
<ul class="navbar-nav flex-row">
<li class="nav-item">
<a class="nav-link" routerLink="/browse" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">All</a>
<a class="nav-link" routerLink="/browse" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">All</a>
</li>
<li class="nav-item" *ngFor="let library of this.libraries">
<a class="nav-link" routerLink="/browse/{{library.slug}}" routerLinkActive="active">{{library.name}}</a>
@ -47,6 +47,6 @@
</div>
</header>
<main>
<main id="main">
<router-outlet></router-outlet>
</main>

View File

@ -1,6 +1,12 @@
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins/breakpoints";
@import "variables";
#toolbar
{
height: $nav-bar-height;
}
.navbar
{
@ -111,29 +117,27 @@ input::-webkit-search-cancel-button
main
{
max-height: calc(100vh - 68px) !important;
margin-top: $nav-bar-height;
padding-top: 4px;
max-height: calc(100vh - #{$nav-bar-height});
display: block;
overflow-y: auto;
scrollbar-color: #999 transparent;
position: relative;
&:last-child
&::-webkit-scrollbar
{
display: block;
overflow-y: auto;
width: 8px;
background: transparent;
}
scrollbar-color: #999 transparent;
&::-webkit-scrollbar-thumb
{
background-color: #999;
&::-webkit-scrollbar
&:host-context(.hoverEnabled) &:hover
{
width: 8px;
background: transparent;
}
&::-webkit-scrollbar-thumb
{
background-color: #999;
&:host-context(.hoverEnabled) &:hover
{
background-color: rgb(134, 127, 127);
}
background-color: rgb(134, 127, 127);
}
}
}

View File

@ -1,6 +1,6 @@
@import "../../../../node_modules/bootstrap/scss/functions";
@import "../../../../node_modules/bootstrap/scss/variables";
@import "../../../../node_modules/bootstrap/scss/mixins/breakpoints";
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins/breakpoints";
.root
{

View File

@ -1,6 +1,6 @@
@import "../../../../node_modules/bootstrap/scss/functions";
@import "../../../../node_modules/bootstrap/scss/variables";
@import "../../../../node_modules/bootstrap/scss/mixins/breakpoints";
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins/breakpoints";
button
{

View File

@ -1,6 +1,6 @@
@import "../../../../node_modules/bootstrap/scss/functions";
@import "../../../../node_modules/bootstrap/scss/variables";
@import "../../../../node_modules/bootstrap/scss/mixins/breakpoints";
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins/breakpoints";
.container
{

View File

@ -1,6 +1,6 @@
@import "../../../../node_modules/bootstrap/scss/functions";
@import "../../../../node_modules/bootstrap/scss/variables";
@import "../../../../node_modules/bootstrap/scss/mixins/breakpoints";
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins/breakpoints";
.people-container
{

View File

@ -53,10 +53,14 @@
{{genre.name}}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input #genreInput placeholder="New genre..." [matChipInputFor]="genreList" (matChipInputTokenEnd)="addGenre($event)"
<input #genreInput placeholder="New genre..."
[formControl]="genreForm"
[matChipInputFor]="genreList"
(matChipInputTokenEnd)="addGenre($event); $event.input.value = null;"
[matAutocomplete]="genreAuto" />
<mat-autocomplete #genreAuto="matAutocomplete" (optionSelected)="autocompleteGenre($event)">
<mat-option *ngFor="let genre of this.allGenres" [value]="genre">
<mat-autocomplete #genreAuto="matAutocomplete"
(optionSelected)="autocompleteGenre($event); genreInput.value = null;">
<mat-option *ngFor="let genre of this.filteredGenres | async" [value]="genre">
{{genre.name}}
</mat-option>
</mat-autocomplete>
@ -73,8 +77,8 @@
<input matInput [value]="this.show.studio?.name"
(input)="this.show.studio = {id: 0, slug: null, name: $event.target.value};"
[matAutocomplete]="studioAuto" name="studio">
<mat-autocomplete #studioAuto="matAutocomplete" (optionSelected)="this.show.studio = $event.option.value">
<mat-option *ngFor="let studio of this.allStudios" [value]="studio">
<mat-autocomplete #studioAuto="matAutocomplete" (optionSelected)="this.show.studio = $event.option.value">
<mat-option *ngFor="let studio of this.filteredStudios | async" [value]="studio">
{{studio.name}}
</mat-option>
</mat-autocomplete>

View File

@ -1,6 +1,6 @@
@import "../../../../node_modules/bootstrap/scss/functions";
@import "../../../../node_modules/bootstrap/scss/variables";
@import "../../../../node_modules/bootstrap/scss/mixins/breakpoints";
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins/breakpoints";
.provider
{
@ -15,4 +15,4 @@
{
width: 25%;
}
}
}

View File

@ -1,53 +1,84 @@
import {Component, ElementRef, Inject, ViewChild} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {HttpClient} from "@angular/common/http";
import {Show} from "../../models/resources/show";
import {Genre} from "../../models/resources/genre";
import {MatChipInputEvent} from "@angular/material/chips";
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
import {Observable, of} from "rxjs";
import {tap} from "rxjs/operators";
import {Studio} from "../../models/resources/studio";
import {Provider} from "../../models/provider";
import {MatSnackBar} from "@angular/material/snack-bar";
import {ShowGridComponent} from "../../components/show-grid/show-grid.component";
import { Component, Inject, OnInit, ViewChild } from "@angular/core";
import { FormControl } from "@angular/forms";
import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
import { HttpClient } from "@angular/common/http";
import { Page } from "../../models/page";
import { Show } from "../../models/resources/show";
import { Genre } from "../../models/resources/genre";
import { MatChipInputEvent } from "@angular/material/chips";
import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete";
import { Observable, of} from "rxjs";
import { catchError, filter, map, mergeAll, tap } from "rxjs/operators";
import { Studio } from "../../models/resources/studio";
import { Provider } from "../../models/provider";
import { MatSnackBar } from "@angular/material/snack-bar";
import { ShowGridComponent } from "../../components/show-grid/show-grid.component";
import { GenreService, StudioService } from "../../services/api.service";
@Component({
selector: 'app-metadata-edit',
templateUrl: './metadata-edit.component.html',
styleUrls: ['./metadata-edit.component.scss']
})
export class MetadataEditComponent
export class MetadataEditComponent implements OnInit
{
@ViewChild("genreInput") private genreInput: ElementRef<HTMLInputElement>;
public allGenres: Genre[];
public allStudios: Studio[];
studioForm: FormControl = new FormControl();
filteredStudios: Observable<Studio[]>;
genreForm: FormControl = new FormControl();
filteredGenres: Observable<Genre[]>;
@ViewChild("identifyGrid") private identifyGrid: ShowGridComponent;
private identifying: Observable<Show[]>;
private identifiedShows: [string, Show[]];
public providers: Provider[];
public providers: Provider[] = [];
public metadataChanged: boolean = false;
constructor(public dialogRef: MatDialogRef<MetadataEditComponent>, @Inject(MAT_DIALOG_DATA) public show: Show, private http: HttpClient, private snackBar: MatSnackBar)
constructor(public dialogRef: MatDialogRef<MetadataEditComponent>,
@Inject(MAT_DIALOG_DATA) public show: Show,
private http: HttpClient,
private studioApi: StudioService,
private genreApi: GenreService,
private snackBar: MatSnackBar)
{
this.http.get<Genre[]>("/api/genres").subscribe(result =>
this.http.get<Page<Provider>>("/api/providers").subscribe(result =>
{
this.allGenres = result;
});
this.http.get<Studio[]>("/api/studios").subscribe(result =>
{
this.allStudios = result;
});
this.http.get<Provider[]>("/api/providers").subscribe(result =>
{
this.providers = result;
this.providers = result.items;
});
this.reIdentify(this.show.title);
}
ngOnInit()
{
this.filteredGenres = this.genreForm.valueChanges
.pipe(
filter(x => x),
map(x => typeof x === "string" ? x : x.name),
map(x => this.genreApi.search(x)),
mergeAll(),
catchError(x =>
{
console.log(x);
return [];
})
);
this.filteredStudios = this.studioForm.valueChanges
.pipe(
filter(x => x),
map(x => typeof x === "string" ? x : x.name),
map(x => this.studioApi.search(x)),
mergeAll(),
catchError(x =>
{
console.log(x);
return [];
})
);
}
apply(): void
{
if (this.metadataChanged)
@ -59,7 +90,7 @@ export class MetadataEditComponent
},
() =>
{
this.snackBar.open("An unknown error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
this.snackBar.open("An unknown error occurred.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
}
);
this.dialogRef.close(this.show);
@ -106,10 +137,9 @@ export class MetadataEditComponent
this.show.genres.splice(i, 1);
}
autocompleteGenre(event: MatAutocompleteSelectedEvent): void
autocompleteGenre(event: MatAutocompleteSelectedEvent): void
{
this.show.genres.push(event.option.value);
this.genreInput.nativeElement.value = '';
}
identityShow(name: string): Observable<Show[]>

View File

@ -1,6 +1,7 @@
@import "../../../../node_modules/bootstrap/scss/functions";
@import "../../../../node_modules/bootstrap/scss/variables";
@import "../../../../node_modules/bootstrap/scss/mixins/breakpoints";
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins/breakpoints";
@import "variables";
a
{

View File

@ -1,4 +1,4 @@
import { Component, HostListener, OnInit } from "@angular/core";
import { AfterViewInit, Component, HostListener, OnInit } from "@angular/core";
import { MatSnackBar } from "@angular/material/snack-bar";
import { DomSanitizer, Title } from "@angular/platform-browser";
import {ActivatedRoute, Router} from '@angular/router';
@ -17,7 +17,7 @@ import {People} from "../../models/resources/people";
templateUrl: './show-details.component.html',
styleUrls: ['./show-details.component.scss']
})
export class ShowDetailsComponent implements OnInit
export class ShowDetailsComponent implements AfterViewInit
{
show: Show;
seasons: Season[];
@ -25,6 +25,7 @@ export class ShowDetailsComponent implements OnInit
episodes: Page<Episode>[] = [];
people: Page<People>;
private scrollZone: HTMLElement;
private toolbar: HTMLElement;
private backdrop: HTMLElement;
@ -65,23 +66,30 @@ export class ShowDetailsComponent implements OnInit
this.getEpisodes(this.season);});
}
ngOnInit()
ngAfterViewInit()
{
this.scrollZone = document.getElementById("main");
this.toolbar = document.getElementById("toolbar");
this.backdrop = document.getElementById("backdrop");
this.toolbar.setAttribute("style", `background-color: rgba(0, 0, 0, 0) !important`);
this.scrollZone.style.marginTop = "0";
this.scrollZone.style.maxHeight = "100vh";
this.scrollZone.addEventListener("scroll", () => this.scroll());
}
ngOnDestroy()
{
this.title.setTitle("Kyoo");
this.toolbar.setAttribute("style", `background-color: #000000 !important`);
this.scrollZone.style.marginTop = null;
this.scrollZone.style.maxHeight = null;
this.scrollZone.removeEventListener("scroll", () => this.scroll());
}
@HostListener("window:scroll")
scroll()
{
let opacity: number = 2 * window.scrollY / this.backdrop.clientHeight;
console.log("scroll");
let opacity: number = 2 * this.scrollZone.scrollTop / this.backdrop.clientHeight;
this.toolbar.setAttribute("style", `background-color: rgba(0, 0, 0, ${opacity}) !important`);
};

View File

@ -2,6 +2,7 @@ import {Injectable} from "@angular/core";
import {HttpClient} from "@angular/common/http";
import {Observable} from "rxjs"
import {Page} from "../models/page";
import { Genre } from "../models/resources/genre";
import {IResource} from "../models/resources/resource";
import {Library} from "../models/resources/library";
import {LibraryItem} from "../models/resources/library-item";
@ -144,6 +145,23 @@ export class PeopleService extends CrudApi<People>
}
}
@Injectable({
providedIn: 'root'
})
export class GenreService extends CrudApi<Genre>
{
constructor(client: HttpClient)
{
super(client, "genres");
}
getFromShow(show: string | number, args?: ApiArgs): Observable<Page<Genre>>
{
return this.client.get<Page<Genre>>(`/api/shows/${show}/genres${this.ArgsAsQuery(args)}`)
.pipe(map(x => Object.assign(new Page<Genre>(), x)));
}
}
@Injectable({
providedIn: 'root'
})

1
src/variables.scss Normal file
View File

@ -0,0 +1 @@
$nav-bar-height: 64px;