Add Language selector for the mobile sidebar and fix the avatar

This commit is contained in:
George Kalampokis 2020-02-18 16:47:58 +02:00
parent 0e98c49d9c
commit 2636f919b2
15 changed files with 197 additions and 51 deletions

View File

@ -0,0 +1,16 @@
<div class="language">
<div class="row d-flex flex-row">
<div mat-dialog-title class="col-auto">
{{'LANGUAGE.TITLE' | translate}}
</div>
<div class="col-auto ml-auto close-btn" (click)="close()">
<mat-icon>close</mat-icon>
</div>
</div>
<div mat-dialog-content class="row">
<app-language></app-language>
</div>
<div mat-dialog-actions class="row">
<div class="ml-auto col-auto"><button mat-button mat-dialog-close mat-raised-button color="primary" (click)="cancel()">{{'LANGUAGE.CLOSE' | translate}}</button></div>
</div>
</div>

View File

@ -0,0 +1,17 @@
.form {
min-width: 150px;
max-width: 500px;
width: 100%;
}
.full-width {
width: 100%;
}
.close-btn {
cursor: pointer;
}
.language {
margin-bottom: 1.125rem;
}

View File

@ -0,0 +1,31 @@
import { Component, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
@Component({
selector: 'app-language-dialog',
templateUrl: './language-dialog.component.html',
styleUrls: ['./language-dialog.component.scss']
})
export class LanguageDialogComponent {
public isDialog: boolean;
constructor(
public dialogRef: MatDialogRef<LanguageDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) {
this.isDialog = data.isDialog;
}
cancel() {
this.dialogRef.close();
}
send() {
this.dialogRef.close(this.data);
}
close() {
this.dialogRef.close(false);
}
}

View File

@ -0,0 +1,5 @@
<mat-button-toggle-group class="lang-menu" vertical (change)="onLanguageSelected($event)" [value]="this.getCurrentLanguage().value">
<div *ngFor="let lang of languages">
<mat-button-toggle class="lang-button" [value]="lang.value">{{lang.label | translate}}</mat-button-toggle>
</div>
</mat-button-toggle-group>

View File

@ -0,0 +1,9 @@
::ng-deep.lang-menu {
border-color: transparent;
padding: 8px;
}
::ng-deep.lang-button {
padding-top: 15px;
padding-bottom: 15px;
}

View File

@ -0,0 +1,61 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '@app/core/services/auth/auth.service';
import { LanguageService } from '@app/core/services/language/language.service';
import { UserService } from '@app/core/services/user/user.service';
import { takeUntil } from 'rxjs/operators';
import { BaseComponent } from '@common/base/base.component';
const availableLanguages: any[] = require('../../../../assets/resources/language.json');
@Component({
selector: 'app-language',
templateUrl: './language.component.html',
styleUrls: ['./language.component.scss']
})
export class LanguageComponent extends BaseComponent implements OnInit {
languages = availableLanguages;
constructor(
private router: Router,
private authentication: AuthService,
private languageService: LanguageService,
private userService: UserService
) { super(); }
ngOnInit() {
}
public isAuthenticated(): boolean {
return !(!this.authentication.current());
}
public getCurrentLanguage(): any {
const lang = this.languages.find(lang => lang.value === this.languageService.getCurrentLanguage());
return lang;
}
onLanguageSelected(selectedLanguage: any) {
if (this.isAuthenticated()) {
const langMap = new Map<string, string>();
langMap.set('language', selectedLanguage.value);
this.userService.updateUserSettings({language: this.languages.find(lang => lang.value === selectedLanguage.value)})
.pipe(takeUntil(this._destroyed))
.subscribe((response) => {
this.languageService.changeLanguage(selectedLanguage.value);
this.authentication.me()
.pipe(takeUntil(this._destroyed))
.subscribe ( innerResponse =>
{this.router.navigateByUrl(this.router.url);});
},
error => {
console.log(error);
});
} else {
this.languageService.changeLanguage(selectedLanguage.value);
this.router.navigateByUrl(this.router.url);
}
}
}

View File

@ -41,15 +41,7 @@
<mat-icon>language</mat-icon> <mat-icon>language</mat-icon>
</button> </button>
<mat-menu #languageMenu="matMenu" class="lang-parent"> <mat-menu #languageMenu="matMenu" class="lang-parent">
<mat-button-toggle-group class="lang-menu" vertical (change)="onLanguageSelected($event)" [value]="this.getCurrentLanguage().value"> <app-language></app-language>
<div *ngFor="let lang of languages">
<mat-button-toggle class="lang-button" [value]="lang.value">{{lang.label | translate}}</mat-button-toggle>
</div>
</mat-button-toggle-group>
<!-- <button mat-menu-item *ngFor="let lang of languages" (click)="onLanguageSelected(lang)">
{{ lang.label | translate }}
</button> -->
</mat-menu> </mat-menu>
</div> </div>

View File

@ -25,13 +25,3 @@ $mat-card-header-size: 40px !default;
width: fit-content !important; width: fit-content !important;
min-width: auto !important; min-width: auto !important;
} }
::ng-deep.lang-menu {
border-color: transparent;
padding: 8px;
}
::ng-deep.lang-button {
padding-top: 15px;
padding-bottom: 15px;
}

View File

@ -37,8 +37,7 @@ export class NavbarComponent extends BaseComponent implements OnInit {
private authentication: AuthService, private authentication: AuthService,
private dialog: MatDialog, private dialog: MatDialog,
private progressIndicationService: ProgressIndicationService, private progressIndicationService: ProgressIndicationService,
private languageService: LanguageService, private languageService: LanguageService
private userService: UserService
) { ) {
super(); super();
this.location = location; this.location = location;
@ -211,26 +210,4 @@ export class NavbarComponent extends BaseComponent implements OnInit {
position: { top: '64px', right: '1em' } position: { top: '64px', right: '1em' }
}); });
} }
onLanguageSelected(selectedLanguage: any) {
if (this.isAuthenticated()) {
const langMap = new Map<string, string>();
langMap.set('language', selectedLanguage.value);
this.userService.updateUserSettings({language: this.languages.find(lang => lang.value === selectedLanguage.value)})
.pipe(takeUntil(this._destroyed))
.subscribe((response) => {
this.languageService.changeLanguage(selectedLanguage.value);
this.authentication.me()
.pipe(takeUntil(this._destroyed))
.subscribe ( innerResponse =>
{this.router.navigate([this.router.url]);});
},
error => {
console.log(error);
});
} else {
this.languageService.changeLanguage(selectedLanguage.value);
this.router.navigate([this.router.url]);
}
}
} }

View File

