diff --git a/projects/aca-content/src/lib/components/favorites/favorites.component.spec.ts b/projects/aca-content/src/lib/components/favorites/favorites.component.spec.ts index 72a9dd25b..ff295db2f 100644 --- a/projects/aca-content/src/lib/components/favorites/favorites.component.spec.ts +++ b/projects/aca-content/src/lib/components/favorites/favorites.component.spec.ts @@ -31,7 +31,7 @@ import { AppTestingModule } from '../../testing/app-testing.module'; import { AppService, ContentApiService } from '@alfresco/aca-shared'; import { getTitleElementText } from '../../testing/test-utils'; import { MatSnackBarModule } from '@angular/material/snack-bar'; -import { testHeader } from '../../testing/document-base-page-utils'; +import { testHeader, testUploadEvents } from '../../testing/document-base-page-utils'; describe('FavoritesComponent', () => { let fixture: ComponentFixture; @@ -143,4 +143,9 @@ describe('FavoritesComponent', () => { }); testHeader(FavoritesComponent); + + testUploadEvents( + () => component, + () => fixture + ); }); diff --git a/projects/aca-content/src/lib/components/favorites/favorites.component.ts b/projects/aca-content/src/lib/components/favorites/favorites.component.ts index 4798947a9..94547b033 100644 --- a/projects/aca-content/src/lib/components/favorites/favorites.component.ts +++ b/projects/aca-content/src/lib/components/favorites/favorites.component.ts @@ -80,8 +80,8 @@ export class FavoritesComponent extends PageComponent implements OnInit { super.ngOnInit(); this.subscriptions = this.subscriptions.concat([ - this.uploadService.fileUploadComplete.pipe(debounceTime(300)).subscribe(() => this.reload()), - this.uploadService.fileUploadDeleted.pipe(debounceTime(300)).subscribe(() => this.reload()) + this.uploadService.fileUploadComplete.pipe(debounceTime(300)).subscribe(() => this.reloadWithoutResettingSelection()), + this.uploadService.fileUploadDeleted.pipe(debounceTime(300)).subscribe(() => this.reloadWithoutResettingSelection()) ]); this.columns = this.extensions.documentListPresets.favorites; diff --git a/projects/aca-content/src/lib/components/files/files.component.spec.ts b/projects/aca-content/src/lib/components/files/files.component.spec.ts index 2514d3b48..8995e08ee 100644 --- a/projects/aca-content/src/lib/components/files/files.component.spec.ts +++ b/projects/aca-content/src/lib/components/files/files.component.spec.ts @@ -25,7 +25,14 @@ import { TestBed, fakeAsync, tick, ComponentFixture } from '@angular/core/testing'; import { NO_ERRORS_SCHEMA, SimpleChange, SimpleChanges } from '@angular/core'; import { Router, ActivatedRoute, convertToParamMap, ParamMap } from '@angular/router'; -import { DocumentListService, FilterSearch, SearchHeaderQueryBuilderService, UploadService } from '@alfresco/adf-content-services'; +import { + DocumentListService, + FileUploadCompleteEvent, + FileUploadDeleteEvent, + FilterSearch, + SearchHeaderQueryBuilderService, + UploadService +} from '@alfresco/adf-content-services'; import { NodeActionsService } from '../../services/node-actions.service'; import { FilesComponent } from './files.component'; import { AppTestingModule } from '../../testing/app-testing.module'; @@ -243,6 +250,7 @@ describe('FilesComponent', () => { describe('refresh on events', () => { beforeEach(() => { spyOn(component, 'reload'); + spyOn(component, 'reloadWithoutResettingSelection'); fixture.detectChanges(); spyOn(component.documentList, 'loadFolder').and.callFake(() => {}); @@ -288,32 +296,34 @@ describe('FilesComponent', () => { expect(component.reload).not.toHaveBeenCalled(); }); - it('should call refresh on fileUploadComplete event if parent node match', fakeAsync(() => { - const file: any = { file: { options: { parentId: 'parentId' } } }; - component.node = { id: 'parentId' } as any; + it('should call reloadWithoutResettingSelection on fileUploadComplete event if parent node match', fakeAsync(() => { + const file = { file: { options: { parentId: 'parentId' } } } as FileUploadCompleteEvent; + component.node = { id: 'parentId' } as Node; uploadService.fileUploadComplete.next(file); tick(500); - expect(component.reload).toHaveBeenCalled(); + expect(component.reload).not.toHaveBeenCalled(); + expect(component.reloadWithoutResettingSelection).toHaveBeenCalled(); })); it('should not call reload on fileUploadComplete event if file parent folder already displayed', fakeAsync(() => { spyOn(component.documentList.data, 'getRows').and.returnValue([{ node: { entry: { isFolder: true, name: 'files' } } }] as any); - const file: any = { file: { options: { parentId: 'parentId', path: '/files' } } }; - component.node = { id: 'parentId' } as any; + const file = { file: { options: { parentId: 'parentId', path: '/files' } } } as FileUploadCompleteEvent; + component.node = { id: 'parentId' } as Node; uploadService.fileUploadComplete.next(file); tick(500); expect(component.reload).not.toHaveBeenCalled(); + expect(component.reloadWithoutResettingSelection).not.toHaveBeenCalled(); })); it('should not call refresh on fileUploadComplete event if parent mismatch', fakeAsync(() => { - const file: any = { file: { options: { parentId: 'otherId' } } }; - component.node = { id: 'parentId' } as any; + const file = { file: { options: { parentId: 'otherId' } } } as FileUploadCompleteEvent; + component.node = { id: 'parentId' } as Node; uploadService.fileUploadComplete.next(file); @@ -322,26 +332,58 @@ describe('FilesComponent', () => { expect(component.reload).not.toHaveBeenCalled(); })); - it('should call refresh on fileUploadDeleted event if parent node match', fakeAsync(() => { - const file: any = { file: { options: { parentId: 'parentId' } } }; - component.node = { id: 'parentId' } as any; - - uploadService.fileUploadDeleted.next(file); - - tick(500); - - expect(component.reload).toHaveBeenCalled(); - })); - - it('should not call refresh on fileUploadDeleted event if parent mismatch', fakeAsync(() => { - const file: any = { file: { options: { parentId: 'otherId' } } }; - component.node = { id: 'parentId' } as any; + it('should call reloadWithoutResettingSelection on fileUploadDeleted event when folder parent uploaded to current folder', fakeAsync(() => { + const file = { file: { options: { parentId: 'parentId' } } } as FileUploadDeleteEvent; + component.node = { id: 'parentId' } as Node; uploadService.fileUploadDeleted.next(file); tick(500); expect(component.reload).not.toHaveBeenCalled(); + expect(component.reloadWithoutResettingSelection).toHaveBeenCalled(); + })); + + it('should not call refresh on fileUploadDeleted event if parent mismatch', fakeAsync(() => { + const file = { file: { options: { parentId: 'otherId' } } } as FileUploadDeleteEvent; + component.node = { id: 'parentId' } as Node; + + uploadService.fileUploadDeleted.next(file); + + tick(500); + + expect(component.reload).not.toHaveBeenCalled(); + })); + + it('should call reloadWithoutResettingSelection when uploaded file belongs to current folder', fakeAsync(() => { + const file = { file: { data: { entry: { parentId: 'folder-id' } }, options: {} } } as FileUploadCompleteEvent; + component.node = { id: 'folder-id' } as Node; + + uploadService.fileUploadComplete.next(file); + tick(500); + + expect(component.reload).not.toHaveBeenCalled(); + expect(component.reloadWithoutResettingSelection).toHaveBeenCalled(); + })); + + it('should NOT call reloadWithoutResettingSelection when uploaded file belongs to a different folder', fakeAsync(() => { + const file = { file: { data: { entry: { parentId: 'other-folder-id' } }, options: {} } } as FileUploadCompleteEvent; + component.node = { id: 'folder-id' } as Node; + + uploadService.fileUploadComplete.next(file); + tick(500); + + expect(component.reloadWithoutResettingSelection).not.toHaveBeenCalled(); + })); + + it('should call reloadWithoutResettingSelection on fileUploadDeleted when file belongs to current folder', fakeAsync(() => { + const file = { file: { data: { entry: { parentId: 'folder-id' } }, options: {} } } as FileUploadDeleteEvent; + component.node = { id: 'folder-id' } as Node; + + uploadService.fileUploadDeleted.next(file); + tick(500); + + expect(component.reloadWithoutResettingSelection).toHaveBeenCalled(); })); }); diff --git a/projects/aca-content/src/lib/components/files/files.component.ts b/projects/aca-content/src/lib/components/files/files.component.ts index c056aeae4..bb11a1e4c 100644 --- a/projects/aca-content/src/lib/components/files/files.component.ts +++ b/projects/aca-content/src/lib/components/files/files.component.ts @@ -271,7 +271,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy { // check root and child nodes if (node?.entry?.parentId === this.getParentNodeId()) { - this.reload(this.selectedNode); + this.reloadWithoutResettingSelection(); return; } @@ -303,7 +303,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy { if (alreadyDisplayedParentFolder) { return; } - this.reload(this.selectedNode); + this.reloadWithoutResettingSelection(); } onContentAdded(nodes: NodeEntry[]) { diff --git a/projects/aca-content/src/lib/components/recent-files/recent-files.component.spec.ts b/projects/aca-content/src/lib/components/recent-files/recent-files.component.spec.ts index 0747a9121..d6dca6d49 100644 --- a/projects/aca-content/src/lib/components/recent-files/recent-files.component.spec.ts +++ b/projects/aca-content/src/lib/components/recent-files/recent-files.component.spec.ts @@ -31,7 +31,7 @@ import { NodePaging, SearchApi } from '@alfresco/js-api'; import { of } from 'rxjs'; import { getTitleElementText } from '../../testing/test-utils'; import { MatSnackBarModule } from '@angular/material/snack-bar'; -import { testHeader } from '../../testing/document-base-page-utils'; +import { testHeader, testUploadEvents } from '../../testing/document-base-page-utils'; describe('RecentFilesComponent', () => { let fixture: ComponentFixture; @@ -113,4 +113,9 @@ describe('RecentFilesComponent', () => { }); testHeader(RecentFilesComponent); + + testUploadEvents( + () => component, + () => fixture + ); }); diff --git a/projects/aca-content/src/lib/components/recent-files/recent-files.component.ts b/projects/aca-content/src/lib/components/recent-files/recent-files.component.ts index afc056d90..87de75402 100644 --- a/projects/aca-content/src/lib/components/recent-files/recent-files.component.ts +++ b/projects/aca-content/src/lib/components/recent-files/recent-files.component.ts @@ -77,8 +77,8 @@ export class RecentFilesComponent extends PageComponent implements OnInit { super.ngOnInit(); this.subscriptions = this.subscriptions.concat([ - this.uploadService.fileUploadComplete.pipe(debounceTime(300)).subscribe(() => this.reload()), - this.uploadService.fileUploadDeleted.pipe(debounceTime(300)).subscribe(() => this.reload()) + this.uploadService.fileUploadComplete.pipe(debounceTime(300)).subscribe(() => this.reloadWithoutResettingSelection()), + this.uploadService.fileUploadDeleted.pipe(debounceTime(300)).subscribe(() => this.reloadWithoutResettingSelection()) ]); this.columns = this.extensions.documentListPresets.recent || []; diff --git a/projects/aca-content/src/lib/components/shared-files/shared-files.component.spec.ts b/projects/aca-content/src/lib/components/shared-files/shared-files.component.spec.ts index bd2cd68fb..f732f893e 100644 --- a/projects/aca-content/src/lib/components/shared-files/shared-files.component.spec.ts +++ b/projects/aca-content/src/lib/components/shared-files/shared-files.component.spec.ts @@ -33,7 +33,7 @@ import { AppService } from '@alfresco/aca-shared'; import { getTitleElementText } from '../../testing/test-utils'; import { ActivatedRoute, NavigationStart, Router } from '@angular/router'; import { MatSnackBarModule } from '@angular/material/snack-bar'; -import { testHeader } from '../../testing/document-base-page-utils'; +import { testHeader, testUploadEvents } from '../../testing/document-base-page-utils'; describe('SharedFilesComponent', () => { let fixture: ComponentFixture; @@ -108,4 +108,9 @@ describe('SharedFilesComponent', () => { }); testHeader(SharedFilesComponent); + + testUploadEvents( + () => component, + () => fixture + ); }); diff --git a/projects/aca-content/src/lib/components/shared-files/shared-files.component.ts b/projects/aca-content/src/lib/components/shared-files/shared-files.component.ts index 7071ed59b..2490dadf5 100644 --- a/projects/aca-content/src/lib/components/shared-files/shared-files.component.ts +++ b/projects/aca-content/src/lib/components/shared-files/shared-files.component.ts @@ -81,8 +81,8 @@ export class SharedFilesComponent extends PageComponent implements OnInit { this.subscriptions = this.subscriptions.concat([ this.appHookService.linksUnshared.pipe(debounceTime(300)).subscribe(() => this.reload()), - this.uploadService.fileUploadComplete.pipe(debounceTime(300)).subscribe(() => this.reload()), - this.uploadService.fileUploadDeleted.pipe(debounceTime(300)).subscribe(() => this.reload()) + this.uploadService.fileUploadComplete.pipe(debounceTime(300)).subscribe(() => this.reloadWithoutResettingSelection()), + this.uploadService.fileUploadDeleted.pipe(debounceTime(300)).subscribe(() => this.reloadWithoutResettingSelection()) ]); this.columns = this.extensions.documentListPresets.shared || []; diff --git a/projects/aca-content/src/lib/testing/document-base-page-utils.ts b/projects/aca-content/src/lib/testing/document-base-page-utils.ts index d0409d057..e39b7ae8c 100644 --- a/projects/aca-content/src/lib/testing/document-base-page-utils.ts +++ b/projects/aca-content/src/lib/testing/document-base-page-utils.ts @@ -23,11 +23,18 @@ */ import { BehaviorSubject, Subject } from 'rxjs'; -import { AgentService, SearchAiInputState, SearchAiService } from '@alfresco/adf-content-services'; +import { + AgentService, + FileUploadCompleteEvent, + FileUploadDeleteEvent, + SearchAiInputState, + SearchAiService, + UploadService +} from '@alfresco/adf-content-services'; import { DebugElement, Type } from '@angular/core'; import { By } from '@angular/platform-browser'; import { SearchAiInputContainerComponent } from '../components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { PageComponent } from '@alfresco/aca-shared'; import { Agent } from '@alfresco/js-api/typings'; @@ -101,3 +108,30 @@ export const testHeader = (component: Type, checkHea } }); }; + +export const testUploadEvents = (getComponent: () => T, getFixture: () => ComponentFixture) => { + describe('upload events', () => { + beforeEach(() => { + const component: PageComponent = getComponent(); + spyOn(component, 'reload'); + spyOn(component, 'reloadWithoutResettingSelection'); + getFixture().detectChanges(); + }); + + it('should call reloadWithoutResettingSelection and not reload on fileUploadComplete', fakeAsync(() => { + TestBed.inject(UploadService).fileUploadComplete.next({} as FileUploadCompleteEvent); + tick(300); + const component = getComponent(); + expect(component.reloadWithoutResettingSelection).toHaveBeenCalled(); + expect(component.reload).not.toHaveBeenCalled(); + })); + + it('should call reloadWithoutResettingSelection and not reload on fileUploadDeleted', fakeAsync(() => { + TestBed.inject(UploadService).fileUploadDeleted.next({} as FileUploadDeleteEvent); + tick(300); + const component = getComponent(); + expect(component.reloadWithoutResettingSelection).toHaveBeenCalled(); + expect(component.reload).not.toHaveBeenCalled(); + })); + }); +}; diff --git a/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts b/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts index cf318a711..70ba023a5 100644 --- a/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts +++ b/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts @@ -226,6 +226,13 @@ export abstract class PageComponent implements OnInit, OnDestroy, OnChanges { } } + reloadWithoutResettingSelection(): void { + if (this.isOutletPreviewUrl()) { + return; + } + this.documentListService.reloadSilently(); + } + trackByActionId(_: number, action: ContentActionRef) { return action.id; } diff --git a/projects/aca-shared/src/lib/components/document-base-page/document-base-page.spec.ts b/projects/aca-shared/src/lib/components/document-base-page/document-base-page.spec.ts index 32167ef37..9377a67fc 100644 --- a/projects/aca-shared/src/lib/components/document-base-page/document-base-page.spec.ts +++ b/projects/aca-shared/src/lib/components/document-base-page/document-base-page.spec.ts @@ -157,6 +157,23 @@ describe('PageComponent', () => { expect(store.dispatch['calls'].mostRecent().args[0]).toEqual(new SetSelectedNodesAction([node])); }); + it('should call documentListService.reloadSilently()', () => { + spyOn(documentListService, 'reloadSilently'); + + component.reloadWithoutResettingSelection(); + + expect(documentListService.reloadSilently).toHaveBeenCalledWith(); + }); + + it('should not call documentListService.reloadSilently() when url contains viewer outlet', () => { + window.history.pushState({}, null, `${locationHref}#test(viewer:view)`); + spyOn(documentListService, 'reloadSilently'); + + component.reloadWithoutResettingSelection(); + + expect(documentListService.reloadSilently).not.toHaveBeenCalled(); + }); + it('should call ViewNodeAction on showPreview for selected node', () => { spyOn(store, 'dispatch'); const node = {