Metadata Editing from the UI! (#1135)

* Added the skeleton code for layout, hooked up Age Rating, Publication Status, and Tags

* Tweaked message of Scan service to Finished scan of to better indicate the total scan time

* Hooked in foundation for person typeaheads

* Fixed people not populating typeaheads on load

* For manga/comics, when parsing, set the SeriesSort from ComicInfo if it exists.

* Implemented the ability to override and create new genre tags. Code is ready to flush out the rest.

* Ability to update metadata from the UI is hooked up. Next is locking.

* Updated typeahead to allow for non-multiple usage. Implemented ability to update Language tag in Series Metadata.

* Fixed a bug in GetContinuePoint for a case where we have Volumes, Loose Leaf chapters and no read progress.

* Added ETag headers on Images to allow for better caching (bookmarks and images in manga reader)

* Built out UI code to show locked indication to user

* Implemented Series locking and refactored a lot of styles in typeahead to make the lock setting work, plus misc cleanup.

* Added locked properties to dtos. Updated typeahead loading indicator to not interfere with close button if present

* Hooked up locking flags in UI

* Integrated regular field locking/unlocking

* Removed some old code

* Prevent input group from wrapping

* Implemented some basic layout for metadata on volume/chapter card modal. Refactored out all metadata from Chapter object in terms of UI and put into a separate call to ensure speedy delivery and simplicity of code.

* Refactored code to hide covers section if not an admin

* Implemented ability to modify a chapter/volume cover from the detail modal

* Removed a few variables and change cover image modal

* Added bookmark to single chapter view

* Put a temp fix in for a ngb v12 z-index bug (reported). Bumped ngb to 12.0 stable and fixed some small rendering bugs

* loading buttons ftw

* Lots of cleanup, looks like the story is finished

* Changed action name from Info to Details

* Style tweaks

* Fixed an issue where Summary would assume it's locked due to a subscription firing on setting the model

* Fixed some misc bugs

* Code smells

Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joseph Milazzo 2022-03-04 15:04:15 -06:00 committed by GitHub
parent 47a92a2e01
commit ba77954d5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 3605 additions and 723 deletions

View file

@ -1,118 +1,102 @@
<ng-container *ngIf="chapter !== undefined">
<div class="container-fluid">
<!-- <h4>{{libraryType !== LibraryType.Comic ? 'Chapter ' : 'Issue #'}} {{chapter.number}} <span title="Id">({{chapter.id}})</span></h4> -->
<!-- Arc Information -->
<ng-container>
<span *ngIf="chapter.writers.length === 0 && chapter.coverArtists.length === 0
&& chapter.pencillers.length === 0 && chapter.inkers.length === 0
&& chapter.colorists.length === 0 && chapter.letterers.length === 0
&& chapter.editors.length === 0 && chapter.publishers.length === 0
&& chapter.characters.length === 0 && chapter.translators.length === 0">
No metadata available
</span>
<div class="row g-0">
<div class="col">
Id: {{chapter.id}}
<div class="col-auto" *ngIf="chapter.writers && chapter.writers.length > 0">
<h6>Writers</h6>
<app-badge-expander [items]="chapter.writers">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge [person]="item"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
</div>
<div class="row g-0">
<div class="col">
Title: {{chapter.titleName || '-'}}
</div>
<div class="col">
Pages: {{chapter.pages}}
</div>
</div>
<div class="row g-0">
<div class="col" *ngIf="chapter.hasOwnProperty('created')">
Added: {{(chapter.created | date: 'short') || '-'}}
</div>
<div class="col">
Release Date: {{(chapter.releaseDate | date: 'shortDate') || '-'}}
</div>
</div>
</div>
<ul class="list-unstyled" >
<li class="d-flex my-4">
<a (click)="readChapter(chapter)" href="javascript:void(0);" title="Read {{libraryType !== LibraryType.Comic ? 'Chapter ' : 'Issue #'}} {{chapter.number}}">
<app-image class="me-3" width="74px" [imageUrl]="chapter.coverImage"></app-image>
</a>
<div class="flex-grow-1">
<h5 class="mt-0 mb-1">
<span *ngIf="chapter.number !== '0'; else specialHeader">
<!-- TODO: Add back in
<span>
<app-card-actionables (actionHandler)="performAction($event, chapter)" [actions]="chapterActions" [labelBy]="utilityService.formatChapterName(libraryType, true, true) + formatChapterNumber(chapter)"></app-card-actionables>&nbsp;
{{utilityService.formatChapterName(libraryType, true, false) }} {{formatChapterNumber(chapter)}}
</span> -->
<span class="badge bg-primary rounded-pill">
<span *ngIf="chapter.pagesRead > 0 && chapter.pagesRead < chapter.pages">{{chapter.pagesRead}} / {{chapter.pages}}</span>
<span *ngIf="chapter.pagesRead === 0">UNREAD</span>
<span *ngIf="chapter.pagesRead === chapter.pages">READ</span>
</span>
</span>
<ng-template #specialHeader>Files</ng-template>
</h5>
<ul class="list-group file-list">
<app-file-info *ngFor="let file of chapter.files" [file]="file" [created]="chapter.created"></app-file-info>
</ul>
<ng-container>
<div class="row g-0 mt-1" *ngIf="chapter.writers && chapter.writers.length > 0">
<div class="col-md-4">
<h5>Writers</h5>
</div>
<div class="col-md-8">
<app-person-badge *ngFor="let person of chapter.writers" [person]="person"></app-person-badge>
</div>
</div>
<div class="row g-0 mt-1" *ngIf="chapter.coverArtist && chapter.coverArtist.length > 0">
<div class="col-md-4">
<h5>Artists</h5>
</div>
<div class="col-md-8">
<app-person-badge *ngFor="let person of chapter.coverArtist" [person]="person"></app-person-badge>
</div>
</div>
<div class="row g-0 mt-1" *ngIf="chapter.publisher && chapter.publisher.length > 0">
<div class="col-md-4">
<h5>Publishers</h5>
</div>
<div class="col-md-8">
<app-person-badge *ngFor="let person of chapter.publisher" [person]="person"></app-person-badge>
</div>
</div>
</ng-container>
<div class="col-auto" *ngIf="chapter.coverArtists && chapter.coverArtists.length > 0">
<h6>Cover Artists</h6>
<app-badge-expander [items]="chapter.coverArtists">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge [person]="item"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
<div class="col-auto" *ngIf="chapter.pencillers && chapter.pencillers.length > 0">
<h6>Pencillers</h6>
<app-badge-expander [items]="chapter.pencillers">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge [person]="item"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
<div class="col-auto" *ngIf="chapter.inkers && chapter.inkers.length > 0">
<h6>Inkers</h6>
<app-badge-expander [items]="chapter.inkers">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge [person]="item"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
<div class="col-auto" *ngIf="chapter.colorists && chapter.colorists.length > 0">
<h6>Colorists</h6>
<app-badge-expander [items]="chapter.colorists">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge [person]="item"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
</li>
</ul>
</ng-container>
<!--
<div class="col-auto" *ngIf="chapter.letterers && chapter.letterers.length > 0">
<h6>Letterers</h6>
<app-badge-expander [items]="chapter.letterers">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge [person]="item"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
<div class="container-fluid" *ngIf="metadata !== undefined">
Chapter {{chapter.range}} {{metadata.title.length > 0 ? ' - ' + metadata.title : ''}}
Title: {{metadata.title || '-'}}
Year: {{metadata.year || '-'}}
Arc Information
<div class="col-auto" *ngIf="chapter.editors && chapter.editors.length > 0">
<h6>Editors</h6>
<app-badge-expander [items]="chapter.editors">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge [person]="item"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
<div class="row g-0">
<div class="col">
Id: {{chapter.id}}
</div>
<div class="col">
Pages: {{chapter.pages}}
</div>
</div>
<div class="col-auto" *ngIf="chapter.publishers && chapter.publishers.length > 0">
<h6>Publishers</h6>
<app-badge-expander [items]="chapter.publishers">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge [person]="item"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
<div class="row g-0">
<div class="col" *ngIf="chapter.hasOwnProperty('created')">
Added: {{(chapter.created | date: 'short') || '-'}}
<div class="col-auto" *ngIf="chapter.characters && chapter.characters.length > 0">
<h6>Characters</h6>
<app-badge-expander [items]="chapter.characters">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge [person]="item"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
<div class="col-auto" *ngIf="chapter.translators && chapter.translators.length > 0">
<h6>Translators</h6>
<app-badge-expander [items]="chapter.translators">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge [person]="item"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
</div>
<div class="col">
Pages: {{chapter.pages}}
</div>
</div>
</div> -->
</ng-container>
</ng-container>

View file

@ -5,6 +5,7 @@ import { ChapterMetadata } from 'src/app/_models/chapter-metadata';
import { UtilityService } from 'src/app/shared/_services/utility.service';
import { LibraryType } from 'src/app/_models/library';
import { ActionItem } from 'src/app/_services/action-factory.service';
import { PersonRole } from 'src/app/_models/person';
@Component({
selector: 'app-chapter-metadata-detail',
@ -13,9 +14,10 @@ import { ActionItem } from 'src/app/_services/action-factory.service';
})
export class ChapterMetadataDetailComponent implements OnInit {
@Input() chapter!: Chapter;
@Input() chapter!: ChapterMetadata;
@Input() libraryType: LibraryType = LibraryType.Manga;
//metadata!: ChapterMetadata;
roles: string[] = [];
get LibraryType(): typeof LibraryType {
return LibraryType;
@ -24,10 +26,14 @@ export class ChapterMetadataDetailComponent implements OnInit {
constructor(private metadataService: MetadataService, public utilityService: UtilityService) { }
ngOnInit(): void {
// this.metadataService.getChapterMetadata(this.chapter.id).subscribe(metadata => {
// console.log('Chapter ', this.chapter.number, ' metadata: ', metadata);
// this.metadata = metadata;
// })
this.roles = Object.keys(PersonRole).filter(role => /[0-9]/.test(role) === false);
}
getPeople(role: string) {
if (this.chapter) {
return (this.chapter as any)[role.toLowerCase()];
}
return [];
}
performAction(action: ActionItem<Chapter>, chapter: Chapter) {