mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2026-09-09 18:02:54 +00:00
[ACS-12391] Clicking the reduce panel displays reduced details view (#5333)
* [ACS-12391] Clicking the reduce panel displays reduced details view * [ACS-12391] Add lifecycle teardown to activatedRoute * [ACS-12391] Fix unit test * [ACS-12391] File remains selected when user clicks on reduce panel button * [ACS-12391] Fix review issues
This commit is contained in:
@@ -25,16 +25,17 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { DetailsComponent } from './details.component';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRoute, NavigationEnd, Params, Router } from '@angular/router';
|
||||
import { BehaviorSubject, of, Subject } from 'rxjs';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppExtensionService, AppHookService, ContentApiService } from '@alfresco/aca-shared';
|
||||
import { NavigateToFolder, SetSelectedNodesAction } from '@alfresco/aca-shared/store';
|
||||
import { NavigateToFolder, NavigateToPreviousPage, SetInfoDrawerStateAction, SetSelectedNodesAction } from '@alfresco/aca-shared/store';
|
||||
import { Node, NodeEntry, PathElement } from '@alfresco/js-api';
|
||||
import { BreadcrumbComponent, ContentService, NodesApiService, SearchQueryBuilderService } from '@alfresco/adf-content-services';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { ContentActionRef } from '@alfresco/adf-extensions';
|
||||
import { Location } from '@angular/common';
|
||||
import { UnitTestingUtils } from '@alfresco/adf-core';
|
||||
|
||||
describe('DetailsComponent', () => {
|
||||
let component: DetailsComponent;
|
||||
@@ -45,7 +46,10 @@ describe('DetailsComponent', () => {
|
||||
let appHookService: AppHookService;
|
||||
let location: Location;
|
||||
let store: Store;
|
||||
let router: Router;
|
||||
let node: NodeEntry;
|
||||
let queryParamsSubject: BehaviorSubject<Params>;
|
||||
let testingUtils: UnitTestingUtils;
|
||||
|
||||
const mockStream = new Subject();
|
||||
const storeMock = {
|
||||
@@ -58,6 +62,7 @@ describe('DetailsComponent', () => {
|
||||
const getBreadcrumb = (): BreadcrumbComponent => fixture.debugElement.query(By.directive(BreadcrumbComponent)).componentInstance;
|
||||
|
||||
beforeEach(() => {
|
||||
queryParamsSubject = new BehaviorSubject<Params>({});
|
||||
TestBed.configureTestingModule({
|
||||
imports: [AppTestingModule, DetailsComponent],
|
||||
providers: [
|
||||
@@ -67,7 +72,8 @@ describe('DetailsComponent', () => {
|
||||
provide: ActivatedRoute,
|
||||
useValue: {
|
||||
snapshot: { data: { preferencePrefix: 'prefix' } },
|
||||
params: of({ nodeId: 'someId', activeTab: 'permissions' })
|
||||
params: of({ nodeId: 'someId', activeTab: 'permissions' }),
|
||||
queryParams: queryParamsSubject
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -78,12 +84,14 @@ describe('DetailsComponent', () => {
|
||||
|
||||
fixture = TestBed.createComponent(DetailsComponent);
|
||||
component = fixture.componentInstance;
|
||||
testingUtils = new UnitTestingUtils(fixture.debugElement);
|
||||
contentApiService = TestBed.inject(ContentApiService);
|
||||
contentService = TestBed.inject(ContentService);
|
||||
nodesApiService = TestBed.inject(NodesApiService);
|
||||
appHookService = TestBed.inject(AppHookService);
|
||||
location = TestBed.inject(Location);
|
||||
store = TestBed.inject(Store);
|
||||
router = TestBed.inject(Router);
|
||||
storeMock.dispatch.calls.reset();
|
||||
|
||||
node = {
|
||||
@@ -243,4 +251,46 @@ describe('DetailsComponent', () => {
|
||||
|
||||
expect(locationSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('Reduce Panel', () => {
|
||||
const getReducePanelButton = (): HTMLButtonElement => testingUtils.getByDataAutomationId('close-library').nativeElement;
|
||||
const clickReducePanelButton = (): void => getReducePanelButton().click();
|
||||
|
||||
it('should navigate to the file list page, keep the node selected and the info drawer open', () => {
|
||||
queryParamsSubject.next({ location: '/personal-files' });
|
||||
fixture.detectChanges();
|
||||
const navigateSpy = spyOn(router, 'navigateByUrl').and.stub();
|
||||
Object.defineProperty(router, 'events', { value: of(new NavigationEnd(1, '', '')) });
|
||||
const nodeToSelectSpy = spyOn(appHookService.nodeToSelect$, 'next');
|
||||
|
||||
clickReducePanelButton();
|
||||
|
||||
expect(navigateSpy).toHaveBeenCalledWith('/personal-files');
|
||||
expect(nodeToSelectSpy).toHaveBeenCalledWith({ entry: node.entry });
|
||||
expect(store.dispatch).toHaveBeenCalledWith(jasmine.any(SetInfoDrawerStateAction));
|
||||
expect(store.dispatch).toHaveBeenCalledWith(jasmine.objectContaining({ payload: true }));
|
||||
});
|
||||
|
||||
it('should navigate to viewer page and keep the info drawer open', () => {
|
||||
queryParamsSubject.next({ location: 'personal-files/(viewer:view/nodeId)?location=personal-files%2Fdetails%2Fabc123%2Fpermissions' });
|
||||
fixture.detectChanges();
|
||||
Object.defineProperty(router, 'events', { value: of(new NavigationEnd(1, '', '')) });
|
||||
const navigateSpy = spyOn(router, 'navigateByUrl').and.stub();
|
||||
|
||||
clickReducePanelButton();
|
||||
|
||||
expect(navigateSpy).toHaveBeenCalledWith('personal-files/(viewer:view/nodeId)?location=personal-files%2Fdetails%2Fabc123%2Fpermissions');
|
||||
expect(store.dispatch).toHaveBeenCalledWith(jasmine.any(SetInfoDrawerStateAction));
|
||||
expect(store.dispatch).toHaveBeenCalledWith(jasmine.objectContaining({ payload: true }));
|
||||
});
|
||||
|
||||
it('should dispatch NavigateToPreviousPage when there is no previous route', () => {
|
||||
fixture.detectChanges();
|
||||
Object.defineProperty(router, 'events', { value: of(new NavigationEnd(1, '', '')) });
|
||||
|
||||
clickReducePanelButton();
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith(jasmine.any(NavigateToPreviousPage));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
*/
|
||||
|
||||
import { Component, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRoute, NavigationEnd } from '@angular/router';
|
||||
import { AppHookService, ContentApiService, PageComponent, PageLayoutComponent, ToolbarComponent } from '@alfresco/aca-shared';
|
||||
import { NavigateToFolder, NavigateToPreviousPage, SetSelectedNodesAction } from '@alfresco/aca-shared/store';
|
||||
import { NavigateToFolder, NavigateToPreviousPage, SetInfoDrawerStateAction, SetSelectedNodesAction } from '@alfresco/aca-shared/store';
|
||||
import { BreadcrumbComponent, ContentService, NodesApiService, PermissionListComponent } from '@alfresco/adf-content-services';
|
||||
import { CommonModule, Location } from '@angular/common';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
@@ -70,6 +70,8 @@ export class DetailsComponent extends PageComponent implements OnInit, OnDestroy
|
||||
private readonly appHookService = inject(AppHookService);
|
||||
private readonly location = inject(Location);
|
||||
|
||||
private previousRoute = '';
|
||||
|
||||
nodeId: string;
|
||||
isLoading: boolean;
|
||||
activeTab = 1;
|
||||
@@ -85,7 +87,12 @@ export class DetailsComponent extends PageComponent implements OnInit, OnDestroy
|
||||
this.title = data.title;
|
||||
this.nodesApiService.nodeUpdated.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((node) => (this.node = { ...node }));
|
||||
this.appHookService.nodesDeleted.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => this.location.back());
|
||||
this.route.params.subscribe((params) => {
|
||||
this.route.queryParams.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => {
|
||||
if (params.location) {
|
||||
this.saveRoute(params.location);
|
||||
}
|
||||
});
|
||||
this.route.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => {
|
||||
this.isLoading = true;
|
||||
this.setActiveTab(params.activeTab);
|
||||
this.nodeId = params.nodeId;
|
||||
@@ -124,8 +131,23 @@ export class DetailsComponent extends PageComponent implements OnInit, OnDestroy
|
||||
}
|
||||
}
|
||||
|
||||
saveRoute(route: string): void {
|
||||
this.previousRoute = route;
|
||||
}
|
||||
|
||||
goBack() {
|
||||
this.store.dispatch(new NavigateToPreviousPage());
|
||||
this.router.events
|
||||
.pipe(first((event) => event instanceof NavigationEnd))
|
||||
.subscribe(() => this.store.dispatch(new SetInfoDrawerStateAction(true)));
|
||||
|
||||
if (this.previousRoute) {
|
||||
if (!this.previousRoute.includes('viewer:') && this.node) {
|
||||
this.appHookService.nodeToSelect$.next({ entry: this.node });
|
||||
}
|
||||
this.router.navigateByUrl(this.previousRoute);
|
||||
} else {
|
||||
this.store.dispatch(new NavigateToPreviousPage());
|
||||
}
|
||||
}
|
||||
|
||||
onBreadcrumbNavigate(path: PathElement) {
|
||||
|
||||
@@ -678,6 +678,25 @@ describe('NodeEffects', () => {
|
||||
jasmine.objectContaining({ ...new NavigateUrlAction('repository/details/node-id?location=test-page') })
|
||||
);
|
||||
});
|
||||
|
||||
it('should use the current url as location when opened from the viewer', () => {
|
||||
spyOn(store, 'dispatch').and.callThrough();
|
||||
spyOnProperty(router, 'url', 'get').and.returnValue('personal-files/(viewer:view/node-id)');
|
||||
Object.defineProperties(router, {
|
||||
events: {
|
||||
value: of(new NavigationEnd(1, 'personal-files/(viewer:view/node-id)', ''))
|
||||
},
|
||||
navigateByUrl: {
|
||||
value: jasmine.createSpy('navigateByUrl')
|
||||
}
|
||||
});
|
||||
const node = { entry: { isFile: true, id: 'node-id' } } as NodeEntry;
|
||||
|
||||
store.dispatch(new ExpandInfoDrawerAction(node));
|
||||
expect(store.dispatch).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({ ...new NavigateUrlAction('personal-files/details/node-id?location=personal-files/(viewer:view/node-id)') })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('nodeInformation$', () => {
|
||||
|
||||
@@ -364,7 +364,8 @@ export class NodeEffects {
|
||||
.subscribe(() => this.store.dispatch(new SetInfoDrawerStateAction(true)));
|
||||
|
||||
this.activatedRoute.queryParams.pipe(take(1)).subscribe((params) => {
|
||||
const location = params.location || this.router.url;
|
||||
const inViewer = this.router.url.includes('viewer:');
|
||||
const location = inViewer ? this.router.url : params.location || this.router.url;
|
||||
const sanitizedLocation = this.sanitizer.sanitize(SecurityContext.URL, location);
|
||||
|
||||
if (action?.payload) {
|
||||
|
||||
Reference in New Issue
Block a user