[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" "NO_LABEL": "No"
} }
}, },
"ADF_DROPDOWN": {
"LOADING": "Loading..."
},
"ADF_CONFIRM_DIALOG": { "ADF_CONFIRM_DIALOG": {
"TITLE": "Confirm", "TITLE": "Confirm",
"ACTION": "Do you want to proceed?", "ACTION": "Do you want to proceed?",

View File

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

View File

@@ -46,6 +46,106 @@ describe('DropdownSitesComponent', () => {
describe('Rendering tests', () => { 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', () => { describe('Sites', () => {
beforeEach(async(() => { beforeEach(async(() => {
@@ -93,7 +193,7 @@ describe('DropdownSitesComponent', () => {
})); }));
function openSelectBox() { 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); selectBox.triggerEventHandler('click', null);
} }

View File

@@ -15,9 +15,10 @@
* limitations under the License. * 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 { SitesService, LogService } from '@alfresco/adf-core';
import { SitePaging, SiteEntry } from '@alfresco/js-api'; import { SitePaging, SiteEntry } from '@alfresco/js-api';
import { MatSelect } from '@angular/material';
export enum Relations { export enum Relations {
Members = 'members', Members = 'members',
@@ -68,6 +69,15 @@ export class DropdownSitesComponent implements OnInit {
@Output() @Output()
change: EventEmitter<SiteEntry> = new EventEmitter(); 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; selected: SiteEntry = null;
public MY_FILES_VALUE = '-my-'; public MY_FILES_VALUE = '-my-';
@@ -77,47 +87,89 @@ export class DropdownSitesComponent implements OnInit {
} }
ngOnInit() { ngOnInit() {
this.siteSelect.openedChange.subscribe(() => {
if (this.siteSelect.panelOpen) {
this.siteSelect.panel.nativeElement.addEventListener('scroll', (event) => this.loadAllOnScroll(event));
}
});
if (!this.siteList) { 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) { selectedSite(event: any) {
this.change.emit(event.value); this.change.emit(event.value);
} }
private setDefaultSiteList() { private loadSiteList() {
let extendedOptions = null; let extendedOptions: any = {
skipCount: this.skipCount,
maxItems: this.MAX_ITEMS
};
this.skipCount += this.MAX_ITEMS;
if (this.relations) { if (this.relations) {
extendedOptions = { relations: [this.relations] }; extendedOptions.relations = [this.relations];
} }
this.sitesService.getSites(extendedOptions).subscribe((sitePaging: SitePaging) => { 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) { if (!this.hideMyFiles) {
let siteEntry = new SiteEntry({ let siteEntry = new SiteEntry({
entry: { entry: {
id: '-my-', id: '-my-',
guid: '-my-', guid: '-my-',
title: 'DROPDOWN.MY_FILES_OPTION' 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.selected = this.siteList.list.entries.find((site: SiteEntry) => site.entry.id === this.value);
this.loading = false;
}, },
(error) => { (error) => {
this.logService.error(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 { private filteredResultsByMember(sites: SitePaging): SitePaging {
const loggedUserName = this.sitesService.getEcmCurrentLoggedUserName(); const loggedUserName = this.sitesService.getEcmCurrentLoggedUserName();
sites.list.entries = sites.list.entries.filter((site) => this.isCurrentUserMember(site, loggedUserName)); sites.list.entries = sites.list.entries.filter((site) => this.isCurrentUserMember(site, loggedUserName));