mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
ACS-11160: improve context menu overlay service implementation (#11661)
* refactor: improve context menu overlay service implementation - Introduced a new interface for overlay references with backdrop handling. - Updated event listener for backdrop clicks to use the new interface, enhancing type safety. - Refactored the injector creation method to utilize the Injector.create method for better clarity and maintainability. - Improved the fake element's type definition in the getOverlayConfig method for better type inference. These changes enhance the overall robustness and readability of the context menu overlay service. * refactor: enhance type safety in context menu components - Introduced the ContextMenuItem interface to improve type definitions for context menu items. - Updated the ContextMenuListComponent to use ContextMenuItem for links and menu item parameters, enhancing clarity and maintainability. - Modified CONTEXT_MENU_DATA injection token to specify ContextMenuItem[] for better type safety. - Adjusted the ContextMenuOverlayConfig interface to accept an array of ContextMenuItem, ensuring consistent data handling. These changes improve the overall robustness and readability of the context menu implementation. [ci:force] * refactor: remove unnecessary eslint-disable comments in category management and search components - Eliminated eslint-disable comments related to no-underscore-dangle in the CategoriesManagementComponent and SearchControlComponent tests, improving code clarity and adherence to linting rules. - This change enhances the overall readability of the test files by ensuring consistent coding standards. * refactor: simplify backdrop click handling in context menu overlay service - Removed the unnecessary backdrop click handling logic, replacing it with a direct call to close the overlay reference. This change enhances code clarity and reduces complexity in the event listener implementation. * refactor: streamline backdrop handling in context menu overlay service - Removed the custom interface for overlay references with backdrop handling, simplifying the code. - Updated the event listener for backdrop clicks to directly use the overlay's backdropElement, enhancing clarity and maintainability. - This change improves the overall robustness of the context menu overlay service.
This commit is contained in:
-2
@@ -328,7 +328,6 @@ describe('CategoriesManagementComponent', () => {
|
||||
const categoriesChangeSpy = spyOn(component.categoriesChange, 'emit').and.callThrough();
|
||||
typeCategory('test');
|
||||
const options = getExistingCategoriesList();
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
options[0].click();
|
||||
|
||||
expect(component.categories.length).toBe(3);
|
||||
@@ -342,7 +341,6 @@ describe('CategoriesManagementComponent', () => {
|
||||
it('should remove selected category from categories list and add it back to existing categories', fakeAsync(() => {
|
||||
typeCategory('test');
|
||||
const options = getExistingCategoriesList();
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
options[0].click();
|
||||
fixture.detectChanges();
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import { NgForOf, NgIf } from '@angular/common';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { DOWN_ARROW, UP_ARROW } from '@angular/cdk/keycodes';
|
||||
import { IconModule } from '../icon/icon.module';
|
||||
import { ContextMenuItem } from './interfaces';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-context-menu',
|
||||
@@ -42,10 +43,10 @@ import { IconModule } from '../icon/icon.module';
|
||||
export class ContextMenuListComponent implements AfterViewInit {
|
||||
private keyManager: FocusKeyManager<MatMenuItem>;
|
||||
@ViewChildren(MatMenuItem) items: QueryList<MatMenuItem>;
|
||||
links: any[];
|
||||
links: ContextMenuItem[];
|
||||
|
||||
@HostListener('document:keydown.Escape', ['$event'])
|
||||
handleKeydownEscape(event: KeyboardEvent) {
|
||||
handleKeydownEscape(event: Event) {
|
||||
if (event) {
|
||||
this.contextMenuOverlayRef.close();
|
||||
}
|
||||
@@ -63,12 +64,12 @@ export class ContextMenuListComponent implements AfterViewInit {
|
||||
|
||||
constructor(
|
||||
@Inject(ContextMenuOverlayRef) private contextMenuOverlayRef: ContextMenuOverlayRef,
|
||||
@Optional() @Inject(CONTEXT_MENU_DATA) private data: any
|
||||
@Optional() @Inject(CONTEXT_MENU_DATA) private data: ContextMenuItem[]
|
||||
) {
|
||||
this.links = this.data;
|
||||
}
|
||||
|
||||
onMenuItemClick(event: Event, menuItem: any) {
|
||||
onMenuItemClick(event: Event, menuItem: ContextMenuItem) {
|
||||
if (menuItem?.model?.disabled) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Injectable, Injector, ElementRef, ComponentRef } from '@angular/core';
|
||||
import { Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
|
||||
import { PortalInjector, ComponentPortal } from '@angular/cdk/portal';
|
||||
import { ComponentPortal } from '@angular/cdk/portal';
|
||||
import { ContextMenuOverlayRef } from './context-menu-overlay';
|
||||
import { ContextMenuOverlayConfig } from './interfaces';
|
||||
import { CONTEXT_MENU_DATA } from './context-menu.tokens';
|
||||
@@ -33,7 +33,10 @@ const DEFAULT_CONFIG: ContextMenuOverlayConfig = {
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ContextMenuOverlayService {
|
||||
constructor(private injector: Injector, private overlay: Overlay) {}
|
||||
constructor(
|
||||
private injector: Injector,
|
||||
private overlay: Overlay
|
||||
) {}
|
||||
|
||||
open(config: ContextMenuOverlayConfig): ContextMenuOverlayRef {
|
||||
const overlayConfig = { ...DEFAULT_CONFIG, ...config };
|
||||
@@ -47,14 +50,12 @@ export class ContextMenuOverlayService {
|
||||
overlay.backdropClick().subscribe(() => overlayRef.close());
|
||||
|
||||
// prevent native contextmenu on overlay element if config.hasBackdrop is true
|
||||
if (overlayConfig.hasBackdrop) {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
(overlay as any).backdropElement.addEventListener(
|
||||
if (overlayConfig.hasBackdrop && overlay.backdropElement) {
|
||||
overlay.backdropElement.addEventListener(
|
||||
'contextmenu',
|
||||
(event) => {
|
||||
event.preventDefault();
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
(overlay as any)._backdropClick.next(null);
|
||||
overlayRef.close();
|
||||
},
|
||||
true
|
||||
);
|
||||
@@ -77,28 +78,32 @@ export class ContextMenuOverlayService {
|
||||
return containerRef.instance;
|
||||
}
|
||||
|
||||
private createInjector(config: ContextMenuOverlayConfig, contextMenuOverlayRef: ContextMenuOverlayRef): PortalInjector {
|
||||
const injectionTokens = new WeakMap();
|
||||
|
||||
injectionTokens.set(ContextMenuOverlayRef, contextMenuOverlayRef);
|
||||
injectionTokens.set(CONTEXT_MENU_DATA, config.data);
|
||||
|
||||
return new PortalInjector(this.injector, injectionTokens);
|
||||
private createInjector(config: ContextMenuOverlayConfig, contextMenuOverlayRef: ContextMenuOverlayRef): Injector {
|
||||
return Injector.create({
|
||||
parent: this.injector,
|
||||
providers: [
|
||||
{ provide: ContextMenuOverlayRef, useValue: contextMenuOverlayRef },
|
||||
{ provide: CONTEXT_MENU_DATA, useValue: config.data }
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
private getOverlayConfig(config: ContextMenuOverlayConfig): OverlayConfig {
|
||||
const { clientY, clientX } = config.source;
|
||||
|
||||
const fakeElement: any = {
|
||||
getBoundingClientRect: (): ClientRect =>
|
||||
const fakeElement: Pick<HTMLElement, 'getBoundingClientRect'> = {
|
||||
getBoundingClientRect: (): DOMRect =>
|
||||
({
|
||||
bottom: clientY,
|
||||
height: 0,
|
||||
left: clientX,
|
||||
right: clientX,
|
||||
top: clientY,
|
||||
width: 0
|
||||
} as any)
|
||||
width: 0,
|
||||
x: clientX,
|
||||
y: clientY,
|
||||
toJSON: () => ({})
|
||||
}) as DOMRect
|
||||
};
|
||||
|
||||
const positionStrategy = this.overlay
|
||||
|
||||
@@ -16,5 +16,6 @@
|
||||
*/
|
||||
|
||||
import { InjectionToken } from '@angular/core';
|
||||
import { ContextMenuItem } from './interfaces';
|
||||
|
||||
export const CONTEXT_MENU_DATA = new InjectionToken<any>('CONTEXT_MENU_DATA');
|
||||
export const CONTEXT_MENU_DATA = new InjectionToken<ContextMenuItem[]>('CONTEXT_MENU_DATA');
|
||||
|
||||
@@ -20,5 +20,19 @@ export interface ContextMenuOverlayConfig {
|
||||
hasBackdrop?: boolean;
|
||||
backdropClass?: string;
|
||||
source?: MouseEvent;
|
||||
data?: any;
|
||||
data?: ContextMenuItem[];
|
||||
}
|
||||
|
||||
export interface ContextMenuItem {
|
||||
title?: string;
|
||||
model?: {
|
||||
title?: string;
|
||||
visible?: boolean;
|
||||
disabled?: boolean;
|
||||
icon?: string;
|
||||
tooltip?: string;
|
||||
};
|
||||
subject: {
|
||||
next: (value: ContextMenuItem) => void;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user