Bugs from UX Overhaul (#3117)

Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo 2024-08-17 18:07:56 -05:00 committed by GitHub
parent 3b915a8289
commit d4bcd354dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 479 additions and 637 deletions

View file

@ -17,7 +17,7 @@
}
<ul class="list-group">
@for(collectionTag of lists | filter: filterList; let i = $index; track collectionTag.title) {
@for(collectionTag of lists | filter: filterList; let i = $index; track collectionTag.title + collectionTag.promoted) {
<li class="list-group-item clickable" tabindex="0" role="option" (click)="addToCollection(collectionTag)">
{{collectionTag.title}}
@if (collectionTag.promoted) {

View file

@ -10,15 +10,16 @@ import {
ViewChild,
ViewEncapsulation
} from '@angular/core';
import {FormGroup, FormControl, ReactiveFormsModule} from '@angular/forms';
import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms';
import {NgbActiveModal, NgbModalModule} from '@ng-bootstrap/ng-bootstrap';
import { ToastrService } from 'ngx-toastr';
import {ToastrService} from 'ngx-toastr';
import {UserCollection} from 'src/app/_models/collection-tag';
import { ReadingList } from 'src/app/_models/reading-list';
import { CollectionTagService } from 'src/app/_services/collection-tag.service';
import {ReadingList} from 'src/app/_models/reading-list';
import {CollectionTagService} from 'src/app/_services/collection-tag.service';
import {CommonModule} from "@angular/common";
import {FilterPipe} from "../../../_pipes/filter.pipe";
import {translate, TranslocoDirective, TranslocoService} from "@jsverse/transloco";
import {translate, TranslocoDirective} from "@jsverse/transloco";
import {ScrobbleProvider} from "../../../_services/scrobbling.service";
@Component({
selector: 'app-bulk-add-to-collection',
@ -60,7 +61,8 @@ export class BulkAddToCollectionComponent implements OnInit, AfterViewInit {
this.loading = true;
this.cdRef.markForCheck();
this.collectionService.allCollections(true).subscribe(tags => {
this.lists = tags;
// Don't allow Smart Collections in
this.lists = tags.filter(t => t.source === ScrobbleProvider.Kavita);
this.loading = false;
this.cdRef.markForCheck();
});

View file

@ -489,85 +489,215 @@
<a ngbNavLink>{{t(tabs[TabID.Info])}}</a>
<ng-template ngbNavContent>
<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 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 class="row g-0">
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('library-title')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{libraryName! | sentenceCase}}
</ng-template>
</app-setting-item>
</div>
</div>
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('format-title')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
<app-tag-badge>{{series.format | mangaFormat}}</app-tag-badge>
</ng-template>
</app-setting-item>
</div>
</div>
</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 mt-3 mb-3" *ngIf="metadata">
<div class="col-md-6">
<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 class="row g-0">
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('folder-path-title')" [subtitle]="t('folder-path-tooltip')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{series.folderPath | defaultValue}}
</ng-template>
</app-setting-item>
</div>
</div>
<div class="col-md-6">
<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 class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('lowest-folder-path-title')" [subtitle]="t('lowest-folder-path-tooltip')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{series.lowestFolderPath | defaultValue}}
</ng-template>
</app-setting-item>
</div>
</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">
<span class="visually-hidden">{{t('loading')}}</span>
</div>
<ul class="list-unstyled" *ngIf="!isLoadingVolumes">
<li class="d-flex my-4" *ngFor="let volume of seriesVolumes">
<app-image class="me-3" style="width: 74px;" width="74px" [imageUrl]="imageService.getVolumeCoverImage(volume.id)"></app-image>
<div class="flex-grow-1">
<h5 class="mt-0 mb-1">{{formatVolumeName(volume)}}</h5>
<div>
<div class="row g-0">
<div class="col">
{{t('added-title')}} {{volume.createdUtc | utcToLocalTime | defaultDate}}
</div>
<div class="col">
{{t('last-modified-title')}} {{volume.lastModifiedUtc | utcToLocalTime | translocoDate: {dateStyle: 'short' } | defaultDate}}
</div>
</div>
<div class="row g-0">
<div class="col">
<button type="button" class="btn btn-outline-primary" (click)="collapse.toggle()"
[attr.aria-expanded]="!volumeCollapsed[volume.name]">
{{t('view-files')}}
</button>
</div>
<div class="col">
{{t('pages-title')}} {{volume.pages}}
</div>
</div>
<div #collapse="ngbCollapse" [(ngbCollapse)]="volumeCollapsed[volume.name]">
<ul class="list-group mt-2">
<li *ngFor="let file of volume.volumeFiles" class="list-group-item">
<span>{{file.filePath}}</span>
<div class="row g-0">
<div class="col">
{{t('chapter-title')}} {{file.chapter}}
</div>
<div class="col">
{{t('pages-title')}} {{file.pages}}
</div>
<div class="col">
{{t('format-title')}} <span class="badge badge-secondary">{{utilityService.mangaFormatToText(file.format)}}</span>
</div>
</div>
</li>
</ul>
</div>
@if (metadata) {
<div class="row g-0">
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('max-items-title')" [subtitle]="t('highest-count-tooltip')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{metadata.maxCount}}
</ng-template>
</app-setting-item>
</div>
</div>
</li>
</ul>
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('total-items-title')" [subtitle]="t('max-issue-tooltip')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{metadata.totalCount}}
</ng-template>
</app-setting-item>
</div>
</div>
</div>
<div class="row g-0">
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('publication-status-title')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{metadata.publicationStatus | publicationStatus}}
</ng-template>
</app-setting-item>
</div>
</div>
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('size-title')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{size | bytes}}
</ng-template>
</app-setting-item>
</div>
</div>
</div>
}
<div class="row g-0">
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('created-title')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{series.created | date:'shortDate'}}
</ng-template>
</app-setting-item>
</div>
</div>
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('last-added-title')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{series.lastChapterAdded | defaultDate | timeAgo}}
</ng-template>
</app-setting-item>
</div>
</div>
</div>
<div class="row g-0">
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('last-scanned-title')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{series.lastFolderScanned | defaultDate | timeAgo}}
</ng-template>
</app-setting-item>
</div>
</div>
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('last-read-title')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{series.lastChapterAdded | defaultDate | timeAgo}}
</ng-template>
</app-setting-item>
</div>
</div>
</div>
<div class="row g-0">
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('total-pages-title')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{series.pages | number}}
</ng-template>
</app-setting-item>
</div>
</div>
<div class="col-lg-6 col-md-12 pe-2">
<div class="mb-3">
<app-setting-item [title]="t('total-words-title')" [toggleOnViewClick]="false" [showEdit]="false">
<ng-template #view>
{{series.wordCount | number}}
</ng-template>
</app-setting-item>
</div>
</div>
</div>
<h4>Volumes</h4>
@if (isLoadingVolumes) {
<div class="spinner-border text-secondary" role="status" *ngIf="isLoadingVolumes">
<span class="visually-hidden">{{t('loading')}}</span>
</div>
} @else {
<ul class="list-unstyled">
@for (volume of seriesVolumes; track volume.id) {
<li class="d-flex my-4">
<app-image class="me-3" style="width: 74px;" width="74px" [imageUrl]="imageService.getVolumeCoverImage(volume.id)"></app-image>
<div class="flex-grow-1">
<h5 class="mt-0 mb-1">{{formatVolumeName(volume)}}</h5>
<div>
<div class="row g-0">
<div class="col">
{{t('added-title')}} {{volume.createdUtc | utcToLocalTime | defaultDate}}
</div>
<div class="col">
{{t('last-modified-title')}} {{volume.lastModifiedUtc | utcToLocalTime | translocoDate: {dateStyle: 'short' } | defaultDate}}
</div>
</div>
<div class="row g-0">
<div class="col">
<button type="button" class="btn btn-outline-primary" (click)="collapse.toggle()"
[attr.aria-expanded]="!volumeCollapsed[volume.name]">
{{t('view-files')}}
</button>
</div>
<div class="col">
{{t('pages-title')}} {{volume.pages}}
</div>
</div>
<div #collapse="ngbCollapse" [(ngbCollapse)]="volumeCollapsed[volume.name]">
<ul class="list-group mt-2">
@for(file of volume.volumeFiles; track file.id) {
<li class="list-group-item">
<span>{{file.filePath}}</span>
<div class="row g-0">
<div class="col">
{{t('chapter-title')}} {{file.chapter}}
</div>
<div class="col">
{{t('pages-title')}} {{file.pages}}
</div>
<div class="col">
{{t('format-title')}} <span class="badge badge-secondary">{{utilityService.mangaFormatToText(file.format)}}</span>
</div>
</div>
</li>
}
</ul>
</div>
</div>
</div>
</li>
}
</ul>
}
</ng-template>
</li>

