profile + i18n

This commit is contained in:
Lurkars
2021-03-18 15:12:30 +01:00
parent 0b4fe16b8e
commit 3e26f43177
16 changed files with 184 additions and 349 deletions
+3 -1
View File
@@ -19,6 +19,7 @@ import {VoucherComponent} from './pages/account/voucher/voucher.component';
import {SecurityComponent} from './pages/account/security/security.component';
import {UnavailableComponent} from './pages/unavailable/unavailable.component';
import {NotfoundComponent} from './pages/notfound/notfound.component';
import {UserComponent} from './pages/user/user.component'
const routes: Routes = [
{path: '', redirectTo: "/account/info", pathMatch: 'full'},
@@ -44,7 +45,8 @@ const routes: Routes = [
{path: 'register', component: RegisterComponent, canActivate: [AnonymousGuard]},
{path: 'tokens', component: TokensComponent, canActivate: [AuthGuard]},
{path: 'unavailable', component: UnavailableComponent},
{path: '**', component: NotfoundComponent, pathMatch: 'full'},
{path: 'p/:username', component: UserComponent, canActivate: [AuthUpdateGuard]},
{path: '**', component: NotfoundComponent, pathMatch: 'full', canActivate: [AuthUpdateGuard]},
];
@NgModule({
+5 -4
View File
@@ -21,6 +21,11 @@ export class AppComponent {
auth;
constructor(private i18n: I18nService, private authService: AuthService, private router: Router, private iconRegistry: MatIconRegistry, private sanitizer: DomSanitizer, private _adapter: DateAdapter<any>) {
iconRegistry.addSvgIcon('logo', sanitizer.bypassSecurityTrustResourceUrl('assets/icons/logo.svg'));
}
ngOnInit() {
this.currentLocale = this.i18n.getLocale();
this.locales = this.i18n.getLocales();
this.authService.auth.subscribe(data => {
@@ -29,10 +34,6 @@ export class AppComponent {
this._adapter.setLocale(this.currentLocale);
iconRegistry.addSvgIcon('logo', sanitizer.bypassSecurityTrustResourceUrl('assets/icons/logo.svg'));
}
ngOnInit() {
const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
if(width < 768) {
this.opened = false;
+6 -2
View File
@@ -33,13 +33,15 @@ import {UsernameDialog} from './pages/register/username-dialog/username.dialog';
import {UnavailableComponent} from './pages/unavailable/unavailable.component';
import {NotfoundComponent} from './pages/notfound/notfound.component';
import {HtmlComponent} from './utils/html/html.component';
import {ConfirmDialog} from './ui/confirm/confirm.component'
import {UserComponent} from './pages/user/user.component'
import {I18nService} from './services/i18n.service';
export function init_app(i18n: I18nService) {
return () => i18n.fetch(i18n.getLocale()).then(response => {}, error => {});
return () => i18n.fetch().then(response => {}, error => {});
}
@Injectable()
@@ -81,7 +83,9 @@ export class XhrInterceptor implements HttpInterceptor {
UsernameDialog,
UnavailableComponent,
NotfoundComponent,
HtmlComponent
HtmlComponent,
ConfirmDialog,
UserComponent
],
imports: [
BrowserModule,
+19
View File
@@ -0,0 +1,19 @@
<br>
<mat-progress-bar *ngIf="!success && !error" mode="indeterminate"></mat-progress-bar>
<div *ngIf="success">
<h3>{{username}}</h3>
<app-profilefields [profileFields]="profileFields"></app-profilefields>
</div>
<mat-card *ngIf="error">
<mat-card-header>
<mat-card-title>{{error.status}}</mat-card-title>
<mat-card-subtitle>{{'user.unavailable' | i18n}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p>
{{'user.unavailable.text' | i18n}}
</p>
</mat-card-content>
</mat-card>
+3
View File
@@ -0,0 +1,3 @@
h3 {
text-transform: uppercase;
}
+25
View File
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserComponent } from './user.component';
describe('UserComponent', () => {
let component: UserComponent;
let fixture: ComponentFixture<UserComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ UserComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(UserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
+35
View File
@@ -0,0 +1,35 @@
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Router, ParamMap} from '@angular/router';
import {ProfileService} from '../../services/profile.service';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.scss']
})
export class UserComponent implements OnInit {
username;
profileFields = [];
error = false;
success = false;
constructor(
private profileService: ProfileService,
private router: Router,
private route: ActivatedRoute) {}
async ngOnInit() {
this.username = this.route.snapshot.paramMap.get('username');
this.profileService.getAllForUser(this.username).subscribe((data: any) => {
this.profileFields = data;
this.success = true;
}, error => {
this.error = error;
})
}
}
+37 -35
View File
@@ -1,35 +1,18 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { isEmpty } from 'rxjs/operators';
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import { environment } from '../../environments/environment';
@Injectable({
providedIn: 'root',
})
export class I18nService {
locale: String;
locales = ["de-informal"];
locale: string;
locales : any = ["de-informal"];
i18n: any;
constructor(private http: HttpClient) {
let browserLocale = navigator.language;
if (browserLocale.indexOf("-") != -1) {
browserLocale = browserLocale.split("-")[0];
}
let locale = localStorage.getItem("bstly.locale") || browserLocale || this.locales[0];
if (locale == 'de') {
locale = 'de-informal';
}
if (this.locales.indexOf(locale) == -1) {
locale = this.locales[0];
}
this.setLocale(locale);
}
getLocales() {
@@ -44,25 +27,44 @@ export class I18nService {
this.locale = locale;
}
async fetch(locale) {
this.i18n = await this.http.get("./assets/i18n/" + locale + ".json").toPromise();
async fetch() {let browserLocale = navigator.language;
if(browserLocale.indexOf("-") != -1) {
browserLocale = browserLocale.split("-")[0];
}
let locale = localStorage.getItem("bstly.locale") || browserLocale || this.locales[0];
if(locale == 'de') {
locale = 'de-informal';
}
this.locales = await this.http.get(environment.apiUrl + "/i18n").toPromise();
if(this.locales.indexOf(locale) == -1) {
locale = this.locales[0];
}
this.i18n = await this.http.get(environment.apiUrl + "/i18n/" + locale).toPromise();
this.setLocale(locale);
}
get(key, args: any[]): String {
get(key, args: string[]): string {
return this.getInternal(key, args, this.i18n);
}
getInternal(key, args: any[], from): String {
if (!from) {
getInternal(key, args: string[], from): string {
if(!from) {
return key;
} else if (from[key]) {
if (from[key]["."]) {
} else if(from[key]) {
if(from[key]["."]) {
return this.insertArguments(from[key]["."], args);
}
return this.insertArguments(from[key], args);
} else {
let keys = key.split(".");
if (from[keys[0]]) {
if(from[keys[0]]) {
key = keys.slice(1, keys.length).join(".");
return this.getInternal(key, args, from[keys[0]])
}
@@ -71,10 +73,10 @@ export class I18nService {
return key;
}
insertArguments(label: String, args: any[]) {
if (args) {
for (let index in args) {
label = label.replace(`{${index}}`, args[index]);
insertArguments(label: string, args: string[]) {
if(args) {
for(let index in args) {
label = label.replace(`{${index}}`, this.get(args[index], []));
}
}
return label;
@@ -0,0 +1,7 @@
<mat-dialog-content>
{{text}}
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button [mat-dialog-close]="false">{{'cancel' | i18n}}</button>
<button mat-raised-button [mat-dialog-close]="true" color="accent">{{'confirm' | i18n}}</button>
</mat-dialog-actions>
@@ -0,0 +1,3 @@
mat-form-field {
display: block;
}
+21
View File
@@ -0,0 +1,21 @@
import {Component, Inject} from '@angular/core';
import {MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog';
import {I18nService} from '../../services/i18n.service';
@Component({
templateUrl: 'confirm.component.html',
styleUrls: ['./confirm.component.scss']
})
export class ConfirmDialog {
text;
constructor(private i18nService: I18nService,
public dialogRef: MatDialogRef<ConfirmDialog>,
@Inject(MAT_DIALOG_DATA) public data: any) {
this.text = i18nService.get(data.label, data.args);
}
}
@@ -1,4 +1,4 @@
<h1 mat-dialog-title></h1>
<h1 mat-dialog-title>{{'profileField.name.' + profileField.name | i18n}}</h1>
<mat-dialog-content>
<pre>
{{profileField.blob}}
@@ -1,4 +1,4 @@
<h1 mat-dialog-title></h1>
<h1 mat-dialog-title>{{'profileField.name.' + profileField.name | i18n}}</h1>
<mat-dialog-content>
<form [formGroup]="form">
<mat-form-field>
@@ -4,6 +4,7 @@ import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog';
import {I18nService} from '../../services/i18n.service';
import {ProfileService} from '../../services/profile.service';
import {ConfirmDialog} from '../confirm/confirm.component';
@Component({
selector: 'app-profilefields',
@@ -55,7 +56,7 @@ export class ProfileFieldsComponent implements OnInit {
const dialogRef = this.dialog.open(ProfileFieldDialog, {
data: profileField,
minWidth : '400px'
minWidth: '400px'
});
@@ -74,16 +75,27 @@ export class ProfileFieldsComponent implements OnInit {
}
confirmDelete(profileField) {
this.profileService.delete(profileField.name).subscribe((result: any) => {
this.profileFields.splice(this.profileFields.indexOf(profileField), 1);
this.profileFields = [...this.profileFields];
const dialogRef = this.dialog.open(ConfirmDialog, {
data: {
'label': 'profileField.confirmDelete',
'args': ['profileField.name.' + profileField.name]
}
})
dialogRef.afterClosed().subscribe(result => {
if(result) {
this.profileService.delete(profileField.name).subscribe((result: any) => {
this.profileFields.splice(this.profileFields.indexOf(profileField), 1);
this.profileFields = [...this.profileFields];
})
}
});
}
openCreate() {
const dialogRef = this.dialog.open(ProfileFieldDialog, {
data: {"type": "TEXT", "visibility": "PRIVATE"},
minWidth : '400px'
minWidth: '400px'
});
dialogRef.afterClosed().subscribe(result => {
@@ -100,7 +112,7 @@ export class ProfileFieldsComponent implements OnInit {
openBlob(profileField) {
this.dialog.open(ProfileFieldBlob, {
data: profileField,
minWidth : '400px'
minWidth: '400px'
});
}