[ADF-3444] Site list displays only a certain number of sites. (#4368)

* add infinite scrolling to sites loading

* add infinite scrolling to sites loading

* add infinite scrolling to sites loading
This commit is contained in:
Eugenio Romano
2019-02-27 22:25:25 +00:00
committed by GitHub
parent fb12da4ae0
commit 596e801283
4 changed files with 179 additions and 21 deletions

View File

@@ -21,6 +21,9 @@
"NO_LABEL": "No"
}
},
"ADF_DROPDOWN": {
"LOADING": "Loading..."
},
"ADF_CONFIRM_DIALOG": {
"TITLE": "Confirm",
"ACTION": "Do you want to proceed?",

View File

@@ -1,17 +1,20 @@
<div id="site-dropdown-container" class="adf-site-dropdown-container">
<mat-form-field>
<mat-select
#siteSelect
data-automation-id="site-my-files-option"
class="adf-site-dropdown-list-element"
id="site-dropdown"
placeholder="{{placeholder | translate}}"
floatPlaceholder="never"
data-automation-id="site-my-files-select"
[(value)]="selected"
(selectionChange)="selectedSite($event)">
<mat-option *ngFor="let site of siteList?.list.entries" [value]="site">
<mat-option *ngFor="let site of siteList?.list.entries;" [value]="site">
{{ site.entry.title | translate}}
</mat-option>
<mat-option *ngIf="showLoading()" disabled="true" data-automation-id="site-loading">
{{ 'ADF_DROPDOWN.LOADING' | translate}}
</mat-option>
</mat-select>
</mat-form-field>
</div>

View File

@@ -46,6 +46,106 @@ describe('DropdownSitesComponent', () => {
describe('Rendering tests', () => {
describe('Infinite Loading', () => {
beforeEach(async(() => {
siteService = TestBed.get(SitesService);
fixture = TestBed.createComponent(DropdownSitesComponent);
debug = fixture.debugElement;
element = fixture.nativeElement;
component = fixture.componentInstance;
}));
it('Should show loading item if there are more itemes', async(() => {
spyOn(siteService, 'getSites').and.returnValue(of({
'list': {
'pagination': {
'count': 2,
'hasMoreItems': true,
'totalItems': 2,
'skipCount': 0,
'maxItems': 100
},
'entries': [
{
'entry': {
'role': 'SiteManager',
'visibility': 'PUBLIC',
'guid': 'fake-1',
'description': 'fake-test-site',
'id': 'fake-test-site',
'preset': 'site-dashboard',
'title': 'fake-test-site'
}
},
{
'entry': {
'role': 'SiteManager',
'visibility': 'PUBLIC',
'guid': 'fake-2',
'description': 'This is a Sample Alfresco Team site.',
'id': 'swsdp',
'preset': 'site-dashboard',
'title': 'fake-test-2'
}
}
]
}
}));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('[data-automation-id="lsite-loading"]')).toBeDefined();
});
}));
it('Should not show loading item if there are more itemes', async(() => {
spyOn(siteService, 'getSites').and.returnValue(of({
'list': {
'pagination': {
'count': 2,
'hasMoreItems': false,
'totalItems': 2,
'skipCount': 0,
'maxItems': 100
},
'entries': [
{
'entry': {
'role': 'SiteManager',
'visibility': 'PUBLIC',
'guid': 'fake-1',
'description': 'fake-test-site',
'id': 'fake-test-site',
'preset': 'site-dashboard',
'title': 'fake-test-site'
}
},
{
'entry': {
'role': 'SiteManager',
'visibility': 'PUBLIC',
'guid': 'fake-2',
'description': 'This is a Sample Alfresco Team site.',
'id': 'swsdp',
'preset': 'site-dashboard',
'title': 'fake-test-2'
}
}
]
}
}));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('[data-automation-id="lsite-loading"]')).toBeNull();
});
}));
});
describe('Sites', () => {
beforeEach(async(() => {
@@ -93,7 +193,7 @@ describe('DropdownSitesComponent', () => {
}));
function openSelectBox() {
const selectBox = debug.query(By.css(('[data-automation-id="site-my-files-select"] .mat-select-trigger')));
const selectBox = debug.query(By.css(('[data-automation-id="site-my-files-option"] .mat-select-trigger')));
selectBox.triggerEventHandler('click', null);
}

View File

@@ -15,9 +15,10 @@
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { SitesService, LogService } from '@alfresco/adf-core';
import { SitePaging, SiteEntry } from '@alfresco/js-api';
import { MatSelect } from '@angular/material';
export enum Relations {
Members = 'members',
@@ -68,6 +69,15 @@ export class DropdownSitesComponent implements OnInit {
@Output()
change: EventEmitter<SiteEntry> = new EventEmitter();
@ViewChild('siteSelect')
siteSelect: MatSelect;
private loading = true;
private skipCount = 0;
private readonly MAX_ITEMS = 50;
private readonly ITEM_HEIGHT = 45;
private readonly ITEM_HEIGHT_TO_WAIT_BEFORE_LOAD_NEXT = (this.ITEM_HEIGHT * (this.MAX_ITEMS / 2));
selected: SiteEntry = null;
public MY_FILES_VALUE = '-my-';
@@ -77,47 +87,89 @@ export class DropdownSitesComponent implements OnInit {
}
ngOnInit() {
this.siteSelect.openedChange.subscribe(() => {
if (this.siteSelect.panelOpen) {
this.siteSelect.panel.nativeElement.addEventListener('scroll', (event) => this.loadAllOnScroll(event));
}
});
if (!this.siteList) {
this.setDefaultSiteList();
this.loadSiteList();
}
}
loadAllOnScroll(event) {
if (this.isInfiniteScrollingEnabled() && this.isScrollInNextFetchArea(event)) {
this.loading = true;
this.loadSiteList();
}
}
isScrollInNextFetchArea(event) {
return event.target.scrollTop >= (event.target.scrollHeight - event.target.offsetHeight - this.ITEM_HEIGHT_TO_WAIT_BEFORE_LOAD_NEXT);
}
selectedSite(event: any) {
this.change.emit(event.value);
}
private setDefaultSiteList() {
let extendedOptions = null;
private loadSiteList() {
let extendedOptions: any = {
skipCount: this.skipCount,
maxItems: this.MAX_ITEMS
};
this.skipCount += this.MAX_ITEMS;
if (this.relations) {
extendedOptions = { relations: [this.relations] };
extendedOptions.relations = [this.relations];
}
this.sitesService.getSites(extendedOptions).subscribe((sitePaging: SitePaging) => {
this.siteList = this.relations === Relations.Members ? this.filteredResultsByMember(sitePaging) : sitePaging;
if (!this.siteList) {
this.siteList = this.relations === Relations.Members ? this.filteredResultsByMember(sitePaging) : sitePaging;
if (!this.hideMyFiles) {
let siteEntry = new SiteEntry({
entry: {
id: '-my-',
guid: '-my-',
title: 'DROPDOWN.MY_FILES_OPTION'
if (!this.hideMyFiles) {
let siteEntry = new SiteEntry({
entry: {
id: '-my-',
guid: '-my-',
title: 'DROPDOWN.MY_FILES_OPTION'
}
});
this.siteList.list.entries.unshift(siteEntry);
if (!this.value) {
this.value = '-my-';
}
});
this.siteList.list.entries.unshift(siteEntry);
if (!this.value) {
this.value = '-my-';
}
} else {
let siteList: SitePaging = this.relations === Relations.Members ? this.filteredResultsByMember(sitePaging) : sitePaging;
this.siteList.list.entries = this.siteList.list.entries.concat(siteList.list.entries);
this.siteList.list.pagination = sitePaging.list.pagination;
}
this.selected = this.siteList.list.entries.find((site: SiteEntry) => site.entry.id === this.value);
this.loading = false;
},
(error) => {
this.logService.error(error);
});
}
showLoading(): boolean {
return this.loading && (this.siteList && this.siteList.list.pagination && this.siteList.list.pagination.hasMoreItems);
}
isInfiniteScrollingEnabled(): boolean {
return !this.loading && (this.siteList && this.siteList.list.pagination && this.siteList.list.pagination.hasMoreItems);
}
private filteredResultsByMember(sites: SitePaging): SitePaging {
const loggedUserName = this.sitesService.getEcmCurrentLoggedUserName();
sites.list.entries = sites.list.entries.filter((site) => this.isCurrentUserMember(site, loggedUserName));