diff --git a/projects/aca-shared/src/lib/components/info-drawer/info-drawer.component.spec.ts b/projects/aca-shared/src/lib/components/info-drawer/info-drawer.component.spec.ts index c7f7bb36f..374ae5c1e 100644 --- a/projects/aca-shared/src/lib/components/info-drawer/info-drawer.component.spec.ts +++ b/projects/aca-shared/src/lib/components/info-drawer/info-drawer.component.spec.ts @@ -22,6 +22,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ + import { ContentActionRef, SidebarTabRef } from '@alfresco/adf-extensions'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; @@ -47,15 +48,14 @@ describe('InfoDrawerComponent', () => { }; const extensionServiceMock = { getSidebarTabs: () => {}, - getAllowedSidebarActions: () => - of([ - { - id: 'app.sidebar.close', - order: 100, - title: 'close', - icon: 'highlight_off' - } - ]) + getAllowedSidebarActions: () => [ + { + id: 'app.sidebar.close', + order: 100, + title: 'close', + icon: 'highlight_off' + } + ] }; beforeEach(() => { diff --git a/projects/aca-shared/src/lib/components/info-drawer/info-drawer.component.ts b/projects/aca-shared/src/lib/components/info-drawer/info-drawer.component.ts index 6d3d13c69..dd81e81ea 100644 --- a/projects/aca-shared/src/lib/components/info-drawer/info-drawer.component.ts +++ b/projects/aca-shared/src/lib/components/info-drawer/info-drawer.component.ts @@ -27,7 +27,7 @@ import { Component, HostListener, Input, OnChanges, OnDestroy, OnInit } from '@a import { MinimalNodeEntity, MinimalNodeEntryEntity, SiteEntry } from '@alfresco/js-api'; import { ContentActionRef, SidebarTabRef } from '@alfresco/adf-extensions'; import { Store } from '@ngrx/store'; -import { SetInfoDrawerStateAction, ToggleInfoDrawerAction, infoDrawerPreview } from '@alfresco/aca-shared/store'; +import { getAppSelection, SetInfoDrawerStateAction, ToggleInfoDrawerAction, infoDrawerPreview } from '@alfresco/aca-shared/store'; import { AppExtensionService } from '../../services/app.extension.service'; import { ContentApiService } from '../../services/content-api.service'; import { takeUntil } from 'rxjs/operators'; @@ -60,11 +60,11 @@ export class InfoDrawerComponent implements OnChanges, OnInit, OnDestroy { ngOnInit() { this.tabs = this.extensions.getSidebarTabs(); - this.extensions - .getAllowedSidebarActions() + this.store + .select(getAppSelection) .pipe(takeUntil(this.onDestroy$)) - .subscribe((actions) => { - this.actions = actions; + .subscribe(() => { + this.actions = this.extensions.getAllowedSidebarActions(); }); this.store diff --git a/projects/aca-shared/src/lib/components/tool-bar/toolbar-button/toolbar-button.component.html b/projects/aca-shared/src/lib/components/tool-bar/toolbar-button/toolbar-button.component.html index a39c6ebd7..8bb294ef9 100644 --- a/projects/aca-shared/src/lib/components/tool-bar/toolbar-button/toolbar-button.component.html +++ b/projects/aca-shared/src/lib/components/tool-bar/toolbar-button/toolbar-button.component.html @@ -6,7 +6,6 @@ [color]="color" [attr.aria-label]="actionRef.description || actionRef.title | translate" [attr.title]="actionRef.description || actionRef.title | translate" - [disabled]="actionRef.disabled" (click)="runAction()" > diff --git a/projects/aca-shared/src/lib/components/tool-bar/toolbar-menu/toolbar-menu.component.html b/projects/aca-shared/src/lib/components/tool-bar/toolbar-menu/toolbar-menu.component.html index b496dae3c..c498390cd 100644 --- a/projects/aca-shared/src/lib/components/tool-bar/toolbar-menu/toolbar-menu.component.html +++ b/projects/aca-shared/src/lib/components/tool-bar/toolbar-menu/toolbar-menu.component.html @@ -5,7 +5,6 @@ [attr.aria-label]="actionRef.description || actionRef.title | translate" [attr.title]="actionRef.description || actionRef.title | translate" [matMenuTriggerFor]="menu" - [disabled]="actionRef.disabled" #matTrigger="matMenuTrigger" > diff --git a/projects/aca-shared/src/lib/services/app.extension.service.spec.ts b/projects/aca-shared/src/lib/services/app.extension.service.spec.ts index af407a265..bb8c4338b 100644 --- a/projects/aca-shared/src/lib/services/app.extension.service.spec.ts +++ b/projects/aca-shared/src/lib/services/app.extension.service.spec.ts @@ -60,17 +60,9 @@ describe('AppExtensionService', () => { extensions = TestBed.inject(ExtensionService); }); - const applyConfig = (config: ExtensionConfig, selection?: boolean) => { + const applyConfig = (config: ExtensionConfig) => { extensions.setup(config); service.setup(config); - if (selection) { - service.selection = { - isEmpty: false, - count: 1, - libraries: null, - nodes: null - }; - } }; describe('configs', () => { @@ -292,7 +284,7 @@ describe('AppExtensionService', () => { }); describe('content actions', () => { - it('should load content actions from the config', (done) => { + it('should load content actions from the config', () => { applyConfig({ $id: 'test', $name: 'test', @@ -305,26 +297,23 @@ describe('AppExtensionService', () => { { id: 'aca:toolbar/separator-1', order: 1, - type: ContentActionType.default, + type: ContentActionType.separator, title: 'action1' }, { id: 'aca:toolbar/separator-2', order: 2, - type: ContentActionType.default, + type: ContentActionType.separator, title: 'action2' } ] } }); - service.getAllowedToolbarActions().subscribe((actions) => { - expect(actions.length).toBe(2); - done(); - }); + expect(service.toolbarActions.length).toBe(2); }); - it('should sort content actions by order', (done) => { + it('should sort content actions by order', () => { applyConfig({ $id: 'test', $name: 'test', @@ -337,30 +326,27 @@ describe('AppExtensionService', () => { { id: 'aca:toolbar/separator-2', order: 2, - type: ContentActionType.default, + type: ContentActionType.separator, title: 'action2' }, { id: 'aca:toolbar/separator-1', order: 1, - type: ContentActionType.default, + type: ContentActionType.separator, title: 'action1' } ] } }); - service.getAllowedToolbarActions().subscribe((actions) => { - expect(actions.length).toBe(2); - expect(actions[0].id).toBe('aca:toolbar/separator-1'); - expect(actions[1].id).toBe('aca:toolbar/separator-2'); - done(); - }); + expect(service.toolbarActions.length).toBe(2); + expect(service.toolbarActions[0].id).toBe('aca:toolbar/separator-1'); + expect(service.toolbarActions[1].id).toBe('aca:toolbar/separator-2'); }); }); describe('open with', () => { - it('should load [open with] actions for the viewer', (done) => { + it('should load [open with] actions for the viewer', () => { applyConfig({ $id: 'test', $name: 'test', @@ -387,13 +373,10 @@ describe('AppExtensionService', () => { } }); - service.getOpenWithActions().subscribe((actions) => { - expect(actions.length).toBe(1); - done(); - }); + expect(service.openWithActions.length).toBe(1); }); - it('should load only enabled [open with] actions for the viewer', (done) => { + it('should load only enabled [open with] actions for the viewer', () => { applyConfig({ $id: 'test', $name: 'test', @@ -430,14 +413,11 @@ describe('AppExtensionService', () => { } }); - service.getOpenWithActions().subscribe((actions) => { - expect(actions.length).toBe(1); - expect(actions[0].id).toBe('aca:viewer/action2'); - done(); - }); + expect(service.openWithActions.length).toBe(1); + expect(service.openWithActions[0].id).toBe('aca:viewer/action2'); }); - it('should sort [open with] actions by order', (done) => { + it('should sort [open with] actions by order', () => { applyConfig({ $id: 'test', $name: 'test', @@ -473,17 +453,14 @@ describe('AppExtensionService', () => { } }); - service.getOpenWithActions().subscribe((actions) => { - expect(actions.length).toBe(2); - expect(actions[0].id).toBe('aca:viewer/action1'); - expect(actions[1].id).toBe('aca:viewer/action2'); - done(); - }); + expect(service.openWithActions.length).toBe(2); + expect(service.openWithActions[0].id).toBe('aca:viewer/action1'); + expect(service.openWithActions[1].id).toBe('aca:viewer/action2'); }); }); describe('create', () => { - it('should load [create] actions from config', (done) => { + it('should load [create] actions from config', () => { applyConfig({ $id: 'test', $name: 'test', @@ -504,13 +481,10 @@ describe('AppExtensionService', () => { } }); - service.getCreateActions().subscribe((actions) => { - expect(actions.length).toBe(1); - done(); - }); + expect(service.createActions.length).toBe(1); }); - it('should sort [create] actions by order', (done) => { + it('should sort [create] actions by order', () => { applyConfig({ $id: 'test', $name: 'test', @@ -538,12 +512,9 @@ describe('AppExtensionService', () => { } }); - service.getCreateActions().subscribe((actions) => { - expect(actions.length).toBe(2); - expect(actions[0].id).toBe('aca:create/folder-2'); - expect(actions[1].id).toBe('aca:create/folder'); - done(); - }); + expect(service.createActions.length).toBe(2); + expect(service.createActions[0].id).toBe('aca:create/folder-2'); + expect(service.createActions[1].id).toBe('aca:create/folder'); }); }); @@ -729,7 +700,7 @@ describe('AppExtensionService', () => { }); describe('getSharedLinkViewerToolbarActions', () => { - it('should get shared link viewer actions', (done) => { + it('should get shared link viewer actions', () => { const actions = [ { id: 'id', @@ -753,29 +724,23 @@ describe('AppExtensionService', () => { } ]; - applyConfig( - { - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', - features: { - viewer: { - shared: { - toolbarActions: actions - } + applyConfig({ + $id: 'test', + $name: 'test', + $version: '1.0.0', + $license: 'MIT', + $vendor: 'Good company', + $runtime: '1.5.0', + features: { + viewer: { + shared: { + toolbarActions: actions } } - }, - true - ); - - service.getSharedLinkViewerToolbarActions().subscribe((sharedLinkViewerToolbarActions) => { - expect(sharedLinkViewerToolbarActions).toEqual(expectedActions); - done(); + } }); + + expect(service.getSharedLinkViewerToolbarActions()).toEqual(expectedActions); }); }); @@ -828,7 +793,7 @@ describe('AppExtensionService', () => { }); describe('getHeaderActions', () => { - it('should load user actions from the config', (done) => { + it('should load user actions from the config', () => { applyConfig({ $id: 'test', $name: 'test', @@ -841,24 +806,21 @@ describe('AppExtensionService', () => { { id: 'header.action.separator.1', order: 1, - type: ContentActionType.default + type: ContentActionType.separator }, { id: 'header.action.separator.2', order: 2, - type: ContentActionType.default + type: ContentActionType.separator } ] } }); - service.getHeaderActions().subscribe((headerActions) => { - expect(headerActions.length).toBe(2); - done(); - }); + expect(service.headerActions.length).toBe(2); }); - it('should sort header actions by order', (done) => { + it('should sort header actions by order', () => { applyConfig({ $id: 'test', $name: 'test', @@ -882,15 +844,12 @@ describe('AppExtensionService', () => { } }); - service.getHeaderActions().subscribe((headerActions) => { - expect(headerActions.length).toBe(2); - expect(headerActions[0].id).toBe('header.action.2'); - expect(headerActions[1].id).toBe('header.action.1'); - done(); - }); + const actions = service.getHeaderActions(); + expect(actions[0].id).toBe('header.action.2'); + expect(actions[1].id).toBe('header.action.1'); }); - it('should sort header menu children actions by order', (done) => { + it('should sort header menu children actions by order', () => { applyConfig({ $id: 'test', $name: 'test', @@ -921,12 +880,9 @@ describe('AppExtensionService', () => { } }); - service.getHeaderActions().subscribe((headerActions) => { - expect(headerActions.length).toBe(1); - expect(headerActions[0].children[0].id).toBe('header.action.2'); - expect(headerActions[0].children[1].id).toBe('header.action.1'); - done(); - }); + const actions = service.getHeaderActions()[0]; + expect(actions.children[0].id).toBe('header.action.2'); + expect(actions.children[1].id).toBe('header.action.1'); }); }); @@ -1094,7 +1050,7 @@ describe('AppExtensionService', () => { } ]; - it('should set the action disabled for create actions', (done) => { + it('should set the action disabled for create actions', () => { applyConfig({ $id: 'test', $name: 'test', @@ -1107,13 +1063,10 @@ describe('AppExtensionService', () => { } }); - service.getCreateActions().subscribe((createActions) => { - expect(createActions).toEqual(expectedActionsWithChildren); - done(); - }); + expect(service.getCreateActions()).toEqual(expectedActionsWithChildren); }); - it('should set the action disabled for sidebar actions', (done) => { + it('should set the action disabled for sidebar actions', () => { applyConfig({ $id: 'test', $name: 'test', @@ -1128,13 +1081,10 @@ describe('AppExtensionService', () => { } }); - service.getAllowedSidebarActions().subscribe((serviceActions) => { - expect(serviceActions).toEqual(expectedActionsWithoutChildren); - done(); - }); + expect(service.getAllowedSidebarActions()).toEqual(expectedActionsWithoutChildren); }); - it('should set the action disabled for toolbar actions', (done) => { + it('should set the action disabled for toolbar actions', () => { applyConfig({ $id: 'test', $name: 'test', @@ -1147,13 +1097,10 @@ describe('AppExtensionService', () => { } }); - service.getAllowedToolbarActions().subscribe((serviceActions) => { - expect(serviceActions).toEqual(expectedActionsWithoutChildren); - done(); - }); + expect(service.getAllowedToolbarActions()).toEqual(expectedActionsWithoutChildren); }); - it('should set the action disabled for viewer toolbar actions', (done) => { + it('should set the action disabled for viewer toolbar actions', () => { applyConfig({ $id: 'test', $name: 'test', @@ -1166,39 +1113,30 @@ describe('AppExtensionService', () => { } }); - service.getViewerToolbarActions().subscribe((serviceActions) => { - expect(serviceActions).toEqual(expectedActionsWithoutChildren); - done(); - }); + expect(service.getViewerToolbarActions()).toEqual(expectedActionsWithoutChildren); }); - it('should set the action disabled for shared link viewer toolbar actions', (done) => { - applyConfig( - { - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', - features: { - viewer: { - shared: { - toolbarActions: actions - } + it('should set the action disabled for shared link viewer toolbar actions', () => { + applyConfig({ + $id: 'test', + $name: 'test', + $version: '1.0.0', + $license: 'MIT', + $vendor: 'Good company', + $runtime: '1.5.0', + features: { + viewer: { + shared: { + toolbarActions: actions } } - }, - true - ); - - service.getSharedLinkViewerToolbarActions().subscribe((serviceActions) => { - expect(serviceActions).toEqual(expectedActionsWithoutChildren); - done(); + } }); + + expect(service.getSharedLinkViewerToolbarActions()).toEqual(expectedActionsWithoutChildren); }); - it('should set the action disabled for header actions', (done) => { + it('should set the action disabled for header actions', () => { applyConfig({ $id: 'test', $name: 'test', @@ -1211,32 +1149,23 @@ describe('AppExtensionService', () => { } }); - service.getHeaderActions().subscribe((serviceActions) => { - expect(serviceActions).toEqual(expectedActionsWithoutChildren); - done(); - }); + expect(service.getHeaderActions()).toEqual(expectedActionsWithoutChildren); }); - it('should set the action disabled for context menu actions', (done) => { - applyConfig( - { - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', - features: { - contextMenu: actions - } - }, - true - ); - - service.getAllowedContextMenuActions().subscribe((serviceActions) => { - expect(serviceActions).toEqual(expectedActionsWithoutChildren); - done(); + it('should set the action disabled for context menu actions', () => { + applyConfig({ + $id: 'test', + $name: 'test', + $version: '1.0.0', + $license: 'MIT', + $vendor: 'Good company', + $runtime: '1.5.0', + features: { + contextMenu: actions + } }); + + expect(service.getAllowedContextMenuActions()).toEqual(expectedActionsWithoutChildren); }); }); }); diff --git a/projects/aca-shared/src/lib/services/app.extension.service.ts b/projects/aca-shared/src/lib/services/app.extension.service.ts index a0fcdf2a8..dabcb13f9 100644 --- a/projects/aca-shared/src/lib/services/app.extension.service.ts +++ b/projects/aca-shared/src/lib/services/app.extension.service.ts @@ -56,7 +56,6 @@ import { RepositoryInfo, NodeEntry } from '@alfresco/js-api'; import { ViewerRules } from '../models/viewer.rules'; import { SettingsGroupRef } from '../models/types'; import { NodePermissionService } from '../services/node-permission.service'; -import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' @@ -64,22 +63,21 @@ import { map } from 'rxjs/operators'; export class AppExtensionService implements RuleContext { private _references = new BehaviorSubject([]); + headerActions: Array = []; + toolbarActions: Array = []; + viewerToolbarActions: Array = []; + sharedLinkViewerToolbarActions: Array = []; + contextMenuActions: Array = []; + openWithActions: Array = []; + createActions: Array = []; navbar: Array = []; sidebarTabs: Array = []; + sidebarActions: Array = []; contentMetadata: any; search: any; viewerRules: ViewerRules = {}; settingGroups: Array = []; - private _headerActions = new BehaviorSubject>([]); - private _toolbarActions = new BehaviorSubject>([]); - private _viewerToolbarActions = new BehaviorSubject>([]); - private _sharedLinkViewerToolbarActions = new BehaviorSubject>([]); - private _contextMenuActions = new BehaviorSubject>([]); - private _openWithActions = new BehaviorSubject>([]); - private _createActions = new BehaviorSubject>([]); - private _sidebarActions = new BehaviorSubject>([]); - documentListPresets: { files: Array; libraries: Array; @@ -108,8 +106,6 @@ export class AppExtensionService implements RuleContext { references$: Observable; - config: ExtensionConfig; - constructor( public auth: AuthenticationService, protected store: Store, @@ -128,16 +124,12 @@ export class AppExtensionService implements RuleContext { this.navigation = result.navigation; this.profile = result.profile; this.repository = result.repository; - - if (this.config) { - this.setup(this.config); - } }); } async load() { - this.config = await this.extensions.load(); - this.setup(this.config); + const config = await this.extensions.load(); + this.setup(config); } setup(config: ExtensionConfig) { @@ -148,15 +140,15 @@ export class AppExtensionService implements RuleContext { this.settingGroups = this.loader.getElements(config, 'settings'); - this._headerActions.next(this.loader.getContentActions(config, 'features.header')); - this._sidebarActions.next(this.loader.getContentActions(config, 'features.sidebar.toolbar')); - this._toolbarActions.next(this.loader.getContentActions(config, 'features.toolbar')); - this._viewerToolbarActions.next(this.loader.getContentActions(config, 'features.viewer.toolbarActions')); - this._sharedLinkViewerToolbarActions.next(this.loader.getContentActions(config, 'features.viewer.shared.toolbarActions')); - this._contextMenuActions.next(this.loader.getContentActions(config, 'features.contextMenu')); - this._openWithActions.next(this.loader.getContentActions(config, 'features.viewer.openWith')); - this._createActions.next(this.loader.getElements(config, 'features.create')); + this.headerActions = this.loader.getContentActions(config, 'features.header'); + this.sidebarActions = this.loader.getContentActions(config, 'features.sidebar.toolbar'); + this.toolbarActions = this.loader.getContentActions(config, 'features.toolbar'); + this.viewerToolbarActions = this.loader.getContentActions(config, 'features.viewer.toolbarActions'); + this.sharedLinkViewerToolbarActions = this.loader.getContentActions(config, 'features.viewer.shared.toolbarActions'); + this.contextMenuActions = this.loader.getContentActions(config, 'features.contextMenu'); + this.openWithActions = this.loader.getContentActions(config, 'features.viewer.openWith'); + this.createActions = this.loader.getElements(config, 'features.create'); this.navbar = this.loadNavBar(config); this.sidebarTabs = this.loader.getElements(config, 'features.sidebar.tabs'); this.contentMetadata = this.loadContentMetadata(config); @@ -352,16 +344,12 @@ export class AppExtensionService implements RuleContext { }; } - getCreateActions(): Observable> { - return this._createActions.pipe( - map((createActions) => - createActions - .filter((action) => this.filterVisible(action)) - .map((action) => this.copyAction(action)) - .map((action) => this.buildMenu(action)) - .map((action) => this.setActionDisabledFromRule(action)) - ) - ); + getCreateActions(): Array { + return this.createActions + .filter((action) => this.filterVisible(action)) + .map((action) => this.copyAction(action)) + .map((action) => this.buildMenu(action)) + .map((action) => this.setActionDisabledFromRule(action)); } private buildMenu(actionRef: ContentActionRef): ContentActionRef { @@ -400,58 +388,48 @@ export class AppExtensionService implements RuleContext { .reduce(reduceSeparators, []); } - getAllowedSidebarActions(): Observable> { - return this._sidebarActions.pipe(map((sidebarActions) => this.getAllowedActions(sidebarActions))); + getAllowedSidebarActions(): Array { + return this.getAllowedActions(this.sidebarActions); } - getAllowedToolbarActions(): Observable> { - return this._toolbarActions.pipe(map((toolbarActions) => this.getAllowedActions(toolbarActions))); + getAllowedToolbarActions(): Array { + return this.getAllowedActions(this.toolbarActions); } - getViewerToolbarActions(): Observable> { - return this._viewerToolbarActions.pipe(map((viewerToolbarActions) => this.getAllowedActions(viewerToolbarActions))); + getViewerToolbarActions(): Array { + return this.getAllowedActions(this.viewerToolbarActions); } - getOpenWithActions(): Observable> { - return this._openWithActions.pipe(map((openWithActions) => this.getAllowedActions(openWithActions))); + getSharedLinkViewerToolbarActions(): Array { + return this.getAllowedActions(this.sharedLinkViewerToolbarActions); } - getSharedLinkViewerToolbarActions(): Observable> { - return this._sharedLinkViewerToolbarActions.pipe( - map((sharedLinkViewerToolbarActions) => (!this.selection.isEmpty ? this.getAllowedActions(sharedLinkViewerToolbarActions) : [])) - ); + getHeaderActions(): Array { + return this.headerActions + .filter((action) => this.filterVisible(action)) + .map((action) => { + if (action.type === ContentActionType.menu) { + const copy = this.copyAction(action); + if (copy.children && copy.children.length > 0) { + copy.children = copy.children + .filter((childAction) => this.filterVisible(childAction)) + .sort(sortByOrder) + .reduce(reduceEmptyMenus, []) + .reduce(reduceSeparators, []); + } + return copy; + } + + return action; + }) + .map((action) => this.setActionDisabledFromRule(action)) + .sort(sortByOrder) + .reduce(reduceEmptyMenus, []) + .reduce(reduceSeparators, []); } - getHeaderActions(): Observable> { - return this._headerActions.pipe( - map((headerActions) => - headerActions - .filter((action) => this.filterVisible(action)) - .map((action) => { - if (action.type === ContentActionType.menu) { - const copy = this.copyAction(action); - if (copy.children && copy.children.length > 0) { - copy.children = copy.children - .filter((childAction) => this.filterVisible(childAction)) - .sort(sortByOrder) - .reduce(reduceEmptyMenus, []) - .reduce(reduceSeparators, []); - } - return copy; - } - - return action; - }) - .map((action) => this.setActionDisabledFromRule(action)) - .sort(sortByOrder) - .reduce(reduceEmptyMenus, []) - .reduce(reduceSeparators, []) - ) - ); - } - - getAllowedContextMenuActions(): Observable> { - return this._contextMenuActions.pipe(map((contextMenuActions) => (!this.selection.isEmpty ? this.getAllowedActions(contextMenuActions) : []))); + getAllowedContextMenuActions(): Array { + return this.getAllowedActions(this.contextMenuActions); } getSettingsGroups(): Array { diff --git a/src/app/components/context-menu/context-menu.component.spec.ts b/src/app/components/context-menu/context-menu.component.spec.ts index 1102f28ac..72f6181e8 100644 --- a/src/app/components/context-menu/context-menu.component.spec.ts +++ b/src/app/components/context-menu/context-menu.component.spec.ts @@ -23,7 +23,7 @@ * along with Alfresco. If not, see . */ -import { TestBed, ComponentFixture } from '@angular/core/testing'; +import { TestBed, ComponentFixture, fakeAsync, tick } from '@angular/core/testing'; import { AppTestingModule } from '../../testing/app-testing.module'; import { ContextMenuComponent } from './context-menu.component'; import { ContextMenuModule } from './context-menu.module'; @@ -75,7 +75,7 @@ describe('ContextMenuComponent', () => { contextMenuOverlayRef = TestBed.inject(ContextMenuOverlayRef); extensionsService = TestBed.inject(AppExtensionService); - spyOn(extensionsService, 'getAllowedContextMenuActions').and.returnValue(of([contextItem])); + spyOn(extensionsService, 'getAllowedContextMenuActions').and.returnValue([contextItem]); fixture.detectChanges(); }); @@ -85,16 +85,15 @@ describe('ContextMenuComponent', () => { expect(contextMenuOverlayRef.close).toHaveBeenCalled(); }); - it('should render defined context menu actions items', async () => { + it('should render defined context menu actions items', fakeAsync(() => { component.ngAfterViewInit(); - fixture.detectChanges(); - await fixture.whenStable(); + tick(500); const contextMenuElements = document.body.querySelector('.aca-context-menu').querySelectorAll('button'); expect(contextMenuElements.length).toBe(1); expect(contextMenuElements[0].querySelector('span').innerText).toBe(contextItem.title); - }); + })); it('should run action with provided action id', () => { spyOn(extensionsService, 'runActionById'); diff --git a/src/app/components/context-menu/context-menu.component.ts b/src/app/components/context-menu/context-menu.component.ts index 38a33a6b9..d31402259 100644 --- a/src/app/components/context-menu/context-menu.component.ts +++ b/src/app/components/context-menu/context-menu.component.ts @@ -25,6 +25,8 @@ import { Component, ViewEncapsulation, OnInit, OnDestroy, HostListener, ViewChild, AfterViewInit, Inject } from '@angular/core'; import { MatMenuTrigger } from '@angular/material/menu'; +import { AppStore, getAppSelection } from '@alfresco/aca-shared/store'; +import { Store } from '@ngrx/store'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { ContentActionRef } from '@alfresco/adf-extensions'; @@ -60,6 +62,7 @@ export class ContextMenuComponent implements OnInit, OnDestroy, AfterViewInit { constructor( private contextMenuOverlayRef: ContextMenuOverlayRef, private extensions: AppExtensionService, + private store: Store, @Inject(CONTEXT_MENU_DIRECTION) public direction: Direction ) {} @@ -79,10 +82,14 @@ export class ContextMenuComponent implements OnInit, OnDestroy, AfterViewInit { } ngOnInit() { - this.extensions - .getAllowedContextMenuActions() + this.store + .select(getAppSelection) .pipe(takeUntil(this.onDestroy$)) - .subscribe((actions) => (this.actions = actions)); + .subscribe((selection) => { + if (selection.count) { + this.actions = this.extensions.getAllowedContextMenuActions(); + } + }); } ngAfterViewInit() { diff --git a/src/app/components/create-menu/create-menu.component.spec.ts b/src/app/components/create-menu/create-menu.component.spec.ts index f866b92f4..88b6fc52d 100644 --- a/src/app/components/create-menu/create-menu.component.spec.ts +++ b/src/app/components/create-menu/create-menu.component.spec.ts @@ -34,7 +34,6 @@ import { By } from '@angular/platform-browser'; import { AppTestingModule } from '../../testing/app-testing.module'; import { MatMenuModule } from '@angular/material/menu'; import { MatButtonModule } from '@angular/material/button'; -import { of } from 'rxjs'; describe('CreateMenuComponent', () => { let fixture: ComponentFixture; @@ -48,15 +47,13 @@ describe('CreateMenuComponent', () => { extensionService = TestBed.inject(AppExtensionService); getCreateActionsSpy = spyOn(extensionService, 'getCreateActions'); - getCreateActionsSpy.and.returnValue( - of([ - { - id: 'action1', - type: ContentActionType.button, - title: 'action one' - } - ]) - ); + getCreateActionsSpy.and.returnValue([ + { + id: 'action1', + type: ContentActionType.button, + title: 'action one' + } + ]); fixture = TestBed.createComponent(CreateMenuComponent); }); @@ -105,22 +102,20 @@ describe('CreateMenuComponent', () => { }); it('should render sub-menus', async () => { - getCreateActionsSpy.and.returnValue( - of([ - { - id: 'level1', - type: ContentActionType.menu, - title: 'level one', - children: [ - { - id: 'level2', - type: ContentActionType.button, - title: 'level two' - } - ] - } - ]) - ); + getCreateActionsSpy.and.returnValue([ + { + id: 'level1', + type: ContentActionType.menu, + title: 'level one', + children: [ + { + id: 'level2', + type: ContentActionType.button, + title: 'level two' + } + ] + } + ]); await clickMenu(); diff --git a/src/app/components/create-menu/create-menu.component.ts b/src/app/components/create-menu/create-menu.component.ts index 3ece99851..1e8e0c6ed 100644 --- a/src/app/components/create-menu/create-menu.component.ts +++ b/src/app/components/create-menu/create-menu.component.ts @@ -25,6 +25,8 @@ import { Component, Input, OnInit, OnDestroy, ViewEncapsulation } from '@angular/core'; import { ContentActionRef } from '@alfresco/adf-extensions'; +import { AppStore, getRuleContext } from '@alfresco/aca-shared/store'; +import { Store } from '@ngrx/store'; import { takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; import { AppExtensionService } from '@alfresco/aca-shared'; @@ -46,14 +48,14 @@ export class CreateMenuComponent implements OnInit, OnDestroy { @Input() expanded: boolean; - constructor(private extensions: AppExtensionService) {} + constructor(private store: Store, private extensions: AppExtensionService) {} ngOnInit() { - this.extensions - .getCreateActions() + this.store + .select(getRuleContext) .pipe(takeUntil(this.onDestroy$)) - .subscribe((createActions) => { - this.createActions = createActions; + .subscribe(() => { + this.createActions = this.extensions.getCreateActions(); }); } diff --git a/src/app/components/header/header.component.spec.ts b/src/app/components/header/header.component.spec.ts index d16723ca2..c9723a84c 100644 --- a/src/app/components/header/header.component.spec.ts +++ b/src/app/components/header/header.component.spec.ts @@ -26,17 +26,11 @@ import { AppHeaderComponent } from './header.component'; import { AppState } from '@alfresco/aca-shared/store'; import { of } from 'rxjs'; -import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; +import { fakeAsync } from '@angular/core/testing'; import { ContentActionRef } from '@alfresco/adf-extensions'; -import { Store } from '@ngrx/store'; -import { AppTestingModule } from '../../testing/app-testing.module'; -import { AppExtensionService } from '../../../../projects/aca-shared/src/lib/services/app.extension.service'; -import { CoreModule } from '@alfresco/adf-core'; -import { AppSearchInputModule } from '../search/search-input.module'; describe('AppHeaderComponent', () => { let component: AppHeaderComponent; - let fixture: ComponentFixture; const actions = [ { id: 'action-1', type: 'button' }, @@ -44,12 +38,11 @@ describe('AppHeaderComponent', () => { ] as Array; const store = { - select: jasmine.createSpy('select'), - dispatch: () => {} + select: jasmine.createSpy('select') } as any; const appExtensionService = { - getHeaderActions: () => of(actions) + getHeaderActions: () => actions } as any; const app = { @@ -59,27 +52,11 @@ describe('AppHeaderComponent', () => { } as AppState; beforeEach(() => { - TestBed.configureTestingModule({ - imports: [AppTestingModule, CoreModule.forChild(), AppSearchInputModule], - declarations: [AppHeaderComponent], - providers: [ - { - provide: AppExtensionService, - useValue: appExtensionService - }, - { - provide: Store, - useValue: store - } - ] - }); - store.select.and.callFake((memoizeFn) => { return of(memoizeFn({ app })); }); - fixture = TestBed.createComponent(AppHeaderComponent); - component = fixture.componentInstance; + component = new AppHeaderComponent(store, appExtensionService); }); it('should set header color, name and logo', fakeAsync(() => { @@ -88,9 +65,8 @@ describe('AppHeaderComponent', () => { component.headerColor$.subscribe((val) => expect(val).toBe(app.headerColor)); })); - it('should get header actions', fakeAsync(() => { + it('should get header actions', () => { component.ngOnInit(); - tick(); expect(component.actions).toEqual(actions); - })); + }); }); diff --git a/src/app/components/header/header.component.ts b/src/app/components/header/header.component.ts index 492a14843..67bf15c9a 100644 --- a/src/app/components/header/header.component.ts +++ b/src/app/components/header/header.component.ts @@ -23,13 +23,12 @@ * along with Alfresco. If not, see . */ -import { Component, ViewEncapsulation, Output, EventEmitter, OnInit, Input, OnDestroy } from '@angular/core'; +import { Component, ViewEncapsulation, Output, EventEmitter, OnInit, Input } from '@angular/core'; import { Store } from '@ngrx/store'; -import { Observable, Subject } from 'rxjs'; +import { Observable } from 'rxjs'; import { ContentActionRef } from '@alfresco/adf-extensions'; import { AppStore, getHeaderColor, getAppName, getLogoPath, getHeaderImagePath } from '@alfresco/aca-shared/store'; import { AppExtensionService } from '@alfresco/aca-shared'; -import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-header', @@ -38,8 +37,7 @@ import { takeUntil } from 'rxjs/operators'; encapsulation: ViewEncapsulation.None, host: { class: 'app-header' } }) -export class AppHeaderComponent implements OnInit, OnDestroy { - private onDestroy$: Subject = new Subject(); +export class AppHeaderComponent implements OnInit { @Output() toggleClicked = new EventEmitter(); @@ -62,17 +60,7 @@ export class AppHeaderComponent implements OnInit, OnDestroy { } ngOnInit() { - this.appExtensions - .getHeaderActions() - .pipe(takeUntil(this.onDestroy$)) - .subscribe((actions) => { - this.actions = actions; - }); - } - - ngOnDestroy() { - this.onDestroy$.next(true); - this.onDestroy$.complete(); + this.actions = this.appExtensions.getHeaderActions(); } trackByActionId(_: number, action: ContentActionRef) { diff --git a/src/app/components/page.component.ts b/src/app/components/page.component.ts index 0e6ff2f03..9efd2b754 100644 --- a/src/app/components/page.component.ts +++ b/src/app/components/page.component.ts @@ -87,23 +87,11 @@ export abstract class PageComponent implements OnInit, OnDestroy, OnChanges { .pipe(takeUntil(this.onDestroy$)) .subscribe((selection) => { this.selection = selection; + this.actions = this.extensions.getAllowedToolbarActions(); + this.viewerToolbarActions = this.extensions.getViewerToolbarActions(); this.canUpdateNode = this.selection.count === 1 && this.content.canUpdateNode(selection.first); }); - this.extensions - .getAllowedToolbarActions() - .pipe(takeUntil(this.onDestroy$)) - .subscribe((actions) => { - this.actions = actions; - }); - - this.extensions - .getViewerToolbarActions() - .pipe(takeUntil(this.onDestroy$)) - .subscribe((actions) => { - this.viewerToolbarActions = actions; - }); - this.store .select(getCurrentFolder) .pipe(takeUntil(this.onDestroy$)) diff --git a/src/app/components/preview/preview.component.ts b/src/app/components/preview/preview.component.ts index 62102860f..a5e7c5fb3 100644 --- a/src/app/components/preview/preview.component.ts +++ b/src/app/components/preview/preview.component.ts @@ -153,12 +153,7 @@ export class PreviewComponent extends PageComponent implements OnInit, OnDestroy .subscribe(() => {}) ]); - this.extensions - .getOpenWithActions() - .pipe(takeUntil(this.onDestroy$)) - .subscribe((actions) => { - this.openWith = actions; - }); + this.openWith = this.extensions.openWithActions; } ngOnDestroy() { diff --git a/src/app/components/shared-link-view/shared-link-view.component.spec.ts b/src/app/components/shared-link-view/shared-link-view.component.spec.ts index a87c40f1e..0bb18dcb4 100644 --- a/src/app/components/shared-link-view/shared-link-view.component.spec.ts +++ b/src/app/components/shared-link-view/shared-link-view.component.spec.ts @@ -64,12 +64,6 @@ describe('SharedLinkViewComponent', () => { fixture = TestBed.createComponent(SharedLinkViewComponent); component = fixture.componentInstance; appExtensionService = TestBed.inject(AppExtensionService); - appExtensionService.selection = { - isEmpty: true, - count: 0, - libraries: null, - nodes: null - }; spyGetSharedLink = spyOn(component['sharedLinksApi'], 'getSharedLink'); @@ -99,6 +93,8 @@ describe('SharedLinkViewComponent', () => { })); it('should not update actions reference if selection is empty', fakeAsync(() => { + spyOn(storeMock, 'select').and.returnValue(of({ isEmpty: true })); + spyGetSharedLink.and.returnValue(Promise.resolve({ entry: { id: 'shared-id' } })); fixture.detectChanges(); @@ -108,13 +104,8 @@ describe('SharedLinkViewComponent', () => { })); it('should update actions reference if selection is not empty', fakeAsync(() => { - appExtensionService.selection = { - isEmpty: false, - count: 1, - libraries: null, - nodes: null - }; - spyOn(appExtensionService, 'getSharedLinkViewerToolbarActions').and.callThrough(); + spyOn(storeMock, 'select').and.returnValue(of({ isEmpty: false })); + spyOn(appExtensionService, 'getSharedLinkViewerToolbarActions'); spyGetSharedLink.and.returnValue(Promise.resolve({ entry: { id: 'shared-id' } })); fixture.detectChanges(); diff --git a/src/app/components/shared-link-view/shared-link-view.component.ts b/src/app/components/shared-link-view/shared-link-view.component.ts index 9dde3e92d..86677a585 100644 --- a/src/app/components/shared-link-view/shared-link-view.component.ts +++ b/src/app/components/shared-link-view/shared-link-view.component.ts @@ -23,15 +23,15 @@ * along with Alfresco. If not, see . */ -import { AppStore, SetSelectedNodesAction } from '@alfresco/aca-shared/store'; +import { AppStore, SetSelectedNodesAction, getAppSelection } from '@alfresco/aca-shared/store'; import { AlfrescoApiService } from '@alfresco/adf-core'; import { ContentActionRef } from '@alfresco/adf-extensions'; import { SharedLinkEntry, SharedlinksApi } from '@alfresco/js-api'; -import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { Component, OnInit, ViewEncapsulation } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Store } from '@ngrx/store'; -import { forkJoin, from, of, Subject } from 'rxjs'; -import { catchError, mergeMap, takeUntil } from 'rxjs/operators'; +import { forkJoin, from, of } from 'rxjs'; +import { catchError, mergeMap } from 'rxjs/operators'; import { AppExtensionService } from '@alfresco/aca-shared'; @Component({ @@ -41,8 +41,7 @@ import { AppExtensionService } from '@alfresco/aca-shared'; encapsulation: ViewEncapsulation.None, host: { class: 'app-shared-link-view' } }) -export class SharedLinkViewComponent implements OnInit, OnDestroy { - private onDestroy$: Subject = new Subject(); +export class SharedLinkViewComponent implements OnInit { private sharedLinksApi: SharedlinksApi; sharedLinkId: string = null; viewerToolbarActions: Array = []; @@ -70,17 +69,9 @@ export class SharedLinkViewComponent implements OnInit, OnDestroy { this.sharedLinkId = sharedId; }); - this.extensions - .getSharedLinkViewerToolbarActions() - .pipe(takeUntil(this.onDestroy$)) - .subscribe((actions) => { - this.viewerToolbarActions = actions; - }); - } - - ngOnDestroy() { - this.onDestroy$.next(true); - this.onDestroy$.complete(); + this.store.select(getAppSelection).subscribe((selection) => { + if (!selection.isEmpty) this.viewerToolbarActions = this.extensions.getSharedLinkViewerToolbarActions(); + }); } trackByActionId(_: number, action: ContentActionRef) { diff --git a/src/app/components/viewer/viewer.component.ts b/src/app/components/viewer/viewer.component.ts index 2897e323e..fb60700a9 100644 --- a/src/app/components/viewer/viewer.component.ts +++ b/src/app/components/viewer/viewer.component.ts @@ -27,7 +27,7 @@ import { AppExtensionService, AppHookService, ContentApiService } from '@alfresc import { AppStore, ClosePreviewAction, - getAppSelection, + getRuleContext, isInfoDrawerOpened, RefreshPreviewAction, ReloadDocumentListAction, @@ -131,24 +131,18 @@ export class AppViewerComponent implements OnInit, OnDestroy { }); this.store - .select(getAppSelection) + .select(getRuleContext) .pipe(takeUntil(this.onDestroy$)) - .subscribe((selection) => { - this.selection = selection; - }); + .subscribe((ruleContext) => { + this.selection = ruleContext.selection; - this.extensions - .getViewerToolbarActions() - .pipe(takeUntil(this.onDestroy$)) - .subscribe((actions) => { - this.toolbarActions = actions; - }); + if (this.toolbarActions.length === 0) { + this.toolbarActions = this.extensions.getViewerToolbarActions(); + } - this.extensions - .getOpenWithActions() - .pipe(takeUntil(this.onDestroy$)) - .subscribe((actions) => { - this.openWith = actions; + if (this.openWith.length === 0) { + this.openWith = this.extensions.openWithActions; + } }); this.route.params.subscribe((params) => {