Scroll to previous offset rather than index

Changes some auto scrolling behavior in our virtual scrolling tables.
Save the scroll offset before any navigation attempt, rather than
saving the index on click.
Should work for every possible navigation action.
This commit is contained in:
Sean 2019-12-06 13:43:09 +01:00
parent 0bb2175f79
commit 01b626d3e7
9 changed files with 41 additions and 68 deletions

View File

@ -10,12 +10,13 @@ import {
ViewChild, ViewChild,
ViewEncapsulation ViewEncapsulation
} from '@angular/core'; } from '@angular/core';
import { NavigationStart, Router } from '@angular/router';
import { columnFactory, createDS, DataSourcePredicate, PblDataSource, PblNgridComponent } from '@pebula/ngrid'; import { columnFactory, createDS, DataSourcePredicate, PblDataSource, PblNgridComponent } from '@pebula/ngrid';
import { PblColumnDefinition, PblColumnFactory, PblNgridColumnSet } from '@pebula/ngrid/lib/table'; import { PblColumnDefinition, PblColumnFactory, PblNgridColumnSet } from '@pebula/ngrid/lib/table';
import { PblNgridDataMatrixRow } from '@pebula/ngrid/target-events'; import { PblNgridDataMatrixRow } from '@pebula/ngrid/target-events';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators'; import { distinctUntilChanged, filter } from 'rxjs/operators';
import { OperatorService, Permission } from 'app/core/core-services/operator.service'; import { OperatorService, Permission } from 'app/core/core-services/operator.service';
import { StorageService } from 'app/core/core-services/storage.service'; import { StorageService } from 'app/core/core-services/storage.service';
@ -384,6 +385,7 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
public constructor( public constructor(
private operator: OperatorService, private operator: OperatorService,
vp: ViewportService, vp: ViewportService,
router: Router,
private store: StorageService, private store: StorageService,
private cd: ChangeDetectorRef private cd: ChangeDetectorRef
) { ) {
@ -393,6 +395,12 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
} }
this.isMobile = mobile; this.isMobile = mobile;
}); });
this.subs.push(
router.events.pipe(filter(event => event instanceof NavigationStart)).subscribe(() => {
this.saveScrollOffset();
})
);
} }
public async ngOnInit(): Promise<void> { public async ngOnInit(): Promise<void> {
@ -400,8 +408,9 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
await this.restoreSearchQuery(); await this.restoreSearchQuery();
this.createDataSource(); this.createDataSource();
this.changeRowHeight(); this.changeRowHeight();
this.scrollToPreviousPosition();
this.cd.detectChanges(); this.cd.detectChanges();
// ngrid exists after the first change detection
this.scrollToPreviousPosition();
} }
/** /**
@ -600,9 +609,17 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
* @param key the key of the scroll index * @param key the key of the scroll index
* @returns the scroll index or 0 if not found * @returns the scroll index or 0 if not found
*/ */
public async getScrollIndex(key: string): Promise<number> { private async getScrollOffset(key: string): Promise<number> {
const scrollIndex = await this.store.get<number>(`scroll_${key}`); const scrollOffset = await this.store.get<number>(`scroll_${key}`);
return scrollIndex ? scrollIndex : 0; return scrollOffset ? scrollOffset : 0;
}
/**
* Store the scroll offset
*/
private saveScrollOffset(): void {
const offset = this.ngrid.viewport.measureScrollOffset();
this.store.set(`scroll_${this.listStorageKey}`, offset);
} }
/** /**
@ -626,18 +643,11 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
/** /**
* Automatically scrolls to a stored scroll position * Automatically scrolls to a stored scroll position
*
* TODO: Only the position will be stored, not the item.
* Changing the filtering and sorting will confuse the order
*
* TODO: getScrollIndex is not supported by virtual scrolling with the `vScrollAuto` directive.
* Furthermore, dynamic assigning the amount of pixels in vScrollFixed
* does not work, tying the tables to the same hight.
*/ */
public async scrollToPreviousPosition(): Promise<void> { private async scrollToPreviousPosition(): Promise<void> {
if (this.ngrid) { if (this.ngrid) {
const scrollIndex = await this.getScrollIndex(this.listStorageKey); const scrollIndex = await this.getScrollOffset(this.listStorageKey);
this.ngrid.viewport.scrollToIndex(scrollIndex); this.ngrid.viewport.scrollToOffset(scrollIndex);
} }
} }

View File

@ -29,12 +29,7 @@
> >
<!-- Title column --> <!-- Title column -->
<div *pblNgridCellDef="'title'; row as item; rowContext as rowContext" class="cell-slot fill"> <div *pblNgridCellDef="'title'; row as item; rowContext as rowContext" class="cell-slot fill">
<a <a class="detail-link" [routerLink]="getDetailUrl(item)" *ngIf="!isMultiSelect"></a>
class="detail-link"
(click)="saveScrollIndex('agenda', rowContext.identity)"
[routerLink]="getDetailUrl(item)"
*ngIf="!isMultiSelect"
></a>
<div [ngStyle]="{ 'margin-left': item.level * 25 + 'px' }" class="innerTable"> <div [ngStyle]="{ 'margin-left': item.level * 25 + 'px' }" class="innerTable">
<os-icon-container [noWrap]="true" [icon]="item.closed ? 'check' : null" size="large"> <os-icon-container [noWrap]="true" [icon]="item.closed ? 'check' : null" size="large">
<div class="ellipsis-overflow"> <div class="ellipsis-overflow">

View File

