dev env setup
This commit is contained in:
@@ -39,6 +39,7 @@
|
||||
"zone.js": "~0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^21.0.2",
|
||||
"@angular/build": "^20.3.8",
|
||||
"@angular/cli": "^20.3.8",
|
||||
"@angular/compiler-cli": "^20.3.0",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
ApplicationConfig,
|
||||
isDevMode,
|
||||
provideBrowserGlobalErrorListeners,
|
||||
provideZoneChangeDetection,
|
||||
} from '@angular/core';
|
||||
@@ -29,7 +30,7 @@ export const appConfig: ApplicationConfig = {
|
||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||
provideKeycloak({
|
||||
config: {
|
||||
url: 'https://keycloak.toni714.de:8443/',
|
||||
url: isDevMode() ? 'http://localhost:8080/' : 'https://keycloak.toni714.de:8443/',
|
||||
realm: 'taekwondo',
|
||||
clientId: 'angular-frontend',
|
||||
},
|
||||
@@ -44,7 +45,7 @@ export const appConfig: ApplicationConfig = {
|
||||
provide: INCLUDE_BEARER_TOKEN_INTERCEPTOR_CONFIG,
|
||||
useValue: [
|
||||
createInterceptorCondition<IncludeBearerTokenCondition>({
|
||||
urlPattern: /^https:\/\/tkd-api\.toni714\.de.*$/,
|
||||
urlPattern: isDevMode()? /^http:\/\/localhost:3000.*$/ : /^https:\/\/tkd-api\.toni714\.de.*$/,
|
||||
}),
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@if(this.loggedIn()){
|
||||
@if(this.auth.loggedIn()){
|
||||
<div class="no-print">
|
||||
<button mat-flat-button color="accent" (click)="onLogOut()">LogOut</button>
|
||||
<a mat-stroked-button color="primary" [routerLink]="['/home']">Home</a>
|
||||
<button mat-flat-button color="accent" (click)="this.auth.logout()">LogOut</button>
|
||||
<button mat-stroked-button color="primary" [routerLink]="['/home']">Home</button>
|
||||
</div>
|
||||
}
|
||||
<router-outlet></router-outlet>
|
||||
|
||||
@@ -16,7 +16,7 @@ export const roles = {
|
||||
MemberAdmin: 'memberadmin',
|
||||
};
|
||||
|
||||
function requireRoles(roles: string[], any: boolean = false): CanActivateFn {
|
||||
function requireRoles(roles: string[]=[], any: boolean = false): CanActivateFn {
|
||||
const isAllowed = async (
|
||||
_: ActivatedRouteSnapshot,
|
||||
__: RouterStateSnapshot,
|
||||
@@ -44,7 +44,12 @@ export const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
loadComponent: () => import('./components/home/home').then((mod) => mod.Home),
|
||||
canActivate: [requireRoles([roles.MemberAdmin, roles.UserAdmin], true)],
|
||||
canActivate: [requireRoles()],
|
||||
},
|
||||
{
|
||||
path: 'home',
|
||||
loadComponent: () => import('./components/home/home').then((mod) => mod.Home),
|
||||
canActivate: [requireRoles()],
|
||||
},
|
||||
{ path: '**', component: MissingPage },
|
||||
];
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Component, signal } from '@angular/core';
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule, RouterOutlet } from '@angular/router';
|
||||
import { Authentication } from './services/authentication';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@@ -9,10 +10,6 @@ import { RouterModule, RouterOutlet } from '@angular/router';
|
||||
styleUrl: './app.scss',
|
||||
})
|
||||
export class App {
|
||||
protected loggedIn = signal(false);
|
||||
protected readonly title = signal('frontend');
|
||||
|
||||
protected onLogOut() {
|
||||
this.loggedIn.set(false);
|
||||
}
|
||||
protected readonly auth = inject(Authentication);
|
||||
}
|
||||
|
||||
@@ -1 +1,14 @@
|
||||
<p>home works!</p>
|
||||
<h1>Startseite</h1>
|
||||
<ul>
|
||||
<!--TODO fix theming/colors-->
|
||||
<button matButton="outlined" class="warn-button" [routerLink]="['/test']">
|
||||
Entwichlungsinformationen
|
||||
</button>
|
||||
<button matButton="filled" color="primary" [routerLink]="['/list']">Mitglieder</button>
|
||||
<button matButton="filled" color="warn" [routerLink]="['/manageUsers']">
|
||||
Benutzer Verwalten
|
||||
</button>
|
||||
<button matButton="filled" color="primary" [routerLink]="['/exam']">
|
||||
Prüfungsanmeldung
|
||||
</button>
|
||||
</ul>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
imports: [],
|
||||
imports: [RouterModule, MatButtonModule],
|
||||
templateUrl: './home.html',
|
||||
styleUrl: './home.scss',
|
||||
})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Authentication } from '../../services/authentication';
|
||||
|
||||
@Component({
|
||||
@@ -9,7 +10,13 @@ import { Authentication } from '../../services/authentication';
|
||||
})
|
||||
export class Login {
|
||||
private readonly authentication = inject(Authentication);
|
||||
private readonly router = inject(Router);
|
||||
|
||||
public constructor() {
|
||||
this.authentication.login();
|
||||
if(this.authentication.loggedIn()){
|
||||
this.router.navigate(['/home']);
|
||||
}else{
|
||||
this.authentication.login();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { effect, inject, Injectable, signal } from '@angular/core';
|
||||
import { computed, effect, inject, Injectable, signal } from '@angular/core';
|
||||
import {
|
||||
KEYCLOAK_EVENT_SIGNAL,
|
||||
KeycloakEventType,
|
||||
@@ -22,6 +22,9 @@ export class Authentication {
|
||||
private readonly _authenticationState = signal<AuthenticationState>(AuthenticationState.Unknown);
|
||||
private readonly _userInfo = signal<KeycloakProfile | null>(null);
|
||||
public readonly authenticationState = this._authenticationState.asReadonly();
|
||||
public readonly loggedIn = computed(()=>{
|
||||
return this.authenticationState() === AuthenticationState.Authenticated;
|
||||
});
|
||||
public readonly userInfo = this._userInfo.asReadonly();
|
||||
|
||||
public constructor() {
|
||||
@@ -69,6 +72,10 @@ export class Authentication {
|
||||
}
|
||||
|
||||
public async login(location?: string): Promise<void> {
|
||||
if(this._authenticationState() === AuthenticationState.Authenticated){
|
||||
return;
|
||||
}
|
||||
|
||||
var redirectUri = location
|
||||
? `${window.location.origin}/${location}`
|
||||
: `${window.location.origin}/login`;
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
// This file was generated by running 'ng generate @angular/material:theme-color'.
|
||||
// Proceed with caution if making changes to this file.
|
||||
|
||||
@use 'sass:map';
|
||||
@use '@angular/material' as mat;
|
||||
|
||||
// Note: Color palettes are generated from primary: #0047a0, secondary: #cc9c00, tertiary: #cd2e3a, error: #E63241
|
||||
$_palettes: (
|
||||
primary: (
|
||||
0: #000000,
|
||||
10: #001a43,
|
||||
20: #002d6c,
|
||||
25: #003881,
|
||||
30: #004397,
|
||||
35: #134fa8,
|
||||
40: #275bb5,
|
||||
50: #4575cf,
|
||||
60: #618feb,
|
||||
70: #83aaff,
|
||||
80: #afc6ff,
|
||||
90: #d8e2ff,
|
||||
95: #edf0ff,
|
||||
98: #faf9ff,
|
||||
99: #fefbff,
|
||||
100: #ffffff,
|
||||
),
|
||||
secondary: (
|
||||
0: #000000,
|
||||
10: #251a00,
|
||||
20: #3f2e00,
|
||||
25: #4c3800,
|
||||
30: #5a4300,
|
||||
35: #694f00,
|
||||
40: #775a00,
|
||||
50: #967200,
|
||||
60: #b58a00,
|
||||
70: #d5a411,
|
||||
80: #f3bf33,
|
||||
90: #ffdf99,
|
||||
95: #ffefd2,
|
||||
98: #fff8f2,
|
||||
99: #fffbff,
|
||||
100: #ffffff,
|
||||
),
|
||||
tertiary: (
|
||||
0: #000000,
|
||||
10: #410007,
|
||||
20: #680010,
|
||||
25: #7d0016,
|
||||
30: #92001b,
|
||||
35: #a60a23,
|
||||
40: #b81d2d,
|
||||
50: #db3943,
|
||||
60: #ff535a,
|
||||
70: #ff8887,
|
||||
80: #ffb3b0,
|
||||
90: #ffdad8,
|
||||
95: #ffedeb,
|
||||
98: #fff8f7,
|
||||
99: #fffbff,
|
||||
100: #ffffff,
|
||||
),
|
||||
neutral: (
|
||||
0: #000000,
|
||||
10: #191b21,
|
||||
20: #2e3036,
|
||||
25: #393b42,
|
||||
30: #45464d,
|
||||
35: #515259,
|
||||
40: #5d5e65,
|
||||
50: #75777e,
|
||||
60: #8f9098,
|
||||
70: #aaabb2,
|
||||
80: #c5c6ce,
|
||||
90: #e2e2ea,
|
||||
95: #f0f0f8,
|
||||
98: #faf9ff,
|
||||
99: #fefbff,
|
||||
100: #ffffff,
|
||||
4: #0c0e14,
|
||||
6: #111319,
|
||||
12: #1d1f25,
|
||||
17: #282a30,
|
||||
22: #33353b,
|
||||
24: #37393f,
|
||||
87: #d9d9e1,
|
||||
92: #e7e7f0,
|
||||
94: #ededf5,
|
||||
96: #f3f3fb,
|
||||
),
|
||||
neutral-variant: (
|
||||
0: #000000,
|
||||
10: #171b25,
|
||||
20: #2c303b,
|
||||
25: #373b46,
|
||||
30: #434752,
|
||||
35: #4e525e,
|
||||
40: #5a5e6a,
|
||||
50: #737783,
|
||||
60: #8d909d,
|
||||
70: #a7abb8,
|
||||
80: #c3c6d4,
|
||||
90: #dfe2f0,
|
||||
95: #edf0ff,
|
||||
98: #faf9ff,
|
||||
99: #fefbff,
|
||||
100: #ffffff,
|
||||
),
|
||||
error: (
|
||||
0: #000000,
|
||||
10: #410007,
|
||||
20: #680011,
|
||||
25: #7d0016,
|
||||
30: #92001c,
|
||||
35: #a90021,
|
||||
40: #bd0b29,
|
||||
50: #e12e3e,
|
||||
60: #ff535a,
|
||||
70: #ff8887,
|
||||
80: #ffb3b1,
|
||||
90: #ffdad8,
|
||||
95: #ffedeb,
|
||||
98: #fff8f7,
|
||||
99: #fffbff,
|
||||
100: #ffffff,
|
||||
),
|
||||
);
|
||||
|
||||
$_rest: (
|
||||
secondary: map.get($_palettes, secondary),
|
||||
neutral: map.get($_palettes, neutral),
|
||||
neutral-variant: map.get($_palettes, neutral-variant),
|
||||
error: map.get($_palettes, error),
|
||||
);
|
||||
|
||||
$primary-palette: map.merge(map.get($_palettes, primary), $_rest);
|
||||
$tertiary-palette: map.merge(map.get($_palettes, tertiary), $_rest);
|
||||
|
||||
@function _high-contrast-value($light, $dark, $theme-type) {
|
||||
@if ($theme-type == light) {
|
||||
@return $light;
|
||||
}
|
||||
@if ($theme-type == dark) {
|
||||
@return $dark;
|
||||
}
|
||||
@if ($theme-type == color-scheme) {
|
||||
@return light-dark(#{$light}, #{$dark});
|
||||
}
|
||||
|
||||
@error 'Unknown theme-type #{$theme-type}. Expected light, dark, or color-scheme';
|
||||
}
|
||||
|
||||
@mixin high-contrast-overrides($theme-type) {
|
||||
@include mat.theme-overrides((
|
||||
primary: _high-contrast-value(#002963, #ecefff, $theme-type),
|
||||
on-primary: _high-contrast-value(#ffffff, #000000, $theme-type),
|
||||
primary-container: _high-contrast-value(#00459c, #a9c2ff, $theme-type),
|
||||
on-primary-container: _high-contrast-value(#ffffff, #000a23, $theme-type),
|
||||
inverse-primary: _high-contrast-value(#afc6ff, #00449a, $theme-type),
|
||||
primary-fixed: _high-contrast-value(#00459c, #d8e2ff, $theme-type),
|
||||
primary-fixed-dim: _high-contrast-value(#003070, #afc6ff, $theme-type),
|
||||
on-primary-fixed: _high-contrast-value(#ffffff, #000000, $theme-type),
|
||||
on-primary-fixed-variant: _high-contrast-value(#ffffff, #00102f, $theme-type),
|
||||
secondary: _high-contrast-value(#392a00, #ffeecf, $theme-type),
|
||||
on-secondary: _high-contrast-value(#ffffff, #000000, $theme-type),
|
||||
secondary-container: _high-contrast-value(#5d4600, #efbb2f, $theme-type),
|
||||
on-secondary-container: _high-contrast-value(#ffffff, #110a00, $theme-type),
|
||||
secondary-fixed: _high-contrast-value(#5d4600, #ffdf99, $theme-type),
|
||||
secondary-fixed-dim: _high-contrast-value(#413000, #f3bf33, $theme-type),
|
||||
on-secondary-fixed: _high-contrast-value(#ffffff, #000000, $theme-type),
|
||||
on-secondary-fixed-variant: _high-contrast-value(#ffffff, #181000, $theme-type),
|
||||
tertiary: _high-contrast-value(#60000e, #ffecea, $theme-type),
|
||||
on-tertiary: _high-contrast-value(#ffffff, #000000, $theme-type),
|
||||
tertiary-container: _high-contrast-value(#97001c, #ffadab, $theme-type),
|
||||
on-tertiary-container: _high-contrast-value(#ffffff, #220002, $theme-type),
|
||||
tertiary-fixed: _high-contrast-value(#97001c, #ffdad8, $theme-type),
|
||||
tertiary-fixed-dim: _high-contrast-value(#6c0011, #ffb3b0, $theme-type),
|
||||
on-tertiary-fixed: _high-contrast-value(#ffffff, #000000, $theme-type),
|
||||
on-tertiary-fixed-variant: _high-contrast-value(#ffffff, #2d0003, $theme-type),
|
||||
background: _high-contrast-value(#faf9ff, #111319, $theme-type),
|
||||
on-background: _high-contrast-value(#191b21, #e2e2ea, $theme-type),
|
||||
surface: _high-contrast-value(#faf9ff, #111319, $theme-type),
|
||||
surface-dim: _high-contrast-value(#b8b8c0, #111319, $theme-type),
|
||||
surface-bright: _high-contrast-value(#faf9ff, #4e5056, $theme-type),
|
||||
surface-container-low: _high-contrast-value(#f0f0f8, #1d1f25, $theme-type),
|
||||
surface-container-lowest: _high-contrast-value(#ffffff, #000000, $theme-type),
|
||||
surface-container: _high-contrast-value(#e2e2ea, #2e3036, $theme-type),
|
||||
surface-container-high: _high-contrast-value(#d3d4dc, #393b42, $theme-type),
|
||||
surface-container-highest: _high-contrast-value(#c5c6ce, #45464d, $theme-type),
|
||||
on-surface: _high-contrast-value(#000000, #ffffff, $theme-type),
|
||||
shadow: _high-contrast-value(#000000, #000000, $theme-type),
|
||||
scrim: _high-contrast-value(#000000, #000000, $theme-type),
|
||||
surface-tint: _high-contrast-value(#275bb5, #afc6ff, $theme-type),
|
||||
inverse-surface: _high-contrast-value(#2e3036, #e2e2ea, $theme-type),
|
||||
inverse-on-surface: _high-contrast-value(#ffffff, #000000, $theme-type),
|
||||
outline: _high-contrast-value(#282c37, #edeffe, $theme-type),
|
||||
outline-variant: _high-contrast-value(#454954, #bfc2d0, $theme-type),
|
||||
error: _high-contrast-value(#60000e, #ffecea, $theme-type),
|
||||
on-error: _high-contrast-value(#ffffff, #000000, $theme-type),
|
||||
error-container: _high-contrast-value(#97001d, #ffadab, $theme-type),
|
||||
on-error-container: _high-contrast-value(#ffffff, #220002, $theme-type),
|
||||
surface-variant: _high-contrast-value(#dfe2f0, #434752, $theme-type),
|
||||
on-surface-variant: _high-contrast-value(#000000, #ffffff, $theme-type),
|
||||
))
|
||||
}
|
||||
@@ -5,16 +5,24 @@
|
||||
// Learn more about theming and how to use it for your application's
|
||||
// custom components at https://material.angular.dev/guide/theming
|
||||
@use '@angular/material' as mat;
|
||||
@use './styles.colors.scss' as my-theme;
|
||||
|
||||
@include mat.core();
|
||||
|
||||
@include mat.all-component-themes(my-theme.$light-theme);
|
||||
@include mat.color-variants-backwards-compatibility(my-theme.$light-theme);
|
||||
|
||||
html {
|
||||
@include mat.theme((
|
||||
color: (
|
||||
primary: mat.$cyan-palette,
|
||||
tertiary: mat.$orange-palette,
|
||||
),
|
||||
typography: Roboto,
|
||||
density: 0,
|
||||
));
|
||||
// @include mat.theme((
|
||||
// color: (
|
||||
// primary: my-theme.$primary-palette,
|
||||
// tertiary: my-theme.$tertiary-palette,
|
||||
// ),
|
||||
// typography: Roboto,
|
||||
// density: 0,
|
||||
// ));
|
||||
@include mat.core-theme(my-theme.$light-theme);
|
||||
@include mat.button-theme(my-theme.$light-theme);
|
||||
}
|
||||
|
||||
body {
|
||||
|
||||
Reference in New Issue
Block a user