fix theming + ui improvements

This commit is contained in:
toni
2025-12-25 20:56:05 +01:00
parent e15be9c7e3
commit 17c0ff208b
14 changed files with 559 additions and 422 deletions
+2 -1
View File
@@ -8,7 +8,8 @@
"watch": "ng build --watch --configuration development",
"test": "ng test",
"generate": "oazapfts --optimistic --useEnumType ./src/app/generated-api/swagger.json ./src/app/generated-api/api.ts",
"dev": "pnpm -w run dev"
"dev": "pnpm -w run dev",
"deploy": "ng build --aot --configuration production"
},
"prettier": {
"printWidth": 100,
+5 -3
View File
@@ -1,14 +1,16 @@
@if(this.auth.loggedIn()){
<div class="no-print">
<button mat-flat-button color="accent" (click)="this.auth.logout()">
<button mat-flat-button class="secondary-btn" (click)="this.auth.logout()">
Abmelden
</button>
<button mat-stroked-button color="primary" [routerLink]="['/home']">
<button mat-flat-button class="primary-btn" [routerLink]="['/home']">
Home
</button>
<button mat-stroked-button color="primary" [routerLink]="['/profile']">
<button mat-flat-button class="tertiary-btn" (click)="gotoProfile()">
Profil
</button>
</div>
}
<div class="outlet">
<router-outlet></router-outlet>
</div>
-5
View File
@@ -11,7 +11,6 @@ import { AuthGuardData, createAuthGuard } from 'keycloak-angular';
import { Login } from './components/login/login';
import { MissingPage } from './components/missing-page/missing-page';
import { Claim } from './generated-api/api';
import { keycloakConfig } from './util/keycloak-config';
export const roles = {
UserAdmin: 'useradmin',
@@ -71,9 +70,5 @@ export const routes: Routes = [
),
canActivate: [requireRoles([Claim.Memberadmin])],
},
{
path: 'profile',
redirectTo: `${keycloakConfig.url}/realms/${keycloakConfig.realm}/account`,
},
{ path: '**', component: MissingPage },
];
+7 -7
View File
@@ -1,10 +1,10 @@
@media print {
.no-print {
display: none;
visibility: hidden;
:host {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
:not(.no-print) {
visibility: visible;
}
.outlet {
overflow: auto;
}
+15 -1
View File
@@ -1,7 +1,8 @@
import { Component, inject, signal } from '@angular/core';
import { Component, effect, inject, signal } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule, RouterOutlet } from '@angular/router';
import { Authentication } from './services/authentication';
import { keycloakConfig } from './util/keycloak-config';
@Component({
selector: 'app-root',
@@ -12,4 +13,17 @@ import { Authentication } from './services/authentication';
export class App {
protected readonly title = signal('frontend');
protected readonly auth = inject(Authentication);
protected gotoProfile() {
window.location.href = `${keycloakConfig.url}/realms/${keycloakConfig.realm}/account`;
}
constructor() {
effect(() => {
const loggedIn = this.auth.loggedIn();
if (!loggedIn) {
this.auth.login();
}
});
}
}
@@ -1,14 +1,26 @@
<h1>Startseite</h1>
<ul>
<!--TODO fix theming/colors-->
<button matButton="outlined" class="warn-button" [routerLink]="['/test']">
Entwichlungsinformationen
<mat-list>
<mat-list-item [claimGuard]="Claim.Memberadmin">
<button matButton="filled" color="primary" [routerLink]="['/list']">
Mitgliederliste
</button>
<button matButton="filled" color="primary" [routerLink]="['/list']">Mitglieder</button>
</mat-list-item>
<mat-list-item [claimGuard]="Claim.Useradmin">
<button matButton="filled" color="warn" [routerLink]="['/manageUsers']">
Benutzer Verwalten
</button>
</mat-list-item>
<mat-list-item [claimGuard]="Claim.Memberadmin">
<button matButton="filled" color="primary" [routerLink]="['/exam']">
Prüfungsanmeldung
</button>
</ul>
</mat-list-item>
<mat-list-item>
<button
matButton="outlined"
class="warn-button"
[routerLink]="['/test']">
Entwichlungsinformationen
</button>
</mat-list-item>
</mat-list>
@@ -1,13 +1,21 @@
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatListModule } from '@angular/material/list';
import { RouterModule } from '@angular/router';
import { ClaimGuardDirective } from '../../directives/claim-guard.directive';
import { Claim } from '../../generated-api/api';
@Component({
selector: 'app-home',
imports: [RouterModule, MatButtonModule],
imports: [
RouterModule,
MatButtonModule,
MatListModule,
ClaimGuardDirective,
],
templateUrl: './home.html',
styleUrl: './home.scss',
})
export class Home {
protected Claim = Claim;
}
@@ -1,15 +1,15 @@
<div>
<h1>Mitglieder & Sportlerübersicht</h1>
<button mat-raised-button color="accent" (click)="newMember()">
</div>
<div>
<button matButton="filled" class="primary-btn" (click)="newMember()">
Neues Mitglied
</button>
<div class="filter-container mat-elevation-z8">
<div class="filter-header">
</div>
<div class="filter-container">
<mat-form-field>
<label>Filter:</label>
<input
matInput
[formControl]="filterControl"
placeholder="Filter" />
<input matInput [formControl]="filterControl" placeholder="Filter" />
</mat-form-field>
<div class="status-filters">
<mat-radio-group [formControl]="statusControl">
@@ -31,7 +31,6 @@
matInput
[matDatepicker]="picker"
[formControl]="statusDateControl"
[disabled]="statusControl.value===MemberStatusFilter.ALL"
placeholder="Aktiv bis" />
<mat-hint>DD.MM.YYYY</mat-hint>
<mat-datepicker-toggle
@@ -41,14 +40,18 @@
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
</div>
<mat-checkbox [formControl]="onlyWithID"
>Nur mit Passnummer</mat-checkbox
>
<mat-checkbox [formControl]="onlyWithID">Nur mit Passnummer</mat-checkbox>
</div>
</div>
<div class="table-container">
<!--TODO implement row count, selecting and alternating colors-->
<table mat-table matSort [dataSource]="dataSource" class="mat-elevation-z8">
<table
mat-table
[dataSource]="dataSource"
class="member-table"
matSort
matSortActive="vorname"
matSortDirection="asc"
matSortDisableClear>
<ng-container matColumnDef="edit">
<th mat-header-cell *matHeaderCellDef>Bearb.</th>
<td mat-cell *matCellDef="let element">
@@ -60,17 +63,12 @@
</button>
</td>
</ng-container>
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef>Entf.</th>
<td mat-cell *matCellDef="let element">
<button
mat-mini-fab-button
(click)="deleteMember(element.id)"
aria-label="Delete Member">
<mat-icon fontIcon="delete"></mat-icon>
</button>
</td>
<ng-container matColumnDef="index" sticky>
<th mat-header-cell *matHeaderCellDef>Nr.</th>
<td mat-cell *matCellDef="let element; let i=index">{{i+1}}</td>
</ng-container>
<ng-container matColumnDef="vorname">
<th mat-header-cell mat-sort-header *matHeaderCellDef>Vorname</th>
<td mat-cell *matCellDef="let element">
@@ -84,23 +82,31 @@
</td>
</ng-container>
<ng-container matColumnDef="geschlecht">
<th mat-header-cell mat-sort-header *matHeaderCellDef>Geschlecht</th>
<th mat-header-cell mat-sort-header *matHeaderCellDef>
Geschlecht
</th>
<td mat-cell *matCellDef="let element">{{ element.geschlecht }}</td>
</ng-container>
<ng-container matColumnDef="passnummer">
<th mat-header-cell mat-sort-header *matHeaderCellDef>Passnummer</th>
<th mat-header-cell mat-sort-header *matHeaderCellDef>
Passnummer
</th>
<td mat-cell *matCellDef="let element">
{{ element.passnummer | nobreakHyphen }}
</td>
</ng-container>
<ng-container matColumnDef="geburtsdatum">
<th mat-header-cell mat-sort-header *matHeaderCellDef>Geburtsdatum</th>
<th mat-header-cell mat-sort-header *matHeaderCellDef>
Geburtsdatum
</th>
<td mat-cell *matCellDef="let element">
{{ element.geburtsdatum | datePipe }}
</td>
</ng-container>
<ng-container matColumnDef="geburtsort">
<th mat-header-cell mat-sort-header *matHeaderCellDef>Geburtsort</th>
<th mat-header-cell mat-sort-header *matHeaderCellDef>
Geburtsort
</th>
<td mat-cell *matCellDef="let element">{{ element.geburtsort }}</td>
</ng-container>
<ng-container matColumnDef="verein">
@@ -137,6 +143,38 @@
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef>Entf.</th>
<td mat-cell *matCellDef="let element">
<button
mat-mini-fab-button
(click)="deleteMember(element.id)"
aria-label="Delete Member">
<mat-icon fontIcon="delete"></mat-icon>
</button>
</td>
</ng-container>
<ng-container matColumnDef="totalCount">
<td
colspan="100%"
mat-footer-cell
*matFooterCellDef
class="footer-entry">
Zeige {{dataSource.filteredData.length}} von
{{dataSource.data.length}} Mitgliedern
@if(dataSource.filteredData.length !== dataSource.data.length)
{(gefiltert) }
</td>
</ng-container>
<tr
mat-header-row
*matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr
mat-row
*matRowDef="let row; columns: displayedColumns"
class="table-row"></tr>
<tr mat-footer-row *matFooterRowDef="['totalCount']; sticky: true"></tr>
</table>
</div>
@@ -1,16 +1,33 @@
mat-radio-group {
@use "@angular/material" as mat;
:host {
display: flex;
flex-direction: column;
flex-flow: column;
height: 100%;
// overflow: auto;
}
.filter-header {
.filter-container {
display: flex;
flex-direction: row;
justify-content: space-evenly;
justify-content: start;
gap: 5vw;
flex-wrap: wrap;
}
.table-container {
overflow: auto;
border: 1px solid var(--mat-sys-outline);
min-height: 400px;
}
mat-form-field {
height: 100%;
display: inline-block;
}
mat-radio-group {
display: flex;
flex-direction: column;
}
.status-filters {
@@ -19,3 +36,16 @@ mat-form-field {
justify-content: center;
gap: 1rem;
}
td {
border: 1px solid var(--mat-sys-outline-variant);
border-collapse: collapse;
}
.table-row:nth-child(even) {
background-color: var(--mat-sys-surface-variant);
}
.table-row:nth-child(odd) {
background-color: var(--mat-sys-surface);
}
@@ -1,4 +1,5 @@
import { AfterViewInit, Component, viewChild } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckbox } from '@angular/material/checkbox';
@@ -62,7 +63,7 @@ export class ViewMembers implements AfterViewInit {
protected readonly displayedColumns: string[] = [
'edit',
'delete',
'index',
'vorname',
'nachname',
'geschlecht',
@@ -72,6 +73,7 @@ export class ViewMembers implements AfterViewInit {
'verein',
'kontakt',
'kuendigungzum',
'delete',
];
protected deleteMember(memberId: any) {
@@ -157,6 +159,7 @@ export class ViewMembers implements AfterViewInit {
return originalFilterPredicate(
{
...data,
id: null,
geburtsdatum: this.datePipe.transform(
data.geburtsdatum ?? undefined,
),
@@ -189,7 +192,22 @@ export class ViewMembers implements AfterViewInit {
const date = combined[2];
const onlyWithID = combined[3];
this.dataSource.filter = `${filter?.replaceAll(';', '') ?? ''};${status};${date?.toISOString()};${onlyWithID}`;
console.log('filter', this.dataSource.filter);
});
this.statusControl.valueChanges
.pipe(takeUntilDestroyed())
.subscribe(value => {
if (
value === MemberStatusFilter.ALL &&
this.statusDateControl.enabled
) {
return this.statusDateControl.disable();
} else if (
value !== MemberStatusFilter.ALL &&
this.statusDateControl.disabled
) {
return this.statusDateControl.enable();
}
});
this.updateData();
@@ -202,8 +220,6 @@ export class ViewMembers implements AfterViewInit {
private async updateData(): Promise<void> {
const members = await api.getMembers();
console.log('Members loaded');
console.dir(members);
this.dataSource.data = members;
}
}
@@ -0,0 +1,27 @@
import { Directive, effect, ElementRef, inject, input } from '@angular/core';
import { Claim } from '../generated-api/api';
import { Authentication } from '../services/authentication';
@Directive({
selector: '[claimGuard]',
})
export class ClaimGuardDirective {
private readonly element = inject(ElementRef);
private readonly auth = inject(Authentication);
public readonly claimGuard = input.required<Claim>();
private readonly originalDisplay = this.element.nativeElement.style.display;
constructor() {
effect(() => {
const claims = this.auth.claims();
const requiredClaim = this.claimGuard();
if (!claims || !claims[requiredClaim]) {
this.element.nativeElement.style.display = 'none';
} else {
this.element.nativeElement.style.display = this.originalDisplay;
}
});
}
}
-205
View File
@@ -1,205 +0,0 @@
// 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),
))
}
+84 -22
View File
@@ -1,47 +1,109 @@
// Include theming for Angular Material with `mat.theme()`.
// This Sass mixin will define CSS variables that are used for styling Angular Material
// components according to the Material 3 design spec.
// 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;
@use "@angular/material" as mat;
@use "./theme-colors.scss" as theme-colors;
@include mat.core();
@include mat.core-theme(my-theme.$primary-palette);
@include mat.button-theme(my-theme.$primary-palette);
html {
@include mat.theme((
color: (
primary: my-theme.$primary-palette,
tertiary: my-theme.$tertiary-palette,
),
typography: Roboto,
density: 0,
));
@include mat.core-theme(my-theme.$primary-palette);
@include mat.button-theme(my-theme.$primary-palette);
}
body {
// Default the application to a light color theme. This can be changed to
// `dark` to enable the dark color theme, or to `light dark` to defer to the
// user's system settings.
color-scheme: light;
@include mat.theme(
(
color: (
theme-type: light,
primary: theme-colors.$primary-palette,
tertiary: theme-colors.$tertiary-palette,
),
typography: (
plain-family: Roboto,
brand-family: Roboto,
),
density: (
scale: 0,
),
)
);
// Define css classes like .mat-text-on-surface
// @include mat.system-classes();
.primary-btn {
@include mat.button-overrides(
(
filled-container-color: var(--mat-sys-primary),
filled-label-text-color: var(--mat-sys-on-primary),
outlined-label-text-color: var(--mat-sys-primary),
outlined-outline-color: var(--mat-sys-primary),
protected-container-color: var(--mat-sys-primary),
protected-label-text-color: var(--mat-sys-on-primary),
text-label-text-color: var(--mat-sys-primary),
tonal-label-text-color: var(--mat-sys-primary),
)
);
}
.secondary-btn {
@include mat.button-overrides(
(
filled-container-color: var(--mat-sys-secondary),
filled-label-text-color: var(--mat-sys-on-secondary),
outlined-label-text-color: var(--mat-sys-secondary),
outlined-outline-color: var(--mat-sys-secondary),
protected-container-color: var(--mat-sys-secondary),
protected-label-text-color: var(--mat-sys-on-secondary),
text-label-text-color: var(--mat-sys-secondary),
tonal-label-text-color: var(--mat-sys-secondary),
)
);
}
.tertiary-btn {
@include mat.button-overrides(
(
filled-container-color: var(--mat-sys-tertiary),
filled-label-text-color: var(--mat-sys-on-tertiary),
outlined-label-text-color: var(--mat-sys-tertiary),
outlined-outline-color: var(--mat-sys-tertiary),
protected-container-color: var(--mat-sys-tertiary),
protected-label-text-color: var(--mat-sys-on-tertiary),
text-label-text-color: var(--mat-sys-tertiary),
tonal-label-text-color: var(--mat-sys-tertiary),
)
);
}
}
body {
// Set a default background, font and text colors for the application using
// Angular Material's system-level CSS variables. Learn more about these
// variables at https://material.angular.dev/guide/system-variables
background-color: var(--mat-sys-surface);
color: var(--mat-sys-on-surface);
font: var(--mat-sys-body-medium);
// font: var(--mat-sys-body-medium);
// Reset the user agent margin.
margin: 0;
}
/* You can add global styles to this file, and also import other style files */
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
html,
body {
height: 100%;
}
@media print {
.no-print {
display: none;
visibility: hidden;
}
:not(.no-print) {
visibility: visible;
}
}
+137
View File
@@ -0,0 +1,137 @@
// 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: #cd2e3a, tertiary: #673b6d
$_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: #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,
),
tertiary: (
0: #000000,
10: #310839,
20: #491f50,
25: #552b5c,
30: #623668,
35: #6f4274,
40: #7c4e81,
50: #96669b,
60: #b27fb6,
70: #ce99d2,
80: #ecb4ef,
90: #ffd5ff,
95: #ffebfc,
98: #fff7fa,
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: #410002,
20: #690005,
25: #7e0007,
30: #93000a,
35: #a80710,
40: #ba1a1a,
50: #de3730,
60: #ff5449,
70: #ff897d,
80: #ffb4ab,
90: #ffdad6,
95: #ffedea,
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);