From 9df7530e5db2390971de3beaea78365cdc976c37 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Sat, 7 Aug 2021 18:55:27 +0300 Subject: [PATCH] update scroll button --- .../scroll-button.component.html | 4 +-- .../scroll-button/scroll-button.component.ts | 36 +++++++++++++------ .../dossier-listing-screen.component.html | 2 +- .../dossier-listing-screen.component.ts | 11 +++--- .../dossier-overview-screen.component.html | 4 +-- .../dossier-overview-screen.component.ts | 19 +++++----- .../search-screen.component.html | 2 +- .../shared/base/base-listing.component.ts | 6 +--- 8 files changed, 50 insertions(+), 34 deletions(-) diff --git a/apps/red-ui/src/app/modules/dossier/components/scroll-button/scroll-button.component.html b/apps/red-ui/src/app/modules/dossier/components/scroll-button/scroll-button.component.html index 8c69dd7d9..d303ac067 100644 --- a/apps/red-ui/src/app/modules/dossier/components/scroll-button/scroll-button.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/scroll-button/scroll-button.component.html @@ -1,7 +1,7 @@ - - diff --git a/apps/red-ui/src/app/modules/dossier/components/scroll-button/scroll-button.component.ts b/apps/red-ui/src/app/modules/dossier/components/scroll-button/scroll-button.component.ts index 6c253406f..335bbfa26 100644 --- a/apps/red-ui/src/app/modules/dossier/components/scroll-button/scroll-button.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/scroll-button/scroll-button.component.ts @@ -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; + showScrollDown$: Observable; + + 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') { diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.html index 80b51c272..96b57646e 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.html @@ -24,7 +24,7 @@ - +
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; + @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 }); diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html index 1dd39f70e..0aa509fea 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html @@ -54,11 +54,11 @@ - +
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; - @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() { diff --git a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html index c3f629476..e8b2c4fde 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html @@ -21,7 +21,7 @@ [text]="'search-screen.no-data' | translate" > - +
extends AutoUnsubscribeComponent implements OnDestroy { - @ViewChild(CdkVirtualScrollViewport) - readonly scrollViewport: CdkVirtualScrollViewport; - readonly filterService = this._injector.get(FilterService); readonly searchService = this._injector.get>(SearchService); readonly sortingService = this._injector.get>(SortingService);