UX Overhaul Part 2 (#3112)

Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo 2024-08-16 19:37:12 -05:00 committed by GitHub
parent 0247bc5012
commit 3d8aa2ad24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
192 changed files with 14808 additions and 1874 deletions

View file

@ -112,7 +112,7 @@
<div class="row g-0 mb-2">
<div class="col-md-6">
<div>{{t('last-sync-title')}}</div>
<div>{{tag.lastSyncUtc | date:'shortDate' | defaultDate}}</div>
<div>{{tag.lastSyncUtc | utcToLocalTime | date:'shortDate' | defaultDate}}</div>
</div>
<div class="col-md-6">
<div>{{t('source-url-title')}}</div>

View file

@ -37,6 +37,7 @@ import {MangaFormatPipe} from "../../../_pipes/manga-format.pipe";
import {SentenceCasePipe} from "../../../_pipes/sentence-case.pipe";
import {TagBadgeComponent} from "../../../shared/tag-badge/tag-badge.component";
import {SelectionModel} from "../../../typeahead/_models/selection-model";
import {UtcToLocalTimePipe} from "../../../_pipes/utc-to-local-time.pipe";
enum TabID {
@ -50,7 +51,7 @@ enum TabID {
selector: 'app-edit-collection-tags',
standalone: true,
imports: [NgbNav, NgbNavItem, NgbNavLink, NgbNavContent, ReactiveFormsModule, FormsModule, NgbPagination,
CoverImageChooserComponent, NgbNavOutlet, NgbTooltip, TranslocoDirective, NgTemplateOutlet, FilterPipe, DatePipe, DefaultDatePipe, ReadMoreComponent, SafeHtmlPipe, SafeUrlPipe, MangaFormatPipe, NgIf, SentenceCasePipe, TagBadgeComponent, DecimalPipe],
CoverImageChooserComponent, NgbNavOutlet, NgbTooltip, TranslocoDirective, NgTemplateOutlet, FilterPipe, DatePipe, DefaultDatePipe, ReadMoreComponent, SafeHtmlPipe, SafeUrlPipe, MangaFormatPipe, NgIf, SentenceCasePipe, TagBadgeComponent, DecimalPipe, UtcToLocalTimePipe],
templateUrl: './edit-collection-tags.component.html',
styleUrls: ['./edit-collection-tags.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush

View file

@ -1,8 +1,8 @@
<ng-container *transloco="let t; read: 'edit-series-modal'">
<div class="modal-container" *ngIf="series !== undefined">
<div class="modal-header">
<h4 class="modal-title">
{{t('title', {seriesName: this.series.name})}}</h4>
<h5 class="modal-title">
{{t('title', {seriesName: this.series.name})}}</h5>
<button type="button" class="btn-close" [attr.aria-label]="t('close')" (click)="close()"></button>
</div>
<div class="modal-body scrollable-modal {{utilityService.getActiveBreakpoint() === Breakpoint.Mobile ? '' : 'd-flex'}}">
@ -14,53 +14,73 @@
<ng-template ngbNavContent>
<div class="row g-0">
<div class="mb-3" style="width: 100%">
<label for="name" class="form-label">{{t('name-label')}}</label>
<div class="input-group">
<input id="name" class="form-control" formControlName="name" type="text" readonly
[class.is-invalid]="editSeriesForm.get('name')?.invalid && editSeriesForm.get('name')?.touched">
<ng-container *ngIf="editSeriesForm.get('name')?.errors as errors">
<div class="invalid-feedback" *ngIf="errors.required">
{{t('required-field')}}
<app-setting-item [title]="t('name-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<div class="input-group">
@if (editSeriesForm.get('name'); as formControl) {
<input id="name" class="form-control" formControlName="name" type="text" readonly
[class.is-invalid]="formControl.invalid && formControl.touched">
@if (formControl.errors) {
@if (formControl.errors.required) {
<div class="invalid-feedback">{{t('required-field')}}</div>
}
}
}
</div>
</ng-container>
</div>
</ng-template>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3" style="width: 100%">
<label for="sort-name" class="form-label">{{t('sort-name-label')}}</label>
<div class="input-group {{series.sortNameLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: series, field: 'sortNameLocked' }"></ng-container>
<input id="sort-name" class="form-control" formControlName="sortName" type="text" [class.is-invalid]="editSeriesForm.get('sortName')?.invalid && editSeriesForm.get('sortName')?.touched">
<ng-container *ngIf="editSeriesForm.get('sortName')?.errors as errors">
<div class="invalid-feedback" *ngIf="errors.required">
{{t('required-field')}}
</div>
</ng-container>
</div>
@if (editSeriesForm.get('sortName'); as formControl) {
<app-setting-item [title]="t('sort-name-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<div class="input-group {{series.sortNameLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: series, field: 'sortNameLocked' }"></ng-container>
<input id="sort-name" class="form-control" formControlName="sortName" type="text" [class.is-invalid]="formControl.invalid && formControl.touched">
@if (formControl.errors) {
@if (formControl.errors.required) {
<div class="invalid-feedback">{{t('required-field')}}</div>
}
}
</div>
</ng-template>
</app-setting-item>
}
</div>
</div>
<div class="row g-0">
<div class="mb-3" style="width: 100%">
<label for="localized-name" class="form-label">{{t('localized-name-label')}}</label>
<div class="input-group {{series.localizedNameLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: series, field: 'localizedNameLocked' }"></ng-container>
<input id="localized-name" class="form-control" formControlName="localizedName" type="text">
</div>
<app-setting-item [title]="t('localized-name-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
@if (editSeriesForm.get('localizedName'); as formControl) {
<div class="input-group {{series.localizedNameLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: series, field: 'localizedNameLocked' }"></ng-container>
<input id="localized-name" class="form-control" formControlName="localizedName" type="text">
</div>
}
</ng-template>
</app-setting-item>
</div>
</div>
<div class="row g-0" *ngIf="metadata">
<div class="mb-3" style="width: 100%">
<label for="summary" class="form-label">{{t('summary-label')}}</label>
<div class="input-group {{metadata.summaryLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'summaryLocked' }"></ng-container>
<textarea id="summary" class="form-control" formControlName="summary" rows="4"></textarea>
@if (metadata) {
<div class="row g-0">
<div class="mb-3" style="width: 100%">
<app-setting-item [title]="t('summary-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<div class="input-group {{metadata.summaryLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'summaryLocked' }"></ng-container>
<textarea id="summary" class="form-control" formControlName="summary" rows="4"></textarea>
</div>
</ng-template>
</app-setting-item>
</div>
</div>
</div>
}
</ng-template>
</li>
@ -72,33 +92,39 @@
<div class="row g-0">
<div class="col-lg-8 col-md-12 pe-2">
<div class="mb-3">
<label for="language" class="form-label">{{t('language-label')}}</label>
<app-typeahead (selectedData)="updateLanguage($event);metadata.languageLocked = true;" [settings]="languageSettings"
[(locked)]="metadata.languageLocked" (onUnlock)="metadata.languageLocked = false"
(newItemAdded)="metadata.languageLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.title}}
<app-setting-item [title]="t('language-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updateLanguage($event);metadata.languageLocked = true;" [settings]="languageSettings"
[(locked)]="metadata.languageLocked" (onUnlock)="metadata.languageLocked = false"
(newItemAdded)="metadata.languageLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.title}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.title}} ({{item.isoCode}})
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.title}} ({{item.isoCode}})
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="col-lg-4 col-md-12">
<div class="mb-3" style="width: 100%">
<label for="release-year" class="form-label">{{t('release-year-label')}}</label>
<div class="input-group {{metadata.releaseYearLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'releaseYearLocked' }"></ng-container>
<input type="number" inputmode="numeric" class="form-control" id="release-year" formControlName="releaseYear"
maxlength="4" minlength="4"
[class.is-invalid]="editSeriesForm.get('releaseYear')?.invalid && editSeriesForm.get('releaseYear')?.touched">
<ng-container *ngIf="editSeriesForm.get('releaseYear')?.errors as errors">
<p class="invalid-feedback" *ngIf="errors.pattern">
This must be a valid year greater than 1000 and 4 characters long
</p>
</ng-container>
</div>
<app-setting-item [title]="t('release-year-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<div class="input-group {{metadata.releaseYearLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'releaseYearLocked' }"></ng-container>
<input type="number" inputmode="numeric" class="form-control" id="release-year" formControlName="releaseYear"
maxlength="4" minlength="4"
[class.is-invalid]="editSeriesForm.get('releaseYear')?.invalid && editSeriesForm.get('releaseYear')?.touched">
<ng-container *ngIf="editSeriesForm.get('releaseYear')?.errors as errors">
<p class="invalid-feedback" *ngIf="errors.pattern">
This must be a valid year greater than 1000 and 4 characters long
</p>
</ng-container>
</div>
</ng-template>
</app-setting-item>
</div>
</div>
</div>
@ -106,17 +132,20 @@
<div class="row g-0">
<div class="col-md-12">
<div class="mb-3">
<label for="genres" class="form-label">{{t('genres-label')}}</label>
<app-typeahead (selectedData)="updateGenres($event);metadata.genresLocked = true" [settings]="genreSettings"
[(locked)]="metadata.genresLocked" (onUnlock)="metadata.genresLocked = false"
(newItemAdded)="metadata.genresLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.title}}
<app-setting-item [title]="t('genres-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updateGenres($event);metadata.genresLocked = true" [settings]="genreSettings"
[(locked)]="metadata.genresLocked" (onUnlock)="metadata.genresLocked = false"
(newItemAdded)="metadata.genresLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.title}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.title}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.title}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
</div>
@ -124,45 +153,53 @@
<div class="row g-0">
<div class="col-md-12">
<div class="mb-3">
<label for="tags" class="form-label">{{t('tags-label')}}</label>
<app-typeahead (selectedData)="updateTags($event);metadata.tagsLocked = true" [settings]="tagsSettings"
[(locked)]="metadata.tagsLocked" (onUnlock)="metadata.tagsLocked = false"
(newItemAdded)="metadata.tagsLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.title}}
<app-setting-item [title]="t('tags-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updateTags($event);metadata.tagsLocked = true" [settings]="tagsSettings"
[(locked)]="metadata.tagsLocked" (onUnlock)="metadata.tagsLocked = false"
(newItemAdded)="metadata.tagsLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.title}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.title}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.title}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
</div>
<div class="row g-0">
<!-- <div class="col-lg-4 col-md-12 pe-2">-->
<!-- -->
<!-- </div>-->
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<label for="age-rating" class="form-label">{{t('age-rating-label')}}</label>
<div class="input-group {{metadata.ageRatingLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'ageRatingLocked' }"></ng-container>
<select class="form-select" id="age-rating" formControlName="ageRating">
<option *ngFor="let opt of ageRatings" [value]="opt.value">{{opt.title | titlecase}}</option>
</select>
</div>
<app-setting-item [title]="t('age-rating-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<div class="input-group {{metadata.ageRatingLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'ageRatingLocked' }"></ng-container>
<select class="form-select" id="age-rating" formControlName="ageRating">
@for (opt of ageRatings; track opt.title) {
<option [value]="opt.value">{{opt.title | titlecase}}</option>
}
</select>
</div>
</ng-template>
</app-setting-item>
</div>
</div>
<div class="col-lg-6 col-md-12">
<div class="mb-3">
<label for="publication-status" class="form-label">{{t('publication-status-label')}}</label>
<div class="input-group {{metadata.publicationStatusLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'publicationStatusLocked' }"></ng-container>
<select class="form-select" id="publication-status" formControlName="publicationStatus">
<option *ngFor="let opt of publicationStatuses" [value]="opt.value">{{opt.title | titlecase}}</option>
</select>
</div>
<app-setting-item [title]="t('publication-status-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<div class="input-group {{metadata.publicationStatusLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'publicationStatusLocked' }"></ng-container>
<select class="form-select" id="publication-status" formControlName="publicationStatus">
<option *ngFor="let opt of publicationStatuses" [value]="opt.value">{{opt.title | titlecase}}</option>
</select>
</div>
</ng-template>
</app-setting-item>
</div>
</div>
</div>
@ -174,113 +211,134 @@
<ng-template ngbNavContent>
<div class="row g-0">
<div class="mb-3">
<label for="writer" class="form-label">{{t('writer-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Writer);metadata.writerLocked = true" [settings]="getPersonsSettings(PersonRole.Writer)"
[(locked)]="metadata.writerLocked" (onUnlock)="metadata.writerLocked = false"
(newItemAdded)="metadata.writerLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('writer-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Writer);metadata.writerLocked = true" [settings]="getPersonsSettings(PersonRole.Writer)"
[(locked)]="metadata.writerLocked" (onUnlock)="metadata.writerLocked = false"
(newItemAdded)="metadata.writerLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="cover-artist" class="form-label">{{t('cover-artist-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.CoverArtist);metadata.coverArtistLocked = true" [settings]="getPersonsSettings(PersonRole.CoverArtist)"
[(locked)]="metadata.coverArtistLocked" (onUnlock)="metadata.coverArtistLocked = false"
(newItemAdded)="metadata.coverArtistLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('cover-artist-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.CoverArtist);metadata.coverArtistLocked = true" [settings]="getPersonsSettings(PersonRole.CoverArtist)"
[(locked)]="metadata.coverArtistLocked" (onUnlock)="metadata.coverArtistLocked = false"
(newItemAdded)="metadata.coverArtistLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="publisher" class="form-label">{{t('publisher-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Publisher);metadata.publisherLocked = true" [settings]="getPersonsSettings(PersonRole.Publisher)"
[(locked)]="metadata.publisherLocked" (onUnlock)="metadata.publisherLocked = false"
(newItemAdded)="metadata.publisherLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('publisher-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Publisher);metadata.publisherLocked = true" [settings]="getPersonsSettings(PersonRole.Publisher)"
[(locked)]="metadata.publisherLocked" (onUnlock)="metadata.publisherLocked = false"
(newItemAdded)="metadata.publisherLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="imprint" class="form-label">{{t('imprint-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Imprint);metadata.publisherLocked = true" [settings]="getPersonsSettings(PersonRole.Imprint)"
[(locked)]="metadata.imprintLocked" (onUnlock)="metadata.imprintLocked = false"
(newItemAdded)="metadata.imprintLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('imprint-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Imprint);metadata.publisherLocked = true" [settings]="getPersonsSettings(PersonRole.Imprint)"
[(locked)]="metadata.imprintLocked" (onUnlock)="metadata.imprintLocked = false"
(newItemAdded)="metadata.imprintLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="penciller" class="form-label">{{t('penciller-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Penciller);metadata.pencillerLocked = true" [settings]="getPersonsSettings(PersonRole.Penciller)"
[(locked)]="metadata.pencillerLocked" (onUnlock)="metadata.pencillerLocked = false"
(newItemAdded)="metadata.pencillerLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('penciller-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Penciller);metadata.pencillerLocked = true" [settings]="getPersonsSettings(PersonRole.Penciller)"
[(locked)]="metadata.pencillerLocked" (onUnlock)="metadata.pencillerLocked = false"
(newItemAdded)="metadata.pencillerLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="letterer" class="form-label">{{t('letterer-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Letterer);metadata.lettererLocked = true" [settings]="getPersonsSettings(PersonRole.Letterer)"
[(locked)]="metadata.lettererLocked" (onUnlock)="metadata.lettererLocked = false"
(newItemAdded)="metadata.lettererLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('letterer-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Letterer);metadata.lettererLocked = true" [settings]="getPersonsSettings(PersonRole.Letterer)"
[(locked)]="metadata.lettererLocked" (onUnlock)="metadata.lettererLocked = false"
(newItemAdded)="metadata.lettererLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="inker" class="form-label">{{t('inker-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Inker);metadata.inkerLocked = true" [settings]="getPersonsSettings(PersonRole.Inker)"
[(locked)]="metadata.inkerLocked" (onUnlock)="metadata.inkerLocked = false"
(newItemAdded)="metadata.inkerLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('inker-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Inker);metadata.inkerLocked = true" [settings]="getPersonsSettings(PersonRole.Inker)"
[(locked)]="metadata.inkerLocked" (onUnlock)="metadata.inkerLocked = false"
(newItemAdded)="metadata.inkerLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
@ -288,96 +346,114 @@
<div class="row g-0">
<div class="mb-3">
<label for="editor" class="form-label">{{t('editor-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Editor);metadata.editorLocked = true" [settings]="getPersonsSettings(PersonRole.Editor)"
[(locked)]="metadata.editorLocked" (onUnlock)="metadata.editorLocked = false"
(newItemAdded)="metadata.editorLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('editor-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Editor);metadata.editorLocked = true" [settings]="getPersonsSettings(PersonRole.Editor)"
[(locked)]="metadata.editorLocked" (onUnlock)="metadata.editorLocked = false"
(newItemAdded)="metadata.editorLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="colorist" class="form-label">{{t('colorist-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Colorist);metadata.coloristLocked = true" [settings]="getPersonsSettings(PersonRole.Colorist)"
[(locked)]="metadata.coloristLocked" (onUnlock)="metadata.coloristLocked = false"
(newItemAdded)="metadata.coloristLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('colorist-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Colorist);metadata.coloristLocked = true" [settings]="getPersonsSettings(PersonRole.Colorist)"
[(locked)]="metadata.coloristLocked" (onUnlock)="metadata.coloristLocked = false"
(newItemAdded)="metadata.coloristLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="translator" class="form-label">{{t('translator-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Translator);metadata.translatorLocked = true;" [settings]="getPersonsSettings(PersonRole.Translator)"
[(locked)]="metadata.translatorLocked" (onUnlock)="metadata.translatorLocked = false"
(newItemAdded)="metadata.translatorLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('translator-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Translator);metadata.translatorLocked = true;" [settings]="getPersonsSettings(PersonRole.Translator)"
[(locked)]="metadata.translatorLocked" (onUnlock)="metadata.translatorLocked = false"
(newItemAdded)="metadata.translatorLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="character" class="form-label">{{t('character-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Character);metadata.characterLocked = true" [settings]="getPersonsSettings(PersonRole.Character)"
[(locked)]="metadata.characterLocked" (onUnlock)="metadata.characterLocked = false"
(newItemAdded)="metadata.characterLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('character-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Character);metadata.characterLocked = true" [settings]="getPersonsSettings(PersonRole.Character)"
[(locked)]="metadata.characterLocked" (onUnlock)="metadata.characterLocked = false"
(newItemAdded)="metadata.characterLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="team" class="form-label">{{t('team-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Character);metadata.teamLocked = true" [settings]="getPersonsSettings(PersonRole.Team)"
[(locked)]="metadata.teamLocked" (onUnlock)="metadata.teamLocked = false"
(newItemAdded)="metadata.teamLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('team-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Character);metadata.teamLocked = true" [settings]="getPersonsSettings(PersonRole.Team)"
[(locked)]="metadata.teamLocked" (onUnlock)="metadata.teamLocked = false"
(newItemAdded)="metadata.teamLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
<div class="row g-0">
<div class="mb-3">
<label for="location" class="form-label">{{t('location-label')}}</label>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Location);metadata.locationLocked = true" [settings]="getPersonsSettings(PersonRole.Location)"
[(locked)]="metadata.locationLocked" (onUnlock)="metadata.locationLocked = false"
(newItemAdded)="metadata.locationLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
<app-setting-item [title]="t('location-label')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Location)" [settings]="getPersonsSettings(PersonRole.Location)"
[(locked)]="metadata.locationLocked" (onUnlock)="metadata.locationLocked = false"
(newItemAdded)="metadata.locationLocked = true">
<ng-template #badgeItem let-item let-position="idx">
{{item.name}}
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</ng-template>
<ng-template #optionItem let-item let-position="idx">
{{item.name}}
</ng-template>
</app-typeahead>
</app-setting-item>
</div>
</div>
@ -395,7 +471,7 @@
<li [ngbNavItem]="tabs[TabID.CoverImage]">
<a ngbNavLink>{{t(tabs[TabID.CoverImage])}}</a>
<ng-template ngbNavContent>
<p class="alert alert-primary" role="alert">
<p class="alert alert-warning" role="alert">
{{t('cover-image-description')}}
</p>
<app-cover-image-chooser [(imageUrls)]="imageUrls" (imageSelected)="updateSelectedIndex($event)" (selectedBase64Url)="updateSelectedImage($event)" [showReset]="series.coverImageLocked" (resetClicked)="handleReset()"></app-cover-image-chooser>
@ -412,33 +488,33 @@
<li [ngbNavItem]="tabs[TabID.Info]">
<a ngbNavLink>{{t(tabs[TabID.Info])}}</a>
<ng-template ngbNavContent>
<h4>{{t('info-title')}}</h4>
<div class="row g-0 mb-2">
<div class="col-md-6" *ngIf="libraryName">{{t('library-title')}} {{libraryName | sentenceCase}}</div>
<div class="col-md-6">{{t('format-title')}} <app-tag-badge>{{series.format | mangaFormat}}</app-tag-badge></div>
<h5>{{t('info-title')}}</h5>
<div class="row g-0 mt-3 mb-3">
<div class="col-md-6" *ngIf="libraryName"><span class="fw-bold text-uppercase">{{t('library-title')}}</span> {{libraryName | sentenceCase}}</div>
<div class="col-md-6"><span class="fw-bold text-uppercase">{{t('format-title')}}</span> <app-tag-badge>{{series.format | mangaFormat}}</app-tag-badge></div>
</div>
<div class="row g-0 mb-2">
<div class="col-md-6">{{t('created-title')}} {{series.created | date:'shortDate'}}</div>
<div class="col-md-6">{{t('last-read-title')}} {{series.latestReadDate | defaultDate | timeAgo}}</div>
<div class="col-md-6">{{t('last-added-title')}} {{series.lastChapterAdded | defaultDate | timeAgo}}</div>
<div class="col-md-6">{{t('last-scanned-title')}} {{series.lastFolderScanned | defaultDate | timeAgo}}</div>
<div class="row g-0 mt-3 mb-3">
<div class="col-md-6"><span class="fw-bold text-uppercase">{{t('created-title')}}</span> {{series.created | date:'shortDate'}}</div>
<div class="col-md-6"><span class="fw-bold text-uppercase">{{t('last-read-title')}}</span> {{series.latestReadDate | defaultDate | timeAgo}}</div>
<div class="col-md-6"><span class="fw-bold text-uppercase">{{t('last-added-title')}}</span> {{series.lastChapterAdded | defaultDate | timeAgo}}</div>
<div class="col-md-6"><span class="fw-bold text-uppercase">{{t('last-scanned-title')}}</span> {{series.lastFolderScanned | defaultDate | timeAgo}}</div>
</div>
<div class="row g-0 mb-2">
<div class="col-auto">{{t('folder-path-title')}} {{series.folderPath | defaultValue}}</div>
<div class="row g-0 mt-3 mb-3">
<div class="col-auto"><span class="fw-bold text-uppercase">{{t('folder-path-title')}}</span> {{series.folderPath | defaultValue}}</div>
</div>
<div class="row g-0 mb-2" *ngIf="metadata">
<div class="row g-0 mt-3 mb-3" *ngIf="metadata">
<div class="col-md-6">
{{t('max-items-title')}} {{metadata.maxCount}}
<span class="fw-bold text-uppercase">{{t('max-items-title')}}</span> {{metadata.maxCount}}
<i class="fa fa-info-circle ms-1" placement="right" [ngbTooltip]="t('highest-count-tooltip')" role="button" tabindex="0"></i>
</div>
<div class="col-md-6">
{{t('total-items-title')}} {{metadata.totalCount}}
<span class="fw-bold text-uppercase">{{t('total-items-title')}}</span> {{metadata.totalCount}}
<i class="fa fa-info-circle ms-1" placement="right" [ngbTooltip]="t('max-issue-tooltip')" role="button" tabindex="0"></i>
</div>
<div class="col-md-6">{{t('publication-status-title')}} {{metadata.publicationStatus | publicationStatus}}</div>
<div class="col-md-6">{{t('total-pages-title')}} {{series.pages}}</div>
<div class="col-md-6">{{t('size-title')}} {{size | bytes}}</div>
<div class="col-md-6"><span class="fw-bold text-uppercase">{{t('publication-status-title')}}</span> {{metadata.publicationStatus | publicationStatus}}</div>
<div class="col-md-6"><span class="fw-bold text-uppercase">{{t('total-pages-title')}}</span> {{series.pages}}</div>
<div class="col-md-6"><span class="fw-bold text-uppercase">{{t('size-title')}}</span> {{size | bytes}}</div>
</div>
<h4>Volumes</h4>
<div class="spinner-border text-secondary" role="status" *ngIf="isLoadingVolumes">

View file

@ -61,6 +61,7 @@ import {Action, ActionFactoryService, ActionItem} from "../../../_services/actio
import {SettingButtonComponent} from "../../../settings/_components/setting-button/setting-button.component";
import {ActionService} from "../../../_services/action.service";
import {DownloadService} from "../../../shared/_services/download.service";
import {SettingItemComponent} from "../../../settings/_components/setting-item/setting-item.component";
enum TabID {
General = 0,
@ -114,6 +115,7 @@ const blackList = [Action.Edit, Action.Info, Action.IncognitoRead, Action.Read,
UtcToLocalTimePipe,
EditListComponent,
SettingButtonComponent,
SettingItemComponent,
],
templateUrl: './edit-series-modal.component.html',
styleUrls: ['./edit-series-modal.component.scss'],
@ -418,7 +420,8 @@ export class EditSeriesModalComponent implements OnInit {
const presetIds = presetField.map(p => p.id);
personSettings.savedData = people.filter(person => presetIds.includes(person.id));
this.peopleSettings[role] = personSettings;
this.updatePerson(personSettings.savedData as Person[], role);
this.metadataService.updatePerson(this.metadata, personSettings.savedData as Person[], role);
this.cdRef.markForCheck();
return true;
}));
} else {
@ -550,8 +553,8 @@ export class EditSeriesModalComponent implements OnInit {
}
if (selectedIndex > 0 && this.selectedCover !== '') {
apis.push(this.uploadService.updateSeriesCoverImage(model.id, this.selectedCover));
if (selectedIndex > 0 || this.coverImageReset) {
apis.push(this.uploadService.updateSeriesCoverImage(model.id, this.selectedCover, !this.coverImageReset));
}
this.saveNestedComponents.emit();
@ -574,6 +577,12 @@ export class EditSeriesModalComponent implements OnInit {
this.cdRef.markForCheck();
}
updatePerson(persons: Person[], role: PersonRole) {
this.metadataService.updatePerson(this.metadata, persons, role);
this.metadata.locationLocked = true;
this.cdRef.markForCheck();
}
updateLanguage(language: Array<Language>) {
if (language.length === 0) {
this.metadata.language = '';
@ -583,56 +592,6 @@ export class EditSeriesModalComponent implements OnInit {
this.cdRef.markForCheck();
}
updatePerson(persons: Person[], role: PersonRole) {
switch (role) {
case PersonRole.Other:
break;
case PersonRole.Artist:
break;
case PersonRole.CoverArtist:
this.metadata.coverArtists = persons;
break;
case PersonRole.Character:
this.metadata.characters = persons;
break;
case PersonRole.Colorist:
this.metadata.colorists = persons;
break;
case PersonRole.Editor:
this.metadata.editors = persons;
break;
case PersonRole.Inker:
this.metadata.inkers = persons;
break;
case PersonRole.Letterer:
this.metadata.letterers = persons;
break;
case PersonRole.Penciller:
this.metadata.pencillers = persons;
break;
case PersonRole.Publisher:
this.metadata.publishers = persons;
break;
case PersonRole.Imprint:
this.metadata.imprints = persons;
break;
case PersonRole.Team:
this.metadata.teams = persons;
break;
case PersonRole.Location:
this.metadata.locations = persons;
break;
case PersonRole.Writer:
this.metadata.writers = persons;
break;
case PersonRole.Translator:
this.metadata.translators = persons;
break;
}
this.cdRef.markForCheck();
}
updateSelectedIndex(index: number) {
this.editSeriesForm.patchValue({
coverImageIndex: index