Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo 2024-08-24 19:23:57 -05:00 committed by GitHub
parent dbc4f35107
commit c93af3e56f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
126 changed files with 1989 additions and 2877 deletions

View file

@ -1,5 +1,5 @@
<ng-container *transloco="let t; read: 'details-tab'">
<div class="details pb-3">
<div class="mb-3">
<app-carousel-reel [items]="genres" [title]="t('genres-title')">
<ng-template #carouselItem let-item>
@ -132,4 +132,5 @@
</ng-template>
</app-carousel-reel>
</div>
</div>
</ng-container>

View file

@ -44,7 +44,6 @@ import {SettingButtonComponent} from "../../settings/_components/setting-button/
import {CoverImageChooserComponent} from "../../cards/cover-image-chooser/cover-image-chooser.component";
import {EditChapterProgressComponent} from "../../cards/edit-chapter-progress/edit-chapter-progress.component";
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import {EntityInfoCardsComponent} from "../../cards/entity-info-cards/entity-info-cards.component";
import {CompactNumberPipe} from "../../_pipes/compact-number.pipe";
import {IconAndTitleComponent} from "../../shared/icon-and-title/icon-and-title.component";
import {MangaFormat} from "../../_models/manga-format";
@ -56,6 +55,7 @@ import {ImageComponent} from "../../shared/image/image.component";
import {SafeHtmlPipe} from "../../_pipes/safe-html.pipe";
import {ReadTimePipe} from "../../_pipes/read-time.pipe";
import {ChapterService} from "../../_services/chapter.service";
import {AgeRating} from "../../_models/metadata/age-rating";
enum TabID {
General = 'general-tab',
@ -100,7 +100,6 @@ const blackList = [Action.Edit, Action.IncognitoRead, Action.AddToReadingList];
CoverImageChooserComponent,
EditChapterProgressComponent,
NgbInputDatepicker,
EntityInfoCardsComponent,
CompactNumberPipe,
IconAndTitleComponent,
DefaultDatePipe,
@ -120,7 +119,6 @@ const blackList = [Action.Edit, Action.IncognitoRead, Action.AddToReadingList];
export class EditChapterModalComponent implements OnInit {
protected readonly modal = inject(NgbActiveModal);
private readonly seriesService = inject(SeriesService);
public readonly utilityService = inject(UtilityService);
public readonly imageService = inject(ImageService);
private readonly uploadService = inject(UploadService);
@ -183,7 +181,7 @@ export class EditChapterModalComponent implements OnInit {
this.editForm.addControl('titleName', new FormControl(this.chapter.titleName, []));
this.editForm.addControl('sortOrder', new FormControl(this.chapter.sortOrder, [Validators.required, Validators.min(0)]));
this.editForm.addControl('summary', new FormControl(this.chapter.summary, []));
this.editForm.addControl('summary', new FormControl(this.chapter.summary || '', []));
this.editForm.addControl('language', new FormControl(this.chapter.language, []));
this.editForm.addControl('isbn', new FormControl(this.chapter.isbn, []));
this.editForm.addControl('ageRating', new FormControl(this.chapter.ageRating, []));
@ -251,6 +249,14 @@ export class EditChapterModalComponent implements OnInit {
const selectedIndex = this.editForm.get('coverImageIndex')?.value || 0;
this.chapter.releaseDate = model.releaseDate;
this.chapter.ageRating = model.ageRating as AgeRating;
this.chapter.genres = model.genres;
this.chapter.tags = model.tags;
this.chapter.sortOrder = model.sortOrder;
this.chapter.language = model.language;
this.chapter.titleName = model.titleName;
this.chapter.summary = model.summary;
this.chapter.isbn = model.isbn;
const apis = [

View file

@ -17,7 +17,6 @@ import {EntityTitleComponent} from "../../cards/entity-title/entity-title.compon
import {SettingButtonComponent} from "../../settings/_components/setting-button/setting-button.component";
import {CoverImageChooserComponent} from "../../cards/cover-image-chooser/cover-image-chooser.component";
import {EditChapterProgressComponent} from "../../cards/edit-chapter-progress/edit-chapter-progress.component";
import {EntityInfoCardsComponent} from "../../cards/entity-info-cards/entity-info-cards.component";
import {CompactNumberPipe} from "../../_pipes/compact-number.pipe";
import {IconAndTitleComponent} from "../../shared/icon-and-title/icon-and-title.component";
import {DefaultDatePipe} from "../../_pipes/default-date.pipe";
@ -83,7 +82,6 @@ const blackList = [Action.Edit, Action.IncognitoRead, Action.AddToReadingList];
CoverImageChooserComponent,
EditChapterProgressComponent,
NgbInputDatepicker,
EntityInfoCardsComponent,
CompactNumberPipe,
IconAndTitleComponent,
DefaultDatePipe,

View file

@ -1,15 +1,15 @@
<ng-container *transloco="let t; read:'review-card'">
<div class="card review-card clickable mb-3" (click)="showModal()">
<div class="row g-0">
<div class="col-md-2 d-none d-md-block p-2">
<div class="col-md-2 col-sm-2 col-2 d-block p-2">
@if (isMyReview) {
<i class="d-md-none fa-solid fa-star me-2" aria-hidden="true" [title]="t('your-review')"></i>
<img class="me-2" [ngSrc]="ScrobbleProvider.Kavita | providerImage" width="40" height="40" alt="">
<i class="d-none fa-solid fa-star me-2" aria-hidden="true" [title]="t('your-review')"></i>
<img class="me-2" [ngSrc]="ScrobbleProvider.Kavita | providerImage:true" width="40" height="40" alt="">
} @else {
<img class="me-2" [ngSrc]="review.provider | providerImage" width="40" height="40" alt="">
<img class="me-2" [ngSrc]="review.provider | providerImage:true" width="40" height="40" alt="">
}
</div>
<div class="col-md-10">
<div class="col-md-10 col-sm-10 col-10">
<div class="card-body p-2">
<!--
<h6 class="card-title">

View file

@ -2,22 +2,25 @@
<div class="offcanvas-header">
<h5 class="offcanvas-title">
{{name}}
</h5>
<button type="button" class="btn-close text-reset" [attr.aria-label]="t('common.close')" (click)="close()"></button>
</div>
<div class="offcanvas-body">
<ng-container *ngIf="CoverUrl as coverUrl">
@if (CoverUrl; as coverUrl) {
<div style="width: 160px" class="mx-auto mb-3">
<app-image *ngIf="coverUrl" height="232.91px" width="160px" [styles]="{'object-fit': 'contain', 'max-height': '232.91px'}" [imageUrl]="coverUrl"></app-image>
@if (coverUrl) {
<app-image height="232.91px" width="160px" [styles]="{'object-fit': 'contain', 'max-height': '232.91px'}" [imageUrl]="coverUrl"></app-image>
}
</div>
</ng-container>
}
<ng-container *ngIf="externalSeries; else localSeriesBody">
<div *ngIf="(externalSeries.volumeCount || 0) > 0 || (externalSeries.chapterCount || 0) > 0" class="text-muted muted mb-2">
{{t('series-preview-drawer.vols-and-chapters', {volCount: externalSeries.volumeCount, chpCount: externalSeries.chapterCount})}}
</div>
@if (externalSeries) {
@if ((externalSeries.volumeCount || 0) > 0 || (externalSeries.chapterCount || 0) > 0) {
<div class="text-muted muted mb-2">
{{t('series-preview-drawer.vols-and-chapters', {volCount: externalSeries.volumeCount, chpCount: externalSeries.chapterCount})}}
</div>
}
@if(isExternalSeries && externalSeries) {
<div class="text-muted muted mb-2">
@ -26,14 +29,20 @@
</div>
}
<app-read-more *ngIf="externalSeries.summary" [maxLength]="300" [text]="externalSeries.summary"></app-read-more>
@if (externalSeries.summary) {
<app-read-more [maxLength]="300" [text]="externalSeries.summary"></app-read-more>
}
}
<a class="btn btn-primary col-12 mt-2" [href]="url" target="_blank" rel="noopener noreferrer">
{{t('series-preview-drawer.view-series')}}
</a>
@if (externalSeries) {
<div class="mt-3">
<app-metadata-detail [tags]="externalSeries.genres" [libraryId]="0" [heading]="t('series-preview-drawer.genres-label')">
<ng-template #itemTemplate let-item>
<app-tag-badge>
{{item}}
</app-tag-badge>
<span class="dark-exempt btn-icon not-clickable">{{item}}</span>
</ng-template>
</app-metadata-detail>
</div>
@ -41,25 +50,22 @@
<div class="mt-3">
<app-metadata-detail [tags]="externalSeries.tags" [libraryId]="0" [heading]="t('series-preview-drawer.tags-label')">
<ng-template #itemTemplate let-item>
<app-tag-badge>
{{item.name}}
</app-tag-badge>
<span class="dark-exempt btn-icon not-clickable">{{item.name}}</span>
</ng-template>
</app-metadata-detail>
</div>
<div class="mt-3">
<app-metadata-detail [tags]="externalSeries.staff" [libraryId]="0" [heading]="t('series-preview-drawer.staff-label')">
<app-metadata-detail [tags]="externalSeries.staff" [libraryId]="0" [heading]="t('series-preview-drawer.staff-label')" [includeComma]="false">
<ng-template #itemTemplate let-item>
<div class="card mb-3">
<div class="row g-0">
<div class="col-md-3">
<ng-container *ngIf="item.imageUrl && !item.imageUrl.endsWith('default.jpg'); else localPerson">
@if (item.imageUrl && !item.imageUrl.endsWith('default.jpg')) {
<app-image height="24px" width="24px" [styles]="{'object-fit': 'contain'}" [imageUrl]="item.imageUrl" classes="person-img"></app-image>
</ng-container>
<ng-template #localPerson>
} @else {
<i class="fa fa-user-circle align-self-center person-img" style="font-size: 28px;" aria-hidden="true"></i>
</ng-template>
}
</div>
<div class="col-md-9">
<div class="card-body">
@ -72,67 +78,56 @@
</ng-template>
</app-metadata-detail>
</div>
</ng-container>
}
@else if(localSeries) {
<div class="d-inline-block mb-2 mt-2" style="width: 100%">
<span class="text-muted muted">{{localSeries.publicationStatus | publicationStatus}}</span>
<button class="btn btn-secondary btn-sm float-end me-3"
(click)="toggleWantToRead()"
ngbTooltip="{{wantToRead ? t('series-preview-drawer.remove-from-want-to-read') : t('series-preview-drawer.add-to-want-to-read')}}">
<i class="{{wantToRead ? 'fa-solid' : 'fa-regular'}} fa-star" aria-hidden="true"></i>
</button>
</div>
<ng-template #localSeriesBody>
<ng-container *ngIf="localSeries">
<div class="d-inline-block mb-2" style="width: 100%">
<span class="text-muted muted">{{localSeries.publicationStatus | publicationStatus}}</span>
<button class="btn btn-secondary btn-sm float-end me-3"
(click)="toggleWantToRead()"
ngbTooltip="{{wantToRead ? t('series-preview-drawer.remove-from-want-to-read') : t('series-preview-drawer.add-to-want-to-read')}}">
<i class="{{wantToRead ? 'fa-solid' : 'fa-regular'}} fa-star" aria-hidden="true"></i>
</button>
</div>
<app-read-more [maxLength]="300" [text]="localSeries.summary"></app-read-more>
<app-read-more [maxLength]="300" [text]="localSeries.summary"></app-read-more>
<div class="mt-3">
<app-metadata-detail [tags]="localSeries.genres" [libraryId]="0" [heading]="t('series-preview-drawer.genres-label')">
<ng-template #itemTemplate let-item>
<app-tag-badge>
{{item.title}}
</app-tag-badge>
</ng-template>
</app-metadata-detail>
</div>
<div class="mt-3">
<app-metadata-detail [tags]="localSeries.genres" [libraryId]="0" [heading]="t('series-preview-drawer.genres-label')">
<ng-template #itemTemplate let-item>
<a class="dark-exempt btn-icon not-clickable">{{item.title}}</a>
</ng-template>
</app-metadata-detail>
</div>
<div class="mt-3">
<app-metadata-detail [tags]="localSeries.tags" [libraryId]="0" [heading]="t('series-preview-drawer.tags-label')">
<ng-template #itemTemplate let-item>
<app-tag-badge>
{{item.title}}
</app-tag-badge>
</ng-template>
</app-metadata-detail>
</div>
<div class="mt-3">
<app-metadata-detail [tags]="localSeries.tags" [libraryId]="0" [heading]="t('series-preview-drawer.tags-label')">
<ng-template #itemTemplate let-item>
<span class="dark-exempt btn-icon not-clickable">{{item.title}}</span>
</ng-template>
</app-metadata-detail>
</div>
<div class="mt-3">
<app-metadata-detail [tags]="localStaff" [libraryId]="0" [heading]="t('series-preview-drawer.staff-label')">
<ng-template #itemTemplate let-item>
<div class="card mb-3">
<div class="row g-0">
<div class="col-md-4">
<i class="fa fa-user-circle align-self-center" style="font-size: 28px; margin-top: 24px; margin-left: 24px" aria-hidden="true"></i>
</div>
<div class="col-md-8">
<div class="card-body">
<h6 class="card-title">{{item.name}}</h6>
<p class="card-text" style="font-size: 14px"><small class="text-muted">{{item.role}}</small></p>
</div>
<div class="mt-3">
<app-metadata-detail [tags]="localStaff" [libraryId]="0" [heading]="t('series-preview-drawer.staff-label')" [includeComma]="false">
<ng-template #itemTemplate let-item>
<div class="card mb-3">
<div class="row g-0">
<div class="col-md-4">
<i class="fa fa-user-circle align-self-center" style="font-size: 28px; margin-top: 24px; margin-left: 24px" aria-hidden="true"></i>
</div>
<div class="col-md-8">
<div class="card-body">
<h6 class="card-title">{{item.name}}</h6>
<p class="card-text" style="font-size: 14px"><small class="text-muted">{{item.role}}</small></p>
</div>
</div>
</div>
</ng-template>
</app-metadata-detail>
</div>
</ng-container>
</ng-template>
</div>
</ng-template>
</app-metadata-detail>
</div>
}
<app-loading [loading]="isLoading"></app-loading>
<a class="btn btn-primary col-12 mt-2" [href]="url" target="_blank" rel="noopener noreferrer">
{{t('series-preview-drawer.view-series')}}
</a>
</div>
</ng-container>

View file

@ -15,4 +15,13 @@
a.read-more-link {
white-space: nowrap;
}
}
.not-clickable {
cursor: text;
}
.offcanvas-body {
mask-image: linear-gradient(to bottom, transparent, black 0%, black 95%, transparent 100%);
-webkit-mask-image: linear-gradient(to bottom, transparent, black 0%, black 95%, transparent 100%);
}

View file

@ -1,5 +1,5 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnInit} from '@angular/core';
import {CommonModule, NgOptimizedImage} from '@angular/common';
import {NgOptimizedImage} from '@angular/common';
import {TranslocoDirective} from "@jsverse/transloco";
import {NgbActiveOffcanvas, NgbTooltip} from "@ng-bootstrap/ng-bootstrap";
import {ExternalSeriesDetail, SeriesStaff} from "../../_models/series-detail/external-series-detail";
@ -17,17 +17,26 @@ import {SeriesMetadata} from "../../_models/metadata/series-metadata";
import {ReadMoreComponent} from "../../shared/read-more/read-more.component";
import {ActionService} from "../../_services/action.service";
import {ProviderImagePipe} from "../../_pipes/provider-image.pipe";
import {ScrobbleProvider} from "../../_services/scrobbling.service";
import {FilterField} from "../../_models/metadata/v2/filter-field";
@Component({
selector: 'app-series-preview-drawer',
standalone: true,
imports: [CommonModule, TranslocoDirective, ImageComponent, LoadingComponent, SafeHtmlPipe, A11yClickDirective, MetadataDetailComponent, PersonBadgeComponent, TagBadgeComponent, PublicationStatusPipe, ReadMoreComponent, NgbTooltip, NgOptimizedImage, ProviderImagePipe],
imports: [TranslocoDirective, ImageComponent, LoadingComponent, SafeHtmlPipe, A11yClickDirective, MetadataDetailComponent, PersonBadgeComponent, TagBadgeComponent, PublicationStatusPipe, ReadMoreComponent, NgbTooltip, NgOptimizedImage, ProviderImagePipe],
templateUrl: './series-preview-drawer.component.html',
styleUrls: ['./series-preview-drawer.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SeriesPreviewDrawerComponent implements OnInit {
private readonly activeOffcanvas = inject(NgbActiveOffcanvas);
private readonly seriesService = inject(SeriesService);
private readonly imageService = inject(ImageService);
private readonly actionService = inject(ActionService);
private readonly cdRef = inject(ChangeDetectorRef);
protected readonly FilterField = FilterField;
@Input({required: true}) name!: string;
@Input() aniListId?: number;
@Input() malId?: number;
@ -42,11 +51,7 @@ export class SeriesPreviewDrawerComponent implements OnInit {
url: string = '';
wantToRead: boolean = false;
private readonly activeOffcanvas = inject(NgbActiveOffcanvas);
private readonly seriesService = inject(SeriesService);
private readonly imageService = inject(ImageService);
private readonly actionService = inject(ActionService);
private readonly cdRef = inject(ChangeDetectorRef);
get CoverUrl() {
if (this.isExternalSeries) {