Feature/local metadata more tags (#832)
* Stashing code * removed some debug code on series detail page. Now detail is collapsed by default. * Added AgeRating * Fixed a crash when NetVips tries to write a cover file and cover directory is not existing. * When a card is selected for bulk actions, show an outline in addition to select box * Added AgeRating into the metadata parsing. Added a hack where ComicInfo uses Number in ComicInfo rather than Volume. This is to test out the effects on users libraries. * Added AgeRating and ReleaseDate to the metadata implelentation.
This commit is contained in:
parent
46f37069db
commit
af24c928d7
31 changed files with 2825 additions and 101 deletions
|
|
@ -19,7 +19,10 @@ export interface Chapter {
|
|||
created: string;
|
||||
|
||||
titleName: string;
|
||||
year: string;
|
||||
/**
|
||||
* This is only Year and Month, Day is not supported from underlying sources
|
||||
*/
|
||||
releaseDate: string;
|
||||
writers: Array<Person>;
|
||||
penciller: Array<Person>;
|
||||
inker: Array<Person>;
|
||||
|
|
|
|||
15
UI/Web/src/app/_models/metadata/age-rating.ts
Normal file
15
UI/Web/src/app/_models/metadata/age-rating.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
export enum AgeRating {
|
||||
Unknown = 0,
|
||||
AdultsOnly = 1,
|
||||
EarlyChildhood = 2,
|
||||
Everyone = 3,
|
||||
Everyone10Plus = 4,
|
||||
G = 5,
|
||||
KidsToAdults = 6,
|
||||
Mature = 7,
|
||||
Mature15Plus = 8,
|
||||
Mature17Plus = 9,
|
||||
RatingPending = 10,
|
||||
Teen = 11,
|
||||
X18Plus = 12
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import { CollectionTag } from "./collection-tag";
|
||||
import { Genre } from "./genre";
|
||||
import { AgeRating } from "./metadata/age-rating";
|
||||
import { Person } from "./person";
|
||||
|
||||
export interface SeriesMetadata {
|
||||
|
|
@ -16,6 +17,7 @@ export interface SeriesMetadata {
|
|||
colorists: Array<Person>;
|
||||
letterers: Array<Person>;
|
||||
editors: Array<Person>;
|
||||
|
||||
ageRating: AgeRating;
|
||||
releaseYear: number;
|
||||
seriesId: number;
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { ChapterMetadata } from '../_models/chapter-metadata';
|
||||
import { AgeRating } from '../_models/metadata/age-rating';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
|
@ -10,9 +13,25 @@ export class MetadataService {
|
|||
|
||||
baseUrl = environment.apiUrl;
|
||||
|
||||
private ageRatingTypes: {[key: number]: string} | undefined = undefined;
|
||||
|
||||
constructor(private httpClient: HttpClient) { }
|
||||
|
||||
getChapterMetadata(chapterId: number) {
|
||||
return this.httpClient.get<ChapterMetadata>(this.baseUrl + 'series/chapter-metadata?chapterId=' + chapterId);
|
||||
// getChapterMetadata(chapterId: number) {
|
||||
// return this.httpClient.get<ChapterMetadata>(this.baseUrl + 'series/chapter-metadata?chapterId=' + chapterId);
|
||||
// }
|
||||
|
||||
getAgeRating(ageRating: AgeRating) {
|
||||
if (this.ageRatingTypes != undefined && this.ageRatingTypes.hasOwnProperty(ageRating)) {
|
||||
return of(this.ageRatingTypes[ageRating]);
|
||||
}
|
||||
return this.httpClient.get<string>(this.baseUrl + 'series/age-rating?ageRating=' + ageRating, {responseType: 'text' as 'json'}).pipe(map(l => {
|
||||
if (this.ageRatingTypes === undefined) {
|
||||
this.ageRatingTypes = {};
|
||||
}
|
||||
|
||||
this.ageRatingTypes[ageRating] = l;
|
||||
return this.ageRatingTypes[ageRating];
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="card">
|
||||
<div class="card {{selected ? 'selected-highlight' : ''}}">
|
||||
<div class="overlay" (click)="handleClick($event)">
|
||||
<img *ngIf="total > 0 || supressArchiveWarning" class="img-top lazyload" [src]="imageService.placeholderImage" [attr.data-src]="imageUrl"
|
||||
(error)="imageService.updateErroredImage($event)" aria-hidden="true" height="230px" width="158px">
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ $image-width: 160px;
|
|||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.selected-highlight {
|
||||
outline: 2px solid colors.$primary-color;
|
||||
}
|
||||
|
||||
|
||||
.img-top {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<ng-container *ngIf="chapter !== undefined">
|
||||
<div class="container-fluid">
|
||||
<h4>{{chapter.range}}</h4>
|
||||
Title: {{chapter.titleName || '-'}}
|
||||
<!-- Year: {{metadata.year || '-'}} -->
|
||||
Arc Information
|
||||
<!-- <h4>{{libraryType !== LibraryType.Comic ? 'Chapter ' : 'Issue #'}} {{chapter.number}} <span title="Id">({{chapter.id}})</span></h4> -->
|
||||
|
||||
|
||||
<!-- Arc Information -->
|
||||
|
||||
|
||||
<div class="row no-gutters">
|
||||
<div class="col">
|
||||
Id: {{chapter.id}}
|
||||
Title: {{chapter.titleName || '-'}}
|
||||
</div>
|
||||
<div class="col">
|
||||
Pages: {{chapter.pages}}
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
Added: {{(chapter.created | date: 'short') || '-'}}
|
||||
</div>
|
||||
<div class="col">
|
||||
Pages: {{chapter.pages}}
|
||||
Release Date: {{(chapter.releaseDate | date: 'shortDate') || '-'}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -33,7 +33,8 @@
|
|||
<div class="media-body">
|
||||
<h5 class="mt-0 mb-1">
|
||||
<span *ngIf="chapter.number !== '0'; else specialHeader">
|
||||
<!-- <span>
|
||||
<!-- 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>
|
||||
{{utilityService.formatChapterName(libraryType, true, false) }} {{formatChapterNumber(chapter)}}
|
||||
</span> -->
|
||||
|
|
|
|||
|
|
@ -55,16 +55,16 @@
|
|||
<app-read-more [text]="seriesSummary" [maxLength]="250"></app-read-more>
|
||||
</div>
|
||||
<div *ngIf="seriesMetadata" class="mt-2">
|
||||
<app-series-metadata-detail [seriesMetadata]="seriesMetadata"></app-series-metadata-detail>
|
||||
<app-series-metadata-detail [seriesMetadata]="seriesMetadata" [series]="series"></app-series-metadata-detail>
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="series.format != MangaFormat.UNKNOWN">
|
||||
<!-- <div class="row no-gutters mt-1" *ngIf="series.format != MangaFormat.UNKNOWN">
|
||||
<div class="col-md-4">
|
||||
<h5>Type</h5>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<app-tag-badge [selectionMode]="TagBadgeCursor.NotAllowed"><app-series-format [format]="series.format">{{utilityService.mangaFormat(series.format)}}</app-series-format></app-tag-badge>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,16 @@
|
|||
<!-- This first row will have random information about the series-->
|
||||
<div class="row no-gutters" *ngIf="seriesMetadata.ageRating">
|
||||
<app-tag-badge title="Age Rating">{{ageRatingName}}</app-tag-badge>
|
||||
<ng-container *ngIf="series">
|
||||
<!-- Maybe we can put the library this resides in to make it easier to get back -->
|
||||
<!-- tooltip here explaining how this is year of first issue -->
|
||||
<app-tag-badge *ngIf="seriesMetadata.releaseYear > 0" title="Release date">{{seriesMetadata.releaseYear}}</app-tag-badge>
|
||||
<app-tag-badge [selectionMode]="TagBadgeCursor.NotAllowed">
|
||||
<app-series-format [format]="series.format">{{utilityService.mangaFormat(series.format)}}</app-series-format>
|
||||
</app-tag-badge>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters" *ngIf="seriesMetadata.genres && seriesMetadata.genres.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Genres</h5>
|
||||
|
|
@ -31,7 +44,6 @@
|
|||
</div>
|
||||
|
||||
<div #collapse="ngbCollapse" [(ngbCollapse)]="isCollapsed" id="extended-series-metadata">
|
||||
Stuff
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.artists && seriesMetadata.artists.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Artists</h5>
|
||||
|
|
@ -41,15 +53,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.publishers && seriesMetadata.publishers.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Publishers</h5>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<app-person-badge *ngFor="let person of seriesMetadata.publishers" [person]="person"></app-person-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.characters && seriesMetadata.characters.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Characters</h5>
|
||||
|
|
@ -58,25 +61,7 @@
|
|||
<app-person-badge *ngFor="let person of seriesMetadata.characters" [person]="person"></app-person-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.pencillers && seriesMetadata.pencillers.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Pencillers</h5>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<app-person-badge *ngFor="let person of seriesMetadata.pencillers" [person]="person"></app-person-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.inkers && seriesMetadata.inkers.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Inkers</h5>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<app-person-badge *ngFor="let person of seriesMetadata.inkers" [person]="person"></app-person-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.colorists && seriesMetadata.colorists.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Colorists</h5>
|
||||
|
|
@ -85,7 +70,25 @@
|
|||
<app-person-badge *ngFor="let person of seriesMetadata.colorists" [person]="person"></app-person-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.editors && seriesMetadata.editors.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Editors</h5>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<app-person-badge *ngFor="let person of seriesMetadata.editors" [person]="person"></app-person-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.inkers && seriesMetadata.inkers.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Inkers</h5>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<app-person-badge *ngFor="let person of seriesMetadata.inkers" [person]="person"></app-person-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.letterers && seriesMetadata.letterers.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Letterers</h5>
|
||||
|
|
@ -95,12 +98,21 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.editors && seriesMetadata.editors.length > 0">
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.pencillers && seriesMetadata.pencillers.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Editors</h5>
|
||||
<h5>Pencillers</h5>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<app-person-badge *ngFor="let person of seriesMetadata.editors" [person]="person"></app-person-badge>
|
||||
<app-person-badge *ngFor="let person of seriesMetadata.pencillers" [person]="person"></app-person-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters mt-1" *ngIf="seriesMetadata.publishers && seriesMetadata.publishers.length > 0">
|
||||
<div class="col-md-4">
|
||||
<h5>Publishers</h5>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<app-person-badge *ngFor="let person of seriesMetadata.publishers" [person]="person"></app-person-badge>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -2,7 +2,9 @@ import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/cor
|
|||
import { TagBadgeCursor } from '../shared/tag-badge/tag-badge.component';
|
||||
import { UtilityService } from '../shared/_services/utility.service';
|
||||
import { MangaFormat } from '../_models/manga-format';
|
||||
import { Series } from '../_models/series';
|
||||
import { SeriesMetadata } from '../_models/series-metadata';
|
||||
import { MetadataService } from '../_services/metadata.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-series-metadata-detail',
|
||||
|
|
@ -12,10 +14,16 @@ import { SeriesMetadata } from '../_models/series-metadata';
|
|||
export class SeriesMetadataDetailComponent implements OnInit, OnChanges {
|
||||
|
||||
@Input() seriesMetadata!: SeriesMetadata;
|
||||
@Input() series!: Series;
|
||||
|
||||
isCollapsed: boolean = false;
|
||||
isCollapsed: boolean = true;
|
||||
hasExtendedProperites: boolean = false;
|
||||
|
||||
/**
|
||||
* String representation of AgeRating enum
|
||||
*/
|
||||
ageRatingName: string = '';
|
||||
|
||||
get MangaFormat(): typeof MangaFormat {
|
||||
return MangaFormat;
|
||||
}
|
||||
|
|
@ -24,7 +32,7 @@ export class SeriesMetadataDetailComponent implements OnInit, OnChanges {
|
|||
return TagBadgeCursor;
|
||||
}
|
||||
|
||||
constructor(public utilityService: UtilityService) { }
|
||||
constructor(public utilityService: UtilityService, private metadataService: MetadataService) { }
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
this.hasExtendedProperites = this.seriesMetadata.colorists.length > 0 ||
|
||||
|
|
@ -34,6 +42,10 @@ export class SeriesMetadataDetailComponent implements OnInit, OnChanges {
|
|||
this.seriesMetadata.letterers.length > 0 ||
|
||||
this.seriesMetadata.pencillers.length > 0 ||
|
||||
this.seriesMetadata.publishers.length > 0;
|
||||
|
||||
this.metadataService.getAgeRating(this.seriesMetadata.ageRating).subscribe(rating => {
|
||||
this.ageRatingName = rating;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
|
@ -43,4 +55,5 @@ export class SeriesMetadataDetailComponent implements OnInit, OnChanges {
|
|||
this.isCollapsed = !this.isCollapsed;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
|
|||
import { Chapter } from 'src/app/_models/chapter';
|
||||
import { LibraryType } from 'src/app/_models/library';
|
||||
import { MangaFormat } from 'src/app/_models/manga-format';
|
||||
import { AgeRating } from 'src/app/_models/metadata/age-rating';
|
||||
import { Series } from 'src/app/_models/series';
|
||||
import { Volume } from 'src/app/_models/volume';
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue