mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-06-30 18:15:11 +00:00
[ADF-4227] Sidenav Layout - support direction (#4583)
* basic ui direction service * direction property * demo shell integration * move the direction in up sidenav layout to allow also the header to reorganize use the configuration editor to change rtl ltr add documenation * Update app.component.html * fix unit tests * fix overlay viewer e2e * fix e2e
This commit is contained in:
parent
83cb98f435
commit
3b83539b13
@ -1,4 +1,4 @@
|
|||||||
<div [dir]="textOrientation" class="adf-demo-app-container" >
|
<div class="adf-demo-app-container">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
<router-outlet name="overlay"></router-outlet>
|
<router-outlet name="overlay"></router-outlet>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
UserPreferencesService,
|
|
||||||
AuthenticationService,
|
AuthenticationService,
|
||||||
AlfrescoApiService,
|
AlfrescoApiService,
|
||||||
PageTitleService
|
PageTitleService
|
||||||
@ -33,24 +32,15 @@ import { MatDialog } from '@angular/material';
|
|||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
|
|
||||||
textOrientation: string = 'ltr';
|
|
||||||
|
|
||||||
constructor(private pageTitleService: PageTitleService,
|
constructor(private pageTitleService: PageTitleService,
|
||||||
private alfrescoApiService: AlfrescoApiService,
|
private alfrescoApiService: AlfrescoApiService,
|
||||||
private authenticationService: AuthenticationService,
|
private authenticationService: AuthenticationService,
|
||||||
private userPreferencesService: UserPreferencesService,
|
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private dialogRef: MatDialog) {
|
private dialogRef: MatDialog) {
|
||||||
|
|
||||||
this.userPreferencesService.set('textOrientation', this.textOrientation);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.userPreferencesService.select('textOrientation').subscribe((textOrientation) => {
|
|
||||||
this.textOrientation = textOrientation;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.pageTitleService.setTitle('title');
|
this.pageTitleService.setTitle('title');
|
||||||
|
|
||||||
this.alfrescoApiService.getInstance().on('error', (error) => {
|
this.alfrescoApiService.getInstance().on('error', (error) => {
|
||||||
|
@ -85,67 +85,61 @@ export const appRoutes: Routes = [
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ path: 'preview/s/:id', component: SharedLinkViewComponent },
|
{ path: 'preview/s/:id', component: SharedLinkViewComponent },
|
||||||
{
|
|
||||||
path: 'breadcrumb',
|
|
||||||
canActivate: [AuthGuardEcm],
|
|
||||||
component: AppLayoutComponent,
|
|
||||||
loadChildren: 'app/components/breadcrumb-demo/breadcrumb-demo.module#AppBreadcrumbModule'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'notifications',
|
|
||||||
component: AppLayoutComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
loadChildren: 'app/components/notifications/notifications.module#AppNotificationsModule'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'config-editor',
|
|
||||||
component: AppLayoutComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
loadChildren: 'app/components/config-editor/config-editor.module#AppConfigEditorModule'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'card-view',
|
|
||||||
component: AppLayoutComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
loadChildren: 'app/components/card-view/card-view.module#AppCardViewModule'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'sites',
|
|
||||||
component: AppLayoutComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
loadChildren: 'app/components/sites/sites.module#SitesModule'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'header-data',
|
|
||||||
component: AppLayoutComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
loadChildren: 'app/components/header-data/header-data.module#AppHeaderDataModule'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: AppLayoutComponent,
|
component: AppLayoutComponent,
|
||||||
canActivate: [AuthGuard],
|
canActivate: [AuthGuard],
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
path: 'breadcrumb',
|
||||||
|
canActivate: [AuthGuardEcm],
|
||||||
|
loadChildren: 'app/components/breadcrumb-demo/breadcrumb-demo.module#AppBreadcrumbModule'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'notifications',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
loadChildren: 'app/components/notifications/notifications.module#AppNotificationsModule'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'config-editor',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
loadChildren: 'app/components/config-editor/config-editor.module#AppConfigEditorModule'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'card-view',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
loadChildren: 'app/components/card-view/card-view.module#AppCardViewModule'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'sites',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
loadChildren: 'app/components/sites/sites.module#SitesModule'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'header-data',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
loadChildren: 'app/components/header-data/header-data.module#AppHeaderDataModule'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: HomeComponent
|
component: HomeComponent
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<adf-sidenav-layout [sidenavMin]="70" [sidenavMax]="220" [stepOver]="780" [hideSidenav]="hideSidenav"
|
<adf-sidenav-layout [sidenavMin]="70" [sidenavMax]="220" [stepOver]="780" [hideSidenav]="hideSidenav" [direction]="direction"
|
||||||
[expandedSidenav]="expandedSidenav" (expanded)="setState($event)" [position]="position">
|
[expandedSidenav]="expandedSidenav" (expanded)="setState($event)" [position]="position">
|
||||||
|
|
||||||
<adf-sidenav-layout-header>
|
<adf-sidenav-layout-header>
|
||||||
|
@ -84,6 +84,7 @@ export class AppLayoutComponent implements OnInit {
|
|||||||
expandedSidenav = false;
|
expandedSidenav = false;
|
||||||
|
|
||||||
position = 'start';
|
position = 'start';
|
||||||
|
direction = 'ltr';
|
||||||
|
|
||||||
hideSidenav = false;
|
hideSidenav = false;
|
||||||
showMenu = true;
|
showMenu = true;
|
||||||
@ -113,16 +114,23 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.userPreferencesService.set('textOrientation', this.direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(state) {
|
setState(state) {
|
||||||
|
@ -75,6 +75,7 @@ sub-components (note the use of `<ng-template>` in the sub-components' body sect
|
|||||||
| sidenavMax | `number` | | Maximum size of the navigation region. |
|
| sidenavMax | `number` | | Maximum size of the navigation region. |
|
||||||
| sidenavMin | `number` | | Minimum size of the navigation region. |
|
| sidenavMin | `number` | | Minimum size of the navigation region. |
|
||||||
| stepOver | `number` | | Screen size at which display switches from small screen to large screen configuration. |
|
| stepOver | `number` | | Screen size at which display switches from small screen to large screen configuration. |
|
||||||
|
| direction | `string` | `ltr` | The direction of the layout. 'ltr' or 'rtl' |
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
|
@ -18,6 +18,18 @@ added to the main `<body>` element in `index.html`. When the attribute is set to
|
|||||||
</body>
|
</body>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you use the [Sidenav Layout component](../core/components/sidenav-layout.component.md) you can choose set the direction property in it using the property direction ans set it to **'rtl'**
|
||||||
|
|
||||||
|
|
||||||
|
```html
|
||||||
|
<adf-sidenav-layout
|
||||||
|
[direction]="'rtl'">
|
||||||
|
......
|
||||||
|
</adf-sidenav-layout>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Also, we have a [translation file](internationalization.md) for Arabic (code: "ar"),
|
Also, we have a [translation file](internationalization.md) for Arabic (code: "ar"),
|
||||||
which is the
|
which is the
|
||||||
[most widely used](https://en.wikipedia.org/wiki/List_of_languages_by_number_of_native_speakers)
|
[most widely used](https://en.wikipedia.org/wiki/List_of_languages_by_number_of_native_speakers)
|
||||||
|
@ -187,6 +187,7 @@ describe('Viewer - properties', () => {
|
|||||||
|
|
||||||
it('[C260100] Should be possible to disable Overlay viewer', () => {
|
it('[C260100] Should be possible to disable Overlay viewer', () => {
|
||||||
viewerPage.clickCloseButton();
|
viewerPage.clickCloseButton();
|
||||||
|
navigationBarPage.scrollTo(navigationBarPage.overlayViewerButton);
|
||||||
navigationBarPage.clickOverlayViewerButton();
|
navigationBarPage.clickOverlayViewerButton();
|
||||||
|
|
||||||
dataTable.doubleClickRow('Name', fileForOverlay.name);
|
dataTable.doubleClickRow('Name', fileForOverlay.name);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { browser, by, element } from 'protractor';
|
import { browser, by, element, ElementFinder } from 'protractor';
|
||||||
import { ProcessServicesPage } from './process-services/processServicesPage';
|
import { ProcessServicesPage } from './process-services/processServicesPage';
|
||||||
import { AppListCloudPage } from '@alfresco/adf-testing';
|
import { AppListCloudPage } from '@alfresco/adf-testing';
|
||||||
import TestConfig = require('../../test.config');
|
import TestConfig = require('../../test.config');
|
||||||
@ -24,6 +24,7 @@ import { BrowserVisibility } from '@alfresco/adf-testing';
|
|||||||
|
|
||||||
export class NavigationBarPage {
|
export class NavigationBarPage {
|
||||||
|
|
||||||
|
linkListContainer = element(by.css('.adf-sidenav-linklist'));
|
||||||
contentServicesButton = element(by.css('a[data-automation-id="Content Services"]'));
|
contentServicesButton = element(by.css('a[data-automation-id="Content Services"]'));
|
||||||
dataTableButton = element(by.css('a[data-automation-id="Datatable"]'));
|
dataTableButton = element(by.css('a[data-automation-id="Datatable"]'));
|
||||||
dataTableNestedButton = element(by.css('button[data-automation-id="Datatable"]'));
|
dataTableNestedButton = element(by.css('button[data-automation-id="Datatable"]'));
|
||||||
@ -247,4 +248,9 @@ export class NavigationBarPage {
|
|||||||
BrowserVisibility.waitUntilElementIsVisible(this.customSourcesButton);
|
BrowserVisibility.waitUntilElementIsVisible(this.customSourcesButton);
|
||||||
this.customSourcesButton.click();
|
this.customSourcesButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scrollTo(el: ElementFinder) {
|
||||||
|
browser.executeScript(`return arguments[0].scrollTop = arguments[1].offsetTop`, this.linkListContainer.getWebElement(), el.getWebElement());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,29 @@
|
|||||||
<ng-container *ngIf="!isHeaderInside">
|
<div [dir]="direction" class="adf-sidenav-layout-full-space">
|
||||||
<ng-container class="adf-sidenav-layout-outer-header"
|
<ng-container *ngIf="!isHeaderInside">
|
||||||
*ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container>
|
<ng-container class="adf-sidenav-layout-outer-header"
|
||||||
</ng-container>
|
*ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container>
|
||||||
|
|
||||||
<adf-layout-container #container
|
|
||||||
[position]="position"
|
|
||||||
[sidenavMin]="sidenavMin"
|
|
||||||
[sidenavMax]="sidenavMax"
|
|
||||||
[mediaQueryList]="mediaQueryList"
|
|
||||||
[hideSidenav]="hideSidenav"
|
|
||||||
[expandedSidenav]="expandedSidenav"
|
|
||||||
data-automation-id="adf-layout-container"
|
|
||||||
class="adf-layout__content">
|
|
||||||
|
|
||||||
<ng-container app-layout-navigation
|
|
||||||
*ngTemplateOutlet="navigationTemplate; context:templateContext"></ng-container>
|
|
||||||
|
|
||||||
<ng-container app-layout-content>
|
|
||||||
<ng-container *ngIf="isHeaderInside">
|
|
||||||
<ng-container *ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngTemplateOutlet="contentTemplate; context:templateContext"></ng-container>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</adf-layout-container>
|
|
||||||
|
|
||||||
<ng-template #emptyTemplate></ng-template>
|
<adf-layout-container #container
|
||||||
|
[position]="position"
|
||||||
|
[sidenavMin]="sidenavMin"
|
||||||
|
[sidenavMax]="sidenavMax"
|
||||||
|
[mediaQueryList]="mediaQueryList"
|
||||||
|
[hideSidenav]="hideSidenav"
|
||||||
|
[expandedSidenav]="expandedSidenav"
|
||||||
|
data-automation-id="adf-layout-container"
|
||||||
|
class="adf-layout__content">
|
||||||
|
|
||||||
|
<ng-container app-layout-navigation
|
||||||
|
*ngTemplateOutlet="navigationTemplate; context:templateContext"></ng-container>
|
||||||
|
|
||||||
|
<ng-container app-layout-content>
|
||||||
|
<ng-container *ngIf="isHeaderInside">
|
||||||
|
<ng-container *ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngTemplateOutlet="contentTemplate; context:templateContext"></ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</adf-layout-container>
|
||||||
|
|
||||||
|
<ng-template #emptyTemplate></ng-template>
|
||||||
|
</div>
|
||||||
|
@ -2,6 +2,17 @@
|
|||||||
$adf-sidenav-max: 300px !default;
|
$adf-sidenav-max: 300px !default;
|
||||||
|
|
||||||
.adf-sidenav-layout {
|
.adf-sidenav-layout {
|
||||||
|
|
||||||
|
&-full-space {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
@include flex-column;
|
@include flex-column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
@ -144,8 +144,8 @@ describe('SidenavLayoutComponent', () => {
|
|||||||
|
|
||||||
describe('adf-sidenav-layout-header', () => {
|
describe('adf-sidenav-layout-header', () => {
|
||||||
|
|
||||||
const outerHeaderSelector = By.css('.adf-sidenav-layout > #header-test'),
|
const outerHeaderSelector = By.css('.adf-sidenav-layout-full-space > #header-test');
|
||||||
innerHeaderSelector = By.css('.adf-sidenav-layout [data-automation-id="adf-layout-container"] #header-test');
|
const innerHeaderSelector = By.css('.adf-layout__content > #header-test');
|
||||||
|
|
||||||
it('should contain the transcluded header template outside of the layout-container', () => {
|
it('should contain the transcluded header template outside of the layout-container', () => {
|
||||||
mediaQueryList.matches = false;
|
mediaQueryList.matches = false;
|
||||||
|
@ -42,9 +42,11 @@ import { BehaviorSubject, Observable } from 'rxjs';
|
|||||||
host: { class: 'adf-sidenav-layout' }
|
host: { class: 'adf-sidenav-layout' }
|
||||||
})
|
})
|
||||||
export class SidenavLayoutComponent implements OnInit, AfterViewInit, OnDestroy {
|
export class SidenavLayoutComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
|
|
||||||
static STEP_OVER = 600;
|
static STEP_OVER = 600;
|
||||||
|
|
||||||
|
/** The direction of the layout. 'ltr' or 'rtl' */
|
||||||
|
@Input() direction = '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';
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user