@ -5,13 +5,15 @@ import { SearchComponent } from '@app/ui/misc/search/search.component';
import { NavbarComponent } from '@app/ui/navbar/navbar.component'; import { NavbarComponent } from '@app/ui/navbar/navbar.component';
import { CommonFormsModule } from '@common/forms/common-forms.module'; import { CommonFormsModule } from '@common/forms/common-forms.module';
import { CommonUiModule } from '@common/ui/common-ui.module'; import { CommonUiModule } from '@common/ui/common-ui.module';
import { LanguageModule } from '../language/language.module';
@NgModule({ @NgModule({
imports: [ imports: [
CommonUiModule, CommonUiModule,
CommonFormsModule, CommonFormsModule,
RouterModule, RouterModule,
BreadcrumbModule BreadcrumbModule,
LanguageModule
], ],
declarations: [ declarations: [
NavbarComponent, NavbarComponent,

View File

@ -29,8 +29,8 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" *ngIf="isAuthenticated();else loginoption"> <a class="nav-link" *ngIf="isAuthenticated();else loginoption">
<p style="display: flex; align-items: center;" [routerLink]=" ['/profile']"> <p style="display: flex; align-items: center;" [routerLink]=" ['/profile']">
<img mat-card-avatar class="my-mat-card-avatar" *ngIf="this.principalHasAvatar()" [src]="this.getPrincipalAvatar()"> <img mat-card-avatar class="my-mat-card-avatar" [src]="this.getPrincipalAvatar()" (error)="applyFallbackAvatar($event)">
<img mat-card-avatar class="my-mat-card-avatar" *ngIf="!this.principalHasAvatar()" [src]="this.getDefaultAvatar()"> <!-- <img mat-card-avatar class="my-mat-card-avatar" *ngIf="!this.principalHasAvatar()" [src]="this.getDefaultAvatar()"> -->
<span class="d-lg-none d-md-block">{{ 'SIDE-BAR.ACCOUNT' | translate }}</span> <span class="d-lg-none d-md-block">{{ 'SIDE-BAR.ACCOUNT' | translate }}</span>
</p> </p>
</a> </a>
@ -47,6 +47,12 @@
<p class="login-label">{{ 'GENERAL.ACTIONS.LOG-IN' | translate }}</p> <p class="login-label">{{ 'GENERAL.ACTIONS.LOG-IN' | translate }}</p>
</a> </a>
</ng-template> </ng-template>
<li class="nav-item" *ngIf="!(isAuthenticated() && onInvalidUrl())">
<a class="nav-link" [routerLink]=" this.router.url " (click)="openLanguageDialog($event)">
<i class="material-icons">language</i>
<p class="login-label">{{ 'GENERAL.TITLES.LANGUAGE' | translate }}</p>
</a>
</li>
</ul> </ul>
</div> </div>
@ -64,7 +70,7 @@
<p>{{groupMenuItem.title | translate}}</p> <p>{{groupMenuItem.title | translate}}</p>
</div> </div>
<li routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}" *ngFor="let groupMenuRoute of groupMenuItem.routes" <li routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}" *ngFor="let groupMenuRoute of groupMenuItem.routes"
class="{{groupMenuRoute.class}} nav-item"> class="nav-item">
<a class="nav-link" [routerLink]="[groupMenuRoute.path]"> <a class="nav-link" [routerLink]="[groupMenuRoute.path]">
<i *ngIf="isFirst" class="material-icons">{{ groupMenuRoute.icon }}</i> <i *ngIf="isFirst" class="material-icons">{{ groupMenuRoute.icon }}</i>
<i *ngIf="!isFirst" class="material-icons-outlined">{{ groupMenuRoute.icon }}</i> <i *ngIf="!isFirst" class="material-icons-outlined">{{ groupMenuRoute.icon }}</i>

View File

@ -7,7 +7,7 @@ import { Principal } from '../../core/model/auth/Principal';
import { AppRole } from '../../core/common/enum/app-role'; import { AppRole } from '../../core/common/enum/app-role';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { Route } from '@angular/compiler/src/core'; import { LanguageDialogComponent } from '../language/dialog/language-dialog.component';
declare interface RouteInfo { declare interface RouteInfo {
path: string; path: string;
@ -74,6 +74,7 @@ export class SidebarComponent implements OnInit {
publicItems: GroupMenuItem; publicItems: GroupMenuItem;
groupMenuItems: GroupMenuItem[] = []; groupMenuItems: GroupMenuItem[] = [];
private toggleButton: any; private toggleButton: any;
currentRoute: string;
constructor( constructor(
public translate: TranslateService, public translate: TranslateService,
@ -85,6 +86,7 @@ export class SidebarComponent implements OnInit {
} }
ngOnInit() { ngOnInit() {
this.currentRoute = this.router.url;
this.generalItems = { this.generalItems = {
title: 'SIDE-BAR.GENERAL', title: 'SIDE-BAR.GENERAL',
routes: GENERAL_ROUTES, routes: GENERAL_ROUTES,
@ -140,6 +142,8 @@ export class SidebarComponent implements OnInit {
} }
this.groupMenuItems.push(this.publicItems); this.groupMenuItems.push(this.publicItems);
this.router.events.subscribe((event) => this.currentRoute = this.router.url);
// this.historyItems = { // this.historyItems = {
// title: 'SIDE-BAR.HISTORY', // title: 'SIDE-BAR.HISTORY',
// routes: HISTORY_ROUTES // routes: HISTORY_ROUTES
@ -159,6 +163,10 @@ export class SidebarComponent implements OnInit {
return 'assets/images/profile-placeholder.png'; return 'assets/images/profile-placeholder.png';
} }
public applyFallbackAvatar(ev: Event) {
(ev.target as HTMLImageElement).src = this.getDefaultAvatar();
}
public isAuthenticated(): boolean { public isAuthenticated(): boolean {
const myBollean = this.isAdmin(); const myBollean = this.isAdmin();
return !(!this.authentication.current()); return !(!this.authentication.current());
@ -209,4 +217,22 @@ export class SidebarComponent implements OnInit {
position: { top: '64px', right: '1em' } position: { top: '64px', right: '1em' }
}); });
} }
public onInvalidUrl(): boolean {
return this.currentRoute === '/language-editor' || this.currentRoute === '/profile';
}
openLanguageDialog() {
if (this.dialog.openDialogs.length > 0) {
this.dialog.closeAll();
}
else {
const dialogRef = this.dialog.open(LanguageDialogComponent, {
disableClose: true,
data: {
isDialog: true
}
});
}
}
} }

View File

@ -8,6 +8,7 @@ import { GlossaryModule } from '../glossary/glossary.module';
import { SidebarFooterComponent } from './sidebar-footer/sidebar-footer.component'; import { SidebarFooterComponent } from './sidebar-footer/sidebar-footer.component';
import { SidebarComponent } from './sidebar.component'; import { SidebarComponent } from './sidebar.component';
import { UserGuideModule } from '../user-guide/user-guide.module'; import { UserGuideModule } from '../user-guide/user-guide.module';
import { LanguageModule } from '../language/language.module';
@NgModule({ @NgModule({
imports: [ imports: [
@ -17,7 +18,8 @@ import { UserGuideModule } from '../user-guide/user-guide.module';
FaqModule, FaqModule,
RouterModule, RouterModule,
ContactModule, ContactModule,
UserGuideModule UserGuideModule,
LanguageModule
], ],
declarations: [ declarations: [
SidebarComponent, SidebarComponent,

View File

@ -121,7 +121,8 @@
"DATASET-PROFILES-NEW-VERSION": "New Version of Dataset Description Template", "DATASET-PROFILES-NEW-VERSION": "New Version of Dataset Description Template",
"DATASET-PROFILES-CLONE": "New Clone of Dataset Description Template", "DATASET-PROFILES-CLONE": "New Clone of Dataset Description Template",
"LANGUAGE-EDITOR": "Language Editor", "LANGUAGE-EDITOR": "Language Editor",
"GUIDE-EDITOR": "User Guide Editor" "GUIDE-EDITOR": "User Guide Editor",
"LANGUAGE": "Language"
}, },
"FILE-TYPES": { "FILE-TYPES": {
"PDF": "PDF", "PDF": "PDF",
@ -1045,6 +1046,11 @@
"HELP": "Help", "HELP": "Help",
"GLOSSARY": "Glossary" "GLOSSARY": "Glossary"
}, },
"LANGUAGE": {
"TITLE": "Language",
"TITLE-DASHED": "-Language-",
"CLOSE": "Close"
},
"DASHBOARD": { "DASHBOARD": {
"MY-GRANTS": "My Grants", "MY-GRANTS": "My Grants",
"GRANTS": "Grants", "GRANTS": "Grants",

View File

@ -121,7 +121,8 @@
"DATASET-PROFILES-NEW-VERSION": "New Version of Dataset Description Template", "DATASET-PROFILES-NEW-VERSION": "New Version of Dataset Description Template",
"DATASET-PROFILES-CLONE": "New Clone of Dataset Description Template", "DATASET-PROFILES-CLONE": "New Clone of Dataset Description Template",
"LANGUAGE-EDITOR": "Language Editor", "LANGUAGE-EDITOR": "Language Editor",
"GUIDE-EDITOR": "User Guide Editor" "GUIDE-EDITOR": "User Guide Editor",
"LANGUAGE": "Language"
}, },
"FILE-TYPES": { "FILE-TYPES": {
"PDF": "PDF", "PDF": "PDF",
@ -1043,6 +1044,11 @@
"HELP": "Help", "HELP": "Help",
"GLOSSARY": "Glossary" "GLOSSARY": "Glossary"
}, },
"LANGUAGE": {
"TITLE": "Language",
"TITLE-DASHED": "-Language-",
"CLOSE": "Close"
},
"DASHBOARD": { "DASHBOARD": {
"MY-GRANTS": "My Grants", "MY-GRANTS": "My Grants",
"GRANTS": "Grants", "GRANTS": "Grants",