Fixed minor issues + added language support
This commit is contained in:
@@ -82,6 +82,8 @@ public class ProjectApi : IProjectApi {
|
|||||||
await _docker.DeleteContainer(project.ContainerName);
|
await _docker.DeleteContainer(project.ContainerName);
|
||||||
|
|
||||||
await _proxy.RemoveLocation(project.ProxyId, project.CertificateId);
|
await _proxy.RemoveLocation(project.ProxyId, project.CertificateId);
|
||||||
|
|
||||||
|
Directory.Delete(_options.Root + projectId, true);
|
||||||
|
|
||||||
_context.Projects.Remove(project);
|
_context.Projects.Remove(project);
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Text;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using ProjectManager.Backend.Entities;
|
using ProjectManager.Backend.Entities;
|
||||||
|
|||||||
@@ -88,6 +88,16 @@ public class ProjectController : ControllerBase {
|
|||||||
return Redirect($"http://{_options.Host}:{project.Port}/_/");
|
return Redirect($"http://{_options.Host}:{project.Port}/_/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorized]
|
||||||
|
[HttpGet("{projectId}/url/string")]
|
||||||
|
public IActionResult GetProjectUrlHead(string projectId) {
|
||||||
|
var project = _projects.GetProject(projectId);
|
||||||
|
if (project == null) return NotFound();
|
||||||
|
if (project.OwnerId != _context.UserId) return Unauthorized();
|
||||||
|
if (_options.Enable) return Ok(new {url = $"https://{projectId}.{_options.Domain}/_/"});
|
||||||
|
return Ok(new {url = $"http://{_options.Host}:{project.Port}/_/"});
|
||||||
|
}
|
||||||
|
|
||||||
[Authorized]
|
[Authorized]
|
||||||
[HttpGet("{projectId}/start")]
|
[HttpGet("{projectId}/start")]
|
||||||
public async Task<IActionResult> StartProject(string projectId) {
|
public async Task<IActionResult> StartProject(string projectId) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ if (app.Environment.IsDevelopment()) {
|
|||||||
|
|
||||||
app.UseCors(
|
app.UseCors(
|
||||||
options => options
|
options => options
|
||||||
.WithOrigins(new []{app.Configuration.GetSection("Frontend").Get<string>() ?? ""})
|
.WithOrigins(app.Configuration.GetSection("Frontend").Get<string>() ?? "")
|
||||||
.AllowAnyMethod()
|
.AllowAnyMethod()
|
||||||
.AllowAnyHeader()
|
.AllowAnyHeader()
|
||||||
.AllowCredentials()
|
.AllowCredentials()
|
||||||
@@ -45,5 +45,10 @@ app.UseCors(
|
|||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
app.MapGet("", async context => {
|
||||||
|
context.Response.StatusCode = StatusCodes.Status200OK;
|
||||||
|
await context.Response.BodyWriter.WriteAsync("Ok"u8.ToArray());
|
||||||
|
await context.Response.BodyWriter.CompleteAsync();
|
||||||
|
});
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
@@ -3,7 +3,7 @@ import 'zone.js/node';
|
|||||||
import { APP_BASE_HREF } from '@angular/common';
|
import { APP_BASE_HREF } from '@angular/common';
|
||||||
import { ngExpressEngine } from '@nguniversal/express-engine';
|
import { ngExpressEngine } from '@nguniversal/express-engine';
|
||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
import { existsSync } from 'fs';
|
import { existsSync, readdirSync } from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
import { AppServerModule } from './src/main.server';
|
import { AppServerModule } from './src/main.server';
|
||||||
@@ -25,11 +25,16 @@ export function app(): express.Express {
|
|||||||
// Example Express Rest API endpoints
|
// Example Express Rest API endpoints
|
||||||
// server.get('/api/**', (req, res) => { });
|
// server.get('/api/**', (req, res) => { });
|
||||||
server.get('/backend', (req, res) => {
|
server.get('/backend', (req, res) => {
|
||||||
let backend = process.env['BACKEND']
|
let backend = process.env['BACKEND'] || "http://localhost:5110/";
|
||||||
if (!backend?.endsWith("/")) backend += "/";
|
if (!backend?.endsWith("/")) backend += "/";
|
||||||
res.json({url: 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
|
// Serve static files from /browser
|
||||||
server.get('*.*', express.static(distFolder, {
|
server.get('*.*', express.static(distFolder, {
|
||||||
maxAge: '1y'
|
maxAge: '1y'
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {MatSnackBarModule} from "@angular/material/snack-bar";
|
|||||||
import {MatTooltipModule} from "@angular/material/tooltip";
|
import {MatTooltipModule} from "@angular/material/tooltip";
|
||||||
import { TextDialogComponent } from './components/text-dialog/text-dialog.component';
|
import { TextDialogComponent } from './components/text-dialog/text-dialog.component';
|
||||||
import { ProjectComponent } from './sites/project/project.component';
|
import { ProjectComponent } from './sites/project/project.component';
|
||||||
|
import {MatMenuModule} from "@angular/material/menu";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -40,7 +41,7 @@ import { ProjectComponent } from './sites/project/project.component';
|
|||||||
ProjectComponent
|
ProjectComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule.withServerTransition({ appId: 'serverApp' }),
|
BrowserModule.withServerTransition({appId: 'serverApp'}),
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
@@ -57,7 +58,8 @@ import { ProjectComponent } from './sites/project/project.component';
|
|||||||
FormsModule,
|
FormsModule,
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
MatTooltipModule
|
MatTooltipModule,
|
||||||
|
MatMenuModule
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
|||||||
@@ -8,24 +8,24 @@
|
|||||||
<mat-selection-list id="actions">
|
<mat-selection-list id="actions">
|
||||||
<mat-list-item routerLink="/dashboard">
|
<mat-list-item routerLink="/dashboard">
|
||||||
<mat-icon matListItemIcon>dashboard</mat-icon>
|
<mat-icon matListItemIcon>dashboard</mat-icon>
|
||||||
<div matListItemTitle>Übersicht</div>
|
<div matListItemTitle>{{langs.currentLang?.dashboard}}</div>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
<mat-list-item (click)="logout()">
|
<mat-list-item (click)="logout()">
|
||||||
<mat-icon matListItemIcon>logout</mat-icon>
|
<mat-icon matListItemIcon>logout</mat-icon>
|
||||||
<div matListItemTitle>Ausloggen</div>
|
<div matListItemTitle>{{langs.currentLang?.logout}}</div>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
<mat-list-item (click)="createProject()">
|
<mat-list-item (click)="createProject()">
|
||||||
<mat-icon matListItemIcon>add</mat-icon>
|
<mat-icon matListItemIcon>add</mat-icon>
|
||||||
<div matListItemTitle>Neues Projekt</div>
|
<div matListItemTitle>{{langs.currentLang?.createProject}}</div>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<div mat-subheader>Projekte</div>
|
<div mat-subheader>{{langs.currentLang?.projects}}</div>
|
||||||
<mat-list-item *ngFor="let project of projects.projects" (click)="openProject(project.projectId)">
|
<mat-list-item *ngFor="let project of projects.projects" (click)="openProject(project.projectId)" class="project">
|
||||||
<mat-icon matListItemIcon>open_in_new</mat-icon>
|
<mat-icon matListItemIcon>open_in_new</mat-icon>
|
||||||
<div matListItemTitle>{{project.name}}</div>
|
<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-list-item>
|
||||||
</mat-selection-list>
|
</mat-selection-list>
|
||||||
|
|
||||||
@@ -37,8 +37,16 @@
|
|||||||
<span>Project Manager</span>
|
<span>Project Manager</span>
|
||||||
|
|
||||||
<section id="top-actions">
|
<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 [matMenuTriggerFor]="menu" [matTooltip]="langs.currentLang?.selectLang"><mat-icon>language</mat-icon></button>
|
||||||
<button mat-icon-button routerLink="/profile" *ngIf="showActions()" matTooltip="Profil Einstellungen"><mat-icon>account_circle</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>
|
</section>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ mat-drawer-container {
|
|||||||
height: calc(100vh - 80px);
|
height: calc(100vh - 80px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.project mat-icon {
|
||||||
|
margin-block: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {Component} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {Router} from "@angular/router";
|
import {Router} from "@angular/router";
|
||||||
import {CrudService} from "../../services/crud.service";
|
import {CrudService} from "../../services/crud.service";
|
||||||
import {ProjectService} from "../../services/project.service";
|
import {ProjectService} from "../../services/project.service";
|
||||||
@@ -7,6 +7,8 @@ import {TextDialogComponent} from "../text-dialog/text-dialog.component";
|
|||||||
import {firstValueFrom} from "rxjs";
|
import {firstValueFrom} from "rxjs";
|
||||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||||
import {StorageService} from "../../services/storage.service";
|
import {StorageService} from "../../services/storage.service";
|
||||||
|
import {LangService} from "../../services/lang.service";
|
||||||
|
import {Language} from "../../entities/language";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-navigation',
|
selector: 'app-navigation',
|
||||||
@@ -17,7 +19,7 @@ export class NavigationComponent {
|
|||||||
public static spinnerVisible: boolean = false;
|
public static spinnerVisible: boolean = false;
|
||||||
public darkMode: boolean;
|
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";
|
this.darkMode = storage.getItem("darkMode") == "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
54
ProjectManager.Frontend/src/app/entities/language.ts
Normal file
54
ProjectManager.Frontend/src/app/entities/language.ts
Normal 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,
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ export class CrudService {
|
|||||||
'Authorization': ''
|
'Authorization': ''
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(private client: HttpClient, private storage: StorageService) {
|
constructor(public client: HttpClient, private storage: StorageService) {
|
||||||
this.getBackendUrl().then(() => {
|
this.getBackendUrl().then(() => {
|
||||||
this.authKey = storage.getItem("api_key");
|
this.authKey = storage.getItem("api_key");
|
||||||
this.setAuthKey(this.authKey);
|
this.setAuthKey(this.authKey);
|
||||||
|
|||||||
41
ProjectManager.Frontend/src/app/services/lang.service.ts
Normal file
41
ProjectManager.Frontend/src/app/services/lang.service.ts
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<section id="main">
|
<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">
|
<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 *ngFor="let project of projects.projects" class="project">
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>{{project.name}}</mat-card-title>
|
<mat-card-title>{{project.name}}</mat-card-title>
|
||||||
@@ -11,9 +11,9 @@
|
|||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
|
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button mat-button color="primary" (click)="router.navigate(['/project', project.projectId])">Öffnen</button>
|
<button mat-button color="primary" (click)="openProject(project.projectId)">{{langs.currentLang?.open}}</button>
|
||||||
<button mat-button color="accent" (click)="editProject(project.projectId)">Bearbeiten</button>
|
<button mat-button color="accent" (click)="editProject(project.projectId)">{{langs.currentLang?.edit}}</button>
|
||||||
<button mat-button color="warn" (click)="deleteProject(project.projectId)">Löschen</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="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>
|
<button mat-icon-button color="accent" *ngIf="!project.running" (click)="updateProjectStatus(project.projectId, true)"><mat-icon>play_arrow</mat-icon></button>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component } from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {ProjectService} from "../../services/project.service";
|
import {ProjectService} from "../../services/project.service";
|
||||||
import {CrudService} from "../../services/crud.service";
|
import {CrudService} from "../../services/crud.service";
|
||||||
import {Router} from "@angular/router";
|
import {Router} from "@angular/router";
|
||||||
@@ -8,6 +8,9 @@ import {firstValueFrom} from "rxjs";
|
|||||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||||
import {TextDialogComponent} from "../../components/text-dialog/text-dialog.component";
|
import {TextDialogComponent} from "../../components/text-dialog/text-dialog.component";
|
||||||
import {NavigationComponent} from "../../components/navigation/navigation.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({
|
@Component({
|
||||||
selector: 'app-dashboard',
|
selector: 'app-dashboard',
|
||||||
@@ -16,7 +19,17 @@ import {NavigationComponent} from "../../components/navigation/navigation.compon
|
|||||||
})
|
})
|
||||||
export class DashboardComponent {
|
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) {
|
public async editProject(projectId: string) {
|
||||||
const dialogRef = this.dialog.open(TextDialogComponent, {
|
const dialogRef = this.dialog.open(TextDialogComponent, {
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-title>Einloggen</mat-card-title>
|
<mat-card-title>{{langs.currentLang?.login}}</mat-card-title>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<form [formGroup]="form" (ngSubmit)="submit()">
|
<form [formGroup]="form" (ngSubmit)="submit()">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>E-Mail</mat-label>
|
<mat-label>{{langs.currentLang?.email}}</mat-label>
|
||||||
<input type="text" matInput formControlName="email" required>
|
<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')">
|
<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>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<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>
|
<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-form-field>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<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>
|
<mat-error *ngIf="error">{{error}}</mat-error>
|
||||||
|
|
||||||
<button type="submit" mat-button>Einloggen</button>
|
<button type="submit" mat-button>{{langs.currentLang?.login}}</button>
|
||||||
</form>
|
</form>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import {Component} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {FormControl, FormGroup, Validators} from "@angular/forms";
|
import {FormControl, FormGroup, Validators} from "@angular/forms";
|
||||||
import {CrudService} from "../../services/crud.service";
|
import {CrudService} from "../../services/crud.service";
|
||||||
import {User} from "../../entities/user";
|
import {User} from "../../entities/user";
|
||||||
import {Router} from "@angular/router";
|
import {Router} from "@angular/router";
|
||||||
|
import {Language} from "../../entities/language";
|
||||||
|
import {LangService} from "../../services/lang.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-login',
|
selector: 'app-login',
|
||||||
@@ -16,7 +18,7 @@ export class LoginComponent {
|
|||||||
});
|
});
|
||||||
public error: string;
|
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.form.reset();
|
||||||
this.error = "";
|
this.error = "";
|
||||||
}
|
}
|
||||||
@@ -33,7 +35,7 @@ export class LoginComponent {
|
|||||||
await this.crud.loadUser(true);
|
await this.crud.loadUser(true);
|
||||||
await this.router.navigate(["/dashboard"]);
|
await this.router.navigate(["/dashboard"]);
|
||||||
}else {
|
}else {
|
||||||
this.error = "E-Mail oder Passwort ist falsch";
|
this.error = this.langs.currentLang.emailOrPasswordWrong;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,46 @@
|
|||||||
<mat-card id="content">
|
<mat-card id="content">
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>Profil</mat-card-title>
|
<mat-card-title>{{langs.currentLang?.profile}}</mat-card-title>
|
||||||
<mat-card-subtitle>Einstellungen</mat-card-subtitle>
|
<mat-card-subtitle>{{langs.currentLang?.profileSub}}</mat-card-subtitle>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
|
|
||||||
<mat-card-content id="main">
|
<mat-card-content id="main">
|
||||||
<form [formGroup]="form" (ngSubmit)="update()" id="form">
|
<form [formGroup]="form" (ngSubmit)="update()" id="form">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>E-Mail</mat-label>
|
<mat-label>{{langs.currentLang?.email}}</mat-label>
|
||||||
<input type="text" matInput formControlName="email" required>
|
<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')">
|
<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>
|
||||||
<mat-error *ngIf="form.hasError('maxlength', 'email') && !form.hasError('required', 'email')">
|
<mat-error *ngIf="form.hasError('maxlength', 'email') && !form.hasError('required', 'email')">
|
||||||
Der eingegebene Wert ist zu lang
|
{{langs.currentLang?.valueToLong}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<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>
|
<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')">
|
<mat-error *ngIf="form.hasError('maxlength', 'username') && !form.hasError('required', 'username')">
|
||||||
Der eingegebene Wert ist zu lang
|
{{langs.currentLang?.valueToLong}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Passwort</mat-label>
|
<mat-label>{{langs.currentLang?.password}}</mat-label>
|
||||||
<input type="password" matInput formControlName="password">
|
<input type="password" matInput formControlName="password">
|
||||||
<mat-error *ngIf="form.hasError('maxlength', 'password')">
|
<mat-error *ngIf="form.hasError('maxlength', 'password')">
|
||||||
Der eingegebene Wert ist zu lang
|
{{langs.currentLang?.valueToLong}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<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">
|
<input type="password" matInput formControlName="passwordRepeat">
|
||||||
<mat-error *ngIf="form.hasError('maxlength', 'passwordRepeat')">
|
<mat-error *ngIf="form.hasError('maxlength', 'passwordRepeat')">
|
||||||
Der eingegebene Wert ist zu lang
|
{{langs.currentLang?.valueToLong}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
|
|
||||||
<mat-card-actions id="actions">
|
<mat-card-actions id="actions">
|
||||||
<button mat-button color="primary" (click)="update()">Account aktualisieren</button>
|
<button mat-button color="primary" (click)="update()">{{langs.currentLang?.updateAccount}}</button>
|
||||||
<button mat-button color="warn" (click)="delete()">Account löschen</button>
|
<button mat-button color="warn" (click)="delete()">{{langs.currentLang?.deleteAccount}}</button>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {Component} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {CrudService} from "../../services/crud.service";
|
import {CrudService} from "../../services/crud.service";
|
||||||
import {FormControl, FormGroup, Validators} from "@angular/forms";
|
import {FormControl, FormGroup, Validators} from "@angular/forms";
|
||||||
import {MatDialog} from "@angular/material/dialog";
|
import {MatDialog} from "@angular/material/dialog";
|
||||||
@@ -7,6 +7,8 @@ import {firstValueFrom} from "rxjs";
|
|||||||
import {User} from "../../entities/user";
|
import {User} from "../../entities/user";
|
||||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||||
import {Router} from "@angular/router";
|
import {Router} from "@angular/router";
|
||||||
|
import {Language} from "../../entities/language";
|
||||||
|
import {LangService} from "../../services/lang.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-profile',
|
selector: 'app-profile',
|
||||||
@@ -22,14 +24,14 @@ export class ProfileComponent {
|
|||||||
});
|
});
|
||||||
public error: string;
|
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("email").setValue(this.crud.user?.email);
|
||||||
this.form.get("username").setValue(this.crud.user?.username);
|
this.form.get("username").setValue(this.crud.user?.username);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async update() {
|
public async update() {
|
||||||
if (!this.form.valid) return;
|
if (!this.form.valid) return;
|
||||||
const result = await this.openDialog("Änderungen speichern?");
|
const result = await this.openDialog(this.langs.currentLang?.saveChanges);
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
|
|
||||||
this.error = "";
|
this.error = "";
|
||||||
@@ -39,7 +41,7 @@ export class ProfileComponent {
|
|||||||
const passwordRepeat = this.form.get("passwordRepeat").value;
|
const passwordRepeat = this.form.get("passwordRepeat").value;
|
||||||
|
|
||||||
if (password != passwordRepeat) {
|
if (password != passwordRepeat) {
|
||||||
this.error = "Passwörter stimmen nicht überein";
|
this.error = this.langs.currentLang?.passwordsDontMatch;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,25 +49,25 @@ export class ProfileComponent {
|
|||||||
|
|
||||||
const response = await this.crud.sendPutRequest("users", user);
|
const response = await this.crud.sendPutRequest("users", user);
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
this.error = "Aktualiserung fehlgeschlagen!";
|
this.error = this.langs.currentLang?.updateFailed;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.crud.loadUser(true);
|
await this.crud.loadUser(true);
|
||||||
this.form.reset();
|
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"]);
|
await this.router.navigate(["dashboard"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async delete() {
|
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;
|
if (!result) return;
|
||||||
|
|
||||||
await this.crud.sendDeleteRequest("users");
|
await this.crud.sendDeleteRequest("users");
|
||||||
|
|
||||||
this.crud.setAuthKey(undefined);
|
this.crud.setAuthKey(undefined);
|
||||||
this.crud.user = 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"]);
|
await this.router.navigate(["login"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,8 +77,8 @@ export class ProfileComponent {
|
|||||||
return new Promise<boolean>(async (resolve) => {
|
return new Promise<boolean>(async (resolve) => {
|
||||||
const dialogRef = this.dialog.open(DialogComponent, {
|
const dialogRef = this.dialog.open(DialogComponent, {
|
||||||
data: {title, subtitle, buttons: [
|
data: {title, subtitle, buttons: [
|
||||||
{text: "Abbrechen", value: false, color: colors[0]},
|
{text: this.langs.currentLang?.cancel, value: false, color: colors[0]},
|
||||||
{text: "Bestätigen", value: true, color: colors[1]},
|
{text: this.langs.currentLang?.submit, value: true, color: colors[1]},
|
||||||
]}
|
]}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,53 +1,53 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-title>Registrieren</mat-card-title>
|
<mat-card-title>{{langs.currentLang?.register}}</mat-card-title>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<form [formGroup]="form" (ngSubmit)="submit()">
|
<form [formGroup]="form" (ngSubmit)="submit()">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>E-Mail</mat-label>
|
<mat-label>{{langs.currentLang?.email}}</mat-label>
|
||||||
<input type="text" matInput formControlName="email" required>
|
<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')">
|
<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>
|
||||||
<mat-error *ngIf="form.hasError('maxlength', 'email') && !form.hasError('required', 'email')">
|
<mat-error *ngIf="form.hasError('maxlength', 'email') && !form.hasError('required', 'email')">
|
||||||
Der eingegebene Wert ist zu lang
|
{{langs.currentLang?.valueToLong}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<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>
|
<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')">
|
<mat-error *ngIf="form.hasError('maxlength', 'username') && !form.hasError('required', 'username')">
|
||||||
Der eingegebene Wert ist zu lang
|
{{langs.currentLang?.valueToLong}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<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>
|
<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')">
|
<mat-error *ngIf="form.hasError('maxlength', 'password') && !form.hasError('required', 'password')">
|
||||||
Der eingegebene Wert ist zu lang
|
{{langs.currentLang?.valueToLong}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<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>
|
<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')">
|
<mat-error *ngIf="form.hasError('maxlength', 'passwordRepeat') && !form.hasError('required', 'passwordRepeat')">
|
||||||
Der eingegebene Wert ist zu lang
|
{{langs.currentLang?.valueToLong}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<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>
|
<mat-error *ngIf="error">{{error}}</mat-error>
|
||||||
|
|
||||||
<button type="submit" mat-button>Registrieren</button>
|
<button type="submit" mat-button>{{langs.currentLang?.register}}</button>
|
||||||
</form>
|
</form>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { Component } from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {FormControl, FormGroup, Validators} from "@angular/forms";
|
import {FormControl, FormGroup, Validators} from "@angular/forms";
|
||||||
import {CrudService} from "../../services/crud.service";
|
import {CrudService} from "../../services/crud.service";
|
||||||
import {Router} from "@angular/router";
|
import {Router} from "@angular/router";
|
||||||
import {User} from "../../entities/user";
|
import {User} from "../../entities/user";
|
||||||
|
import {Language} from "../../entities/language";
|
||||||
|
import {LangService} from "../../services/lang.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-register',
|
selector: 'app-register',
|
||||||
@@ -18,7 +20,7 @@ export class RegisterComponent {
|
|||||||
});
|
});
|
||||||
public error: string;
|
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() {
|
public async submit() {
|
||||||
this.error = "";
|
this.error = "";
|
||||||
@@ -28,14 +30,14 @@ export class RegisterComponent {
|
|||||||
const passwordRepeat = this.form.get("passwordRepeat").value;
|
const passwordRepeat = this.form.get("passwordRepeat").value;
|
||||||
|
|
||||||
if (password != passwordRepeat) {
|
if (password != passwordRepeat) {
|
||||||
this.error = "Passwörter stimmen nicht überein";
|
this.error = this.langs.currentLang?.passwordsDontMatch;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const user: User = {email, username, password};
|
const user: User = {email, username, password};
|
||||||
const result = await this.crud.sendPostRequest<{token: string}>("users/register", user);
|
const result = await this.crud.sendPostRequest<{token: string}>("users/register", user);
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
this.error = "Registrierung fehlgeschlagen";
|
this.error = this.langs.currentLang?.registerFailed;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
49
ProjectManager.Frontend/src/assets/languages/de-DE.json
Normal file
49
ProjectManager.Frontend/src/assets/languages/de-DE.json
Normal 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"
|
||||||
|
}
|
||||||
49
ProjectManager.Frontend/src/assets/languages/en-US.json
Normal file
49
ProjectManager.Frontend/src/assets/languages/en-US.json
Normal 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"
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ Es handelt sich hierbei um ein einfach zu benutzendes WebInterface zum Erstellen
|
|||||||
- [x] Automatische Docker Konfiguration
|
- [x] Automatische Docker Konfiguration
|
||||||
- [x] Automatisches DNS Mapping
|
- [x] Automatisches DNS Mapping
|
||||||
- [x] Automatische SSL-Konfiguration mithilfe von NginxProxyManager
|
- [x] Automatische SSL-Konfiguration mithilfe von NginxProxyManager
|
||||||
- [ ] Projekt Transferierung auf verschiedene Nodes
|
- [ ] Projekte exportieren / importieren
|
||||||
- [ ] Eigene Domains
|
- [ ] Eigene Domains
|
||||||
- [ ] Mehrere Sprachen
|
- [ ] Mehrere Sprachen
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ services:
|
|||||||
|
|
||||||
### SourceCode bearbeiten und Docker Images selber erstellen
|
### SourceCode bearbeiten und Docker Images selber erstellen
|
||||||
Falls Sie den SourceCode selbst bearbeiten wollen, steht Ihnen dieser natürlich zur Verfügung. Um das Backend im Debug Modus zu verwenden sollten sie eine
|
Falls Sie den SourceCode selbst bearbeiten wollen, steht Ihnen dieser natürlich zur Verfügung. Um das Backend im Debug Modus zu verwenden sollten sie eine
|
||||||
``appsettings.Development.json`` Datei im Hauptverzeichnis anlegen um dort die entsprechende Konfiguration für die Entwicklungsumgebung erstellen.
|
``appsettings.Development.json`` Datei im Hauptverzeichnis anlegen, um dort die entsprechende Konfiguration für die Entwicklungsumgebung erstellen.
|
||||||
Zum Debuggen empfehle ich ``npm run dev:ssr`` um das Frontend zu starten und ``dotnet run`` um das Backend zu starten. Sofern Sie mit den Bearbeitungen fertig
|
Zum Debuggen empfehle ich ``npm run dev:ssr`` um das Frontend zu starten und ``dotnet run`` um das Backend zu starten. Sofern Sie mit den Bearbeitungen fertig
|
||||||
sind, gibt es eine ``docker-compose.example.yml`` Datei im dem Repository die automatisch den SoruceCode neu baut und die Container startet.
|
sind, gibt es eine ``docker-compose.example.yml`` Datei im dem Repository die automatisch den SoruceCode neu baut und die Container startet.
|
||||||
Wahlweise können Sie diese mit ``docker build`` auch selbst bauen.
|
Wahlweise können Sie diese mit ``docker build`` auch selbst bauen.
|
||||||
|
|||||||
Reference in New Issue
Block a user