From fec2b89b2d56064461007fdf9d5b8d73e5452a77 Mon Sep 17 00:00:00 2001 From: Eugenio Romano Date: Sun, 3 Feb 2019 20:10:54 +0000 Subject: [PATCH] [ADF-3930] Can't load more results in Copy/Move dialog (#4247) * fix unrelated failing test improve type definition add set get filtering node selector fix directive highlight fix minor problem style breadcrumb small refactoring problem documentlist * fix lint style * fix html node * fix test --- .../breadcrumb-demo.component.html | 7 + .../app/components/files/files.component.html | 6 +- .../app/components/files/files.component.ts | 1 - docs/content-services/breadcrumb.component.md | 3 +- .../breadcrumb/breadcrumb.component.spec.ts | 11 +- .../breadcrumb/breadcrumb.component.ts | 36 ++-- .../dropdown-breadcrumb.component.scss | 5 +- .../dropdown-breadcrumb.component.spec.ts | 6 +- .../dropdown-breadcrumb.component.ts | 19 +- .../navigable-component.interface.ts | 4 +- .../content-node-dialog.service.ts | 2 +- ...content-node-selector-panel.component.html | 6 +- ...tent-node-selector-panel.component.spec.ts | 73 ++++--- .../content-node-selector-panel.component.ts | 38 +--- .../document-list.component.spec.ts | 78 ++----- .../components/document-list.component.ts | 198 +++++++++--------- .../data/share-datatable-adapter.ts | 32 ++- .../mock/document-list.component.mock.ts | 10 +- .../datatable/datatable.component.scss | 2 +- lib/core/directives/highlight.directive.ts | 11 +- .../infinite-pagination.component.spec.ts | 10 +- .../infinite-pagination.component.ts | 5 +- .../services/highlight-transform.service.ts | 3 +- package-lock.json | 82 +++----- package.json | 2 +- 25 files changed, 288 insertions(+), 362 deletions(-) diff --git a/demo-shell/src/app/components/breadcrumb-demo/breadcrumb-demo.component.html b/demo-shell/src/app/components/breadcrumb-demo/breadcrumb-demo.component.html index 929c6faa7b..35d547f8cd 100644 --- a/demo-shell/src/app/components/breadcrumb-demo/breadcrumb-demo.component.html +++ b/demo-shell/src/app/components/breadcrumb-demo/breadcrumb-demo.component.html @@ -76,6 +76,13 @@ +

6. Dropdown Breadcrumb