View file

@ -54,7 +54,6 @@ import {TranslocoDatePipe} from "@jsverse/transloco-locale";
import {UtcToLocalTimePipe} from "../../../_pipes/utc-to-local-time.pipe";
import {EditListComponent} from "../../../shared/edit-list/edit-list.component";
import {AccountService} from "../../../_services/account.service";
import {LibraryType} from "../../../_models/library/library";
import {ToastrService} from "ngx-toastr";
import {Volume} from "../../../_models/volume";
import {Action, ActionFactoryService, ActionItem} from "../../../_services/action-factory.service";
@ -62,6 +61,7 @@ import {SettingButtonComponent} from "../../../settings/_components/setting-butt
import {ActionService} from "../../../_services/action.service";
import {DownloadService} from "../../../shared/_services/download.service";
import {SettingItemComponent} from "../../../settings/_components/setting-item/setting-item.component";
import {ReadTimePipe} from "../../../_pipes/read-time.pipe";
enum TabID {
General = 0,
@ -116,6 +116,7 @@ const blackList = [Action.Edit, Action.Info, Action.IncognitoRead, Action.Read,
EditListComponent,
SettingButtonComponent,
SettingItemComponent,
ReadTimePipe,
],
templateUrl: './edit-series-modal.component.html',
styleUrls: ['./edit-series-modal.component.scss'],

View file

@ -25,7 +25,7 @@
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 158px);
grid-template-columns: repeat(auto-fill, 160px);
grid-gap: 0.5rem;
justify-content: space-between;
width: 100%;

View file

@ -2,9 +2,9 @@
<div class="card-item-container card {{selected ? 'selected-highlight' : ''}}">
<div class="overlay" (click)="handleClick($event)">
@if (total > 0 || suppressArchiveWarning) {
<app-image height="230px" width="158px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageUrl"></app-image>
<app-image height="232.91px" width="160px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageUrl"></app-image>
} @else if (total === 0 && !suppressArchiveWarning) {
<app-image height="230px" width="158px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.errorImage"></app-image>
<app-image height="232.91px" width="160px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.errorImage"></app-image>
}
<div class="progress-banner">

View file

@ -2,9 +2,9 @@
<div class="card-item-container card position-relative {{selected ? 'selected-highlight' : ''}}" >
<div class="overlay" (click)="handleClick($event)">
@if (chapter.pages > 0 || suppressArchiveWarning) {
<app-image height="230px" width="158px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.getChapterCoverImage(chapter.id)"></app-image>
<app-image height="232.91px" width="160px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.getChapterCoverImage(chapter.id)"></app-image>
} @else if (chapter.pages === 0 && !suppressArchiveWarning) {
<app-image height="230px" width="158px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.errorImage"></app-image>
<app-image height="232.91px" width="160px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.errorImage"></app-image>
}
<div class="progress-banner">

View file

@ -55,7 +55,7 @@
<div class="clickable col-auto"
*ngIf="showReset" tabindex="0" (click)="reset()"
[ngClass]="{'selected': !showApplyButton && selectedIndex === -1}">
<app-image class="card-img-top" [title]="t('reset-cover-tooltip')" height="230px" width="158px" [imageUrl]="imageService.resetCoverImage"></app-image>
<app-image class="card-img-top" [title]="t('reset-cover-tooltip')" height="232.91px" width="160px" [imageUrl]="imageService.resetCoverImage"></app-image>
<ng-container *ngIf="showApplyButton">
<br>
<button style="width: 100%;" class="btn btn-secondary" (click)="resetImage()">{{t('reset')}}</button>
@ -65,7 +65,7 @@
<div class="clickable col-auto"
*ngFor="let url of imageUrls; let idx = index;" tabindex="0" [attr.aria-label]="t('image-num', {num: idx + 1})" (click)="selectImage(idx)"
[ngClass]="{'selected': !showApplyButton && selectedIndex === idx}">
<app-image class="card-img-top" height="230px" width="158px" [imageUrl]="url" [processEvents]="idx > 0"></app-image>
<app-image class="card-img-top" height="232.91px" width="160px" [imageUrl]="url" [processEvents]="idx > 0"></app-image>
<ng-container *ngIf="showApplyButton">
<br>
<button class="btn btn-primary" style="width: 100%;"

View file

@ -16,7 +16,7 @@ $image-width: 160px;
.chooser {
display: grid;
grid-template-columns: repeat(auto-fill, 158px);
grid-template-columns: repeat(auto-fill, 160px);
grid-gap: 0.5rem;
justify-content: space-around;
}

