[ACA-2873] Move acaContextActions to aca-shared library (#1301)

* move to aca-shared library

* export directive

* context menu action

* import directive from shared library

* context menu effect

* test

* update docs

* fix production code

* fix imports

* fix licence header

* fix licence headers
This commit is contained in:
Cilibiu Bogdan
2020-01-20 10:42:42 +02:00
committed by Adina Parpalita
parent b09c93b103
commit 8b7c7b5ed4
13 changed files with 247 additions and 49 deletions
@@ -1,124 +0,0 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2020 Alfresco Software Limited
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import {
Directive,
HostListener,
Input,
OnInit,
OnDestroy
} from '@angular/core';
import { ContextMenuOverlayRef } from './context-menu-overlay';
import { ContextMenuService } from './context-menu.service';
import { debounceTime } from 'rxjs/operators';
import { Subject, fromEvent, Subscription } from 'rxjs';
@Directive({
selector: '[acaContextActions]'
})
export class ContextActionsDirective implements OnInit, OnDestroy {
private execute$: Subject<any> = new Subject();
private subscriptions: Subscription[] = [];
private overlayRef: ContextMenuOverlayRef = null;
// tslint:disable-next-line:no-input-rename
@Input('acaContextEnable')
enabled = true;
@HostListener('contextmenu', ['$event'])
onContextMenuEvent(event: MouseEvent) {
if (event) {
event.preventDefault();
if (this.enabled) {
const target = this.getTarget(event);
if (target) {
this.execute(event, target);
}
}
}
}
constructor(private contextMenuService: ContextMenuService) {}
ngOnInit() {
this.subscriptions.push(
fromEvent(document.body, 'contextmenu').subscribe(() => {
if (this.overlayRef) {
this.overlayRef.close();
}
}),
this.execute$.pipe(debounceTime(300)).subscribe((event: MouseEvent) => {
this.render(event);
})
);
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
this.subscriptions = [];
this.execute$ = null;
}
execute(event: MouseEvent, target: Element) {
if (!this.isSelected(target)) {
target.dispatchEvent(new MouseEvent('click'));
}
this.execute$.next(event);
}
private render(event: MouseEvent) {
this.overlayRef = this.contextMenuService.open({
source: event,
hasBackdrop: false,
backdropClass: 'cdk-overlay-transparent-backdrop',
panelClass: 'cdk-overlay-pane'
});
}
private getTarget(event: MouseEvent): Element {
return this.findAncestor(<Element>event.target, 'adf-datatable-cell');
}
private isSelected(target: Element): boolean {
if (!target) {
return false;
}
return this.findAncestor(target, 'adf-datatable-row').classList.contains(
'adf-is-selected'
);
}
private findAncestor(el: Element, className: string): Element {
if (el.classList.contains(className)) {
return el;
}
// tslint:disable-next-line:curly
while ((el = el.parentElement) && !el.classList.contains(className));
return el;
}
}
@@ -1,63 +0,0 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2020 Alfresco Software Limited
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { ContextActionsDirective } from './context-menu.directive';
import { fakeAsync, tick } from '@angular/core/testing';
describe('ContextActionsDirective', () => {
let directive;
const contextMenuServiceMock = <any>{
open: jasmine.createSpy('open')
};
beforeEach(() => {
directive = new ContextActionsDirective(contextMenuServiceMock);
});
it('should not render context menu when `enabled` property is false', () => {
directive.enabled = false;
directive.onContextMenuEvent(new MouseEvent('contextmenu'));
expect(contextMenuServiceMock.open).not.toHaveBeenCalled();
});
it('should call service to render context menu', fakeAsync(() => {
const el = document.createElement('div');
el.className =
'adf-datatable-cell adf-datatable-cell--text adf-datatable-row';
const fragment = document.createDocumentFragment();
fragment.appendChild(el);
const target = fragment.querySelector('div');
directive.ngOnInit();
directive.onContextMenuEvent(<any>{ preventDefault: () => {}, target });
tick(500);
expect(contextMenuServiceMock.open).toHaveBeenCalled();
}));
});
@@ -35,7 +35,7 @@ import { AppCommonModule } from '../common/common.module';
import { ContextMenuItemComponent } from './context-menu-item.component';
import { OutsideEventDirective } from './context-menu-outside-event.directive';
import { ContextMenuComponent } from './context-menu.component';
import { ContextActionsDirective } from './context-menu.directive';
import { ContextActionsModule } from '@alfresco/aca-shared';
@NgModule({
imports: [
@@ -46,19 +46,19 @@ import { ContextActionsDirective } from './context-menu.directive';
CoreExtensionsModule.forChild(),
CoreModule.forChild(),
AppCommonModule,
ExtensionsModule
ExtensionsModule,
ContextActionsModule
],
declarations: [
ContextActionsDirective,
ContextMenuComponent,
ContextMenuItemComponent,
OutsideEventDirective
],
exports: [
OutsideEventDirective,
ContextActionsDirective,
ContextMenuComponent,
ContextMenuItemComponent
ContextMenuItemComponent,
ContextActionsModule
],
entryComponents: [ContextMenuComponent]
})
+4 -2
View File
@@ -40,7 +40,8 @@ import {
LibraryEffects,
UploadEffects,
FavoriteEffects,
TemplateEffects
TemplateEffects,
ContextMenuEffects
} from './effects';
import { INITIAL_STATE } from './initial-state';
@@ -58,7 +59,8 @@ import { INITIAL_STATE } from './initial-state';
LibraryEffects,
UploadEffects,
FavoriteEffects,
TemplateEffects
TemplateEffects,
ContextMenuEffects
]),
!environment.production
? StoreDevtoolsModule.instrument({ maxAge: 25 })
+1
View File
@@ -33,3 +33,4 @@ export * from './effects/library.effects';
export * from './effects/upload.effects';
export * from './effects/upload.effects';
export * from './effects/template.effects';
export * from './effects/contextmenu.effects';
@@ -0,0 +1,65 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2020 Alfresco Software Limited
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { TestBed } from '@angular/core/testing';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContextMenuEffects } from './contextmenu.effects';
import { EffectsModule } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { ContextMenu } from '@alfresco/aca-shared/store';
import { ContextMenuService } from '../../components/context-menu/context-menu.service';
describe('ContextMenuEffects', () => {
let store: Store<any>;
let contextMenuService: ContextMenuService;
const overlayRefMock = {
close: jasmine.createSpy('close')
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [AppTestingModule, EffectsModule.forRoot([ContextMenuEffects])],
providers: [ContextMenuService]
});
store = TestBed.get(Store);
contextMenuService = TestBed.get(ContextMenuService);
spyOn(contextMenuService, 'open').and.returnValue(overlayRefMock);
});
it('should open dialog', () => {
store.dispatch(new ContextMenu(new MouseEvent('click')));
expect(contextMenuService.open).toHaveBeenCalled();
});
it('should close dialog reference if previously was opened', () => {
store.dispatch(new ContextMenu(new MouseEvent('click')));
expect(contextMenuService.open).toHaveBeenCalled();
store.dispatch(new ContextMenu(new MouseEvent('click')));
expect(overlayRefMock.close).toHaveBeenCalled();
});
});
@@ -0,0 +1,61 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2020 Alfresco Software Limited
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import {
ContextMenuActionTypes,
ContextMenu
} from '@alfresco/aca-shared/store';
import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { map } from 'rxjs/operators';
import { ContextMenuOverlayRef } from '../../components/context-menu/context-menu-overlay';
import { ContextMenuService } from '../../components/context-menu/context-menu.service';
@Injectable()
export class ContextMenuEffects {
private overlayRef: ContextMenuOverlayRef = null;
constructor(
private contextMenuService: ContextMenuService,
private actions$: Actions
) {}
@Effect({ dispatch: false })
contextMenu$ = this.actions$.pipe(
ofType<ContextMenu>(ContextMenuActionTypes.ContextMenu),
map(action => {
if (this.overlayRef) {
this.overlayRef.close();
}
this.overlayRef = this.contextMenuService.open({
source: action.event,
hasBackdrop: false,
backdropClass: 'cdk-overlay-transparent-backdrop',
panelClass: 'cdk-overlay-pane'
});
})
);
}