Co-authored-by: Stepan Goremykin <s.goremykin@proton.me> Co-authored-by: goremykin <goremukin@gmail.com> Co-authored-by: Christopher <39032787+MrRobotjs@users.noreply.github.com> Co-authored-by: Fesaa <77553571+Fesaa@users.noreply.github.com>
96 lines
3.6 KiB
HTML
96 lines
3.6 KiB
HTML
<ng-container *transloco="let t; read: 'card-detail-layout'">
|
|
<app-loading [loading]="isLoading"></app-loading>
|
|
|
|
@if (header().length > 0) {
|
|
<div class="row mt-2 g-0 pb-2">
|
|
<div class="col me-auto">
|
|
<h4>
|
|
@if (actions().length > 0) {
|
|
<span>
|
|
<app-card-actionables (actionHandler)="performAction($event)" [inputActions]="actions()" [labelBy]="header()"></app-card-actionables>
|
|
</span>
|
|
}
|
|
|
|
<span>
|
|
{{header()}}
|
|
@if (pagination) {
|
|
<span class="badge bg-primary rounded-pill"
|
|
[attr.aria-label]="t('total-items', {count: pagination.totalItems})">{{pagination.totalItems}}</span>
|
|
}
|
|
</span>
|
|
|
|
</h4>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
@if (filterSettings) {
|
|
<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">
|
|
@if (items.length === 0 && !isLoading) {
|
|
<p><ng-container [ngTemplateOutlet]="noDataTemplate"></ng-container></p>
|
|
}
|
|
|
|
<virtual-scroller [ngClass]="{'empty': items.length === 0 && !isLoading}" #scroll [items]="items" [bufferAmount]="bufferAmount" [parentScroll]="parentScroll">
|
|
<div class="grid row g-0" #container>
|
|
@for (item of scroll.viewPortItems; track trackByIdentity(i, item); let i = $index) {
|
|
<div class="card col-auto mt-2 mb-2"
|
|
(click)="tryToSaveJumpKey()"
|
|
id="jumpbar-index--{{i}}"
|
|
[attr.jumpbar-index]="i">
|
|
<ng-container [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletContext]="{ $implicit: item, idx: scroll.viewPortInfo.startIndexWithBuffer + i }"></ng-container>
|
|
</div>
|
|
}
|
|
</div>
|
|
</virtual-scroller>
|
|
</div>
|
|
</div>
|
|
|
|
@if (jumpBarKeysToRender.length >= 4 && items.length > 0 && scroll.viewPortInfo.maxScrollPosition > 0) {
|
|
<ng-container [ngTemplateOutlet]="jumpBar" [ngTemplateOutletContext]="{ id: 'jumpbar' }"></ng-container>
|
|
}
|
|
</div>
|
|
|
|
<ng-template #cardTemplate>
|
|
<virtual-scroller #scroll [items]="items" [bufferAmount]="bufferAmount">
|
|
<div class="grid row g-0" #container>
|
|
|
|
<div class="card col-auto mt-2 mb-2" *ngFor="let item of scroll.viewPortItems; trackBy:trackByIdentity; index as i" (click)="tryToSaveJumpKey()" id="jumpbar-index--{{i}}" [attr.jumpbar-index]="i">
|
|
<ng-container [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletContext]="{ $implicit: item, idx: i }"></ng-container>
|
|
</div>
|
|
|
|
</div>
|
|
</virtual-scroller>
|
|
|
|
@if (items.length === 0 && !isLoading) {
|
|
<div class="mx-auto" style="width: 200px;">
|
|
<p>
|
|
@if (noDataTemplate) {
|
|
<ng-container [ngTemplateOutlet]="noDataTemplate"></ng-container>
|
|
} @else {
|
|
{{t('no-data')}}
|
|
}
|
|
</p>
|
|
</div>
|
|
}
|
|
|
|
</ng-template>
|
|
|
|
<ng-template #jumpBar>
|
|
<div class="jump-bar">
|
|
@for(jumpKey of jumpBarKeysToRender; track jumpKey.key; let i = $index) {
|
|
<button class="btn btn-link flip-button" [ngClass]="{'disabled': hasCustomSort()}"
|
|
(click)="scrollTo(jumpKey)">
|
|
<div class="flip-button-inner">
|
|
<div class="flip-button-front">{{jumpKey.title}}</div>
|
|
<div class="flip-button-back">{{jumpKey.size}}</div>
|
|
</div>
|
|
</button>
|
|
}
|
|
</div>
|
|
</ng-template>
|
|
</ng-container>
|