Kavita+ Comic Metadata Matching (#3740)
This commit is contained in:
parent
4521965315
commit
ed154e4768
46 changed files with 4207 additions and 98 deletions
|
@ -27,8 +27,9 @@ export interface MetadataTagDto {
|
|||
|
||||
export interface ExternalSeriesDetail {
|
||||
name: string;
|
||||
aniListId?: number;
|
||||
malId?: number;
|
||||
aniListId?: number | null;
|
||||
malId?: number | null;
|
||||
cbrId?: number | null;
|
||||
synonyms: Array<string>;
|
||||
plusMediaFormat: PlusMediaFormat;
|
||||
siteUrl?: string;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import {Pipe, PipeTransform} from '@angular/core';
|
||||
import {MetadataSettingField} from "../admin/_models/metadata-setting-field";
|
||||
import {translate} from "@jsverse/transloco";
|
||||
|
||||
|
@ -10,9 +10,19 @@ export class MetadataSettingFiledPipe implements PipeTransform {
|
|||
|
||||
transform(value: MetadataSettingField): string {
|
||||
switch (value) {
|
||||
case MetadataSettingField.ChapterTitle:
|
||||
return translate('metadata-setting-field-pipe.chapter-title');
|
||||
case MetadataSettingField.ChapterSummary:
|
||||
return translate('metadata-setting-field-pipe.chapter-summary');
|
||||
case MetadataSettingField.ChapterReleaseDate:
|
||||
return translate('metadata-setting-field-pipe.chapter-release-date');
|
||||
case MetadataSettingField.ChapterPublisher:
|
||||
return translate('metadata-setting-field-pipe.chapter-publisher');
|
||||
case MetadataSettingField.ChapterCovers:
|
||||
return translate('metadata-setting-field-pipe.chapter-covers');
|
||||
case MetadataSettingField.AgeRating:
|
||||
return translate('metadata-setting-field-pipe.age-rating');
|
||||
case MetadataSettingField.People:
|
||||
case MetadataSettingField.People:
|
||||
return translate('metadata-setting-field-pipe.people');
|
||||
case MetadataSettingField.Covers:
|
||||
return translate('metadata-setting-field-pipe.covers');
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import {Pipe, PipeTransform} from '@angular/core';
|
||||
import {PlusMediaFormat} from "../_models/series-detail/external-series-detail";
|
||||
import {translate} from "@jsverse/transloco";
|
||||
|
||||
|
@ -13,7 +13,7 @@ export class PlusMediaFormatPipe implements PipeTransform {
|
|||
case PlusMediaFormat.Manga:
|
||||
return translate('library-type-pipe.manga');
|
||||
case PlusMediaFormat.Comic:
|
||||
return translate('library-type-pipe.comic');
|
||||
return translate('library-type-pipe.comicVine');
|
||||
case PlusMediaFormat.LightNovel:
|
||||
return translate('library-type-pipe.lightNovel');
|
||||
case PlusMediaFormat.Book:
|
||||
|
|
|
@ -17,6 +17,8 @@ export class ProviderImagePipe implements PipeTransform {
|
|||
return `assets/images/ExternalServices/GoogleBooks${large ? '-lg' : ''}.png`;
|
||||
case ScrobbleProvider.Kavita:
|
||||
return `assets/images/logo-${large ? '64' : '32'}.png`;
|
||||
case ScrobbleProvider.Cbr:
|
||||
return `assets/images/ExternalServices/ComicBookRoundup.png`;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import {ScrobbleProvider} from "../_services/scrobbling.service";
|
||||
|
||||
@Pipe({
|
||||
name: 'providerName',
|
||||
standalone: true
|
||||
})
|
||||
export class ProviderNamePipe implements PipeTransform {
|
||||
|
||||
transform(value: ScrobbleProvider): string {
|
||||
switch (value) {
|
||||
case ScrobbleProvider.AniList:
|
||||
return 'AniList';
|
||||
case ScrobbleProvider.Mal:
|
||||
return 'MAL';
|
||||
case ScrobbleProvider.Kavita:
|
||||
return 'Kavita';
|
||||
case ScrobbleProvider.GoogleBooks:
|
||||
return 'Google Books';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@ export class ScrobbleProviderNamePipe implements PipeTransform {
|
|||
case ScrobbleProvider.AniList: return 'AniList';
|
||||
case ScrobbleProvider.Mal: return 'MAL';
|
||||
case ScrobbleProvider.Kavita: return 'Kavita';
|
||||
case ScrobbleProvider.Cbr: return 'Comicbook Roundup';
|
||||
case ScrobbleProvider.GoogleBooks: return 'Google Books';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,10 @@ import {UtilityService} from "../shared/_services/utility.service";
|
|||
|
||||
export enum ScrobbleProvider {
|
||||
Kavita = 0,
|
||||
AniList= 1,
|
||||
AniList = 1,
|
||||
Mal = 2,
|
||||
GoogleBooks = 3
|
||||
GoogleBooks = 3,
|
||||
Cbr = 4
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
|
|
|
@ -242,7 +242,7 @@ export class SeriesService {
|
|||
}
|
||||
|
||||
updateMatch(seriesId: number, series: ExternalSeriesDetail) {
|
||||
return this.httpClient.post<string>(this.baseUrl + `series/update-match?seriesId=${seriesId}&aniListId=${series.aniListId}${series.malId ? '&malId=' + series.malId : ''}`, {}, TextResonse);
|
||||
return this.httpClient.post<string>(this.baseUrl + `series/update-match?seriesId=${seriesId}&aniListId=${series.aniListId || 0}&malId=${series.malId || 0}&cbrId=${series.cbrId || 0}`, {}, TextResonse);
|
||||
}
|
||||
|
||||
updateDontMatch(seriesId: number, dontMatch: boolean) {
|
||||
|
|
|
@ -91,7 +91,7 @@ export class MatchSeriesModalComponent implements OnInit {
|
|||
data.tags = data.tags || [];
|
||||
data.genres = data.genres || [];
|
||||
|
||||
this.seriesService.updateMatch(this.series.id, data).subscribe(_ => {
|
||||
this.seriesService.updateMatch(this.series.id, item.series).subscribe(_ => {
|
||||
this.save();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,7 +7,14 @@ export enum MetadataSettingField {
|
|||
LocalizedName = 6,
|
||||
Covers = 7,
|
||||
AgeRating = 8,
|
||||
People = 9
|
||||
People = 9,
|
||||
|
||||
// Chapter fields
|
||||
ChapterTitle = 10,
|
||||
ChapterSummary = 11,
|
||||
ChapterReleaseDate = 12,
|
||||
ChapterPublisher = 13,
|
||||
ChapterCovers = 14,
|
||||
}
|
||||
|
||||
export const allMetadataSettingField = Object.keys(MetadataSettingField)
|
||||
|
|
|
@ -25,6 +25,14 @@ export interface MetadataSettings {
|
|||
enableStartDate: boolean;
|
||||
enableCoverImage: boolean;
|
||||
enableLocalizedName: boolean;
|
||||
|
||||
enableChapterSummary: boolean;
|
||||
enableChapterReleaseDate: boolean;
|
||||
enableChapterTitle: boolean;
|
||||
enableChapterPublisher: boolean;
|
||||
enableChapterCoverImage: boolean;
|
||||
|
||||
|
||||
enableGenres: boolean;
|
||||
enableTags: boolean;
|
||||
firstLastPeopleNaming: boolean;
|
||||
|
|
|
@ -89,6 +89,70 @@
|
|||
}
|
||||
</div>
|
||||
|
||||
<div class="setting-section-break"></div>
|
||||
|
||||
<!-- Chapter-based fields -->
|
||||
<h5>{{t('chapter-header')}}</h5>
|
||||
<div class="row g-0 mt-4 mb-4">
|
||||
@if(settingsForm.get('enableChapterTitle'); as formControl) {
|
||||
<app-setting-switch [title]="t('enable-chapter-title-label')" [subtitle]="t('enable-chapter-title-tooltip')">
|
||||
<ng-template #switch>
|
||||
<div class="form-check form-switch float-end">
|
||||
<input id="enable-chapter-title" type="checkbox" class="form-check-input" formControlName="enableChapterTitle">
|
||||
</div>
|
||||
</ng-template>
|
||||
</app-setting-switch>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="row g-0 mt-4 mb-4">
|
||||
@if(settingsForm.get('enableChapterSummary'); as formControl) {
|
||||
<app-setting-switch [title]="t('enable-chapter-summary-label')" [subtitle]="t('enable-chapter-summary-tooltip')">
|
||||
<ng-template #switch>
|
||||
<div class="form-check form-switch float-end">
|
||||
<input id="enable-chapter-summary" type="checkbox" class="form-check-input" formControlName="enableChapterSummary">
|
||||
</div>
|
||||
</ng-template>
|
||||
</app-setting-switch>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="row g-0 mt-4 mb-4">
|
||||
@if(settingsForm.get('enableChapterReleaseDate'); as formControl) {
|
||||
<app-setting-switch [title]="t('enable-chapter-release-date-label')" [subtitle]="t('enable-chapter-release-date-tooltip')">
|
||||
<ng-template #switch>
|
||||
<div class="form-check form-switch float-end">
|
||||
<input id="enable-chapter-release-date" type="checkbox" class="form-check-input" formControlName="enableChapterReleaseDate">
|
||||
</div>
|
||||
</ng-template>
|
||||
</app-setting-switch>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="row g-0 mt-4 mb-4">
|
||||
@if(settingsForm.get('enableChapterPublisher'); as formControl) {
|
||||
<app-setting-switch [title]="t('enable-chapter-publisher-label')" [subtitle]="t('enable-chapter-publisher-tooltip')">
|
||||
<ng-template #switch>
|
||||
<div class="form-check form-switch float-end">
|
||||
<input id="enable-chapter-publisher" type="checkbox" class="form-check-input" formControlName="enableChapterPublisher">
|
||||
</div>
|
||||
</ng-template>
|
||||
</app-setting-switch>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="row g-0 mt-4 mb-4">
|
||||
@if(settingsForm.get('enableChapterCoverImage'); as formControl) {
|
||||
<app-setting-switch [title]="t('enable-chapter-cover-label')" [subtitle]="t('enable-chapter-cover-tooltip')">
|
||||
<ng-template #switch>
|
||||
<div class="form-check form-switch float-end">
|
||||
<input id="enable-chapter-cover" type="checkbox" class="form-check-input" formControlName="enableChapterCoverImage">
|
||||
</div>
|
||||
</ng-template>
|
||||
</app-setting-switch>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if(settingsForm.get('enablePeople'); as formControl) {
|
||||
<div class="setting-section-break"></div>
|
||||
|
||||
|
@ -133,6 +197,7 @@
|
|||
|
||||
|
||||
|
||||
|
||||
<div class="setting-section-break"></div>
|
||||
|
||||
|
||||
|
|
|
@ -79,6 +79,13 @@ export class ManageMetadataSettingsComponent implements OnInit {
|
|||
this.settingsForm.addControl('enableStartDate', new FormControl(settings.enableStartDate, []));
|
||||
this.settingsForm.addControl('enableCoverImage', new FormControl(settings.enableCoverImage, []));
|
||||
|
||||
|
||||
this.settingsForm.addControl('enableChapterTitle', new FormControl(settings.enableChapterTitle, []));
|
||||
this.settingsForm.addControl('enableChapterSummary', new FormControl(settings.enableChapterSummary, []));
|
||||
this.settingsForm.addControl('enableChapterReleaseDate', new FormControl(settings.enableChapterReleaseDate, []));
|
||||
this.settingsForm.addControl('enableChapterPublisher', new FormControl(settings.enableChapterPublisher, []));
|
||||
this.settingsForm.addControl('enableChapterCoverImage', new FormControl(settings.enableChapterCoverImage, []));
|
||||
|
||||
this.settingsForm.addControl('blacklist', new FormControl((settings.blacklist || '').join(','), []));
|
||||
this.settingsForm.addControl('whitelist', new FormControl((settings.whitelist || '').join(','), []));
|
||||
this.settingsForm.addControl('firstLastPeopleNaming', new FormControl((settings.firstLastPeopleNaming), []));
|
||||
|
|
|
@ -43,6 +43,7 @@ import {DefaultModalOptions} from "../../../_models/default-modal-options";
|
|||
templateUrl: './all-collections.component.html',
|
||||
styleUrls: ['./all-collections.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [SideNavCompanionBarComponent, CardDetailLayoutComponent, CardItemComponent, AsyncPipe, DecimalPipe,
|
||||
TranslocoDirective, CollectionOwnerComponent, BulkOperationsComponent]
|
||||
})
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<div class="under-image">
|
||||
<app-image [imageUrl]="collectionTag.source | providerImage"
|
||||
width="16px" height="16px"
|
||||
[ngbTooltip]="collectionTag.source | providerName" tabindex="0"></app-image>
|
||||
[ngbTooltip]="collectionTag.source | scrobbleProviderName" tabindex="0"></app-image>
|
||||
<span class="ms-2 me-2">{{t('sync-progress', {title: series.length + ' / ' + collectionTag.totalSourceCount})}}</span>
|
||||
<i class="fa-solid fa-question-circle" aria-hidden="true" [ngbTooltip]="t('last-sync', {date: collectionTag.lastSyncUtc | date: 'short' | defaultDate })"></i>
|
||||
</div>
|
||||
|
|
|
@ -56,20 +56,20 @@ import {User} from "../../../_models/user";
|
|||
import {ScrobbleProvider} from "../../../_services/scrobbling.service";
|
||||
import {DefaultDatePipe} from "../../../_pipes/default-date.pipe";
|
||||
import {ProviderImagePipe} from "../../../_pipes/provider-image.pipe";
|
||||
import {ProviderNamePipe} from "../../../_pipes/provider-name.pipe";
|
||||
import {
|
||||
SmartCollectionDrawerComponent
|
||||
} from "../../../_single-module/smart-collection-drawer/smart-collection-drawer.component";
|
||||
import {DefaultModalOptions} from "../../../_models/default-modal-options";
|
||||
import {ScrobbleProviderNamePipe} from "../../../_pipes/scrobble-provider-name.pipe";
|
||||
|
||||
@Component({
|
||||
selector: 'app-collection-detail',
|
||||
templateUrl: './collection-detail.component.html',
|
||||
styleUrls: ['./collection-detail.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
selector: 'app-collection-detail',
|
||||
templateUrl: './collection-detail.component.html',
|
||||
styleUrls: ['./collection-detail.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [SideNavCompanionBarComponent, CardActionablesComponent, ImageComponent, ReadMoreComponent,
|
||||
BulkOperationsComponent, CardDetailLayoutComponent, SeriesCardComponent, TranslocoDirective, NgbTooltip,
|
||||
DatePipe, DefaultDatePipe, ProviderImagePipe, ProviderNamePipe, AsyncPipe]
|
||||
DatePipe, DefaultDatePipe, ProviderImagePipe, AsyncPipe, ScrobbleProviderNamePipe]
|
||||
})
|
||||
export class CollectionDetailComponent implements OnInit, AfterContentChecked {
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
{{t('collection-via-label')}}
|
||||
<app-image [imageUrl]="collection.source | providerImage"
|
||||
width="16px" height="16px"
|
||||
[ngbTooltip]="collection.source | providerName"
|
||||
[attr.aria-label]="collection.source | providerName"></app-image>
|
||||
[ngbTooltip]="collection.source | scrobbleProviderName"
|
||||
[attr.aria-label]="collection.source | scrobbleProviderName"></app-image>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
import {ChangeDetectionStrategy, Component, inject, Input} from '@angular/core';
|
||||
import {ScrobbleProvider} from "../../../_services/scrobbling.service";
|
||||
import {ProviderImagePipe} from "../../../_pipes/provider-image.pipe";
|
||||
import {ProviderNamePipe} from "../../../_pipes/provider-name.pipe";
|
||||
import {UserCollection} from "../../../_models/collection-tag";
|
||||
import {TranslocoDirective} from "@jsverse/transloco";
|
||||
import {AsyncPipe} from "@angular/common";
|
||||
import {AccountService} from "../../../_services/account.service";
|
||||
import {ImageComponent} from "../../../shared/image/image.component";
|
||||
import {NgbTooltip} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {ScrobbleProviderNamePipe} from "../../../_pipes/scrobble-provider-name.pipe";
|
||||
|
||||
@Component({
|
||||
selector: 'app-collection-owner',
|
||||
imports: [
|
||||
ProviderImagePipe,
|
||||
ProviderNamePipe,
|
||||
TranslocoDirective,
|
||||
AsyncPipe,
|
||||
ImageComponent,
|
||||
NgbTooltip
|
||||
NgbTooltip,
|
||||
ScrobbleProviderNamePipe
|
||||
],
|
||||
templateUrl: './collection-owner.component.html',
|
||||
styleUrl: './collection-owner.component.scss',
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
@for (rating of ratings; track rating.provider + rating.averageScore) {
|
||||
<div class="col-auto custom-col clickable" [ngbPopover]="externalPopContent" [popoverContext]="{rating: rating}"
|
||||
[popoverTitle]="rating.provider | providerName" popoverClass="sm-popover">
|
||||
[popoverTitle]="rating.provider | scrobbleProviderName" popoverClass="sm-popover">
|
||||
<span class="badge rounded-pill me-1">
|
||||
<img class="me-1" [ngSrc]="rating.provider | providerImage:true" width="24" height="24" alt="" aria-hidden="true">
|
||||
{{rating.averageScore}}%
|
||||
|
@ -64,9 +64,11 @@
|
|||
</ng-template>
|
||||
|
||||
<ng-template #externalPopContent let-rating="rating">
|
||||
<div>
|
||||
<i class="fa-solid fa-heart" aria-hidden="true"></i> {{rating.favoriteCount}}
|
||||
</div>
|
||||
@if (rating.favoriteCount > 0) {
|
||||
<div>
|
||||
<i class="fa-solid fa-heart" aria-hidden="true"></i> {{rating.favoriteCount}}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (rating.providerUrl) {
|
||||
<a [href]="rating.providerUrl" target="_blank" rel="noreferrer nofollow">{{t('entry-label')}}</a>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component, DestroyRef,
|
||||
Component,
|
||||
DestroyRef,
|
||||
inject,
|
||||
Input,
|
||||
OnInit,
|
||||
|
@ -13,7 +14,6 @@ import {ProviderImagePipe} from "../../../_pipes/provider-image.pipe";
|
|||
import {NgbModal, NgbPopover} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {LoadingComponent} from "../../../shared/loading/loading.component";
|
||||
import {LibraryType} from "../../../_models/library/library";
|
||||
import {ProviderNamePipe} from "../../../_pipes/provider-name.pipe";
|
||||
import {NgxStarsModule} from "ngx-stars";
|
||||
import {ThemeService} from "../../../_services/theme.service";
|
||||
import {Breakpoint, UtilityService} from "../../../shared/_services/utility.service";
|
||||
|
@ -23,15 +23,16 @@ import {SafeHtmlPipe} from "../../../_pipes/safe-html.pipe";
|
|||
import {ImageService} from "../../../_services/image.service";
|
||||
import {AsyncPipe, NgOptimizedImage, NgTemplateOutlet} from "@angular/common";
|
||||
import {RatingModalComponent} from "../rating-modal/rating-modal.component";
|
||||
import {ScrobbleProviderNamePipe} from "../../../_pipes/scrobble-provider-name.pipe";
|
||||
|
||||
@Component({
|
||||
selector: 'app-external-rating',
|
||||
imports: [ProviderImagePipe, NgbPopover, LoadingComponent, ProviderNamePipe, NgxStarsModule, ImageComponent,
|
||||
TranslocoDirective, SafeHtmlPipe, NgOptimizedImage, AsyncPipe, NgTemplateOutlet],
|
||||
templateUrl: './external-rating.component.html',
|
||||
styleUrls: ['./external-rating.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None
|
||||
selector: 'app-external-rating',
|
||||
imports: [ProviderImagePipe, NgbPopover, LoadingComponent, NgxStarsModule, ImageComponent,
|
||||
TranslocoDirective, SafeHtmlPipe, NgOptimizedImage, AsyncPipe, NgTemplateOutlet, ScrobbleProviderNamePipe],
|
||||
templateUrl: './external-rating.component.html',
|
||||
styleUrls: ['./external-rating.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ExternalRatingComponent implements OnInit {
|
||||
|
||||
|
|
|
@ -128,6 +128,11 @@ export class LibrarySettingsModalComponent implements OnInit {
|
|||
return libType === LibraryType.Manga || libType === LibraryType.LightNovel;
|
||||
}
|
||||
|
||||
get IsMetadataDownloadEligible() {
|
||||
const libType = parseInt(this.libraryForm.get('type')?.value + '', 10) as LibraryType;
|
||||
return libType === LibraryType.Manga || libType === LibraryType.LightNovel || libType === LibraryType.ComicVine;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.library === undefined) {
|
||||
this.isAddLibrary = true;
|
||||
|
@ -141,11 +146,19 @@ export class LibrarySettingsModalComponent implements OnInit {
|
|||
|
||||
if (this.library && !(this.library.type === LibraryType.Manga || this.library.type === LibraryType.LightNovel) ) {
|
||||
this.libraryForm.get('allowScrobbling')?.setValue(false);
|
||||
this.libraryForm.get('allowMetadataMatching')?.setValue(false);
|
||||
this.libraryForm.get('allowScrobbling')?.disable();
|
||||
this.libraryForm.get('allowMetadataMatching')?.disable();
|
||||
|
||||
if (this.IsMetadataDownloadEligible) {
|
||||
this.libraryForm.get('allowMetadataMatching')?.setValue(this.library.allowMetadataMatching);
|
||||
this.libraryForm.get('allowMetadataMatching')?.enable();
|
||||
} else {
|
||||
this.libraryForm.get('allowMetadataMatching')?.setValue(false);
|
||||
this.libraryForm.get('allowMetadataMatching')?.disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.libraryForm.get('name')?.valueChanges.pipe(
|
||||
debounceTime(100),
|
||||
distinctUntilChanged(),
|
||||
|
@ -208,11 +221,16 @@ export class LibrarySettingsModalComponent implements OnInit {
|
|||
|
||||
if (!this.IsKavitaPlusEligible) {
|
||||
this.libraryForm.get('allowScrobbling')?.disable();
|
||||
this.libraryForm.get('allowMetadataMatching')?.disable();
|
||||
} else {
|
||||
this.libraryForm.get('allowScrobbling')?.enable();
|
||||
this.libraryForm.get('allowMetadataMatching')?.enable();
|
||||
}
|
||||
|
||||
if (this.IsMetadataDownloadEligible) {
|
||||
this.libraryForm.get('allowMetadataMatching')?.enable();
|
||||
} else {
|
||||
this.libraryForm.get('allowMetadataMatching')?.disable();
|
||||
}
|
||||
|
||||
this.cdRef.markForCheck();
|
||||
}),
|
||||
takeUntilDestroyed(this.destroyRef)
|
||||
|
@ -231,7 +249,7 @@ export class LibrarySettingsModalComponent implements OnInit {
|
|||
this.libraryForm.get('manageReadingLists')?.setValue(this.library.manageReadingLists);
|
||||
this.libraryForm.get('collapseSeriesRelationships')?.setValue(this.library.collapseSeriesRelationships);
|
||||
this.libraryForm.get('allowScrobbling')?.setValue(this.IsKavitaPlusEligible ? this.library.allowScrobbling : false);
|
||||
this.libraryForm.get('allowMetadataMatching')?.setValue(this.IsKavitaPlusEligible ? this.library.allowMetadataMatching : false);
|
||||
this.libraryForm.get('allowMetadataMatching')?.setValue(this.IsMetadataDownloadEligible ? this.library.allowMetadataMatching : false);
|
||||
this.selectedFolders = this.library.folders;
|
||||
|
||||
this.madeChanges = false;
|
||||
|
|
BIN
UI/Web/src/assets/images/ExternalServices/ComicBookRoundup.png
Normal file
BIN
UI/Web/src/assets/images/ExternalServices/ComicBookRoundup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
|
@ -806,6 +806,17 @@
|
|||
"enable-cover-image-tooltip": "Allow Kavita to write the cover image for the Series",
|
||||
"enable-start-date-label": "Start Date",
|
||||
"enable-start-date-tooltip": "Allow Start Date of Series to be written to the Series",
|
||||
|
||||
"enable-chapter-title-label": "Title",
|
||||
"enable-chapter-title-tooltip": "Allow Title of Chapter/Issue to be written",
|
||||
"enable-chapter-summary-label": "{{manage-metadata-settings.summary-label}}",
|
||||
"enable-chapter-summary-tooltip": "{{manage-metadata-settings.summary-tooltip}}",
|
||||
"enable-chapter-release-date-label": "Release Date",
|
||||
"enable-chapter-release-date-tooltip": "Allow Release Date of Chapter/Issue to be written",
|
||||
"enable-chapter-publisher-label": "Publisher",
|
||||
"enable-chapter-publisher-tooltip": "Allow Publisher of Chapter/Issue to be written",
|
||||
"enable-chapter-cover-label": "Chapter Cover",
|
||||
"enable-chapter-cover-tooltip": "Allow Cover of Chapter/Issue to be set",
|
||||
"enable-genres-label": "Genres",
|
||||
"enable-genres-tooltip": "Allow Series Genres to be written.",
|
||||
"enable-tags-label": "Tags",
|
||||
|
@ -827,7 +838,8 @@
|
|||
"first-last-name-tooltip": "Ensure People's names are written First then Last",
|
||||
"person-roles-label": "Roles",
|
||||
"overrides-label": "Overrides",
|
||||
"overrides-description": "Allow Kavita to write over locked fields."
|
||||
"overrides-description": "Allow Kavita to write over locked fields.",
|
||||
"chapter-header": "Chapter Fields"
|
||||
},
|
||||
|
||||
"book-line-overlay": {
|
||||
|
@ -2686,7 +2698,12 @@
|
|||
"start-date": "{{manage-metadata-settings.enable-start-date-label}}",
|
||||
"genres": "{{metadata-fields.genres-title}}",
|
||||
"tags": "{{metadata-fields.tags-title}}",
|
||||
"localized-name": "{{edit-series-modal.localized-name-label}}"
|
||||
"localized-name": "{{edit-series-modal.localized-name-label}}",
|
||||
"chapter-release-date": "Release Date (Chapter)",
|
||||
"chapter-summary": "Summary (Chapter)",
|
||||
"chapter-covers": "Covers (Chapter)",
|
||||
"chapter-publisher": "{{person-role-pipe.publisher}} (Chapter)",
|
||||
"chapter-title": "Title (Chapter)"
|
||||
},
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue