UX Overhaul Part 2 (#3112)
Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
parent
0247bc5012
commit
3d8aa2ad24
192 changed files with 14808 additions and 1874 deletions
178
UI/Web/src/app/volume-detail/volume-detail.component.html
Normal file
178
UI/Web/src/app/volume-detail/volume-detail.component.html
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
<ng-container *transloco="let t; read: 'series-detail'">
|
||||
|
||||
<div [ngStyle]="{'height': ScrollingBlockHeight}" class="main-container container-fluid" #scrollingBlock>
|
||||
|
||||
@if (volume && series && libraryType !== null) {
|
||||
<div class="row mb-0 mb-xl-3 info-container">
|
||||
<div class="image-container col-5 col-sm-6 col-md-5 col-lg-5 col-xl-2 col-xxl-2 col-xxxl-2 d-none d-sm-block mb-3">
|
||||
|
||||
<app-image [styles]="{'object-fit': 'contain', 'background': 'none', 'max-height': '400px'}" [imageUrl]="coverImage"></app-image>
|
||||
@if (volume.pagesRead < volume.pages && hasReadingProgress) {
|
||||
<div class="progress-banner" ngbTooltip="{{(volume.pagesRead / volume.pages) * 100 | number:'1.0-1'}}%">
|
||||
<ngb-progressbar type="primary" height="5px" [value]="volume.pagesRead" [max]="volume.pages" [showValue]="true"></ngb-progressbar>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-xl-10 col-lg-7 col-md-7 col-xs-8 col-sm-6">
|
||||
<h4 class="title mb-2">
|
||||
<a routerLink="/library/{{series.libraryId}}/series/{{series.id}}" class="dark-exempt btn-icon">{{series.name}}</a>
|
||||
</h4>
|
||||
<div class="subtitle mt-2 mb-2">
|
||||
<span>
|
||||
{{t('volume-num')}}
|
||||
<app-entity-title [libraryType]="libraryType!" [entity]="volume" [prioritizeTitleName]="true"></app-entity-title>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<app-metadata-detail-row [entity]="volumeCast"
|
||||
[ageRating]="maxAgeRating"
|
||||
[hasReadingProgress]="hasReadingProgress"
|
||||
[readingTimeEntity]="volume"
|
||||
[libraryType]="libraryType">
|
||||
</app-metadata-detail-row>
|
||||
|
||||
<!-- Rating goes here (after I implement support for rating individual issues -->
|
||||
<!-- @if (libraryType !== null && series) {-->
|
||||
<!-- <div class="mt-2 mb-2">-->
|
||||
<!-- <app-external-rating [seriesId]="series.id"-->
|
||||
<!-- [ratings]="[]"-->
|
||||
<!-- [userRating]="series.userRating"-->
|
||||
<!-- [hasUserRated]="series.hasUserRated"-->
|
||||
<!-- [libraryType]="libraryType">-->
|
||||
<!-- </app-external-rating>-->
|
||||
<!-- </div>-->
|
||||
<!-- }-->
|
||||
|
||||
<div class="mt-2 mb-3">
|
||||
<div class="row g-0">
|
||||
<div class="col-auto">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary-outline" (click)="readVolume()">
|
||||
<span>
|
||||
<i class="fa {{hasReadingProgress ? 'fa-book-open' : 'fa-book'}}" aria-hidden="true"></i>
|
||||
<span class="read-btn--text"> {{(hasReadingProgress) ? t('continue') : t('read')}}</span>
|
||||
</span>
|
||||
</button>
|
||||
<div class="btn-group" ngbDropdown role="group" display="dynamic" [attr.aria-label]="t('read-options-alt')">
|
||||
<button type="button" class="btn btn-primary-outline dropdown-toggle-split" ngbDropdownToggle></button>
|
||||
<div class="dropdown-menu" ngbDropdownMenu>
|
||||
<button ngbDropdownItem (click)="readVolume(true)">
|
||||
<span>
|
||||
<i class="fa fa-glasses" aria-hidden="true"></i>
|
||||
<span class="read-btn--text"> {{(hasReadingProgress) ? t('continue-incognito') : t('read-incognito')}}</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@if (accountService.isAdmin$ | async) {
|
||||
<div class="col-auto ms-2">
|
||||
<button class="btn btn-secondary-outline" (click)="openEditModal()" [ngbTooltip]="t('edit-series-alt')">
|
||||
<span><i class="fa fa-pen" aria-hidden="true"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="col-auto ms-2 d-none d-md-block">
|
||||
<app-download-button [download$]="download$" [entity]="volume" entityType="volume"></app-download-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-2 mb-3">
|
||||
<app-read-more [text]="volume.chapters[0].summary || ''"></app-read-more>
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<div class="row g-0">
|
||||
<div class="col-6">
|
||||
<span>{{t('writers-title')}}</span>
|
||||
<div>
|
||||
<app-badge-expander [items]="volumeCast.writers">
|
||||
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
||||
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="openPerson(FilterField.Writers, item.id)">{{item.name}}</a>
|
||||
@if (!last) {
|
||||
,
|
||||
}
|
||||
</ng-template>
|
||||
</app-badge-expander>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<span>{{t('cover-artists-title')}}</span>
|
||||
<div>
|
||||
<app-badge-expander [items]="volumeCast.coverArtists">
|
||||
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
||||
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="openPerson(FilterField.CoverArtist, item.id)">{{item.name}}</a>
|
||||
@if (!last) {
|
||||
,
|
||||
}
|
||||
</ng-template>
|
||||
</app-badge-expander>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="carousel-tabs-container">
|
||||
<ul ngbNav #nav="ngbNav" [(activeId)]="activeTabId" class="nav nav-tabs mb-2" (navChange)="onNavChange($event)">
|
||||
<li [ngbNavItem]="TabID.Chapters">
|
||||
<a ngbNavLink>
|
||||
{{utilityService.formatChapterName(libraryType!, false, false, true)}}
|
||||
<span class="badge rounded-pill text-bg-secondary">{{volume.chapters.length}}</span>
|
||||
</a>
|
||||
<ng-template ngbNavContent>
|
||||
@defer (when activeTabId === TabID.Chapters; prefetch on idle) {
|
||||
<virtual-scroller #scroll [items]="volume.chapters" [bufferAmount]="1" [parentScroll]="scrollingBlock" [childHeight]="1">
|
||||
<div class="card-container row g-0" #container>
|
||||
@for(item of scroll.viewPortItems; let idx = $index; track item.id + '_' + item.pagesRead) {
|
||||
<app-chapter-card class="col-auto mt-2 mb-2" [chapter]="item" [seriesId]="seriesId" [libraryId]="libraryId" [libraryType]="libraryType"></app-chapter-card>
|
||||
}
|
||||
</div>
|
||||
</virtual-scroller>
|
||||
}
|
||||
</ng-template>
|
||||
</li>
|
||||
|
||||
@if (volume.chapters.length === 1 && readingLists.length > 0) {
|
||||
<li [ngbNavItem]="TabID.Related">
|
||||
<a ngbNavLink>{{t('related-tab')}}</a>
|
||||
<ng-template ngbNavContent>
|
||||
@defer (when activeTabId === TabID.Related; prefetch on idle) {
|
||||
<app-related-tab [readingLists]="readingLists"></app-related-tab>
|
||||
}
|
||||
</ng-template>
|
||||
</li>
|
||||
}
|
||||
|
||||
@if (showDetailsTab) {
|
||||
<li [ngbNavItem]="TabID.Details">
|
||||
<a ngbNavLink>{{t('details-tab')}}</a>
|
||||
<ng-template ngbNavContent>
|
||||
@defer (when activeTabId === TabID.Details; prefetch on idle) {
|
||||
<app-details-tab [metadata]="volumeCast" [genres]="genres" [tags]="tags"></app-details-tab>
|
||||
}
|
||||
</ng-template>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
<!-- Min height helps with scroll jerking when switching from chapter -> related/details -->
|
||||
<div [ngbNavOutlet]="nav" style="min-height: 300px"></div>
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
<app-loading [loading]="isLoading"></app-loading>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
Loading…
Add table
Add a link
Reference in a new issue