Co-authored-by: Joseph Milazzo <joseph.v.milazzo@gmail.com>
This commit is contained in:
Robbie Davis 2024-08-26 10:52:46 -04:00 committed by GitHub
parent fc644985be
commit 62383042b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
70 changed files with 741 additions and 399 deletions

View file

@ -647,7 +647,7 @@
</div>
</div>
<h4>Volumes</h4>
<h4>{{t('volumes-title')}}</h4>
@if (isLoadingVolumes) {
<div class="spinner-border text-secondary" role="status">
<span class="visually-hidden">{{t('loading')}}</span>
@ -671,7 +671,7 @@
<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]">
[attr.aria-expanded]="!volumeCollapsed[volume.name]" [disabled]="!isAdmin">
{{t('view-files')}}
</button>
</div>

View file

@ -17,7 +17,7 @@ import {
NgbNavOutlet,
NgbTooltip
} from '@ng-bootstrap/ng-bootstrap';
import { forkJoin, Observable, of } from 'rxjs';
import {forkJoin, Observable, of, tap} from 'rxjs';
import { map } from 'rxjs/operators';
import { Breakpoint, UtilityService } from 'src/app/shared/_services/utility.service';
import { TypeaheadSettings } from 'src/app/typeahead/_models/typeahead-settings';
@ -184,6 +184,7 @@ export class EditSeriesModalComponent implements OnInit {
*/
selectedCover: string = '';
coverImageReset = false;
isAdmin: boolean = false;
saveNestedComponents: EventEmitter<void> = new EventEmitter();
@ -202,6 +203,11 @@ export class EditSeriesModalComponent implements OnInit {
this.libraryName = names[this.series.libraryId];
});
this.accountService.isAdmin$.pipe(takeUntilDestroyed(this.destroyRef), tap(isAdmin => {
this.isAdmin = isAdmin;
this.cdRef.markForCheck();
})).subscribe();
this.initSeries = Object.assign({}, this.series);
this.editSeriesForm = this.fb.group({

View file

@ -1,33 +1,36 @@
<ng-container *transloco="let t; read: 'bulk-operations'">
<ng-container *ngIf="bulkSelectionService.selections$ | async as selectionCount">
<div *ngIf="selectionCount > 0" class="bulk-select mb-3 {{modalMode ? '' : 'fixed-top'}}" [ngStyle]="{'margin-top': topOffset + 'px'}">
<div class="d-flex justify-content-around align-items-center">
@if (bulkSelectionService.selections$ | async; as selectionCount) {
@if (selectionCount > 0) {
<div class="bulk-select mb-3 {{modalMode ? '' : 'fixed-top'}}" [ngStyle]="{'margin-top': topOffset + 'px'}">
<div class="d-flex justify-content-around align-items-center">
<span class="highlight">
<i class="fa fa-check me-1" aria-hidden="true"></i>
{{t('items-selected',{num: selectionCount | number})}}
</span>
<span>
<span>
@if (hasMarkAsUnread) {
<button class="btn btn-icon" (click)="executeAction(Action.MarkAsUnread)" [ngbTooltip]="t('mark-as-unread')" placement="bottom">
<i class="fa-regular fa-circle-check" aria-hidden="true"></i>
<span class="visually-hidden">{{t('mark-as-unread')}}</span>
</button>
}
@if (hasMarkAsRead) {
<button class="btn btn-icon" (click)="executeAction(Action.MarkAsRead)" [ngbTooltip]="t('mark-as-read')" placement="bottom">
@if (hasMarkAsRead) {
<button class="btn btn-icon" (click)="executeAction(Action.MarkAsRead)" [ngbTooltip]="t('mark-as-read')" placement="bottom">
<i class="fa-solid fa-circle-check" aria-hidden="true"></i>
<span class="visually-hidden">{{t('mark-as-read')}}</span>
</button>
}
<app-card-actionables [actions]="actions" labelBy="bulk-actions-header" iconClass="fa-ellipsis-h" (actionHandler)="performAction($event)"></app-card-actionables>
}
<app-card-actionables [actions]="actions" labelBy="bulk-actions-header" iconClass="fa-ellipsis-h" (actionHandler)="performAction($event)"></app-card-actionables>
</span>
<span id="bulk-actions-header" class="visually-hidden">Bulk Actions</span>
<span id="bulk-actions-header" class="visually-hidden">Bulk Actions</span>
<button class="btn btn-icon" (click)="bulkSelectionService.deselectAll()"><i class="fa fa-times me-1" aria-hidden="true"></i>{{t('deselect-all')}}</button>
<button class="btn btn-icon" (click)="bulkSelectionService.deselectAll()"><i class="fa fa-times me-1" aria-hidden="true"></i>{{t('deselect-all')}}</button>
</div>
</div>
</div>
</ng-container>
}
}
</ng-container>

View file

@ -10,7 +10,7 @@ import {
import { Action, ActionFactoryService, ActionItem } from 'src/app/_services/action-factory.service';
import { BulkSelectionService } from '../bulk-selection.service';
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import {AsyncPipe, CommonModule} from "@angular/common";
import {AsyncPipe, DecimalPipe, NgStyle} from "@angular/common";
import {TranslocoModule} from "@jsverse/transloco";
import {NgbTooltip} from "@ng-bootstrap/ng-bootstrap";
import {CardActionablesComponent} from "../../_single-module/card-actionables/card-actionables.component";
@ -19,11 +19,12 @@ import {CardActionablesComponent} from "../../_single-module/card-actionables/ca
selector: 'app-bulk-operations',
standalone: true,
imports: [
CommonModule,
AsyncPipe,
CardActionablesComponent,
TranslocoModule,
NgbTooltip
NgbTooltip,
NgStyle,
DecimalPipe
],
templateUrl: './bulk-operations.component.html',
styleUrls: ['./bulk-operations.component.scss'],
@ -36,7 +37,7 @@ export class BulkOperationsComponent implements OnInit {
* Modal mode means don't fix to the top
*/
@Input() modalMode = false;
@Input() topOffset: number = 60;
@Input() topOffset: number = 75;
hasMarkAsRead: boolean = false;
hasMarkAsUnread: boolean = false;
actions: Array<ActionItem<any>> = [];

View file

@ -26,7 +26,7 @@
<app-metadata-filter [filterSettings]="filterSettings" [filterOpen]="filterOpen" (applyFilter)="applyMetadataFilter($event)"></app-metadata-filter>
<div class="viewport-container ms-1" [ngClass]="{'empty': items.length === 0 && !isLoading}">
<div class="content-container">
<div class="card-container mt-2 mb-2">
<div class="card-container mt-">
@if (items.length === 0 && !isLoading) {
<p><ng-container [ngTemplateOutlet]="noDataTemplate"></ng-container></p>
}

View file

@ -2,7 +2,7 @@
display: flex;
flex-direction: row;
width: 100%;
height: calc((var(--vh) *100) - 173px);
height: calc((var(--vh) *100) - 157px);
margin-bottom: 10px;
&.empty {
@ -94,10 +94,12 @@
.virtual-scroller, virtual-scroller {
width: 100%;
height: calc(var(--vh) * 100 - 143px);
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%);
height: calc(var(--vh) * 100 - 155px);
mask-image: linear-gradient(to bottom, transparent, black 0%, black 97%, transparent 100%);
-webkit-mask-image: linear-gradient(to bottom, transparent, black 0%, black 97%, transparent 100%);
overflow: auto;
scrollbar-color: rgba(255,255,255,0.3) rgba(0, 0, 0, 0.1);
scrollbar-width: thin;
}
@ -163,6 +165,7 @@ h2 {
justify-content: center;
font-size: 18px;
border-radius: 4px;
transform-style: preserve-3d;
}
.flip-button-back {