mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-4579] Layout - RTL support (#4741)
* single contentAnimation state * fine tune contentAnimation state based on direction and position * tets * fix mock component inputs * use native direction attribute * update docs * pass direction to calculate sidenav layout * update test * fix unit test * remove dialogs directionality workaround * set document directionality service * remove context menu direction workaround * remove unneeded dependencies * remove direction style workaround * remove permission icon direction * remove sidenav layout direction attribute * update docs * update sidenav layout direction * test * remove document type * update test dependencies * clear storage before test * test * fix dl gap * try to fix Uncaught QuotaExceededError * fix QuotaExceededError * fix tests * fix tests
This commit is contained in:
committed by
Eugenio Romano
parent
f3e90298e6
commit
9cf6f5519c
@@ -1,4 +1,4 @@
|
|||||||
<adf-sidenav-layout [sidenavMin]="70" [sidenavMax]="220" [stepOver]="780" [hideSidenav]="hideSidenav" [direction]="direction"
|
<adf-sidenav-layout [sidenavMin]="70" [sidenavMax]="220" [stepOver]="780" [hideSidenav]="hideSidenav"
|
||||||
[expandedSidenav]="expandedSidenav" (expanded)="setState($event)" [position]="position">
|
[expandedSidenav]="expandedSidenav" (expanded)="setState($event)" [position]="position">
|
||||||
|
|
||||||
<adf-sidenav-layout-header>
|
<adf-sidenav-layout-header>
|
||||||
|
@@ -115,17 +115,12 @@ export class AppLayoutComponent implements OnInit {
|
|||||||
this.headerService.tooltip.subscribe((tooltip) => this.tooltip = tooltip);
|
this.headerService.tooltip.subscribe((tooltip) => this.tooltip = tooltip);
|
||||||
this.headerService.position.subscribe((position) => this.position = position);
|
this.headerService.position.subscribe((position) => this.position = position);
|
||||||
this.headerService.hideSidenav.subscribe((hideSidenav) => this.hideSidenav = hideSidenav);
|
this.headerService.hideSidenav.subscribe((hideSidenav) => this.hideSidenav = hideSidenav);
|
||||||
|
|
||||||
this.userPreferencesService.select('textOrientation').subscribe((textOrientation) => {
|
|
||||||
this.direction = textOrientation;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private userPreferences: UserPreferencesService,
|
private userPreferences: UserPreferencesService,
|
||||||
private config: AppConfigService,
|
private config: AppConfigService,
|
||||||
private alfrescoApiService: AlfrescoApiService,
|
private alfrescoApiService: AlfrescoApiService,
|
||||||
private userPreferencesService: UserPreferencesService,
|
|
||||||
private headerService: HeaderDataService) {
|
private headerService: HeaderDataService) {
|
||||||
if (this.alfrescoApiService.getInstance().isOauthConfiguration()) {
|
if (this.alfrescoApiService.getInstance().isOauthConfiguration()) {
|
||||||
this.enableRedirect = false;
|
this.enableRedirect = false;
|
||||||
|
@@ -69,7 +69,6 @@ sub-components (note the use of `<ng-template>` in the sub-components' body sect
|
|||||||
|
|
||||||
| Name | Type | Default value | Description |
|
| Name | Type | Default value | Description |
|
||||||
| ---- | ---- | ------------- | ----------- |
|
| ---- | ---- | ------------- | ----------- |
|
||||||
| direction | `string` | "ltr" | The direction of the layout. 'ltr' or 'rtl' |
|
|
||||||
| expandedSidenav | `boolean` | true | Should the navigation region be expanded initially? |
|
| expandedSidenav | `boolean` | true | Should the navigation region be expanded initially? |
|
||||||
| hideSidenav | `boolean` | false | Toggles showing/hiding the navigation region. |
|
| hideSidenav | `boolean` | false | Toggles showing/hiding the navigation region. |
|
||||||
| position | `string` | "start" | The side that the drawer is attached to. Possible values are 'start' and 'end'. |
|
| position | `string` | "start" | The side that the drawer is attached to. Possible values are 'start' and 'end'. |
|
||||||
|
@@ -41,7 +41,7 @@
|
|||||||
<adf-no-permission-template>
|
<adf-no-permission-template>
|
||||||
<ng-template>
|
<ng-template>
|
||||||
<div class="adf-no-permission__template" *ngIf="!customNoPermissionsTemplate">
|
<div class="adf-no-permission__template" *ngIf="!customNoPermissionsTemplate">
|
||||||
<mat-icon>ic_error</mat-icon>
|
<mat-icon>error</mat-icon>
|
||||||
<p class="adf-no-permission__template--text">{{ 'ADF-DOCUMENT-LIST.NO_PERMISSION' | translate }}</p>
|
<p class="adf-no-permission__template--text">{{ 'ADF-DOCUMENT-LIST.NO_PERMISSION' | translate }}</p>
|
||||||
</div>
|
</div>
|
||||||
<ng-content select="adf-custom-no-permission-template, no-permission-content"></ng-content>
|
<ng-content select="adf-custom-no-permission-template, no-permission-content"></ng-content>
|
||||||
|
@@ -41,7 +41,6 @@
|
|||||||
font-size: 52px;
|
font-size: 52px;
|
||||||
height: 52px;
|
height: 52px;
|
||||||
width: 52px;
|
width: 52px;
|
||||||
direction: rtl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&--text {
|
&--text {
|
||||||
|
@@ -20,12 +20,9 @@ import { Overlay } from '@angular/cdk/overlay';
|
|||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||||
import { ContextMenuOverlayService } from './context-menu-overlay.service';
|
import { ContextMenuOverlayService } from './context-menu-overlay.service';
|
||||||
import { UserPreferencesService } from '../services/user-preferences.service';
|
|
||||||
import { Injector } from '@angular/core';
|
import { Injector } from '@angular/core';
|
||||||
import { of } from 'rxjs';
|
|
||||||
|
|
||||||
describe('ContextMenuService', () => {
|
describe('ContextMenuService', () => {
|
||||||
let userPreferencesService: UserPreferencesService;
|
|
||||||
let contextMenuOverlayService: ContextMenuOverlayService;
|
let contextMenuOverlayService: ContextMenuOverlayService;
|
||||||
let overlay: Overlay;
|
let overlay: Overlay;
|
||||||
let injector: Injector;
|
let injector: Injector;
|
||||||
@@ -40,13 +37,9 @@ describe('ContextMenuService', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [NoopAnimationsModule, CoreTestingModule],
|
imports: [NoopAnimationsModule, CoreTestingModule],
|
||||||
providers: [
|
providers: [ Overlay ]
|
||||||
Overlay,
|
|
||||||
UserPreferencesService
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
userPreferencesService = TestBed.get(UserPreferencesService);
|
|
||||||
overlay = TestBed.get(Overlay);
|
overlay = TestBed.get(Overlay);
|
||||||
injector = TestBed.get(Injector);
|
injector = TestBed.get(Injector);
|
||||||
});
|
});
|
||||||
@@ -55,8 +48,7 @@ describe('ContextMenuService', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
contextMenuOverlayService = new ContextMenuOverlayService(
|
contextMenuOverlayService = new ContextMenuOverlayService(
|
||||||
injector,
|
injector,
|
||||||
overlay,
|
overlay
|
||||||
userPreferencesService
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -71,32 +63,5 @@ describe('ContextMenuService', () => {
|
|||||||
|
|
||||||
expect(document.querySelector('adf-context-menu')).not.toBe(null);
|
expect(document.querySelector('adf-context-menu')).not.toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Overlay direction', () => {
|
|
||||||
it('should have default LTR direction value', () => {
|
|
||||||
contextMenuOverlayService = new ContextMenuOverlayService(
|
|
||||||
injector,
|
|
||||||
overlay,
|
|
||||||
userPreferencesService
|
|
||||||
);
|
|
||||||
contextMenuOverlayService.open(overlayConfig);
|
|
||||||
|
|
||||||
expect(document.body.querySelector('div[dir="ltr"]')).not.toBe(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be created with textOrientation event value', () => {
|
|
||||||
spyOn(userPreferencesService, 'select').and.returnValue(of('rtl'));
|
|
||||||
|
|
||||||
contextMenuOverlayService = new ContextMenuOverlayService(
|
|
||||||
injector,
|
|
||||||
overlay,
|
|
||||||
userPreferencesService
|
|
||||||
);
|
|
||||||
contextMenuOverlayService.open(overlayConfig);
|
|
||||||
|
|
||||||
expect(document.body.querySelector('div[dir="rtl"]')).not.toBe(null);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -22,8 +22,6 @@ import { ContextMenuOverlayRef } from './context-menu-overlay';
|
|||||||
import { ContextMenuOverlayConfig } from './interfaces';
|
import { ContextMenuOverlayConfig } from './interfaces';
|
||||||
import { CONTEXT_MENU_DATA } from './context-menu.tokens';
|
import { CONTEXT_MENU_DATA } from './context-menu.tokens';
|
||||||
import { ContextMenuListComponent } from './context-menu-list.component';
|
import { ContextMenuListComponent } from './context-menu-list.component';
|
||||||
import { UserPreferencesService } from '../services/user-preferences.service';
|
|
||||||
import { Direction } from '@angular/cdk/bidi';
|
|
||||||
|
|
||||||
const DEFAULT_CONFIG: ContextMenuOverlayConfig = {
|
const DEFAULT_CONFIG: ContextMenuOverlayConfig = {
|
||||||
panelClass: 'cdk-overlay-pane',
|
panelClass: 'cdk-overlay-pane',
|
||||||
@@ -35,17 +33,11 @@ const DEFAULT_CONFIG: ContextMenuOverlayConfig = {
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class ContextMenuOverlayService {
|
export class ContextMenuOverlayService {
|
||||||
private direction: Direction;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private injector: Injector,
|
private injector: Injector,
|
||||||
private overlay: Overlay,
|
private overlay: Overlay
|
||||||
private userPreferencesService: UserPreferencesService
|
) {}
|
||||||
) {
|
|
||||||
this.userPreferencesService.select('textOrientation').subscribe((textOrientation) => {
|
|
||||||
this.direction = textOrientation;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
open(config: ContextMenuOverlayConfig): ContextMenuOverlayRef {
|
open(config: ContextMenuOverlayConfig): ContextMenuOverlayRef {
|
||||||
const overlayConfig = { ...DEFAULT_CONFIG, ...config };
|
const overlayConfig = { ...DEFAULT_CONFIG, ...config };
|
||||||
@@ -134,8 +126,7 @@ export class ContextMenuOverlayService {
|
|||||||
backdropClass: config.backdropClass,
|
backdropClass: config.backdropClass,
|
||||||
panelClass: config.panelClass,
|
panelClass: config.panelClass,
|
||||||
scrollStrategy: this.overlay.scrollStrategies.close(),
|
scrollStrategy: this.overlay.scrollStrategies.close(),
|
||||||
positionStrategy,
|
positionStrategy
|
||||||
direction: this.direction
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return overlayConfig;
|
return overlayConfig;
|
||||||
|
@@ -53,8 +53,8 @@ import { SortingPickerModule } from './sorting-picker/sorting-picker.module';
|
|||||||
import { IconModule } from './icon/icon.module';
|
import { IconModule } from './icon/icon.module';
|
||||||
import { TranslateLoaderService } from './services/translate-loader.service';
|
import { TranslateLoaderService } from './services/translate-loader.service';
|
||||||
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
||||||
import { dialogConfigFactory } from './services/dialog-config-factory';
|
import { directionalityConfigFactory } from './services/directionality-config-factory';
|
||||||
import { DialogConfigService } from './services/dialog-config.service';
|
import { DirectionalityConfigService } from './services/directionality-config.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -140,8 +140,8 @@ export class CoreModule {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
useFactory: dialogConfigFactory,
|
useFactory: directionalityConfigFactory,
|
||||||
deps: [ DialogConfigService],
|
deps: [ DirectionalityConfigService ],
|
||||||
multi: true
|
multi: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="adf-rtl-container-alignment adf-container-full-width" [@contentAnimationLeft]="getContentAnimationStateLeft()" [@contentAnimationRight]="getContentAnimationStateRight()">
|
<div class="adf-container-full-width" [@contentAnimationLeft]="getContentAnimationState()">
|
||||||
<ng-content select="[app-layout-content]"></ng-content>
|
<ng-content select="[app-layout-content]"></ng-content>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -9,14 +9,9 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
[dir='rtl'] .adf-rtl-container-alignment {
|
|
||||||
margin-left: 10px!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.adf-container-full-width {
|
.adf-container-full-width {
|
||||||
width: inherit;
|
width: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* query for Microsoft IE 11*/
|
/* query for Microsoft IE 11*/
|
||||||
@media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
|
@media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
|
||||||
.adf-container-full-width {
|
.adf-container-full-width {
|
||||||
@@ -24,6 +19,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mat-sidenav-content.mat-drawer-content.mat-sidenav-content {
|
||||||
|
margin: 0!important;
|
||||||
|
}
|
||||||
|
|
||||||
.adf-sidenav--hidden {
|
.adf-sidenav--hidden {
|
||||||
visibility: hidden !important;
|
visibility: hidden !important;
|
||||||
width: 0 !important;
|
width: 0 !important;
|
||||||
|
@@ -0,0 +1,210 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { LayoutContainerComponent } from './layout-container.component';
|
||||||
|
import { SimpleChange } from '@angular/core';
|
||||||
|
|
||||||
|
describe('LayoutContainerComponent', () => {
|
||||||
|
let layoutContainerComponent: LayoutContainerComponent;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
layoutContainerComponent = new LayoutContainerComponent();
|
||||||
|
layoutContainerComponent.sidenavMin = 70;
|
||||||
|
layoutContainerComponent.sidenavMax = 200;
|
||||||
|
layoutContainerComponent.mediaQueryList = {
|
||||||
|
matches: false,
|
||||||
|
addListener: () => {},
|
||||||
|
removeListener: () => {}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('OnInit', () => {
|
||||||
|
describe('Sidenav expanded', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
layoutContainerComponent.expandedSidenav = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Sidenav [start] position', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
layoutContainerComponent.position = 'start';
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-left` equal to sidenavMax when direction is `ltr`', () => {
|
||||||
|
layoutContainerComponent.direction = 'ltr';
|
||||||
|
layoutContainerComponent.ngOnInit();
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState).toEqual({
|
||||||
|
value: 'compact', params: { 'margin-left': layoutContainerComponent.sidenavMax}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-right` equal to sidenavMax when direction is `rtl`', () => {
|
||||||
|
layoutContainerComponent.direction = 'rtl';
|
||||||
|
layoutContainerComponent.ngOnInit();
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState).toEqual({
|
||||||
|
value: 'compact', params: { 'margin-right': layoutContainerComponent.sidenavMax}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Sidenav [end] position', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
layoutContainerComponent.position = 'end';
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-right` equal to sidenavMax when direction is `ltr`', () => {
|
||||||
|
layoutContainerComponent.direction = 'ltr';
|
||||||
|
layoutContainerComponent.ngOnInit();
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState).toEqual({
|
||||||
|
value: 'compact', params: { 'margin-right': layoutContainerComponent.sidenavMax}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-left` equal to sidenavMax when direction is `rtl`', () => {
|
||||||
|
layoutContainerComponent.direction = 'rtl';
|
||||||
|
layoutContainerComponent.ngOnInit();
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState).toEqual({
|
||||||
|
value: 'compact', params: { 'margin-left': layoutContainerComponent.sidenavMax}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Sidenav compact', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
layoutContainerComponent.expandedSidenav = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Sidenav [start] position', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
layoutContainerComponent.position = 'start';
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-left` equal to sidenavMin when direction is `ltr`', () => {
|
||||||
|
layoutContainerComponent.direction = 'ltr';
|
||||||
|
layoutContainerComponent.ngOnInit();
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState).toEqual({
|
||||||
|
value: 'expanded', params: { 'margin-left': layoutContainerComponent.sidenavMin}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-right` equal to sidenavMin when direction is `rtl`', () => {
|
||||||
|
layoutContainerComponent.direction = 'rtl';
|
||||||
|
layoutContainerComponent.ngOnInit();
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState).toEqual({
|
||||||
|
value: 'expanded', params: { 'margin-right': layoutContainerComponent.sidenavMin}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Sidenav [end] position', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
layoutContainerComponent.position = 'end';
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-right` equal to sidenavMin when direction is `ltr`', () => {
|
||||||
|
layoutContainerComponent.direction = 'ltr';
|
||||||
|
layoutContainerComponent.ngOnInit();
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState).toEqual({
|
||||||
|
value: 'expanded', params: { 'margin-right': layoutContainerComponent.sidenavMin}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-left` equal to sidenavMin when direction is `rtl`', () => {
|
||||||
|
layoutContainerComponent.direction = 'rtl';
|
||||||
|
layoutContainerComponent.ngOnInit();
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState).toEqual({
|
||||||
|
value: 'expanded', params: { 'margin-left': layoutContainerComponent.sidenavMin}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('OnChange direction', () => {
|
||||||
|
describe('Sidenav [start] position', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
layoutContainerComponent.position = 'start';
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-left` when current direction is `ltr`', () => {
|
||||||
|
layoutContainerComponent.direction = 'ltr';
|
||||||
|
layoutContainerComponent.ngOnChanges({ direction: new SimpleChange('', '', false) });
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState.params['margin-left']).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-right` when current direction is `rtl`', () => {
|
||||||
|
layoutContainerComponent.direction = 'rtl';
|
||||||
|
layoutContainerComponent.ngOnChanges({ direction: new SimpleChange('', '', false) });
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState.params['margin-right']).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Sidenav [end] position', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
layoutContainerComponent.position = 'end';
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-right` when current direction is `ltr`', () => {
|
||||||
|
layoutContainerComponent.direction = 'ltr';
|
||||||
|
layoutContainerComponent.ngOnChanges({ direction: new SimpleChange('', '', false) });
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState.params['margin-right']).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set `margin-left` when current direction is `rtl`', () => {
|
||||||
|
layoutContainerComponent.direction = 'rtl';
|
||||||
|
layoutContainerComponent.ngOnChanges({ direction: new SimpleChange('', '', false) });
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.contentAnimationState.params['margin-left']).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('toggleMenu()', () => {
|
||||||
|
it('should switch to sidenav to compact state', () => {
|
||||||
|
layoutContainerComponent.expandedSidenav = true;
|
||||||
|
layoutContainerComponent.ngOnInit();
|
||||||
|
|
||||||
|
layoutContainerComponent.toggleMenu();
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.sidenavAnimationState).toEqual({
|
||||||
|
value: 'compact', params: { width: layoutContainerComponent.sidenavMin }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should switch to sidenav to expanded state', () => {
|
||||||
|
layoutContainerComponent.expandedSidenav = false;
|
||||||
|
layoutContainerComponent.ngOnInit();
|
||||||
|
|
||||||
|
layoutContainerComponent.toggleMenu();
|
||||||
|
|
||||||
|
expect(layoutContainerComponent.sidenavAnimationState).toEqual({
|
||||||
|
value: 'expanded', params: { width: layoutContainerComponent.sidenavMax }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -15,18 +15,19 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, Input, ViewChild, OnInit, OnDestroy, ViewEncapsulation } from '@angular/core';
|
import { Component, Input, ViewChild, OnInit, OnDestroy, ViewEncapsulation, OnChanges } from '@angular/core';
|
||||||
import { MatSidenav } from '@angular/material';
|
import { MatSidenav } from '@angular/material';
|
||||||
import { sidenavAnimation, contentAnimationLeft, contentAnimationRight } from '../../helpers/animations';
|
import { sidenavAnimation, contentAnimation } from '../../helpers/animations';
|
||||||
|
import { Direction } from '@angular/cdk/bidi';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-layout-container',
|
selector: 'adf-layout-container',
|
||||||
templateUrl: './layout-container.component.html',
|
templateUrl: './layout-container.component.html',
|
||||||
styleUrls: ['./layout-container.component.scss'],
|
styleUrls: ['./layout-container.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
animations: [sidenavAnimation, contentAnimationLeft, contentAnimationRight]
|
animations: [sidenavAnimation, contentAnimation]
|
||||||
})
|
})
|
||||||
export class LayoutContainerComponent implements OnInit, OnDestroy {
|
export class LayoutContainerComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
@Input() sidenavMin: number;
|
@Input() sidenavMin: number;
|
||||||
@Input() sidenavMax: number;
|
@Input() sidenavMax: number;
|
||||||
|
|
||||||
@@ -39,6 +40,9 @@ export class LayoutContainerComponent implements OnInit, OnDestroy {
|
|||||||
/** The side that the drawer is attached to 'start' | 'end' page */
|
/** The side that the drawer is attached to 'start' | 'end' page */
|
||||||
@Input() position = 'start';
|
@Input() position = 'start';
|
||||||
|
|
||||||
|
/** Layout text orientation 'ltr' | 'rtl' */
|
||||||
|
@Input() direction: Direction = 'ltr';
|
||||||
|
|
||||||
@ViewChild(MatSidenav) sidenav: MatSidenav;
|
@ViewChild(MatSidenav) sidenav: MatSidenav;
|
||||||
|
|
||||||
sidenavAnimationState: any;
|
sidenavAnimationState: any;
|
||||||
@@ -56,9 +60,7 @@ export class LayoutContainerComponent implements OnInit, OnDestroy {
|
|||||||
this.SIDENAV_STATES.EXPANDED = { value: 'expanded', params: { width: this.sidenavMax } };
|
this.SIDENAV_STATES.EXPANDED = { value: 'expanded', params: { width: this.sidenavMax } };
|
||||||
this.SIDENAV_STATES.COMPACT = { value: 'compact', params: { width: this.sidenavMin } };
|
this.SIDENAV_STATES.COMPACT = { value: 'compact', params: { width: this.sidenavMin } };
|
||||||
|
|
||||||
this.CONTENT_STATES.MOBILE = { value: 'expanded', params: { margin: 0 } };
|
this.CONTENT_STATES.MOBILE = { value: 'expanded' };
|
||||||
this.CONTENT_STATES.EXPANDED = { value: 'expanded', params: { margin: this.sidenavMin } };
|
|
||||||
this.CONTENT_STATES.COMPACT = { value: 'compact', params: { margin: this.sidenavMax } };
|
|
||||||
|
|
||||||
this.mediaQueryList.addListener(this.onMediaQueryChange);
|
this.mediaQueryList.addListener(this.onMediaQueryChange);
|
||||||
|
|
||||||
@@ -67,10 +69,10 @@ export class LayoutContainerComponent implements OnInit, OnDestroy {
|
|||||||
this.contentAnimationState = this.CONTENT_STATES.MOBILE;
|
this.contentAnimationState = this.CONTENT_STATES.MOBILE;
|
||||||
} else if (this.expandedSidenav) {
|
} else if (this.expandedSidenav) {
|
||||||
this.sidenavAnimationState = this.SIDENAV_STATES.EXPANDED;
|
this.sidenavAnimationState = this.SIDENAV_STATES.EXPANDED;
|
||||||
this.contentAnimationState = this.CONTENT_STATES.COMPACT;
|
this.contentAnimationState = this.toggledContentAnimation;
|
||||||
} else {
|
} else {
|
||||||
this.sidenavAnimationState = this.SIDENAV_STATES.COMPACT;
|
this.sidenavAnimationState = this.SIDENAV_STATES.COMPACT;
|
||||||
this.contentAnimationState = this.CONTENT_STATES.EXPANDED;
|
this.contentAnimationState = this.toggledContentAnimation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +80,12 @@ export class LayoutContainerComponent implements OnInit, OnDestroy {
|
|||||||
this.mediaQueryList.removeListener(this.onMediaQueryChange);
|
this.mediaQueryList.removeListener(this.onMediaQueryChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes) {
|
||||||
|
if (changes && changes.direction) {
|
||||||
|
this.contentAnimationState = this.toggledContentAnimation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
toggleMenu(): void {
|
toggleMenu(): void {
|
||||||
if (this.isMobileScreenSize) {
|
if (this.isMobileScreenSize) {
|
||||||
this.sidenav.toggle();
|
this.sidenav.toggle();
|
||||||
@@ -87,6 +95,14 @@ export class LayoutContainerComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isMobileScreenSize(): boolean {
|
||||||
|
return this.mediaQueryList.matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
getContentAnimationState() {
|
||||||
|
return this.contentAnimationState;
|
||||||
|
}
|
||||||
|
|
||||||
private get toggledSidenavAnimation() {
|
private get toggledSidenavAnimation() {
|
||||||
return this.sidenavAnimationState === this.SIDENAV_STATES.EXPANDED
|
return this.sidenavAnimationState === this.SIDENAV_STATES.EXPANDED
|
||||||
? this.SIDENAV_STATES.COMPACT
|
? this.SIDENAV_STATES.COMPACT
|
||||||
@@ -99,35 +115,43 @@ export class LayoutContainerComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.sidenavAnimationState === this.SIDENAV_STATES.EXPANDED) {
|
if (this.sidenavAnimationState === this.SIDENAV_STATES.EXPANDED) {
|
||||||
return this.CONTENT_STATES.COMPACT;
|
if (this.position === 'start' && this.direction === 'ltr') {
|
||||||
} else {
|
return { value: 'compact', params: { 'margin-left': this.sidenavMax } };
|
||||||
return this.CONTENT_STATES.EXPANDED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get isMobileScreenSize(): boolean {
|
if (this.position === 'start' && this.direction === 'rtl') {
|
||||||
return this.mediaQueryList.matches;
|
return { value: 'compact', params: { 'margin-right': this.sidenavMax } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.position === 'end' && this.direction === 'ltr') {
|
||||||
|
return { value: 'compact', params: { 'margin-right': this.sidenavMax } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.position === 'end' && this.direction === 'rtl') {
|
||||||
|
return { value: 'compact', params: { 'margin-left': this.sidenavMax } };
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (this.position === 'start' && this.direction === 'ltr') {
|
||||||
|
return { value: 'expanded', params: { 'margin-left': this.sidenavMin } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.position === 'start' && this.direction === 'rtl') {
|
||||||
|
return { value: 'expanded', params: { 'margin-right': this.sidenavMin } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.position === 'end' && this.direction === 'ltr') {
|
||||||
|
return { value: 'expanded', params: { 'margin-right': this.sidenavMin } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.position === 'end' && this.direction === 'rtl') {
|
||||||
|
return { value: 'expanded', params: { 'margin-left': this.sidenavMin } };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMediaQueryChange() {
|
private onMediaQueryChange() {
|
||||||
this.sidenavAnimationState = this.SIDENAV_STATES.EXPANDED;
|
this.sidenavAnimationState = this.SIDENAV_STATES.EXPANDED;
|
||||||
this.contentAnimationState = this.toggledContentAnimation;
|
this.contentAnimationState = this.toggledContentAnimation;
|
||||||
}
|
}
|
||||||
|
|
||||||
getContentAnimationStateLeft() {
|
|
||||||
if (this.position === 'start') {
|
|
||||||
return this.contentAnimationState;
|
|
||||||
} else {
|
|
||||||
return { value: 'compact', params: { width: this.sidenavMin } };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getContentAnimationStateRight() {
|
|
||||||
if (this.position === 'end') {
|
|
||||||
return this.contentAnimationState;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return { value: 'compact', params: { width: this.sidenavMin } };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
<div [dir]="direction" class="adf-sidenav-layout-full-space">
|
<div class="adf-sidenav-layout-full-space">
|
||||||
<ng-container *ngIf="!isHeaderInside">
|
<ng-container *ngIf="!isHeaderInside">
|
||||||
<ng-container class="adf-sidenav-layout-outer-header"
|
<ng-container class="adf-sidenav-layout-outer-header"
|
||||||
*ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container>
|
*ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<adf-layout-container #container
|
<adf-layout-container #container
|
||||||
|
[direction]="dir"
|
||||||
[position]="position"
|
[position]="position"
|
||||||
[sidenavMin]="sidenavMin"
|
[sidenavMin]="sidenavMin"
|
||||||
[sidenavMax]="sidenavMax"
|
[sidenavMax]="sidenavMax"
|
||||||
|
@@ -27,7 +27,10 @@ import { MaterialModule } from '../../../material.module';
|
|||||||
import { SidenavLayoutContentDirective } from '../../directives/sidenav-layout-content.directive';
|
import { SidenavLayoutContentDirective } from '../../directives/sidenav-layout-content.directive';
|
||||||
import { SidenavLayoutHeaderDirective } from '../../directives/sidenav-layout-header.directive';
|
import { SidenavLayoutHeaderDirective } from '../../directives/sidenav-layout-header.directive';
|
||||||
import { SidenavLayoutNavigationDirective } from '../../directives/sidenav-layout-navigation.directive';
|
import { SidenavLayoutNavigationDirective } from '../../directives/sidenav-layout-navigation.directive';
|
||||||
|
import { UserPreferencesService } from '../../../services/user-preferences.service';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Direction } from '@angular/cdk/bidi';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-layout-container',
|
selector: 'adf-layout-container',
|
||||||
@@ -39,6 +42,7 @@ export class DummyLayoutContainerComponent {
|
|||||||
@Input() sidenavMin: number;
|
@Input() sidenavMin: number;
|
||||||
@Input() sidenavMax: number;
|
@Input() sidenavMax: number;
|
||||||
@Input() position: string;
|
@Input() position: string;
|
||||||
|
@Input() direction: Direction;
|
||||||
@Input() mediaQueryList: MediaQueryList;
|
@Input() mediaQueryList: MediaQueryList;
|
||||||
@Input() hideSidenav: boolean;
|
@Input() hideSidenav: boolean;
|
||||||
@Input() expandedSidenav: boolean;
|
@Input() expandedSidenav: boolean;
|
||||||
@@ -67,7 +71,8 @@ describe('SidenavLayoutComponent', () => {
|
|||||||
SidenavLayoutNavigationDirective
|
SidenavLayoutNavigationDirective
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
MediaMatcher
|
MediaMatcher,
|
||||||
|
{ provide: UserPreferencesService, useValue: { select: () => of()} }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@@ -29,10 +29,13 @@ import {
|
|||||||
ViewEncapsulation
|
ViewEncapsulation
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { MediaMatcher } from '@angular/cdk/layout';
|
import { MediaMatcher } from '@angular/cdk/layout';
|
||||||
|
import { UserPreferencesService } from '../../../services/user-preferences.service';
|
||||||
import { SidenavLayoutContentDirective } from '../../directives/sidenav-layout-content.directive';
|
import { SidenavLayoutContentDirective } from '../../directives/sidenav-layout-content.directive';
|
||||||
import { SidenavLayoutHeaderDirective } from '../../directives/sidenav-layout-header.directive';
|
import { SidenavLayoutHeaderDirective } from '../../directives/sidenav-layout-header.directive';
|
||||||
import { SidenavLayoutNavigationDirective } from '../../directives/sidenav-layout-navigation.directive';
|
import { SidenavLayoutNavigationDirective } from '../../directives/sidenav-layout-navigation.directive';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||||
|
import { Direction } from '@angular/cdk/bidi';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-sidenav-layout',
|
selector: 'adf-sidenav-layout',
|
||||||
@@ -45,7 +48,7 @@ export class SidenavLayoutComponent implements OnInit, AfterViewInit, OnDestroy
|
|||||||
static STEP_OVER = 600;
|
static STEP_OVER = 600;
|
||||||
|
|
||||||
/** The direction of the layout. 'ltr' or 'rtl' */
|
/** The direction of the layout. 'ltr' or 'rtl' */
|
||||||
@Input() direction = 'ltr';
|
dir = 'ltr';
|
||||||
|
|
||||||
/** The side that the drawer is attached to. Possible values are 'start' and 'end'. */
|
/** The side that the drawer is attached to. Possible values are 'start' and 'end'. */
|
||||||
@Input() position = 'start';
|
@Input() position = 'start';
|
||||||
@@ -86,7 +89,9 @@ export class SidenavLayoutComponent implements OnInit, AfterViewInit, OnDestroy
|
|||||||
isMenuMinimized: () => this.isMenuMinimized
|
isMenuMinimized: () => this.isMenuMinimized
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(private mediaMatcher: MediaMatcher) {
|
private onDestroy$ = new Subject<boolean>();
|
||||||
|
|
||||||
|
constructor(private mediaMatcher: MediaMatcher, private userPreferencesService: UserPreferencesService ) {
|
||||||
this.onMediaQueryChange = this.onMediaQueryChange.bind(this);
|
this.onMediaQueryChange = this.onMediaQueryChange.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +106,13 @@ export class SidenavLayoutComponent implements OnInit, AfterViewInit, OnDestroy
|
|||||||
|
|
||||||
this.mediaQueryList = this.mediaMatcher.matchMedia(`(max-width: ${stepOver}px)`);
|
this.mediaQueryList = this.mediaMatcher.matchMedia(`(max-width: ${stepOver}px)`);
|
||||||
this.mediaQueryList.addListener(this.onMediaQueryChange);
|
this.mediaQueryList.addListener(this.onMediaQueryChange);
|
||||||
|
|
||||||
|
this.userPreferencesService
|
||||||
|
.select('textOrientation')
|
||||||
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
.subscribe((direction: Direction) => {
|
||||||
|
this.dir = direction;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
@@ -109,6 +121,8 @@ export class SidenavLayoutComponent implements OnInit, AfterViewInit, OnDestroy
|
|||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.mediaQueryList.removeListener(this.onMediaQueryChange);
|
this.mediaQueryList.removeListener(this.onMediaQueryChange);
|
||||||
|
this.onDestroy$.next(true);
|
||||||
|
this.onDestroy$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleMenu() {
|
toggleMenu() {
|
||||||
|
@@ -23,14 +23,14 @@ export const sidenavAnimation: AnimationTriggerMetadata = trigger('sidenavAnimat
|
|||||||
transition('compact <=> expanded', animate('0.4s cubic-bezier(0.25, 0.8, 0.25, 1)'))
|
transition('compact <=> expanded', animate('0.4s cubic-bezier(0.25, 0.8, 0.25, 1)'))
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const contentAnimationLeft: AnimationTriggerMetadata = trigger('contentAnimationLeft', [
|
export const contentAnimation: AnimationTriggerMetadata = trigger('contentAnimationLeft', [
|
||||||
state('expanded', style({ 'margin-left': '{{ margin }}px' }), { params : { margin: 0 } }),
|
state('expanded', style({
|
||||||
state('compact', style({'margin-left': '{{ margin }}px' }), { params : { margin: 0 } }),
|
'margin-left': '{{ margin-left }}px',
|
||||||
transition('expanded <=> compact', animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)'))
|
'margin-right': '{{ margin-right }}px'
|
||||||
]);
|
}), { params: { 'margin-left': 0, 'margin-right': 0 } }),
|
||||||
|
state('compact', style({
|
||||||
export const contentAnimationRight: AnimationTriggerMetadata = trigger('contentAnimationRight', [
|
'margin-left': '{{ margin-left }}px',
|
||||||
state('expanded', style({ 'margin-right': '{{ margin }}px' }), { params : { margin: 0 } }),
|
'margin-right': '{{ margin-right }}px'
|
||||||
state('compact', style({'margin-right': '{{ margin }}px' }), { params : { margin: 0 } }),
|
}), { params: { 'margin-left': 0, 'margin-right': 0 } }),
|
||||||
transition('expanded <=> compact', animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)'))
|
transition('expanded <=> compact', animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)'))
|
||||||
]);
|
]);
|
||||||
|
@@ -24,7 +24,7 @@ import {
|
|||||||
MatInputModule, MatListModule, MatNativeDateModule, MatOptionModule, MatProgressSpinnerModule, MatRadioModule,
|
MatInputModule, MatListModule, MatNativeDateModule, MatOptionModule, MatProgressSpinnerModule, MatRadioModule,
|
||||||
MatRippleModule, MatSelectModule, MatSlideToggleModule, MatTableModule, MatTabsModule,
|
MatRippleModule, MatSelectModule, MatSlideToggleModule, MatTableModule, MatTabsModule,
|
||||||
MatMenuModule, MatProgressBarModule, MatSidenavModule, MatSnackBarModule, MatToolbarModule,
|
MatMenuModule, MatProgressBarModule, MatSidenavModule, MatSnackBarModule, MatToolbarModule,
|
||||||
MatTooltipModule, MatExpansionModule, MAT_DIALOG_DEFAULT_OPTIONS, MatDialogConfig
|
MatTooltipModule, MatExpansionModule
|
||||||
} from '@angular/material';
|
} from '@angular/material';
|
||||||
|
|
||||||
export function modules() {
|
export function modules() {
|
||||||
@@ -40,13 +40,6 @@ export function modules() {
|
|||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: modules(),
|
imports: modules(),
|
||||||
providers: [
|
|
||||||
MatDialogConfig,
|
|
||||||
{
|
|
||||||
provide: MAT_DIALOG_DEFAULT_OPTIONS,
|
|
||||||
useValue: MAT_DIALOG_DEFAULT_OPTIONS
|
|
||||||
}
|
|
||||||
],
|
|
||||||
exports: modules()
|
exports: modules()
|
||||||
})
|
})
|
||||||
export class MaterialModule {}
|
export class MaterialModule {}
|
||||||
|
@@ -47,6 +47,9 @@ describe('AuthenticationService', () => {
|
|||||||
|
|
||||||
jasmine.Ajax.install();
|
jasmine.Ajax.install();
|
||||||
appConfigService = TestBed.get(AppConfigService);
|
appConfigService = TestBed.get(AppConfigService);
|
||||||
|
appConfigService.config.pagination = {
|
||||||
|
supportedPageSizes: []
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@@ -1,52 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright 2019 Alfresco Software, Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* spellchecker: disable */
|
|
||||||
import { Injectable, Inject } from '@angular/core';
|
|
||||||
import { MAT_DIALOG_DEFAULT_OPTIONS, MatDialogConfig } from '@angular/material/dialog';
|
|
||||||
import { Direction } from '@angular/cdk/bidi';
|
|
||||||
import { UserPreferencesService } from '../services/user-preferences.service';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root'
|
|
||||||
})
|
|
||||||
export class DialogConfigService {
|
|
||||||
constructor(
|
|
||||||
@Inject(MAT_DIALOG_DEFAULT_OPTIONS) private defaultOptions: MatDialogConfig,
|
|
||||||
private matDialogConfig: MatDialogConfig,
|
|
||||||
private userPreferencesService: UserPreferencesService
|
|
||||||
) {
|
|
||||||
this.userPreferencesService
|
|
||||||
.select('textOrientation')
|
|
||||||
.subscribe((direction: Direction) => {
|
|
||||||
this.changeDirection(direction);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loadDefaults() {
|
|
||||||
Object.assign(this.defaultOptions, this.matDialogConfig, <MatDialogConfig> {
|
|
||||||
autoFocus: true,
|
|
||||||
closeOnNavigation: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private changeDirection(direction: Direction) {
|
|
||||||
Object.assign(this.defaultOptions, this.matDialogConfig, <MatDialogConfig> {
|
|
||||||
direction
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@@ -14,10 +14,9 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { DialogConfigService } from '../services/dialog-config.service';
|
|
||||||
|
|
||||||
export function dialogConfigFactory(
|
import { DirectionalityConfigService } from '../services/directionality-config.service';
|
||||||
dialogConfigService: DialogConfigService
|
|
||||||
): Function {
|
export function directionalityConfigFactory(
|
||||||
return () => dialogConfigService.loadDefaults();
|
directionalityConfigService: DirectionalityConfigService
|
||||||
}
|
): Function { return () => directionalityConfigService; }
|
@@ -16,54 +16,33 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { DialogConfigService } from './dialog-config.service';
|
import { DirectionalityConfigService } from './directionality-config.service';
|
||||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||||
import { setupTestBed } from '../testing/setupTestBed';
|
import { setupTestBed } from '../testing/setupTestBed';
|
||||||
import { MAT_DIALOG_DEFAULT_OPTIONS, MatDialogConfig } from '@angular/material/dialog';
|
|
||||||
import { UserPreferencesService } from './user-preferences.service';
|
import { UserPreferencesService } from './user-preferences.service';
|
||||||
import { Direction } from '@angular/cdk/bidi';
|
|
||||||
|
|
||||||
describe('DialogConfigService', () => {
|
describe('DirectionalityConfigService', () => {
|
||||||
let matDialogConfig: MatDialogConfig;
|
|
||||||
let userPreferencesService: UserPreferencesService;
|
let userPreferencesService: UserPreferencesService;
|
||||||
let matDialogGlobalOptions: MatDialogConfig;
|
|
||||||
|
|
||||||
setupTestBed({
|
setupTestBed({
|
||||||
imports: [CoreTestingModule],
|
imports: [CoreTestingModule],
|
||||||
providers: [
|
providers: [
|
||||||
DialogConfigService,
|
DirectionalityConfigService,
|
||||||
UserPreferencesService,
|
UserPreferencesService
|
||||||
{
|
|
||||||
provide: MAT_DIALOG_DEFAULT_OPTIONS,
|
|
||||||
useValue: MAT_DIALOG_DEFAULT_OPTIONS
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
userPreferencesService = TestBed.get(UserPreferencesService);
|
userPreferencesService = TestBed.get(UserPreferencesService);
|
||||||
matDialogConfig = TestBed.get(MatDialogConfig);
|
|
||||||
matDialogGlobalOptions = TestBed.get(MAT_DIALOG_DEFAULT_OPTIONS);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load custom defaults', () => {
|
it('should set document direction on textOrientation event to `rtl`', () => {
|
||||||
expect(matDialogConfig).toEqual(jasmine.objectContaining({
|
|
||||||
autoFocus: true,
|
|
||||||
closeOnNavigation: true
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set dialog direction option on textOrientation event', () => {
|
|
||||||
userPreferencesService.set('textOrientation', 'rtl');
|
userPreferencesService.set('textOrientation', 'rtl');
|
||||||
|
expect(document.body.getAttribute('dir')).toBe('rtl');
|
||||||
|
});
|
||||||
|
|
||||||
expect(matDialogGlobalOptions).toEqual(jasmine.objectContaining({
|
it('should set document direction on textOrientation event to `ltr`', () => {
|
||||||
direction: <Direction> 'rtl'
|
|
||||||
}));
|
|
||||||
|
|
||||||
userPreferencesService.set('textOrientation', 'ltr');
|
userPreferencesService.set('textOrientation', 'ltr');
|
||||||
|
expect(document.body.getAttribute('dir')).toBe('ltr');
|
||||||
expect(matDialogGlobalOptions).toEqual(jasmine.objectContaining({
|
|
||||||
direction: <Direction> 'ltr'
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
42
lib/core/services/directionality-config.service.ts
Normal file
42
lib/core/services/directionality-config.service.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Injectable, Inject, Renderer2, RendererFactory2 } from '@angular/core';
|
||||||
|
import { Directionality, Direction } from '@angular/cdk/bidi';
|
||||||
|
import { UserPreferencesService } from '../services/user-preferences.service';
|
||||||
|
import { DOCUMENT } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class DirectionalityConfigService {
|
||||||
|
constructor(
|
||||||
|
@Inject(DOCUMENT) private document: any,
|
||||||
|
private rendererFactory: RendererFactory2,
|
||||||
|
private userPreferencesService: UserPreferencesService,
|
||||||
|
private directionality: Directionality
|
||||||
|
) {
|
||||||
|
const renderer: Renderer2 = this.rendererFactory.createRenderer(null, null);
|
||||||
|
|
||||||
|
this.userPreferencesService
|
||||||
|
.select('textOrientation')
|
||||||
|
.subscribe((direction: Direction) => {
|
||||||
|
renderer.setAttribute(this.document.body, 'dir', direction);
|
||||||
|
(<any> this.directionality).value = direction;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -66,9 +66,8 @@ describe('StorageService', () => {
|
|||||||
|
|
||||||
appConfig.load().then(() => {
|
appConfig.load().then(() => {
|
||||||
storage.setItem(key, value);
|
storage.setItem(key, value);
|
||||||
const storageKey = localStorage.key(0);
|
expect(localStorage.hasOwnProperty('ADF_APP_' + key)).not.toBe(null);
|
||||||
expect(storageKey).toBe('ADF_APP_' + key);
|
expect(localStorage.getItem('ADF_APP_' + key)).toBe(value);
|
||||||
expect(localStorage.getItem(storageKey)).toBe(value);
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -79,10 +78,8 @@ describe('StorageService', () => {
|
|||||||
|
|
||||||
appConfig.load().then(() => {
|
appConfig.load().then(() => {
|
||||||
storage.setItem(key, value);
|
storage.setItem(key, value);
|
||||||
|
expect(localStorage.hasOwnProperty(key)).not.toBe(null);
|
||||||
const storageKey = localStorage.key(0);
|
expect(localStorage.getItem(key)).toBe(value);
|
||||||
expect(storageKey).toBe(key);
|
|
||||||
expect(localStorage.getItem(storageKey)).toBe(value);
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -53,6 +53,10 @@ describe('UserPreferencesService', () => {
|
|||||||
translate = TestBed.get(TranslateService);
|
translate = TestBed.get(TranslateService);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
storage.clear();
|
||||||
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
if (changeDisposable) {
|
if (changeDisposable) {
|
||||||
changeDisposable.unsubscribe();
|
changeDisposable.unsubscribe();
|
||||||
|
@@ -28,7 +28,6 @@ import { TranslationMock } from '../mock/translation.service.mock';
|
|||||||
import { DatePipe } from '@angular/common';
|
import { DatePipe } from '@angular/common';
|
||||||
import { CookieService } from '../services/cookie.service';
|
import { CookieService } from '../services/cookie.service';
|
||||||
import { CookieServiceMock } from '../mock/cookie.service.mock';
|
import { CookieServiceMock } from '../mock/cookie.service.mock';
|
||||||
import { DialogConfigService } from 'core/services/dialog-config.service';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [NoopAnimationsModule, RouterTestingModule, CoreModule.forRoot()],
|
imports: [NoopAnimationsModule, RouterTestingModule, CoreModule.forRoot()],
|
||||||
@@ -37,8 +36,7 @@ import { DialogConfigService } from 'core/services/dialog-config.service';
|
|||||||
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
|
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
|
||||||
{ provide: AppConfigService, useClass: AppConfigServiceMock },
|
{ provide: AppConfigService, useClass: AppConfigServiceMock },
|
||||||
{ provide: TranslationService, useClass: TranslationMock },
|
{ provide: TranslationService, useClass: TranslationMock },
|
||||||
{ provide: CookieService, useClass: CookieServiceMock },
|
{ provide: CookieService, useClass: CookieServiceMock }
|
||||||
{ provide: DialogConfigService, useValue: { loadDefaults: () => {} } }
|
|
||||||
|
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
|
Reference in New Issue
Block a user