Archived
Private
Public Access
1
0

Fixed minor issues + added language support

This commit is contained in:
2023-03-25 18:36:19 +01:00
parent 4422d8818a
commit 6dfb5a4b48
23 changed files with 334 additions and 83 deletions

View File

@@ -3,7 +3,7 @@ import 'zone.js/node';
import { APP_BASE_HREF } from '@angular/common';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { existsSync } from 'fs';
import { existsSync, readdirSync } from 'fs';
import { join } from 'path';
import { AppServerModule } from './src/main.server';
@@ -25,11 +25,16 @@ export function app(): express.Express {
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
server.get('/backend', (req, res) => {
let backend = process.env['BACKEND']
let backend = process.env['BACKEND'] || "http://localhost:5110/";
if (!backend?.endsWith("/")) backend += "/";
res.json({url: backend});
});
server.get('/lang', (req, res) => {
const files: string[] = readdirSync(distFolder + "/assets/languages");
res.json({files});
})
// Serve static files from /browser
server.get('*.*', express.static(distFolder, {
maxAge: '1y'

View File

@@ -26,6 +26,7 @@ import {MatSnackBarModule} from "@angular/material/snack-bar";
import {MatTooltipModule} from "@angular/material/tooltip";
import { TextDialogComponent } from './components/text-dialog/text-dialog.component';
import { ProjectComponent } from './sites/project/project.component';
import {MatMenuModule} from "@angular/material/menu";
@NgModule({
declarations: [
@@ -40,7 +41,7 @@ import { ProjectComponent } from './sites/project/project.component';
ProjectComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
BrowserModule.withServerTransition({appId: 'serverApp'}),
AppRoutingModule,
BrowserAnimationsModule,
HttpClientModule,
@@ -57,7 +58,8 @@ import { ProjectComponent } from './sites/project/project.component';
FormsModule,
MatDialogModule,
MatSnackBarModule,
MatTooltipModule
MatTooltipModule,
MatMenuModule
],
providers: [],
bootstrap: [AppComponent]

View File

@@ -8,24 +8,24 @@
<mat-selection-list id="actions">
<mat-list-item routerLink="/dashboard">
<mat-icon matListItemIcon>dashboard</mat-icon>
<div matListItemTitle>Übersicht</div>
<div matListItemTitle>{{langs.currentLang?.dashboard}}</div>
</mat-list-item>
<mat-list-item (click)="logout()">
<mat-icon matListItemIcon>logout</mat-icon>
<div matListItemTitle>Ausloggen</div>
<div matListItemTitle>{{langs.currentLang?.logout}}</div>
</mat-list-item>
<mat-list-item (click)="createProject()">
<mat-icon matListItemIcon>add</mat-icon>
<div matListItemTitle>Neues Projekt</div>
<div matListItemTitle>{{langs.currentLang?.createProject}}</div>
</mat-list-item>
<mat-divider></mat-divider>
<div mat-subheader>Projekte</div>
<mat-list-item *ngFor="let project of projects.projects" (click)="openProject(project.projectId)">
<div mat-subheader>{{langs.currentLang?.projects}}</div>
<mat-list-item *ngFor="let project of projects.projects" (click)="openProject(project.projectId)" class="project">
<mat-icon matListItemIcon>open_in_new</mat-icon>
<div matListItemTitle>{{project.name}}</div>
<div matListItemLine [ngClass]="{startColor: project.running, stopColor: !project.running}">{{project.running ? 'Läuft' : 'Gestoppt'}}</div>
<div matListItemLine [ngClass]="{startColor: project.running, stopColor: !project.running}">{{project.running ? langs.currentLang?.running : langs.currentLang?.stopped}}</div>
</mat-list-item>
</mat-selection-list>
@@ -37,8 +37,16 @@
<span>Project Manager</span>
<section id="top-actions">
<button mat-icon-button (click)="onModeChange()" matTooltip="Farbmodus ändern"><mat-icon>{{darkMode ? 'light_mode' : 'dark_mode'}}</mat-icon></button>
<button mat-icon-button routerLink="/profile" *ngIf="showActions()" matTooltip="Profil Einstellungen"><mat-icon>account_circle</mat-icon></button>
<button mat-icon-button [matMenuTriggerFor]="menu" [matTooltip]="langs.currentLang?.selectLang"><mat-icon>language</mat-icon></button>
<mat-menu #menu>
<button mat-menu-item (click)="langs.setLanguage(language)" *ngFor="let language of langs.allLanguages">
<mat-icon>language</mat-icon>
<span>{{language}}</span>
</button>
</mat-menu>
<button mat-icon-button (click)="onModeChange()" [matTooltip]="langs.currentLang?.design"><mat-icon>{{darkMode ? 'light_mode' : 'dark_mode'}}</mat-icon></button>
<button mat-icon-button routerLink="/profile" *ngIf="showActions()" [matTooltip]="langs.currentLang?.profileSettings"><mat-icon>account_circle</mat-icon></button>
</section>
</mat-toolbar>

View File

@@ -14,6 +14,10 @@ mat-drawer-container {
height: calc(100vh - 80px);
overflow-y: auto;
}
.project mat-icon {
margin-block: auto;
}
}
}

View File

@@ -1,4 +1,4 @@
import {Component} from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {Router} from "@angular/router";
import {CrudService} from "../../services/crud.service";
import {ProjectService} from "../../services/project.service";
@@ -7,6 +7,8 @@ import {TextDialogComponent} from "../text-dialog/text-dialog.component";
import {firstValueFrom} from "rxjs";
import {MatSnackBar} from "@angular/material/snack-bar";
import {StorageService} from "../../services/storage.service";
import {LangService} from "../../services/lang.service";
import {Language} from "../../entities/language";
@Component({
selector: 'app-navigation',
@@ -17,7 +19,7 @@ export class NavigationComponent {
public static spinnerVisible: boolean = false;
public darkMode: boolean;
public constructor(public router: Router, public crud: CrudService, public projects: ProjectService, public dialog: MatDialog, private snackBar: MatSnackBar, private storage: StorageService) {
public constructor(public router: Router, public langs: LangService, public crud: CrudService, public projects: ProjectService, public dialog: MatDialog, private snackBar: MatSnackBar, private storage: StorageService) {
this.darkMode = storage.getItem("darkMode") == "true";
}

View File

@@ -0,0 +1,54 @@
export interface Language {
// Navigation
selectLang: string,
design: string,
profileSettings: string,
dashboard: string,
logout: string,
addProject: string,
projects: string,
running: string,
stopped: string,
// Dashboard
welcome: string,
noProjects: string,
open: string,
edit: string,
delete: string,
// Popups
name: string,
cancel: string,
createProject: string,
editProject: string
// Profile
profile: string,
profileSub: string,
email: string,
username: string,
password: string,
passwordRepeat: string,
updateAccount: string,
deleteAccount: string,
saveChanges: string,
updateFailed: string,
accountUpdated: string,
deleteQuestion: string,
deleteWarning: string,
accountDeleted: string,
submit: string,
// Login / Register
login: string,
register: string,
noAccount: string,
alreadyAccount: string,
valueToLong: string,
validEmail: string,
isRequired: string,
emailOrPasswordWrong: string,
passwordsDontMatch: string,
registerFailed: string,
}

View File

@@ -25,7 +25,7 @@ export class CrudService {
'Authorization': ''
});
constructor(private client: HttpClient, private storage: StorageService) {
constructor(public client: HttpClient, private storage: StorageService) {
this.getBackendUrl().then(() => {
this.authKey = storage.getItem("api_key");
this.setAuthKey(this.authKey);

View File

@@ -0,0 +1,41 @@
import { Injectable } from '@angular/core';
import {Language} from "../entities/language";
import {CrudService} from "./crud.service";
import {firstValueFrom} from "rxjs";
import {StorageService} from "./storage.service";
@Injectable({
providedIn: 'root'
})
export class LangService {
private languages: Map<string, Language> = new Map<string, Language>();
public allLanguages: string[] = [];
public currentLang: Language;
constructor(private crud: CrudService, private storage: StorageService) {
this.loadLanguages();
}
private async loadLanguages() {
this.languages = new Map<string, Language>();
const res = await firstValueFrom(this.crud.client.get<{files: string[]}>(location?.origin + "/lang"));
const languages = res.files;
this.allLanguages = languages.map(lang => lang.replace(".json", ""));
const tasks = [];
for (let lang of languages) {
const task = firstValueFrom(this.crud.client.get<Language>(location?.origin + "/assets/languages/" + lang))
.then(result => this.languages.set(lang.replace(".json", ""), result));
tasks.push(task);
}
await Promise.all(tasks);
this.currentLang = this.languages.get(this.storage.getItem("language") || "en-US");
}
public setLanguage(lang: string) {
this.currentLang = this.languages.get(lang);
this.storage.setItem("language", lang);
}
}

View File

@@ -1,9 +1,9 @@
<section id="main">
<h1 id="welcome">Willkommen {{crud.user.username}}</h1>
<h1 id="welcome">{{langs.currentLang?.welcome}} {{crud.user.username}}</h1>
<h2 id="title">Projekte</h2>
<h2 id="title">{{langs.currentLang?.projects}}</h2>
<div id="projects">
<span *ngIf="projects.projects.length == 0 && crud.user != undefined" class="disabled">Du hast noch keine Projekte erstellt</span>
<span *ngIf="projects.projects.length == 0 && crud.user != undefined" class="disabled">{{langs.currentLang?.noProjects}}</span>
<mat-card *ngFor="let project of projects.projects" class="project">
<mat-card-header>
<mat-card-title>{{project.name}}</mat-card-title>
@@ -11,9 +11,9 @@
</mat-card-header>
<mat-card-actions>
<button mat-button color="primary" (click)="router.navigate(['/project', project.projectId])">Öffnen</button>
<button mat-button color="accent" (click)="editProject(project.projectId)">Bearbeiten</button>
<button mat-button color="warn" (click)="deleteProject(project.projectId)">Löschen</button>
<button mat-button color="primary" (click)="openProject(project.projectId)">{{langs.currentLang?.open}}</button>
<button mat-button color="accent" (click)="editProject(project.projectId)">{{langs.currentLang?.edit}}</button>
<button mat-button color="warn" (click)="deleteProject(project.projectId)">{{langs.currentLang?.delete}}</button>
<button mat-icon-button color="warn" *ngIf="project.running" (click)="updateProjectStatus(project.projectId, false)"><mat-icon>pause</mat-icon></button>
<button mat-icon-button color="accent" *ngIf="!project.running" (click)="updateProjectStatus(project.projectId, true)"><mat-icon>play_arrow</mat-icon></button>

View File

@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {ProjectService} from "../../services/project.service";
import {CrudService} from "../../services/crud.service";
import {Router} from "@angular/router";
@@ -8,6 +8,9 @@ import {firstValueFrom} from "rxjs";
import {MatSnackBar} from "@angular/material/snack-bar";
import {TextDialogComponent} from "../../components/text-dialog/text-dialog.component";
import {NavigationComponent} from "../../components/navigation/navigation.component";
import {Project} from "../../entities/project";
import {LangService} from "../../services/lang.service";
import {Language} from "../../entities/language";
@Component({
selector: 'app-dashboard',
@@ -16,7 +19,17 @@ import {NavigationComponent} from "../../components/navigation/navigation.compon
})
export class DashboardComponent {
public constructor(public crud: CrudService, public projects: ProjectService, public router: Router, private dialog: MatDialog, private snackBar: MatSnackBar) {}
public constructor(public langs: LangService, public crud: CrudService, public projects: ProjectService, public router: Router, private dialog: MatDialog, private snackBar: MatSnackBar) {}
public async openProject(projectId: string) {
const response = await this.crud.sendGetRequest<{url: string}>('projects/' + projectId + '/url/string');
const url = response.content.url;
if (!url.startsWith("https")) {
window.open(`${this.crud.backendUrl}projects/${projectId}/url?token=${this.crud.authKey}`, '_blank').focus();
} else {
await this.router.navigate(['/project', projectId]);
}
}
public async editProject(projectId: string) {
const dialogRef = this.dialog.open(TextDialogComponent, {

View File

@@ -1,29 +1,29 @@
<mat-card>
<mat-card-title>Einloggen</mat-card-title>
<mat-card-title>{{langs.currentLang?.login}}</mat-card-title>
<mat-divider></mat-divider>
<mat-card-content>
<form [formGroup]="form" (ngSubmit)="submit()">
<mat-form-field>
<mat-label>E-Mail</mat-label>
<mat-label>{{langs.currentLang?.email}}</mat-label>
<input type="text" matInput formControlName="email" required>
<mat-error *ngIf="form.hasError('required', 'email')">E-Mail ist erforderlich</mat-error>
<mat-error *ngIf="form.hasError('required', 'email')">{{langs.currentLang?.email}} {{langs.currentLang?.isRequired}}</mat-error>
<mat-error *ngIf="form.hasError('email', 'email') && !form.hasError('required', 'email')">
Bitte geben Sie eine gültige E-Mail-Adresse ein
{{langs.currentLang?.validEmail}}
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Passwort</mat-label>
<mat-label>{{langs.currentLang?.password}}</mat-label>
<input type="password" matInput formControlName="password" required>
<mat-error *ngIf="form.hasError('required', 'password')">Passwort ist erforderlich</mat-error>
<mat-error *ngIf="form.hasError('required', 'password')">{{langs.currentLang?.password}} {{langs.currentLang?.isRequired}}</mat-error>
</mat-form-field>
<mat-divider></mat-divider>
<span>Du besitzt keinen Account? <a routerLink="/register">Registrieren</a></span>
<span>{{langs.currentLang?.noAccount}} <a routerLink="/register">{{langs.currentLang?.register}}</a></span>
<mat-error *ngIf="error">{{error}}</mat-error>
<button type="submit" mat-button>Einloggen</button>
<button type="submit" mat-button>{{langs.currentLang?.login}}</button>
</form>
</mat-card-content>
</mat-card>

View File

@@ -1,8 +1,10 @@
import {Component} from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {FormControl, FormGroup, Validators} from "@angular/forms";
import {CrudService} from "../../services/crud.service";
import {User} from "../../entities/user";
import {Router} from "@angular/router";
import {Language} from "../../entities/language";
import {LangService} from "../../services/lang.service";
@Component({
selector: 'app-login',
@@ -16,7 +18,7 @@ export class LoginComponent {
});
public error: string;
public constructor(private crud: CrudService, private router: Router) {
public constructor(public langs: LangService, private crud: CrudService, private router: Router) {
this.form.reset();
this.error = "";
}
@@ -33,7 +35,7 @@ export class LoginComponent {
await this.crud.loadUser(true);
await this.router.navigate(["/dashboard"]);
}else {
this.error = "E-Mail oder Passwort ist falsch";
this.error = this.langs.currentLang.emailOrPasswordWrong;
}
}
}

View File

@@ -1,46 +1,46 @@
<mat-card id="content">
<mat-card-header>
<mat-card-title>Profil</mat-card-title>
<mat-card-subtitle>Einstellungen</mat-card-subtitle>
<mat-card-title>{{langs.currentLang?.profile}}</mat-card-title>
<mat-card-subtitle>{{langs.currentLang?.profileSub}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content id="main">
<form [formGroup]="form" (ngSubmit)="update()" id="form">
<mat-form-field>
<mat-label>E-Mail</mat-label>
<mat-label>{{langs.currentLang?.email}}</mat-label>
<input type="text" matInput formControlName="email" required>
<mat-error *ngIf="form.hasError('required', 'email')">E-Mail ist erforderlich</mat-error>
<mat-error *ngIf="form.hasError('required', 'email')">{{langs.currentLang?.email}} {{langs.currentLang?.isRequired}}</mat-error>
<mat-error *ngIf="form.hasError('email', 'email') && !form.hasError('required', 'email')">
Bitte geben Sie eine gültige E-Mail-Adresse ein
{{langs.currentLang?.validEmail}}
</mat-error>
<mat-error *ngIf="form.hasError('maxlength', 'email') && !form.hasError('required', 'email')">
Der eingegebene Wert ist zu lang
{{langs.currentLang?.valueToLong}}
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Benutzername</mat-label>
<mat-label>{{langs.currentLang?.username}}</mat-label>
<input type="text" matInput formControlName="username" required>
<mat-error *ngIf="form.hasError('required', 'username')">Benutzername ist erforderlich</mat-error>
<mat-error *ngIf="form.hasError('required', 'username')">{{langs.currentLang?.username}} {{langs.currentLang?.isRequired}}</mat-error>
<mat-error *ngIf="form.hasError('maxlength', 'username') && !form.hasError('required', 'username')">
Der eingegebene Wert ist zu lang
{{langs.currentLang?.valueToLong}}
</mat-error>
</mat-form-field>
<div>
<mat-form-field>
<mat-label>Passwort</mat-label>
<mat-label>{{langs.currentLang?.password}}</mat-label>
<input type="password" matInput formControlName="password">
<mat-error *ngIf="form.hasError('maxlength', 'password')">
Der eingegebene Wert ist zu lang
{{langs.currentLang?.valueToLong}}
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Passwort wiederholen</mat-label>
<mat-label>{{langs.currentLang?.passwordRepeat}}</mat-label>
<input type="password" matInput formControlName="passwordRepeat">
<mat-error *ngIf="form.hasError('maxlength', 'passwordRepeat')">
Der eingegebene Wert ist zu lang
{{langs.currentLang?.valueToLong}}
</mat-error>
</mat-form-field>
</div>
@@ -51,7 +51,7 @@
</mat-card-content>
<mat-card-actions id="actions">
<button mat-button color="primary" (click)="update()">Account aktualisieren</button>
<button mat-button color="warn" (click)="delete()">Account löschen</button>
<button mat-button color="primary" (click)="update()">{{langs.currentLang?.updateAccount}}</button>
<button mat-button color="warn" (click)="delete()">{{langs.currentLang?.deleteAccount}}</button>
</mat-card-actions>
</mat-card>

View File

@@ -1,4 +1,4 @@
import {Component} from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {CrudService} from "../../services/crud.service";
import {FormControl, FormGroup, Validators} from "@angular/forms";
import {MatDialog} from "@angular/material/dialog";
@@ -7,6 +7,8 @@ import {firstValueFrom} from "rxjs";
import {User} from "../../entities/user";
import {MatSnackBar} from "@angular/material/snack-bar";
import {Router} from "@angular/router";
import {Language} from "../../entities/language";
import {LangService} from "../../services/lang.service";
@Component({
selector: 'app-profile',
@@ -22,14 +24,14 @@ export class ProfileComponent {
});
public error: string;
public constructor(public crud: CrudService, private router: Router, public dialog: MatDialog, private snackBar: MatSnackBar) {
public constructor(public langs: LangService, public crud: CrudService, private router: Router, public dialog: MatDialog, private snackBar: MatSnackBar) {
this.form.get("email").setValue(this.crud.user?.email);
this.form.get("username").setValue(this.crud.user?.username);
}
public async update() {
if (!this.form.valid) return;
const result = await this.openDialog("Änderungen speichern?");
const result = await this.openDialog(this.langs.currentLang?.saveChanges);
if (!result) return;
this.error = "";
@@ -39,7 +41,7 @@ export class ProfileComponent {
const passwordRepeat = this.form.get("passwordRepeat").value;
if (password != passwordRepeat) {
this.error = "Passwörter stimmen nicht überein";
this.error = this.langs.currentLang?.passwordsDontMatch;
return;
}
@@ -47,25 +49,25 @@ export class ProfileComponent {
const response = await this.crud.sendPutRequest("users", user);
if (!response.success) {
this.error = "Aktualiserung fehlgeschlagen!";
this.error = this.langs.currentLang?.updateFailed;
return;
}
await this.crud.loadUser(true);
this.form.reset();
this.snackBar.open("Account aktualisiert!", undefined, {duration: 2000});
this.snackBar.open(this.langs.currentLang?.updateAccount, undefined, {duration: 2000});
await this.router.navigate(["dashboard"]);
}
public async delete() {
const result = await this.openDialog("Möchtest du deinen Account wirklich löschen?", "All deine Projekte werden für immer gelöscht!", ['', 'warn']);
const result = await this.openDialog(this.langs.currentLang?.deleteQuestion, this.langs.currentLang?.deleteWarning, ['', 'warn']);
if (!result) return;
await this.crud.sendDeleteRequest("users");
this.crud.setAuthKey(undefined);
this.crud.user = undefined;
this.snackBar.open("Account gelöscht!", undefined, {duration: 2000});
this.snackBar.open(this.langs.currentLang?.accountDeleted, undefined, {duration: 2000});
await this.router.navigate(["login"]);
}
@@ -75,8 +77,8 @@ export class ProfileComponent {
return new Promise<boolean>(async (resolve) => {
const dialogRef = this.dialog.open(DialogComponent, {
data: {title, subtitle, buttons: [
{text: "Abbrechen", value: false, color: colors[0]},
{text: "Bestätigen", value: true, color: colors[1]},
{text: this.langs.currentLang?.cancel, value: false, color: colors[0]},
{text: this.langs.currentLang?.submit, value: true, color: colors[1]},
]}
});

View File

@@ -1,53 +1,53 @@
<mat-card>
<mat-card-title>Registrieren</mat-card-title>
<mat-card-title>{{langs.currentLang?.register}}</mat-card-title>
<mat-divider></mat-divider>
<mat-card-content>
<form [formGroup]="form" (ngSubmit)="submit()">
<mat-form-field>
<mat-label>E-Mail</mat-label>
<mat-label>{{langs.currentLang?.email}}</mat-label>
<input type="text" matInput formControlName="email" required>
<mat-error *ngIf="form.hasError('required', 'email')">E-Mail ist erforderlich</mat-error>
<mat-error *ngIf="form.hasError('required', 'email')">{{langs.currentLang?.email}} {{langs.currentLang?.isRequired}}</mat-error>
<mat-error *ngIf="form.hasError('email', 'email') && !form.hasError('required', 'email')">
Bitte geben Sie eine gültige E-Mail-Adresse ein
{{langs.currentLang?.validEmail}}
</mat-error>
<mat-error *ngIf="form.hasError('maxlength', 'email') && !form.hasError('required', 'email')">
Der eingegebene Wert ist zu lang
{{langs.currentLang?.valueToLong}}
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Benutzername</mat-label>
<mat-label>{{langs.currentLang?.username}}</mat-label>
<input type="text" matInput formControlName="username" required>
<mat-error *ngIf="form.hasError('required', 'username')">Benutzername ist erforderlich</mat-error>
<mat-error *ngIf="form.hasError('required', 'username')">{{langs.currentLang?.username}} {{langs.currentLang?.isRequired}}</mat-error>
<mat-error *ngIf="form.hasError('maxlength', 'username') && !form.hasError('required', 'username')">
Der eingegebene Wert ist zu lang
{{langs.currentLang?.valueToLong}}
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Passwort</mat-label>
<mat-label>{{langs.currentLang?.password}}</mat-label>
<input type="password" matInput formControlName="password" required>
<mat-error *ngIf="form.hasError('required', 'password')">Passwort ist erforderlich</mat-error>
<mat-error *ngIf="form.hasError('required', 'password')">{{langs.currentLang?.password}} {{langs.currentLang?.isRequired}}</mat-error>
<mat-error *ngIf="form.hasError('maxlength', 'password') && !form.hasError('required', 'password')">
Der eingegebene Wert ist zu lang
{{langs.currentLang?.valueToLong}}
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Passwort wiederholen</mat-label>
<mat-label>{{langs.currentLang?.passwordRepeat}}</mat-label>
<input type="password" matInput formControlName="passwordRepeat" required>
<mat-error *ngIf="form.hasError('required', 'passwordRepeat')">Passwort ist erforderlich</mat-error>
<mat-error *ngIf="form.hasError('required', 'passwordRepeat')">{{langs.currentLang?.password}} {{langs.currentLang?.isRequired}}</mat-error>
<mat-error *ngIf="form.hasError('maxlength', 'passwordRepeat') && !form.hasError('required', 'passwordRepeat')">
Der eingegebene Wert ist zu lang
{{langs.currentLang?.valueToLong}}
</mat-error>
</mat-form-field>
<mat-divider></mat-divider>
<span>Du hast bereits einen Account? <a routerLink="/login">Einloggen</a></span>
<span>{{langs.currentLang?.alreadyAccount}} <a routerLink="/login">{{langs.currentLang?.login}}</a></span>
<mat-error *ngIf="error">{{error}}</mat-error>
<button type="submit" mat-button>Registrieren</button>
<button type="submit" mat-button>{{langs.currentLang?.register}}</button>
</form>
</mat-card-content>
</mat-card>

View File

@@ -1,8 +1,10 @@
import { Component } from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {FormControl, FormGroup, Validators} from "@angular/forms";
import {CrudService} from "../../services/crud.service";
import {Router} from "@angular/router";
import {User} from "../../entities/user";
import {Language} from "../../entities/language";
import {LangService} from "../../services/lang.service";
@Component({
selector: 'app-register',
@@ -18,7 +20,7 @@ export class RegisterComponent {
});
public error: string;
public constructor(private crud: CrudService, private router: Router) {}
public constructor(public langs: LangService, private crud: CrudService, private router: Router) {}
public async submit() {
this.error = "";
@@ -28,14 +30,14 @@ export class RegisterComponent {
const passwordRepeat = this.form.get("passwordRepeat").value;
if (password != passwordRepeat) {
this.error = "Passwörter stimmen nicht überein";
this.error = this.langs.currentLang?.passwordsDontMatch;
return;
}
const user: User = {email, username, password};
const result = await this.crud.sendPostRequest<{token: string}>("users/register", user);
if (!result.success) {
this.error = "Registrierung fehlgeschlagen";
this.error = this.langs.currentLang?.registerFailed;
return;
}

View File

@@ -0,0 +1,49 @@
{
"selectLang": "Sprache auswählen",
"design": "Farbmodus wählen",
"profileSettings": "Profil Einstellungen",
"dashboard": "Übersicht",
"logout": "Ausloggen",
"addProject": "Neues Projekt",
"projects": "Projekte",
"running": "Läuft",
"stopped": "Gestoppt",
"welcome": "Willkommen",
"noProjects": "Du hast noch keine Projekte erstellt",
"open": "Öffnen",
"edit": "Bearbeiten",
"delete": "Löschen",
"name": "Name",
"cancel": "Abbrechen",
"createProject": "Projekt erstellen",
"editProject": "Projekt bearbeiten",
"profile": "Profil",
"profileSub": "Einstellungen",
"email": "E-Mail",
"username": "Benutzername",
"password": "Passwort",
"passwordRepeat": "Passwort wiederholen",
"updateAccount": "Account aktualisieren",
"deleteAccount": "Account löschen",
"saveChanges": "Änderungen speichern?",
"updateFailed": "Aktualisierung fehlgeschlagen",
"accountUpdated": "Account aktualisiert!",
"deleteQuestion": "Möchtest du deinen Account wirklich löschen?",
"deleteWarning": "All deine Projekte werden für immer gelöscht!",
"accountDeleted": "Account gelöscht!",
"submit": "Bestätigen",
"login": "Einloggen",
"register": "Registrieren",
"noAccount": "Du besitzt keinen Account?",
"alreadyAccount": "Du hast bereits einen Account?",
"valueToLong": "Der eingegebene Wert ist zu lang",
"validEmail": "Gebe eine gültige E-Mail Addresse an",
"isRequired": "ist erforderlich",
"emailOrPasswordWrong": "E-Mail oder Passwort ist falsch",
"passwordsDontMatch": "Passwörter stimmen nicht überein",
"registerFailed": "Registrierung fehlgeschlagen"
}

View File

@@ -0,0 +1,49 @@
{
"selectLang": "Select language",
"design": "Design",
"profileSettings": "Profile settings",
"dashboard": "Dashboard",
"logout": "Logout",
"addProject": "Add Project",
"projects": "Projects",
"running": "Running",
"stopped": "Stopped",
"welcome": "Welcome",
"noProjects": "You have not created a Project yet",
"open": "Open",
"edit": "Edit",
"delete": "Delete",
"name": "Name",
"cancel": "Cancel",
"createProject": "Create project",
"editProject": "Edit project",
"profile": "Profile",
"profileSub": "Settings",
"email": "Email",
"username": "Username",
"password": "Password",
"passwordRepeat": "Repeat password",
"updateAccount": "Update account",
"deleteAccount": "Delete account",
"saveChanges": "Save changes?",
"updateFailed": "Update failed",
"accountUpdated": "Account updated",
"deleteQuestion": "Do you really want to delete your account?",
"deleteWarning": "All your data will be lost!",
"accountDeleted": "Account deleted!",
"submit": "Submit",
"login": "Login",
"register": "Register",
"noAccount": "You don't have a account?",
"alreadyAccount": "You already have an account?",
"valueToLong": "The entered value is to long",
"validEmail": "Please enter a valid Email address",
"isRequired": "is required",
"emailOrPasswordWrong": "Email or Password is wrong",
"passwordsDontMatch": "Passwords doesn't match",
"registerFailed": "Register failed"
}