UX Pass 7 (#3135)
Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
parent
5bf5558212
commit
79eb98a3bb
67 changed files with 1398 additions and 1006 deletions
|
|
@ -1,36 +1,39 @@
|
|||
<ng-container *transloco="let t; read: 'all-collections'">
|
||||
<app-side-nav-companion-bar [hasFilter]="false" (filterOpen)="filterOpen.emit($event)">
|
||||
<h4 title>{{t('title')}}</h4>
|
||||
<h5 subtitle>{{t('item-count', {num: collections.length | number})}}</h5>
|
||||
</app-side-nav-companion-bar>
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
||||
<div class="main-container container-fluid">
|
||||
<ng-container *transloco="let t; read: 'all-collections'">
|
||||
<app-side-nav-companion-bar [hasFilter]="false" (filterOpen)="filterOpen.emit($event)">
|
||||
<h4 title>{{t('title')}}</h4>
|
||||
<h5 subtitle>{{t('item-count', {num: collections.length | number})}}</h5>
|
||||
</app-side-nav-companion-bar>
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
||||
|
||||
<app-card-detail-layout
|
||||
[isLoading]="isLoading"
|
||||
[items]="collections"
|
||||
[filterOpen]="filterOpen"
|
||||
[jumpBarKeys]="jumpbarKeys"
|
||||
[trackByIdentity]="trackByIdentity"
|
||||
>
|
||||
<ng-template #cardItem let-item let-position="idx">
|
||||
<app-card-item [title]="item.title" [entity]="item" [actions]="collectionTagActions"
|
||||
[imageUrl]="imageService.getCollectionCoverImage(item.id)"
|
||||
(clicked)="loadCollection(item)"
|
||||
(selection)="bulkSelectionService.handleCardSelection('collection', position, collections.length, $event)"
|
||||
[selected]="bulkSelectionService.isCardSelected('collection', position)" [allowSelection]="true">
|
||||
<app-card-detail-layout
|
||||
[isLoading]="isLoading"
|
||||
[items]="collections"
|
||||
[filterOpen]="filterOpen"
|
||||
[jumpBarKeys]="jumpbarKeys"
|
||||
[trackByIdentity]="trackByIdentity"
|
||||
>
|
||||
<ng-template #cardItem let-item let-position="idx">
|
||||
<app-card-item [title]="item.title" [entity]="item" [actions]="collectionTagActions"
|
||||
[imageUrl]="imageService.getCollectionCoverImage(item.id)"
|
||||
[linkUrl]="'/collections/' + item.id"
|
||||
(clicked)="loadCollection(item)"
|
||||
(selection)="bulkSelectionService.handleCardSelection('collection', position, collections.length, $event)"
|
||||
[selected]="bulkSelectionService.isCardSelected('collection', position)" [allowSelection]="true">
|
||||
|
||||
<ng-template #subtitle>
|
||||
<app-collection-owner [collection]="item"></app-collection-owner>
|
||||
</ng-template>
|
||||
</app-card-item>
|
||||
</ng-template>
|
||||
<ng-template #subtitle>
|
||||
<app-collection-owner [collection]="item"></app-collection-owner>
|
||||
</ng-template>
|
||||
</app-card-item>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #noData>
|
||||
{{t('no-data')}}
|
||||
@if(accountService.isAdmin$ | async) {
|
||||
{{t('create-one-part-1')}} <a [href]="WikiLink.Collections" rel="noopener noreferrer" target="_blank">{{t('create-one-part-2')}}<i class="fa fa-external-link-alt ms-1" aria-hidden="true"></i></a>
|
||||
}
|
||||
</ng-template>
|
||||
</app-card-detail-layout>
|
||||
<ng-template #noData>
|
||||
{{t('no-data')}}
|
||||
@if(accountService.isAdmin$ | async) {
|
||||
{{t('create-one-part-1')}} <a [href]="WikiLink.Collections" rel="noopener noreferrer" target="_blank">{{t('create-one-part-2')}}<i class="fa fa-external-link-alt ms-1" aria-hidden="true"></i></a>
|
||||
}
|
||||
</ng-template>
|
||||
</app-card-detail-layout>
|
||||
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
.main-container {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
|
@ -1,74 +1,76 @@
|
|||
<ng-container *transloco="let t; read: 'collection-detail'">
|
||||
<div #companionBar>
|
||||
<app-side-nav-companion-bar *ngIf="series !== undefined" [hasFilter]="true" (filterOpen)="filterOpen.emit($event)" [filterActive]="filterActive">
|
||||
<ng-container title>
|
||||
<h4 *ngIf="collectionTag !== undefined">
|
||||
{{collectionTag.title}}<span class="ms-1" *ngIf="collectionTag.promoted">(<i aria-hidden="true" class="fa fa-angle-double-up"></i>)</span>
|
||||
<app-card-actionables [disabled]="actionInProgress" (actionHandler)="performAction($event)" [actions]="collectionTagActions" [labelBy]="collectionTag.title" iconClass="fa-ellipsis-v"></app-card-actionables>
|
||||
</h4>
|
||||
</ng-container>
|
||||
</app-side-nav-companion-bar>
|
||||
</div>
|
||||
<div class="main-container container-fluid">
|
||||
<ng-container *transloco="let t; read: 'collection-detail'">
|
||||
<div #companionBar>
|
||||
<app-side-nav-companion-bar *ngIf="series !== undefined" [hasFilter]="true" (filterOpen)="filterOpen.emit($event)" [filterActive]="filterActive">
|
||||
<ng-container title>
|
||||
<h4 *ngIf="collectionTag !== undefined">
|
||||
{{collectionTag.title}}<span class="ms-1" *ngIf="collectionTag.promoted">(<i aria-hidden="true" class="fa fa-angle-double-up"></i>)</span>
|
||||
<app-card-actionables [disabled]="actionInProgress" (actionHandler)="performAction($event)" [actions]="collectionTagActions" [labelBy]="collectionTag.title" iconClass="fa-ellipsis-v"></app-card-actionables>
|
||||
</h4>
|
||||
</ng-container>
|
||||
</app-side-nav-companion-bar>
|
||||
</div>
|
||||
|
||||
<div [ngStyle]="{'height': ScrollingBlockHeight}" class="main-container container-fluid pt-2" *ngIf="collectionTag !== undefined" #scrollingBlock>
|
||||
@if (summary.length > 0 || collectionTag.source !== ScrobbleProvider.Kavita) {
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-2 col-xs-4 col-sm-6 d-none d-sm-block">
|
||||
<app-image [styles]="{'max-width': '481px'}" [imageUrl]="imageService.getCollectionCoverImage(collectionTag.id)"></app-image>
|
||||
@if (collectionTag.source !== ScrobbleProvider.Kavita && collectionTag.missingSeriesFromSource !== null
|
||||
&& series.length !== collectionTag.totalSourceCount && collectionTag.totalSourceCount > 0) {
|
||||
<div class="under-image">
|
||||
<app-image [imageUrl]="collectionTag.source | providerImage"
|
||||
width="16px" height="16px"
|
||||
[ngbTooltip]="collectionTag.source | providerName" 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>
|
||||
}
|
||||
<div [ngStyle]="{'height': ScrollingBlockHeight}" class="main-container container-fluid pt-2" *ngIf="collectionTag !== undefined" #scrollingBlock>
|
||||
@if (summary.length > 0 || collectionTag.source !== ScrobbleProvider.Kavita) {
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-2 col-xs-4 col-sm-6 d-none d-sm-block">
|
||||
<app-image [styles]="{'max-width': '481px'}" [imageUrl]="imageService.getCollectionCoverImage(collectionTag.id)"></app-image>
|
||||
@if (collectionTag.source !== ScrobbleProvider.Kavita && collectionTag.missingSeriesFromSource !== null
|
||||
&& series.length !== collectionTag.totalSourceCount && collectionTag.totalSourceCount > 0) {
|
||||
<div class="under-image">
|
||||
<app-image [imageUrl]="collectionTag.source | providerImage"
|
||||
width="16px" height="16px"
|
||||
[ngbTooltip]="collectionTag.source | providerName" 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>
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-10 col-xs-8 col-sm-6 mt-2">
|
||||
@if (summary.length > 0) {
|
||||
<div class="mb-2">
|
||||
<app-read-more [text]="summary" [maxLength]="(utilityService.activeBreakpoint$ | async)! >= Breakpoint.Desktop ? 585 : 200"></app-read-more>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-md-10 col-xs-8 col-sm-6 mt-2">
|
||||
@if (summary.length > 0) {
|
||||
<div class="mb-2">
|
||||
<app-read-more [text]="summary" [maxLength]="utilityService.getActiveBreakpoint() < Breakpoint.Tablet ? 250 : 600"></app-read-more>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
||||
|
||||
<app-card-detail-layout *ngIf="filter"
|
||||
[header]="t('series-header')"
|
||||
[isLoading]="isLoading"
|
||||
[items]="series"
|
||||
[pagination]="pagination"
|
||||
[filterSettings]="filterSettings"
|
||||
[filterOpen]="filterOpen"
|
||||
[parentScroll]="scrollingBlock"
|
||||
[trackByIdentity]="trackByIdentity"
|
||||
[jumpBarKeys]="jumpbarKeys"
|
||||
(applyFilter)="updateFilter($event)">
|
||||
<ng-template #cardItem let-item let-position="idx">
|
||||
<app-series-card [series]="item" [libraryId]="item.libraryId" (reload)="loadPage()"
|
||||
(selection)="bulkSelectionService.handleCardSelection('series', position, series.length, $event)" [selected]="bulkSelectionService.isCardSelected('series', position)" [allowSelection]="true"
|
||||
></app-series-card>
|
||||
</ng-template>
|
||||
|
||||
<div *ngIf="!filterActive && series.length === 0">
|
||||
<ng-template #noData>
|
||||
{{t('no-data')}}
|
||||
</ng-template>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
||||
|
||||
<app-card-detail-layout *ngIf="filter"
|
||||
[header]="t('series-header')"
|
||||
[isLoading]="isLoading"
|
||||
[items]="series"
|
||||
[pagination]="pagination"
|
||||
[filterSettings]="filterSettings"
|
||||
[filterOpen]="filterOpen"
|
||||
[parentScroll]="scrollingBlock"
|
||||
[trackByIdentity]="trackByIdentity"
|
||||
[jumpBarKeys]="jumpbarKeys"
|
||||
(applyFilter)="updateFilter($event)">
|
||||
<ng-template #cardItem let-item let-position="idx">
|
||||
<app-series-card [series]="item" [libraryId]="item.libraryId" (reload)="loadPage()"
|
||||
(selection)="bulkSelectionService.handleCardSelection('series', position, series.length, $event)" [selected]="bulkSelectionService.isCardSelected('series', position)" [allowSelection]="true"
|
||||
></app-series-card>
|
||||
</ng-template>
|
||||
|
||||
<div *ngIf="!filterActive && series.length === 0">
|
||||
<ng-template #noData>
|
||||
{{t('no-data')}}
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<div *ngIf="filterActive && series.length === 0">
|
||||
<ng-template #noData>
|
||||
{{t('no-data-filtered')}}
|
||||
</ng-template>
|
||||
</div>
|
||||
</app-card-detail-layout>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div *ngIf="filterActive && series.length === 0">
|
||||
<ng-template #noData>
|
||||
{{t('no-data-filtered')}}
|
||||
</ng-template>
|
||||
</div>
|
||||
</app-card-detail-layout>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {DatePipe, DOCUMENT, NgIf, NgStyle} from '@angular/common';
|
||||
import {AsyncPipe, DatePipe, DOCUMENT, NgIf, NgStyle} from '@angular/common';
|
||||
import {
|
||||
AfterContentChecked,
|
||||
ChangeDetectionStrategy,
|
||||
|
|
@ -67,7 +67,7 @@ import {ProviderNamePipe} from "../../../_pipes/provider-name.pipe";
|
|||
styleUrls: ['./collection-detail.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [NgIf, SideNavCompanionBarComponent, CardActionablesComponent, NgStyle, ImageComponent, ReadMoreComponent, BulkOperationsComponent, CardDetailLayoutComponent, SeriesCardComponent, TranslocoDirective, NgbTooltip, SafeHtmlPipe, TranslocoDatePipe, DatePipe, DefaultDatePipe, ProviderImagePipe, ProviderNamePipe]
|
||||
imports: [NgIf, SideNavCompanionBarComponent, CardActionablesComponent, NgStyle, ImageComponent, ReadMoreComponent, BulkOperationsComponent, CardDetailLayoutComponent, SeriesCardComponent, TranslocoDirective, NgbTooltip, SafeHtmlPipe, TranslocoDatePipe, DatePipe, DefaultDatePipe, ProviderImagePipe, ProviderNamePipe, AsyncPipe]
|
||||
})
|
||||
export class CollectionDetailComponent implements OnInit, AfterContentChecked {
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue