[ACS-5133] view details button is inactive in expanded view (#3603)

* ACS-5133 Allow to click View Details button in expanded view

* ACS-5133 Unit tests for returning to previous page when info drawer becomes closed

* ACS-5133 Unit tests for changes in expandInfoDrawer effect

* ACS-5133 Fix after rebase

* ACS-5133 Fix

* ACS-5133 Use first instead of filter

* ACS-5133 Fix e2e

* ACS-5133 Trigger jobs

---------

Co-authored-by: Akash Rathod <41251473+akashrathod28@users.noreply.github.com>
This commit is contained in:
AleksanderSklorz 2024-01-21 20:11:36 +01:00 committed by GitHub
parent 608e6c5eb4
commit 91cdb1a9d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 129 additions and 27 deletions

View File

@ -25,12 +25,19 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppTestingModule } from '../../testing/app-testing.module'; import { AppTestingModule } from '../../testing/app-testing.module';
import { DetailsComponent } from './details.component'; import { DetailsComponent } from './details.component';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute, NavigationStart, Router } from '@angular/router';
import { BehaviorSubject, of, Subject } from 'rxjs'; import { BehaviorSubject, of, Subject } from 'rxjs';
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Store } from '@ngrx/store'; import { DefaultProjectorFn, MemoizedSelector, Store } from '@ngrx/store';
import { ContentApiService } from '@alfresco/aca-shared'; import { ContentApiService } from '@alfresco/aca-shared';
import { NavigateToFolder, SetSelectedNodesAction, STORE_INITIAL_APP_DATA } from '@alfresco/aca-shared/store'; import {
AppStore,
isInfoDrawerOpened,
NavigateToFolder,
NavigateToPreviousPage,
SetSelectedNodesAction,
STORE_INITIAL_APP_DATA
} from '@alfresco/aca-shared/store';
import { NodeEntry, PathElement } from '@alfresco/js-api'; import { NodeEntry, PathElement } from '@alfresco/js-api';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { AuthenticationService, PageTitleService } from '@alfresco/adf-core'; import { AuthenticationService, PageTitleService } from '@alfresco/adf-core';
@ -100,6 +107,7 @@ describe('DetailsComponent', () => {
contentApiService = TestBed.inject(ContentApiService); contentApiService = TestBed.inject(ContentApiService);
contentService = TestBed.inject(ContentService); contentService = TestBed.inject(ContentService);
store = TestBed.inject(Store); store = TestBed.inject(Store);
storeMock.dispatch.calls.reset();
node = { node = {
entry: { entry: {
@ -242,4 +250,45 @@ describe('DetailsComponent', () => {
component.setActiveTab('permissions'); component.setActiveTab('permissions');
expect(component.activeTab).not.toBe(2); expect(component.activeTab).not.toBe(2);
}); });
describe('infoDrawerOpened$ event', () => {
let infoDrawerOpened$: Subject<boolean>;
beforeEach(() => {
infoDrawerOpened$ = new Subject<boolean>();
spyOn(store, 'select').and.callFake((mapFn: MemoizedSelector<AppStore, boolean, DefaultProjectorFn<boolean>>) =>
mapFn === isInfoDrawerOpened ? infoDrawerOpened$ : mockStream
);
});
it('should dispatch store NavigateToPreviousPage by store if info drawer is closed', () => {
component.ngOnInit();
infoDrawerOpened$.next(false);
expect(storeMock.dispatch).toHaveBeenCalledWith(jasmine.any(NavigateToPreviousPage));
});
it('should not dispatch store NavigateToPreviousPage by store if info drawer is opened', () => {
component.ngOnInit();
infoDrawerOpened$.next(true);
expect(storeMock.dispatch).not.toHaveBeenCalledWith(jasmine.any(NavigateToPreviousPage));
});
it('should not dispatch store NavigateToPreviousPage by store if info drawer opening state is not changed', () => {
component.ngOnInit();
expect(storeMock.dispatch).not.toHaveBeenCalledWith(jasmine.any(NavigateToPreviousPage));
});
it('should not dispatch store NavigateToPreviousPage by store if info drawer is closed but there occurred NavigationStart event', () => {
Object.defineProperty(TestBed.inject(Router), 'events', {
value: of(new NavigationStart(1, ''))
});
component.ngOnInit();
infoDrawerOpened$.next(false);
expect(storeMock.dispatch).not.toHaveBeenCalledWith(jasmine.any(NavigateToPreviousPage));
});
});
}); });

View File

@ -23,10 +23,10 @@
*/ */
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute, NavigationStart } from '@angular/router';
import { ContentApiService, PageComponent, PageLayoutComponent, ToolbarComponent } from '@alfresco/aca-shared'; import { ContentApiService, PageComponent, PageLayoutComponent, ToolbarComponent } from '@alfresco/aca-shared';
import { NavigateToFolder, NavigateToPreviousPage, SetSelectedNodesAction } from '@alfresco/aca-shared/store'; import { NavigateToFolder, NavigateToPreviousPage, SetSelectedNodesAction } from '@alfresco/aca-shared/store';
import { Subject } from 'rxjs'; import { merge, Subject } from 'rxjs';
import { BreadcrumbModule, ContentService, PermissionManagerModule } from '@alfresco/adf-content-services'; import { BreadcrumbModule, ContentService, PermissionManagerModule } from '@alfresco/adf-content-services';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
@ -37,7 +37,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MetadataTabComponent } from '../info-drawer/metadata-tab/metadata-tab.component'; import { MetadataTabComponent } from '../info-drawer/metadata-tab/metadata-tab.component';
import { CommentsTabComponent } from '../info-drawer/comments-tab/comments-tab.component'; import { CommentsTabComponent } from '../info-drawer/comments-tab/comments-tab.component';
import { NodeEntry, PathElement } from '@alfresco/js-api'; import { NodeEntry, PathElement } from '@alfresco/js-api';
import { takeUntil } from 'rxjs/operators'; import { first, takeUntil } from 'rxjs/operators';
import { ContentActionRef } from '@alfresco/adf-extensions'; import { ContentActionRef } from '@alfresco/adf-extensions';
@Component({ @Component({
@ -99,6 +99,20 @@ export class DetailsComponent extends PageComponent implements OnInit, OnDestroy
.subscribe((aspectActions) => { .subscribe((aspectActions) => {
this.aspectActions = aspectActions; this.aspectActions = aspectActions;
}); });
this.infoDrawerOpened$
.pipe(
first((opened) => !opened),
takeUntil(
merge(
this.onDestroy$,
this.router.events.pipe(
first((event) => event instanceof NavigationStart),
takeUntil(this.onDestroy$)
)
)
)
)
.subscribe(() => this.goBack());
} }
setActiveTab(tabName: string) { setActiveTab(tabName: string) {

View File

@ -22,36 +22,38 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>. * from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { TestBed, fakeAsync, tick } from '@angular/core/testing'; import { fakeAsync, TestBed, tick } from '@angular/core/testing';
import { AppTestingModule } from '../../testing/app-testing.module'; import { AppTestingModule } from '../../testing/app-testing.module';
import { NodeEffects } from './node.effects'; import { NodeEffects } from './node.effects';
import { EffectsModule } from '@ngrx/effects'; import { EffectsModule } from '@ngrx/effects';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { ContentManagementService } from '../../services/content-management.service'; import { ContentManagementService } from '../../services/content-management.service';
import { import {
SharedStoreModule,
ShareNodeAction,
SetSelectedNodesAction,
UnshareNodesAction,
PurgeDeletedNodesAction,
RestoreDeletedNodesAction,
DeleteNodesAction,
UndoDeleteNodesAction,
CreateFolderAction,
EditFolderAction,
CopyNodesAction, CopyNodesAction,
MoveNodesAction, CreateFolderAction,
UnlockWriteAction, DeleteNodesAction,
EditFolderAction,
ExpandInfoDrawerAction,
FullscreenViewerAction, FullscreenViewerAction,
PrintFileAction,
SetCurrentFolderAction,
ManageAspectsAction, ManageAspectsAction,
ManagePermissionsAction, ManagePermissionsAction,
ShowLoaderAction MoveNodesAction,
PrintFileAction,
PurgeDeletedNodesAction,
RestoreDeletedNodesAction,
SetCurrentFolderAction,
SetInfoDrawerStateAction,
SetSelectedNodesAction,
SharedStoreModule,
ShareNodeAction,
ShowLoaderAction,
UndoDeleteNodesAction,
UnlockWriteAction,
UnshareNodesAction
} from '@alfresco/aca-shared/store'; } from '@alfresco/aca-shared/store';
import { RenditionService } from '@alfresco/adf-content-services'; import { RenditionService } from '@alfresco/adf-content-services';
import { ViewerEffects } from './viewer.effects'; import { ViewerEffects } from './viewer.effects';
import { Router } from '@angular/router'; import { NavigationEnd, Router } from '@angular/router';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { MatDialogModule } from '@angular/material/dialog'; import { MatDialogModule } from '@angular/material/dialog';
import { MatSnackBarModule } from '@angular/material/snack-bar'; import { MatSnackBarModule } from '@angular/material/snack-bar';
@ -403,6 +405,21 @@ describe('NodeEffects', () => {
expect(router.navigate).not.toHaveBeenCalled(); expect(router.navigate).not.toHaveBeenCalled();
}); });
it('should call dispatch on store with SetInfoDrawerStateAction when NavigationEnd event occurs', () => {
spyOn(store, 'dispatch').and.callThrough();
Object.defineProperty(router, 'events', {
value: of(new NavigationEnd(1, '', ''))
});
store.dispatch(new ManagePermissionsAction(null));
expect(store.dispatch).toHaveBeenCalledWith(jasmine.any(SetInfoDrawerStateAction));
expect(store.dispatch).toHaveBeenCalledWith(
jasmine.objectContaining({
payload: true
})
);
});
}); });
describe('printFile$', () => { describe('printFile$', () => {
@ -507,4 +524,21 @@ describe('NodeEffects', () => {
expect(contentService.manageAspects).toHaveBeenCalledWith({ entry: { isFile: false, id: 'folder-node-id' } }, undefined); expect(contentService.manageAspects).toHaveBeenCalledWith({ entry: { isFile: false, id: 'folder-node-id' } }, undefined);
})); }));
}); });
describe('expandInfoDrawer$', () => {
it('should call dispatch on store with SetInfoDrawerStateAction when NavigationEnd event occurs', () => {
spyOn(store, 'dispatch').and.callThrough();
Object.defineProperty(router, 'events', {
value: of(new NavigationEnd(1, '', ''))
});
store.dispatch(new ExpandInfoDrawerAction(undefined));
expect(store.dispatch).toHaveBeenCalledWith(jasmine.any(SetInfoDrawerStateAction));
expect(store.dispatch).toHaveBeenCalledWith(
jasmine.objectContaining({
payload: true
})
);
});
});
}); });

View File

@ -24,7 +24,7 @@
import { Actions, ofType, createEffect } from '@ngrx/effects'; import { Actions, ofType, createEffect } from '@ngrx/effects';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { map, take } from 'rxjs/operators'; import { first, map, take } from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { import {
AppStore, AppStore,
@ -50,12 +50,12 @@ import {
ExpandInfoDrawerAction, ExpandInfoDrawerAction,
ManageRulesAction, ManageRulesAction,
ShowLoaderAction, ShowLoaderAction,
ToggleInfoDrawerAction, SetInfoDrawerStateAction,
NavigateUrlAction NavigateUrlAction
} from '@alfresco/aca-shared/store'; } from '@alfresco/aca-shared/store';
import { ContentManagementService } from '../../services/content-management.service'; import { ContentManagementService } from '../../services/content-management.service';
import { RenditionService } from '@alfresco/adf-content-services'; import { RenditionService } from '@alfresco/adf-content-services';
import { Router } from '@angular/router'; import { NavigationEnd, Router } from '@angular/router';
@Injectable() @Injectable()
export class NodeEffects { export class NodeEffects {
@ -284,6 +284,9 @@ export class NodeEffects {
this.actions$.pipe( this.actions$.pipe(
ofType<ManagePermissionsAction>(NodeActionTypes.ManagePermissions), ofType<ManagePermissionsAction>(NodeActionTypes.ManagePermissions),
map((action) => { map((action) => {
this.router.events
.pipe(first((event) => event instanceof NavigationEnd))
.subscribe(() => this.store.dispatch(new SetInfoDrawerStateAction(true)));
if (action?.payload) { if (action?.payload) {
const route = 'personal-files/details'; const route = 'personal-files/details';
this.store.dispatch(new NavigateUrlAction([route, action.payload.entry.id, 'permissions'].join('/'))); this.store.dispatch(new NavigateUrlAction([route, action.payload.entry.id, 'permissions'].join('/')));
@ -308,6 +311,9 @@ export class NodeEffects {
this.actions$.pipe( this.actions$.pipe(
ofType<ExpandInfoDrawerAction>(NodeActionTypes.ExpandInfoDrawer), ofType<ExpandInfoDrawerAction>(NodeActionTypes.ExpandInfoDrawer),
map((action) => { map((action) => {
this.router.events
.pipe(first((event) => event instanceof NavigationEnd))
.subscribe(() => this.store.dispatch(new SetInfoDrawerStateAction(true)));
if (action?.payload) { if (action?.payload) {
const route = 'personal-files/details'; const route = 'personal-files/details';
this.router.navigate([route, action.payload.entry.id], { this.router.navigate([route, action.payload.entry.id], {
@ -330,7 +336,6 @@ export class NodeEffects {
} }
}); });
} }
this.store.dispatch(new ToggleInfoDrawerAction());
}) })
), ),
{ dispatch: false } { dispatch: false }