[ACA-1696] contextmenu (#587)

* enbale contextmenu by default

* attach event only when backdrop is set

* outside event for contextmenu

* apply outside event directive

* workaround fro contextmenu event row selection

* remove Output parameter

* update dockerfile

* update docker compose file
This commit is contained in:
Cilibiu Bogdan 2018-08-29 15:44:47 +03:00 committed by Denys Vuika
parent 5759ea1b62
commit 091e0d3e3f
14 changed files with 141 additions and 20 deletions

View File

@ -1,4 +1,4 @@
FROM nginx:alpine
FROM nginx:stable-alpine
LABEL version="1.3"
LABEL maintainer="Denys Vuika <denys.vuika@alfresco.com>"

View File

@ -81,7 +81,7 @@ services:
# - ./nginx.conf:/etc/nginx/conf.d/default.conf
proxy:
image: nginx
image: nginx:stable-alpine
depends_on:
- content-app
volumes:

View File

@ -0,0 +1,28 @@
import { Directive, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';
import { delay } from 'rxjs/operators';
@Directive({
selector: '[acaContextMenuOutsideEvent]'
})
export class OutsideEventDirective implements OnInit, OnDestroy {
private subscriptions: Subscription[] = [];
@Output() clickOutside: EventEmitter<null> = new EventEmitter();
constructor() {}
ngOnInit() {
this.subscriptions = this.subscriptions.concat([
fromEvent(document, 'click')
.pipe(delay(1))
.subscribe(() => this.clickOutside.next())
]);
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
this.subscriptions = [];
}
}

View File

@ -1,4 +1,8 @@
<div mat-menu class="mat-menu-panel" @panelAnimation>
<div mat-menu class="mat-menu-panel"
@panelAnimation
acaContextMenuOutsideEvent
(clickOutside)="onClickOutsideEvent()">
<div class="mat-menu-content">
<ng-container *ngFor="let entry of actions" [ngSwitch]="entry.type">
<ng-container *ngSwitchCase="'default'">

View File

@ -68,10 +68,22 @@ export class ContextMenuComponent implements OnInit, OnDestroy, AfterViewInit {
@ViewChildren(ContextMenuItemDirective)
private contextMenuItems: QueryList<ContextMenuItemDirective>;
@HostListener('contextmenu', ['$event'])
handleContextMenu(event: MouseEvent) {
if (event) {
event.preventDefault();
if (this.contextMenuOverlayRef) {
this.contextMenuOverlayRef.close();
}
}
}
@HostListener('document:keydown.Escape', ['$event'])
handleKeydownEscape(event: KeyboardEvent) {
if (event) {
this.contextMenuOverlayRef.close();
if (this.contextMenuOverlayRef) {
this.contextMenuOverlayRef.close();
}
}
}
@ -91,6 +103,12 @@ export class ContextMenuComponent implements OnInit, OnDestroy, AfterViewInit {
private store: Store<AppStore>,
) { }
onClickOutsideEvent() {
if (this.contextMenuOverlayRef) {
this.contextMenuOverlayRef.close();
}
}
runAction(actionId: string) {
const context = {
selection: this.selection

View File

@ -26,6 +26,12 @@
import { Directive, HostListener, Input } 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';
@Directive({
selector: '[acaContextActions]'
@ -34,11 +40,12 @@ export class ContextActionsDirective {
private overlayRef: ContextMenuOverlayRef = null;
// tslint:disable-next-line:no-input-rename
@Input('acaContextEnable') enabled: boolean;
@Input('acaContextEnable') enabled = true;
@HostListener('window:resize', ['$event'])
onResize(event) {
if (event && this.overlayRef) {
this.clearSelection();
this.overlayRef.close();
}
}
@ -49,19 +56,84 @@ export class ContextActionsDirective {
event.preventDefault();
if (this.enabled) {
this.render(event);
this.execute(event);
}
}
}
constructor(private contextMenuService: ContextMenuService) { }
constructor(
private documentList: DocumentListComponent,
private store: Store<AppStore>,
private contextMenuService: ContextMenuService
) { }
private execute(event: MouseEvent) {
const selected = this.getSelectedRow();
if (selected) {
if (!this.isInSelection(selected)) {
this.clearSelection();
this.documentList.dataTable.selectRow(selected, true);
this.documentList.selection.push((<any>selected).node);
this.updateSelection();
}
this.render(event);
}
}
private render(event: MouseEvent) {
if (this.overlayRef) {
this.overlayRef.close();
}
this.overlayRef = this.contextMenuService.open({
source: event,
hasBackdrop: true,
hasBackdrop: false,
backdropClass: 'cdk-overlay-transparent-backdrop',
panelClass: 'cdk-overlay-pane',
});
}
private updateSelection() {
this.store.dispatch(
new SetSelectedNodesAction(this.documentList.selection)
);
}
private isInSelection(row: DataRow): MinimalNodeEntity {
return this.documentList.selection.find((selected) =>
row.getValue('name') === selected.entry.name);
}
private getSelectedRow(): DataRow {
const rowElement = this.findAncestor(<HTMLElement>event.target, 'adf-datatable-row');
if (!rowElement) {
return null;
}
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 = [];
}
private findAncestor (el: Element, className: string): Element {
// tslint:disable-next-line:curly
while ((el = el.parentElement) && !el.classList.contains(className));
return el;
}
}

View File

@ -33,6 +33,7 @@ import { ContextActionsDirective } from './context-menu.directive';
import { ContextMenuService } from './context-menu.service';
import { ContextMenuComponent } from './context-menu.component';
import { ContextMenuItemDirective } from './context-menu-item.directive';
import { OutsideEventDirective } from './context-menu-outside-event.directive';
@NgModule({
imports: [
@ -47,9 +48,11 @@ import { ContextMenuItemDirective } from './context-menu-item.directive';
declarations: [
ContextActionsDirective,
ContextMenuComponent,
ContextMenuItemDirective
ContextMenuItemDirective,
OutsideEventDirective
],
exports: [
OutsideEventDirective,
ContextActionsDirective,
ContextMenuComponent
],

View File

@ -22,11 +22,13 @@ export class ContextMenuService {
overlay.backdropClick().subscribe(() => overlayRef.close());
// prevent native contextmenu on overlay element if config.hasBackdrop is true
(<any>overlay)._backdropElement
.addEventListener('contextmenu', () => {
event.preventDefault();
(<any>overlay)._backdropClick.next(null);
}, true);
if (config.hasBackdrop) {
(<any>overlay)._backdropElement
.addEventListener('contextmenu', () => {
event.preventDefault();
(<any>overlay)._backdropClick.next(null);
}, true);
}
return overlayRef;
}

View File

@ -16,7 +16,6 @@
<adf-document-list #documentList
acaDocumentList
acaContextActions
[acaContextEnable]="selection.count"
[display]="documentDisplayMode$ | async"
currentFolderId="-favorites-"
selectionMode="multiple"

View File

@ -27,7 +27,6 @@
<adf-document-list #documentList
acaDocumentList
acaContextActions
[acaContextEnable]="selection.count"
[display]="documentDisplayMode$ | async"
[sorting]="[ 'modifiedAt', 'desc' ]"
selectionMode="multiple"

View File

@ -19,7 +19,6 @@
<adf-document-list #documentList
acaDocumentList
acaContextActions
[acaContextEnable]="selection.count"
[display]="documentDisplayMode$ | async"
currentFolderId="-mysites-"
selectionMode="single"

View File

@ -17,7 +17,6 @@
<adf-document-list #documentList
acaDocumentList
acaContextActions
[acaContextEnable]="selection.count"
[display]="documentDisplayMode$ | async"
currentFolderId="-recent-"
selectionMode="multiple"

View File

@ -17,7 +17,6 @@
<adf-document-list #documentList
acaDocumentList
acaContextActions
[acaContextEnable]="selection.count"
[display]="documentDisplayMode$ | async"
currentFolderId="-sharedlinks-"
selectionMode="multiple"

View File

@ -17,7 +17,6 @@
<adf-document-list #documentList
acaDocumentList
acaContextActions
[acaContextEnable]="selection.count"
[display]="documentDisplayMode$ | async"
currentFolderId="-trashcan-"
selectionMode="multiple"