Pull request #190: add scroll button
Merge in RED/ui from RED-1486 to master * commit '4f8b2adaf32f82881ad290d8a68f8f66743d950b': add scroll button
This commit is contained in:
commit
b9f8d28e8d
@ -18,6 +18,7 @@ export class IconsModule {
|
||||
'analyse',
|
||||
'approved',
|
||||
'arrow-down',
|
||||
'arrow-down-o',
|
||||
'arrow-right',
|
||||
'arrow-up',
|
||||
'assign',
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
<button class="scroll-button pointer" *ngIf="showScrollButton()" (click)="scroll()">
|
||||
<mat-icon svgIcon="red:arrow-down-o"></mat-icon>
|
||||
</button>
|
||||
@ -0,0 +1,19 @@
|
||||
@import 'apps/red-ui/src/assets/styles/red-variables';
|
||||
|
||||
.scroll-button {
|
||||
background-color: $white;
|
||||
position: absolute;
|
||||
bottom: 30px;
|
||||
right: 0;
|
||||
height: 40px;
|
||||
width: 44px;
|
||||
border: none;
|
||||
border-radius: 8px 0 0 8px;
|
||||
box-shadow: -1px 1px 5px 0 rgba(40, 50, 65, 0.25);
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
color: $grey-7;
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
import { Component, HostListener, Input } from '@angular/core';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-scroll-button',
|
||||
templateUrl: './scroll-button.component.html',
|
||||
styleUrls: ['./scroll-button.component.scss']
|
||||
})
|
||||
export class ScrollButtonComponent {
|
||||
@Input()
|
||||
scrollViewport: CdkVirtualScrollViewport;
|
||||
@Input()
|
||||
itemSize: number;
|
||||
|
||||
scroll(): void {
|
||||
const scrollOffset = this.scrollViewport.measureScrollOffset('top');
|
||||
const ligaturePortion = 50;
|
||||
const viewportSize = this.scrollViewport.getViewportSize() - ligaturePortion;
|
||||
|
||||
this.scrollViewport.scrollToOffset(scrollOffset + viewportSize, 'smooth');
|
||||
}
|
||||
|
||||
showScrollButton(): boolean {
|
||||
const reachedBottom = this.scrollViewport.measureScrollOffset('bottom') === 0;
|
||||
const scrollSize = this.scrollViewport.getDataLength() * this.itemSize;
|
||||
const scrollIsNeeded = this.scrollViewport.getViewportSize() < scrollSize;
|
||||
|
||||
return scrollIsNeeded && !reachedBottom;
|
||||
}
|
||||
|
||||
@HostListener('document:keyup', ['$event'])
|
||||
spaceAndPageDownScroll(event: KeyboardEvent): void {
|
||||
if (['Space', 'PageDown'].includes(event.code)) {
|
||||
this.scroll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -44,6 +44,7 @@ import { EditProjectDictionaryComponent } from './dialogs/edit-project-dialog/di
|
||||
import { EditProjectTeamMembersComponent } from './dialogs/edit-project-dialog/team-members/edit-project-team-members.component';
|
||||
import { TeamMembersManagerComponent } from './components/team-members-manager/team-members-manager.component';
|
||||
import { TeamMembersDialogComponent } from './dialogs/team-members-dialog/team-members-dialog.component';
|
||||
import { ScrollButtonComponent } from './components/scroll-button/scroll-button.component';
|
||||
|
||||
const screens = [
|
||||
ProjectListingScreenComponent,
|
||||
@ -59,7 +60,8 @@ const dialogs = [
|
||||
ForceRedactionDialogComponent,
|
||||
RemoveAnnotationsDialogComponent,
|
||||
DocumentInfoDialogComponent,
|
||||
AssignReviewerApproverDialogComponent
|
||||
AssignReviewerApproverDialogComponent,
|
||||
DossierDictionaryDialogComponent
|
||||
];
|
||||
|
||||
const components = [
|
||||
@ -84,6 +86,7 @@ const components = [
|
||||
EditProjectDictionaryComponent,
|
||||
EditProjectTeamMembersComponent,
|
||||
TeamMembersManagerComponent,
|
||||
ScrollButtonComponent,
|
||||
|
||||
...screens,
|
||||
...dialogs
|
||||
@ -101,7 +104,7 @@ const services = [
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [...components, DossierDictionaryDialogComponent],
|
||||
declarations: [...components],
|
||||
providers: [...services],
|
||||
imports: [CommonModule, SharedModule, FileUploadDownloadModule, ProjectsRoutingModule]
|
||||
})
|
||||
|
||||
@ -104,7 +104,7 @@
|
||||
type="no-match"
|
||||
></redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="85" redactionHasScrollbar>
|
||||
<cdk-virtual-scroll-viewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="
|
||||
let pw of displayedEntities
|
||||
@ -169,6 +169,12 @@
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
|
||||
<redaction-scroll-button
|
||||
[scrollViewport]="scrollBar"
|
||||
[itemSize]="itemSize"
|
||||
*ngIf="scrollBar && itemSize > 0"
|
||||
></redaction-scroll-button>
|
||||
</div>
|
||||
|
||||
<div class="right-container" redactionHasScrollbar>
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
@import '../../../../../assets/styles/red-variables';
|
||||
|
||||
.content-container {
|
||||
position: relative;
|
||||
|
||||
cdk-virtual-scroll-viewport {
|
||||
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
||||
grid-template-columns: 2fr 1fr 1fr auto 11px;
|
||||
|
||||
@ -47,12 +47,13 @@ export class ProjectListingScreenComponent
|
||||
} = {
|
||||
statusFilters: []
|
||||
};
|
||||
readonly itemSize = 85;
|
||||
protected readonly _searchKey = 'name';
|
||||
protected readonly _sortKey = 'project-listing';
|
||||
private _projectAutoUpdateTimer: Subscription;
|
||||
private _lastScrollPosition: number;
|
||||
|
||||
@ViewChild(CdkVirtualScrollViewport) private _scrollBar: CdkVirtualScrollViewport;
|
||||
@ViewChild(CdkVirtualScrollViewport) scrollBar: CdkVirtualScrollViewport;
|
||||
|
||||
@ViewChild('statusFilter') private _statusFilterComponent: FilterComponent;
|
||||
@ViewChild('peopleFilter') private _peopleFilterComponent: FilterComponent;
|
||||
@ -146,7 +147,7 @@ export class ProjectListingScreenComponent
|
||||
)
|
||||
.subscribe((event) => {
|
||||
if (event instanceof NavigationStart && event.url !== '/main/projects') {
|
||||
this._lastScrollPosition = this._scrollBar.measureScrollOffset('top');
|
||||
this._lastScrollPosition = this.scrollBar.measureScrollOffset('top');
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -155,7 +156,7 @@ export class ProjectListingScreenComponent
|
||||
this._appStateService.reset();
|
||||
this._loadEntitiesFromState();
|
||||
this.ngOnInit();
|
||||
this._scrollBar.scrollTo({ top: this._lastScrollPosition });
|
||||
this.scrollBar.scrollTo({ top: this._lastScrollPosition });
|
||||
}
|
||||
|
||||
ngOnDetach() {
|
||||
|
||||
@ -184,7 +184,7 @@
|
||||
type="no-match"
|
||||
></redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="80" redactionHasScrollbar>
|
||||
<cdk-virtual-scroll-viewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="
|
||||
let fileStatus of displayedEntities
|
||||
@ -309,6 +309,12 @@
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
|
||||
<redaction-scroll-button
|
||||
[scrollViewport]="scrollBar"
|
||||
[itemSize]="itemSize"
|
||||
*ngIf="scrollBar && itemSize > 0"
|
||||
></redaction-scroll-button>
|
||||
</div>
|
||||
|
||||
<div [class.collapsed]="collapsedDetails" class="right-container" redactionHasScrollbar>
|
||||
|
||||
@ -48,6 +48,7 @@ export class ProjectOverviewScreenComponent
|
||||
needsWorkFilters: FilterModel[];
|
||||
statusFilters: FilterModel[];
|
||||
} = { needsWorkFilters: [], statusFilters: [] };
|
||||
readonly itemSize = 80;
|
||||
protected readonly _searchKey = 'searchField';
|
||||
protected readonly _selectionKey = 'fileId';
|
||||
protected readonly _sortKey = 'project-overview';
|
||||
@ -59,7 +60,7 @@ export class ProjectOverviewScreenComponent
|
||||
private _lastScrollPosition: number;
|
||||
private _lastOpenedFileId = '';
|
||||
|
||||
@ViewChild(CdkVirtualScrollViewport) private _scrollBar: CdkVirtualScrollViewport;
|
||||
@ViewChild(CdkVirtualScrollViewport) scrollBar: CdkVirtualScrollViewport;
|
||||
|
||||
@ViewChild('statusFilter') private _statusFilterComponent: FilterComponent;
|
||||
@ViewChild('peopleFilter') private _peopleFilterComponent: FilterComponent;
|
||||
@ -147,7 +148,7 @@ export class ProjectOverviewScreenComponent
|
||||
.pipe(filter((events) => events instanceof NavigationStart))
|
||||
.subscribe((event: NavigationStart) => {
|
||||
if (!event.url.endsWith(this._appStateService.activeProjectId)) {
|
||||
this._lastScrollPosition = this._scrollBar.measureScrollOffset('top');
|
||||
this._lastScrollPosition = this.scrollBar.measureScrollOffset('top');
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -162,7 +163,7 @@ export class ProjectOverviewScreenComponent
|
||||
ngOnAttach() {
|
||||
this._loadEntitiesFromState();
|
||||
this.ngOnInit();
|
||||
this._scrollBar.scrollTo({ top: this._lastScrollPosition });
|
||||
this.scrollBar.scrollTo({ top: this._lastScrollPosition });
|
||||
}
|
||||
|
||||
ngOnDetach() {
|
||||
|
||||
18
apps/red-ui/src/assets/icons/general/arrow-down-o.svg
Normal file
18
apps/red-ui/src/assets/icons/general/arrow-down-o.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14.8285 12.0259L16.2427 13.4402L12 17.6828L7.7574 13.4402L9.17161 12.0259L11 13.8544V6.31724H13V13.8544L14.8285 12.0259Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M19.7782 19.7782C15.4824 24.0739 8.51759 24.0739 4.22183 19.7782C-0.0739417 15.4824 -0.0739417 8.51759 4.22183 4.22183C8.51759 -0.0739419 15.4824 -0.0739419 19.7782 4.22183C24.0739 8.51759 24.0739 15.4824 19.7782 19.7782ZM18.364 18.364C14.8492 21.8787 9.15076 21.8787 5.63604 18.364C2.12132 14.8492 2.12132 9.15076 5.63604 5.63604C9.15076 2.12132 14.8492 2.12132 18.364 5.63604C21.8787 9.15076 21.8787 14.8492 18.364 18.364Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 841 B |
Loading…
x
Reference in New Issue
Block a user