This commit is contained in:
Flo 2024-08-26 20:19:10 +00:00
parent 0499c81924
commit 9145bc245f
42 changed files with 839 additions and 635 deletions

View File

@ -1,18 +1,17 @@
import { Component, OnInit } from '@angular/core';
import { AuthService } from './core/services/auth.service';
import { AppService } from './core/services/app.service';
import { Component, OnInit } from "@angular/core";
import { AuthService } from "./core/services/auth.service";
import { AppService } from "./core/services/app.service";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"],
})
export class AppComponent implements OnInit {
constructor(
private authService: AuthService,
private appService: AppService,
) {
}
private appService: AppService
) {}
ngOnInit(): void {
this.authService.readUserState();

View File

@ -1,21 +1,28 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { HttpClientModule } from "@angular/common/http";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { AppComponent } from './app.component';
import { RouterModule, Routes } from '@angular/router';
import { SharedModule } from './shared/shared.module';
import { HomeComponent } from './core/components/home/home.component';
import { CoreModule } from './core/core.module';
import { AuthGuard } from './core/guards/auth.guard';
import { SettingsComponent } from './core/components/settings/settings.component';
import { AppComponent } from "./app.component";
import { RouterModule, Routes } from "@angular/router";
import { SharedModule } from "./shared/shared.module";
import { HomeComponent } from "./core/components/home/home.component";
import { CoreModule } from "./core/core.module";
import { AuthGuard } from "./core/guards/auth.guard";
import { SettingsComponent } from "./core/components/settings/settings.component";
const routes: Routes = [
{ path: 'auth', loadChildren: () => import('./core/auth/auth.module').then(m => m.AuthModule) },
{ path: '', component: HomeComponent, canActivate: [AuthGuard], children: [
{path: 'settings', component: SettingsComponent}
]},
{
path: "auth",
loadChildren: () =>
import("./core/auth/auth.module").then((m) => m.AuthModule),
},
{
path: "",
component: HomeComponent,
canActivate: [AuthGuard],
children: [{ path: "settings", component: SettingsComponent }],
},
];
@NgModule({
@ -24,6 +31,7 @@ const routes: Routes = [
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
RouterModule,
RouterModule.forRoot(routes),
SharedModule,
CoreModule,

View File

@ -1,33 +1,32 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { LoginComponent } from './components/login/login.component';
import { RegistrationComponent } from './components/registration/registration.component';
import { ConfirmRegistrationComponent } from './components/confirm-registration/confirm-registration.component';
import { RouterModule, Routes } from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { LoginComponent } from "./components/login/login.component";
import { RegistrationComponent } from "./components/registration/registration.component";
import { ConfirmRegistrationComponent } from "./components/confirm-registration/confirm-registration.component";
import { RouterModule, Routes } from "@angular/router";
import { ReactiveFormsModule } from "@angular/forms";
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'registration', component: RegistrationComponent },
{ path: 'registration/:registrationId', component: ConfirmRegistrationComponent },
{ path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: "login", component: LoginComponent },
{ path: "registration", component: RegistrationComponent },
{
path: "registration/:registrationId",
component: ConfirmRegistrationComponent,
},
{ path: "", redirectTo: "login", pathMatch: "full" },
];
@NgModule({
declarations: [
LoginComponent,
RegistrationComponent,
ConfirmRegistrationComponent
ConfirmRegistrationComponent,
],
exports: [
LoginComponent,
RegistrationComponent,
ConfirmRegistrationComponent
ConfirmRegistrationComponent,
],
imports: [
RouterModule.forChild(routes),
CommonModule,
ReactiveFormsModule
]
imports: [RouterModule.forChild(routes), CommonModule, ReactiveFormsModule],
})
export class AuthModule {}

View File

@ -1,5 +1,4 @@
<div class="mb-10">
</div>
<div class="mb-10"></div>
<div class="max-w-sm mx-auto mb-10">
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
@ -12,12 +11,39 @@
<form class="max-w-sm mx-auto" [formGroup]="confirmRegistrationForm">
<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 />
<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
/>
</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 />
<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>
<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>

View File

@ -1,18 +1,18 @@
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { filter } from 'rxjs';
import { AuthService } from 'src/app/core/services/auth.service';
import { Component } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { ActivatedRoute, Router } from "@angular/router";
import { filter } from "rxjs";
import { AuthService } from "src/app/core/services/auth.service";
@Component({
selector: 'app-confirm-registration',
templateUrl: './confirm-registration.component.html',
styleUrls: ['./confirm-registration.component.scss']
selector: "app-confirm-registration",
templateUrl: "./confirm-registration.component.html",
styleUrls: ["./confirm-registration.component.scss"],
})
export class ConfirmRegistrationComponent {
confirmRegistrationForm = new FormGroup({
password: new FormControl('', [Validators.required]),
passwordConfirmation: new FormControl('', [Validators.required]),
password: new FormControl("", [Validators.required]),
passwordConfirmation: new FormControl("", [Validators.required]),
});
registrationId: string | undefined;
@ -22,27 +22,23 @@ export class ConfirmRegistrationComponent {
private activatedRoute: ActivatedRoute,
private router: Router
) {
this.activatedRoute.params.subscribe(
(params) => {
this.registrationId = params['registrationId'];
}
);
this.activatedRoute.params.subscribe((params) => {
this.registrationId = params["registrationId"];
});
this.authService.currentState$.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("/"));
}
confirm(): void {
if (this.registrationId === undefined)
return;
if (this.registrationId === undefined) return;
this.authService.confirmRegistration({
id: this.registrationId!,
password: this.confirmRegistrationForm.value.password!,
passwordConfirmation: this.confirmRegistrationForm.value.passwordConfirmation!
passwordConfirmation:
this.confirmRegistrationForm.value.passwordConfirmation!,
});
}
}

View File

@ -1,24 +1,59 @@
<div class="mb-10">
</div>
<div class="mb-10"></div>
<div class="max-w-sm mx-auto mb-10">
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
Beekeeper
</h1>
<h1 class="font-bold text-center text-skin-accent text-xl">
Anmeldung
</h1>
<h1 class="font-bold text-center text-skin-accent text-xl">Anmeldung</h1>
</div>
<form class="max-w-sm mx-auto" [formGroup]="loginForm">
<div class="mb-5">
<label for="identifier" class="block mb-2 text-sm font-medium text-skin-primary-muted">Benutzername oder E-Mail</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 />
<label
for="identifier"
class="block mb-2 text-sm font-medium text-skin-primary-muted"
>Benutzername oder E-Mail</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
/>
</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>
<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>
<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>

View File

@ -1,35 +1,30 @@
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { filter, map } from 'rxjs';
import { AuthService } from 'src/app/core/services/auth.service';
import { Component } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { Router } from "@angular/router";
import { filter, map } from "rxjs";
import { AuthService } from "src/app/core/services/auth.service";
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
selector: "app-login",
templateUrl: "./login.component.html",
styleUrls: ["./login.component.scss"],
})
export class LoginComponent {
loginForm = new FormGroup({
identifier: new FormControl('', [Validators.required]),
password: new FormControl('', [Validators.required]),
identifier: new FormControl("", [Validators.required]),
password: new FormControl("", [Validators.required]),
});
constructor(
private authService: AuthService,
private router: Router
) {
this.authService.currentState$.pipe(
filter(state=>state !== undefined && state !== null)
).subscribe((state) =>
this.router.navigateByUrl('/')
);
constructor(private authService: AuthService, private router: Router) {
this.authService.currentState$
.pipe(filter((state) => state !== undefined && state !== null))
.subscribe((state) => this.router.navigateByUrl("/"));
}
login(): void {
this.authService.login({
identifier: this.loginForm.value.identifier!,
password: this.loginForm.value.password!
password: this.loginForm.value.password!,
});
}
}

View File

@ -1,24 +1,59 @@
<div class="mb-10">
</div>
<div class="mb-10"></div>
<div class="max-w-sm mx-auto mb-10">
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
Beekeeper
</h1>
<h1 class="font-bold text-center text-skin-accent text-xl">
Registrierung
</h1>
<h1 class="font-bold text-center text-skin-accent text-xl">Registrierung</h1>
</div>
<form class="max-w-sm mx-auto" [formGroup]="registrationForm">
<div class="mb-5">
<label for="mail" class="block mb-2 text-sm font-medium text-skin-primary-muted">E-Mail</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 />
<label
for="mail"
class="block mb-2 text-sm font-medium text-skin-primary-muted"
>E-Mail</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
/>
</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>
<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>
<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>

View File

@ -1,37 +1,32 @@
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { filter } from 'rxjs';
import { AuthService } from 'src/app/core/services/auth.service';
import { Component } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { Router } from "@angular/router";
import { filter } from "rxjs";
import { AuthService } from "src/app/core/services/auth.service";
@Component({
selector: 'app-registration',
templateUrl: './registration.component.html',
styleUrls: ['./registration.component.scss']
selector: "app-registration",
templateUrl: "./registration.component.html",
styleUrls: ["./registration.component.scss"],
})
export class RegistrationComponent {
registrationForm = new FormGroup({
mail: new FormControl('', [Validators.required]),
username: new FormControl('', [Validators.required]),
mail: new FormControl("", [Validators.required]),
username: new FormControl("", [Validators.required]),
});
constructor(
private authService: AuthService,
private router: Router
) {
this.authService.currentState$.pipe(
filter(state=>state !== undefined && state !== null)
).subscribe((state) =>
this.router.navigateByUrl('/')
);
constructor(private authService: AuthService, private router: Router) {
this.authService.currentState$
.pipe(filter((state) => state !== undefined && state !== null))
.subscribe((state) => this.router.navigateByUrl("/"));
}
register(): void {
this.authService.register({
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");
}
}

View File

@ -1,26 +1,5 @@
<app-navigation></app-navigation>
<div class="max-w-screen-xl mx-auto p-4">
<shared-card icon="/assets/icon.png" header="Test" subHeader="lol noch ein test">
I'm working
</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>

View File

@ -1,40 +1,8 @@
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;
}
import { Component } from "@angular/core";
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
selector: "app-home",
templateUrl: "./home.component.html",
styleUrls: ["./home.component.scss"],
})
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) {
}
}
export class HomeComponent {}

