mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-07 18:24:14 -04:00
Adding a metadata editor for shows
This commit is contained in:
parent
e0c9b1f4d8
commit
6801bb620c
@ -35,6 +35,9 @@ import {AuthModule} from "./auth/auth.module";
|
|||||||
import {AuthRoutingModule} from "./auth/auth-routing.module";
|
import {AuthRoutingModule} from "./auth/auth-routing.module";
|
||||||
import { TrailerDialogComponent } from './trailer-dialog/trailer-dialog.component';
|
import { TrailerDialogComponent } from './trailer-dialog/trailer-dialog.component';
|
||||||
import {CollectionsListComponent} from "./collection-list/collections-list.component";
|
import {CollectionsListComponent} from "./collection-list/collections-list.component";
|
||||||
|
import { MetadataEditComponent } from './metadata-edit/metadata-edit.component';
|
||||||
|
import {MatChipsModule} from "@angular/material/chips";
|
||||||
|
import {MatAutocompleteModule} from "@angular/material/autocomplete";
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -52,7 +55,8 @@ import {CollectionsListComponent} from "./collection-list/collections-list.compo
|
|||||||
PasswordValidator,
|
PasswordValidator,
|
||||||
FallbackDirective,
|
FallbackDirective,
|
||||||
TrailerDialogComponent,
|
TrailerDialogComponent,
|
||||||
CollectionsListComponent
|
CollectionsListComponent,
|
||||||
|
MetadataEditComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@ -77,7 +81,9 @@ import {CollectionsListComponent} from "./collection-list/collections-list.compo
|
|||||||
FormsModule,
|
FormsModule,
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
MatCheckboxModule,
|
MatCheckboxModule,
|
||||||
AuthModule
|
AuthModule,
|
||||||
|
MatChipsModule,
|
||||||
|
MatAutocompleteModule
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
68
src/app/metadata-edit/metadata-edit.component.html
Normal file
68
src/app/metadata-edit/metadata-edit.component.html
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<h2 mat-dialog-title>Editing metadata of {{this.show.title}}</h2>
|
||||||
|
<div matDialogContent>
|
||||||
|
<form #showForm="ngForm">
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<mat-label>Title</mat-label>
|
||||||
|
<input matInput [(ngModel)]="this.show.title" name="title">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<mat-label>Overview</mat-label>
|
||||||
|
<textarea matInput [(ngModel)]="this.show.overview" name="overview"></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field class="w-25 pr-3">
|
||||||
|
<mat-label>Start Year</mat-label>
|
||||||
|
<input matInput [(ngModel)]="this.show.startYear" name="startYear" type="number" [max]="this.show.endYear"/>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="w-25 pr-3">
|
||||||
|
<mat-label>End Year</mat-label>
|
||||||
|
<input matInput [(ngModel)]="this.show.endYear" name="endYear" type="number" [min]="this.show.startYear"/>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="w-50">
|
||||||
|
<mat-label>Status</mat-label>
|
||||||
|
<mat-select>
|
||||||
|
<mat-option value="Finished">Finished</mat-option>
|
||||||
|
<mat-option value="Airing">Airing</mat-option>
|
||||||
|
<mat-option value="Planned">Planned</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<mat-label>Genres</mat-label>
|
||||||
|
<mat-chip-list #genreList>
|
||||||
|
<mat-chip *ngFor="let genre of this.show.genres" (removed)="removeGenre(genre)" removable="true">
|
||||||
|
{{genre.name}}
|
||||||
|
<mat-icon matChipRemove>cancel</mat-icon>
|
||||||
|
</mat-chip>
|
||||||
|
<input #genreInput placeholder="New genre..." [matChipInputFor]="genreList" (matChipInputTokenEnd)="addGenre($event)"
|
||||||
|
[matAutocomplete]="genreAuto" />
|
||||||
|
<mat-autocomplete #genreAuto="matAutocomplete" (optionSelected)="autocompleteGenre($event)">
|
||||||
|
<mat-option *ngFor="let genre of this.allGenres" [value]="genre">
|
||||||
|
{{genre.name}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-autocomplete>
|
||||||
|
</mat-chip-list>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<mat-label>Trailer</mat-label>
|
||||||
|
<input matInput [(ngModel)]="this.show.trailerUrl" name="trailer">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<mat-label>Studio</mat-label>
|
||||||
|
<input matInput [value]="this.show.studio?.name" (input)="this.show.studio = {slug: null, name: $event.target.value}"
|
||||||
|
[matAutocomplete]="studioAuto" name="studio">
|
||||||
|
<mat-autocomplete #studioAuto="matAutocomplete">
|
||||||
|
<mat-option *ngFor="let studio of this.allStudios" [value]="studio.name">
|
||||||
|
{{studio.name}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-autocomplete>
|
||||||
|
</mat-form-field>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div mat-dialog-actions align="end">
|
||||||
|
<button mat-button mat-dialog-close>Cancel</button>
|
||||||
|
<button mat-button (click)="apply()">Apply</button>
|
||||||
|
</div>
|
0
src/app/metadata-edit/metadata-edit.component.scss
Normal file
0
src/app/metadata-edit/metadata-edit.component.scss
Normal file
71
src/app/metadata-edit/metadata-edit.component.ts
Normal file
71
src/app/metadata-edit/metadata-edit.component.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import {Component, ElementRef, Inject, OnInit, ViewChild} from '@angular/core';
|
||||||
|
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||||
|
import {HttpClient} from "@angular/common/http";
|
||||||
|
import {Show} from "../../models/show";
|
||||||
|
import {Genre} from "../../models/genre";
|
||||||
|
import {MatChipInputEvent} from "@angular/material/chips";
|
||||||
|
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
|
||||||
|
import {FormControl} from "@angular/forms";
|
||||||
|
import {Studio} from "../../models/studio";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-metadata-edit',
|
||||||
|
templateUrl: './metadata-edit.component.html',
|
||||||
|
styleUrls: ['./metadata-edit.component.scss']
|
||||||
|
})
|
||||||
|
export class MetadataEditComponent implements OnInit
|
||||||
|
{
|
||||||
|
@ViewChild("genreInput") genreInput: ElementRef<HTMLInputElement>;
|
||||||
|
|
||||||
|
private allGenres: Genre[];
|
||||||
|
private allStudios: Studio[];
|
||||||
|
|
||||||
|
constructor(public dialogRef: MatDialogRef<MetadataEditComponent>, @Inject(MAT_DIALOG_DATA) public show: Show, private http: HttpClient)
|
||||||
|
{
|
||||||
|
this.http.get<Genre[]>("/api/genres").subscribe(result =>
|
||||||
|
{
|
||||||
|
this.allGenres = result;
|
||||||
|
});
|
||||||
|
this.http.get<Studio[]>("/api/studios").subscribe(result =>
|
||||||
|
{
|
||||||
|
this.allStudios = result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(): void
|
||||||
|
{
|
||||||
|
this.http.post("/api/show/edit/" + this.show.slug, this.show).subscribe(() =>
|
||||||
|
{
|
||||||
|
this.dialogRef.close(this.show);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addGenre(event: MatChipInputEvent)
|
||||||
|
{
|
||||||
|
const input = event.input;
|
||||||
|
const value = event.value;
|
||||||
|
let genre: Genre = {slug: null, name: value};
|
||||||
|
|
||||||
|
this.show.genres.push(genre);
|
||||||
|
if (input)
|
||||||
|
input.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
removeGenre(genre: Genre): void
|
||||||
|
{
|
||||||
|
console.log("Removing a genre");
|
||||||
|
console.log(genre);
|
||||||
|
const i = this.show.genres.indexOf(genre);
|
||||||
|
this.show.genres.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
autocompleteGenre(event: MatAutocompleteSelectedEvent): void
|
||||||
|
{
|
||||||
|
this.show.genres.push(event.option.value);
|
||||||
|
this.genreInput.nativeElement.value = '';
|
||||||
|
}
|
||||||
|
}
|
@ -26,7 +26,7 @@
|
|||||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Watched">
|
<button mat-icon-button matTooltipPosition="above" matTooltip="Watched">
|
||||||
<mat-icon>done</mat-icon>
|
<mat-icon>done</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button mat-icon-button matTooltipPosition="above" matTooltip="More">
|
<button mat-icon-button matTooltipPosition="above" matTooltip="More" [matMenuTriggerFor]="showMenu">
|
||||||
<mat-icon>more_horiz</mat-icon>
|
<mat-icon>more_horiz</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -39,12 +39,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<mat-menu #showMenu="matMenu">
|
||||||
|
<button mat-menu-item (click)="editMetadata()">Edit metadata</button>
|
||||||
|
</mat-menu>
|
||||||
|
|
||||||
<div class="row pt-3 d-md-none">
|
<div class="row pt-3 d-md-none">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<p class="mr-1 d-inline-block">Studio: <b><a routerLink="/studio/{{this.show.studio?.slug}}">{{this.show.studio?.name}}</a></b></p>
|
<p class="mr-1 d-inline-block">Studio: <b><a routerLink="/studio/{{this.show.studio?.slug}}">{{this.show.studio?.name}}</a></b></p>
|
||||||
<div class="d-sm-none">
|
<div class="d-sm-none">
|
||||||
<p>Genres: <span *ngFor="let genre of this.show.genres; let isLast = last"><b><a routerLink="/genre/{{genre.slug}}">{{genre.name}}</a></b>{{isLast ? "" : ", "}}</span></p>
|
<p>Genres: <span *ngFor="let genre of this.show.genres; let isLast = last"><b><a routerLink="/genre/{{genre.slug}}">{{genre.name}}</a></b>{{isLast ? "" : ", "}}</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,6 +7,8 @@ import { Episode } from "../../models/episode";
|
|||||||
import { Show } from "../../models/show";
|
import { Show } from "../../models/show";
|
||||||
import {MatDialog} from "@angular/material/dialog";
|
import {MatDialog} from "@angular/material/dialog";
|
||||||
import {TrailerDialogComponent} from "../trailer-dialog/trailer-dialog.component";
|
import {TrailerDialogComponent} from "../trailer-dialog/trailer-dialog.component";
|
||||||
|
import {MetadataEditComponent} from "../metadata-edit/metadata-edit.component";
|
||||||
|
import {Account} from "../../models/account";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-show-details',
|
selector: 'app-show-details',
|
||||||
@ -92,6 +94,15 @@ export class ShowDetailsComponent implements OnInit
|
|||||||
|
|
||||||
openTrailer()
|
openTrailer()
|
||||||
{
|
{
|
||||||
this.dialog.open(TrailerDialogComponent, {width: "80%", height: "45vw", data: this.show.trailerUrl});
|
this.dialog.open(TrailerDialogComponent, {width: "80%", height: "45vw", data: this.show.trailerUrl, panelClass: "panel"});
|
||||||
|
}
|
||||||
|
|
||||||
|
editMetadata()
|
||||||
|
{
|
||||||
|
this.dialog.open(MetadataEditComponent, {width: "80%", data: this.show}).afterClosed().subscribe((result: Show) =>
|
||||||
|
{
|
||||||
|
if (result)
|
||||||
|
this.show = result;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
.panel .mat-dialog-container
|
||||||
|
{
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
@ -7,7 +7,7 @@ export interface Show
|
|||||||
{
|
{
|
||||||
slug: string;
|
slug: string;
|
||||||
title: string;
|
title: string;
|
||||||
Aliases: string[];
|
aliases: string[];
|
||||||
overview: string;
|
overview: string;
|
||||||
genres: Genre[];
|
genres: Genre[];
|
||||||
status: string;
|
status: string;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user