generated from flo/template-frontend
changes
This commit is contained in:
parent
d8d09d7bac
commit
1f99cfb53c
@ -15,8 +15,12 @@ export class AppComponent implements OnInit {
|
||||
) {
|
||||
var language = navigator.language;
|
||||
|
||||
translate.setDefaultLang(language);
|
||||
translate.use(language);
|
||||
this.translate.setDefaultLang(language);
|
||||
this.translate.use(language);
|
||||
|
||||
this.translate.onLangChange.subscribe(() => {
|
||||
document.title = this.translate.instant("title");
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
@ -8,6 +8,7 @@ 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";
|
||||
import { SharedModule } from "src/app/shared/shared.module";
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: "login", component: LoginComponent },
|
||||
@ -44,6 +45,7 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
SharedModule,
|
||||
],
|
||||
})
|
||||
export class AuthModule {}
|
||||
|
||||
@ -11,39 +11,20 @@
|
||||
|
||||
<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"
|
||||
>{{ "auth.password" | translate }}</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
|
||||
<shared-input
|
||||
key="password"
|
||||
inputType="password"
|
||||
label="auth.password"
|
||||
required="true"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-5">
|
||||
<label
|
||||
for="passwordConfirmation"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "auth.password-confirmation" | translate }}</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
|
||||
<shared-input
|
||||
key="passwordConfirmation"
|
||||
inputType="password"
|
||||
label="auth.password-confirmation"
|
||||
required="true"
|
||||
/>
|
||||
</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"
|
||||
>
|
||||
{{ "auth.confirm-registration" | translate }}
|
||||
</button>
|
||||
<shared-submit label="auth.confirm-registration" (onSubmit)="confirm()" />
|
||||
</form>
|
||||
|
||||
@ -40,5 +40,7 @@ export class ConfirmRegistrationComponent {
|
||||
passwordConfirmation:
|
||||
this.confirmRegistrationForm.value.passwordConfirmation!,
|
||||
});
|
||||
|
||||
this.router.navigateByUrl("/auth/login");
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,26 +11,12 @@
|
||||
|
||||
<form class="max-w-sm mx-auto" [formGroup]="forgotPasswordForm">
|
||||
<div class="mb-5">
|
||||
<label
|
||||
for="mail"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>
|
||||
{{ "auth.email" | translate }}</label
|
||||
>
|
||||
<input
|
||||
formControlName="mail"
|
||||
type="email"
|
||||
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"
|
||||
required
|
||||
<shared-input
|
||||
key="mail"
|
||||
inputType="email"
|
||||
label="auth.email"
|
||||
required="true"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
(click)="confirm()"
|
||||
[disabled]="!forgotPasswordForm.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"
|
||||
>
|
||||
{{ "auth.reset-password" | translate }}
|
||||
</button>
|
||||
<shared-submit label="auth.reset-password" (onSubmit)="confirm()" />
|
||||
</form>
|
||||
|
||||
@ -11,23 +11,13 @@
|
||||
|
||||
<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"
|
||||
>{{ "auth.username-or-email" | translate }}</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
|
||||
<shared-input
|
||||
key="identifier"
|
||||
inputType="text"
|
||||
label="auth.username-or-email"
|
||||
required="true"
|
||||
/>
|
||||
<p
|
||||
id="helper-text-explanation"
|
||||
class="mt-2 text-sm text-skin-primary-muted"
|
||||
>
|
||||
<p class="mt-2 text-sm text-skin-primary-muted">
|
||||
{{ "auth.not-yet-registered" | translate }}
|
||||
<a
|
||||
routerLink="/auth/registration"
|
||||
@ -37,22 +27,13 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="mb-5">
|
||||
<label
|
||||
for="password"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "auth.password" | translate }}</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
|
||||
<shared-input
|
||||
key="password"
|
||||
inputType="password"
|
||||
label="auth.password"
|
||||
required="true"
|
||||
/>
|
||||
<p
|
||||
id="helper-text-explanation"
|
||||
class="mt-2 text-sm text-skin-primary-muted"
|
||||
>
|
||||
<p class="mt-2 text-sm text-skin-primary-muted">
|
||||
<a
|
||||
routerLink="/auth/forgot-password"
|
||||
class="font-medium text-skin-accent hover:underline hover:font-bold"
|
||||
@ -60,12 +41,6 @@
|
||||
>
|
||||
</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"
|
||||
>
|
||||
{{ "auth.login" | translate }}
|
||||
</button>
|
||||
|
||||
<shared-submit label="auth.login" (onSubmit)="login()" />
|
||||
</form>
|
||||
|
||||
@ -11,34 +11,12 @@
|
||||
|
||||
<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"
|
||||
>
|
||||
{{ "auth.email" | translate }}</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"
|
||||
<shared-input
|
||||
key="mail"
|
||||
inputType="email"
|
||||
label="auth.email"
|
||||
required="true"
|
||||
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"
|
||||
>
|
||||
{{ "auth.reset-password" | translate }}</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"
|
||||
@ -52,12 +30,13 @@
|
||||
>
|
||||
</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"
|
||||
>
|
||||
{{ "auth.register" | translate }}
|
||||
</button>
|
||||
<div class="mb-5">
|
||||
<shared-input
|
||||
key="username"
|
||||
inputType="string"
|
||||
label="auth.username"
|
||||
required="true"
|
||||
/>
|
||||
</div>
|
||||
<shared-submit label="auth.register" (onSubmit)="register()" />
|
||||
</form>
|
||||
|
||||
@ -11,39 +11,20 @@
|
||||
|
||||
<form class="max-w-sm mx-auto" [formGroup]="resetPasswordForm">
|
||||
<div class="mb-5">
|
||||
<label
|
||||
for="newPassword"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "auth.new-password" | translate }}</label
|
||||
>
|
||||
<input
|
||||
formControlName="newPassword"
|
||||
type="password"
|
||||
id="newPassword"
|
||||
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
|
||||
<shared-input
|
||||
key="newPassword"
|
||||
inputType="password"
|
||||
label="auth.new-password"
|
||||
required="true"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-5">
|
||||
<label
|
||||
for="passwordConfirmation"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "auth.password-confirmation" | translate }}</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
|
||||
<shared-input
|
||||
key="passwordConfirmation"
|
||||
inputType="password"
|
||||
label="auth.password-confirmation"
|
||||
required="true"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
(click)="confirm()"
|
||||
[disabled]="!resetPasswordForm.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"
|
||||
>
|
||||
{{ "auth.new-password" | translate }}
|
||||
</button>
|
||||
<shared-submit label="auth.reset-password" (onSubmit)="confirm()" />
|
||||
</form>
|
||||
|
||||
@ -21,18 +21,27 @@
|
||||
</button>
|
||||
|
||||
<!-- Title -->
|
||||
<a routerLink="/" class="flex items-center space-x-3">
|
||||
<img src="assets/icon.png" class="h-10 w-10" alt="Beekeeper Logo" />
|
||||
<span
|
||||
class="text-skin-primary self-center text-4xl font-semibold whitespace-nowrap"
|
||||
>{{ "title" | translate }}</span
|
||||
<a routerLink="/" class="text-skin-primary flex items-center space-x-3"
|
||||
><svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="4 4 16 16"
|
||||
class="w-12 h-12"
|
||||
>
|
||||
<title>{{ "title" | translate }}</title>
|
||||
<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>
|
||||
<span class="self-center text-4xl font-semibold whitespace-nowrap">{{
|
||||
"title" | translate
|
||||
}}</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"
|
||||
class="w-12 h-12 text-sm bg-skin-primary rounded-full focus:ring-4 focus:ring-skin-accent"
|
||||
id="user-menu-button"
|
||||
aria-expanded="false"
|
||||
data-dropdown-toggle="user-dropdown"
|
||||
@ -57,13 +66,26 @@
|
||||
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
|
||||
routerLinkActive="underline"
|
||||
>
|
||||
<div class="flex flex-row gap-4">
|
||||
<svg
|
||||
*ngIf="navigationLink.path !== undefined"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
class="w-8 h-8 basis-auto"
|
||||
>
|
||||
<title>{{ navigationLink.label | translate }}</title>
|
||||
<path fill="currentColor" [attr.d]="navigationLink.path" />
|
||||
</svg>
|
||||
<div class="basis-full">
|
||||
{{ navigationLink.label | translate }}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- User dropdown -->
|
||||
<div id="user-dropdown" class="hidden min-w-full md:min-w-64 px-4 z-50">
|
||||
<div
|
||||
@ -81,7 +103,7 @@
|
||||
<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"
|
||||
class="block py-2 px-3 rounded text-skin-primary hover:text-skin-secondary hover:bg-skin-accent w-full text-right"
|
||||
[routerLink]="
|
||||
usermenuButton.routerLink === undefined
|
||||
? null
|
||||
|
||||
@ -9,7 +9,8 @@ import { NotificationService } from "../../services/notification.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface NavigationLink {
|
||||
label: Function | string;
|
||||
path: string | undefined;
|
||||
label: string;
|
||||
routerLink: string;
|
||||
}
|
||||
|
||||
@ -26,10 +27,20 @@ interface UserMenuButton {
|
||||
})
|
||||
export class NavigationComponent implements OnInit {
|
||||
navigationLinks: NavigationLink[] = [
|
||||
{ routerLink: "/", label: () => "navigation.home" },
|
||||
{
|
||||
routerLink: "/",
|
||||
path: "M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z",
|
||||
label: "navigation.home",
|
||||
},
|
||||
{
|
||||
routerLink: "/settings",
|
||||
path: "M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z",
|
||||
label: "menu.settings",
|
||||
},
|
||||
{
|
||||
routerLink: "/colonies",
|
||||
label: () => "navigation.colonies",
|
||||
path: "M23 14.5C23 12.94 21.97 11.63 20.55 11.18C20.83 10.68 21 10.11 21 9.5C21 7.94 19.97 6.63 18.55 6.18C18.83 5.68 19 5.11 19 4.5C19 2.57 17.43 1 15.5 1H8.5C6.57 1 5 2.57 5 4.5C5 5.11 5.17 5.68 5.45 6.18C4.04 6.63 3 7.94 3 9.5C3 10.11 3.17 10.68 3.45 11.18C2.04 11.63 1 12.94 1 14.5C1 15.76 1.67 16.84 2.67 17.46C2.25 18.03 2 18.74 2 19.5C2 21.43 3.57 23 5.5 23H18.5C20.43 23 22 21.43 22 19.5C22 18.74 21.75 18.03 21.33 17.46C22.33 16.84 23 15.76 23 14.5M8.5 3H15.5C16.33 3 17 3.67 17 4.5S16.33 6 15.5 6H8.5C7.67 6 7 5.33 7 4.5S7.67 3 8.5 3M6.5 8H17.5C18.33 8 19 8.67 19 9.5S18.33 11 17.5 11H6.5C5.67 11 5 10.33 5 9.5S5.67 8 6.5 8M4 19.5C4 18.67 4.67 18 5.5 18H9V21H5.5C4.67 21 4 20.33 4 19.5M18.5 21H15V18H18.5C19.33 18 20 18.67 20 19.5S19.33 21 18.5 21M19.5 16H14.82C14.4 14.84 13.3 14 12 14S9.6 14.84 9.18 16H4.5C3.67 16 3 15.33 3 14.5S3.67 13 4.5 13H19.5C20.33 13 21 13.67 21 14.5S20.33 16 19.5 16Z",
|
||||
label: "navigation.colonies",
|
||||
},
|
||||
];
|
||||
|
||||
@ -143,11 +154,4 @@ export class NavigationComponent implements OnInit {
|
||||
return button.label;
|
||||
}
|
||||
}
|
||||
getNavigationLinkLabel(link: NavigationLink) {
|
||||
if (typeof link.label === "function") {
|
||||
return link.label();
|
||||
} else {
|
||||
return link.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
</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"
|
||||
class="ms-auto -mx-1.5 -my-1.5 bg-skin-secondary text-skin-accent rounded-lg focus:ring-2 focus:ring-skin-accent 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>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<div class="rounded-lg shadow-sm shadow-skin-primary bg-skin-secondary p-5">
|
||||
<div class="inline-block text-skin-secondary bg-skin-accent rounded-lg p-2">
|
||||
<div class="inline-block text-skin-primary bg-skin-accent rounded-lg p-2">
|
||||
<div class="font-bold">
|
||||
{{ state.username }}
|
||||
</div>
|
||||
@ -10,57 +10,49 @@
|
||||
|
||||
<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"
|
||||
role="tablist"
|
||||
class="flex flex-nowrap -mb-px text-sm font-medium text-center"
|
||||
data-tabs-toggle="#tab-outlet"
|
||||
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">
|
||||
<li class="me-2 w-full xl:w-auto" 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"
|
||||
class="block p-4 w-full xl:w-auto border-b-2 rounded-t-lg"
|
||||
data-tabs-target="#profile"
|
||||
>
|
||||
{{ "settings.tab-profile" | translate }}
|
||||
</button>
|
||||
</li>
|
||||
<li class="me-2" role="presentation">
|
||||
<li class="me-2 last:me-0 w-full xl:w-auto" role="presentation">
|
||||
<button
|
||||
class="inline-block p-4 border-b-2 rounded-t-lg"
|
||||
id="security-styled-tab"
|
||||
data-tabs-target="#styled-security"
|
||||
type="button"
|
||||
class="block p-4 w-full xl:w-auto border-b-2 rounded-t-lg"
|
||||
data-tabs-target="#security"
|
||||
role="tab"
|
||||
aria-controls="security"
|
||||
aria-selected="false"
|
||||
>
|
||||
{{ "settings.tab-security" | translate }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="default-styled-tab-content" class="text-skin-primary">
|
||||
<div
|
||||
class="hidden p-4 rounded-lg"
|
||||
id="styled-profile"
|
||||
role="tabpanel"
|
||||
aria-labelledby="profile-tab"
|
||||
>
|
||||
<div id="tab-outlet" class="text-skin-primary">
|
||||
<div role="tabpanel" class="hidden py-4 xl:p-4 rounded-lg" id="profile">
|
||||
<app-tab-profile />
|
||||
</div>
|
||||
<div
|
||||
class="hidden p-4 rounded-lg"
|
||||
id="styled-security"
|
||||
role="tabpanel"
|
||||
aria-labelledby="security-tab"
|
||||
>
|
||||
<div role="tabpanel" class="hidden py-4 xl:p-4 rounded-lg" id="security">
|
||||
<app-tab-security />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<shared-tab-control [tabs]="tabs">
|
||||
<div role="tabpanel" class="hidden py-4 xl:p-4 rounded-lg" id="profile">
|
||||
<app-tab-profile />
|
||||
</div>
|
||||
<div role="tabpanel" class="hidden py-4 xl:p-4 rounded-lg" id="security">
|
||||
<app-tab-security />
|
||||
</div>
|
||||
</shared-tab-control>
|
||||
-->
|
||||
</div>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { initFlowbite } from "flowbite";
|
||||
import { AuthService } from "../../services/auth.service";
|
||||
import { filter } from "rxjs";
|
||||
import { UserStateResponse } from "../../models/user-state-request.model";
|
||||
import { TabItem } from "src/app/shared/models/tab-item.model";
|
||||
|
||||
@Component({
|
||||
selector: "app-settings",
|
||||
@ -11,6 +11,16 @@ import { UserStateResponse } from "../../models/user-state-request.model";
|
||||
})
|
||||
export class SettingsComponent implements OnInit {
|
||||
state: UserStateResponse;
|
||||
tabs: TabItem[] = [
|
||||
{
|
||||
label: "settings.tab-profile",
|
||||
target: "profile",
|
||||
},
|
||||
{
|
||||
label: "settings.tab-security",
|
||||
target: "security",
|
||||
},
|
||||
];
|
||||
|
||||
constructor(private authService: AuthService) {
|
||||
this.state = this.authService.currentState$.value!;
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
<shared-table [items]="items" [columns]="columns" [rowActions]="rowActions">
|
||||
</shared-table>
|
||||
@ -1,9 +1,15 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { NotificationService } from "src/app/core/services/notification.service";
|
||||
import {
|
||||
ColumnDefinition,
|
||||
RowAction,
|
||||
} from "src/app/shared/components/table/table.component";
|
||||
|
||||
interface User {
|
||||
username: string;
|
||||
mail: string;
|
||||
age: number;
|
||||
interface Product {
|
||||
description: string;
|
||||
id: string;
|
||||
price: number;
|
||||
stock: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
@ -11,4 +17,75 @@ interface User {
|
||||
templateUrl: "./tab-profile.component.html",
|
||||
styleUrls: ["./tab-profile.component.scss"],
|
||||
})
|
||||
export class TabProfileComponent {}
|
||||
export class TabProfileComponent {
|
||||
constructor(private notificationService: NotificationService) {}
|
||||
|
||||
columns: ColumnDefinition[] = [
|
||||
{
|
||||
label: "test.product",
|
||||
content: (item: Product) => item.description,
|
||||
routerLink: (item: Product) => ["/", "product", item.id],
|
||||
},
|
||||
{
|
||||
label: "test.price",
|
||||
content: (item: Product) => item.price,
|
||||
routerLink: undefined,
|
||||
},
|
||||
{
|
||||
label: "test.delete",
|
||||
content: "Löschen",
|
||||
routerLink: undefined,
|
||||
},
|
||||
{
|
||||
label: "test.stock",
|
||||
content: (item: Product) => item.stock,
|
||||
routerLink: undefined,
|
||||
},
|
||||
];
|
||||
|
||||
rowActions: RowAction[] = [
|
||||
{
|
||||
label: "test.edit",
|
||||
path: "M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z",
|
||||
action: (item: Product) => {
|
||||
this.edit(item);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "test.delete",
|
||||
path: "M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z",
|
||||
action: (item: Product) => {
|
||||
this.delete(item);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
items: Product[] = [
|
||||
{
|
||||
id: "1",
|
||||
description: "Flüssiger Honig",
|
||||
price: 6.5,
|
||||
stock: 40,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
description: "Cremiger Honig",
|
||||
price: 5,
|
||||
stock: 32,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
description: "Labello",
|
||||
price: 2.3,
|
||||
stock: 7,
|
||||
},
|
||||
];
|
||||
|
||||
delete(item: Product) {
|
||||
this.notificationService.push(item.description + " gelöscht", "info");
|
||||
}
|
||||
|
||||
edit(item: Product) {
|
||||
this.notificationService.push(item.description + " bearbeitet", "info");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,104 +1,66 @@
|
||||
<div class="grid grid-cols-1 md:grid-cols-2">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-10">
|
||||
<div>
|
||||
<h2>{{ "settings.security.change-password" | translate }}</h2>
|
||||
<form class="mx-auto p-5" [formGroup]="changePasswordForm">
|
||||
<form class="mx-auto py-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
|
||||
>
|
||||
<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
|
||||
<shared-input
|
||||
key="password"
|
||||
inputType="password"
|
||||
label="settings.security.current-password"
|
||||
required="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mb-5">
|
||||
<label
|
||||
for="newPassword"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "settings.security.new-password" | translate }}</label
|
||||
>
|
||||
<input
|
||||
formControlName="newPassword"
|
||||
type="password"
|
||||
id="newPassword"
|
||||
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
|
||||
<shared-input
|
||||
key="newPassword"
|
||||
inputType="password"
|
||||
label="settings.security.new-password"
|
||||
required="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mb-5">
|
||||
<label
|
||||
for="newPasswordConfirmation"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "settings.security.password-confirmation" | translate }}</label
|
||||
>
|
||||
<input
|
||||
formControlName="newPasswordConfirmation"
|
||||
type="password"
|
||||
id="newPasswordConfirmation"
|
||||
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
|
||||
<shared-input
|
||||
key="newPasswordConfirmation"
|
||||
inputType="password"
|
||||
label="settings.security.password-confirmation"
|
||||
required="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
(click)="changePassword()"
|
||||
[disabled]="!changePasswordForm.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"
|
||||
>
|
||||
{{ "settings.security.change-password" | translate }}
|
||||
</button>
|
||||
<shared-submit
|
||||
label="settings.security.change-password"
|
||||
(onSubmit)="changePassword()"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>{{ "settings.security.change-username" | translate }}</h2>
|
||||
<form class="mx-auto p-5" [formGroup]="changeUsernameForm">
|
||||
<form class="mx-auto py-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
|
||||
>
|
||||
<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
|
||||
<shared-input
|
||||
key="password"
|
||||
inputType="password"
|
||||
label="settings.security.current-password"
|
||||
required="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mb-5">
|
||||
<label
|
||||
for="newUsername"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ "settings.security.new-username" | translate }}</label
|
||||
>
|
||||
<input
|
||||
formControlName="newUsername"
|
||||
type="string"
|
||||
id="newUsername"
|
||||
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
|
||||
<shared-input
|
||||
key="newUsername"
|
||||
inputType="string"
|
||||
label="settings.security.new-username"
|
||||
required="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
(click)="changeUsername()"
|
||||
[disabled]="!changeUsernameForm.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"
|
||||
>
|
||||
{{ "settings.security.change-username" | translate }}
|
||||
</button>
|
||||
<shared-submit
|
||||
label="settings.security.change-username"
|
||||
(onSubmit)="changeUsername()"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -22,6 +22,14 @@ export class TabSecurityComponent {
|
||||
constructor(private authService: AuthService) {}
|
||||
|
||||
changePassword(): void {
|
||||
console.log({
|
||||
password: this.changePasswordForm.value.password!,
|
||||
newPassword: this.changePasswordForm.value.newPassword!,
|
||||
newPasswordConfirmation:
|
||||
this.changePasswordForm.value.newPasswordConfirmation!,
|
||||
});
|
||||
return;
|
||||
|
||||
this.authService.changePassword({
|
||||
password: this.changePasswordForm.value.password!,
|
||||
newPassword: this.changePasswordForm.value.newPassword!,
|
||||
|
||||
27
src/app/shared/components/input/input.component.html
Normal file
27
src/app/shared/components/input/input.component.html
Normal file
@ -0,0 +1,27 @@
|
||||
<div>
|
||||
<label
|
||||
*ngIf="label !== undefined"
|
||||
[for]="key"
|
||||
class="block mb-2 text-sm font-medium text-skin-primary-muted"
|
||||
>{{ label | translate }}</label
|
||||
>
|
||||
|
||||
<input
|
||||
*ngIf="required"
|
||||
[id]="key"
|
||||
[type]="inputType"
|
||||
[formControlName]="key"
|
||||
[placeholder]="placeholder"
|
||||
class="bg-skin-primary border border-skin-primary text-skin-primary text-sm rounded-lg focus:ring-skin-accent focus:border-skin-accent block w-full p-2.5"
|
||||
required
|
||||
/>
|
||||
|
||||
<input
|
||||
*ngIf="!required"
|
||||
[id]="key"
|
||||
[type]="inputType"
|
||||
[formControlName]="key"
|
||||
[placeholder]="placeholder"
|
||||
class="bg-skin-primary border border-skin-primary text-skin-primary text-sm rounded-lg focus:ring-skin-accent focus:border-skin-accent block w-full p-2.5"
|
||||
/>
|
||||
</div>
|
||||
21
src/app/shared/components/input/input.component.ts
Normal file
21
src/app/shared/components/input/input.component.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Component, inject, Input } from "@angular/core";
|
||||
import { ControlContainer, FormGroup } from "@angular/forms";
|
||||
|
||||
@Component({
|
||||
selector: "shared-input",
|
||||
templateUrl: "./input.component.html",
|
||||
styleUrl: "./input.component.scss",
|
||||
viewProviders: [
|
||||
{
|
||||
provide: ControlContainer,
|
||||
useFactory: () => inject(ControlContainer, { skipSelf: true }),
|
||||
},
|
||||
],
|
||||
})
|
||||
export class InputComponent {
|
||||
@Input() label: string | undefined = undefined;
|
||||
@Input() placeholder: string = "";
|
||||
@Input() required: boolean = false;
|
||||
@Input({ required: true }) inputType!: string;
|
||||
@Input({ required: true }) key!: string;
|
||||
}
|
||||
8
src/app/shared/components/submit/submit.component.html
Normal file
8
src/app/shared/components/submit/submit.component.html
Normal file
@ -0,0 +1,8 @@
|
||||
<button
|
||||
(click)="submit()"
|
||||
[disabled]="!getParentFormGroup().valid"
|
||||
type="submit"
|
||||
class="w-full cursor-pointer 9xl:w-auto font-bold text-skin-primary bg-skin-accent hover:bg-skin-accent-muted focus:ring-2 focus:ring-skin-accent rounded-lg text-sm px-5 py-2.5 text-center"
|
||||
>
|
||||
{{ label | translate }}
|
||||
</button>
|
||||
34
src/app/shared/components/submit/submit.component.ts
Normal file
34
src/app/shared/components/submit/submit.component.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { Component, EventEmitter, inject, Input, Output } from "@angular/core";
|
||||
import { ControlContainer, FormGroup } from "@angular/forms";
|
||||
|
||||
@Component({
|
||||
selector: "shared-submit",
|
||||
templateUrl: "./submit.component.html",
|
||||
styleUrl: "./submit.component.scss",
|
||||
viewProviders: [
|
||||
{
|
||||
provide: ControlContainer,
|
||||
useFactory: () => inject(ControlContainer, { skipSelf: true }),
|
||||
},
|
||||
],
|
||||
})
|
||||
export class SubmitComponent {
|
||||
@Output() onSubmit = new EventEmitter();
|
||||
@Input({ required: true }) label!: string;
|
||||
|
||||
constructor(private controlContainer: ControlContainer) {}
|
||||
|
||||
getParentFormGroup(): FormGroup {
|
||||
return this.controlContainer.control as FormGroup;
|
||||
}
|
||||
|
||||
submit(): void {
|
||||
var formGroup = this.getParentFormGroup();
|
||||
if (!formGroup.valid) {
|
||||
console.log("formGroup not Valid");
|
||||
return;
|
||||
}
|
||||
|
||||
this.onSubmit.emit();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
<div class="">
|
||||
<div class="mb-4 border-b border-skin-primary">
|
||||
<ul
|
||||
role="tablist"
|
||||
class="flex flex-nowrap -mb-px text-sm font-medium text-center"
|
||||
data-tabs-toggle="#tab-outlet"
|
||||
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"
|
||||
>
|
||||
<li
|
||||
*ngFor="let tab of tabs"
|
||||
class="me-2 w-full xl:w-auto"
|
||||
role="presentation"
|
||||
>
|
||||
<button
|
||||
role="tab"
|
||||
class="block p-4 w-full xl:w-auto border-b-2 rounded-t-lg"
|
||||
[data-tabs-target]="tab.target"
|
||||
>
|
||||
{{ tab.label | translate }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="tab-outlet" class="text-skin-primary">
|
||||
<ng-content />
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,16 @@
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
import { initFlowbite } from "flowbite";
|
||||
import { TabItem } from "../../models/tab-item.model";
|
||||
|
||||
@Component({
|
||||
selector: "shared-tab-control",
|
||||
templateUrl: "./tab-control.component.html",
|
||||
styleUrl: "./tab-control.component.scss",
|
||||
})
|
||||
export class TabControlComponent implements OnInit {
|
||||
@Input({ required: true }) tabs!: TabItem[];
|
||||
|
||||
ngOnInit(): void {
|
||||
initFlowbite();
|
||||
}
|
||||
}
|
||||
@ -1,55 +1,57 @@
|
||||
<table class="w-full text-skin-primary">
|
||||
|
||||
<thead class="uppercase bg-skin-accent border-b border-skin-primary text-left">
|
||||
<tr>
|
||||
<th
|
||||
*ngFor="let column of columns"
|
||||
class="px-5 py-2"
|
||||
<table class="w-full table-fixed text-skin-primary">
|
||||
<thead
|
||||
class="uppercase bg-skin-accent border-b border-skin-primary text-left"
|
||||
>
|
||||
{{column.header}}
|
||||
<tr>
|
||||
<th *ngFor="let column of columns" class="px-5 py-2">
|
||||
{{ column.label | translate }}
|
||||
</th>
|
||||
<th *ngIf="rowActions.length > 0" class="px-5 py-2"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr *ngFor="let item of items" class="border-b border-skin-primary">
|
||||
|
||||
<td
|
||||
*ngFor="let column of columns; index as currentIndex"
|
||||
class="px-5 py-2"
|
||||
class="px-5 py-2 text-skin-primary"
|
||||
[ngClass]="{
|
||||
'bg-skin-primary': currentIndex % 2 === 0,
|
||||
'bg-skin-secondary': currentIndex % 2 === 1,
|
||||
}"
|
||||
>
|
||||
<div *ngIf="column.routerLink !== undefined">
|
||||
<a [routerLink]="column.routerLink(item)" class="font-bold hover:text-skin-accent hover:underline">
|
||||
<div *ngIf="column.columnContent !== undefined">
|
||||
{{ column.columnContent }}
|
||||
<a [routerLink]="getRouterLink(column, item)">
|
||||
<div class="text-skin-accent hover:underline">
|
||||
{{ getContent(column, item) }}
|
||||
</div>
|
||||
<div
|
||||
*ngIf="column.columnFunction !== undefined"
|
||||
[innerHtml]="column.columnFunction(item)"
|
||||
></div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div *ngIf="column.routerLink === undefined">
|
||||
<div *ngIf="column.columnContent !== undefined">
|
||||
<div *ngIf="isBoolean(column.columnContent)">
|
||||
<input type="checkbox" [(ngModel)]="column.columnContent" />
|
||||
</div>
|
||||
<div *ngIf="!isBoolean(column.columnContent)">
|
||||
{{ column.columnContent }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="column.columnFunction !== undefined"
|
||||
[innerHtml]="column.columnFunction(item)"
|
||||
></div>
|
||||
{{ getContent(column, item) }}
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td
|
||||
*ngIf="rowActions.length > 0"
|
||||
class="text-right w-auto h-full"
|
||||
[ngClass]="{
|
||||
'bg-skin-primary': columns.length % 2 === 0,
|
||||
'bg-skin-secondary': columns.length % 2 === 1,
|
||||
}"
|
||||
>
|
||||
<button
|
||||
class="p-2 font-bold text-skin-primary-muted hover:text-skin-primary"
|
||||
*ngFor="let rowAction of rowActions"
|
||||
(click)="rowAction.action(item)"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6">
|
||||
<title>{{ rowAction.label | translate }}</title>
|
||||
<path fill="currentColor" [attr.d]="rowAction.path" />
|
||||
</svg>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
import { Component, Input } from "@angular/core";
|
||||
|
||||
export interface ColumnDefinition {
|
||||
header: string;
|
||||
columnContent?: string | undefined;
|
||||
columnFunction?: Function | undefined;
|
||||
routerLink?: Function | undefined;
|
||||
label: string;
|
||||
content: Function | string | boolean | number;
|
||||
routerLink: Function | string | undefined;
|
||||
}
|
||||
|
||||
export interface RowAction {
|
||||
label: string;
|
||||
action: Function;
|
||||
path: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
@ -15,8 +20,29 @@ export interface ColumnDefinition {
|
||||
export class TableComponent {
|
||||
@Input() items: any[] = [];
|
||||
@Input() columns: ColumnDefinition[] = [];
|
||||
@Input() rowActions: RowAction[] = [];
|
||||
|
||||
isBoolean(obje: any): boolean {
|
||||
return typeof obje === "boolean";
|
||||
}
|
||||
|
||||
getRouterLink(column: ColumnDefinition, item: any) {
|
||||
if (column.routerLink === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (typeof column.routerLink === "string") {
|
||||
return column.routerLink;
|
||||
}
|
||||
|
||||
return column.routerLink(item);
|
||||
}
|
||||
|
||||
getContent(column: ColumnDefinition, item: any) {
|
||||
if (typeof column.content === "function") {
|
||||
return column.content(item);
|
||||
}
|
||||
|
||||
return column.content;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export interface TabItem {
|
||||
id: string;
|
||||
title: string;
|
||||
label: string;
|
||||
target: string;
|
||||
}
|
||||
|
||||
@ -4,11 +4,35 @@ 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 { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { InputComponent } from "./components/input/input.component";
|
||||
import { TranslateModule } from "@ngx-translate/core";
|
||||
import { SubmitComponent } from "./components/submit/submit.component";
|
||||
import { TabControlComponent } from "./components/tab-control/tab-control.component";
|
||||
|
||||
@NgModule({
|
||||
declarations: [CardComponent, PaginatorComponent, TableComponent],
|
||||
exports: [CardComponent, PaginatorComponent, TableComponent, FormsModule],
|
||||
imports: [RouterModule, CommonModule, FormsModule],
|
||||
declarations: [
|
||||
CardComponent,
|
||||
PaginatorComponent,
|
||||
TableComponent,
|
||||
TabControlComponent,
|
||||
InputComponent,
|
||||
SubmitComponent,
|
||||
],
|
||||
exports: [
|
||||
CardComponent,
|
||||
PaginatorComponent,
|
||||
TableComponent,
|
||||
TabControlComponent,
|
||||
InputComponent,
|
||||
SubmitComponent,
|
||||
],
|
||||
imports: [
|
||||
RouterModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
],
|
||||
})
|
||||
export class SharedModule {}
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
"login-now": "Jetzt anmelden!",
|
||||
"register-now": "Jetzt registrieren!",
|
||||
"forgot-password": "Passwort vergessen",
|
||||
"confirm-registration": "Registrierung bestätigen"
|
||||
"confirm-registration": "Registrierung abschließen"
|
||||
},
|
||||
"settings": {
|
||||
"tab-security": "Sicherheit",
|
||||
@ -50,5 +50,13 @@
|
||||
"new-username": "Neuer Benutzername",
|
||||
"password-confirmation": "Passwort wiederholen"
|
||||
}
|
||||
},
|
||||
|
||||
"test": {
|
||||
"product": "Produkt",
|
||||
"price": "Preis",
|
||||
"stock": "Lagerbestand",
|
||||
"edit": "Bearbeiten",
|
||||
"delete": "Löschen"
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,5 +50,13 @@
|
||||
"new-username": "New Username",
|
||||
"password-confirmation": "Confirm Password"
|
||||
}
|
||||
},
|
||||
|
||||
"test": {
|
||||
"product": "Product",
|
||||
"price": "Price",
|
||||
"stock": "Stock",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,28 +3,41 @@
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
/* Light Theme */
|
||||
:root {
|
||||
--color-text-primary: 0, 0, 0;
|
||||
--color-text-primary-muted: 100, 100, 100;
|
||||
--color-text-primary-muted: 50, 50, 50;
|
||||
--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-secondary-muted: 200, 200, 200;
|
||||
|
||||
--color-primary: 244, 244, 245;
|
||||
--color-secondary: 238, 238, 240;
|
||||
--color-accent: 255, 199, 44;
|
||||
--color-text-accent: 255, 180, 0;
|
||||
--color-text-accent-muted: 240, 170, 0;
|
||||
|
||||
--color-background-primary: 255, 255, 255;
|
||||
--color-background-primary-muted: 240, 240, 240;
|
||||
--color-background-secondary: 245, 245, 245;
|
||||
--color-background-secondary-muted: 230, 230, 230;
|
||||
|
||||
--color-background-accent: 255, 199, 44;
|
||||
--color-background-accent-muted: 240, 184, 34;
|
||||
}
|
||||
|
||||
/* Dark Theme */
|
||||
.theme-dark {
|
||||
--color-text-primary: 255, 255, 255;
|
||||
--color-text-primary-muted: 170, 170, 170;
|
||||
--color-text-secondary: 0, 0, 0;
|
||||
--color-text-secondary-muted: 100, 100, 100;
|
||||
--color-text-accent: 250, 183, 0;
|
||||
--color-text-accent-muted: 250, 183, 0;
|
||||
|
||||
--color-primary: 24, 24, 27;
|
||||
--color-secondary: 39, 39, 42;
|
||||
--color-accent: 250, 183, 0;
|
||||
--color-text-accent: 255, 180, 50;
|
||||
--color-text-accent-muted: 230, 160, 40;
|
||||
|
||||
--color-background-primary: 24, 24, 27;
|
||||
--color-background-primary-muted: 34, 34, 37;
|
||||
--color-background-secondary: 39, 39, 42;
|
||||
--color-background-secondary-muted: 49, 49, 52;
|
||||
|
||||
--color-background-accent: 250, 183, 0;
|
||||
--color-background-accent-muted: 225, 158, 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,9 +37,12 @@ module.exports = {
|
||||
// "backgrounds"
|
||||
backgroundColor: {
|
||||
skin: {
|
||||
primary: withOpacity("--color-primary"),
|
||||
secondary: withOpacity("--color-secondary"),
|
||||
accent: withOpacity("--color-accent"),
|
||||
primary: withOpacity("--color-background-primary"),
|
||||
"primary-muted": withOpacity("--color-background-primary-muted"),
|
||||
secondary: withOpacity("--color-background-secondary"),
|
||||
"secondary-muted": withOpacity("--color-background-secondary-muted"),
|
||||
accent: withOpacity("--color-background-accent"),
|
||||
"accent-muted": withOpacity("--color-background-accent-muted"),
|
||||
},
|
||||
},
|
||||
|
||||
@ -52,6 +55,7 @@ module.exports = {
|
||||
ringColor: {
|
||||
skin: {
|
||||
primary: withOpacity("--color-text-secondary-muted"),
|
||||
accent: withOpacity("--color-text-accent-muted"),
|
||||
},
|
||||
},
|
||||
divideColor: {
|
||||
|
||||
Reference in New Issue
Block a user