+ + + +
diff --git a/demo-shell/src/app/components/files/files.component.html b/demo-shell/src/app/components/files/files.component.html index 2e79671144..0ed1f4ab9d 100644 --- a/demo-shell/src/app/components/files/files.component.html +++ b/demo-shell/src/app/components/files/files.component.html @@ -51,13 +51,11 @@ + [target]="documentList"> + [target]="documentList"> diff --git a/demo-shell/src/app/components/files/files.component.ts b/demo-shell/src/app/components/files/files.component.ts index 002c65cca8..977e563c45 100644 --- a/demo-shell/src/app/components/files/files.component.ts +++ b/demo-shell/src/app/components/files/files.component.ts @@ -529,7 +529,6 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { onInfiniteScrolling(): void { this.infiniteScrolling = !this.infiniteScrolling; this.infinitePaginationComponent.reset(); - this.documentList.reload(); } canDownloadNode(node: MinimalNodeEntity): boolean { diff --git a/docs/content-services/breadcrumb.component.md b/docs/content-services/breadcrumb.component.md index 961ba99d5a..66e99ad9b2 100644 --- a/docs/content-services/breadcrumb.component.md +++ b/docs/content-services/breadcrumb.component.md @@ -15,8 +15,7 @@ Indicates the current position within a navigation hierarchy. ```html + [target]="documentList"> ``` diff --git a/lib/content-services/breadcrumb/breadcrumb.component.spec.ts b/lib/content-services/breadcrumb/breadcrumb.component.spec.ts index 522edde408..ba82420b61 100644 --- a/lib/content-services/breadcrumb/breadcrumb.component.spec.ts +++ b/lib/content-services/breadcrumb/breadcrumb.component.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { PathElementEntity } from '@alfresco/js-api'; import { setupTestBed } from '@alfresco/adf-core'; @@ -52,10 +52,9 @@ describe('Breadcrumb', () => { }); it('should root be present as default node if the path is null', () => { - let change = new SimpleChange(null, fakeNodeWithCreatePermission, true); - component.root = 'default'; - component.ngOnChanges({ 'folderNode': change }); + component.folderNode = fakeNodeWithCreatePermission; + component.ngOnChanges(null); expect(component.route[0].name).toBe('default'); }); @@ -211,8 +210,8 @@ describe('Breadcrumb', () => { transformNode.name = 'test-name'; return transformNode; }); - let change = new SimpleChange(null, node, true); - component.ngOnChanges({ 'folderNode': change }); + component.folderNode = node; + component.ngOnChanges(null); expect(component.route.length).toBe(4); expect(component.route[3].id).toBe('test-id'); expect(component.route[3].name).toBe('test-name'); diff --git a/lib/content-services/breadcrumb/breadcrumb.component.ts b/lib/content-services/breadcrumb/breadcrumb.component.ts index b5f27d5809..07a7fcd68b 100644 --- a/lib/content-services/breadcrumb/breadcrumb.component.ts +++ b/lib/content-services/breadcrumb/breadcrumb.component.ts @@ -15,7 +15,17 @@ * limitations under the License. */ -import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core'; +import { + Component, + EventEmitter, + Input, + OnChanges, + OnInit, + Output, + SimpleChanges, + ViewChild, + ViewEncapsulation +} from '@angular/core'; import { MatSelect } from '@angular/material'; import { Node, PathElementEntity } from '@alfresco/js-api'; import { DocumentListComponent } from '../document-list'; @@ -84,23 +94,24 @@ export class BreadcrumbComponent implements OnInit, OnChanges { ngOnInit() { this.transform = this.transform ? this.transform : null; + + if (this.target) { + this.target.$folderNode.subscribe((folderNode: Node) => { + this.folderNode = folderNode; + this.recalculateNodes(); + }); + } } ngOnChanges(changes: SimpleChanges): void { - if (changes.folderNode) { - let node: Node = null; - node = this.transform ? this.transform(changes.folderNode.currentValue) : changes.folderNode.currentValue; - this.route = this.parseRoute(node); - } - - if (changes.transform) { - let node = this.transform ? this.transform(this.folderNode) : this.folderNode; - this.route = this.parseRoute(node); - } this.recalculateNodes(); } protected recalculateNodes(): void { + let node: Node = this.transform ? this.transform(this.folderNode) : this.folderNode; + + this.route = this.parseRoute(node); + if (this.maxItems && this.route.length > this.maxItems) { this.lastNodes = this.route.slice(this.route.length - this.maxItems); this.previousNodes = this.route.slice(0, this.route.length - this.maxItems); @@ -127,7 +138,8 @@ export class BreadcrumbComponent implements OnInit, OnChanges { route.push( { id: node.id, - name: node.name + name: node.name, + node: node }); const rootPos = this.getElementPosition(route, this.rootId); diff --git a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.scss b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.scss index 319eb8439b..655b312ae5 100644 --- a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.scss +++ b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.scss @@ -10,6 +10,7 @@ } &-dropdown-breadcrumb-trigger { + height: 0; cursor: pointer; padding: 0; border: none; @@ -21,10 +22,6 @@ } } - &-dropdown-breadcrumb-item-chevron { - margin-top: 5px; - } - &-dropdown-breadcrumb-trigger.adf-isRoot { cursor: not-allowed; } diff --git a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts index b0627a8d95..cc012321c7 100644 --- a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts +++ b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { setupTestBed } from '@alfresco/adf-core'; @@ -52,8 +52,8 @@ describe('DropdownBreadcrumb', () => { } function triggerComponentChange(fakeNodeData) { - const change = new SimpleChange(null, fakeNodeData, true); - component.ngOnChanges({ 'folderNode': change }); + component.folderNode = fakeNodeData; + component.ngOnChanges(null); fixture.detectChanges(); } diff --git a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.ts b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.ts index 7598310d95..2352f9db03 100644 --- a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.ts +++ b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, OnChanges, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core'; +import { Component, OnChanges, ViewChild, ViewEncapsulation } from '@angular/core'; import { MatSelect } from '@angular/material'; import { PathElementEntity, Node } from '@alfresco/js-api'; import { BreadcrumbComponent } from './breadcrumb.component'; @@ -37,24 +37,13 @@ export class DropdownBreadcrumbComponent extends BreadcrumbComponent implements currentNode: PathElementEntity; previousNodes: PathElementEntity[]; - ngOnChanges(changes: SimpleChanges): void { - if (changes.folderNode) { - let node: Node = null; - node = this.transform ? this.transform(changes.folderNode.currentValue) : changes.folderNode.currentValue; - this.route = this.parseRoute(node); - } - - if (changes.transform) { - let node = this.transform ? this.transform(this.folderNode) : this.folderNode; - this.route = this.parseRoute(node); - } - this.recalculateNodes(); - } - /** * Calculate the current and previous nodes from the route array */ protected recalculateNodes(): void { + let node: Node = this.transform ? this.transform(this.folderNode) : this.folderNode; + + this.route = this.parseRoute(node); this.currentNode = this.route[this.route.length - 1]; this.previousNodes = this.route.slice(0, this.route.length - 1).reverse(); } diff --git a/lib/content-services/breadcrumb/navigable-component.interface.ts b/lib/content-services/breadcrumb/navigable-component.interface.ts index 903f84a7b4..542ea20cc8 100644 --- a/lib/content-services/breadcrumb/navigable-component.interface.ts +++ b/lib/content-services/breadcrumb/navigable-component.interface.ts @@ -15,6 +15,8 @@ * limitations under the License. */ +import { Node } from '@alfresco/js-api'; + export interface NavigableComponentInterface { - navigateTo(nodeId: string); + navigateTo(node: Node | string); } 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 b15edb689e..fddbfbbcf1 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 @@ -232,7 +232,7 @@ export class ContentNodeDialogService { return null; } - private rowFilter(currentNodeId, row: ShareDataRow): boolean { + private rowFilter(currentNodeId: string, row: ShareDataRow): boolean { const node: Node = row.node.entry; if (node.id === currentNodeId || node.isFile) { diff --git a/lib/content-services/content-node-selector/content-node-selector-panel.component.html b/lib/content-services/content-node-selector/content-node-selector-panel.component.html index 555276e578..12a3516adc 100644 --- a/lib/content-services/content-node-selector/content-node-selector-panel.component.html +++ b/lib/content-services/content-node-selector/content-node-selector-panel.component.html @@ -53,8 +53,8 @@ data-automation-id="content-node-selector-content-list"> diff --git a/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts b/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts index 9b2ef3cfea..1f80e93def 100644 --- a/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts +++ b/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts @@ -112,32 +112,28 @@ describe('ContentNodeSelectorComponent', () => { component.excludeSiteContent = ['blog']; fixture.detectChanges(); - const testSiteContent = new Node({id: 'blog-id', properties: { 'st:componentId': 'blog' }}); - expect(component.rowFilter( {node: {entry: testSiteContent}}, null, null)).toBe(false); + const testSiteContent = new Node({ id: 'blog-id', properties: { 'st:componentId': 'blog' } }); + expect(component.rowFilter( { node: { entry: testSiteContent } }, null, null)).toBe(false); }); it('should NOT filter out any site content by default', () => { fixture.detectChanges(); - const testSiteContent = new Node({id: 'blog-id', properties: { 'st:componentId': 'blog' }}); - expect(component.rowFilter( {node: {entry: testSiteContent}}, null, null)).toBe(true); + const testSiteContent = new Node({ id: 'blog-id', properties: { 'st:componentId': 'blog' } }); + expect(component.rowFilter( { node: { entry: testSiteContent } }, null, null)).toBe(true); }); }); describe('Breadcrumbs', () => { - let documentListService, - sitesService, - expectedDefaultFolderNode; + let documentListService, sitesService; beforeEach(() => { - expectedDefaultFolderNode = { path: { elements: [] } }; documentListService = TestBed.get(DocumentListService); sitesService = TestBed.get(SitesService); spyOn(documentListService, 'getFolderNode').and.returnValue(of( { entry: { path: { elements: [] } } })); spyOn(documentListService, 'getFolder').and.returnValue(throwError('No results for test')); spyOn(sitesService, 'getSites').and.returnValue(of({ list: { entries: [] } })); - spyOn(component.documentList, 'loadFolderNodesByFolderNodeId').and.returnValue(Promise.resolve()); component.currentFolderId = 'cat-girl-nuku-nuku'; fixture.detectChanges(); }); @@ -149,7 +145,7 @@ describe('ContentNodeSelectorComponent', () => { fixture.detectChanges(); const breadcrumb = fixture.debugElement.query(By.directive(DropdownBreadcrumbComponent)); expect(breadcrumb).not.toBeNull(); - expect(breadcrumb.componentInstance.folderNode).toEqual(expectedDefaultFolderNode); + expect(breadcrumb.componentInstance.folderNode).toEqual(undefined); done(); }); }); @@ -215,26 +211,27 @@ describe('ContentNodeSelectorComponent', () => { expect(breadcrumb.componentInstance.folderNode.path).toBe(chosenNode.path); })); - it('should NOT show the breadcrumb for the selected node when not on search results list', (done) => { + it('should NOT show the breadcrumb for the selected node when not on search results list', fakeAsync(() => { typeToSearchBox(); - setTimeout(() => { - respondWithSearchResults(ONE_FOLDER_RESULT); + fixture.detectChanges(); - fixture.detectChanges(); - component.onFolderChange(); - fixture.detectChanges(); + respondWithSearchResults(ONE_FOLDER_RESULT); + fixture.detectChanges(); - const chosenNode = { path: { elements: [] } }; - component.onNodeSelect({ detail: { node: { entry: chosenNode } } }); - fixture.detectChanges(); + component.onFolderChange(); + fixture.detectChanges(); - const breadcrumb = fixture.debugElement.query(By.directive(DropdownBreadcrumbComponent)); - expect(breadcrumb).not.toBeNull(); - expect(breadcrumb.componentInstance.folderNode).toEqual(expectedDefaultFolderNode); - done(); - }, 300); - }); + const chosenNode = { path: { elements: [] } }; + component.onNodeSelect({ detail: { node: { entry: chosenNode } } }); + fixture.detectChanges(); + + tick(debounceSearch); + + const breadcrumb = fixture.debugElement.query(By.directive(DropdownBreadcrumbComponent)); + expect(breadcrumb).not.toBeNull(); + expect(breadcrumb.componentInstance.folderNode).toEqual(undefined); + })); it('should keep breadcrumb\'s folderNode unchanged if breadcrumbTransform is NOT defined', (done) => { fixture.detectChanges(); @@ -244,7 +241,7 @@ describe('ContentNodeSelectorComponent', () => { expect(component.breadcrumbTransform).toBeNull(); const breadcrumb = fixture.debugElement.query(By.directive(DropdownBreadcrumbComponent)); - expect(breadcrumb.componentInstance.folderNode).toEqual(expectedDefaultFolderNode); + expect(breadcrumb.componentInstance.folderNode).toEqual(undefined); done(); }); }); @@ -306,7 +303,6 @@ describe('ContentNodeSelectorComponent', () => { const expectedDefaultFolderNode = { entry: { path: { elements: [] } } }; spyOn(documentListService, 'getFolderNode').and.returnValue(of(expectedDefaultFolderNode)); - spyOn(component.documentList, 'loadFolderNodesByFolderNodeId').and.returnValue(Promise.resolve()); const sitesService = TestBed.get(SitesService); spyOn(sitesService, 'getSites').and.returnValue(of({ list: { entries: [] } })); @@ -588,19 +584,20 @@ describe('ContentNodeSelectorComponent', () => { }, 300); }); - it('should highlight the results when search was performed in the next timeframe', fakeAsync(() => { - spyOn(component.highlighter, 'highlight'); - typeToSearchBox('shenron'); + it('should highlight the results when search was performed in the next timeframe', (done) => { + typeToSearchBox('My'); - tick(debounceSearch); + setTimeout(() => { + respondWithSearchResults(ONE_FOLDER_RESULT); + fixture.detectChanges(); - respondWithSearchResults(ONE_FOLDER_RESULT); - fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.nativeElement.querySelector('.adf-highlight').innerHTML).toBe('My'); - tick(debounceSearch); - - expect(component.highlighter.highlight).toHaveBeenCalledWith('shenron'); - })); + done(); + }); + }, 300); + }); it('should show the default text instead of result list if search was cleared', (done) => { typeToSearchBox(); @@ -670,7 +667,7 @@ describe('ContentNodeSelectorComponent', () => { component.searchTerm = ''; fixture.detectChanges(); - component.updatePagination({ skipCount }); + component.getNextPageOfSearch({ skipCount }); fixture.detectChanges(); expect(component.searchTerm).toBe(''); diff --git a/lib/content-services/content-node-selector/content-node-selector-panel.component.ts b/lib/content-services/content-node-selector/content-node-selector-panel.component.ts index ae8a10e9a2..789e6c0ccb 100644 --- a/lib/content-services/content-node-selector/content-node-selector-panel.component.ts +++ b/lib/content-services/content-node-selector/content-node-selector-panel.component.ts @@ -16,10 +16,7 @@ */ import { Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; -import { - AlfrescoApiService, HighlightDirective, UserPreferencesService, - PaginatedComponent, PaginationModel -} from '@alfresco/adf-core'; +import { AlfrescoApiService, HighlightDirective, UserPreferencesService, PaginationModel } from '@alfresco/adf-core'; import { FormControl } from '@angular/forms'; import { Node, NodePaging, Pagination, SiteEntry, SitePaging } from '@alfresco/js-api'; import { DocumentListComponent, PaginationStrategy } from '../document-list/components/document-list.component'; @@ -30,6 +27,7 @@ import { debounceTime } from 'rxjs/operators'; import { BehaviorSubject } from 'rxjs'; import { CustomResourcesService } from '../document-list/services/custom-resources.service'; import { ShareDataRow } from '../document-list'; +import { NodeEntry } from '@alfresco/js-api/src/api/content-rest-api/model/nodeEntry'; export type ValidationFunction = (entry: Node) => boolean; @@ -42,7 +40,7 @@ const defaultValidation = () => true; encapsulation: ViewEncapsulation.None, host: { 'class': 'adf-content-node-selector-panel' } }) -export class ContentNodeSelectorPanelComponent implements OnInit, PaginatedComponent { +export class ContentNodeSelectorPanelComponent implements OnInit { /** Node ID of the folder currently listed. */ @Input() @@ -270,20 +268,6 @@ export class ContentNodeSelectorPanelComponent implements OnInit, PaginatedCompo this.querySearch(); } - /** - * Loads the next batch of search results - * - * @param event Pagination object - */ - updatePagination(pagination: Pagination): void { - this.infiniteScroll = true; - this.skipCount = pagination.skipCount; - - if (this.searchTerm.length > 0) { - this.querySearch(); - } - } - /** * Perform the call to searchService with the proper parameters */ @@ -322,16 +306,6 @@ export class ContentNodeSelectorPanelComponent implements OnInit, PaginatedCompo } this.pagination.next(nodePaging.list.pagination); - this.highlight(); - } - - /** - * Highlight the actual search term in the next frame - */ - highlight(): void { - setTimeout(() => { - this.highlighter.highlight(this.searchTerm); - }, 0); } /** @@ -346,7 +320,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, PaginatedCompo /** * Attempts to set the currently loaded node */ - onFolderLoaded(nodePaging: NodePaging): void { + onFolderLoaded(): void { if (!this.showingSearchResults) { this.attemptNodeSelection(this.documentList.folderNode); } @@ -413,8 +387,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, PaginatedCompo }; this.apiService.nodesApi.getNode(node.guid, options) - .then((documentLibrary) => { - this.documentList.performCustomSourceNavigation(documentLibrary); + .then((nodeEntry: NodeEntry) => { + this.documentList.navigateTo(nodeEntry.entry); }); } } 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 b187ff39ee..bb827b6def 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 @@ -23,7 +23,6 @@ import { Subject, of, throwError } from 'rxjs'; import { FileNode, FolderNode } from '../../mock'; import { fakeNodeAnswerWithNOEntries, - fakeNodeWithCreatePermission, fakeNodeWithNoPermission, fakeGetSitesAnswer, fakeGetSiteMembership @@ -249,7 +248,6 @@ describe('DocumentList', () => { }); it('should empty template be present when no element are present', () => { - spyOn(documentList, 'loadFolderNodesByFolderNodeId').and.returnValue(Promise.resolve('')); spyOn(documentList, 'loadFolder').and.callThrough(); spyOn(documentListService, 'getFolderNode').and.returnValue(of({ entry: { id: 'fake-node' } })); spyOn(documentListService, 'getFolder').and.returnValue(of(fakeNodeAnswerWithNOEntries)); @@ -675,41 +673,41 @@ describe('DocumentList', () => { it('should perform folder navigation on single click', () => { let folder = new FolderNode(); - spyOn(documentList, 'performNavigation').and.stub(); + spyOn(documentList, 'navigateTo').and.stub(); documentList.navigationMode = DocumentListComponent.SINGLE_CLICK_NAVIGATION; documentList.onNodeClick(folder); - expect(documentList.performNavigation).toHaveBeenCalled(); + expect(documentList.navigateTo).toHaveBeenCalled(); }); it('should perform folder navigation on double click', () => { let folder = new FolderNode(); - spyOn(documentList, 'performNavigation').and.stub(); + spyOn(documentList, 'navigateTo').and.stub(); documentList.navigationMode = DocumentListComponent.DOUBLE_CLICK_NAVIGATION; documentList.onNodeDblClick(folder); - expect(documentList.performNavigation).toHaveBeenCalled(); + expect(documentList.navigateTo).toHaveBeenCalled(); }); it('should not perform folder navigation on double click when single mode', () => { let folder = new FolderNode(); - spyOn(documentList, 'performNavigation').and.stub(); + spyOn(documentList, 'navigateTo').and.stub(); documentList.navigationMode = DocumentListComponent.SINGLE_CLICK_NAVIGATION; documentList.onNodeDblClick(folder); - expect(documentList.performNavigation).not.toHaveBeenCalled(); + expect(documentList.navigateTo).not.toHaveBeenCalled(); }); it('should not perform folder navigation on double click when navigation off', () => { let folder = new FolderNode(); - spyOn(documentList, 'performNavigation').and.stub(); + spyOn(documentList, 'navigateTo').and.stub(); documentList.navigate = false; documentList.navigationMode = DocumentListComponent.DOUBLE_CLICK_NAVIGATION; documentList.onNodeDblClick(folder); - expect(documentList.performNavigation).not.toHaveBeenCalled(); + expect(documentList.navigateTo).not.toHaveBeenCalled(); }); it('should perform navigation for folder node only', () => { @@ -718,9 +716,9 @@ describe('DocumentList', () => { spyOn(documentList, 'loadFolder').and.stub(); - expect(documentList.performNavigation(folder)).toBeTruthy(); - expect(documentList.performNavigation(file)).toBeFalsy(); - expect(documentList.performNavigation(null)).toBeFalsy(); + expect(documentList.navigateTo(folder.entry)).toBeTruthy(); + expect(documentList.navigateTo(file.entry)).toBeFalsy(); + expect(documentList.navigateTo(null)).toBeFalsy(); }); it('should perform navigation through corret linked folder', () => { @@ -731,7 +729,7 @@ describe('DocumentList', () => { spyOn(documentList, 'loadFolder').and.stub(); - expect(documentList.performNavigation(linkFolder)).toBeTruthy(); + expect(documentList.navigateTo(linkFolder.entry)).toBeTruthy(); expect(documentList.currentFolderId).toBe('normal-folder'); }); @@ -754,7 +752,7 @@ describe('DocumentList', () => { it('should require valid node for folder navigation', () => { let folder = new FolderNode(); folder.entry = null; - spyOn(documentList, 'performNavigation').and.stub(); + spyOn(documentList, 'navigateTo').and.stub(); documentList.navigationMode = DocumentListComponent.SINGLE_CLICK_NAVIGATION; documentList.onNodeClick(folder); @@ -762,13 +760,12 @@ describe('DocumentList', () => { documentList.navigationMode = DocumentListComponent.DOUBLE_CLICK_NAVIGATION; documentList.onNodeDblClick(folder); - expect(documentList.performNavigation).not.toHaveBeenCalled(); + expect(documentList.navigateTo).not.toHaveBeenCalled(); }); it('should display folder content from loadFolder on reload if folderNode defined', () => { documentList.folderNode = new NodeMinimal(); - spyOn(documentList, 'loadFolderNodesByFolderNodeId').and.returnValue(Promise.resolve('')); spyOn(documentList, 'loadFolder').and.callThrough(); documentList.reload(); expect(documentList.loadFolder).toHaveBeenCalled(); @@ -878,9 +875,9 @@ describe('DocumentList', () => { let filter = {}; documentList.currentFolderId = 'id'; spyOn(documentList.data, 'setFilter').and.callThrough(); - spyOn(documentListService, 'getFolder'); + spyOn(documentListService, 'getFolder').and.callThrough(); - documentList.ngOnChanges({ rowFilter: new SimpleChange(null, filter, true) }); + documentList.rowFilter = filter; expect(documentList.data.setFilter).toHaveBeenCalledWith(filter); expect(documentListService.getFolder).toHaveBeenCalled(); @@ -950,21 +947,7 @@ describe('DocumentList', () => { it('should emit error when getFolderNode fails', (done) => { const error = { message: '{ "error": { "statusCode": 501 } }' }; - spyOn(documentListService, 'getFolderNode').and.returnValue(throwError(error)); - - let disposableError = documentList.error.subscribe((val) => { - expect(val).toBe(error); - disposableError.unsubscribe(); - done(); - }); - - documentList.loadFolderByNodeId('123'); - }); - - it('should emit error when loadFolderNodesByFolderNodeId fails', (done) => { - const error = { message: '{ "error": { "statusCode": 501 } }' }; - spyOn(documentListService, 'getFolderNode').and.returnValue(of({ entry: fakeNodeWithCreatePermission })); - spyOn(documentList, 'loadFolderNodesByFolderNodeId').and.returnValue(Promise.reject(error)); + spyOn(documentListService, 'getFolder').and.returnValue(throwError(error)); let disposableError = documentList.error.subscribe((val) => { expect(val).toBe(error); @@ -987,7 +970,7 @@ describe('DocumentList', () => { it('should set no permission when getFolderNode fails with 403', (done) => { const error = { message: '{ "error": { "statusCode": 403 } }' }; - spyOn(documentListService, 'getFolderNode').and.returnValue(throwError(error)); + spyOn(documentListService, 'getFolder').and.returnValue(throwError(error)); let disposableError = documentList.error.subscribe((val) => { expect(val).toBe(error); @@ -1045,11 +1028,11 @@ describe('DocumentList', () => { const node = new FolderNode('folder'); documentList.currentFolderId = 'node-id'; - expect(documentList.canNavigateFolder(node)).toBeTruthy(); + expect(documentList.canNavigateFolder(node.entry)).toBeTruthy(); sources.forEach((source) => { documentList.currentFolderId = source; - expect(documentList.canNavigateFolder(node)).toBeFalsy(); + expect(documentList.canNavigateFolder(node.entry)).toBeFalsy(); }); }); @@ -1245,23 +1228,6 @@ describe('DocumentList', () => { documentList.loadFolderByNodeId('-recent-'); }); - it('should reset folder node upon changing current folder id', () => { - documentList.currentFolderId = 'fake-node-id'; - documentList.folderNode = {}; - - documentList.ngOnChanges({ currentFolderId: new SimpleChange(null, '-sites-', false) }); - - expect(documentList.folderNode).toBeNull(); - }); - - it('should reset folder node on loading folder by node id', () => { - documentList.folderNode = {}; - - documentList.loadFolderByNodeId('-sites-'); - - expect(documentList.folderNode).toBeNull(); - }); - it('should have correct currentFolderId on loading folder by node id', () => { documentList.currentFolderId = '12345-some-id-6789'; @@ -1298,9 +1264,9 @@ describe('DocumentList', () => { fixture.detectChanges(); documentList.currentFolderId = 'fake-id'; documentList.includeFields = ['test-include']; - spyOn(documentListService, 'getFolder').and.stub(); + spyOn(documentListService, 'getFolder').and.callThrough(); - documentList.ngOnChanges({ rowFilter: new SimpleChange(null, {}, true) }); + documentList.ngOnChanges({ currentFolderId: new SimpleChange(null, '-root-', false) }); expect(documentListService.getFolder).toHaveBeenCalledWith(null, { maxItems: 25, 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 317724ad2a..cf08933d85 100644 --- a/lib/content-services/document-list/components/document-list.component.ts +++ b/lib/content-services/document-list/components/document-list.component.ts @@ -23,9 +23,23 @@ import { } from '@angular/core'; import { - ContentService, DataCellEvent, DataColumn, DataRowActionEvent, DataSorting, DataTableComponent, - DisplayMode, ObjectDataColumn, PaginatedComponent, AppConfigService, DataColumnListComponent, - UserPreferencesService, PaginationModel, ThumbnailService, CustomLoadingContentTemplateDirective, CustomNoPermissionTemplateDirective, CustomEmptyContentTemplateDirective + ContentService, + DataCellEvent, + DataColumn, + DataRowActionEvent, + DataSorting, + DataTableComponent, + DisplayMode, + ObjectDataColumn, + PaginatedComponent, + AppConfigService, + DataColumnListComponent, + UserPreferencesService, + PaginationModel, + ThumbnailService, + CustomLoadingContentTemplateDirective, + CustomNoPermissionTemplateDirective, + CustomEmptyContentTemplateDirective } from '@alfresco/adf-core'; import { Node, NodeEntry, NodePaging } from '@alfresco/js-api'; @@ -39,6 +53,7 @@ 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'; export enum PaginationStrategy { Finite, @@ -172,7 +187,22 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte /** Custom row filter */ @Input() - rowFilter: any | null = null; + _rowFilter: RowFilter | null = null; + + @Input() + set rowFilter(rowFilter: RowFilter) { + this._rowFilter = rowFilter; + if (this.data) { + this.data.setFilter(this._rowFilter); + if (this.currentFolderId) { + this.reload(); + } + } + } + + get rowFilter(): RowFilter { + return this._rowFilter; + } /** Custom image resolver */ @Input() @@ -225,7 +255,10 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte data: ShareDataTableAdapter; noPermission: boolean = false; selection = new Array(); - folderNode: Node = null; + $folderNode: Subject = new Subject(); + + // @deprecated 3.0.0 + folderNode: Node; private _pagination: BehaviorSubject; private layoutPresets = {}; @@ -305,8 +338,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte this.data.thumbnails = this.thumbnails; this.data.permissionsStyle = this.permissionsStyle; - if (this.rowFilter) { - this.data.setFilter(this.rowFilter); + if (this._rowFilter) { + this.data.setFilter(this._rowFilter); } if (this.imageResolver) { @@ -371,17 +404,16 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte if (changes.currentFolderId && changes.currentFolderId.currentValue && changes.currentFolderId.currentValue !== changes.currentFolderId.previousValue) { + if (this.data) { + this.data.loadPage(null, false); + } + this.resetNewFolderPagination(); this.loadFolder(); } else if (this.data) { if (changes.node && changes.node.currentValue) { this.data.loadPage(changes.node.currentValue); this.onDataReady(changes.node.currentValue); - } else if (changes.rowFilter && changes.rowFilter.currentValue !== changes.rowFilter.previousValue) { - this.data.setFilter(changes.rowFilter.currentValue); - if (this.currentFolderId) { - this.loadFolderNodesByFolderNodeId(this.currentFolderId, this.pagination.getValue()).catch((err) => this.error.emit(err)); - } } else if (changes.imageResolver) { this.data.setImageResolver(changes.imageResolver.currentValue); } @@ -392,7 +424,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte this.ngZone.run(() => { this.resetSelection(); if (this.node) { - this.data.loadPage(this.node); + this.data.loadPage(this.node, this.pagination.getValue().merge); this.onDataReady(this.node); } else { this.loadFolder(); @@ -479,40 +511,35 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte } } - performNavigation(node: NodeEntry): boolean { - if (this.canNavigateFolder(node)) { - this.updateFolderData(node); + navigateTo(node: Node | string): boolean { + if (typeof node === 'string') { + this.resetNewFolderPagination(); + this.currentFolderId = node; + this.folderChange.emit(new NodeEntryEvent( { id: node })); + this.reload(); return true; + } else { + if (this.canNavigateFolder(node)) { + this.resetNewFolderPagination(); + this.currentFolderId = this.getNodeFolderDestinationId(node); + this.folderChange.emit(new NodeEntryEvent( { id: this.currentFolderId })); + this.reload(); + return true; + } } return false; } - performCustomSourceNavigation(node: NodeEntry): boolean { - if (this.customResourcesService.isCustomSource(this.currentFolderId)) { - this.updateFolderData(node); - return true; - } - return false; + private getNodeFolderDestinationId(node: Node) { + return this.isLinkFolder(node) ? node.properties['cm:destination'] : node.id; } - updateFolderData(node: NodeEntry): void { - this.resetNewFolderPagination(); - this.currentFolderId = this.getNodeFolderDestinationId(node); - this.folderChange.emit(new NodeEntryEvent( { id: this.currentFolderId })); - this.reload(); - } - - private getNodeFolderDestinationId(node: NodeEntry) { - return this.isLinkFolder(node) ? node.entry.properties['cm:destination'] : node.entry.id; - } - - private isLinkFolder(node: NodeEntry) { - return node.entry.nodeType === 'app:folderlink' && node.entry.properties && - node.entry.properties['cm:destination']; + private isLinkFolder(node: Node) { + return node.nodeType === 'app:folderlink' && node.properties && + node.properties['cm:destination']; } updateCustomSourceData(nodeId: string): void { - this.folderNode = null; this.currentFolderId = nodeId; } @@ -573,39 +600,26 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte this.error.emit(err); }); } else { - this.documentListService - .getFolderNode(nodeId, this.includeFields) - .subscribe((node: NodeEntry) => { - this.folderNode = node.entry; - return this.loadFolderNodesByFolderNodeId(node.entry.id, this.pagination.getValue()) - .catch((err) => this.handleError(err)); + let pagination = this.pagination.getValue(); + this.documentListService.getFolder(null, { + maxItems: pagination.maxItems, + skipCount: pagination.skipCount, + rootFolderId: nodeId + }, this.includeFields) + .subscribe((nodePaging: NodePaging) => { + this.data.loadPage(nodePaging, this.pagination.getValue().merge); + this.setLoadingState(false); + this.onDataReady(nodePaging); + this.documentListService.getFolderNode(nodeId, this.includeFields).subscribe((nodeEntry: NodeEntry) => { + this.folderNode = nodeEntry.entry; + this.$folderNode.next(this.folderNode); + }); }, (err) => { this.handleError(err); }); } } - loadFolderNodesByFolderNodeId(id: string, pagination: PaginationModel): Promise { - return new Promise((resolve, reject) => { - - this.documentListService - .getFolder(null, { - maxItems: pagination.maxItems, - skipCount: pagination.skipCount, - rootFolderId: id - }, this.includeFields) - .subscribe( - (nodePaging) => { - this.data.loadPage( nodePaging, this.pagination.getValue().merge); - this.setLoadingState(false); - this.onDataReady(nodePaging); - resolve(true); - }, (err) => { - this.handleError(err); - }); - }); - } - resetSelection() { this.dataTable.resetSelection(); this.selection = []; @@ -636,58 +650,56 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte } } - onNodeClick(node: NodeEntry) { + onNodeClick(nodeEntry: NodeEntry) { const domEvent = new CustomEvent('node-click', { detail: { sender: this, - node: node + node: nodeEntry }, bubbles: true }); + this.elementRef.nativeElement.dispatchEvent(domEvent); - const event = new NodeEntityEvent(node); + const event = new NodeEntityEvent(nodeEntry); this.nodeClick.emit(event); if (!event.defaultPrevented) { if (this.navigate && this.navigationMode === DocumentListComponent.SINGLE_CLICK_NAVIGATION) { - if (node && node.entry) { - if (node.entry.isFile) { - this.onPreviewFile(node); - } - - if (node.entry.isFolder) { - this.performNavigation(node); - } - } + this.executeActionClick(nodeEntry); } } + } - onNodeDblClick(node: NodeEntry) { + onNodeDblClick(nodeEntry: NodeEntry) { const domEvent = new CustomEvent('node-dblclick', { detail: { sender: this, - node: node + node: nodeEntry }, bubbles: true }); this.elementRef.nativeElement.dispatchEvent(domEvent); - const event = new NodeEntityEvent(node); + const event = new NodeEntityEvent(nodeEntry); this.nodeDblClick.emit(event); if (!event.defaultPrevented) { if (this.navigate && this.navigationMode === DocumentListComponent.DOUBLE_CLICK_NAVIGATION) { - if (node && node.entry) { - if (node.entry.isFile) { - this.onPreviewFile(node); - } + this.executeActionClick(nodeEntry); + } + } + } - if (node.entry.isFolder) { - this.performNavigation(node); - } - } + executeActionClick(nodeEntry: NodeEntry) { + if (nodeEntry && nodeEntry.entry) { + if (nodeEntry.entry.isFile) { + this.onPreviewFile(nodeEntry); + } + + if (nodeEntry.entry.isFolder) { + this.navigateTo(nodeEntry.entry); } } } @@ -751,12 +763,12 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte } } - canNavigateFolder(node: NodeEntry): boolean { + canNavigateFolder(node: Node): boolean { let canNavigateFolder: boolean = false; if (this.customResourcesService.isCustomSource(this.currentFolderId)) { canNavigateFolder = false; - } else if (node && node.entry && node.entry.isFolder) { + } else if (node && node.isFolder) { canNavigateFolder = true; } @@ -784,15 +796,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte this.reload(); } - navigateTo(nodeId: string) { - this.currentFolderId = nodeId; - this.resetNewFolderPagination(); - this.loadFolder(); - this.folderChange.emit(new NodeEntryEvent( { id: nodeId })); - } - private resetNewFolderPagination() { - this.folderNode = null; this.pagination.value.skipCount = 0; } 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 9e3a8412e0..ffd3430114 100644 --- a/lib/content-services/document-list/data/share-datatable-adapter.ts +++ b/lib/content-services/document-list/data/share-datatable-adapter.ts @@ -15,11 +15,20 @@ * limitations under the License. */ -import { DataColumn, DataRow, DataSorting, DataTableAdapter, ThumbnailService, ContentService } from '@alfresco/adf-core'; +import { + DataColumn, + DataRow, + DataSorting, + DataTableAdapter, + ThumbnailService, + ContentService +} 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'; export class ShareDataTableAdapter implements DataTableAdapter { @@ -31,7 +40,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { private rows: DataRow[]; private columns: DataColumn[]; - private filter: any; + private filter: RowFilter; private imageResolver: any; thumbnails: boolean = false; @@ -156,7 +165,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { this.setSorting(sorting); } - setFilter(filter: any) { + setFilter(filter: RowFilter) { this.filter = filter; } @@ -237,15 +246,15 @@ export class ShareDataTableAdapter implements DataTableAdapter { } public loadPage(page: NodePaging, merge: boolean = false) { - let rows = []; + let shareDataRows: ShareDataRow[] = []; if (page && page.list) { - let data = page.list.entries; - if (data && data.length > 0) { - rows = data.map((item) => new ShareDataRow(item, this.contentService, this.permissionsStyle, this.thumbnailService)); + let nodeEntries: NodeEntry[] = page.list.entries; + if (nodeEntries && nodeEntries.length > 0) { + shareDataRows = nodeEntries.map((item) => new ShareDataRow(item, this.contentService, this.permissionsStyle, this.thumbnailService)); if (this.filter) { - rows = rows.filter(this.filter); + shareDataRows = shareDataRows.filter(this.filter); } if (this.sortingMode !== 'server') { @@ -253,7 +262,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { if (this.columns && this.columns.length > 0) { let sorting = this.getSorting(); if (sorting) { - this.sortRows(rows, sorting); + this.sortRows(shareDataRows, sorting); } else { let sortable = this.columns.filter((c) => c.sortable); if (sortable.length > 0) { @@ -268,7 +277,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { } if (merge) { - let listPrunedDuplicate = rows.filter((elementToFilter) => { + let listPrunedDuplicate = shareDataRows.filter((elementToFilter: any) => { let isPresent = this.rows.find((currentRow: any) => { return currentRow.obj.entry.id === elementToFilter.obj.entry.id; }); @@ -278,7 +287,8 @@ export class ShareDataTableAdapter implements DataTableAdapter { this.rows = this.rows.concat(listPrunedDuplicate); } else { - this.rows = rows; + this.rows = shareDataRows; } } + } diff --git a/lib/content-services/mock/document-list.component.mock.ts b/lib/content-services/mock/document-list.component.mock.ts index d2f499d62a..43413239bf 100644 --- a/lib/content-services/mock/document-list.component.mock.ts +++ b/lib/content-services/mock/document-list.component.mock.ts @@ -15,7 +15,9 @@ * limitations under the License. */ -export const fakeNodeWithCreatePermission = { +import { Node } from '@alfresco/js-api'; + +export const fakeNodeWithCreatePermission = new Node({ isFile: false, createdByUser: { id: 'admin', displayName: 'Administrator' }, modifiedAt: '2017-06-08T13:53:46.495Z', @@ -36,9 +38,9 @@ export const fakeNodeWithCreatePermission = { id: '70e1cc6a-6918-468a-b84a-1048093b06fd', properties: {}, allowableOperations: ['delete', 'update', 'create'] -}; +}); -export const fakeNodeWithNoPermission = { +export const fakeNodeWithNoPermission = new Node({ isFile: false, createdByUser: { id: 'admin', displayName: 'Administrator' }, modifiedAt: '2017-06-08T13:53:46.495Z', @@ -59,7 +61,7 @@ export const fakeNodeWithNoPermission = { name: 'Test', id: '70e1cc6a-6918-468a-b84a-1048093b06fd', properties: {} -}; +}); export const fakeNodeAnswerWithEntries = { 'list': { diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index ded0a5c307..26c8d54d5a 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -414,7 +414,7 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - line-height: 1.12em; + line-height: 1.2em; } /* visible content */ diff --git a/lib/core/directives/highlight.directive.ts b/lib/core/directives/highlight.directive.ts index adfbbb11b9..373faf8790 100644 --- a/lib/core/directives/highlight.directive.ts +++ b/lib/core/directives/highlight.directive.ts @@ -17,13 +17,13 @@ /* tslint:disable:no-input-rename */ -import { Directive, ElementRef, Input, Renderer2 } from '@angular/core'; +import { Directive, ElementRef, Input, Renderer2, AfterViewChecked } from '@angular/core'; import { HighlightTransformService, HighlightTransformResult } from '../services/highlight-transform.service'; @Directive({ selector: '[adf-highlight]' }) -export class HighlightDirective { +export class HighlightDirective implements AfterViewChecked { /** Class selector for highlightable elements. */ @Input('adf-highlight-selector') @@ -40,7 +40,12 @@ export class HighlightDirective { constructor( private el: ElementRef, private renderer: Renderer2, - private highlightTransformService: HighlightTransformService) { } + private highlightTransformService: HighlightTransformService) { + } + + ngAfterViewChecked() { + this.highlight(); + } public highlight(search = this.search, selector = this.selector, classToApply = this.classToApply) { if (search && selector) { diff --git a/lib/core/pagination/infinite-pagination.component.spec.ts b/lib/core/pagination/infinite-pagination.component.spec.ts index 49ab5edd69..1c314712eb 100644 --- a/lib/core/pagination/infinite-pagination.component.spec.ts +++ b/lib/core/pagination/infinite-pagination.component.spec.ts @@ -131,7 +131,7 @@ describe('InfinitePaginationComponent', () => { fixture.detectChanges(); component.loadMore.subscribe((newPagination: Pagination) => { - expect(newPagination.skipCount).toBe(0); + expect(newPagination.skipCount).toBe(10); done(); }); @@ -166,8 +166,8 @@ describe('InfinitePaginationComponent', () => { component.onLoadMore(); expect(spyTarget).toHaveBeenCalledWith({ - maxItems: 444 + 25, - skipCount: 0, + maxItems: 444, + skipCount: 25, totalItems: 888, hasMoreItems: true, merge: true @@ -182,8 +182,8 @@ describe('InfinitePaginationComponent', () => { component.onLoadMore(); expect(spyTarget).toHaveBeenCalledWith({ - maxItems: 444 + component.pageSize, - skipCount: 0, + maxItems: 444, + skipCount: 7, totalItems: 888, hasMoreItems: true, merge: true diff --git a/lib/core/pagination/infinite-pagination.component.ts b/lib/core/pagination/infinite-pagination.component.ts index 395ba8ec7c..22ca6c6c0c 100644 --- a/lib/core/pagination/infinite-pagination.component.ts +++ b/lib/core/pagination/infinite-pagination.component.ts @@ -87,12 +87,11 @@ export class InfinitePaginationComponent implements OnInit, OnDestroy, Paginatio } onLoadMore() { - this.pagination.skipCount = 0; - this.pagination.maxItems = this.pagination.maxItems + this.pageSize; + this.pagination.skipCount += this.pageSize; this.pagination.merge = true; this.loadMore.next(this.pagination); - if (this.pagination.maxItems >= this.pagination.totalItems) { + if (this.pagination.skipCount >= this.pagination.totalItems || !this.pagination.hasMoreItems) { this.pagination.hasMoreItems = false; } diff --git a/lib/core/services/highlight-transform.service.ts b/lib/core/services/highlight-transform.service.ts index 447b33d8c6..115649ac88 100644 --- a/lib/core/services/highlight-transform.service.ts +++ b/lib/core/services/highlight-transform.service.ts @@ -45,10 +45,11 @@ export class HighlightTransformService { }).join('|'); const regex = new RegExp(pattern, 'gi'); - result = text.replace(regex, (match) => { + result = text.replace(/<[^>]+>/g, '').replace(regex, (match) => { isMatching = true; return `${match}`; }); + return { text: result, changed: isMatching }; } else { return { text: result, changed: isMatching }; diff --git a/package-lock.json b/package-lock.json index be906fd3e3..99783a955c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,9 +53,9 @@ } }, "@alfresco/js-api": { - "version": "3.0.0-e9c8ed80decc71d2fc6833cef22851b64ce4b604", - "resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-3.0.0-e9c8ed80decc71d2fc6833cef22851b64ce4b604.tgz", - "integrity": "sha512-EgCTW+ZOJGvxVUFu5Ul8e0vnW1aITuxTgOKk5AGMFW4JxJoFqEYuo77oqXJITE/1JFsyeuqG63oOjQs2NDjHHw==", + "version": "3.0.0-d7850f421268e21861e2cd219441b7343efd27ba", + "resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-3.0.0-d7850f421268e21861e2cd219441b7343efd27ba.tgz", + "integrity": "sha512-glHDIbJX5xoOT1SBlmryJ1aDEH99a/826KnJK5M/ybLfv5yBg+LFL8aMRRMkz26wzKn9YxRwxh14a+6u2u9o1A==", "requires": { "event-emitter": "0.3.4", "superagent": "3.8.2" @@ -3191,7 +3191,6 @@ "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, - "optional": true, "requires": { "hoek": "2.x.x" } @@ -3852,8 +3851,7 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", - "dev": true, - "optional": true + "dev": true }, "buffer-xor": { "version": "1.0.3", @@ -7191,8 +7189,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -7216,15 +7213,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7241,22 +7236,19 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -7387,8 +7379,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -7402,7 +7393,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -7419,7 +7409,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -7428,15 +7417,13 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -7457,7 +7444,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -7546,8 +7532,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -7561,7 +7546,6 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -7657,8 +7641,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7700,7 +7683,6 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7722,7 +7704,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7771,15 +7752,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", - "dev": true, - "optional": true + "dev": true } } }, @@ -8660,8 +8639,7 @@ "version": "2.16.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true, - "optional": true + "dev": true }, "home-or-tmp": { "version": "2.0.0", @@ -8807,7 +8785,6 @@ "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", "dev": true, - "optional": true, "requires": { "httpreq": ">=0.4.22", "underscore": "~1.7.0" @@ -8817,8 +8794,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true, - "optional": true + "dev": true } } }, @@ -8826,8 +8802,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true, - "optional": true + "dev": true }, "https-browserify": { "version": "1.0.0", @@ -9710,8 +9685,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true, - "optional": true + "dev": true }, "is-redirect": { "version": "1.0.0", @@ -10670,15 +10644,13 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true, - "optional": true + "dev": true }, "libmime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", "dev": true, - "optional": true, "requires": { "iconv-lite": "0.4.15", "libbase64": "0.1.0", @@ -10689,8 +10661,7 @@ "version": "0.4.15", "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true, - "optional": true + "dev": true } } }, @@ -10698,8 +10669,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true, - "optional": true + "dev": true }, "license-webpack-plugin": { "version": "2.0.2", @@ -13030,15 +13000,13 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true, - "optional": true + "dev": true }, "nodemailer-shared": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", "dev": true, - "optional": true, "requires": { "nodemailer-fetch": "1.6.0" } @@ -13071,8 +13039,7 @@ "version": "0.1.10", "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true, - "optional": true + "dev": true }, "nopt": { "version": "3.0.6", @@ -16536,7 +16503,6 @@ "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", "dev": true, - "optional": true, "requires": { "httpntlm": "1.6.1", "nodemailer-shared": "1.1.0" diff --git a/package.json b/package.json index 73c9b2cb93..e450ff3696 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "@alfresco/adf-insights": "3.0.0-1c25b50b1a15635da1689fdb9f38449a5714630b", "@alfresco/adf-process-services": "3.0.0-1c25b50b1a15635da1689fdb9f38449a5714630b", "@alfresco/adf-process-services-cloud": "3.0.0-1c25b50b1a15635da1689fdb9f38449a5714630b", - "@alfresco/js-api": "3.0.0-e9c8ed80decc71d2fc6833cef22851b64ce4b604", + "@alfresco/js-api": "^3.0.0-d7850f421268e21861e2cd219441b7343efd27ba", "@angular/animations": "7.0.3", "@angular/cdk": "7.0.3", "@angular/common": "7.0.3",