Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo 2024-08-29 08:46:17 -05:00 committed by GitHub
parent 5bf5558212
commit 79eb98a3bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
67 changed files with 1398 additions and 1006 deletions

View file

@ -1,166 +1,168 @@
<ng-container *transloco="let t; read: 'reading-list-detail'">
<app-side-nav-companion-bar [hasExtras]="readingList !== undefined" [extraDrawer]="extrasDrawer">
<h4 title>
{{readingList?.title}}
@if (readingList?.promoted) {
<span class="ms-1">(<i class="fa fa-angle-double-up" aria-hidden="true"></i>)</span>
}
@if (actions.length > 0) {
<app-card-actionables (actionHandler)="performAction($event)" [actions]="actions" [attr.aria-labelledby]="readingList?.title"></app-card-actionables>
}
</h4>
<h5 subtitle class="subtitle-with-actionables">{{t('item-count', {num: items.length | number})}}</h5>
<div class="main-container container-fluid">
<ng-container *transloco="let t; read: 'reading-list-detail'">
<app-side-nav-companion-bar [hasExtras]="readingList !== undefined" [extraDrawer]="extrasDrawer">
<h4 title>
{{readingList?.title}}
@if (readingList?.promoted) {
<span class="ms-1">(<i class="fa fa-angle-double-up" aria-hidden="true"></i>)</span>
}
@if (actions.length > 0) {
<app-card-actionables (actionHandler)="performAction($event)" [actions]="actions" [attr.aria-labelledby]="readingList?.title"></app-card-actionables>
}
</h4>
<h5 subtitle class="subtitle-with-actionables">{{t('item-count', {num: items.length | number})}}</h5>
<ng-template #extrasDrawer let-offcanvas>
@if (readingList) {
<div>
<div class="offcanvas-header">
<h4 class="offcanvas-title" id="offcanvas-basic-title">{{t('page-settings-title')}}</h4>
<button type="button" class="btn-close" aria-label="Close" (click)="offcanvas.dismiss()"></button>
<ng-template #extrasDrawer let-offcanvas>
@if (readingList) {
<div>
<div class="offcanvas-header">
<h4 class="offcanvas-title" id="offcanvas-basic-title">{{t('page-settings-title')}}</h4>
<button type="button" class="btn-close" aria-label="Close" (click)="offcanvas.dismiss()"></button>
</div>
<div class="offcanvas-body">
<div class="row g-0">
<div class="col-md-12 col-sm-12 pe-2 mb-3">
<button class="btn btn-danger" (click)="removeRead()" [disabled]="readingList.promoted && !this.isAdmin">
<span>
<i class="fa fa-check"></i>
</span>
<span class="read-btn--text">&nbsp;{{t('remove-read')}}</span>
</button>
@if (!(readingList.promoted && !this.isAdmin)) {
<div class="col-auto ms-2 mt-2">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="accessibility-mode" [disabled]="this.utilityService.getActiveBreakpoint() < Breakpoint.Tablet" [value]="accessibilityMode" (change)="updateAccessibilityMode()">
<label class="form-check-label" for="accessibility-mode">{{t('order-numbers-label')}}</label>
</div>
</div>
}
</div>
</div>
</div>
</div>
<div class="offcanvas-body">
<div class="row g-0">
<div class="col-md-12 col-sm-12 pe-2 mb-3">
<button class="btn btn-danger" (click)="removeRead()" [disabled]="readingList.promoted && !this.isAdmin">
<span>
<i class="fa fa-check"></i>
</span>
<span class="read-btn--text">&nbsp;{{t('remove-read')}}</span>
</button>
}
</ng-template>
</app-side-nav-companion-bar>
@if (!(readingList.promoted && !this.isAdmin)) {
<div class="col-auto ms-2 mt-2">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="accessibility-mode" [disabled]="this.utilityService.getActiveBreakpoint() < Breakpoint.Tablet" [value]="accessibilityMode" (change)="updateAccessibilityMode()">
<label class="form-check-label" for="accessibility-mode">{{t('order-numbers-label')}}</label>
@if (readingList) {
<div class="container-fluid mt-2">
<div class="row mb-2">
<div class="col-md-2 col-xs-4 col-sm-6 d-none d-sm-block">
<app-image [styles]="{'max-height': '400px', 'max-width': '300px'}" [imageUrl]="imageService.getReadingListCoverImage(readingList.id)"></app-image>
</div>
<div class="col-md-10 col-xs-8 col-sm-6 mt-2">
<div class="row g-0 mb-3">
<div class="col-auto me-2">
<!-- Action row-->
<div class="btn-group me-3">
<button type="button" class="btn btn-primary" (click)="continue()">
<span>
<i class="fa fa-book-open me-1" aria-hidden="true"></i>
<span class="read-btn--text">{{t('continue')}}</span>
</span>
</button>
<div class="btn-group" ngbDropdown role="group" [attr.aria-label]="t('read-options-alt')">
<button type="button" class="btn btn-primary dropdown-toggle-split" ngbDropdownToggle></button>
<div class="dropdown-menu" ngbDropdownMenu>
<button ngbDropdownItem (click)="read()">
<span>
<i class="fa fa-book" aria-hidden="true"></i>
<span class="read-btn--text">&nbsp;{{t('read')}}</span>
</span>
</button>
<button ngbDropdownItem (click)="continue(true)">
<span>
<i class="fa fa-book-open me-1" aria-hidden="true"></i>
<span class="read-btn--text">{{t('continue')}}</span>
(<i class="fa fa-glasses ms-1" aria-hidden="true"></i>)
<span class="visually-hidden">{{t('incognito-alt')}}</span>
</span>
</button>
<button ngbDropdownItem (click)="read(true)">
<span>
<i class="fa fa-book me-1" aria-hidden="true"></i>
<span class="read-btn--text">&nbsp;{{t('read')}}</span>
(<i class="fa fa-glasses ms-1" aria-hidden="true"></i>)
<span class="visually-hidden">{{t('incognito-alt')}}</span>
</span>
</button>
</div>
</div>
}
</div>
</div>
</div>
</div>
}
</ng-template>
</app-side-nav-companion-bar>
@if (readingList) {
<div class="container-fluid mt-2">
<div class="row mb-2">
<div class="col-md-2 col-xs-4 col-sm-6 d-none d-sm-block">
<app-image [styles]="{'max-height': '400px', 'max-width': '300px'}" [imageUrl]="imageService.getReadingListCoverImage(readingList.id)"></app-image>
</div>
<div class="col-md-10 col-xs-8 col-sm-6 mt-2">
<div class="row g-0 mb-3">
<div class="col-auto me-2">
<!-- Action row-->
<div class="btn-group me-3">
<button type="button" class="btn btn-primary" (click)="continue()">
<span>
<i class="fa fa-book-open me-1" aria-hidden="true"></i>
<span class="read-btn--text">{{t('continue')}}</span>
</span>
</button>
<div class="btn-group" ngbDropdown role="group" [attr.aria-label]="t('read-options-alt')">
<button type="button" class="btn btn-primary dropdown-toggle-split" ngbDropdownToggle></button>
<div class="dropdown-menu" ngbDropdownMenu>
<button ngbDropdownItem (click)="read()">
<span>
<i class="fa fa-book" aria-hidden="true"></i>
<span class="read-btn--text">&nbsp;{{t('read')}}</span>
</span>
</button>
<button ngbDropdownItem (click)="continue(true)">
<span>
<i class="fa fa-book-open me-1" aria-hidden="true"></i>
<span class="read-btn--text">{{t('continue')}}</span>
(<i class="fa fa-glasses ms-1" aria-hidden="true"></i>)
<span class="visually-hidden">{{t('incognito-alt')}}</span>
</span>
</button>
<button ngbDropdownItem (click)="read(true)">
<span>
<i class="fa fa-book me-1" aria-hidden="true"></i>
<span class="read-btn--text">&nbsp;{{t('read')}}</span>
(<i class="fa fa-glasses ms-1" aria-hidden="true"></i>)
<span class="visually-hidden">{{t('incognito-alt')}}</span>
</span>
</button>
</div>
</div>
</div>
</div>
</div>
@if (readingList.startingYear !== 0) {
<div class="row g-0 mt-2">
<h4 class="reading-list-years">
@if (readingList.startingMonth > 0) {
{{(readingList.startingMonth +'/01/2020')| date:'MMM'}}
}
@if (readingList.startingMonth > 0 && readingList.startingYear > 0) {
,
}
@if (readingList.startingYear > 0) {
{{readingList.startingYear}}
}
@if (readingList.endingYear > 0) {
@if (readingList.endingMonth > 0) {
{{(readingList.endingMonth +'/01/2020')| date:'MMM'}}
@if (readingList.startingYear !== 0) {
<div class="row g-0 mt-2">
<h4 class="reading-list-years">
@if (readingList.startingMonth > 0) {
{{(readingList.startingMonth +'/01/2020')| date:'MMM'}}
}
@if (readingList.endingMonth > 0 && readingList.endingYear > 0) {
@if (readingList.startingMonth > 0 && readingList.startingYear > 0) {
,
}
@if (readingList.endingYear > 0) {
{{readingList.endingYear}}
@if (readingList.startingYear > 0) {
{{readingList.startingYear}}
}
}
</h4>
</div>
}
<!-- Summary row-->
<div class="row g-0 mt-2">
<app-read-more [text]="readingListSummary" [maxLength]="250"></app-read-more>
</div>
@if (characters$ | async; as characters) {
@if (characters && characters.length > 0) {
<div class="row mb-2">
<div class="row">
<h5>{{t('characters-title')}}</h5>
<app-badge-expander [items]="characters">
<ng-template #badgeExpanderItem let-item let-position="idx">
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="goToCharacter(item)">{{item.name}}</a>
</ng-template>
</app-badge-expander>
</div>
@if (readingList.endingYear > 0) {
@if (readingList.endingMonth > 0) {
{{(readingList.endingMonth +'/01/2020')| date:'MMM'}}
}
@if (readingList.endingMonth > 0 && readingList.endingYear > 0) {
,
}
@if (readingList.endingYear > 0) {
{{readingList.endingYear}}
}
}
</h4>
</div>
}
<!-- Summary row-->
<div class="row g-0 mt-2">
<app-read-more [text]="readingListSummary" [maxLength]="(utilityService.activeBreakpoint$ | async)! >= Breakpoint.Desktop ? 585 : 200"></app-read-more>
</div>
@if (characters$ | async; as characters) {
@if (characters && characters.length > 0) {
<div class="row mb-2">
<div class="row">
<h5>{{t('characters-title')}}</h5>
<app-badge-expander [items]="characters">
<ng-template #badgeExpanderItem let-item let-position="idx">
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="goToCharacter(item)">{{item.name}}</a>
</ng-template>
</app-badge-expander>
</div>
</div>
}
}
</div>
</div>
<div class="row mb-1 scroll-container" #scrollingBlock>
@if (items.length === 0 && !isLoading) {
<div class="mx-auto" style="width: 200px;">
{{t('no-data')}}
</div>
} @else if(isLoading) {
<app-loading [loading]="isLoading"></app-loading>
}
<app-draggable-ordered-list [items]="items" (orderUpdated)="orderUpdated($event)" [accessibilityMode]="accessibilityMode"
[showRemoveButton]="false">
<ng-template #draggableItem let-item let-position="idx">
<app-reading-list-item [ngClass]="{'content-container': items.length < 100, 'non-virtualized-container': items.length >= 100}" [item]="item" [position]="position" [libraryTypes]="libraryTypes"
[promoted]="item.promoted" (read)="readChapter($event)" (remove)="itemRemoved($event, position)"></app-reading-list-item>
</ng-template>
</app-draggable-ordered-list>
</div>
</div>
<div class="row mb-1 scroll-container" #scrollingBlock>
@if (items.length === 0 && !isLoading) {
<div class="mx-auto" style="width: 200px;">
{{t('no-data')}}
</div>
} @else if(isLoading) {
<app-loading [loading]="isLoading"></app-loading>
}
<app-draggable-ordered-list [items]="items" (orderUpdated)="orderUpdated($event)" [accessibilityMode]="accessibilityMode"
[showRemoveButton]="false">
<ng-template #draggableItem let-item let-position="idx">
<app-reading-list-item [ngClass]="{'content-container': items.length < 100, 'non-virtualized-container': items.length >= 100}" [item]="item" [position]="position" [libraryTypes]="libraryTypes"
[promoted]="item.promoted" (read)="readChapter($event)" (remove)="itemRemoved($event, position)"></app-reading-list-item>
</ng-template>
</app-draggable-ordered-list>
</div>
</div>
}
</ng-container>
}
</ng-container>
</div>

View file

@ -1,35 +1,38 @@
<ng-container *transloco="let t; read: 'reading-lists'">
<app-side-nav-companion-bar>
<h4 title>
<span>{{t('title')}}</span>
<app-card-actionables [actions]="globalActions" (actionHandler)="performGlobalAction($event)"></app-card-actionables>
</h4>
@if (pagination) {
<h5 subtitle class="subtitle-with-actionables">{{t('item-count', {num: pagination.totalItems | number})}}</h5>
}
<div class="main-container container-fluid">
<ng-container *transloco="let t; read: 'reading-lists'">
<app-side-nav-companion-bar>
<h4 title>
<span>{{t('title')}}</span>
<app-card-actionables [actions]="globalActions" (actionHandler)="performGlobalAction($event)"></app-card-actionables>
</h4>
@if (pagination) {
<h5 subtitle class="subtitle-with-actionables">{{t('item-count', {num: pagination.totalItems | number})}}</h5>
}
</app-side-nav-companion-bar>
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
</app-side-nav-companion-bar>
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
<app-card-detail-layout
[isLoading]="loadingLists"
[items]="lists"
[pagination]="pagination"
[jumpBarKeys]="jumpbarKeys"
[filteringDisabled]="true"
[trackByIdentity]="trackByIdentity"
>
<ng-template #cardItem let-item let-position="idx" >
<app-card-item [title]="item.title" [entity]="item" [actions]="actions[item.id]"
[suppressLibraryLink]="true" [imageUrl]="imageService.getReadingListCoverImage(item.id)"
(clicked)="handleClick(item)"
(selection)="bulkSelectionService.handleCardSelection('readingList', position, lists.length, $event)"
[selected]="bulkSelectionService.isCardSelected('readingList', position)" [allowSelection]="true"></app-card-item>
</ng-template>
<app-card-detail-layout
[isLoading]="loadingLists"
[items]="lists"
[pagination]="pagination"
[jumpBarKeys]="jumpbarKeys"
[filteringDisabled]="true"
[trackByIdentity]="trackByIdentity"
>
<ng-template #cardItem let-item let-position="idx" >
<app-card-item [title]="item.title" [entity]="item" [actions]="actions[item.id]"
[suppressLibraryLink]="true" [imageUrl]="imageService.getReadingListCoverImage(item.id)"
[linkUrl]="'/lists/' + item.id"
(clicked)="handleClick(item)"
(selection)="bulkSelectionService.handleCardSelection('readingList', position, lists.length, $event)"
[selected]="bulkSelectionService.isCardSelected('readingList', position)" [allowSelection]="true"></app-card-item>
</ng-template>
<ng-template #noData>
{{t('no-data')}} {{t('create-one-part-1')}} <a [href]="WikiLink.ReadingLists" 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')}} {{t('create-one-part-1')}} <a [href]="WikiLink.ReadingLists" 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>

View file

@ -89,18 +89,16 @@ export class ReadingListsComponent implements OnInit {
.filter(action => this.readingListService.actionListFilter(action, readingList, this.isAdmin || this.hasPromote));
}
performAction(action: ActionItem<ReadingList>, readingList: ReadingList) {
if (typeof action.callback === 'function') {
action.callback(action, readingList);
}
}
performGlobalAction(action: ActionItem<any>) {
if (typeof action.callback === 'function') {
action.callback(action, undefined);
}
}
handleClick(list: ReadingList) {
this.router.navigateByUrl('lists/' + list.id);
}
handleReadingListActionCallback(action: ActionItem<ReadingList>, readingList: ReadingList) {
switch(action.action) {
case Action.Delete:
@ -159,10 +157,6 @@ export class ReadingListsComponent implements OnInit {
});
}
handleClick(list: ReadingList) {
this.router.navigateByUrl('lists/' + list.id);
}
bulkActionCallback = (action: ActionItem<any>, data: any) => {
const selectedReadingListIndexies = this.bulkSelectionService.getSelectedCardsForSource('readingList');
const selectedReadingLists = this.lists.filter((col, index: number) => selectedReadingListIndexies.includes(index + ''));