View File

@ -1,60 +1,105 @@
<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 -->
<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" />
<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>
<div class="flex items-center md:order-2 space-x-3 md:space-x-0">
<!--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">
<span class="text-skin-accent rounded-full font-bold p-2">AA</span>
<!-- <img class="w-8 h-8 rounded-full" src="/docs/images/people/profile-picture-3.jpg" alt="user photo"> -->
<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"
>
<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-->
<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
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"
>
<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
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>
</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 -->
<div class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" id="navbar-user">
<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">
<li>
<a routerLink="/home" class="block py-2 px-3 rounded text-skin-primary md:p-0" aria-current="page">Home</a>
</li>
<li>
<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>
<div
class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1"
id="navbar-user"
>
<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"
>
<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>
</ul>
</div>
</div>
</nav>

View File

@ -1,17 +1,54 @@
import { Component, OnInit } from '@angular/core';
import { initFlowbite } from 'flowbite';
import { AuthService } from '../../services/auth.service';
import { UserStateResponse } from '../../models/user-state-request.model';
import { Router } from '@angular/router';
import { filter, map } from 'rxjs';
import { AppService } from '../../services/app.service';
import { Component, OnInit } from "@angular/core";
import { initFlowbite } from "flowbite";
import { AuthService } from "../../services/auth.service";
import { UserStateResponse } from "../../models/user-state-request.model";
import { Router } from "@angular/router";
import { filter, map } from "rxjs";
import { AppService } from "../../services/app.service";
interface NavigationLink {
label: string;
routerLink: string;
}
interface UserMenuButton {
label: Function | string;
routerLink: string | undefined;
clickCallback: Function | undefined;
}
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.scss'],
selector: "app-navigation",
templateUrl: "./navigation.component.html",
styleUrls: ["./navigation.component.scss"],
})
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;
darkMode: boolean;
@ -19,14 +56,14 @@ export class NavigationComponent implements OnInit {
constructor(
private authService: AuthService,
private appService: AppService,
private router: Router,
private router: Router
) {
this.darkMode = this.appService.darkMode;
this.state = this.authService.currentState$.value;
this.authService.currentState$.pipe(
filter(state => state === undefined)
).subscribe( state =>{
this.router.navigateByUrl('/auth/login');
this.authService.currentState$
.pipe(filter((state) => state === undefined))
.subscribe((state) => {
this.router.navigateByUrl("/auth/login");
});
}
@ -42,4 +79,18 @@ export class NavigationComponent implements OnInit {
this.appService.toggleDarkMode();
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;
}
}
}

View File

@ -1,33 +1,57 @@
<div>
<div class="mb-4 border-b border-gray-200 dark:border-gray-700">
<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">
<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-skin-accent border-skin-accent"
data-tabs-inactive-classes="text-skin-primary-muted hover:text-skin-primary border-skin-primary hover:border-skin-accent"
role="tablist"
>
<li class="me-2" role="presentation">
<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>
<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"
>
Profil
</button>
</li>
<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="dashboard-styled-tab" data-tabs-target="#styled-dashboard" type="button" role="tab" aria-controls="dashboard" aria-selected="false">Dashboard</button>
</li>
<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>
<li 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="contacts-styled-tab" data-tabs-target="#styled-contacts" type="button" role="tab" aria-controls="contacts" aria-selected="false">Contacts</button>
<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">
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="styled-profile" role="tabpanel" aria-labelledby="profile-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">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>
<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 class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="styled-dashboard" role="tabpanel" aria-labelledby="dashboard-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>
<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
class="hidden p-4 rounded-lg"
id="styled-security"
role="tabpanel"
aria-labelledby="security-tab"
>
<app-tab-security />
</div>
</div>
</div>

View File

@ -1,10 +1,13 @@
import { Component } from '@angular/core';
import { Component, OnInit } from "@angular/core";
import { initFlowbite } from "flowbite";
@Component({
selector: 'app-settings',
templateUrl: './settings.component.html',
styleUrls: ['./settings.component.scss']
selector: "app-settings",
templateUrl: "./settings.component.html",
styleUrls: ["./settings.component.scss"],
})
export class SettingsComponent {
export class SettingsComponent implements OnInit {
ngOnInit(): void {
initFlowbite();
}
}

View File

@ -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>

View File

@ -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 {
}

View File

@ -0,0 +1,5 @@
<div class="mb-5">
<shared-table [items]="colonies" [columns]="columns"> </shared-table>
</div>
<shared-paginator total="20" perPage="5" />

View File

@ -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" }];
}

View File

@ -1,20 +1,27 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NavigationComponent } from './components/navigation/navigation.component';
import { AuthGuard } from './guards/auth.guard';
import { AuthService } from './services/auth.service';
import { RequestService } from './services/request.service';
import { AppService } from './services/app.service';
import { SharedModule } from '../shared/shared.module';
import { SettingsComponent } from './components/settings/settings.component';
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { NavigationComponent } from "./components/navigation/navigation.component";
import { AuthGuard } from "./guards/auth.guard";
import { AuthService } from "./services/auth.service";
import { RequestService } from "./services/request.service";
import { AppService } from "./services/app.service";
import { SharedModule } from "../shared/shared.module";
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({
declarations: [NavigationComponent, SettingsComponent],
exports: [NavigationComponent, SettingsComponent],
imports: [
CommonModule,
SharedModule
declarations: [
NavigationComponent,
SettingsComponent,
TabProfileComponent,
TabSecurityComponent,
TabProfileComponent,
TabSecurityComponent,
],
providers: [AuthGuard, AuthService, RequestService, AppService]
exports: [NavigationComponent, SettingsComponent],
imports: [CommonModule, SharedModule, RouterModule],
providers: [AuthGuard, AuthService, RequestService, AppService],
})
export class CoreModule {}

View File

@ -1,26 +1,28 @@
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 { AuthService } from "../services/auth.service";
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthService,
private router: Router
) {
}
constructor(private authService: AuthService, private router: Router) {}
canActivate(): Observable<boolean> | boolean {
return this.authService.currentState$.pipe(
filter(currentState=>currentState!==undefined),
filter((currentState) => currentState !== undefined),
map((currentState) => {
if (currentState === null) {
this.router.navigateByUrl('/auth/login');
this.router.navigateByUrl("/auth/login");
return false;
}
return true;
}));
})
);
}
}

View File

@ -1,14 +1,14 @@
export interface ConfirmRegistrationRequest {
id: string,
password: string,
passwordConfirmation: string,
id: string;
password: string;
passwordConfirmation: string;
}
export interface ConfirmRegistrationResponse {
id: string,
username: string,
roleIdentifier: string,
createdAt: string,
updatedAt: string,
permissions: string[]
id: string;
username: string;
roleIdentifier: string;
createdAt: string;
updatedAt: string;
permissions: string[];
}

View File

@ -1,8 +1,8 @@
export interface LoginRequest {
identifier: string,
password: string,
identifier: string;
password: string;
}
export interface LoginResponse {
sessionId: string
sessionId: string;
}

View File

@ -1,7 +1,6 @@
export interface RegisterUserRequest {
mail: string,
username: string,
mail: string;
username: string;
}
export interface RegisterUserResponse {
}
export interface RegisterUserResponse {}

View File

@ -1,12 +1,11 @@
export interface UserStateRequest {
}
export interface UserStateRequest {}
export interface UserStateResponse {
id: string,
sessionId: string,
username: string,
roleIdentifier: string,
createdAt: string,
updatedAt: string,
permissions: string[],
id: string;
sessionId: string;
username: string;
roleIdentifier: string;
createdAt: string;
updatedAt: string;
permissions: string[];
}

