Merge pull request #5156 from tsiegleauq/dymanic-ngrid-index-jumping

Scroll to previous offset rather than index
This commit is contained in:
Emanuel Schütze 2019-12-09 11:07:23 +01:00 committed by GitHub
commit 50ce5e7d61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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>