mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-06-02 17:34:51 +00:00
Context menu - library files fix (#815)
This commit is contained in:
parent
94f2762940
commit
43b55102be
@ -6,7 +6,7 @@ import {
|
|||||||
OnDestroy
|
OnDestroy
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { fromEvent, Subscription } from 'rxjs';
|
import { fromEvent, Subscription } from 'rxjs';
|
||||||
import { delay } from 'rxjs/operators';
|
import { filter } from 'rxjs/operators';
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[acaContextMenuOutsideEvent]'
|
selector: '[acaContextMenuOutsideEvent]'
|
||||||
@ -22,7 +22,7 @@ export class OutsideEventDirective implements OnInit, OnDestroy {
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.subscriptions = this.subscriptions.concat([
|
this.subscriptions = this.subscriptions.concat([
|
||||||
fromEvent(document.body, 'click')
|
fromEvent(document.body, 'click')
|
||||||
.pipe(delay(1))
|
.pipe(filter(event => !this.findAncestor(event.target as Element)))
|
||||||
.subscribe(() => this.clickOutside.next())
|
.subscribe(() => this.clickOutside.next())
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -31,4 +31,15 @@ export class OutsideEventDirective implements OnInit, OnDestroy {
|
|||||||
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
||||||
this.subscriptions = [];
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,20 +23,24 @@
|
|||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Directive, HostListener, Input } from '@angular/core';
|
import {
|
||||||
|
Directive,
|
||||||
|
HostListener,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
OnDestroy
|
||||||
|
} from '@angular/core';
|
||||||
import { ContextMenuOverlayRef } from './context-menu-overlay';
|
import { ContextMenuOverlayRef } from './context-menu-overlay';
|
||||||
import { ContextMenuService } from './context-menu.service';
|
import { ContextMenuService } from './context-menu.service';
|
||||||
import { DocumentListComponent } from '@alfresco/adf-content-services';
|
import { debounceTime } from 'rxjs/operators';
|
||||||
import { SetSelectedNodesAction } from '../../store/actions';
|
import { Subject, fromEvent, Subscription } from 'rxjs';
|
||||||
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({
|
@Directive({
|
||||||
selector: '[acaContextActions]'
|
selector: '[acaContextActions]'
|
||||||
})
|
})
|
||||||
export class ContextActionsDirective {
|
export class ContextActionsDirective implements OnInit, OnDestroy {
|
||||||
|
private execute$: Subject<any> = new Subject();
|
||||||
|
private subscriptions: Subscription[] = [];
|
||||||
private overlayRef: ContextMenuOverlayRef = null;
|
private overlayRef: ContextMenuOverlayRef = null;
|
||||||
|
|
||||||
// tslint:disable-next-line:no-input-rename
|
// tslint:disable-next-line:no-input-rename
|
||||||
@ -49,40 +53,44 @@ export class ContextActionsDirective {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if (this.enabled) {
|
if (this.enabled) {
|
||||||
this.execute(event);
|
const target = this.getTarget(event);
|
||||||
|
if (target) {
|
||||||
|
this.execute(event, target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(private contextMenuService: ContextMenuService) {}
|
||||||
private documentList: DocumentListComponent,
|
|
||||||
private store: Store<AppStore>,
|
|
||||||
private contextMenuService: ContextMenuService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
private execute(event: MouseEvent) {
|
ngOnInit() {
|
||||||
// todo: review this in ADF
|
this.subscriptions.push(
|
||||||
const selected = this.getSelectedRow(event);
|
fromEvent(document.body, 'contextmenu').subscribe(() => {
|
||||||
|
if (this.overlayRef) {
|
||||||
|
this.overlayRef.close();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
if (selected) {
|
this.execute$.pipe(debounceTime(300)).subscribe((event: MouseEvent) => {
|
||||||
if (!this.isInSelection(selected)) {
|
this.render(event);
|
||||||
this.clearSelection();
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this.documentList.dataTable.selectRow(selected, true);
|
ngOnDestroy() {
|
||||||
this.documentList.selection.push((<any>selected).node);
|
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
||||||
|
this.subscriptions = [];
|
||||||
|
this.execute$ = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.updateSelection();
|
execute(event: MouseEvent, target: Element) {
|
||||||
}
|
if (!this.isSelected(target)) {
|
||||||
|
target.dispatchEvent(new MouseEvent('click'));
|
||||||
this.render(event);
|
|
||||||
}
|
}
|
||||||
|
this.execute$.next(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private render(event: MouseEvent) {
|
private render(event: MouseEvent) {
|
||||||
if (this.overlayRef) {
|
|
||||||
this.overlayRef.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.overlayRef = this.contextMenuService.open({
|
this.overlayRef = this.contextMenuService.open({
|
||||||
source: event,
|
source: event,
|
||||||
hasBackdrop: false,
|
hasBackdrop: false,
|
||||||
@ -91,46 +99,24 @@ export class ContextActionsDirective {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateSelection() {
|
private getTarget(event: MouseEvent): Element {
|
||||||
this.store.dispatch(
|
return this.findAncestor(<Element>event.target, 'adf-datatable-table-cell');
|
||||||
new SetSelectedNodesAction(this.documentList.selection)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private isInSelection(row: DataRow): MinimalNodeEntity {
|
private isSelected(target): boolean {
|
||||||
return this.documentList.selection.find(
|
if (!target) {
|
||||||
selected => row.getValue('name') === selected.entry.name
|
return false;
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getSelectedRow(event): DataRow {
|
|
||||||
const rowElement = this.findAncestor(
|
|
||||||
<HTMLElement>event.target,
|
|
||||||
'adf-datatable-row'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!rowElement) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const rowName = rowElement
|
return this.findAncestor(target, 'adf-datatable-row').classList.contains(
|
||||||
.querySelector('.adf-data-table-cell--text .adf-datatable-cell')
|
'is-selected'
|
||||||
.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 {
|
private findAncestor(el: Element, className: string): Element {
|
||||||
|
if (el.classList.contains(className)) {
|
||||||
|
return el;
|
||||||
|
}
|
||||||
// tslint:disable-next-line:curly
|
// tslint:disable-next-line:curly
|
||||||
while ((el = el.parentElement) && !el.classList.contains(className));
|
while ((el = el.parentElement) && !el.classList.contains(className));
|
||||||
return el;
|
return el;
|
||||||
|
@ -24,39 +24,40 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ContextActionsDirective } from './context-menu.directive';
|
import { ContextActionsDirective } from './context-menu.directive';
|
||||||
|
import { fakeAsync, tick } from '@angular/core/testing';
|
||||||
|
|
||||||
describe('ContextActionsDirective', () => {
|
describe('ContextActionsDirective', () => {
|
||||||
let directive;
|
let directive;
|
||||||
const contextMenuServiceMock = <any>{
|
const contextMenuServiceMock = <any>{
|
||||||
open: jasmine.createSpy('open')
|
open: jasmine.createSpy('open')
|
||||||
};
|
};
|
||||||
const storeMock = <any>{};
|
|
||||||
const documentListMock = <any>{};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
directive = new ContextActionsDirective(
|
directive = new ContextActionsDirective(contextMenuServiceMock);
|
||||||
documentListMock,
|
|
||||||
storeMock,
|
|
||||||
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;
|
directive.enabled = false;
|
||||||
spyOn(directive, 'getSelectedRow').and.returnValue({});
|
|
||||||
|
|
||||||
directive.onContextMenuEvent(new MouseEvent('contextmenu'));
|
directive.onContextMenuEvent(new MouseEvent('contextmenu'));
|
||||||
|
|
||||||
expect(contextMenuServiceMock.open).not.toHaveBeenCalled();
|
expect(contextMenuServiceMock.open).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render context menu when disable property is true', () => {
|
it('should call service to render context menu', fakeAsync(() => {
|
||||||
directive.enabled = true;
|
const el = document.createElement('div');
|
||||||
spyOn(directive, 'getSelectedRow').and.returnValue({});
|
el.className =
|
||||||
spyOn(directive, 'isInSelection').and.returnValue(true);
|
'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(<any>{ preventDefault: () => {}, target });
|
||||||
|
|
||||||
|
tick(500);
|
||||||
|
|
||||||
expect(contextMenuServiceMock.open).toHaveBeenCalled();
|
expect(contextMenuServiceMock.open).toHaveBeenCalled();
|
||||||
});
|
}));
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user