generated from flo/template-frontend
changes
This commit is contained in:
parent
0499c81924
commit
9145bc245f
@ -1 +1 @@
|
|||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
|
|||||||
@ -1,18 +1,17 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { AuthService } from './core/services/auth.service';
|
import { AuthService } from "./core/services/auth.service";
|
||||||
import { AppService } from './core/services/app.service';
|
import { AppService } from "./core/services/app.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: "app-root",
|
||||||
templateUrl: './app.component.html',
|
templateUrl: "./app.component.html",
|
||||||
styleUrls: ['./app.component.scss']
|
styleUrls: ["./app.component.scss"],
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
constructor(
|
constructor(
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private appService: AppService,
|
private appService: AppService
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.authService.readUserState();
|
this.authService.readUserState();
|
||||||
|
|||||||
@ -1,21 +1,28 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from "@angular/core";
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from "@angular/platform-browser";
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from "@angular/common/http";
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from "./app.component";
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from "@angular/router";
|
||||||
import { SharedModule } from './shared/shared.module';
|
import { SharedModule } from "./shared/shared.module";
|
||||||
import { HomeComponent } from './core/components/home/home.component';
|
import { HomeComponent } from "./core/components/home/home.component";
|
||||||
import { CoreModule } from './core/core.module';
|
import { CoreModule } from "./core/core.module";
|
||||||
import { AuthGuard } from './core/guards/auth.guard';
|
import { AuthGuard } from "./core/guards/auth.guard";
|
||||||
import { SettingsComponent } from './core/components/settings/settings.component';
|
import { SettingsComponent } from "./core/components/settings/settings.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: 'auth', loadChildren: () => import('./core/auth/auth.module').then(m => m.AuthModule) },
|
{
|
||||||
{ path: '', component: HomeComponent, canActivate: [AuthGuard], children: [
|
path: "auth",
|
||||||
{path: 'settings', component: SettingsComponent}
|
loadChildren: () =>
|
||||||
]},
|
import("./core/auth/auth.module").then((m) => m.AuthModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
component: HomeComponent,
|
||||||
|
canActivate: [AuthGuard],
|
||||||
|
children: [{ path: "settings", component: SettingsComponent }],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -24,6 +31,7 @@ const routes: Routes = [
|
|||||||
BrowserModule,
|
BrowserModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
|
RouterModule,
|
||||||
RouterModule.forRoot(routes),
|
RouterModule.forRoot(routes),
|
||||||
SharedModule,
|
SharedModule,
|
||||||
CoreModule,
|
CoreModule,
|
||||||
|
|||||||
@ -1,33 +1,32 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from "@angular/core";
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from "@angular/common";
|
||||||
import { LoginComponent } from './components/login/login.component';
|
import { LoginComponent } from "./components/login/login.component";
|
||||||
import { RegistrationComponent } from './components/registration/registration.component';
|
import { RegistrationComponent } from "./components/registration/registration.component";
|
||||||
import { ConfirmRegistrationComponent } from './components/confirm-registration/confirm-registration.component';
|
import { ConfirmRegistrationComponent } from "./components/confirm-registration/confirm-registration.component";
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from "@angular/router";
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from "@angular/forms";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: 'login', component: LoginComponent },
|
{ path: "login", component: LoginComponent },
|
||||||
{ path: 'registration', component: RegistrationComponent },
|
{ path: "registration", component: RegistrationComponent },
|
||||||
{ path: 'registration/:registrationId', component: ConfirmRegistrationComponent },
|
{
|
||||||
{ path: '', redirectTo: 'login', pathMatch: 'full' },
|
path: "registration/:registrationId",
|
||||||
|
component: ConfirmRegistrationComponent,
|
||||||
|
},
|
||||||
|
{ path: "", redirectTo: "login", pathMatch: "full" },
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
LoginComponent,
|
LoginComponent,
|
||||||
RegistrationComponent,
|
RegistrationComponent,
|
||||||
ConfirmRegistrationComponent
|
ConfirmRegistrationComponent,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
LoginComponent,
|
LoginComponent,
|
||||||
RegistrationComponent,
|
RegistrationComponent,
|
||||||
ConfirmRegistrationComponent
|
ConfirmRegistrationComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [RouterModule.forChild(routes), CommonModule, ReactiveFormsModule],
|
||||||
RouterModule.forChild(routes),
|
|
||||||
CommonModule,
|
|
||||||
ReactiveFormsModule
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
export class AuthModule { }
|
export class AuthModule {}
|
||||||
|
|||||||
@ -1,23 +1,49 @@
|
|||||||
<div class="mb-10">
|
<div class="mb-10"></div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto mb-10">
|
<div class="max-w-sm mx-auto mb-10">
|
||||||
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
||||||
Beekeeper
|
Beekeeper
|
||||||
</h1>
|
</h1>
|
||||||
<h1 class="font-bold text-center text-skin-accent text-xl">
|
<h1 class="font-bold text-center text-skin-accent text-xl">
|
||||||
Registrierung Abschließen
|
Registrierung Abschließen
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form class="max-w-sm mx-auto" [formGroup]="confirmRegistrationForm">
|
<form class="max-w-sm mx-auto" [formGroup]="confirmRegistrationForm">
|
||||||
<div class="mb-5">
|
<div class="mb-5">
|
||||||
<label for="password" class="block mb-2 text-sm font-medium text-skin-primary-muted">Passwort</label>
|
<label
|
||||||
<input formControlName="password" type="password" id="password" class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required />
|
for="password"
|
||||||
</div>
|
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||||
<div class="mb-5">
|
>Passwort</label
|
||||||
<label for="passwordConfirmation" class="block mb-2 text-sm font-medium text-skin-primary-muted">Passwort wiederholen</label>
|
>
|
||||||
<input formControlName="passwordConfirmation" type="password" id="passwordConfirmation" class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required />
|
<input
|
||||||
</div>
|
formControlName="password"
|
||||||
<button (click)="confirm()" [disabled]="!confirmRegistrationForm.valid" type="submit" class="w-full 9xl:w-auto font-bold text-skin-secondary bg-skin-accent hover:text-skin-primary rounded-lg text-sm px-5 py-2.5 text-center">Registrieren</button>
|
type="password"
|
||||||
|
id="password"
|
||||||
|
class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-5">
|
||||||
|
<label
|
||||||
|
for="passwordConfirmation"
|
||||||
|
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||||
|
>Passwort wiederholen</label
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
formControlName="passwordConfirmation"
|
||||||
|
type="password"
|
||||||
|
id="passwordConfirmation"
|
||||||
|
class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
(click)="confirm()"
|
||||||
|
[disabled]="!confirmRegistrationForm.valid"
|
||||||
|
type="submit"
|
||||||
|
class="w-full 9xl:w-auto font-bold text-skin-secondary bg-skin-accent hover:text-skin-primary rounded-lg text-sm px-5 py-2.5 text-center"
|
||||||
|
>
|
||||||
|
Registrieren
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from "@angular/core";
|
||||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { filter } from 'rxjs';
|
import { filter } from "rxjs";
|
||||||
import { AuthService } from 'src/app/core/services/auth.service';
|
import { AuthService } from "src/app/core/services/auth.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-confirm-registration',
|
selector: "app-confirm-registration",
|
||||||
templateUrl: './confirm-registration.component.html',
|
templateUrl: "./confirm-registration.component.html",
|
||||||
styleUrls: ['./confirm-registration.component.scss']
|
styleUrls: ["./confirm-registration.component.scss"],
|
||||||
})
|
})
|
||||||
export class ConfirmRegistrationComponent {
|
export class ConfirmRegistrationComponent {
|
||||||
confirmRegistrationForm = new FormGroup({
|
confirmRegistrationForm = new FormGroup({
|
||||||
password: new FormControl('', [Validators.required]),
|
password: new FormControl("", [Validators.required]),
|
||||||
passwordConfirmation: new FormControl('', [Validators.required]),
|
passwordConfirmation: new FormControl("", [Validators.required]),
|
||||||
});
|
});
|
||||||
|
|
||||||
registrationId: string | undefined;
|
registrationId: string | undefined;
|
||||||
@ -22,27 +22,23 @@ export class ConfirmRegistrationComponent {
|
|||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
private router: Router
|
private router: Router
|
||||||
) {
|
) {
|
||||||
this.activatedRoute.params.subscribe(
|
this.activatedRoute.params.subscribe((params) => {
|
||||||
(params) => {
|
this.registrationId = params["registrationId"];
|
||||||
this.registrationId = params['registrationId'];
|
});
|
||||||
}
|
|
||||||
);
|
this.authService.currentState$
|
||||||
|
.pipe(filter((state) => state !== undefined && state !== null))
|
||||||
this.authService.currentState$.pipe(
|
.subscribe((state) => this.router.navigateByUrl("/"));
|
||||||
filter(state=>state !== undefined && state !== null)
|
|
||||||
).subscribe((state) =>
|
|
||||||
this.router.navigateByUrl('/')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
confirm(): void {
|
confirm(): void {
|
||||||
if (this.registrationId === undefined)
|
if (this.registrationId === undefined) return;
|
||||||
return;
|
|
||||||
|
|
||||||
this.authService.confirmRegistration({
|
this.authService.confirmRegistration({
|
||||||
id: this.registrationId!,
|
id: this.registrationId!,
|
||||||
password: this.confirmRegistrationForm.value.password!,
|
password: this.confirmRegistrationForm.value.password!,
|
||||||
passwordConfirmation: this.confirmRegistrationForm.value.passwordConfirmation!
|
passwordConfirmation:
|
||||||
|
this.confirmRegistrationForm.value.passwordConfirmation!,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,59 @@
|
|||||||
<div class="mb-10">
|
<div class="mb-10"></div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto mb-10">
|
<div class="max-w-sm mx-auto mb-10">
|
||||||
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
||||||
Beekeeper
|
Beekeeper
|
||||||
</h1>
|
</h1>
|
||||||
<h1 class="font-bold text-center text-skin-accent text-xl">
|
<h1 class="font-bold text-center text-skin-accent text-xl">Anmeldung</h1>
|
||||||
Anmeldung
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form class="max-w-sm mx-auto" [formGroup]="loginForm">
|
<form class="max-w-sm mx-auto" [formGroup]="loginForm">
|
||||||
<div class="mb-5">
|
<div class="mb-5">
|
||||||
<label for="identifier" class="block mb-2 text-sm font-medium text-skin-primary-muted">Benutzername oder E-Mail</label>
|
<label
|
||||||
<input formControlName="identifier" type="text" id="identifier" class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" placeholder="username72 / your@email.com" required />
|
for="identifier"
|
||||||
</div>
|
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||||
<div class="mb-5">
|
>Benutzername oder E-Mail</label
|
||||||
<label for="password" class="block mb-2 text-sm font-medium text-skin-primary-muted">Passwort</label>
|
>
|
||||||
<input formControlName="password" type="password" id="password" class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required />
|
<input
|
||||||
<p id="helper-text-explanation" class="mt-2 text-sm text-skin-primary-muted">Neu hier? <a routerLink="/auth/registration" class="font-medium text-skin-accent hover:underline hover:font-bold">Jetzt registrieren!</a></p>
|
formControlName="identifier"
|
||||||
</div>
|
type="text"
|
||||||
<button (click)="login()" [disabled]="!loginForm.valid" type="submit" class="w-full 9xl:w-auto font-bold text-skin-secondary bg-skin-accent hover:text-skin-primary rounded-lg text-sm px-5 py-2.5 text-center">Anmelden</button>
|
id="identifier"
|
||||||
|
class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||||
|
placeholder="username72 / your@email.com"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-5">
|
||||||
|
<label
|
||||||
|
for="password"
|
||||||
|
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||||
|
>Passwort</label
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
formControlName="password"
|
||||||
|
type="password"
|
||||||
|
id="password"
|
||||||
|
class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<p
|
||||||
|
id="helper-text-explanation"
|
||||||
|
class="mt-2 text-sm text-skin-primary-muted"
|
||||||
|
>
|
||||||
|
Neu hier?
|
||||||
|
<a
|
||||||
|
routerLink="/auth/registration"
|
||||||
|
class="font-medium text-skin-accent hover:underline hover:font-bold"
|
||||||
|
>Jetzt registrieren!</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
(click)="login()"
|
||||||
|
[disabled]="!loginForm.valid"
|
||||||
|
type="submit"
|
||||||
|
class="w-full 9xl:w-auto font-bold text-skin-secondary bg-skin-accent hover:text-skin-primary rounded-lg text-sm px-5 py-2.5 text-center"
|
||||||
|
>
|
||||||
|
Anmelden
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -1,35 +1,30 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from "@angular/core";
|
||||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||||
import { Router } from '@angular/router';
|
import { Router } from "@angular/router";
|
||||||
import { filter, map } from 'rxjs';
|
import { filter, map } from "rxjs";
|
||||||
import { AuthService } from 'src/app/core/services/auth.service';
|
import { AuthService } from "src/app/core/services/auth.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-login',
|
selector: "app-login",
|
||||||
templateUrl: './login.component.html',
|
templateUrl: "./login.component.html",
|
||||||
styleUrls: ['./login.component.scss']
|
styleUrls: ["./login.component.scss"],
|
||||||
})
|
})
|
||||||
export class LoginComponent {
|
export class LoginComponent {
|
||||||
loginForm = new FormGroup({
|
loginForm = new FormGroup({
|
||||||
identifier: new FormControl('', [Validators.required]),
|
identifier: new FormControl("", [Validators.required]),
|
||||||
password: new FormControl('', [Validators.required]),
|
password: new FormControl("", [Validators.required]),
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(
|
constructor(private authService: AuthService, private router: Router) {
|
||||||
private authService: AuthService,
|
this.authService.currentState$
|
||||||
private router: Router
|
.pipe(filter((state) => state !== undefined && state !== null))
|
||||||
) {
|
.subscribe((state) => this.router.navigateByUrl("/"));
|
||||||
this.authService.currentState$.pipe(
|
|
||||||
filter(state=>state !== undefined && state !== null)
|
|
||||||
).subscribe((state) =>
|
|
||||||
this.router.navigateByUrl('/')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
login(): void {
|
login(): void {
|
||||||
this.authService.login({
|
this.authService.login({
|
||||||
identifier: this.loginForm.value.identifier!,
|
identifier: this.loginForm.value.identifier!,
|
||||||
password: this.loginForm.value.password!
|
password: this.loginForm.value.password!,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,59 @@
|
|||||||
<div class="mb-10">
|
<div class="mb-10"></div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto mb-10">
|
<div class="max-w-sm mx-auto mb-10">
|
||||||
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
||||||
Beekeeper
|
Beekeeper
|
||||||
</h1>
|
</h1>
|
||||||
<h1 class="font-bold text-center text-skin-accent text-xl">
|
<h1 class="font-bold text-center text-skin-accent text-xl">Registrierung</h1>
|
||||||
Registrierung
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form class="max-w-sm mx-auto" [formGroup]="registrationForm">
|
<form class="max-w-sm mx-auto" [formGroup]="registrationForm">
|
||||||
<div class="mb-5">
|
<div class="mb-5">
|
||||||
<label for="mail" class="block mb-2 text-sm font-medium text-skin-primary-muted">E-Mail</label>
|
<label
|
||||||
<input formControlName="mail" type="mail" id="mail" class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" placeholder="your@email.com" required />
|
for="mail"
|
||||||
</div>
|
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||||
<div class="mb-5">
|
>E-Mail</label
|
||||||
<label for="username" class="block mb-2 text-sm font-medium text-skin-primary-muted">Benutzername</label>
|
>
|
||||||
<input formControlName="username" type="string" id="username" class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required />
|
<input
|
||||||
<p id="helper-text-explanation" class="mt-2 text-sm text-skin-primary-muted">Bereits registiert? <a routerLink="/auth/login" class="font-medium text-skin-accent hover:underline hover:font-bold">Jetzt anmelden!</a></p>
|
formControlName="mail"
|
||||||
</div>
|
type="mail"
|
||||||
<button (click)="register()" [disabled]="!registrationForm.valid" type="submit" class="w-full 9xl:w-auto font-bold text-skin-secondary bg-skin-accent hover:text-skin-primary rounded-lg text-sm px-5 py-2.5 text-center">Registrieren</button>
|
id="mail"
|
||||||
|
class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||||
|
placeholder="your@email.com"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-5">
|
||||||
|
<label
|
||||||
|
for="username"
|
||||||
|
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||||
|
>Benutzername</label
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
formControlName="username"
|
||||||
|
type="string"
|
||||||
|
id="username"
|
||||||
|
class="bg-skin-primary border border-gray-300 text-skin-primary text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<p
|
||||||
|
id="helper-text-explanation"
|
||||||
|
class="mt-2 text-sm text-skin-primary-muted"
|
||||||
|
>
|
||||||
|
Bereits registiert?
|
||||||
|
<a
|
||||||
|
routerLink="/auth/login"
|
||||||
|
class="font-medium text-skin-accent hover:underline hover:font-bold"
|
||||||
|
>Jetzt anmelden!</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
(click)="register()"
|
||||||
|
[disabled]="!registrationForm.valid"
|
||||||
|
type="submit"
|
||||||
|
class="w-full 9xl:w-auto font-bold text-skin-secondary bg-skin-accent hover:text-skin-primary rounded-lg text-sm px-5 py-2.5 text-center"
|
||||||
|
>
|
||||||
|
Registrieren
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -1,37 +1,32 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from "@angular/core";
|
||||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||||
import { Router } from '@angular/router';
|
import { Router } from "@angular/router";
|
||||||
import { filter } from 'rxjs';
|
import { filter } from "rxjs";
|
||||||
import { AuthService } from 'src/app/core/services/auth.service';
|
import { AuthService } from "src/app/core/services/auth.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-registration',
|
selector: "app-registration",
|
||||||
templateUrl: './registration.component.html',
|
templateUrl: "./registration.component.html",
|
||||||
styleUrls: ['./registration.component.scss']
|
styleUrls: ["./registration.component.scss"],
|
||||||
})
|
})
|
||||||
export class RegistrationComponent {
|
export class RegistrationComponent {
|
||||||
registrationForm = new FormGroup({
|
registrationForm = new FormGroup({
|
||||||
mail: new FormControl('', [Validators.required]),
|
mail: new FormControl("", [Validators.required]),
|
||||||
username: new FormControl('', [Validators.required]),
|
username: new FormControl("", [Validators.required]),
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(
|
constructor(private authService: AuthService, private router: Router) {
|
||||||
private authService: AuthService,
|
this.authService.currentState$
|
||||||
private router: Router
|
.pipe(filter((state) => state !== undefined && state !== null))
|
||||||
) {
|
.subscribe((state) => this.router.navigateByUrl("/"));
|
||||||
this.authService.currentState$.pipe(
|
|
||||||
filter(state=>state !== undefined && state !== null)
|
|
||||||
).subscribe((state) =>
|
|
||||||
this.router.navigateByUrl('/')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
register(): void {
|
register(): void {
|
||||||
this.authService.register({
|
this.authService.register({
|
||||||
mail: this.registrationForm.value.mail!,
|
mail: this.registrationForm.value.mail!,
|
||||||
username: this.registrationForm.value.username!
|
username: this.registrationForm.value.username!,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.router.navigateByUrl('/auth/login');
|
this.router.navigateByUrl("/auth/login");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +1,5 @@
|
|||||||
<app-navigation></app-navigation>
|
<app-navigation></app-navigation>
|
||||||
|
|
||||||
<div class="max-w-screen-xl mx-auto p-4">
|
<div class="max-w-screen-xl mx-auto p-4">
|
||||||
<shared-card icon="/assets/icon.png" header="Test" subHeader="lol noch ein test">
|
<router-outlet></router-outlet>
|
||||||
I'm working
|
</div>
|
||||||
</shared-card>
|
|
||||||
|
|
||||||
<shared-card icon="/assets/icon.png" header="Test" >
|
|
||||||
I'm working
|
|
||||||
</shared-card>
|
|
||||||
|
|
||||||
<shared-card>
|
|
||||||
I'm working
|
|
||||||
</shared-card>
|
|
||||||
|
|
||||||
<div class="mb-5">
|
|
||||||
<shared-table [items]="colonies" [columns]="columns">
|
|
||||||
|
|
||||||
</shared-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<shared-paginator total="20" perPage="5" />
|
|
||||||
|
|
||||||
<router-outlet></router-outlet>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|||||||
@ -1,40 +1,8 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from "@angular/core";
|
||||||
import { RequestService } from 'src/app/core/services/request.service';
|
|
||||||
import { ColumnDefinition } from 'src/app/shared/components/table/table.component';
|
|
||||||
|
|
||||||
interface Colony {
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: "app-home",
|
||||||
templateUrl: './home.component.html',
|
templateUrl: "./home.component.html",
|
||||||
styleUrls: ['./home.component.scss'],
|
styleUrls: ["./home.component.scss"],
|
||||||
})
|
})
|
||||||
export class HomeComponent {
|
export class HomeComponent {}
|
||||||
|
|
||||||
columns: ColumnDefinition[] = [
|
|
||||||
{
|
|
||||||
header: 'Name',
|
|
||||||
columnFunction: (colony:Colony) => colony.name,
|
|
||||||
routerLink: (colony:Colony) => '#',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Name2',
|
|
||||||
columnFunction: (colony:Colony) => colony.name,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
colonies: Colony[] = [
|
|
||||||
{
|
|
||||||
name: 'Die Römer'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Die Griechen'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor(public requestService: RequestService) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,60 +1,105 @@
|
|||||||
|
|
||||||
|
|
||||||
<nav class="bg-skin-accent">
|
<nav class="bg-skin-accent">
|
||||||
<div class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4">
|
<div
|
||||||
|
class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4"
|
||||||
|
>
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<a href="#" class="flex items-center space-x-3">
|
<a routerLink="/" class="flex items-center space-x-3">
|
||||||
<img src="assets/icon.png" class="h-10" alt="Beekeeper Logo" />
|
<img src="assets/icon.png" class="h-10" alt="Beekeeper Logo" />
|
||||||
<span class="text-skin-primary self-center text-4xl font-semibold whitespace-nowrap">Beekeeper</span>
|
<span
|
||||||
|
class="text-skin-primary self-center text-4xl font-semibold whitespace-nowrap"
|
||||||
|
>Bienenkeeper</span
|
||||||
|
>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="flex items-center md:order-2 space-x-3 md:space-x-0">
|
<div class="flex items-center md:order-2 space-x-3 md:space-x-0">
|
||||||
<!--User Bubble-->
|
<!--User Bubble-->
|
||||||
<button type="button" class="block w-10 h-10 text-sm bg-skin-primary rounded-full md:me-0 focus:ring-4 focus:ring-skin-primary" id="user-menu-button" aria-expanded="false" data-dropdown-toggle="user-dropdown" data-dropdown-placement="bottom">
|
<button
|
||||||
<span class="text-skin-accent rounded-full font-bold p-2">AA</span>
|
type="button"
|
||||||
<!-- <img class="w-8 h-8 rounded-full" src="/docs/images/people/profile-picture-3.jpg" alt="user photo"> -->
|
class="block w-10 h-10 text-sm bg-skin-primary rounded-full md:me-0 focus:ring-4 focus:ring-skin-primary"
|
||||||
</button>
|
id="user-menu-button"
|
||||||
|
aria-expanded="false"
|
||||||
|
data-dropdown-toggle="user-dropdown"
|
||||||
|
data-dropdown-placement="bottom"
|
||||||
|
>
|
||||||
|
<span class="text-skin-accent rounded-full font-bold p-2 uppercase">{{
|
||||||
|
state?.username[0] + state?.roleIdentifier[0]
|
||||||
|
}}</span>
|
||||||
|
</button>
|
||||||
|
<!-- User dropdown -->
|
||||||
|
<div
|
||||||
|
class="z-50 hidden my-4 text-base list-none divide-y divide-skin-primary rounded-lg shadow-sm shadow-skin-primary bg-skin-primary"
|
||||||
|
id="user-dropdown"
|
||||||
|
>
|
||||||
|
<div class="px-4 py-3">
|
||||||
|
<span class="block text-sm text-skin-accent font-bold">{{
|
||||||
|
state?.username
|
||||||
|
}}</span>
|
||||||
|
<span class="block text-sm text-skin-primary-muted truncate">{{
|
||||||
|
state?.roleIdentifier
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="p-4" aria-labelledby="user-menu-button">
|
||||||
|
<li *ngFor="let usermenuButton of usermenuButtons">
|
||||||
|
<button
|
||||||
|
[routerLink]="
|
||||||
|
usermenuButton.routerLink === undefined
|
||||||
|
? null
|
||||||
|
: [usermenuButton.routerLink]
|
||||||
|
"
|
||||||
|
class="w-full text-left block py-2 px-3 rounded text-skin-primary hover:bg-skin-accent"
|
||||||
|
(click)="clickUserMenuButtonLabel(usermenuButton)"
|
||||||
|
>
|
||||||
|
{{ getUserMenuButtonLabel(usermenuButton) }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!--Burger Menu-->
|
<!--Burger Menu-->
|
||||||
<button data-collapse-toggle="navbar-user" type="button" class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-skin-primary rounded-lg md:hidden hover:bg-skin-primary" aria-controls="navbar-user" aria-expanded="false">
|
<button
|
||||||
<span class="sr-only">Open main menu</span>
|
data-collapse-toggle="navbar-user"
|
||||||
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
|
type="button"
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15"/>
|
class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-skin-primary rounded-lg md:hidden hover:bg-skin-primary"
|
||||||
</svg>
|
aria-controls="navbar-user"
|
||||||
|
aria-expanded="false"
|
||||||
|
>
|
||||||
|
<span class="sr-only">Open main menu</span>
|
||||||
|
<svg
|
||||||
|
class="w-5 h-5"
|
||||||
|
aria-hidden="true"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 17 14"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M1 1h15M1 7h15M1 13h15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- User dropdown -->
|
|
||||||
<div class="z-50 hidden my-4 text-base list-none divide-y divide-skin-primary rounded-lg shadow-sm shadow-skin-primary bg-skin-primary" id="user-dropdown">
|
|
||||||
<div class="px-4 py-3">
|
|
||||||
<span class="block text-sm text-skin-accent font-bold">{{state?.username}}</span>
|
|
||||||
<span class="block text-sm text-skin-primary-muted truncate">{{state?.roleIdentifier}}</span>
|
|
||||||
</div>
|
|
||||||
<ul class="p-4" aria-labelledby="user-menu-button">
|
|
||||||
<li>
|
|
||||||
<a href="/settings" class="block py-2 px-3 rounded text-skin-primary hover:bg-skin-accent">Einstellungen</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button class="w-full block py-2 px-3 rounded text-skin-primary hover:bg-skin-accent" (click)="toggleDarkmode()">{{ darkMode ? 'Hell' : 'Dunkel' }}</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button class="w-full block py-2 px-3 rounded text-skin-primary hover:bg-skin-accent" (click)="logout()">Ausloggen</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Navigatoin -->
|
<!-- Navigatoin -->
|
||||||
<div class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" id="navbar-user">
|
<div
|
||||||
<ul class="flex flex-col text-xl p-4 md:p-0 mt-4 rounded-lg bg-skin-primary md:bg-skin-accent md:space-x-8 md:flex-row md:mt-0 md:border-0">
|
class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1"
|
||||||
<li>
|
id="navbar-user"
|
||||||
<a routerLink="/home" class="block py-2 px-3 rounded text-skin-primary md:p-0" aria-current="page">Home</a>
|
>
|
||||||
</li>
|
<ul
|
||||||
<li>
|
class="flex flex-col text-xl p-4 md:p-0 mt-4 rounded-lg bg-skin-primary md:bg-skin-accent md:space-x-8 md:flex-row md:mt-0 md:border-0"
|
||||||
<a href="#" class="block py-2 px-3 rounded text-skin-primary-muted hover:text-skin-primary hover:bg-skin-accent md:p-0">About</a>
|
>
|
||||||
|
<li *ngFor="let navigationLink of navigationLinks">
|
||||||
|
<a
|
||||||
|
class="block py-2 px-3 rounded text-skin-primary hover:font-bold hover:bg-skin-accent md:p-0"
|
||||||
|
[routerLink]="navigationLink.routerLink"
|
||||||
|
[routerLinkActiveOptions]="{ exact: true }"
|
||||||
|
routerLinkActive="font-bold"
|
||||||
|
>{{ navigationLink.label }}</a
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@ -1,17 +1,54 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { initFlowbite } from 'flowbite';
|
import { initFlowbite } from "flowbite";
|
||||||
import { AuthService } from '../../services/auth.service';
|
import { AuthService } from "../../services/auth.service";
|
||||||
import { UserStateResponse } from '../../models/user-state-request.model';
|
import { UserStateResponse } from "../../models/user-state-request.model";
|
||||||
import { Router } from '@angular/router';
|
import { Router } from "@angular/router";
|
||||||
import { filter, map } from 'rxjs';
|
import { filter, map } from "rxjs";
|
||||||
import { AppService } from '../../services/app.service';
|
import { AppService } from "../../services/app.service";
|
||||||
|
|
||||||
|
interface NavigationLink {
|
||||||
|
label: string;
|
||||||
|
routerLink: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UserMenuButton {
|
||||||
|
label: Function | string;
|
||||||
|
routerLink: string | undefined;
|
||||||
|
clickCallback: Function | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-navigation',
|
selector: "app-navigation",
|
||||||
templateUrl: './navigation.component.html',
|
templateUrl: "./navigation.component.html",
|
||||||
styleUrls: ['./navigation.component.scss'],
|
styleUrls: ["./navigation.component.scss"],
|
||||||
})
|
})
|
||||||
export class NavigationComponent implements OnInit {
|
export class NavigationComponent implements OnInit {
|
||||||
|
navigationLinks: NavigationLink[] = [
|
||||||
|
{ routerLink: "/", label: "Startseite" },
|
||||||
|
{ routerLink: "/settings", label: "Völker" },
|
||||||
|
];
|
||||||
|
|
||||||
|
usermenuButtons: UserMenuButton[] = [
|
||||||
|
{
|
||||||
|
label: "Einstellungen",
|
||||||
|
routerLink: "/settings",
|
||||||
|
clickCallback: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: () => (this.darkMode ? "Hell" : "Dunkel"),
|
||||||
|
routerLink: undefined,
|
||||||
|
clickCallback: () => {
|
||||||
|
this.toggleDarkmode();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Ausloggen",
|
||||||
|
routerLink: undefined,
|
||||||
|
clickCallback: () => {
|
||||||
|
this.logout();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
state: UserStateResponse | undefined | null;
|
state: UserStateResponse | undefined | null;
|
||||||
darkMode: boolean;
|
darkMode: boolean;
|
||||||
@ -19,15 +56,15 @@ export class NavigationComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private appService: AppService,
|
private appService: AppService,
|
||||||
private router: Router,
|
private router: Router
|
||||||
) {
|
) {
|
||||||
this.darkMode = this.appService.darkMode;
|
this.darkMode = this.appService.darkMode;
|
||||||
this.state = this.authService.currentState$.value;
|
this.state = this.authService.currentState$.value;
|
||||||
this.authService.currentState$.pipe(
|
this.authService.currentState$
|
||||||
filter(state => state === undefined)
|
.pipe(filter((state) => state === undefined))
|
||||||
).subscribe( state =>{
|
.subscribe((state) => {
|
||||||
this.router.navigateByUrl('/auth/login');
|
this.router.navigateByUrl("/auth/login");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -42,4 +79,18 @@ export class NavigationComponent implements OnInit {
|
|||||||
this.appService.toggleDarkMode();
|
this.appService.toggleDarkMode();
|
||||||
this.darkMode = this.appService.darkMode;
|
this.darkMode = this.appService.darkMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clickUserMenuButtonLabel(button: UserMenuButton) {
|
||||||
|
if (button.clickCallback !== undefined) {
|
||||||
|
button.clickCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserMenuButtonLabel(button: UserMenuButton) {
|
||||||
|
if (typeof button.label === "function") {
|
||||||
|
return button.label();
|
||||||
|
} else {
|
||||||
|
return button.label;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,33 +1,57 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="mb-4 border-b border-gray-200 dark:border-gray-700">
|
<div class="mb-4 border-b border-skin-primary">
|
||||||
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center" id="default-styled-tab" data-tabs-toggle="#default-styled-tab-content" data-tabs-active-classes="text-purple-600 hover:text-purple-600 dark:text-purple-500 dark:hover:text-purple-500 border-purple-600 dark:border-purple-500" data-tabs-inactive-classes="dark:border-transparent text-gray-500 hover:text-gray-600 dark:text-gray-400 border-gray-100 hover:border-gray-300 dark:border-gray-700 dark:hover:text-gray-300" role="tablist">
|
<ul
|
||||||
<li class="me-2" role="presentation">
|
class="flex flex-wrap -mb-px text-sm font-medium text-center"
|
||||||
<button class="inline-block p-4 border-b-2 rounded-t-lg" id="profile-styled-tab" data-tabs-target="#styled-profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
|
id="default-styled-tab"
|
||||||
</li>
|
data-tabs-toggle="#default-styled-tab-content"
|
||||||
<li class="me-2" role="presentation">
|
data-tabs-active-classes="text-skin-accent border-skin-accent"
|
||||||
<button class="inline-block p-4 border-b-2 rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="dashboard-styled-tab" data-tabs-target="#styled-dashboard" type="button" role="tab" aria-controls="dashboard" aria-selected="false">Dashboard</button>
|
data-tabs-inactive-classes="text-skin-primary-muted hover:text-skin-primary border-skin-primary hover:border-skin-accent"
|
||||||
</li>
|
role="tablist"
|
||||||
<li class="me-2" role="presentation">
|
>
|
||||||
<button class="inline-block p-4 border-b-2 rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="settings-styled-tab" data-tabs-target="#styled-settings" type="button" role="tab" aria-controls="settings" aria-selected="false">Settings</button>
|
<li class="me-2" role="presentation">
|
||||||
</li>
|
<button
|
||||||
<li role="presentation">
|
class="inline-block p-4 border-b-2 rounded-t-lg"
|
||||||
<button class="inline-block p-4 border-b-2 rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="contacts-styled-tab" data-tabs-target="#styled-contacts" type="button" role="tab" aria-controls="contacts" aria-selected="false">Contacts</button>
|
id="profile-styled-tab"
|
||||||
</li>
|
data-tabs-target="#styled-profile"
|
||||||
</ul>
|
type="button"
|
||||||
|
role="tab"
|
||||||
|
aria-controls="profile"
|
||||||
|
aria-selected="false"
|
||||||
|
>
|
||||||
|
Profil
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="me-2" role="presentation">
|
||||||
|
<button
|
||||||
|
class="inline-block p-4 border-b-2 rounded-t-lg"
|
||||||
|
id="security-styled-tab"
|
||||||
|
data-tabs-target="#styled-security"
|
||||||
|
type="button"
|
||||||
|
role="tab"
|
||||||
|
aria-controls="security"
|
||||||
|
aria-selected="false"
|
||||||
|
>
|
||||||
|
Sicherheit
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="default-styled-tab-content" class="text-skin-primary">
|
||||||
|
<div
|
||||||
|
class="hidden p-4 rounded-lg"
|
||||||
|
id="styled-profile"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="profile-tab"
|
||||||
|
>
|
||||||
|
<app-tab-profile />
|
||||||
</div>
|
</div>
|
||||||
<div id="default-styled-tab-content">
|
<div
|
||||||
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="styled-profile" role="tabpanel" aria-labelledby="profile-tab">
|
class="hidden p-4 rounded-lg"
|
||||||
<p class="text-sm text-gray-500 dark:text-gray-400">This is some placeholder content the <strong class="font-medium text-gray-800 dark:text-white">Profile tab's associated content</strong>. Clicking another tab will toggle the visibility of this one for the next. The tab JavaScript swaps classes to control the content visibility and styling.</p>
|
id="styled-security"
|
||||||
</div>
|
role="tabpanel"
|
||||||
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="styled-dashboard" role="tabpanel" aria-labelledby="dashboard-tab">
|
aria-labelledby="security-tab"
|
||||||
<p class="text-sm text-gray-500 dark:text-gray-400">This is some placeholder content the <strong class="font-medium text-gray-800 dark:text-white">Dashboard tab's associated content</strong>. Clicking another tab will toggle the visibility of this one for the next. The tab JavaScript swaps classes to control the content visibility and styling.</p>
|
>
|
||||||
</div>
|
<app-tab-security />
|
||||||
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="styled-settings" role="tabpanel" aria-labelledby="settings-tab">
|
|
||||||
<p class="text-sm text-gray-500 dark:text-gray-400">This is some placeholder content the <strong class="font-medium text-gray-800 dark:text-white">Settings tab's associated content</strong>. Clicking another tab will toggle the visibility of this one for the next. The tab JavaScript swaps classes to control the content visibility and styling.</p>
|
|
||||||
</div>
|
|
||||||
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="styled-contacts" role="tabpanel" aria-labelledby="contacts-tab">
|
|
||||||
<p class="text-sm text-gray-500 dark:text-gray-400">This is some placeholder content the <strong class="font-medium text-gray-800 dark:text-white">Contacts tab's associated content</strong>. Clicking another tab will toggle the visibility of this one for the next. The tab JavaScript swaps classes to control the content visibility and styling.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { initFlowbite } from "flowbite";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings',
|
selector: "app-settings",
|
||||||
templateUrl: './settings.component.html',
|
templateUrl: "./settings.component.html",
|
||||||
styleUrls: ['./settings.component.scss']
|
styleUrls: ["./settings.component.scss"],
|
||||||
})
|
})
|
||||||
export class SettingsComponent {
|
export class SettingsComponent implements OnInit {
|
||||||
|
ngOnInit(): void {
|
||||||
|
initFlowbite();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,12 @@
|
|||||||
|
<shared-card
|
||||||
|
icon="/assets/icon.png"
|
||||||
|
header="Test"
|
||||||
|
subHeader="lol noch ein test"
|
||||||
|
>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ligula erat,
|
||||||
|
auctor eget dolor sed, interdum interdum quam. Donec dui nisl, dignissim quis
|
||||||
|
sollicitudin vitae, eleifend sit amet dui. Cras mattis pretium metus nec
|
||||||
|
venenatis. Nam tempus eros in tempus facilisis. Aliquam sit amet consequat
|
||||||
|
lacus. Mauris lacinia mollis justo eu dapibus. Maecenas vestibulum diam id mi
|
||||||
|
pellentesque accumsan.
|
||||||
|
</shared-card>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-tab-profile',
|
||||||
|
templateUrl: './tab-profile.component.html',
|
||||||
|
styleUrls: ['./tab-profile.component.scss']
|
||||||
|
})
|
||||||
|
export class TabProfileComponent {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
<div class="mb-5">
|
||||||
|
<shared-table [items]="colonies" [columns]="columns"> </shared-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<shared-paginator total="20" perPage="5" />
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
import { Component } from "@angular/core";
|
||||||
|
import { ColumnDefinition } from "src/app/shared/components/table/table.component";
|
||||||
|
|
||||||
|
interface Colony {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "app-tab-security",
|
||||||
|
templateUrl: "./tab-security.component.html",
|
||||||
|
styleUrls: ["./tab-security.component.scss"],
|
||||||
|
})
|
||||||
|
export class TabSecurityComponent {
|
||||||
|
columns: ColumnDefinition[] = [
|
||||||
|
{
|
||||||
|
header: "Name",
|
||||||
|
columnFunction: (colony: Colony) => colony.name,
|
||||||
|
routerLink: (colony: Colony) => "#",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: "Name2",
|
||||||
|
columnFunction: (colony: Colony) => colony.name,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
colonies: Colony[] = [{ name: "Die Römer" }, { name: "Die Griechen" }];
|
||||||
|
}
|
||||||
@ -1,20 +1,27 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from "@angular/core";
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from "@angular/common";
|
||||||
import { NavigationComponent } from './components/navigation/navigation.component';
|
import { NavigationComponent } from "./components/navigation/navigation.component";
|
||||||
import { AuthGuard } from './guards/auth.guard';
|
import { AuthGuard } from "./guards/auth.guard";
|
||||||
import { AuthService } from './services/auth.service';
|
import { AuthService } from "./services/auth.service";
|
||||||
import { RequestService } from './services/request.service';
|
import { RequestService } from "./services/request.service";
|
||||||
import { AppService } from './services/app.service';
|
import { AppService } from "./services/app.service";
|
||||||
import { SharedModule } from '../shared/shared.module';
|
import { SharedModule } from "../shared/shared.module";
|
||||||
import { SettingsComponent } from './components/settings/settings.component';
|
import { SettingsComponent } from "./components/settings/settings.component";
|
||||||
|
import { TabProfileComponent } from "./components/settings/tabs/tab-profile/tab-profile.component";
|
||||||
|
import { TabSecurityComponent } from "./components/settings/tabs/tab-security/tab-security.component";
|
||||||
|
import { RouterModule } from "@angular/router";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [NavigationComponent, SettingsComponent],
|
declarations: [
|
||||||
exports: [NavigationComponent, SettingsComponent],
|
NavigationComponent,
|
||||||
imports: [
|
SettingsComponent,
|
||||||
CommonModule,
|
TabProfileComponent,
|
||||||
SharedModule
|
TabSecurityComponent,
|
||||||
|
TabProfileComponent,
|
||||||
|
TabSecurityComponent,
|
||||||
],
|
],
|
||||||
providers: [AuthGuard, AuthService, RequestService, AppService]
|
exports: [NavigationComponent, SettingsComponent],
|
||||||
|
imports: [CommonModule, SharedModule, RouterModule],
|
||||||
|
providers: [AuthGuard, AuthService, RequestService, AppService],
|
||||||
})
|
})
|
||||||
export class CoreModule { }
|
export class CoreModule {}
|
||||||
|
|||||||
@ -1,26 +1,28 @@
|
|||||||
import { Injectable } from "@angular/core";
|
import { Injectable } from "@angular/core";
|
||||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from "@angular/router";
|
import {
|
||||||
|
ActivatedRouteSnapshot,
|
||||||
|
CanActivate,
|
||||||
|
Router,
|
||||||
|
RouterStateSnapshot,
|
||||||
|
UrlTree,
|
||||||
|
} from "@angular/router";
|
||||||
import { filter, map, Observable } from "rxjs";
|
import { filter, map, Observable } from "rxjs";
|
||||||
import { AuthService } from "../services/auth.service";
|
import { AuthService } from "../services/auth.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthGuard implements CanActivate {
|
export class AuthGuard implements CanActivate {
|
||||||
|
constructor(private authService: AuthService, private router: Router) {}
|
||||||
|
|
||||||
constructor(
|
canActivate(): Observable<boolean> | boolean {
|
||||||
private authService: AuthService,
|
return this.authService.currentState$.pipe(
|
||||||
private router: Router
|
filter((currentState) => currentState !== undefined),
|
||||||
) {
|
map((currentState) => {
|
||||||
}
|
if (currentState === null) {
|
||||||
|
this.router.navigateByUrl("/auth/login");
|
||||||
canActivate(): Observable<boolean> | boolean {
|
return false;
|
||||||
return this.authService.currentState$.pipe(
|
}
|
||||||
filter(currentState=>currentState!==undefined),
|
return true;
|
||||||
map((currentState) => {
|
})
|
||||||
if (currentState === null) {
|
);
|
||||||
this.router.navigateByUrl('/auth/login');
|
}
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
export interface ConfirmRegistrationRequest {
|
export interface ConfirmRegistrationRequest {
|
||||||
id: string,
|
id: string;
|
||||||
password: string,
|
password: string;
|
||||||
passwordConfirmation: string,
|
passwordConfirmation: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConfirmRegistrationResponse {
|
export interface ConfirmRegistrationResponse {
|
||||||
id: string,
|
id: string;
|
||||||
username: string,
|
username: string;
|
||||||
roleIdentifier: string,
|
roleIdentifier: string;
|
||||||
createdAt: string,
|
createdAt: string;
|
||||||
updatedAt: string,
|
updatedAt: string;
|
||||||
permissions: string[]
|
permissions: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
export interface LoginRequest {
|
export interface LoginRequest {
|
||||||
identifier: string,
|
identifier: string;
|
||||||
password: string,
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LoginResponse {
|
export interface LoginResponse {
|
||||||
sessionId: string
|
sessionId: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
export interface RegisterUserRequest {
|
export interface RegisterUserRequest {
|
||||||
mail: string,
|
mail: string;
|
||||||
username: string,
|
username: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RegisterUserResponse {
|
export interface RegisterUserResponse {}
|
||||||
}
|
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
export interface UserStateRequest {
|
export interface UserStateRequest {}
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserStateResponse {
|
export interface UserStateResponse {
|
||||||
id: string,
|
id: string;
|
||||||
sessionId: string,
|
sessionId: string;
|
||||||
username: string,
|
username: string;
|
||||||
roleIdentifier: string,
|
roleIdentifier: string;
|
||||||
createdAt: string,
|
createdAt: string;
|
||||||
updatedAt: string,
|
updatedAt: string;
|
||||||
permissions: string[],
|
permissions: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,29 +2,29 @@ import { Injectable } from "@angular/core";
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AppService {
|
export class AppService {
|
||||||
|
darkMode: boolean;
|
||||||
darkMode: boolean;
|
|
||||||
|
|
||||||
constructor(
|
constructor() {
|
||||||
) {
|
this.darkMode =
|
||||||
this.darkMode = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
window.matchMedia &&
|
||||||
this.applyDarkMode();
|
window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
}
|
this.applyDarkMode();
|
||||||
|
}
|
||||||
|
|
||||||
private applyDarkMode(): void {
|
private applyDarkMode(): void {
|
||||||
if (this.darkMode) {
|
if (this.darkMode) {
|
||||||
document.documentElement.classList.add('theme-dark');
|
document.documentElement.classList.add("theme-dark");
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.classList.remove('theme-dark');
|
document.documentElement.classList.remove("theme-dark");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
toggleDarkMode() {
|
toggleDarkMode() {
|
||||||
this.darkMode = !this.darkMode;
|
this.darkMode = !this.darkMode;
|
||||||
this.applyDarkMode();
|
this.applyDarkMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
getDarkMode(): boolean {
|
getDarkMode(): boolean {
|
||||||
return this.darkMode;
|
return this.darkMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,87 +4,88 @@ import { UserStateResponse } from "../models/user-state-request.model";
|
|||||||
import { BehaviorSubject } from "rxjs";
|
import { BehaviorSubject } from "rxjs";
|
||||||
import { LoginRequest, LoginResponse } from "../models/login-request.model";
|
import { LoginRequest, LoginResponse } from "../models/login-request.model";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
import { RegisterUserRequest, RegisterUserResponse } from "../models/register-user-request.model";
|
import {
|
||||||
import { ConfirmRegistrationRequest, ConfirmRegistrationResponse } from "../models/confirm-registration-request.model";
|
RegisterUserRequest,
|
||||||
|
RegisterUserResponse,
|
||||||
|
} from "../models/register-user-request.model";
|
||||||
|
import {
|
||||||
|
ConfirmRegistrationRequest,
|
||||||
|
ConfirmRegistrationResponse,
|
||||||
|
} from "../models/confirm-registration-request.model";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
|
currentState$ = new BehaviorSubject<UserStateResponse | null | undefined>(
|
||||||
currentState$ = new BehaviorSubject<UserStateResponse | null | undefined>(undefined);
|
undefined
|
||||||
|
);
|
||||||
|
|
||||||
constructor(
|
constructor(private requestService: RequestService, private router: Router) {}
|
||||||
private requestService: RequestService,
|
|
||||||
private router: Router
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
readUserState(): void {
|
readUserState(): void {
|
||||||
this.requestService.get(
|
this.requestService.get(
|
||||||
'user/state',
|
"user/state",
|
||||||
{},
|
{},
|
||||||
(response: UserStateResponse) => {
|
(response: UserStateResponse) => {
|
||||||
console.log('set next state');
|
console.log("set next state");
|
||||||
this.currentState$.next(response);
|
this.currentState$.next(response);
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this.currentState$.next(null);
|
this.currentState$.next(null);
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
login(body: LoginRequest): LoginResponse|null {
|
login(body: LoginRequest): LoginResponse | null {
|
||||||
let result = null;
|
let result = null;
|
||||||
|
|
||||||
this.requestService.post(
|
this.requestService.post(
|
||||||
'auth/login-user',
|
"auth/login-user",
|
||||||
body,
|
body,
|
||||||
(response: LoginResponse) => {
|
(response: LoginResponse) => {
|
||||||
result = response;
|
result = response;
|
||||||
this.readUserState();
|
this.readUserState();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
register(body: RegisterUserRequest): RegisterUserResponse|null {
|
register(body: RegisterUserRequest): RegisterUserResponse | null {
|
||||||
let result = null;
|
let result = null;
|
||||||
|
|
||||||
this.requestService.post(
|
this.requestService.post(
|
||||||
'auth/register-user',
|
"auth/register-user",
|
||||||
body,
|
body,
|
||||||
(response: LoginResponse) => {
|
(response: LoginResponse) => {
|
||||||
result = response;
|
result = response;
|
||||||
this.readUserState();
|
this.readUserState();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmRegistration(body: ConfirmRegistrationRequest): ConfirmRegistrationResponse|null {
|
confirmRegistration(
|
||||||
let result = null;
|
body: ConfirmRegistrationRequest
|
||||||
|
): ConfirmRegistrationResponse | null {
|
||||||
|
let result = null;
|
||||||
|
|
||||||
this.requestService.post(
|
this.requestService.post(
|
||||||
'auth/confirm-registration',
|
"auth/confirm-registration",
|
||||||
body,
|
body,
|
||||||
(response: LoginResponse) => {
|
(response: LoginResponse) => {
|
||||||
result = response;
|
result = response;
|
||||||
this.readUserState();
|
this.readUserState();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(): void {
|
logout(): void {
|
||||||
this.requestService.post(
|
this.requestService.post("auth/logout-user", {}, (response: any) => {
|
||||||
'auth/logout-user',
|
this.currentState$.next(undefined);
|
||||||
{},
|
this.readUserState();
|
||||||
(response: any) => {
|
});
|
||||||
this.currentState$.next(undefined);
|
}
|
||||||
this.readUserState();
|
}
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,71 +1,73 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from "@angular/common/http";
|
||||||
import { Router } from '@angular/router';
|
import { Router } from "@angular/router";
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from "@angular/core";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: "root",
|
||||||
})
|
})
|
||||||
export class RequestService {
|
export class RequestService {
|
||||||
|
constructor(private http: HttpClient, private router: Router) {}
|
||||||
|
|
||||||
constructor(
|
public post(
|
||||||
private http: HttpClient,
|
apiPath: string,
|
||||||
private router: Router,
|
body: any,
|
||||||
|
successFunction: Function,
|
||||||
|
errorFunction: Function | null = null
|
||||||
) {
|
) {
|
||||||
}
|
|
||||||
|
|
||||||
public post(apiPath: string, body: any, successFunction: Function, errorFunction: Function|null = null)
|
|
||||||
{
|
|
||||||
let url = this.obtainUrl(apiPath);
|
let url = this.obtainUrl(apiPath);
|
||||||
let observable = this.http.post(url, body).subscribe(
|
let observable = this.http.post(url, body).subscribe(
|
||||||
(answer:any) => {
|
(answer: any) => {
|
||||||
successFunction(answer);
|
successFunction(answer);
|
||||||
},
|
},
|
||||||
(error:any) => {
|
(error: any) => {
|
||||||
if (errorFunction === null)
|
if (errorFunction === null) this.handleError(error);
|
||||||
this.handleError(error);
|
else errorFunction(error);
|
||||||
else
|
|
||||||
errorFunction(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get(apiPath: string, body: any, successFunction: Function, errorFunction: Function|null = null)
|
|
||||||
{
|
|
||||||
let url = this.obtainUrl(apiPath);
|
|
||||||
let observable = this.http.get(url, body).subscribe(
|
|
||||||
(answer:any) => {
|
|
||||||
successFunction(answer);
|
|
||||||
},
|
|
||||||
(error:any) => {
|
|
||||||
if (errorFunction === null)
|
|
||||||
this.handleError(error);
|
|
||||||
else
|
|
||||||
errorFunction(error);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public postFiles(apiPath: string, files: File[], successFunction: Function, errorFunction: Function|null = null) {
|
public get(
|
||||||
|
apiPath: string,
|
||||||
|
body: any,
|
||||||
|
successFunction: Function,
|
||||||
|
errorFunction: Function | null = null
|
||||||
|
) {
|
||||||
|
let url = this.obtainUrl(apiPath);
|
||||||
|
let observable = this.http.get(url, body).subscribe(
|
||||||
|
(answer: any) => {
|
||||||
|
successFunction(answer);
|
||||||
|
},
|
||||||
|
(error: any) => {
|
||||||
|
if (errorFunction === null) this.handleError(error);
|
||||||
|
else errorFunction(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public postFiles(
|
||||||
|
apiPath: string,
|
||||||
|
files: File[],
|
||||||
|
successFunction: Function,
|
||||||
|
errorFunction: Function | null = null
|
||||||
|
) {
|
||||||
if (!files || files.length === 0) {
|
if (!files || files.length === 0) {
|
||||||
throw 'Need to select at least one file';
|
throw "Need to select at least one file";
|
||||||
}
|
}
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
||||||
for (let fileIndex = 0; fileIndex < files.length; fileIndex++) {
|
for (let fileIndex = 0; fileIndex < files.length; fileIndex++) {
|
||||||
formData.append('file' + fileIndex, files[fileIndex]);
|
formData.append("file" + fileIndex, files[fileIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = this.obtainUrl(apiPath);
|
let url = this.obtainUrl(apiPath);
|
||||||
let observable = this.http.post<any>(url, formData).subscribe(
|
let observable = this.http.post<any>(url, formData).subscribe(
|
||||||
(answer: any) => {
|
(answer: any) => {
|
||||||
successFunction(answer);
|
successFunction(answer);
|
||||||
},
|
},
|
||||||
(error: any) => {
|
(error: any) => {
|
||||||
if (errorFunction === null)
|
if (errorFunction === null) this.handleError(error);
|
||||||
this.handleError(error);
|
else errorFunction(error);
|
||||||
else
|
|
||||||
errorFunction(error);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -73,34 +75,33 @@ export class RequestService {
|
|||||||
private obtainUrl(apiPath: string): string {
|
private obtainUrl(apiPath: string): string {
|
||||||
let hostString = window.location.host;
|
let hostString = window.location.host;
|
||||||
let protocol = window.location.protocol;
|
let protocol = window.location.protocol;
|
||||||
return protocol + '//' + hostString + '/api/' + apiPath;
|
return protocol + "//" + hostString + "/api/" + apiPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleError(answer: any): void {
|
private handleError(answer: any): void {
|
||||||
|
|
||||||
if (answer.status == 401) {
|
if (answer.status == 401) {
|
||||||
console.log('Deine Sitzung konnte nicht gefunden werden');
|
console.log("Deine Sitzung konnte nicht gefunden werden");
|
||||||
this.router.navigate(['/auth']);
|
this.router.navigate(["/auth"]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (answer.status == 403) {
|
if (answer.status == 403) {
|
||||||
this.showSnackBar('Du bist nicht für diese Aktion autorisiert', 'Ok');
|
this.showSnackBar("Du bist nicht für diese Aktion autorisiert", "Ok");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let errorObject = answer.error.error;
|
let errorObject = answer.error.error;
|
||||||
|
|
||||||
if (errorObject.hasOwnProperty('message')) {
|
if (errorObject.hasOwnProperty("message")) {
|
||||||
throw errorObject.message.toString();
|
throw errorObject.message.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errorObject.hasOwnProperty('code')) {
|
if (errorObject.hasOwnProperty("code")) {
|
||||||
throw errorObject.code.toString();
|
throw errorObject.code.toString();
|
||||||
}
|
}
|
||||||
} catch(error:any) {
|
} catch (error: any) {
|
||||||
this.showSnackBar(error.toString(), 'Ok');
|
this.showSnackBar(error.toString(), "Ok");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,11 @@
|
|||||||
id="card"
|
id="card"
|
||||||
class="grow p-3 my-2 rounded-xl shadow-sm shadow-skin-primary border border-skin-primary divide-y divide-skin-primary"
|
class="grow p-3 my-2 rounded-xl shadow-sm shadow-skin-primary border border-skin-primary divide-y divide-skin-primary"
|
||||||
>
|
>
|
||||||
<div *ngIf="icon !== null || header !== null || subHeader !== null" id="header" class="mb-5">
|
<div
|
||||||
|
*ngIf="icon !== null || header !== null || subHeader !== null"
|
||||||
|
id="header"
|
||||||
|
class="mb-5"
|
||||||
|
>
|
||||||
<div class="w-full flex flex-row">
|
<div class="w-full flex flex-row">
|
||||||
<!--Icon-->
|
<!--Icon-->
|
||||||
<div *ngIf="icon !== null" class="basis-auto">
|
<div *ngIf="icon !== null" class="basis-auto">
|
||||||
@ -11,14 +15,13 @@
|
|||||||
|
|
||||||
<!--Header-->
|
<!--Header-->
|
||||||
<div class="basis-full truncate">
|
<div class="basis-full truncate">
|
||||||
<div
|
<div
|
||||||
*ngIf="header !== null"
|
*ngIf="header !== null"
|
||||||
class="text-xl font-medium text-skin-primary mb-2">
|
class="text-xl font-medium text-skin-primary mb-2"
|
||||||
|
>
|
||||||
{{ header }}
|
{{ header }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div *ngIf="subHeader !== null" class="text-skin-primary-muted pl-2">
|
||||||
*ngIf="subHeader !== null"
|
|
||||||
class="text-skin-primary-muted pl-2">
|
|
||||||
{{ subHeader }}
|
{{ subHeader }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from "@angular/core";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'shared-card',
|
selector: "shared-card",
|
||||||
templateUrl: './card.component.html',
|
templateUrl: "./card.component.html",
|
||||||
styleUrls: ['./card.component.scss'],
|
styleUrls: ["./card.component.scss"],
|
||||||
})
|
})
|
||||||
export class CardComponent {
|
export class CardComponent {
|
||||||
@Input() header: string | null = null;
|
@Input() header: string | null = null;
|
||||||
|
|||||||
@ -28,9 +28,9 @@
|
|||||||
<div
|
<div
|
||||||
class="flex items-center justify-center h-8 leading-tight border border-skin-primary text-skin-primary"
|
class="flex items-center justify-center h-8 leading-tight border border-skin-primary text-skin-primary"
|
||||||
[ngClass]="{
|
[ngClass]="{
|
||||||
'bg-skin-accent font-bold text-skin-secondary hover:text-skin-primary': item.page === page,
|
'bg-skin-accent font-bold text-skin-secondary hover:text-skin-primary':
|
||||||
'bg-skin-secondary':
|
item.page === page,
|
||||||
item.page !== page
|
'bg-skin-secondary': item.page !== page
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div *ngIf="item.page === null" class="px-3">...</div>
|
<div *ngIf="item.page === null" class="px-3">...</div>
|
||||||
|
|||||||
@ -5,16 +5,16 @@ import {
|
|||||||
OnChanges,
|
OnChanges,
|
||||||
Output,
|
Output,
|
||||||
SimpleChanges,
|
SimpleChanges,
|
||||||
} from '@angular/core';
|
} from "@angular/core";
|
||||||
|
|
||||||
export interface PaginatorItem {
|
export interface PaginatorItem {
|
||||||
page: number | null;
|
page: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'shared-paginator',
|
selector: "shared-paginator",
|
||||||
templateUrl: './paginator.component.html',
|
templateUrl: "./paginator.component.html",
|
||||||
styleUrls: ['./paginator.component.scss'],
|
styleUrls: ["./paginator.component.scss"],
|
||||||
})
|
})
|
||||||
export class PaginatorComponent implements OnChanges {
|
export class PaginatorComponent implements OnChanges {
|
||||||
@Output() pageChange = new EventEmitter<number>();
|
@Output() pageChange = new EventEmitter<number>();
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from "@angular/core";
|
||||||
|
|
||||||
export interface ColumnDefinition {
|
export interface ColumnDefinition {
|
||||||
header: string;
|
header: string;
|
||||||
@ -8,9 +8,9 @@ export interface ColumnDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'shared-table',
|
selector: "shared-table",
|
||||||
templateUrl: './table.component.html',
|
templateUrl: "./table.component.html",
|
||||||
styleUrls: ['./table.component.scss'],
|
styleUrls: ["./table.component.scss"],
|
||||||
})
|
})
|
||||||
export class TableComponent {
|
export class TableComponent {
|
||||||
@Input() items: any[] = [];
|
@Input() items: any[] = [];
|
||||||
@ -18,6 +18,6 @@ export class TableComponent {
|
|||||||
|
|
||||||
isBoolean(obje: any): boolean {
|
isBoolean(obje: any): boolean {
|
||||||
console.log(obje);
|
console.log(obje);
|
||||||
return typeof obje === 'boolean';
|
return typeof obje === "boolean";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
export interface TabItem {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
}
|
|
||||||
4
src/app/shared/models/tab-item.model.ts
Normal file
4
src/app/shared/models/tab-item.model.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface TabItem {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
@ -1,28 +1,14 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from "@angular/core";
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from "@angular/router";
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from "@angular/common";
|
||||||
import { CardComponent } from './components/card/card.component';
|
import { CardComponent } from "./components/card/card.component";
|
||||||
import { PaginatorComponent } from './components/paginator/paginator.component';
|
import { PaginatorComponent } from "./components/paginator/paginator.component";
|
||||||
import { TableComponent } from './components/table/table.component';
|
import { TableComponent } from "./components/table/table.component";
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from "@angular/forms";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [CardComponent, PaginatorComponent, TableComponent],
|
||||||
CardComponent,
|
exports: [CardComponent, PaginatorComponent, TableComponent, FormsModule],
|
||||||
PaginatorComponent,
|
imports: [RouterModule, CommonModule, FormsModule],
|
||||||
TableComponent,
|
|
||||||
],
|
|
||||||
exports: [
|
|
||||||
CardComponent,
|
|
||||||
PaginatorComponent,
|
|
||||||
TableComponent,
|
|
||||||
|
|
||||||
FormsModule,
|
|
||||||
],
|
|
||||||
imports: [
|
|
||||||
RouterModule,
|
|
||||||
CommonModule,
|
|
||||||
FormsModule,
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
export class SharedModule {}
|
export class SharedModule {}
|
||||||
|
|||||||
10
src/main.ts
10
src/main.ts
@ -1,7 +1,7 @@
|
|||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
|
||||||
|
|
||||||
import { AppModule } from './app/app.module';
|
import { AppModule } from "./app/app.module";
|
||||||
|
|
||||||
|
platformBrowserDynamic()
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
.bootstrapModule(AppModule)
|
||||||
.catch(err => console.error(err));
|
.catch((err) => console.error(err));
|
||||||
|
|||||||
@ -3,29 +3,28 @@
|
|||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--color-text-primary: 0,0,0;
|
--color-text-primary: 0, 0, 0;
|
||||||
--color-text-primary-muted: 100,100,100;
|
--color-text-primary-muted: 100, 100, 100;
|
||||||
--color-text-secondary: 255,255,255;
|
--color-text-secondary: 255, 255, 255;
|
||||||
--color-text-secondary-muted: 170,170,170;
|
--color-text-secondary-muted: 170, 170, 170;
|
||||||
--color-text-accent: 255, 199, 44;
|
--color-text-accent: 255, 199, 44;
|
||||||
--color-text-accent-muted: 255, 199, 44;
|
--color-text-accent-muted: 255, 199, 44;
|
||||||
|
|
||||||
--color-primary: 244, 244, 245;
|
--color-primary: 244, 244, 245;
|
||||||
--color-secondary: 238, 238, 240;
|
--color-secondary: 238, 238, 240;
|
||||||
--color-accent: 255, 199, 44;
|
--color-accent: 255, 199, 44;
|
||||||
}
|
|
||||||
.theme-dark {
|
|
||||||
--color-text-primary: 255,255,255;
|
|
||||||
--color-text-primary-muted: 170,170,170;
|
|
||||||
--color-text-secondary: 0,0,0;
|
|
||||||
--color-text-secondary-muted: 100,100,100;
|
|
||||||
--color-text-accent: 250, 183, 0;
|
|
||||||
--color-text-accent-muted: 250, 183, 0;
|
|
||||||
|
|
||||||
--color-primary: 24, 24, 27;
|
|
||||||
--color-secondary: 39, 39, 42;
|
|
||||||
--color-accent: 250, 183, 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.theme-dark {
|
||||||
|
--color-text-primary: 255, 255, 255;
|
||||||
|
--color-text-primary-muted: 170, 170, 170;
|
||||||
|
--color-text-secondary: 0, 0, 0;
|
||||||
|
--color-text-secondary-muted: 100, 100, 100;
|
||||||
|
--color-text-accent: 250, 183, 0;
|
||||||
|
--color-text-accent-muted: 250, 183, 0;
|
||||||
|
|
||||||
|
--color-primary: 24, 24, 27;
|
||||||
|
--color-secondary: 39, 39, 42;
|
||||||
|
--color-accent: 250, 183, 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,61 +1,56 @@
|
|||||||
function withOpacity(variableName) {
|
function withOpacity(variableName) {
|
||||||
return ({ opacityValue }) => {
|
return ({ opacityValue }) => {
|
||||||
if (opacityValue !== undefined) {
|
if (opacityValue !== undefined) {
|
||||||
return `rgba(var(${variableName}), ${opacityValue})`
|
return `rgba(var(${variableName}), ${opacityValue})`;
|
||||||
}
|
}
|
||||||
return `rgb(var(${variableName}))`
|
return `rgb(var(${variableName}))`;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: ["./src/**/*.{html,ts}", "./node_modules/flowbite/**/*.js"],
|
||||||
"./src/**/*.{html,ts}",
|
|
||||||
"./node_modules/flowbite/**/*.js"
|
|
||||||
],
|
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
textColor: {
|
textColor: {
|
||||||
skin: {
|
skin: {
|
||||||
primary: withOpacity('--color-text-primary'),
|
primary: withOpacity("--color-text-primary"),
|
||||||
'primary-muted': withOpacity('--color-text-primary-muted'),
|
"primary-muted": withOpacity("--color-text-primary-muted"),
|
||||||
secondary: withOpacity('--color-text-secondary'),
|
secondary: withOpacity("--color-text-secondary"),
|
||||||
'secondary-muted': withOpacity('--color-text-secondary-muted'),
|
"secondary-muted": withOpacity("--color-text-secondary-muted"),
|
||||||
accent: withOpacity('--color-text-accent'),
|
accent: withOpacity("--color-text-accent"),
|
||||||
'accent-muted': withOpacity('--color-text-accent-muted'),
|
"accent-muted": withOpacity("--color-text-accent-muted"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
backgroundColor: {
|
backgroundColor: {
|
||||||
skin: {
|
skin: {
|
||||||
primary: withOpacity('--color-primary'),
|
primary: withOpacity("--color-primary"),
|
||||||
secondary: withOpacity('--color-secondary'),
|
secondary: withOpacity("--color-secondary"),
|
||||||
accent: withOpacity('--color-accent'),
|
accent: withOpacity("--color-accent"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
boxShadowColor: {
|
boxShadowColor: {
|
||||||
skin: {
|
skin: {
|
||||||
primary: withOpacity('--color-text-secondary-muted'),
|
primary: withOpacity("--color-text-secondary-muted"),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
ringColor: {
|
ringColor: {
|
||||||
skin: {
|
skin: {
|
||||||
primary: withOpacity('--color-text-secondary-muted'),
|
primary: withOpacity("--color-text-secondary-muted"),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
divideColor: {
|
divideColor: {
|
||||||
skin: {
|
skin: {
|
||||||
primary: withOpacity('--color-text-secondary-muted'),
|
primary: withOpacity("--color-text-secondary-muted"),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
borderColor: {
|
borderColor: {
|
||||||
skin: {
|
skin: {
|
||||||
primary: withOpacity('--color-text-secondary-muted'),
|
primary: withOpacity("--color-text-secondary-muted"),
|
||||||
}
|
accent: withOpacity("--color-text-accent-muted"),
|
||||||
}
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [require("flowbite/plugin")],
|
||||||
require('flowbite/plugin')
|
};
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user