diff --git a/lib/content-services/breadcrumb/breadcrumb.component.spec.ts b/lib/content-services/breadcrumb/breadcrumb.component.spec.ts index 3a1f4292de..7cf8667b68 100644 --- a/lib/content-services/breadcrumb/breadcrumb.component.spec.ts +++ b/lib/content-services/breadcrumb/breadcrumb.component.spec.ts @@ -20,25 +20,29 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { PathElementEntity } from '@alfresco/js-api'; import { setupTestBed } from '@alfresco/adf-core'; import { fakeNodeWithCreatePermission } from '../mock'; -import { DocumentListComponent } from '../document-list'; +import { DocumentListComponent, DocumentListService } from '../document-list'; import { BreadcrumbComponent } from './breadcrumb.component'; import { ContentTestingModule } from '../testing/content.testing.module'; +import { of } from 'rxjs'; describe('Breadcrumb', () => { let component: BreadcrumbComponent; let fixture: ComponentFixture; - let documentList: DocumentListComponent; + let documentListService: DocumentListService = jasmine.createSpyObj({'loadFolderByNodeId' : of(''), 'isCustomSourceService': false}); + let documentListComponent: DocumentListComponent; setupTestBed({ imports: [ContentTestingModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] + schemas: [CUSTOM_ELEMENTS_SCHEMA], + providers : [{ provide: DocumentListService, useValue: documentListService }] }); beforeEach(() => { fixture = TestBed.createComponent(BreadcrumbComponent); component = fixture.componentInstance; - documentList = TestBed.createComponent(DocumentListComponent).componentInstance; + documentListComponent = TestBed.createComponent(DocumentListComponent).componentInstance; + documentListService = TestBed.get(DocumentListService); }); afterEach(() => { @@ -69,17 +73,17 @@ describe('Breadcrumb', () => { component.onRoutePathClick(node, null); }); - it('should update document list on click', (done) => { - spyOn(documentList, 'loadFolderByNodeId').and.stub(); + it('should update document list on click', () => { const node = { id: '-id-', name: 'name' }; - component.target = documentList; + component.target = documentListComponent; component.onRoutePathClick(node, null); - setTimeout(() => { - expect(documentList.loadFolderByNodeId).toHaveBeenCalledWith(node.id); - done(); - }, 0); + + expect(documentListService.loadFolderByNodeId).toHaveBeenCalledWith(node.id, + documentListComponent.DEFAULT_PAGINATION, + documentListComponent.includeFields, + documentListComponent.where); }); it('should not parse the route when node not provided', () => { diff --git a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts index 12983a1385..ec64a09e49 100644 --- a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts +++ b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts @@ -20,25 +20,29 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { setupTestBed } from '@alfresco/adf-core'; import { fakeNodeWithCreatePermission } from '../mock'; -import { DocumentListComponent } from '../document-list'; +import { DocumentListComponent, DocumentListService } from '../document-list'; import { DropdownBreadcrumbComponent } from './dropdown-breadcrumb.component'; import { ContentTestingModule } from '../testing/content.testing.module'; +import { of } from 'rxjs'; describe('DropdownBreadcrumb', () => { let component: DropdownBreadcrumbComponent; let fixture: ComponentFixture; let documentList: DocumentListComponent; + let documentListService: DocumentListService = jasmine.createSpyObj({'loadFolderByNodeId' : of(''), 'isCustomSourceService': false}); setupTestBed({ imports: [ContentTestingModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] + schemas: [CUSTOM_ELEMENTS_SCHEMA], + providers : [{ provide: DocumentListService, useValue: documentListService }] }); beforeEach(async(() => { fixture = TestBed.createComponent(DropdownBreadcrumbComponent); component = fixture.componentInstance; documentList = TestBed.createComponent(DocumentListComponent).componentInstance; + documentListService = TestBed.get(DocumentListService); })); afterEach(async(() => { @@ -151,7 +155,6 @@ describe('DropdownBreadcrumb', () => { }); it('should update document list when clicking on an option', (done) => { - spyOn(documentList, 'loadFolderByNodeId').and.stub(); component.target = documentList; const fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); fakeNodeWithCreatePermissionInstance.path.elements = [{ id: '1', name: 'Stark Industries' }]; @@ -160,10 +163,9 @@ describe('DropdownBreadcrumb', () => { fixture.whenStable().then(() => { openSelect(); fixture.whenStable().then(() => { - clickOnTheFirstOption(); - expect(documentList.loadFolderByNodeId).toHaveBeenCalledWith('1'); + expect(documentListService.loadFolderByNodeId).toHaveBeenCalledWith('1', documentList.DEFAULT_PAGINATION, undefined, undefined); done(); }); }); diff --git a/lib/content-services/content-node-selector/content-node-dialog.service.ts b/lib/content-services/content-node-selector/content-node-dialog.service.ts index b1ef6e41ce..5a343b1d5f 100644 --- a/lib/content-services/content-node-selector/content-node-dialog.service.ts +++ b/lib/content-services/content-node-selector/content-node-dialog.service.ts @@ -17,7 +17,7 @@ import { MatDialog } from '@angular/material'; import { EventEmitter, Injectable, Output } from '@angular/core'; -import { ContentService } from '@alfresco/adf-core'; +import { ContentService, ThumbnailService } from '@alfresco/adf-core'; import { Subject, Observable, throwError } from 'rxjs'; import { ShareDataRow } from '../document-list/data/share-data-row.model'; import { Node, NodeEntry, SitePaging } from '@alfresco/js-api'; @@ -49,7 +49,8 @@ export class ContentNodeDialogService { private contentService: ContentService, private documentListService: DocumentListService, private siteService: SitesService, - private translation: TranslationService) { + private translation: TranslationService, + private thumbnailService: ThumbnailService) { } /** @@ -224,7 +225,7 @@ export class ContentNodeDialogService { private imageResolver(row: ShareDataRow, col: DataColumn): string | null { const entry: Node = row.node.entry; if (!this.contentService.hasAllowableOperations(entry, 'create')) { - return this.documentListService.getMimeTypeIcon('disable/folder'); + return this.thumbnailService.getMimeTypeIcon('disable/folder'); } return null; diff --git a/lib/content-services/document-list/components/document-list.component.spec.ts b/lib/content-services/document-list/components/document-list.component.spec.ts index 05aa233fbd..a0e87f8169 100644 --- a/lib/content-services/document-list/components/document-list.component.spec.ts +++ b/lib/content-services/document-list/components/document-list.component.spec.ts @@ -866,9 +866,9 @@ describe('DocumentList', () => { it('should display folder content from loadFolderByNodeId on reload if currentFolderId defined', () => { documentList.currentFolderId = 'id-folder'; - spyOn(documentList, 'loadFolderByNodeId').and.stub(); + spyOn(documentList, 'loadFolder').and.stub(); documentList.reload(); - expect(documentList.loadFolderByNodeId).toHaveBeenCalled(); + expect(documentList.loadFolder).toHaveBeenCalled(); }); it('should require node to resolve context menu actions', () => { @@ -1050,8 +1050,8 @@ describe('DocumentList', () => { disposableError.unsubscribe(); done(); }); - - documentList.loadFolderByNodeId('123'); + documentList.currentFolderId = '123'; + documentList.loadFolder(); }); it('should emit folderChange event when a folder node is clicked', (done) => { @@ -1075,7 +1075,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('123'); + documentList.currentFolderId = '123'; + documentList.loadFolder(); }); it('should reset noPermission upon reload', () => { @@ -1135,7 +1136,8 @@ describe('DocumentList', () => { it('should fetch trashcan', () => { spyOn(apiService.nodesApi, 'getDeletedNodes').and.returnValue(Promise.resolve(null)); - documentList.loadFolderByNodeId('-trashcan-'); + documentList.currentFolderId = '-trashcan-'; + documentList.loadFolder(); expect(apiService.nodesApi.getDeletedNodes).toHaveBeenCalled(); }); @@ -1148,14 +1150,16 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-trashcan-'); + documentList.currentFolderId = '-trashcan-'; + documentList.loadFolder(); }); it('should fetch shared links', () => { const sharedlinksApi = apiService.getInstance().core.sharedlinksApi; spyOn(sharedlinksApi, 'findSharedLinks').and.returnValue(Promise.resolve(null)); - documentList.loadFolderByNodeId('-sharedlinks-'); + documentList.currentFolderId = '-sharedlinks-'; + documentList.loadFolder(); expect(sharedlinksApi.findSharedLinks).toHaveBeenCalled(); }); @@ -1169,13 +1173,15 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-sharedlinks-'); + documentList.currentFolderId = '-sharedlinks-'; + documentList.loadFolder(); }); it('should fetch sites', () => { const sitesApi = apiService.getInstance().core.sitesApi; - documentList.loadFolderByNodeId('-sites-'); + documentList.currentFolderId = '-sites-'; + documentList.loadFolder(); expect(sitesApi.getSites).toHaveBeenCalled(); }); @@ -1188,7 +1194,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-sites-'); + documentList.currentFolderId = '-sites-'; + documentList.loadFolder(); }); it('should assure that sites have name property set', (done) => { @@ -1201,7 +1208,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-sites-'); + documentList.currentFolderId = '-sites-'; + documentList.loadFolder(); }); it('should assure that sites have name property set correctly', (done) => { @@ -1214,14 +1222,16 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-sites-'); + documentList.currentFolderId = '-sites-'; + documentList.loadFolder(); }); it('should fetch user membership sites', () => { const peopleApi = apiService.getInstance().core.peopleApi; spyOn(peopleApi, 'listSiteMembershipsForPerson').and.returnValue(Promise.resolve(fakeGetSiteMembership)); - documentList.loadFolderByNodeId('-mysites-'); + documentList.currentFolderId = '-mysites-'; + documentList.loadFolder(); expect(peopleApi.listSiteMembershipsForPerson).toHaveBeenCalled(); }); @@ -1235,7 +1245,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-mysites-'); + documentList.currentFolderId = '-mysites-'; + documentList.loadFolder(); }); it('should assure that user membership sites have name property set', (done) => { @@ -1243,7 +1254,8 @@ describe('DocumentList', () => { const peopleApi = apiService.getInstance().core.peopleApi; spyOn(peopleApi, 'listSiteMembershipsForPerson').and.returnValue(Promise.resolve(fakeGetSiteMembership)); - documentList.loadFolderByNodeId('-mysites-'); + documentList.currentFolderId = '-mysites-'; + documentList.loadFolder(); expect(peopleApi.listSiteMembershipsForPerson).toHaveBeenCalled(); const disposableReady = documentList.ready.subscribe((page) => { @@ -1259,7 +1271,8 @@ describe('DocumentList', () => { const peopleApi = apiService.getInstance().core.peopleApi; spyOn(peopleApi, 'listSiteMembershipsForPerson').and.returnValue(Promise.resolve(fakeGetSiteMembership)); - documentList.loadFolderByNodeId('-mysites-'); + documentList.currentFolderId = '-mysites-'; + documentList.loadFolder(); expect(peopleApi.listSiteMembershipsForPerson).toHaveBeenCalled(); const disposableReady = documentList.ready.subscribe((page) => { @@ -1274,7 +1287,8 @@ describe('DocumentList', () => { const favoritesApi = apiService.getInstance().core.favoritesApi; spyFavorite.and.returnValue(Promise.resolve(null)); - documentList.loadFolderByNodeId('-favorites-'); + documentList.currentFolderId = '-favorites-'; + documentList.loadFolder(); expect(favoritesApi.getFavorites).toHaveBeenCalled(); }); @@ -1287,7 +1301,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-favorites-'); + documentList.currentFolderId = '-favorites-'; + documentList.loadFolder(); }); it('should fetch recent', () => { @@ -1295,7 +1310,8 @@ describe('DocumentList', () => { const getPersonSpy = spyOn(apiService.peopleApi, 'getPerson').and.returnValue(Promise.resolve(person)); - documentList.loadFolderByNodeId('-recent-'); + documentList.currentFolderId = '-recent-'; + documentList.loadFolder(); expect(getPersonSpy).toHaveBeenCalledWith('-me-'); }); @@ -1309,7 +1325,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-recent-'); + documentList.currentFolderId = '-recent-'; + documentList.loadFolder(); }); it('should emit error when fetch recent fails on search call', (done) => { @@ -1321,7 +1338,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-recent-'); + documentList.currentFolderId = '-recent-'; + documentList.loadFolder(); }); it('should have correct currentFolderId on loading folder by node id', () => { @@ -1330,7 +1348,8 @@ describe('DocumentList', () => { const peopleApi = apiService.getInstance().core.peopleApi; spyOn(peopleApi, 'listSiteMembershipsForPerson').and.returnValue(Promise.resolve(fakeGetSiteMembership)); - documentList.loadFolderByNodeId('-mysites-'); + documentList.currentFolderId = '-mysites-'; + documentList.loadFolder(); expect(documentList.currentFolderId).toBe('-mysites-'); }); diff --git a/lib/content-services/document-list/components/document-list.component.ts b/lib/content-services/document-list/components/document-list.component.ts index 620f9ea4cd..5484758c3d 100644 --- a/lib/content-services/document-list/components/document-list.component.ts +++ b/lib/content-services/document-list/components/document-list.component.ts @@ -53,12 +53,11 @@ import { ShareDataTableAdapter } from './../data/share-datatable-adapter'; import { presetsDefaultModel } from '../models/preset.model'; import { ContentActionModel } from './../models/content-action.model'; import { PermissionStyleModel } from './../models/permissions-style.model'; -import { DocumentListService } from './../services/document-list.service'; import { NodeEntityEvent, NodeEntryEvent } from './node.event'; -import { CustomResourcesService } from './../services/custom-resources.service'; import { NavigableComponentInterface } from '../../breadcrumb/navigable-component.interface'; import { RowFilter } from '../data/row-filter.model'; -import { Observable } from 'rxjs/index'; +import { DocumentListService } from '../services/document-list.service'; +import { DocumentLoaderNode } from '../models/document-folder.model'; @Component({ selector: 'adf-document-list', @@ -323,7 +322,6 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte private elementRef: ElementRef, private appConfig: AppConfigService, private userPreferencesService: UserPreferencesService, - private customResourcesService: CustomResourcesService, private contentService: ContentService, private thumbnailService: ThumbnailService, private alfrescoApiService: AlfrescoApiService, @@ -378,7 +376,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte ngOnInit() { this.rowMenuCache = {}; this.loadLayoutPresets(); - this.data = new ShareDataTableAdapter(this.documentListService, this.thumbnailService, this.contentService, null, this.getDefaultSorting(), this.sortingMode); + this.data = new ShareDataTableAdapter(this.thumbnailService, this.contentService, null, this.getDefaultSorting(), this.sortingMode); this.data.thumbnails = this.thumbnails; this.data.permissionsStyle = this.permissionsStyle; @@ -416,7 +414,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte } if (!this.data) { - this.data = new ShareDataTableAdapter(this.documentListService, this.thumbnailService, this.contentService, schema, this.getDefaultSorting(), this.sortingMode); + this.data = new ShareDataTableAdapter(this.thumbnailService, this.contentService, schema, this.getDefaultSorting(), this.sortingMode); } else if (schema && schema.length > 0) { this.data.setColumns(schema); } @@ -627,45 +625,20 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte this.setupDefaultColumns(this._currentFolderId); } - this.loadFolderByNodeId(this._currentFolderId); - } - - loadFolderByNodeId(nodeId: string) { - if (this.customResourcesService.isCustomSource(nodeId)) { - this.updateCustomSourceData(nodeId); - this.customResourcesService.loadFolderByNodeId(nodeId, this._pagination, this.includeFields) - .subscribe((nodePaging: NodePaging) => { - this.onPageLoaded(nodePaging); - }, (err) => { - this.error.emit(err); - }); - } else { - - this.documentListService.getFolder(null, { - maxItems: this._pagination.maxItems, - skipCount: this._pagination.skipCount, - rootFolderId: nodeId, - where: this.where - }, this.includeFields) - .subscribe((nodePaging: NodePaging) => { - this.getSourceNodeWithPath(nodeId).subscribe((nodeEntry: NodeEntry) => { - this.onPageLoaded(nodePaging); - }); - }, (err) => { - this.handleError(err); - }); + if (this.documentListService.isCustomSourceService(this._currentFolderId)) { + this.updateCustomSourceData(this._currentFolderId); } - } - getSourceNodeWithPath(nodeId: string): Observable { - const getSourceObservable = this.documentListService.getFolderNode(nodeId, this.includeFields); - - getSourceObservable.subscribe((nodeEntry: NodeEntry) => { - this.folderNode = nodeEntry.entry; - this.$folderNode.next(this.folderNode); - }); - - return getSourceObservable; + this.documentListService.loadFolderByNodeId(this._currentFolderId, this._pagination, this.includeFields, this.where) + .subscribe((documentNode: DocumentLoaderNode) => { + if (documentNode.currentNode) { + this.folderNode = documentNode.currentNode.entry; + this.$folderNode.next(documentNode.currentNode.entry); + } + this.onPageLoaded(documentNode.children); + }, (err) => { + this.handleError(err); + }); } resetSelection() { diff --git a/lib/content-services/document-list/data/share-datatable-adapter.spec.ts b/lib/content-services/document-list/data/share-datatable-adapter.spec.ts index 40cf06bfd2..c4624e64d0 100644 --- a/lib/content-services/document-list/data/share-datatable-adapter.spec.ts +++ b/lib/content-services/document-list/data/share-datatable-adapter.spec.ts @@ -15,31 +15,64 @@ * limitations under the License. */ -import { DataColumn, DataRow, DataSorting, ContentService } from '@alfresco/adf-core'; +import { DataColumn, DataRow, DataSorting, ContentService, ThumbnailService } from '@alfresco/adf-core'; import { FileNode, FolderNode, SmartFolderNode, RuleFolderNode, LinkFolderNode } from './../../mock'; -import { DocumentListService } from './../services/document-list.service'; import { ShareDataRow } from './share-data-row.model'; import { ShareDataTableAdapter } from './share-datatable-adapter'; +import { DomSanitizer } from '@angular/platform-browser'; +import { MatIconRegistry } from '@angular/material'; + +class FakeSanitizer extends DomSanitizer { + + constructor() { + super(); + } + + sanitize(html) { + return html; + } + + bypassSecurityTrustHtml(value: string): any { + return value; + } + + bypassSecurityTrustStyle(value: string): any { + return null; + } + + bypassSecurityTrustScript(value: string): any { + return null; + } + + bypassSecurityTrustUrl(value: string): any { + return null; + } + + bypassSecurityTrustResourceUrl(value: string): any { + return null; + } +} describe('ShareDataTableAdapter', () => { - let documentListService: DocumentListService; + let thumbnailService: ThumbnailService; let contentService: ContentService; + const fakeMatIconRegistry: MatIconRegistry = jasmine.createSpyObj(['addSvgIcon', 'addSvgIconInNamespace']); beforeEach(() => { const imageUrl: string = 'http://'; contentService = new ContentService(null, null, null, null); - documentListService = new DocumentListService(null, contentService, null, null, null); - spyOn(documentListService, 'getDocumentThumbnailUrl').and.returnValue(imageUrl); + thumbnailService = new ThumbnailService(contentService, fakeMatIconRegistry, new FakeSanitizer()); + spyOn(thumbnailService, 'getDocumentThumbnailUrl').and.returnValue(imageUrl); }); it('should use client sorting by default', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, []); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []); expect(adapter.sortingMode).toBe('client'); }); it('should not be case sensitive for sorting mode value', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, []); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []); adapter.sortingMode = 'CLIENT'; expect(adapter.sortingMode).toBe('client'); @@ -49,7 +82,7 @@ describe('ShareDataTableAdapter', () => { }); it('should fallback to client sorting for unknown values', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, []); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []); adapter.sortingMode = 'SeRvEr'; expect(adapter.sortingMode).toBe('server'); @@ -60,27 +93,27 @@ describe('ShareDataTableAdapter', () => { it('should setup rows and columns with constructor', () => { const schema = [ {}]; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, schema); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, schema); expect(adapter.getRows()).toEqual([]); expect(adapter.getColumns()).toEqual(schema); }); it('should setup columns when constructor is missing schema', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); expect(adapter.getColumns()).toEqual([]); }); it('should set new columns', () => { const columns = [ {}, {}]; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); adapter.setColumns(columns); expect(adapter.getColumns()).toEqual(columns); }); it('should reset columns', () => { const columns = [ {}, {}]; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, columns); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, columns); expect(adapter.getColumns()).toEqual(columns); adapter.setColumns(null); @@ -89,7 +122,7 @@ describe('ShareDataTableAdapter', () => { it('should set new rows', () => { const rows = [ {}, {}]; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); expect(adapter.getRows()).toEqual([]); adapter.setRows(rows); @@ -98,7 +131,7 @@ describe('ShareDataTableAdapter', () => { it('should reset rows', () => { const rows = [ {}, {}]; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); adapter.setRows(rows); expect(adapter.getRows()).toEqual(rows); @@ -108,7 +141,7 @@ describe('ShareDataTableAdapter', () => { }); it('should sort new rows', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); spyOn(adapter, 'sort').and.callThrough(); const rows = [ {}]; @@ -118,7 +151,7 @@ describe('ShareDataTableAdapter', () => { }); it('should fail when getting value for missing row', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const check = () => { return adapter.getValue(null, {}); }; @@ -126,7 +159,7 @@ describe('ShareDataTableAdapter', () => { }); it('should fail when getting value for missing column', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const check = () => { return adapter.getValue( {}, null); }; @@ -145,16 +178,16 @@ describe('ShareDataTableAdapter', () => { }; const row = new ShareDataRow(file, contentService, null); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const value = adapter.getValue(row, col); expect(value).toBe(rawValue); }); it('should generate fallback icon for a file thumbnail with missing mime type', () => { - spyOn(documentListService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); + spyOn(thumbnailService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const file = new FileNode(); file.entry.content.mimeType = null; @@ -168,9 +201,9 @@ describe('ShareDataTableAdapter', () => { }); it('should generate fallback icon for a file with no content entry', () => { - spyOn(documentListService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); + spyOn(thumbnailService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const file = new FileNode(); file.entry.content = null; @@ -189,7 +222,7 @@ describe('ShareDataTableAdapter', () => { const file = new FileNode(); file.entry['icon'] = imageUrl; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const row = new ShareDataRow(file, contentService, null); const col = { type: 'image', key: 'icon' }; @@ -198,9 +231,9 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve folder icon', () => { - spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder.svg`); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const row = new ShareDataRow(new FolderNode(), contentService, null); const col = { type: 'image', key: '$thumbnail' }; @@ -211,9 +244,9 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve smart folder icon', () => { - spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_smart_folder.svg`); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_smart_folder.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const row = new ShareDataRow(new SmartFolderNode(), contentService, null); const col = { type: 'folder', key: '$thumbnail' }; @@ -224,9 +257,9 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve link folder icon', () => { - spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder_shortcut_link.svg`); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder_shortcut_link.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const row = new ShareDataRow(new LinkFolderNode(), contentService, null); const col = { type: 'folder', key: '$thumbnail' }; @@ -237,9 +270,9 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve rule folder icon', () => { - spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder_rule.svg`); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder_rule.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const row = new ShareDataRow(new RuleFolderNode(), contentService, null); const col = { type: 'folder', key: '$thumbnail' }; @@ -251,7 +284,7 @@ describe('ShareDataTableAdapter', () => { it('should resolve file thumbnail', () => { const imageUrl = 'http://'; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); adapter.thumbnails = true; const file = new FileNode(); @@ -260,13 +293,13 @@ describe('ShareDataTableAdapter', () => { const value = adapter.getValue(row, col); expect(value).toBe(imageUrl); - expect(documentListService.getDocumentThumbnailUrl).toHaveBeenCalledWith(file); + expect(thumbnailService.getDocumentThumbnailUrl).toHaveBeenCalledWith(file); }); it('should resolve fallback file icon for unknown node', () => { - spyOn(documentListService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); + spyOn(thumbnailService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const file = new FileNode(); file.entry.isFile = false; @@ -282,8 +315,8 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve file icon for content type', () => { - spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_raster_image.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_raster_image.svg`); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const file = new FileNode(); file.entry.isFile = false; @@ -304,7 +337,7 @@ describe('ShareDataTableAdapter', () => { const folder = new FolderNode(); const col = { key: 'name' }; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, [col]); adapter.setSorting(new DataSorting('name', 'asc')); adapter.setRows([ @@ -327,7 +360,7 @@ describe('ShareDataTableAdapter', () => { file2.entry['dateProp'] = new Date(2016, 6, 30, 13, 14, 2); const col = { key: 'dateProp' }; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, [col]); adapter.setRows([ new ShareDataRow(file2, contentService, null), @@ -357,7 +390,7 @@ describe('ShareDataTableAdapter', () => { file4.entry.content.sizeInBytes = 2852791665; // 2.66 GB const col = { key: 'content.sizeInBytes' }; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, [col]); adapter.setRows([ new ShareDataRow(file3, contentService, null), @@ -390,7 +423,7 @@ describe('ShareDataTableAdapter', () => { const file6 = new FileNode('b'); const col = { key: 'name' }; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, [col]); adapter.setRows([ new ShareDataRow(file4, contentService, null), diff --git a/lib/content-services/document-list/data/share-datatable-adapter.ts b/lib/content-services/document-list/data/share-datatable-adapter.ts index 4e2b2eeb13..975f76b612 100644 --- a/lib/content-services/document-list/data/share-datatable-adapter.ts +++ b/lib/content-services/document-list/data/share-datatable-adapter.ts @@ -25,7 +25,6 @@ import { } from '@alfresco/adf-core'; import { NodePaging } from '@alfresco/js-api'; import { PermissionStyleModel } from './../models/permissions-style.model'; -import { DocumentListService } from './../services/document-list.service'; import { ShareDataRow } from './share-data-row.model'; import { NodeEntry } from '@alfresco/js-api/src/api/content-rest-api/model/nodeEntry'; import { RowFilter } from './row-filter.model'; @@ -59,8 +58,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { return this._sortingMode; } - constructor(private documentListService: DocumentListService, - private thumbnailService: ThumbnailService, + constructor(private thumbnailService: ThumbnailService, private contentService: ContentService, schema: DataColumn[] = [], sorting?: DataSorting, @@ -119,18 +117,18 @@ export class ShareDataTableAdapter implements DataTableAdapter { if (node.entry.isFile) { if (this.thumbnails) { - return this.documentListService.getDocumentThumbnailUrl(node); + return this.thumbnailService.getDocumentThumbnailUrl(node); } } if (node.entry.content) { const mimeType = node.entry.content.mimeType; if (mimeType) { - return this.documentListService.getMimeTypeIcon(mimeType); + return this.thumbnailService.getMimeTypeIcon(mimeType); } } - return this.documentListService.getDefaultMimeTypeIcon(); + return this.thumbnailService.getDefaultMimeTypeIcon(); } if (col.type === 'image') { @@ -175,13 +173,13 @@ export class ShareDataTableAdapter implements DataTableAdapter { private getFolderIcon(node: any) { if (this.isSmartFolder(node)) { - return this.documentListService.getMimeTypeIcon('smartFolder'); + return this.thumbnailService.getMimeTypeIcon('smartFolder'); } else if (this.isRuleFolder(node)) { - return this.documentListService.getMimeTypeIcon('ruleFolder'); + return this.thumbnailService.getMimeTypeIcon('ruleFolder'); } else if (this.isALinkFolder(node)) { - return this.documentListService.getMimeTypeIcon('linkFolder'); + return this.thumbnailService.getMimeTypeIcon('linkFolder'); } else { - return this.documentListService.getMimeTypeIcon('folder'); + return this.thumbnailService.getMimeTypeIcon('folder'); } } diff --git a/lib/content-services/document-list/interfaces/document-list-loader.interface.ts b/lib/content-services/document-list/interfaces/document-list-loader.interface.ts new file mode 100644 index 0000000000..c49e9c57c8 --- /dev/null +++ b/lib/content-services/document-list/interfaces/document-list-loader.interface.ts @@ -0,0 +1,25 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { PaginationModel } from '@alfresco/adf-core'; +import { Observable } from 'rxjs'; +import { DocumentLoaderNode } from '../models/document-folder.model'; + +export interface DocumentListLoader { + + loadFolderByNodeId(nodeId: string, pagination: PaginationModel, includeFields: string[], where?: string): Observable ; +} diff --git a/lib/content-services/document-list/models/document-folder.model.ts b/lib/content-services/document-list/models/document-folder.model.ts new file mode 100644 index 0000000000..31aaf96433 --- /dev/null +++ b/lib/content-services/document-list/models/document-folder.model.ts @@ -0,0 +1,28 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NodeEntry, NodePaging } from '@alfresco/js-api'; + +export class DocumentLoaderNode { + currentNode: NodeEntry; + children: NodePaging; + + constructor(currentNode: NodeEntry, children: NodePaging) { + this.currentNode = currentNode; + this.children = children; + } +} diff --git a/lib/content-services/document-list/public-api.ts b/lib/content-services/document-list/public-api.ts index 38fec6edc4..98c6ca60bf 100644 --- a/lib/content-services/document-list/public-api.ts +++ b/lib/content-services/document-list/public-api.ts @@ -46,4 +46,6 @@ export * from './models/document-library.model'; export * from './models/permissions.model'; export * from './models/permissions-style.model'; +export * from './interfaces/document-list-loader.interface'; + export * from './document-list.module'; diff --git a/lib/content-services/document-list/services/document-actions.service.spec.ts b/lib/content-services/document-list/services/document-actions.service.spec.ts index e28a6562c6..67e9e8d7d6 100644 --- a/lib/content-services/document-list/services/document-actions.service.spec.ts +++ b/lib/content-services/document-list/services/document-actions.service.spec.ts @@ -39,7 +39,7 @@ describe('DocumentActionsService', () => { const contentService = new ContentService(null, null, null, null); const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); - documentListService = new DocumentListService(null, contentService, alfrescoApiService, null, null); + documentListService = new DocumentListService(contentService, alfrescoApiService, null, null); service = new DocumentActionsService(null, null, new TranslationMock(), documentListService, contentService); }); diff --git a/lib/content-services/document-list/services/document-list.service.spec.ts b/lib/content-services/document-list/services/document-list.service.spec.ts index b97d7dfc3d..403f0788e7 100644 --- a/lib/content-services/document-list/services/document-list.service.spec.ts +++ b/lib/content-services/document-list/services/document-list.service.spec.ts @@ -18,6 +18,7 @@ import { AlfrescoApiServiceMock, AlfrescoApiService, AppConfigService, StorageService, ContentService, setupTestBed, CoreModule, LogService, AppConfigServiceMock } from '@alfresco/adf-core'; import { DocumentListService } from './document-list.service'; +import { CustomResourcesService } from './custom-resources.service'; declare let jasmine: any; @@ -70,7 +71,8 @@ describe('DocumentListService', () => { const logService = new LogService(new AppConfigServiceMock(null)); const contentService = new ContentService(null, null, null, null); alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); - service = new DocumentListService(null, contentService, alfrescoApiService, logService, null); + const customActionService = new CustomResourcesService(alfrescoApiService, logService); + service = new DocumentListService(contentService, alfrescoApiService, logService, customActionService); jasmine.Ajax.install(); }); diff --git a/lib/content-services/document-list/services/document-list.service.ts b/lib/content-services/document-list/services/document-list.service.ts index 7507d49fbe..8d3420df1a 100644 --- a/lib/content-services/document-list/services/document-list.service.ts +++ b/lib/content-services/document-list/services/document-list.service.ts @@ -16,26 +16,28 @@ */ import { - AlfrescoApiService, AuthenticationService, ContentService, LogService, ThumbnailService + AlfrescoApiService, ContentService, LogService, PaginationModel } from '@alfresco/adf-core'; import { Injectable } from '@angular/core'; import { NodeEntry, NodePaging } from '@alfresco/js-api'; -import { Observable, from, throwError } from 'rxjs'; -import { catchError } from 'rxjs/operators'; +import { DocumentLoaderNode } from '../models/document-folder.model'; +import { Observable, from, throwError, forkJoin } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; +import { DocumentListLoader } from '../interfaces/document-list-loader.interface'; +import { CustomResourcesService } from './custom-resources.service'; @Injectable({ providedIn: 'root' }) -export class DocumentListService { +export class DocumentListService implements DocumentListLoader { static ROOT_ID = '-root-'; - constructor(authService: AuthenticationService, - private contentService: ContentService, + constructor(private contentService: ContentService, private apiService: AlfrescoApiService, private logService: LogService, - private thumbnailService: ThumbnailService) { + private customResourcesService: CustomResourcesService) { } /** @@ -155,30 +157,31 @@ export class DocumentListService { ); } - /** - * Get thumbnail URL for the given document node. - * @param node Node to get URL for. - * @returns Thumbnail URL string - */ - getDocumentThumbnailUrl(node: NodeEntry): string { - return this.thumbnailService.getDocumentThumbnailUrl(node); + isCustomSourceService(nodeId): boolean { + return this.customResourcesService.isCustomSource(nodeId); } - /** - * Gets the icon that represents a MIME type. - * @param mimeType MIME type to get the icon for - * @returns Path to the icon file - */ - getMimeTypeIcon(mimeType: string): string { - return this.thumbnailService.getMimeTypeIcon(mimeType); + loadFolderByNodeId(nodeId: string, pagination: PaginationModel, includeFields: string[], where?: string): Observable { + if (this.customResourcesService.isCustomSource(nodeId)) { + return this.customResourcesService.loadFolderByNodeId(nodeId, pagination, includeFields).pipe( + map((result: any) => new DocumentLoaderNode(null, result)) + ); + } else { + return this.retrieveDocumentNode(nodeId, pagination, includeFields, where); + } } - /** - * Gets a default icon for MIME types with no specific icon. - * @returns Path to the icon file - */ - getDefaultMimeTypeIcon(): string { - return this.thumbnailService.getDefaultMimeTypeIcon(); + private retrieveDocumentNode(nodeId: string, pagination: PaginationModel, includeFields: string[], where?: string): Observable { + return forkJoin( + this.getFolderNode(nodeId, includeFields), + this.getFolder(null, { + maxItems: pagination.maxItems, + skipCount: pagination.skipCount, + rootFolderId: nodeId, + where: where + }, includeFields)).pipe( + map((results) => new DocumentLoaderNode(results[0], results[1])) + ); } private handleError(error: any) { diff --git a/lib/content-services/document-list/services/folder-actions.service.spec.ts b/lib/content-services/document-list/services/folder-actions.service.spec.ts index b73253c080..badb07cd34 100644 --- a/lib/content-services/document-list/services/folder-actions.service.spec.ts +++ b/lib/content-services/document-list/services/folder-actions.service.spec.ts @@ -40,7 +40,7 @@ describe('FolderActionsService', () => { const contentService = new ContentService(null, null, null, null); const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); - documentListService = new DocumentListService(null, contentService, alfrescoApiService, null, null); + documentListService = new DocumentListService(contentService, alfrescoApiService, null, null); service = new FolderActionsService(null, documentListService, contentService, new TranslationMock()); });