generated from flo/template-frontend
Compare commits
No commits in common. "d8d09d7bac31fe1c7456ed481b37e004f9f7c28d" and "070e9bb87649aea011e0e016fc10491d8a02a0d6" have entirely different histories.
d8d09d7bac
...
070e9bb876
@ -84,10 +84,10 @@
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "bee:build:production"
|
||||
"browserTarget": "bee:build:production"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "bee:build:development"
|
||||
"browserTarget": "bee:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
@ -95,7 +95,7 @@
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "bee:build"
|
||||
"browserTarget": "bee:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
|
||||
29
package.json
29
package.json
@ -9,25 +9,24 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^18.2.2",
|
||||
"@angular/common": "^18.2.2",
|
||||
"@angular/compiler": "^18.2.2",
|
||||
"@angular/core": "^18.2.2",
|
||||
"@angular/forms": "^18.2.2",
|
||||
"@angular/platform-browser": "^18.2.2",
|
||||
"@angular/platform-browser-dynamic": "^18.2.2",
|
||||
"@angular/router": "^18.2.2",
|
||||
"@ngx-translate/core": "^15.0.0",
|
||||
"@ngx-translate/http-loader": "^8.0.0",
|
||||
"@angular/animations": "^15.2.10",
|
||||
"@angular/cdk": "^15.2.9",
|
||||
"@angular/common": "^15.2.0",
|
||||
"@angular/compiler": "^15.2.0",
|
||||
"@angular/core": "^15.2.0",
|
||||
"@angular/forms": "^15.2.0",
|
||||
"@angular/platform-browser": "^15.2.0",
|
||||
"@angular/platform-browser-dynamic": "^15.2.0",
|
||||
"@angular/router": "^15.2.0",
|
||||
"flowbite": "^2.5.1",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.14.10"
|
||||
"zone.js": "~0.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^18.2.2",
|
||||
"@angular/cli": "~18.2.2",
|
||||
"@angular/compiler-cli": "^18.2.2",
|
||||
"@angular-devkit/build-angular": "^15.2.6",
|
||||
"@angular/cli": "~15.2.6",
|
||||
"@angular/compiler-cli": "^15.2.0",
|
||||
"@types/jasmine": "~4.3.0",
|
||||
"jasmine-core": "~4.5.0",
|
||||
"karma": "~6.4.0",
|
||||
@ -36,6 +35,6 @@
|
||||
"karma-jasmine": "~5.1.0",
|
||||
"karma-jasmine-html-reporter": "~2.0.0",
|
||||
"tailwindcss": "^3.4.10",
|
||||
"typescript": "~5.4.5"
|
||||
"typescript": "~4.9.4"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1 @@
|
||||
<router-outlet></router-outlet>
|
||||
|
||||
<div class="absolute bottom-0 w-full z-50">
|
||||
<app-notification-bar />
|
||||
</div>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { AuthService } from "./core/services/auth.service";
|
||||
import { AppService } from "./core/services/app.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
selector: "app-root",
|
||||
@ -11,13 +10,8 @@ import { TranslateService } from "@ngx-translate/core";
|
||||
export class AppComponent implements OnInit {
|
||||
constructor(
|
||||
private authService: AuthService,
|
||||
private translate: TranslateService
|
||||
) {
|
||||
var language = navigator.language;
|
||||
|
||||
translate.setDefaultLang(language);
|
||||
translate.use(language);
|
||||
}
|
||||
private appService: AppService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.authService.readUserState();
|
||||
|
||||
@ -1,13 +1,8 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { BrowserModule } from "@angular/platform-browser";
|
||||
import {
|
||||
HttpClient,
|
||||
provideHttpClient,
|
||||
withInterceptorsFromDi,
|
||||
} from "@angular/common/http";
|
||||
import { HttpClientModule } from "@angular/common/http";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { TranslateModule, TranslateLoader } from "@ngx-translate/core";
|
||||
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
|
||||
|
||||
import { AppComponent } from "./app.component";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
import { SharedModule } from "./shared/shared.module";
|
||||
@ -30,28 +25,18 @@ const routes: Routes = [
|
||||
},
|
||||
];
|
||||
|
||||
export function createTranslateLoader(http: HttpClient) {
|
||||
return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, HomeComponent],
|
||||
bootstrap: [AppComponent],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
HttpClientModule,
|
||||
RouterModule,
|
||||
RouterModule.forRoot(routes),
|
||||
SharedModule,
|
||||
CoreModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useFactory: createTranslateLoader,
|
||||
deps: [HttpClient],
|
||||
},
|
||||
}),
|
||||
],
|
||||
providers: [provideHttpClient(withInterceptorsFromDi())],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
@ -7,7 +7,6 @@ import { RouterModule, Routes } from "@angular/router";
|
||||
import { ReactiveFormsModule } from "@angular/forms";
|
||||
import { ForgotPasswordComponent } from "./components/forgot-password/forgot-password.component";
|
||||
import { ResetPasswordComponent } from "./components/reset-password/reset-password.component";
|
||||
import { TranslateModule } from "@ngx-translate/core";
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: "login", component: LoginComponent },
|
||||
@ -39,11 +38,6 @@ const routes: Routes = [
|
||||
ForgotPasswordComponent,
|
||||
ResetPasswordComponent,
|
||||
],
|
||||
imports: [
|
||||
RouterModule.forChild(routes),
|
||||
CommonModule,
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, ReactiveFormsModule],
|
||||
})
|
||||
export class AuthModule {}
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
|
||||
<div class="max-w-sm mx-auto mb-10">
|
||||
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
||||
{{ "title" | translate }}
|
||||
Beekeeper
|
||||
</h1>
|
||||
<h1 class="font-bold text-center text-skin-accent text-xl">
|
||||
{{ "auth.confirm-registration" | translate }}
|
||||
Registrierung Abschließen
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
<label
|
||||
for="password"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "auth.password" | translate }}</label
|
||||
>Passwort</label
|
||||
>
|
||||
<input
|
||||
formControlName="password"
|
||||
@ -28,7 +28,7 @@
|
||||
<label
|
||||
for="passwordConfirmation"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "auth.password-confirmation" | translate }}</label
|
||||
>Passwort wiederholen</label
|
||||
>
|
||||
<input
|
||||
formControlName="passwordConfirmation"
|
||||
@ -44,6 +44,6 @@
|
||||
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"
|
||||
>
|
||||
{{ "auth.confirm-registration" | translate }}
|
||||
Registrieren
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
|
||||
<div class="max-w-sm mx-auto mb-10">
|
||||
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
||||
{{ "title" | translate }}
|
||||
Beekeeper
|
||||
</h1>
|
||||
<h1 class="font-bold text-center text-skin-accent text-xl">
|
||||
{{ "auth.forgot-password" | translate }}
|
||||
Passwort vergessen?
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@ -14,8 +14,7 @@
|
||||
<label
|
||||
for="mail"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>
|
||||
{{ "auth.email" | translate }}</label
|
||||
>E-Mail</label
|
||||
>
|
||||
<input
|
||||
formControlName="mail"
|
||||
@ -31,6 +30,6 @@
|
||||
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"
|
||||
>
|
||||
{{ "auth.reset-password" | translate }}
|
||||
Passwort zurücksetzen
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@ -2,11 +2,9 @@
|
||||
|
||||
<div class="max-w-sm mx-auto mb-10">
|
||||
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
||||
{{ "title" | translate }}
|
||||
</h1>
|
||||
<h1 class="font-bold text-center text-skin-accent text-xl">
|
||||
{{ "auth.login" | translate }}
|
||||
Beekeeper
|
||||
</h1>
|
||||
<h1 class="font-bold text-center text-skin-accent text-xl">Anmeldung</h1>
|
||||
</div>
|
||||
|
||||
<form class="max-w-sm mx-auto" [formGroup]="loginForm">
|
||||
@ -14,7 +12,7 @@
|
||||
<label
|
||||
for="identifier"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "auth.username-or-email" | translate }}</label
|
||||
>Benutzername oder E-Mail</label
|
||||
>
|
||||
<input
|
||||
formControlName="identifier"
|
||||
@ -28,11 +26,11 @@
|
||||
id="helper-text-explanation"
|
||||
class="mt-2 text-sm text-skin-primary-muted"
|
||||
>
|
||||
{{ "auth.not-yet-registered" | translate }}
|
||||
Neu hier?
|
||||
<a
|
||||
routerLink="/auth/registration"
|
||||
class="font-medium text-skin-accent hover:underline hover:font-bold"
|
||||
>{{ "auth.register-now" | translate }}</a
|
||||
>Jetzt registrieren!</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
@ -40,7 +38,7 @@
|
||||
<label
|
||||
for="password"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "auth.password" | translate }}</label
|
||||
>Passwort</label
|
||||
>
|
||||
<input
|
||||
formControlName="password"
|
||||
@ -56,7 +54,7 @@
|
||||
<a
|
||||
routerLink="/auth/forgot-password"
|
||||
class="font-medium text-skin-accent hover:underline hover:font-bold"
|
||||
>{{ "auth.forgot-password" | translate }}?</a
|
||||
>Passwort vergessen?</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
@ -66,6 +64,6 @@
|
||||
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"
|
||||
>
|
||||
{{ "auth.login" | translate }}
|
||||
Anmelden
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@ -2,11 +2,9 @@
|
||||
|
||||
<div class="max-w-sm mx-auto mb-10">
|
||||
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
||||
{{ "title" | translate }}
|
||||
</h1>
|
||||
<h1 class="font-bold text-center text-skin-accent text-xl">
|
||||
{{ "auth.registration" | translate }}
|
||||
Beekeeper
|
||||
</h1>
|
||||
<h1 class="font-bold text-center text-skin-accent text-xl">Registrierung</h1>
|
||||
</div>
|
||||
|
||||
<form class="max-w-sm mx-auto" [formGroup]="registrationForm">
|
||||
@ -14,8 +12,7 @@
|
||||
<label
|
||||
for="mail"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>
|
||||
{{ "auth.email" | translate }}</label
|
||||
>E-Mail</label
|
||||
>
|
||||
<input
|
||||
formControlName="mail"
|
||||
@ -30,8 +27,7 @@
|
||||
<label
|
||||
for="username"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>
|
||||
{{ "auth.reset-password" | translate }}</label
|
||||
>Benutzername</label
|
||||
>
|
||||
<input
|
||||
formControlName="username"
|
||||
@ -44,11 +40,11 @@
|
||||
id="helper-text-explanation"
|
||||
class="mt-2 text-sm text-skin-primary-muted"
|
||||
>
|
||||
{{ "auth.already-registered" | translate }}
|
||||
Bereits registiert?
|
||||
<a
|
||||
routerLink="/auth/login"
|
||||
class="font-medium text-skin-accent hover:underline hover:font-bold"
|
||||
>{{ "auth.login-now" | translate }}</a
|
||||
>Jetzt anmelden!</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
@ -58,6 +54,6 @@
|
||||
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"
|
||||
>
|
||||
{{ "auth.register" | translate }}
|
||||
Registrieren
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
|
||||
<div class="max-w-sm mx-auto mb-10">
|
||||
<h1 class="font-bold text-center text-skin-primary text-5xl mb-5">
|
||||
{{ "title" | translate }}
|
||||
Beekeeper
|
||||
</h1>
|
||||
<h1 class="font-bold text-center text-skin-accent text-xl">
|
||||
{{ "auth.reset-password" | translate }}
|
||||
Passwort zurücksetzen
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
<label
|
||||
for="newPassword"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "auth.new-password" | translate }}</label
|
||||
>Neues Passwort</label
|
||||
>
|
||||
<input
|
||||
formControlName="newPassword"
|
||||
@ -28,7 +28,7 @@
|
||||
<label
|
||||
for="passwordConfirmation"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "auth.password-confirmation" | translate }}</label
|
||||
>Passwort wiederholen</label
|
||||
>
|
||||
<input
|
||||
formControlName="passwordConfirmation"
|
||||
@ -44,6 +44,6 @@
|
||||
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"
|
||||
>
|
||||
{{ "auth.new-password" | translate }}
|
||||
Neues Passwort bestätigen
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@ -1,10 +1,5 @@
|
||||
<app-navigation></app-navigation>
|
||||
|
||||
<div class="mx-auto p-5 flex flex-row">
|
||||
<div id="sidebar-placehodler" class="basis-auto">
|
||||
<div class="w-0 xl:w-64"></div>
|
||||
</div>
|
||||
<div id="content" class="basis-full">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
<div class="max-w-screen-xl mx-auto p-4">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
||||
@ -1,97 +1,108 @@
|
||||
<nav class="bg-skin-accent">
|
||||
<div class="h-20 flex flex-wrap items-center justify-between mx-auto p-4">
|
||||
<!--Burger Menu-->
|
||||
<button
|
||||
data-collapse-toggle="default-sidebar"
|
||||
type="button"
|
||||
class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-skin-primary rounded-lg hover:bg-skin-primary xl:hidden"
|
||||
aria-controls="default-sidebar"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="sr-only">Open main menu</span>
|
||||
<svg class="w-5 h-5" aria-hidden="true" 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
|
||||
class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4"
|
||||
>
|
||||
<!-- Title -->
|
||||
<a routerLink="/" class="flex items-center space-x-3">
|
||||
<img src="assets/icon.png" class="h-10 w-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"
|
||||
>{{ "title" | translate }}</span
|
||||
>Bienenkeeper</span
|
||||
>
|
||||
</a>
|
||||
|
||||
<!--User Bubble-->
|
||||
<button
|
||||
type="button"
|
||||
class="w-12 h-12 text-sm bg-skin-primary rounded-full 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>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Navbar -->
|
||||
<div
|
||||
id="default-sidebar"
|
||||
class="fixed hidden xl:block -bottom-20 left-0 z-40 w-64 h-screen translate-x-0 bg-skin-secondary"
|
||||
aria-label="Sidebar"
|
||||
>
|
||||
<ul class="text-xl p-4 rounded-lg">
|
||||
<li *ngFor="let navigationLink of navigationLinks">
|
||||
<a
|
||||
class="block py-2 px-3 rounded text-skin-primary hover:text-skin-secondary hover:bg-skin-accent"
|
||||
[routerLink]="navigationLink.routerLink"
|
||||
[routerLinkActiveOptions]="{ exact: true }"
|
||||
routerLinkActive="font-bold"
|
||||
>{{ getNavigationLinkLabel(navigationLink) | translate }}</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"
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<span class="text-skin-accent rounded-full font-bold p-2 uppercase">{{
|
||||
state?.username[0] + state?.roleIdentifier[0]
|
||||
}}</span>
|
||||
</button>
|
||||
|
||||
<!-- User dropdown -->
|
||||
<div id="user-dropdown" class="hidden min-w-full md:min-w-64 px-4 z-50">
|
||||
<div
|
||||
class="text-base list-none divide-y divide-skin-primary rounded-lg shadow-sm shadow-skin-primary bg-skin-primary"
|
||||
>
|
||||
<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>
|
||||
<!--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"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<ul class="p-4" aria-labelledby="user-menu-button">
|
||||
<li *ngFor="let usermenuButton of usermenuButtons">
|
||||
<button
|
||||
class="w-full text-center block py-2 px-3 rounded text-skin-primary hover:bg-skin-accent"
|
||||
[routerLink]="
|
||||
usermenuButton.routerLink === undefined
|
||||
? null
|
||||
: [usermenuButton.routerLink]
|
||||
"
|
||||
(click)="clickUserMenuButtonLabel(usermenuButton)"
|
||||
>
|
||||
{{ getUserMenuButtonLabel(usermenuButton) | translate }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- User dropdown -->
|
||||
<div id="user-dropdown" class="hidden min-w-full md:min-w-72 px-4">
|
||||
<div
|
||||
class="text-base list-none divide-y divide-skin-primary rounded-lg shadow-sm shadow-skin-primary bg-skin-primary"
|
||||
>
|
||||
<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>
|
||||
</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 *ngFor="let navigationLink of navigationLinks">
|
||||
<a
|
||||
class="block py-2 px-3 rounded text-skin-primary hover:text-skin-secondary hover:bg-skin-accent md:p-0"
|
||||
[routerLink]="navigationLink.routerLink"
|
||||
[routerLinkActiveOptions]="{ exact: true }"
|
||||
routerLinkActive="font-bold"
|
||||
>{{ navigationLink.label }}</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@ -3,13 +3,11 @@ 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 } from "rxjs";
|
||||
import { filter, map } from "rxjs";
|
||||
import { AppService } from "../../services/app.service";
|
||||
import { NotificationService } from "../../services/notification.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface NavigationLink {
|
||||
label: Function | string;
|
||||
label: string;
|
||||
routerLink: string;
|
||||
}
|
||||
|
||||
@ -26,45 +24,25 @@ interface UserMenuButton {
|
||||
})
|
||||
export class NavigationComponent implements OnInit {
|
||||
navigationLinks: NavigationLink[] = [
|
||||
{ routerLink: "/", label: () => "navigation.home" },
|
||||
{
|
||||
routerLink: "/colonies",
|
||||
label: () => "navigation.colonies",
|
||||
},
|
||||
{ routerLink: "/", label: "Startseite" },
|
||||
{ routerLink: "/settings", label: "Völker" },
|
||||
];
|
||||
|
||||
usermenuButtons: UserMenuButton[] = [
|
||||
{
|
||||
label: () => "menu.settings",
|
||||
label: "Einstellungen",
|
||||
routerLink: "/settings",
|
||||
clickCallback: undefined,
|
||||
},
|
||||
{
|
||||
label: () => (this.darkMode ? "menu.theme.light" : "menu.theme.dark"),
|
||||
label: () => (this.darkMode ? "Hell" : "Dunkel"),
|
||||
routerLink: undefined,
|
||||
clickCallback: () => {
|
||||
this.toggleDarkmode();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: () => (this.language === "de" ? "languages.en" : "languages.de"),
|
||||
routerLink: undefined,
|
||||
clickCallback: () => {
|
||||
this.toggleLanguage();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Test",
|
||||
routerLink: undefined,
|
||||
clickCallback: () => {
|
||||
this.notificationService.push(
|
||||
this.translate.instant("error.Generic.SomethingWentWrong"),
|
||||
"danger"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: () => "menu.logout",
|
||||
label: "Ausloggen",
|
||||
routerLink: undefined,
|
||||
clickCallback: () => {
|
||||
this.logout();
|
||||
@ -74,28 +52,13 @@ export class NavigationComponent implements OnInit {
|
||||
|
||||
state: UserStateResponse | undefined | null;
|
||||
darkMode: boolean;
|
||||
language: "de" | "en";
|
||||
|
||||
constructor(
|
||||
private authService: AuthService,
|
||||
private appService: AppService,
|
||||
private notificationService: NotificationService,
|
||||
private translate: TranslateService,
|
||||
private router: Router
|
||||
) {
|
||||
this.darkMode = this.appService.darkMode;
|
||||
|
||||
switch (translate.currentLang) {
|
||||
case "en":
|
||||
this.language = "en";
|
||||
break;
|
||||
case "de":
|
||||
this.language = "de";
|
||||
break;
|
||||
default:
|
||||
this.language = "de";
|
||||
}
|
||||
|
||||
this.state = this.authService.currentState$.value;
|
||||
this.authService.currentState$
|
||||
.pipe(filter((state) => state === undefined))
|
||||
@ -117,19 +80,6 @@ export class NavigationComponent implements OnInit {
|
||||
this.darkMode = this.appService.darkMode;
|
||||
}
|
||||
|
||||
toggleLanguage() {
|
||||
switch (this.language) {
|
||||
case "en":
|
||||
this.language = "de";
|
||||
break;
|
||||
case "de":
|
||||
this.language = "en";
|
||||
break;
|
||||
}
|
||||
|
||||
this.translate.use(this.language);
|
||||
}
|
||||
|
||||
clickUserMenuButtonLabel(button: UserMenuButton) {
|
||||
if (button.clickCallback !== undefined) {
|
||||
button.clickCallback();
|
||||
@ -143,11 +93,4 @@ export class NavigationComponent implements OnInit {
|
||||
return button.label;
|
||||
}
|
||||
}
|
||||
getNavigationLinkLabel(link: NavigationLink) {
|
||||
if (typeof link.label === "function") {
|
||||
return link.label();
|
||||
} else {
|
||||
return link.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
<div
|
||||
*ngFor="let item of items"
|
||||
class="flex items-center opacity-90 p-4 mb-4 text-skin-accent rounded-lg bg-skin-secondary md:max-w-3xl mx-5 md:mx-auto shadow-sm shadow-skin-primary"
|
||||
>
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path
|
||||
d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="sr-only">{{ item.element.type }}</span>
|
||||
<div class="ms-3 text-sm font-medium">
|
||||
{{ item.element.message }}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="ms-auto -mx-1.5 -my-1.5 bg-skin-secondary text-skin-accent rounded-lg focus:ring-2 focus:ring-blue-400 p-1.5 hover:bg-skin-primary inline-flex items-center justify-center h-8 w-8"
|
||||
(click)="dismiss(item)"
|
||||
>
|
||||
<span class="sr-only">Close</span>
|
||||
<svg
|
||||
class="w-3 h-3"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 14 14"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
@ -1,69 +0,0 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { NotificationService } from "../../services/notification.service";
|
||||
|
||||
export interface NotificationElement {
|
||||
message: string;
|
||||
type: "info" | "danger" | "warn" | "success";
|
||||
timeout: number | undefined;
|
||||
}
|
||||
|
||||
interface NotificationItem {
|
||||
element: NotificationElement;
|
||||
shownAt: Date;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: "app-notification-bar",
|
||||
templateUrl: "./notification-bar.component.html",
|
||||
styleUrls: ["./notification-bar.component.scss"],
|
||||
})
|
||||
export class NotificationBarComponent {
|
||||
items: NotificationItem[] = [];
|
||||
isRunning: boolean;
|
||||
|
||||
constructor(private notificationService: NotificationService) {
|
||||
this.isRunning = false;
|
||||
|
||||
this.notificationService.notification$.subscribe((notification) => {
|
||||
if (notification !== undefined) {
|
||||
this.items.push({
|
||||
element: notification,
|
||||
shownAt: new Date(),
|
||||
});
|
||||
|
||||
this.startTimeoutIfNecessary();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startTimeoutIfNecessary(): void {
|
||||
if (this.isRunning === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
let intervalId = setInterval(() => {
|
||||
this.isRunning = true;
|
||||
let now = new Date();
|
||||
this.items.forEach((item) => {
|
||||
if (item.element.timeout !== undefined) {
|
||||
let timeout = new Date(
|
||||
item.shownAt.getTime() + item.element.timeout * 1000
|
||||
);
|
||||
|
||||
if (timeout < now) {
|
||||
this.dismiss(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (this.items.length === 0) {
|
||||
clearInterval(intervalId);
|
||||
this.isRunning = false;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
dismiss(item: NotificationItem): void {
|
||||
this.items = this.items.filter((i) => i !== item);
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@
|
||||
aria-controls="profile"
|
||||
aria-selected="false"
|
||||
>
|
||||
{{ "settings.tab-profile" | translate }}
|
||||
Profil
|
||||
</button>
|
||||
</li>
|
||||
<li class="me-2" role="presentation">
|
||||
@ -40,7 +40,7 @@
|
||||
aria-controls="security"
|
||||
aria-selected="false"
|
||||
>
|
||||
{{ "settings.tab-security" | translate }}
|
||||
Sicherheit
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -1,14 +1,10 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
interface User {
|
||||
username: string;
|
||||
mail: string;
|
||||
age: number;
|
||||
}
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: "app-tab-profile",
|
||||
templateUrl: "./tab-profile.component.html",
|
||||
styleUrls: ["./tab-profile.component.scss"],
|
||||
selector: 'app-tab-profile',
|
||||
templateUrl: './tab-profile.component.html',
|
||||
styleUrls: ['./tab-profile.component.scss']
|
||||
})
|
||||
export class TabProfileComponent {}
|
||||
export class TabProfileComponent {
|
||||
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<div class="grid grid-cols-1 md:grid-cols-2">
|
||||
<div>
|
||||
<h2>{{ "settings.security.change-password" | translate }}</h2>
|
||||
<h2>Passwort ändern</h2>
|
||||
<form class="mx-auto p-5" [formGroup]="changePasswordForm">
|
||||
<div class="mb-5">
|
||||
<label
|
||||
for="password"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "settings.security.current-password" | translate }}</label
|
||||
>Aktuelles Passwort</label
|
||||
>
|
||||
<input
|
||||
formControlName="password"
|
||||
@ -21,7 +21,7 @@
|
||||
<label
|
||||
for="newPassword"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "settings.security.new-password" | translate }}</label
|
||||
>Neues Passwort</label
|
||||
>
|
||||
<input
|
||||
formControlName="newPassword"
|
||||
@ -36,7 +36,7 @@
|
||||
<label
|
||||
for="newPasswordConfirmation"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "settings.security.password-confirmation" | translate }}</label
|
||||
>Neues Passwort bestätigen</label
|
||||
>
|
||||
<input
|
||||
formControlName="newPasswordConfirmation"
|
||||
@ -53,19 +53,19 @@
|
||||
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"
|
||||
>
|
||||
{{ "settings.security.change-password" | translate }}
|
||||
Passwort ändern
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>{{ "settings.security.change-username" | translate }}</h2>
|
||||
<h2>Benutername ändern</h2>
|
||||
<form class="mx-auto p-5" [formGroup]="changeUsernameForm">
|
||||
<div class="mb-5">
|
||||
<label
|
||||
for="password"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "settings.security.current-password" | translate }}</label
|
||||
>Aktuelles Passwort</label
|
||||
>
|
||||
<input
|
||||
formControlName="password"
|
||||
@ -80,7 +80,7 @@
|
||||
<label
|
||||
for="newUsername"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "settings.security.new-username" | translate }}</label
|
||||
>Neuer Benutzername</label
|
||||
>
|
||||
<input
|
||||
formControlName="newUsername"
|
||||
@ -97,7 +97,7 @@
|
||||
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"
|
||||
>
|
||||
{{ "settings.security.change-username" | translate }}
|
||||
Benutzername ändern
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -11,9 +11,6 @@ import { TabProfileComponent } from "./components/settings/tabs/tab-profile/tab-
|
||||
import { TabSecurityComponent } from "./components/settings/tabs/tab-security/tab-security.component";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { ReactiveFormsModule } from "@angular/forms";
|
||||
import { NotificationBarComponent } from "./components/notification-bar/notification-bar.component";
|
||||
import { NotificationService } from "./services/notification.service";
|
||||
import { TranslateModule } from "@ngx-translate/core";
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -21,28 +18,14 @@ import { TranslateModule } from "@ngx-translate/core";
|
||||
SettingsComponent,
|
||||
TabProfileComponent,
|
||||
TabSecurityComponent,
|
||||
NotificationBarComponent,
|
||||
],
|
||||
exports: [
|
||||
NavigationComponent,
|
||||
SettingsComponent,
|
||||
TabProfileComponent,
|
||||
TabSecurityComponent,
|
||||
NotificationBarComponent,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
RouterModule,
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
],
|
||||
providers: [
|
||||
AuthGuard,
|
||||
AuthService,
|
||||
RequestService,
|
||||
AppService,
|
||||
NotificationService,
|
||||
],
|
||||
imports: [CommonModule, SharedModule, RouterModule, ReactiveFormsModule],
|
||||
providers: [AuthGuard, AuthService, RequestService, AppService],
|
||||
})
|
||||
export class CoreModule {}
|
||||
|
||||
@ -1,10 +1,16 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { ActivatedRouteSnapshot, 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 {
|
||||
export class AuthGuard implements CanActivate {
|
||||
constructor(private authService: AuthService, private router: Router) {}
|
||||
|
||||
canActivate(): Observable<boolean> | boolean {
|
||||
|
||||
@ -42,6 +42,7 @@ export class AuthService {
|
||||
"user/state",
|
||||
{},
|
||||
(response: UserStateResponse) => {
|
||||
console.log("set next state");
|
||||
this.currentState$.next(response);
|
||||
},
|
||||
() => {
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { BehaviorSubject, Observable, Subject } from "rxjs";
|
||||
import { NotificationElement } from "../components/notification-bar/notification-bar.component";
|
||||
|
||||
@Injectable()
|
||||
export class NotificationService {
|
||||
notification$ = new Subject<NotificationElement>();
|
||||
|
||||
push(message: string, type: "info" | "danger" | "warn" | "success"): void {
|
||||
console.log(type + ": " + message);
|
||||
|
||||
let timeout = undefined;
|
||||
switch (type) {
|
||||
case "info":
|
||||
timeout = 5;
|
||||
break;
|
||||
case "danger":
|
||||
timeout = 10;
|
||||
break;
|
||||
case "warn":
|
||||
timeout = 7;
|
||||
break;
|
||||
case "success":
|
||||
timeout = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
this.notification$.next({
|
||||
message: message,
|
||||
type: type,
|
||||
timeout: timeout,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,12 @@
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { Router } from "@angular/router";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { NotificationService } from "./notification.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class RequestService {
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
private router: Router,
|
||||
private notificationService: NotificationService,
|
||||
private translate: TranslateService
|
||||
) {}
|
||||
constructor(private http: HttpClient, private router: Router) {}
|
||||
|
||||
public post(
|
||||
apiPath: string,
|
||||
@ -87,13 +80,13 @@ export class RequestService {
|
||||
|
||||
private handleError(answer: any): void {
|
||||
if (answer.status == 401) {
|
||||
this.showSnackBar("Deine Sitzung konnte nicht gefunden werden");
|
||||
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");
|
||||
this.showSnackBar("Du bist nicht für diese Aktion autorisiert", "Ok");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -105,17 +98,17 @@ export class RequestService {
|
||||
}
|
||||
|
||||
if (errorObject.hasOwnProperty("code")) {
|
||||
throw (
|
||||
this.translate.instant("error." + errorObject.code.toString()) ??
|
||||
errorObject.code.toString()
|
||||
);
|
||||
throw errorObject.code.toString();
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.showSnackBar(error.toString());
|
||||
this.showSnackBar(error.toString(), "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
private showSnackBar(message: string) {
|
||||
this.notificationService.push(message, "info");
|
||||
private showSnackBar(message: string, action?: string) {
|
||||
/*this.snackBar.open(message.toString(), action, {
|
||||
duration: 3000,
|
||||
});*/
|
||||
console.log(message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ export class TableComponent {
|
||||
@Input() columns: ColumnDefinition[] = [];
|
||||
|
||||
isBoolean(obje: any): boolean {
|
||||
console.log(obje);
|
||||
return typeof obje === "boolean";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
{
|
||||
"title": "Bienenkeeper",
|
||||
"error": {
|
||||
"Generic.SomethingWentWrong": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es später erneut."
|
||||
},
|
||||
"languages": {
|
||||
"de": "Deutsch",
|
||||
"en": "Englisch"
|
||||
},
|
||||
"menu": {
|
||||
"settings": "Einstellungen",
|
||||
"logout": "Ausloggen",
|
||||
"theme": {
|
||||
"dark": "Dunkel",
|
||||
"light": "Hell"
|
||||
}
|
||||
},
|
||||
"navigation": {
|
||||
"home": "Startseite",
|
||||
"colonies": "Völker"
|
||||
},
|
||||
"auth": {
|
||||
"password": "Password",
|
||||
"email": "E-Mail",
|
||||
"username-or-email": "Benutzername oder E-Mail",
|
||||
"username": "Benutzername",
|
||||
"login": "Anmelden",
|
||||
"registration": "Registrierung",
|
||||
"register": "Registrieren",
|
||||
"reset-password": "Passwort zurücksetzen",
|
||||
"new-password": "Neues Passwort",
|
||||
"password-confirmation": "Passwort wiederholen",
|
||||
"reset-password-confirmation": "Neues Passwort setzen",
|
||||
"already-registered": "Bereits registriert?",
|
||||
"not-yet-registered": "Noch nicht registriert?",
|
||||
"login-now": "Jetzt anmelden!",
|
||||
"register-now": "Jetzt registrieren!",
|
||||
"forgot-password": "Passwort vergessen",
|
||||
"confirm-registration": "Registrierung bestätigen"
|
||||
},
|
||||
"settings": {
|
||||
"tab-security": "Sicherheit",
|
||||
"tab-profile": "Profil",
|
||||
|
||||
"security": {
|
||||
"change-username": "Benutzername ändern",
|
||||
"change-password": "Passwort ändern",
|
||||
"current-password": "Aktuelles Passwort",
|
||||
"new-password": "Neues Passwort",
|
||||
"new-username": "Neuer Benutzername",
|
||||
"password-confirmation": "Passwort wiederholen"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
{
|
||||
"title": "Beekeeper",
|
||||
"error": {
|
||||
"Generic.SomethingWentWrong": "An unexpected error has occurred. Please try again later."
|
||||
},
|
||||
"languages": {
|
||||
"de": "German",
|
||||
"en": "English"
|
||||
},
|
||||
"menu": {
|
||||
"settings": "Settings",
|
||||
"logout": "Logout",
|
||||
"theme": {
|
||||
"dark": "Dark",
|
||||
"light": "Light"
|
||||
}
|
||||
},
|
||||
"navigation": {
|
||||
"home": "Home",
|
||||
"colonies": "Colonies"
|
||||
},
|
||||
"auth": {
|
||||
"password": "Password",
|
||||
"email": "Email",
|
||||
"username-or-email": "Username or Email",
|
||||
"username": "Username",
|
||||
"login": "Login",
|
||||
"registration": "Registration",
|
||||
"register": "Register",
|
||||
"reset-password": "Reset Password",
|
||||
"new-password": "New Password",
|
||||
"password-confirmation": "Confirm Password",
|
||||
"reset-password-confirmation": "Set New Password",
|
||||
"already-registered": "Already registered?",
|
||||
"not-yet-registered": "Not yet registered?",
|
||||
"login-now": "Login now!",
|
||||
"register-now": "Register now!",
|
||||
"forgot-password": "Forgot Password",
|
||||
"confirm-registration": "Confirm Registration"
|
||||
},
|
||||
"settings": {
|
||||
"tab-security": "Security",
|
||||
"tab-profile": "Profile",
|
||||
|
||||
"security": {
|
||||
"change-username": "Change Username",
|
||||
"change-password": "Change Password",
|
||||
"current-password": "Current Password",
|
||||
"new-password": "New Password",
|
||||
"new-username": "New Username",
|
||||
"password-confirmation": "Confirm Password"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M17.4 9C17 7.8 16.2 7 15 6.5V5H14V6.4H13.6C12.5 6.4 11.6 6.8 10.8 7.6L10.4 8L9 7.5C8.7 7.4 8.4 7.3 8 7.3C7.4 7.3 6.8 7.5 6.3 7.9C5.7 8.3 5.4 8.8 5.2 9.3C5 10 5 10.6 5.2 11.3C5.5 12 5.8 12.5 6.3 12.8C5.9 14.3 6.2 15.6 7.3 16.7C8.1 17.5 9 17.9 10.1 17.9C10.6 17.9 10.9 17.9 11.2 17.8C11.8 18.6 12.6 19.1 13.6 19.1C13.9 19.1 14.3 19.1 14.6 19C15.2 18.8 15.6 18.4 16 17.9C16.4 17.3 16.6 16.8 16.6 16.2C16.6 15.8 16.6 15.5 16.5 15.2L16 13.6L16.6 13.2C17.4 12.4 17.8 11.3 17.7 10.1H19V9H17.4M7.7 11.3C7.1 11 6.9 10.6 7.1 10C7.3 9.4 7.7 9.2 8.3 9.4L11.5 10.6C9.9 11.4 8.7 11.6 7.7 11.3M14 16.9C13.4 17.1 13 16.9 12.7 16.3C12.4 15.3 12.6 14.1 13.4 12.5L14.6 15.6C14.8 16.3 14.6 16.7 14 16.9M15.2 11.6L14.6 10V9.9L14.3 9.6H14.2L12.6 9C13 8.7 13.4 8.5 13.9 8.5C14.4 8.5 14.9 8.7 15.3 9.1C15.7 9.5 15.9 9.9 15.9 10.4C15.7 10.7 15.5 11.2 15.2 11.6Z" /></svg>
|
||||
|
Before Width: | Height: | Size: 935 B |
@ -8,8 +8,8 @@
|
||||
--color-text-primary-muted: 100, 100, 100;
|
||||
--color-text-secondary: 255, 255, 255;
|
||||
--color-text-secondary-muted: 170, 170, 170;
|
||||
--color-text-accent: 250, 183, 0;
|
||||
--color-text-accent-muted: 250, 183, 0;
|
||||
--color-text-accent: 255, 199, 44;
|
||||
--color-text-accent-muted: 255, 199, 44;
|
||||
|
||||
--color-primary: 244, 244, 245;
|
||||
--color-secondary: 238, 238, 240;
|
||||
|
||||
@ -12,7 +12,6 @@ module.exports = {
|
||||
content: ["./src/**/*.{html,ts}", "./node_modules/flowbite/**/*.js"],
|
||||
theme: {
|
||||
extend: {
|
||||
// "foregrounds"
|
||||
textColor: {
|
||||
skin: {
|
||||
primary: withOpacity("--color-text-primary"),
|
||||
@ -23,18 +22,6 @@ module.exports = {
|
||||
"accent-muted": withOpacity("--color-text-accent-muted"),
|
||||
},
|
||||
},
|
||||
fill: {
|
||||
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"),
|
||||
},
|
||||
},
|
||||
|
||||
// "backgrounds"
|
||||
backgroundColor: {
|
||||
skin: {
|
||||
primary: withOpacity("--color-primary"),
|
||||
@ -42,8 +29,6 @@ module.exports = {
|
||||
accent: withOpacity("--color-accent"),
|
||||
},
|
||||
},
|
||||
|
||||
// "delicate lines"
|
||||
boxShadowColor: {
|
||||
skin: {
|
||||
primary: withOpacity("--color-text-secondary-muted"),
|
||||
|
||||
Reference in New Issue
Block a user