@ -33,12 +33,7 @@
> >
<!-- Title --> <!-- Title -->
<div *pblNgridCellDef="'title'; row as assignment; rowContext as rowContext" class="cell-slot fill"> <div *pblNgridCellDef="'title'; row as assignment; rowContext as rowContext" class="cell-slot fill">
<a <a class="detail-link" [routerLink]="assignment.id" *ngIf="!isMultiSelect"></a>
class="detail-link"
(click)="saveScrollIndex('assignments', rowContext.identity)"
[routerLink]="assignment.id"
*ngIf="!isMultiSelect"
></a>
<div> <div>
<div class="title-line ellipsis-overflow"> <div class="title-line ellipsis-overflow">
{{ assignment.getListTitle() }} {{ assignment.getListTitle() }}

View File

@ -106,14 +106,4 @@ export abstract class BaseListViewComponent<V extends BaseViewModel> extends Bas
public get isMultiSelect(): boolean { public get isMultiSelect(): boolean {
return this._multiSelectMode; return this._multiSelectMode;
} }
/**
* Saves the scroll index in the storage
*
* @param key
* @param index
*/
public saveScrollIndex(key: string, index: number): void {
this.storage.set(`scroll_${key}`, index);
}
} }

View File

@ -25,11 +25,7 @@
> >
<!-- Title --> <!-- Title -->
<div *pblNgridCellDef="'title'; row as category; rowContext as rowContext" class="cell-slot fill"> <div *pblNgridCellDef="'title'; row as category; rowContext as rowContext" class="cell-slot fill">
<a <a class="detail-link" [routerLink]="category.id"></a>
class="detail-link"
[routerLink]="category.id"
(click)="saveScrollIndex('category', rowContext.identity)"
></a>
<div [style.margin-left]="getMargin(category)">{{ category.prefixedName }}</div> <div [style.margin-left]="getMargin(category)">{{ category.prefixedName }}</div>
</div> </div>

View File

@ -18,14 +18,14 @@
> >
<!-- Title column --> <!-- Title column -->
<div *pblNgridCellDef="'title'; value as title; row as block; rowContext as rowContext" class="cell-slot fill"> <div *pblNgridCellDef="'title'; value as title; row as block; rowContext as rowContext" class="cell-slot fill">
<a <a class="detail-link" [routerLink]="block.id" *ngIf="!isMultiSelect"></a>
class="detail-link"
(click)="saveScrollIndex('motionBlock', rowContext.identity)"
[routerLink]="block.id"
*ngIf="!isMultiSelect"
></a>
<div class="innerTable"> <div class="innerTable">
<os-icon-container [noWrap]="true" [icon]="block.internal ? 'lock' : null" size="large" [matTooltip]="Internal"> <os-icon-container
[noWrap]="true"
[icon]="block.internal ? 'lock' : null"
size="large"
[matTooltip]="Internal"
>
<div class="ellipsis-overflow"> <div class="ellipsis-overflow">
{{ title }} {{ title }}
</div> </div>

View File

@ -63,12 +63,7 @@
<!-- Title --> <!-- Title -->
<div *pblNgridCellDef="'title'; row as motion; rowContext as rowContext" class="cell-slot fill"> <div *pblNgridCellDef="'title'; row as motion; rowContext as rowContext" class="cell-slot fill">
<a <a class="detail-link" [routerLink]="motion.id" *ngIf="!isMultiSelect"></a>
class="detail-link"
(click)="saveScrollIndex('motion', rowContext.identity)"
[routerLink]="motion.id"
*ngIf="!isMultiSelect"
></a>
<div class="column-title innerTable"> <div class="column-title innerTable">
<div class="title-line ellipsis-overflow"> <div class="title-line ellipsis-overflow">
<!-- Is Favorite --> <!-- Is Favorite -->

View File

@ -15,12 +15,7 @@
> >
<!-- Name column --> <!-- Name column -->
<div *pblNgridCellDef="'name'; value as name; row as workflow; rowContext as rowContext" class="cell-slot fill"> <div *pblNgridCellDef="'name'; value as name; row as workflow; rowContext as rowContext" class="cell-slot fill">
<a <a class="detail-link" [routerLink]="workflow.id" *ngIf="!isMultiSelect"></a>
class="detail-link"
(click)="saveScrollIndex('workflow', rowContext.identity)"
[routerLink]="workflow.id"
*ngIf="!isMultiSelect"
></a>
<div>{{ name | translate }}</div> <div>{{ name | translate }}</div>
</div> </div>

View File

@ -29,12 +29,7 @@
> >
<!-- Name column --> <!-- Name column -->
<div *pblNgridCellDef="'short_name'; value as name; row as user; rowContext as rowContext" class="cell-slot fill"> <div *pblNgridCellDef="'short_name'; value as name; row as user; rowContext as rowContext" class="cell-slot fill">
<a <a class="detail-link" [routerLink]="user.id" *ngIf="!isMultiSelect"></a>
class="detail-link"
(click)="saveScrollIndex('user', rowContext.identity)"
[routerLink]="user.id"
*ngIf="!isMultiSelect"
></a>
<div class="nameCell"> <div class="nameCell">
<span>{{ name }}</span> <span>{{ name }}</span>
</div> </div>
@ -89,7 +84,9 @@
comment comment
</mat-icon> </mat-icon>
<os-icon-container *ngIf="user.isSamlUser" icon="device_hub"><span translate>Is SAML user</span></os-icon-container> <os-icon-container *ngIf="user.isSamlUser" icon="device_hub"
><span translate>Is SAML user</span></os-icon-container
>
</div> </div>
</div> </div>