diff --git a/src/app/components/context-menu/context-menu-outside-event.directive.ts b/src/app/components/context-menu/context-menu-outside-event.directive.ts
index ff352239b..c840eb32e 100644
--- a/src/app/components/context-menu/context-menu-outside-event.directive.ts
+++ b/src/app/components/context-menu/context-menu-outside-event.directive.ts
@@ -6,7 +6,7 @@ import {
OnDestroy
} from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';
-import { delay } from 'rxjs/operators';
+import { filter } from 'rxjs/operators';
@Directive({
selector: '[acaContextMenuOutsideEvent]'
@@ -22,7 +22,7 @@ export class OutsideEventDirective implements OnInit, OnDestroy {
ngOnInit() {
this.subscriptions = this.subscriptions.concat([
fromEvent(document.body, 'click')
- .pipe(delay(1))
+ .pipe(filter(event => !this.findAncestor(event.target as Element)))
.subscribe(() => this.clickOutside.next())
]);
}
@@ -31,4 +31,15 @@ export class OutsideEventDirective implements OnInit, OnDestroy {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
this.subscriptions = [];
}
+
+ private findAncestor(el: Element): boolean {
+ const className = 'aca-context-menu';
+
+ if (el.classList.contains(className)) {
+ return true;
+ }
+ // tslint:disable-next-line:curly
+ while ((el = el.parentElement) && !el.classList.contains(className));
+ return !!el;
+ }
}
diff --git a/src/app/components/context-menu/context-menu.directive.ts b/src/app/components/context-menu/context-menu.directive.ts
index 2acc26031..5fb5af91c 100644
--- a/src/app/components/context-menu/context-menu.directive.ts
+++ b/src/app/components/context-menu/context-menu.directive.ts
@@ -23,20 +23,24 @@
* along with Alfresco. If not, see .
*/
-import { Directive, HostListener, Input } from '@angular/core';
+import {
+ Directive,
+ HostListener,
+ Input,
+ OnInit,
+ OnDestroy
+} from '@angular/core';
import { ContextMenuOverlayRef } from './context-menu-overlay';
import { ContextMenuService } from './context-menu.service';
-import { DocumentListComponent } from '@alfresco/adf-content-services';
-import { SetSelectedNodesAction } from '../../store/actions';
-import { Store } from '@ngrx/store';
-import { AppStore } from '../../store/states/app.state';
-import { DataRow } from '@alfresco/adf-core';
-import { MinimalNodeEntity } from 'alfresco-js-api';
+import { debounceTime } from 'rxjs/operators';
+import { Subject, fromEvent, Subscription } from 'rxjs';
@Directive({
selector: '[acaContextActions]'
})
-export class ContextActionsDirective {
+export class ContextActionsDirective implements OnInit, OnDestroy {
+ private execute$: Subject = new Subject();
+ private subscriptions: Subscription[] = [];
private overlayRef: ContextMenuOverlayRef = null;
// tslint:disable-next-line:no-input-rename
@@ -49,40 +53,44 @@ export class ContextActionsDirective {
event.preventDefault();
if (this.enabled) {
- this.execute(event);
+ const target = this.getTarget(event);
+ if (target) {
+ this.execute(event, target);
+ }
}
}
}
- constructor(
- private documentList: DocumentListComponent,
- private store: Store,
- private contextMenuService: ContextMenuService
- ) {}
+ constructor(private contextMenuService: ContextMenuService) {}
- private execute(event: MouseEvent) {
- // todo: review this in ADF
- const selected = this.getSelectedRow(event);
+ ngOnInit() {
+ this.subscriptions.push(
+ fromEvent(document.body, 'contextmenu').subscribe(() => {
+ if (this.overlayRef) {
+ this.overlayRef.close();
+ }
+ }),
- if (selected) {
- if (!this.isInSelection(selected)) {
- this.clearSelection();
+ this.execute$.pipe(debounceTime(300)).subscribe((event: MouseEvent) => {
+ this.render(event);
+ })
+ );
+ }
- this.documentList.dataTable.selectRow(selected, true);
- this.documentList.selection.push((selected).node);
+ ngOnDestroy() {
+ this.subscriptions.forEach(subscription => subscription.unsubscribe());
+ this.subscriptions = [];
+ this.execute$ = null;
+ }
- this.updateSelection();
- }
-
- this.render(event);
+ execute(event: MouseEvent, target: Element) {
+ if (!this.isSelected(target)) {
+ target.dispatchEvent(new MouseEvent('click'));
}
+ this.execute$.next(event);
}
private render(event: MouseEvent) {
- if (this.overlayRef) {
- this.overlayRef.close();
- }
-
this.overlayRef = this.contextMenuService.open({
source: event,
hasBackdrop: false,
@@ -91,46 +99,24 @@ export class ContextActionsDirective {
});
}
- private updateSelection() {
- this.store.dispatch(
- new SetSelectedNodesAction(this.documentList.selection)
- );
+ private getTarget(event: MouseEvent): Element {
+ return this.findAncestor(event.target, 'adf-datatable-table-cell');
}
- private isInSelection(row: DataRow): MinimalNodeEntity {
- return this.documentList.selection.find(
- selected => row.getValue('name') === selected.entry.name
- );
- }
-
- private getSelectedRow(event): DataRow {
- const rowElement = this.findAncestor(
- event.target,
- 'adf-datatable-row'
- );
-
- if (!rowElement) {
- return null;
+ private isSelected(target): boolean {
+ if (!target) {
+ return false;
}
- const rowName = rowElement
- .querySelector('.adf-data-table-cell--text .adf-datatable-cell')
- .textContent.trim();
-
- return this.documentList.data
- .getRows()
- .find((row: DataRow) => row.getValue('name') === rowName);
- }
-
- private clearSelection() {
- this.documentList.data.getRows().map((row: DataRow) => {
- return this.documentList.dataTable.selectRow(row, false);
- });
-
- this.documentList.selection = [];
+ return this.findAncestor(target, 'adf-datatable-row').classList.contains(
+ '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;
diff --git a/src/app/components/context-menu/context-menu.directives.spec.ts b/src/app/components/context-menu/context-menu.directives.spec.ts
index 88516a83f..13d57e0f1 100644
--- a/src/app/components/context-menu/context-menu.directives.spec.ts
+++ b/src/app/components/context-menu/context-menu.directives.spec.ts
@@ -24,39 +24,40 @@
*/
import { ContextActionsDirective } from './context-menu.directive';
+import { fakeAsync, tick } from '@angular/core/testing';
describe('ContextActionsDirective', () => {
let directive;
const contextMenuServiceMock = {
open: jasmine.createSpy('open')
};
- const storeMock = {};
- const documentListMock = {};
beforeEach(() => {
- directive = new ContextActionsDirective(
- documentListMock,
- storeMock,
- contextMenuServiceMock
- );
+ directive = new ContextActionsDirective(contextMenuServiceMock);
});
- it('should not render context menu when disable property is false', () => {
+ it('should not render context menu when `enabled` property is false', () => {
directive.enabled = false;
- spyOn(directive, 'getSelectedRow').and.returnValue({});
-
directive.onContextMenuEvent(new MouseEvent('contextmenu'));
expect(contextMenuServiceMock.open).not.toHaveBeenCalled();
});
- it('should render context menu when disable property is true', () => {
- directive.enabled = true;
- spyOn(directive, 'getSelectedRow').and.returnValue({});
- spyOn(directive, 'isInSelection').and.returnValue(true);
+ it('should call service to render context menu', fakeAsync(() => {
+ const el = document.createElement('div');
+ el.className =
+ 'adf-data-table-cell adf-datatable-table-cell adf-datatable-row';
- directive.onContextMenuEvent(new MouseEvent('contextmenu'));
+ const fragment = document.createDocumentFragment();
+ fragment.appendChild(el);
+ const target = fragment.querySelector('div');
+
+ directive.ngOnInit();
+
+ directive.onContextMenuEvent({ preventDefault: () => {}, target });
+
+ tick(500);
expect(contextMenuServiceMock.open).toHaveBeenCalled();
- });
+ }));
});