UX Overhaul Part 1 (#3047)
Co-authored-by: Joseph Milazzo <joseph.v.milazzo@gmail.com>
This commit is contained in:
parent
5934d516f3
commit
ff79710ac6
324 changed files with 11589 additions and 4598 deletions
|
|
@ -6,7 +6,7 @@
|
|||
</div>
|
||||
<form style="width: 100%" [formGroup]="listForm">
|
||||
<div class="modal-body">
|
||||
@if (lists.length >= 5) {
|
||||
@if (lists.length >= MaxItems) {
|
||||
<div class="mb-3">
|
||||
<label for="filter" class="form-label">{{t('filter-label')}}</label>
|
||||
<div class="input-group">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.clickable:hover, .clickable:focus {
|
||||
background-color: lightgreen;
|
||||
background-color: var(--list-group-hover-bg-color, --primary-color);
|
||||
}
|
||||
|
||||
.collection {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ export class BulkAddToCollectionComponent implements OnInit, AfterViewInit {
|
|||
private readonly collectionService = inject(CollectionTagService);
|
||||
private readonly toastr = inject(ToastrService);
|
||||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
protected readonly MaxItems = 8;
|
||||
|
||||
@Input({required: true}) title!: string;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import {ToastrService} from 'ngx-toastr';
|
|||
import {debounceTime, distinctUntilChanged, forkJoin, switchMap, tap} from 'rxjs';
|
||||
import {ConfirmService} from 'src/app/shared/confirm.service';
|
||||
import {Breakpoint, UtilityService} from 'src/app/shared/_services/utility.service';
|
||||
import {SelectionModel} from 'src/app/typeahead/_components/typeahead.component';
|
||||
import {UserCollection} from 'src/app/_models/collection-tag';
|
||||
import {Pagination} from 'src/app/_models/pagination';
|
||||
import {Series} from 'src/app/_models/series';
|
||||
|
|
@ -24,12 +23,11 @@ import {LibraryService} from 'src/app/_services/library.service';
|
|||
import {SeriesService} from 'src/app/_services/series.service';
|
||||
import {UploadService} from 'src/app/_services/upload.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {CommonModule, DatePipe, DecimalPipe, NgIf, NgTemplateOutlet} from "@angular/common";
|
||||
import {DatePipe, DecimalPipe, NgIf, NgTemplateOutlet} from "@angular/common";
|
||||
import {CoverImageChooserComponent} from "../../cover-image-chooser/cover-image-chooser.component";
|
||||
import {translate, TranslocoDirective} from "@ngneat/transloco";
|
||||
import {ScrobbleProvider} from "../../../_services/scrobbling.service";
|
||||
import {FilterPipe} from "../../../_pipes/filter.pipe";
|
||||
import {ScrobbleError} from "../../../_models/scrobbling/scrobble-error";
|
||||
import {AccountService} from "../../../_services/account.service";
|
||||
import {DefaultDatePipe} from "../../../_pipes/default-date.pipe";
|
||||
import {ReadMoreComponent} from "../../../shared/read-more/read-more.component";
|
||||
|
|
@ -38,6 +36,7 @@ import {SafeUrlPipe} from "../../../_pipes/safe-url.pipe";
|
|||
import {MangaFormatPipe} from "../../../_pipes/manga-format.pipe";
|
||||
import {SentenceCasePipe} from "../../../_pipes/sentence-case.pipe";
|
||||
import {TagBadgeComponent} from "../../../shared/tag-badge/tag-badge.component";
|
||||
import {SelectionModel} from "../../../typeahead/_models/selection-model";
|
||||
|
||||
|
||||
enum TabID {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.bulk-select {
|
||||
background-color: var(--navbar-bg-color);
|
||||
background-color: var(--bulk-background-color);
|
||||
border-bottom: 2px solid var(--primary-color);
|
||||
color: var(--bulk-selection-text-color) !important;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export class BulkOperationsComponent implements OnInit {
|
|||
* Modal mode means don't fix to the top
|
||||
*/
|
||||
@Input() modalMode = false;
|
||||
@Input() topOffset: number = 56;
|
||||
@Input() topOffset: number = 60;
|
||||
hasMarkAsRead: boolean = false;
|
||||
hasMarkAsUnread: boolean = false;
|
||||
actions: Array<ActionItem<any>> = [];
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
</ng-template>
|
||||
</li>
|
||||
|
||||
<li [ngbNavItem]="tabs[TabID.Cover]" [disabled]="(isAdmin$ | async) === false">
|
||||
<li [ngbNavItem]="tabs[TabID.Cover]" [disabled]="(accountService.isAdmin$ | async) === false">
|
||||
<a ngbNavLink>{{t(tabs[TabID.Cover].title)}}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<app-cover-image-chooser [(imageUrls)]="imageUrls" (imageSelected)="updateCoverImageIndex($event)"
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
</ng-template>
|
||||
</li>
|
||||
|
||||
<li [ngbNavItem]="tabs[TabID.Files]" [disabled]="(isAdmin$ | async) === false">
|
||||
<li [ngbNavItem]="tabs[TabID.Files]" [disabled]="(accountService.isAdmin$ | async) === false">
|
||||
<a ngbNavLink>{{t(tabs[TabID.Files].title)}}</a>
|
||||
<ng-template ngbNavContent>
|
||||
@if (!utilityService.isChapter(data)) {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import {
|
|||
NgbNavOutlet
|
||||
} from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { Observable, of, map, shareReplay } from 'rxjs';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { DownloadService } from 'src/app/shared/_services/download.service';
|
||||
import { Breakpoint, UtilityService } from 'src/app/shared/_services/utility.service';
|
||||
import {Chapter, LooseLeafOrDefaultNumber} from 'src/app/_models/chapter';
|
||||
|
|
@ -32,9 +32,7 @@ import { ActionService } from 'src/app/_services/action.service';
|
|||
import { ImageService } from 'src/app/_services/image.service';
|
||||
import { LibraryService } from 'src/app/_services/library.service';
|
||||
import { ReaderService } from 'src/app/_services/reader.service';
|
||||
import { SeriesService } from 'src/app/_services/series.service';
|
||||
import { UploadService } from 'src/app/_services/upload.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {EntityTitleComponent} from "../entity-title/entity-title.component";
|
||||
import {ImageComponent} from "../../shared/image/image.component";
|
||||
|
|
@ -69,6 +67,19 @@ enum TabID {
|
|||
})
|
||||
export class CardDetailDrawerComponent implements OnInit {
|
||||
|
||||
protected readonly utilityService = inject(UtilityService);
|
||||
protected readonly imageService = inject(ImageService);
|
||||
private readonly uploadService = inject(UploadService);
|
||||
private readonly toastr = inject(ToastrService);
|
||||
protected readonly accountService = inject(AccountService);
|
||||
private readonly actionFactoryService = inject(ActionFactoryService);
|
||||
private readonly actionService = inject(ActionService);
|
||||
private readonly router = inject(Router);
|
||||
private readonly libraryService = inject(LibraryService);
|
||||
private readonly readerService = inject(ReaderService);
|
||||
protected readonly activeOffcanvas = inject(NgbActiveOffcanvas);
|
||||
private readonly downloadService = inject(DownloadService);
|
||||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
protected readonly MangaFormat = MangaFormat;
|
||||
|
|
@ -115,22 +126,6 @@ export class CardDetailDrawerComponent implements OnInit {
|
|||
summary: string = '';
|
||||
downloadInProgress: boolean = false;
|
||||
|
||||
|
||||
|
||||
|
||||
constructor(public utilityService: UtilityService,
|
||||
public imageService: ImageService, private uploadService: UploadService, private toastr: ToastrService,
|
||||
private accountService: AccountService, private actionFactoryService: ActionFactoryService,
|
||||
private actionService: ActionService, private router: Router, private libraryService: LibraryService,
|
||||
private seriesService: SeriesService, private readerService: ReaderService,
|
||||
public activeOffcanvas: NgbActiveOffcanvas, private downloadService: DownloadService, private readonly cdRef: ChangeDetectorRef) {
|
||||
this.isAdmin$ = this.accountService.currentUser$.pipe(
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
map(user => (user && this.accountService.hasAdminRole(user)) || false),
|
||||
shareReplay()
|
||||
);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.imageUrls = this.chapters.map(c => this.imageService.getChapterCoverImage(c.id));
|
||||
this.isChapter = this.utilityService.isChapter(this.data);
|
||||
|
|
|
|||
|
|
@ -1,35 +1,42 @@
|
|||
<ng-container *transloco="let t; read: 'card-detail-layout'">
|
||||
|
||||
<div class="row mt-2 g-0 pb-2" *ngIf="header !== undefined && header.length > 0">
|
||||
<div class="col me-auto">
|
||||
<h2>
|
||||
<span *ngIf="actions.length > 0" class="">
|
||||
<app-card-actionables (actionHandler)="performAction($event)" [actions]="actions" [labelBy]="header"></app-card-actionables>
|
||||
</span>
|
||||
<span *ngIf="header !== undefined && header.length > 0">
|
||||
{{header}}
|
||||
<span class="badge bg-primary rounded-pill"
|
||||
[attr.aria-label]="t('total-items', {count: pagination.totalItems})"
|
||||
*ngIf="pagination !== undefined">{{pagination.totalItems}}</span>
|
||||
</span>
|
||||
</h2>
|
||||
@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)" [actions]="actions" [labelBy]="header"></app-card-actionables>
|
||||
</span>
|
||||
}
|
||||
|
||||
<span>
|
||||
{{header}}
|
||||
@if (pagination !== undefined) {
|
||||
<span class="badge bg-primary rounded-pill"
|
||||
[attr.aria-label]="t('total-items', {count: pagination.totalItems})">{{pagination.totalItems}}</span>
|
||||
}
|
||||
</span>
|
||||
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<app-metadata-filter [filterSettings]="filterSettings" [filterOpen]="filterOpen" (applyFilter)="applyMetadataFilter($event)"></app-metadata-filter>
|
||||
<div class="viewport-container" [ngClass]="{'empty': items.length === 0 && !isLoading}">
|
||||
<div class="viewport-container ms-1" [ngClass]="{'empty': items.length === 0 && !isLoading}">
|
||||
<div class="content-container">
|
||||
<div class="card-container mt-2 mb-2">
|
||||
<p *ngIf="items.length === 0 && !isLoading">
|
||||
<ng-container [ngTemplateOutlet]="noDataTemplate"></ng-container>
|
||||
</p>
|
||||
@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>
|
||||
<!-- TODO: @for (item of scroll.viewPortItems; track trackByIdentity; let i = $index;) { works -->
|
||||
<div class="card col-auto mt-2 mb-2"
|
||||
(click)="tryToSaveJumpKey(item)"
|
||||
*ngFor="let item of scroll.viewPortItems; trackBy:trackByIdentity; index as i" id="jumpbar-index--{{i}}"
|
||||
(click)="tryToSaveJumpKey()"
|
||||
*ngFor="let item of scroll.viewPortItems; trackBy:trackByIdentity; index as i"
|
||||
id="jumpbar-index--{{i}}"
|
||||
[attr.jumpbar-index]="i">
|
||||
<ng-container [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletContext]="{ $implicit: item, idx: scroll.viewPortInfo.startIndexWithBuffer + i }"></ng-container>
|
||||
</div>
|
||||
|
|
@ -38,34 +45,43 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="jumpBarKeysToRender.length >= 4 && items.length > 0 && scroll.viewPortInfo.maxScrollPosition > 0" [ngTemplateOutlet]="jumpBar" [ngTemplateOutletContext]="{ id: 'jumpbar' }"></ng-container>
|
||||
@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" (click)="tryToSaveJumpKey(item)" *ngFor="let item of scroll.viewPortItems; trackBy:trackByIdentity; index as i" id="jumpbar-index--{{i}}" [attr.jumpbar-index]="i">
|
||||
<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>
|
||||
|
||||
<div class="mx-auto" *ngIf="items.length === 0 && !isLoading" style="width: 200px;">
|
||||
<p>
|
||||
<ng-container [ngTemplateOutlet]="noDataTemplate"></ng-container>
|
||||
</p>
|
||||
</div>
|
||||
@if (items.length === 0 && !isLoading) {
|
||||
<div class="mx-auto" style="width: 200px;">
|
||||
<p>
|
||||
<ng-container [ngTemplateOutlet]="noDataTemplate"></ng-container>
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
</ng-template>
|
||||
|
||||
<app-loading [loading]="isLoading"></app-loading>
|
||||
|
||||
<ng-template #jumpBar>
|
||||
<div class="jump-bar">
|
||||
<ng-container *ngFor="let jumpKey of jumpBarKeysToRender; let i = index;">
|
||||
<button class="btn btn-link" [ngClass]="{'disabled': hasCustomSort()}" (click)="scrollTo(jumpKey)" [ngbTooltip]="t('jumpkey-count', {count: jumpKey.size})" placement="left">
|
||||
{{jumpKey.title}}
|
||||
@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>
|
||||
</ng-container>
|
||||
}
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, 158px);
|
||||
grid-gap: 0.5rem;
|
||||
justify-content: space-around;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
|
@ -103,3 +103,46 @@ h2 {
|
|||
display: inline-block;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
|
||||
.flip-button {
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 40px;
|
||||
height: 25px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.flip-button-inner {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
transition: transform 0.6s;
|
||||
transform-style: preserve-3d;
|
||||
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.flip-button:hover .flip-button-inner {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
|
||||
.flip-button-front, .flip-button-back {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
backface-visibility: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.flip-button-back {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {CommonModule, DOCUMENT} from '@angular/common';
|
||||
import {DOCUMENT, NgClass, NgForOf, NgTemplateOutlet} from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
|
|
@ -28,7 +28,6 @@ import {Pagination} from 'src/app/_models/pagination';
|
|||
import {FilterEvent, FilterItem, SortField} from 'src/app/_models/metadata/series-filter';
|
||||
import {ActionItem} from 'src/app/_services/action-factory.service';
|
||||
import {JumpbarService} from 'src/app/_services/jumpbar.service';
|
||||
import {ScrollService} from 'src/app/_services/scroll.service';
|
||||
import {LoadingComponent} from "../../shared/loading/loading.component";
|
||||
|
||||
|
||||
|
|
@ -44,7 +43,8 @@ const ANIMATION_TIME_MS = 0;
|
|||
@Component({
|
||||
selector: 'app-card-detail-layout',
|
||||
standalone: true,
|
||||
imports: [CommonModule, LoadingComponent, VirtualScrollerModule, CardActionablesComponent, NgbTooltip, MetadataFilterComponent, TranslocoDirective],
|
||||
imports: [LoadingComponent, VirtualScrollerModule, CardActionablesComponent, NgbTooltip, MetadataFilterComponent,
|
||||
TranslocoDirective, NgTemplateOutlet, NgClass, NgForOf],
|
||||
templateUrl: './card-detail-layout.component.html',
|
||||
styleUrls: ['./card-detail-layout.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
|
@ -56,7 +56,8 @@ export class CardDetailLayoutComponent implements OnInit, OnChanges {
|
|||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
private readonly jumpbarService = inject(JumpbarService);
|
||||
private readonly router = inject(Router);
|
||||
private readonly scrollService = inject(ScrollService);
|
||||
|
||||
protected readonly Breakpoint = Breakpoint;
|
||||
|
||||
@Input() header: string = '';
|
||||
@Input() isLoading: boolean = false;
|
||||
|
|
@ -101,10 +102,9 @@ export class CardDetailLayoutComponent implements OnInit, OnChanges {
|
|||
libraries: Array<FilterItem<Library>> = [];
|
||||
|
||||
updateApplied: number = 0;
|
||||
hasResumedJumpKey: boolean = false;
|
||||
bufferAmount: number = 1;
|
||||
|
||||
protected readonly Breakpoint = Breakpoint;
|
||||
|
||||
|
||||
constructor(@Inject(DOCUMENT) private document: Document) {}
|
||||
|
||||
|
|
@ -145,34 +145,16 @@ export class CardDetailLayoutComponent implements OnInit, OnChanges {
|
|||
this.jumpBarKeysToRender = [...this.jumpBarKeys];
|
||||
this.resizeJumpBar();
|
||||
|
||||
// TODO: I wish I had signals so I can tap into when isLoading is false and trigger the scroll code
|
||||
|
||||
// Don't resume jump key when there is a custom sort order, as it won't work
|
||||
if (!this.hasCustomSort()) {
|
||||
if (!this.hasResumedJumpKey && this.jumpBarKeysToRender.length > 0) {
|
||||
const resumeKey = this.jumpbarService.getResumeKey(this.router.url);
|
||||
if (resumeKey === '') return;
|
||||
const keys = this.jumpBarKeysToRender.filter(k => k.key === resumeKey);
|
||||
if (keys.length < 1) return;
|
||||
|
||||
this.hasResumedJumpKey = true;
|
||||
setTimeout(() => this.scrollTo(keys[0]), 100);
|
||||
}
|
||||
const startIndex = this.jumpbarService.getResumePosition(this.router.url);
|
||||
if (startIndex > 0) {
|
||||
setTimeout(() => this.virtualScroller.scrollToIndex(startIndex, true, 0, ANIMATION_TIME_MS), 10);
|
||||
}
|
||||
// else {
|
||||
// // I will come back and refactor this to work
|
||||
// // const scrollPosition = this.jumpbarService.getResumePosition(this.router.url);
|
||||
// // console.log('scroll position: ', scrollPosition);
|
||||
// // if (scrollPosition > 0) {
|
||||
// // setTimeout(() => this.virtualScroller.scrollToIndex(scrollPosition, true, 0, 1000), 100);
|
||||
// // }
|
||||
// }
|
||||
}
|
||||
|
||||
hasCustomSort() {
|
||||
if (this.filteringDisabled) return false;
|
||||
const hasCustomSort = this.filter?.sortOptions?.sortField != SortField.SortName || !this.filter?.sortOptions.isAscending;
|
||||
const hasNonDefaultSortField = this.filterSettings?.presetsV2?.sortOptions?.sortField != SortField.SortName;
|
||||
//const hasNonDefaultSortField = this.filterSettings?.presetsV2?.sortOptions?.sortField != SortField.SortName;
|
||||
|
||||
return hasCustomSort;
|
||||
}
|
||||
|
|
@ -201,20 +183,10 @@ export class CardDetailLayoutComponent implements OnInit, OnChanges {
|
|||
}
|
||||
|
||||
this.virtualScroller.scrollToIndex(targetIndex, true, 0, ANIMATION_TIME_MS);
|
||||
this.jumpbarService.saveResumeKey(this.router.url, jumpKey.key);
|
||||
// TODO: This doesn't work, we need the offset from virtual scroller
|
||||
this.jumpbarService.saveScrollOffset(this.router.url, this.scrollService.scrollPosition);
|
||||
|
||||
this.cdRef.markForCheck();
|
||||
setTimeout(() => this.jumpbarService.saveResumePosition(this.router.url, this.virtualScroller.viewPortInfo.startIndex), ANIMATION_TIME_MS + 100);
|
||||
}
|
||||
|
||||
tryToSaveJumpKey(item: any) {
|
||||
let name = '';
|
||||
if (item.hasOwnProperty('name')) {
|
||||
name = item.name;
|
||||
} else if (item.hasOwnProperty('title')) {
|
||||
name = item.title;
|
||||
}
|
||||
this.jumpbarService.saveResumeKey(this.router.url, name.charAt(0));
|
||||
tryToSaveJumpKey() {
|
||||
this.jumpbarService.saveResumePosition(this.router.url, this.virtualScroller.viewPortInfo.startIndex);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue