diff --git a/src/app/components/context-menu/context-menu.component.html b/src/app/components/context-menu/context-menu.component.html
index 7283cb02c..d9ee883bf 100644
--- a/src/app/components/context-menu/context-menu.component.html
+++ b/src/app/components/context-menu/context-menu.component.html
@@ -1,50 +1,54 @@
-
+
+
-
+
+
diff --git a/src/app/components/context-menu/context-menu.component.ts b/src/app/components/context-menu/context-menu.component.ts
index 4fae5f538..f72046871 100644
--- a/src/app/components/context-menu/context-menu.component.ts
+++ b/src/app/components/context-menu/context-menu.component.ts
@@ -30,10 +30,10 @@ import {
OnDestroy,
HostListener,
ViewChild,
- AfterViewInit
+ AfterViewInit,
+ Inject
} from '@angular/core';
import { MatMenuTrigger } from '@angular/material/menu';
-
import { AppExtensionService } from '../../extensions/extension.service';
import { AppStore, getAppSelection } from '@alfresco/aca-shared/store';
import { Store } from '@ngrx/store';
@@ -41,6 +41,8 @@ import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ContentActionRef } from '@alfresco/adf-extensions';
import { ContextMenuOverlayRef } from './context-menu-overlay';
+import { CONTEXT_MENU_DIRECTION } from './direction.token';
+import { Directionality } from '@angular/cdk/bidi';
@Component({
selector: 'aca-context-menu',
@@ -70,7 +72,8 @@ export class ContextMenuComponent implements OnInit, OnDestroy, AfterViewInit {
constructor(
private contextMenuOverlayRef: ContextMenuOverlayRef,
private extensions: AppExtensionService,
- private store: Store
+ private store: Store,
+ @Inject(CONTEXT_MENU_DIRECTION) public direction: Directionality
) {}
onClickOutsideEvent() {
diff --git a/src/app/components/context-menu/context-menu.service.spec.ts b/src/app/components/context-menu/context-menu.service.spec.ts
index 5ac488db6..a21d19e39 100644
--- a/src/app/components/context-menu/context-menu.service.spec.ts
+++ b/src/app/components/context-menu/context-menu.service.spec.ts
@@ -31,36 +31,85 @@ import { of } from 'rxjs';
import { CoreModule } from '@alfresco/adf-core';
import { ContextMenuService } from './context-menu.service';
import { ContextMenuModule } from './context-menu.module';
+import { UserPreferencesService } from '@alfresco/adf-core';
describe('ContextMenuService', () => {
let contextMenuService;
+ let overlay;
+ let injector;
+ let userPreferencesService;
const overlayConfig = {
hasBackdrop: false,
backdropClass: '',
- panelClass: 'test-panel'
+ panelClass: 'test-panel',
+ source: {
+ x: 1,
+ y: 1
+ }
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreModule.forRoot(), ContextMenuModule],
- providers: [Overlay, { provide: Store, useValue: { select: () => of() } }]
+ providers: [
+ Overlay,
+ { provide: Store, useValue: { select: () => of() } },
+ UserPreferencesService
+ ]
});
- const injector = TestBed.get(Injector);
- const overlay = TestBed.get(Overlay);
-
- contextMenuService = new ContextMenuService(injector, overlay);
+ injector = TestBed.get(Injector);
+ overlay = TestBed.get(Overlay);
+ userPreferencesService = TestBed.get(UserPreferencesService);
});
it('should create a custom overlay', () => {
+ contextMenuService = new ContextMenuService(
+ injector,
+ overlay,
+ userPreferencesService
+ );
+
contextMenuService.open(overlayConfig);
expect(document.querySelector('.test-panel')).not.toBe(null);
});
it('should render component', () => {
+ contextMenuService = new ContextMenuService(
+ injector,
+ overlay,
+ userPreferencesService
+ );
+
contextMenuService.open(overlayConfig);
expect(document.querySelector('aca-context-menu')).not.toBe(null);
});
+
+ it('should have default LTR direction value', () => {
+ contextMenuService = new ContextMenuService(
+ injector,
+ overlay,
+ userPreferencesService
+ );
+
+ contextMenuService.open(overlayConfig);
+
+ expect(document.body.querySelector('div[dir="ltr"]')).not.toBe(null);
+ });
+
+ it('should change direction on textOrientation event', () => {
+ spyOn(userPreferencesService, 'select').and.returnValue(of('rtl'));
+
+ contextMenuService = new ContextMenuService(
+ injector,
+ overlay,
+ userPreferencesService
+ );
+
+ contextMenuService.open(overlayConfig);
+
+ expect(document.body.querySelector('div[dir="rtl"]')).not.toBe(null);
+ });
});
diff --git a/src/app/components/context-menu/context-menu.service.ts b/src/app/components/context-menu/context-menu.service.ts
index bd9a71fea..4787e43e9 100644
--- a/src/app/components/context-menu/context-menu.service.ts
+++ b/src/app/components/context-menu/context-menu.service.ts
@@ -1,15 +1,55 @@
-import { Injectable, Injector, ComponentRef, ElementRef } from '@angular/core';
+/*!
+ * @license
+ * Alfresco Example Content Application
+ *
+ * Copyright (C) 2005 - 2019 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 .
+ */
+
+import { Injectable, Injector, ComponentRef } from '@angular/core';
import { Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal, PortalInjector } from '@angular/cdk/portal';
import { ContextMenuOverlayRef } from './context-menu-overlay';
import { ContextMenuComponent } from './context-menu.component';
import { ContextmenuOverlayConfig } from './interfaces';
+import { UserPreferencesService } from '@alfresco/adf-core';
+import { Directionality } from '@angular/cdk/bidi';
+import { CONTEXT_MENU_DIRECTION } from './direction.token';
@Injectable({
providedIn: 'root'
})
export class ContextMenuService {
- constructor(private injector: Injector, private overlay: Overlay) {}
+ private direction: Directionality;
+
+ constructor(
+ private injector: Injector,
+ private overlay: Overlay,
+ private userPreferenceService: UserPreferencesService
+ ) {
+ this.userPreferenceService
+ .select('textOrientation')
+ .subscribe(textOrientation => {
+ this.direction = textOrientation;
+ });
+ }
open(config: ContextmenuOverlayConfig) {
const overlay = this.createOverlay(config);
@@ -49,56 +89,33 @@ export class ContextMenuService {
const injectionTokens = new WeakMap();
injectionTokens.set(ContextMenuOverlayRef, contextmenuOverlayRef);
+ injectionTokens.set(CONTEXT_MENU_DIRECTION, this.direction);
return new PortalInjector(this.injector, injectionTokens);
}
private getOverlayConfig(config: ContextmenuOverlayConfig): OverlayConfig {
- const fakeElement: any = {
- getBoundingClientRect: (): ClientRect => ({
- bottom: config.source.clientY,
- height: 0,
- left: config.source.clientX,
- right: config.source.clientX,
- top: config.source.clientY,
- width: 0
- })
- };
+ const { x, y } = config.source;
const positionStrategy = this.overlay
.position()
- .connectedTo(
- new ElementRef(fakeElement),
- { originX: 'start', originY: 'bottom' },
- { overlayX: 'start', overlayY: 'top' }
- )
- .withFallbackPosition(
- { originX: 'start', originY: 'top' },
- { overlayX: 'start', overlayY: 'bottom' }
- )
- .withFallbackPosition(
- { originX: 'end', originY: 'top' },
- { overlayX: 'start', overlayY: 'top' }
- )
- .withFallbackPosition(
- { originX: 'start', originY: 'top' },
- { overlayX: 'end', overlayY: 'top' }
- )
- .withFallbackPosition(
- { originX: 'end', originY: 'center' },
- { overlayX: 'start', overlayY: 'center' }
- )
- .withFallbackPosition(
- { originX: 'start', originY: 'center' },
- { overlayX: 'end', overlayY: 'center' }
- );
+ .flexibleConnectedTo({ x, y })
+ .withPositions([
+ {
+ originX: 'end',
+ originY: 'bottom',
+ overlayX: 'end',
+ overlayY: 'top'
+ }
+ ]);
const overlayConfig = new OverlayConfig({
hasBackdrop: config.hasBackdrop,
backdropClass: config.backdropClass,
panelClass: config.panelClass,
scrollStrategy: this.overlay.scrollStrategies.close(),
- positionStrategy
+ positionStrategy,
+ direction: this.direction
});
return overlayConfig;
diff --git a/src/app/components/context-menu/direction.token.ts b/src/app/components/context-menu/direction.token.ts
new file mode 100644
index 000000000..07eca2e5c
--- /dev/null
+++ b/src/app/components/context-menu/direction.token.ts
@@ -0,0 +1,34 @@
+/*!
+ * @license
+ * Alfresco Example Content Application
+ *
+ * Copyright (C) 2005 - 2019 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 .
+ */
+
+import { InjectionToken } from '@angular/core';
+
+export const CONTEXT_MENU_DIRECTION = new InjectionToken(
+ 'CONTEXT_MENU_DIRECTION',
+ {
+ providedIn: 'root',
+ factory: () => 'ltr'
+ }
+);