update scroll button
This commit is contained in:
parent
a84cc03dae
commit
9df7530e5d
@ -1,7 +1,7 @@
|
||||
<button (click)="scroll(buttonType.top)" [hidden]="!showScroll(buttonType.top)" class="scroll-button top pointer">
|
||||
<button (click)="scroll(buttonType.top)" [hidden]="(showScrollUp$ | async) === false" class="scroll-button top pointer">
|
||||
<mat-icon svgIcon="red:arrow-down-o"></mat-icon>
|
||||
</button>
|
||||
|
||||
<button (click)="scroll(buttonType.bottom)" [hidden]="!showScroll(buttonType.bottom)" class="scroll-button bottom pointer">
|
||||
<button (click)="scroll(buttonType.bottom)" [hidden]="(showScrollDown$ | async) === false" class="scroll-button bottom pointer">
|
||||
<mat-icon svgIcon="red:arrow-down-o"></mat-icon>
|
||||
</button>
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { Component, HostListener, Input } from '@angular/core';
|
||||
import { Component, HostListener, Input, OnInit } from '@angular/core';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { concatMap, delay, distinctUntilChanged, map, startWith } from 'rxjs/operators';
|
||||
import { Observable, of } from 'rxjs';
|
||||
|
||||
const ButtonTypes = {
|
||||
top: 'top',
|
||||
@ -13,28 +15,40 @@ type ButtonType = keyof typeof ButtonTypes;
|
||||
templateUrl: './scroll-button.component.html',
|
||||
styleUrls: ['./scroll-button.component.scss']
|
||||
})
|
||||
export class ScrollButtonComponent {
|
||||
buttonType = ButtonTypes;
|
||||
export class ScrollButtonComponent implements OnInit {
|
||||
readonly buttonType = ButtonTypes;
|
||||
|
||||
@Input()
|
||||
scrollViewport: CdkVirtualScrollViewport;
|
||||
@Input()
|
||||
itemSize: number;
|
||||
|
||||
showScrollUp$: Observable<boolean>;
|
||||
showScrollDown$: Observable<boolean>;
|
||||
|
||||
ngOnInit() {
|
||||
const scrollSize = () => this.scrollViewport.getDataLength() * this.itemSize;
|
||||
const scrollIsNeeded = () => this.scrollViewport.getViewportSize() < scrollSize();
|
||||
const reachedEnd = (type: ButtonType) => this.scrollViewport.measureScrollOffset(type) === 0;
|
||||
|
||||
const showScrollUp = () => scrollIsNeeded() && !reachedEnd(ButtonTypes.top);
|
||||
const showScrollDown = () => scrollIsNeeded() && !reachedEnd(ButtonTypes.bottom);
|
||||
|
||||
const scroll$ = this.scrollViewport.elementScrolled().pipe(
|
||||
startWith(''),
|
||||
/** Delay first value so that we can wait for items to be rendered in viewport and get correct values */
|
||||
concatMap((value, index) => (index === 0 ? of(value).pipe(delay(0)) : of(value)))
|
||||
);
|
||||
this.showScrollUp$ = scroll$.pipe(map(showScrollUp), distinctUntilChanged());
|
||||
this.showScrollDown$ = scroll$.pipe(map(showScrollDown), distinctUntilChanged());
|
||||
}
|
||||
|
||||
scroll(type: ButtonType): void {
|
||||
const viewportSize = (this.scrollViewport?.getViewportSize() - this.itemSize) * (type === ButtonTypes.top ? -1 : 1);
|
||||
const scrollOffset = this.scrollViewport?.measureScrollOffset('top');
|
||||
this.scrollViewport?.scrollToOffset(scrollOffset + viewportSize, 'smooth');
|
||||
}
|
||||
|
||||
showScroll(type: ButtonType): boolean {
|
||||
const reachedEnd = this.scrollViewport?.measureScrollOffset(type) === 0;
|
||||
const scrollSize = this.scrollViewport?.getDataLength() * this.itemSize;
|
||||
const scrollIsNeeded = this.scrollViewport?.getViewportSize() < scrollSize;
|
||||
|
||||
return scrollIsNeeded && !reachedEnd;
|
||||
}
|
||||
|
||||
@HostListener('document:keyup', ['$event'])
|
||||
spaceAndPageDownScroll(event: KeyboardEvent): void {
|
||||
if (['Space', 'PageDown'].includes(event.code) && (event.target as any).tagName === 'BODY') {
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
<redaction-empty-state *ngIf="noMatch$ | async" [text]="'dossier-listing.no-match.title' | translate"></redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<cdk-virtual-scroll-viewport #scrollViewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="let dw of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
|
||||
[class.pointer]="!!dw"
|
||||
|
||||
@ -28,6 +28,7 @@ import {
|
||||
dossierTemplateChecker
|
||||
} from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
|
||||
const isLeavingScreen = event => event instanceof NavigationStart && event.url !== '/main/dossiers';
|
||||
|
||||
@ -42,8 +43,8 @@ export class DossierListingScreenComponent
|
||||
{
|
||||
readonly itemSize = 95;
|
||||
protected readonly _primaryKey = 'dossierName';
|
||||
readonly tableHeaderLabel = _('dossier-listing.table-header.title');
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly tableHeaderLabel = _('dossier-listing.table-header.title');
|
||||
readonly buttonConfigs: ButtonConfig[] = [
|
||||
{
|
||||
label: _('dossier-listing.add-new'),
|
||||
@ -76,6 +77,8 @@ export class DossierListingScreenComponent
|
||||
private _lastScrollPosition: number;
|
||||
@ViewChild('needsWorkTemplate', { read: TemplateRef, static: true })
|
||||
private readonly _needsWorkTemplate: TemplateRef<any>;
|
||||
@ViewChild(CdkVirtualScrollViewport)
|
||||
private readonly _scrollViewport: CdkVirtualScrollViewport;
|
||||
|
||||
constructor(
|
||||
private readonly _router: Router,
|
||||
@ -120,7 +123,7 @@ export class DossierListingScreenComponent
|
||||
});
|
||||
|
||||
this.addSubscription = this._router.events.pipe(filter(isLeavingScreen)).subscribe(() => {
|
||||
this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top');
|
||||
this._lastScrollPosition = this._scrollViewport.measureScrollOffset('top');
|
||||
});
|
||||
}
|
||||
|
||||
@ -129,7 +132,7 @@ export class DossierListingScreenComponent
|
||||
}
|
||||
|
||||
ngOnAttach() {
|
||||
this.scrollViewport.scrollTo({ top: this._lastScrollPosition });
|
||||
this._scrollViewport.scrollTo({ top: this._lastScrollPosition });
|
||||
this._appStateService.reset();
|
||||
this._loadEntitiesFromState();
|
||||
this.ngOnInit();
|
||||
@ -254,7 +257,7 @@ export class DossierListingScreenComponent
|
||||
slug: 'dossierTemplateFilters',
|
||||
label: this._translateService.instant('filters.dossier-templates'),
|
||||
icon: 'red:template',
|
||||
hide: this.filterService.getFilterGroup('dossierTemplateFilters')?.filters?.length <= 1,
|
||||
hide: this.filterService.getGroup('dossierTemplateFilters')?.filters?.length <= 1,
|
||||
filters: dossierTemplateFilters,
|
||||
checker: dossierTemplateChecker
|
||||
});
|
||||
|
||||
@ -54,11 +54,11 @@
|
||||
|
||||
<redaction-empty-state *ngIf="noMatch$ | async" [text]="'dossier-overview.no-match.title' | translate"></redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<cdk-virtual-scroll-viewport #scrollViewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="let fileStatus of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
|
||||
[class.disabled]="fileStatus.isExcluded"
|
||||
[class.last-opened]="isLastOpenedFile(fileStatus)"
|
||||
[class.last-opened]="isLastOpenedFile(fileStatus.fileId)"
|
||||
[class.pointer]="permissionsService.canOpenFile(fileStatus)"
|
||||
[routerLink]="fileLink(fileStatus)"
|
||||
class="table-item"
|
||||
|
||||
@ -32,6 +32,7 @@ import { fileStatusTranslations } from '../../translations/file-status-translati
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { annotationFilterChecker } from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-overview-screen.component.html',
|
||||
@ -42,11 +43,11 @@ export class DossierOverviewScreenComponent
|
||||
extends BaseListingComponent<FileStatusWrapper>
|
||||
implements OnInit, OnDestroy, OnDetach, OnAttach
|
||||
{
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly itemSize = 80;
|
||||
protected readonly _primaryKey = 'filename';
|
||||
readonly tableHeaderLabel = _('dossier-overview.table-header.title');
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly tableHeaderLabel = _('dossier-overview.table-header.title');
|
||||
private readonly _lastOpenedFileKey = 'Dossier-Recent-' + this.activeDossier.dossierId;
|
||||
|
||||
readonly actionConfigs: ActionConfig[] = [
|
||||
@ -97,7 +98,9 @@ export class DossierOverviewScreenComponent
|
||||
private _lastScrollPosition: number;
|
||||
@ViewChild('needsWorkTemplate', { read: TemplateRef, static: true })
|
||||
private readonly _needsWorkTemplate: TemplateRef<any>;
|
||||
@ViewChild('fileInput') private _fileInput: ElementRef;
|
||||
@ViewChild('fileInput') private readonly _fileInput: ElementRef;
|
||||
@ViewChild(CdkVirtualScrollViewport)
|
||||
private readonly _scrollViewport: CdkVirtualScrollViewport;
|
||||
|
||||
constructor(
|
||||
private readonly _router: Router,
|
||||
@ -126,14 +129,14 @@ export class DossierOverviewScreenComponent
|
||||
}
|
||||
|
||||
get checkedRequiredFilters() {
|
||||
return this.filterService.getFilterGroup('quickFilters')?.filters.filter(f => f.required && f.checked);
|
||||
return this.filterService.getGroup('quickFilters')?.filters.filter(f => f.required && f.checked);
|
||||
}
|
||||
|
||||
get checkedNotRequiredFilters() {
|
||||
return this.filterService.getFilterGroup('quickFilters')?.filters.filter(f => !f.required && f.checked);
|
||||
return this.filterService.getGroup('quickFilters')?.filters.filter(f => !f.required && f.checked);
|
||||
}
|
||||
|
||||
isLastOpenedFile({ fileId }: FileStatusWrapper): boolean {
|
||||
isLastOpenedFile(fileId: string): boolean {
|
||||
return this._userPreferenceService.getLastOpenedFileId(this._lastOpenedFileKey) === fileId;
|
||||
}
|
||||
|
||||
@ -157,7 +160,7 @@ export class DossierOverviewScreenComponent
|
||||
.pipe(filter(event => event instanceof NavigationStart))
|
||||
.subscribe((event: NavigationStart) => {
|
||||
if (!event.url.endsWith(this._appStateService.activeDossierId)) {
|
||||
this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top');
|
||||
this._lastScrollPosition = this._scrollViewport.measureScrollOffset('top');
|
||||
}
|
||||
});
|
||||
|
||||
@ -178,7 +181,7 @@ export class DossierOverviewScreenComponent
|
||||
await this._appStateService.reloadActiveDossierFiles();
|
||||
this._loadEntitiesFromState();
|
||||
await this.ngOnInit();
|
||||
this.scrollViewport.scrollTo({ top: this._lastScrollPosition });
|
||||
this._scrollViewport.scrollTo({ top: this._lastScrollPosition });
|
||||
}
|
||||
|
||||
ngOnDetach() {
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
[text]="'search-screen.no-data' | translate"
|
||||
></redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<cdk-virtual-scroll-viewport #scrollViewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="let item of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
|
||||
[class.pointer]="true"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, Injector, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { Component, Injector, OnDestroy } from '@angular/core';
|
||||
import {
|
||||
AutoUnsubscribeComponent,
|
||||
EntitiesService,
|
||||
@ -9,7 +9,6 @@ import {
|
||||
SortingService,
|
||||
TableColumnConfig
|
||||
} from '@iqser/common-ui';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
|
||||
|
||||
@ -17,9 +16,6 @@ export const DefaultListingServices = [FilterService, SearchService, EntitiesSer
|
||||
|
||||
@Component({ template: '' })
|
||||
export abstract class BaseListingComponent<T extends object> extends AutoUnsubscribeComponent implements OnDestroy {
|
||||
@ViewChild(CdkVirtualScrollViewport)
|
||||
readonly scrollViewport: CdkVirtualScrollViewport;
|
||||
|
||||
readonly filterService = this._injector.get(FilterService);
|
||||
readonly searchService = this._injector.get<SearchService<T>>(SearchService);
|
||||
readonly sortingService = this._injector.get<SortingService<T>>(SortingService);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user