View file

@ -20,12 +20,12 @@ export class ExternalListItemComponent {
@Input() imageUrl: string = '';
/**
* Size of the Image Height. Defaults to 230px.
* Size of the Image Height. Defaults to 232.91px.
*/
@Input() imageHeight: string = '230px';
@Input() imageHeight: string = '232.91px';
/**
* Size of the Image Width Defaults to 158px.
* Size of the Image Width Defaults to 160px.
*/
@Input() imageWidth: string = '158px';
@Input() imageWidth: string = '160px';
@Input() summary: string | null = '';
}

View file

@ -3,7 +3,7 @@
<div class="card-item-container card clickable position-relative">
<div class="overlay" (click)="handleClick()">
<ng-container>
<app-image [styles]="{'border-radius': '.25rem .25rem 0 0'}" height="230px" width="158px" [imageUrl]="data.coverUrl"></app-image>
<app-image [styles]="{'border-radius': '.25rem .25rem 0 0'}" height="232.91px" width="160px" [imageUrl]="data.coverUrl"></app-image>
</ng-container>

View file

@ -61,13 +61,13 @@ export class ListItemComponent implements OnInit {
@Input() seriesName: string = '';
/**
* Size of the Image Height. Defaults to 230px.
* Size of the Image Height. Defaults to 232.91px.
*/
@Input() imageHeight: string = '230px';
@Input() imageHeight: string = '232.91px';
/**
* Size of the Image Width Defaults to 158px.
* Size of the Image Width Defaults to 160px.
*/
@Input() imageWidth: string = '158px';
@Input() imageWidth: string = '160px';
@Input() seriesLink: string = '';
@Input() pagesRead: number = 0;

View file

@ -1,6 +1,6 @@
<div class="card-item-container card">
<div class="overlay">
<app-image [styles]="{'border-radius': '.25rem .25rem 0 0'}" height="230px" width="158px" classes="extreme-blur"
<app-image [styles]="{'border-radius': '.25rem .25rem 0 0'}" height="232.91px" width="160px" classes="extreme-blur"
[imageUrl]="imageUrl"></app-image>
<div class="card-overlay"></div>

View file

@ -2,9 +2,9 @@
<div class="card-item-container card position-relative {{selected ? 'selected-highlight' : ''}}">
<div class="overlay" (click)="handleClick()">
@if (series.pages > 0) {
<app-image height="230px" width="158px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.getSeriesCoverImage(series.id)"></app-image>
<app-image height="232.91px" width="160px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.getSeriesCoverImage(series.id)"></app-image>
} @else if (series.pages === 0) {
<app-image height="230px" width="158px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.errorImage"></app-image>
<app-image height="232.91px" width="160px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.errorImage"></app-image>
}
<div class="progress-banner">

View file

@ -2,9 +2,9 @@
<div class="card-item-container card {{selected ? 'selected-highlight' : ''}}" >
<div class="overlay position-relative" (click)="handleClick($event)">
@if (volume.pages > 0 || suppressArchiveWarning) {
<app-image height="230px" width="158px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.getVolumeCoverImage(volume.id)"></app-image>
<app-image height="232.91px" width="160px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.getVolumeCoverImage(volume.id)"></app-image>
} @else if (volume.pages === 0 && !suppressArchiveWarning) {
<app-image height="230px" width="158px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.errorImage"></app-image>
<app-image height="232.91px" width="160px" [styles]="{'border-radius': '.25rem .25rem 0 0'}" [imageUrl]="imageService.errorImage"></app-image>
}
<div class="progress-banner">
@ -50,11 +50,13 @@
</div>
</div>
<div class="card-body meta-title">
<div class="card-content d-flex justify-content-center align-items-center text-center" style="width:100%;min-height:58px;">
{{volume.name}}
@if (libraryType === LibraryType.LightNovel || libraryType === LibraryType.Book) {
<div class="card-body meta-title">
<div class="card-content d-flex justify-content-center align-items-center text-center" style="width:100%;min-height:58px;">
{{volume.name}}
</div>
</div>
</div>
}
<div class="card-title-container">
<span class="card-title" id="{{volume.id}}" tabindex="0">

View file

@ -216,4 +216,5 @@ export class VolumeCardComponent implements OnInit {
this.readerService.readVolume(this.libraryId, this.seriesId, this.volume, false);
}
protected readonly LibraryType = LibraryType;
}