mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[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:
@@ -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?",
|
||||||
|
@@ -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>
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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));
|
||||||
|
Reference in New Issue
Block a user