View File

@ -2,20 +2,20 @@ import { Injectable } from "@angular/core";
@Injectable()
export class AppService {
darkMode: boolean;
constructor(
) {
this.darkMode = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
constructor() {
this.darkMode =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
this.applyDarkMode();
}
private applyDarkMode(): void {
if (this.darkMode) {
document.documentElement.classList.add('theme-dark');
document.documentElement.classList.add("theme-dark");
} else {
document.documentElement.classList.remove('theme-dark');
document.documentElement.classList.remove("theme-dark");
}
}

View File

@ -4,39 +4,42 @@ import { UserStateResponse } from "../models/user-state-request.model";
import { BehaviorSubject } from "rxjs";
import { LoginRequest, LoginResponse } from "../models/login-request.model";
import { Router } from "@angular/router";
import { RegisterUserRequest, RegisterUserResponse } from "../models/register-user-request.model";
import { ConfirmRegistrationRequest, ConfirmRegistrationResponse } from "../models/confirm-registration-request.model";
import {
RegisterUserRequest,
RegisterUserResponse,
} from "../models/register-user-request.model";
import {
ConfirmRegistrationRequest,
ConfirmRegistrationResponse,
} from "../models/confirm-registration-request.model";
@Injectable()
export class AuthService {
currentState$ = new BehaviorSubject<UserStateResponse | null | undefined>(
undefined
);
currentState$ = new BehaviorSubject<UserStateResponse | null | undefined>(undefined);
constructor(
private requestService: RequestService,
private router: Router
) {
}
constructor(private requestService: RequestService, private router: Router) {}
readUserState(): void {
this.requestService.get(
'user/state',
"user/state",
{},
(response: UserStateResponse) => {
console.log('set next state');
console.log("set next state");
this.currentState$.next(response);
},
() => {
this.currentState$.next(null);
}
)
);
}
login(body: LoginRequest): LoginResponse | null {
let result = null;
this.requestService.post(
'auth/login-user',
"auth/login-user",
body,
(response: LoginResponse) => {
result = response;
@ -51,7 +54,7 @@ export class AuthService {
let result = null;
this.requestService.post(
'auth/register-user',
"auth/register-user",
body,
(response: LoginResponse) => {
result = response;
@ -62,11 +65,13 @@ export class AuthService {
return result;
}
confirmRegistration(body: ConfirmRegistrationRequest): ConfirmRegistrationResponse|null {
confirmRegistration(
body: ConfirmRegistrationRequest
): ConfirmRegistrationResponse | null {
let result = null;
this.requestService.post(
'auth/confirm-registration',
"auth/confirm-registration",
body,
(response: LoginResponse) => {
result = response;
@ -78,13 +83,9 @@ export class AuthService {
}
logout(): void {
this.requestService.post(
'auth/logout-user',
{},
(response: any) => {
this.requestService.post("auth/logout-user", {}, (response: any) => {
this.currentState$.next(undefined);
this.readUserState();
}
);
});
}
}

View File

@ -1,59 +1,63 @@
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { Injectable } from '@angular/core';
import { HttpClient } from "@angular/common/http";
import { Router } from "@angular/router";
import { Injectable } from "@angular/core";
@Injectable({
providedIn: 'root'
providedIn: "root",
})
export class RequestService {
constructor(private http: HttpClient, private router: Router) {}
constructor(
private http: HttpClient,
private router: Router,
public post(
apiPath: string,
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 observable = this.http.post(url, body).subscribe(
(answer: any) => {
successFunction(answer);
},
(error: any) => {
if (errorFunction === null)
this.handleError(error);
else
errorFunction(error);
if (errorFunction === null) this.handleError(error);
else errorFunction(error);
}
);
}
public get(apiPath: string, body: any, 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);
if (errorFunction === null) this.handleError(error);
else errorFunction(error);
}
);
}
public postFiles(apiPath: string, files: File[], successFunction: Function, errorFunction: Function|null = null) {
public postFiles(
apiPath: string,
files: File[],
successFunction: Function,
errorFunction: Function | null = null
) {
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();
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);
@ -62,10 +66,8 @@ export class RequestService {
successFunction(answer);
},
(error: any) => {
if (errorFunction === null)
this.handleError(error);
else
errorFunction(error);
if (errorFunction === null) this.handleError(error);
else errorFunction(error);
}
);
}
@ -73,34 +75,33 @@ export class RequestService {
private obtainUrl(apiPath: string): string {
let hostString = window.location.host;
let protocol = window.location.protocol;
return protocol + '//' + hostString + '/api/' + apiPath;
return protocol + "//" + hostString + "/api/" + apiPath;
}
private handleError(answer: any): void {
if (answer.status == 401) {
console.log('Deine Sitzung konnte nicht gefunden werden');
this.router.navigate(['/auth']);
console.log("Deine Sitzung konnte nicht gefunden werden");
this.router.navigate(["/auth"]);
return;
}
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;
}
try {
let errorObject = answer.error.error;
if (errorObject.hasOwnProperty('message')) {
if (errorObject.hasOwnProperty("message")) {
throw errorObject.message.toString();
}
if (errorObject.hasOwnProperty('code')) {
if (errorObject.hasOwnProperty("code")) {
throw errorObject.code.toString();
}
} catch (error: any) {
this.showSnackBar(error.toString(), 'Ok');
this.showSnackBar(error.toString(), "Ok");
}
}

View File

@ -2,7 +2,11 @@
id="card"
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">
<!--Icon-->
<div *ngIf="icon !== null" class="basis-auto">
@ -13,12 +17,11 @@
<div class="basis-full truncate">
<div
*ngIf="header !== null"
class="text-xl font-medium text-skin-primary mb-2">
class="text-xl font-medium text-skin-primary mb-2"
>
{{ header }}
</div>
<div
*ngIf="subHeader !== null"
class="text-skin-primary-muted pl-2">
<div *ngIf="subHeader !== null" class="text-skin-primary-muted pl-2">
{{ subHeader }}
</div>
</div>

View File

@ -1,9 +1,9 @@
import { Component, Input } from '@angular/core';
import { Component, Input } from "@angular/core";
@Component({
selector: 'shared-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.scss'],
selector: "shared-card",
templateUrl: "./card.component.html",
styleUrls: ["./card.component.scss"],
})
export class CardComponent {
@Input() header: string | null = null;

View File

@ -28,9 +28,9 @@
<div
class="flex items-center justify-center h-8 leading-tight border border-skin-primary text-skin-primary"
[ngClass]="{
'bg-skin-accent font-bold text-skin-secondary hover:text-skin-primary': item.page === page,
'bg-skin-secondary':
item.page !== page
'bg-skin-accent font-bold text-skin-secondary hover:text-skin-primary':
item.page === page,
'bg-skin-secondary': item.page !== page
}"
>
<div *ngIf="item.page === null" class="px-3">...</div>

View File

@ -5,16 +5,16 @@ import {
OnChanges,
Output,
SimpleChanges,
} from '@angular/core';
} from "@angular/core";
export interface PaginatorItem {
page: number | null;
}
@Component({
selector: 'shared-paginator',
templateUrl: './paginator.component.html',
styleUrls: ['./paginator.component.scss'],
selector: "shared-paginator",
templateUrl: "./paginator.component.html",
styleUrls: ["./paginator.component.scss"],
})
export class PaginatorComponent implements OnChanges {
@Output() pageChange = new EventEmitter<number>();

View File

@ -1,4 +1,4 @@
import { Component, Input } from '@angular/core';
import { Component, Input } from "@angular/core";
export interface ColumnDefinition {
header: string;
@ -8,9 +8,9 @@ export interface ColumnDefinition {
}
@Component({
selector: 'shared-table',
templateUrl: './table.component.html',
styleUrls: ['./table.component.scss'],
selector: "shared-table",
templateUrl: "./table.component.html",
styleUrls: ["./table.component.scss"],
})
export class TableComponent {
@Input() items: any[] = [];
@ -18,6 +18,6 @@ export class TableComponent {
isBoolean(obje: any): boolean {
console.log(obje);
return typeof obje === 'boolean';
return typeof obje === "boolean";
}
}

View File

@ -1,4 +0,0 @@
export interface TabItem {
id: string;
title: string;
}

View File

@ -0,0 +1,4 @@
export interface TabItem {
id: string;
title: string;
}

View File

@ -1,28 +1,14 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { CardComponent } from './components/card/card.component';
import { PaginatorComponent } from './components/paginator/paginator.component';
import { TableComponent } from './components/table/table.component';
import { FormsModule } from '@angular/forms';
import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { CommonModule } from "@angular/common";
import { CardComponent } from "./components/card/card.component";
import { PaginatorComponent } from "./components/paginator/paginator.component";
import { TableComponent } from "./components/table/table.component";
import { FormsModule } from "@angular/forms";
@NgModule({
declarations: [
CardComponent,
PaginatorComponent,
TableComponent,
],
exports: [
CardComponent,
PaginatorComponent,
TableComponent,
FormsModule,
],
imports: [
RouterModule,
CommonModule,
FormsModule,
],
declarations: [CardComponent, PaginatorComponent, TableComponent],
exports: [CardComponent, PaginatorComponent, TableComponent, FormsModule],
imports: [RouterModule, CommonModule, FormsModule],
})
export class SharedModule {}

View File

@ -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().bootstrapModule(AppModule)
.catch(err => console.error(err));
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));

View File

@ -28,4 +28,3 @@
--color-accent: 250, 183, 0;
}
}

View File

@ -1,61 +1,56 @@
function withOpacity(variableName) {
return ({ opacityValue }) => {
if (opacityValue !== undefined) {
return `rgba(var(${variableName}), ${opacityValue})`
}
return `rgb(var(${variableName}))`
return `rgba(var(${variableName}), ${opacityValue})`;
}
return `rgb(var(${variableName}))`;
};
}
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{html,ts}",
"./node_modules/flowbite/**/*.js"
],
content: ["./src/**/*.{html,ts}", "./node_modules/flowbite/**/*.js"],
theme: {
extend: {
textColor: {
skin: {
primary: withOpacity('--color-text-primary'),
'primary-muted': withOpacity('--color-text-primary-muted'),
secondary: withOpacity('--color-text-secondary'),
'secondary-muted': withOpacity('--color-text-secondary-muted'),
accent: withOpacity('--color-text-accent'),
'accent-muted': withOpacity('--color-text-accent-muted'),
primary: withOpacity("--color-text-primary"),
"primary-muted": withOpacity("--color-text-primary-muted"),
secondary: withOpacity("--color-text-secondary"),
"secondary-muted": withOpacity("--color-text-secondary-muted"),
accent: withOpacity("--color-text-accent"),
"accent-muted": withOpacity("--color-text-accent-muted"),
},
},
backgroundColor: {
skin: {
primary: withOpacity('--color-primary'),
secondary: withOpacity('--color-secondary'),
accent: withOpacity('--color-accent'),
primary: withOpacity("--color-primary"),
secondary: withOpacity("--color-secondary"),
accent: withOpacity("--color-accent"),
},
},
boxShadowColor: {
skin: {
primary: withOpacity('--color-text-secondary-muted'),
}
primary: withOpacity("--color-text-secondary-muted"),
},
},
ringColor: {
skin: {
primary: withOpacity('--color-text-secondary-muted'),
}
primary: withOpacity("--color-text-secondary-muted"),
},
},
divideColor: {
skin: {
primary: withOpacity('--color-text-secondary-muted'),
}
primary: withOpacity("--color-text-secondary-muted"),
},
},
borderColor: {
skin: {
primary: withOpacity('--color-text-secondary-muted'),
}
}
primary: withOpacity("--color-text-secondary-muted"),
accent: withOpacity("--color-text-accent-muted"),
},
},
plugins: [
require('flowbite/plugin')
],
}
},
},
plugins: [require("flowbite/plugin")],
};