diff --git a/lib/content-services/i18n/en.json b/lib/content-services/i18n/en.json
index 71cd50f25d..25624894c6 100644
--- a/lib/content-services/i18n/en.json
+++ b/lib/content-services/i18n/en.json
@@ -21,6 +21,9 @@
"NO_LABEL": "No"
}
},
+ "ADF_DROPDOWN": {
+ "LOADING": "Loading..."
+ },
"ADF_CONFIRM_DIALOG": {
"TITLE": "Confirm",
"ACTION": "Do you want to proceed?",
diff --git a/lib/content-services/site-dropdown/sites-dropdown.component.html b/lib/content-services/site-dropdown/sites-dropdown.component.html
index 716a1ccfa5..43ed4f552a 100644
--- a/lib/content-services/site-dropdown/sites-dropdown.component.html
+++ b/lib/content-services/site-dropdown/sites-dropdown.component.html
@@ -1,17 +1,20 @@
-
+
{{ site.entry.title | translate}}
+
+ {{ 'ADF_DROPDOWN.LOADING' | translate}}
+
diff --git a/lib/content-services/site-dropdown/sites-dropdown.component.spec.ts b/lib/content-services/site-dropdown/sites-dropdown.component.spec.ts
index 4ff38cb72e..5103eb976f 100644
--- a/lib/content-services/site-dropdown/sites-dropdown.component.spec.ts
+++ b/lib/content-services/site-dropdown/sites-dropdown.component.spec.ts
@@ -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);
}
diff --git a/lib/content-services/site-dropdown/sites-dropdown.component.ts b/lib/content-services/site-dropdown/sites-dropdown.component.ts
index 31e445517b..d77d29dea4 100644
--- a/lib/content-services/site-dropdown/sites-dropdown.component.ts
+++ b/lib/content-services/site-dropdown/sites-dropdown.component.ts
@@ -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 = 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));