Init webapp

This commit is contained in:
Peter Rossa
2023-05-10 15:02:48 +02:00
parent 88111e2acf
commit b101ccf6b6
60 changed files with 2519 additions and 1206 deletions

View File

@@ -1,27 +1,25 @@
import { Component } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { LoaderService } from 'src/app/components/loader/loader.service';
import { MeterDataAddDialogComponent } from 'src/app/components/dialogs/meter-data-add-dialog/meter-data-add-dialog.component';
import { DatabaseService } from 'src/app/services/database.service';
import { GlobalService } from 'src/app/services/global.service';
import { UsageType } from 'src/app/models/UsageType';
import { MeterData } from 'src/app/models/Meterdata';
import { HttpErrorResponse } from "@angular/common/http";
import { Component } from "@angular/core";
import { MatDialog } from "@angular/material/dialog";
import { LoaderService } from "src/app/components/loader/loader.service";
import { MeterData } from "src/app/dataModels/Meterdata";
import { UsageType } from "src/app/dataModels/UsageType";
import { MeterDataAddDialogComponent } from "src/app/dialogs/meter-data-add-dialog/meter-data-add-dialog.component";
import { DatabaseService } from "src/app/services/database.service";
import { ErrorService } from "src/app/services/error.service";
import { GlobalService } from "src/app/services/global.service";
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss'],
selector: "app-dashboard",
templateUrl: "./dashboard.component.html",
styleUrls: ["./dashboard.component.scss"],
})
export class DashboardComponent {
usageTypes = UsageType;
// meterDataEnergy1Hem: MeterData[] = [];
// meterDataEnergy1Log: MeterData[] = [];
meterDataEnergy: MeterData[] = [];
meterDataWater: MeterData[] = [];
// meterDataEnergyDTO1Log: MeterData[] = [];
// meterDataEnergyDTO1Hem: MeterData[] = [];
meterDataEnergyDTO: MeterData[] = [];
meterDataWaterDTO: MeterData[] = [];
@@ -29,12 +27,13 @@ export class DashboardComponent {
energyAverageAmountLastYear1Hem: number = 0;
waterAverageAmountLastYear: number = 0;
displayedColumns: string[] = ['date', 'amount', 'meter'];
displayedColumns: string[] = ["date", "amount", "meter"];
constructor(
private dataService: DatabaseService,
private loaderService: LoaderService,
private globalService: GlobalService,
private errorService: ErrorService,
private dialog: MatDialog
) {
this.loadMeterData();
@@ -46,11 +45,11 @@ export class DashboardComponent {
next: (data) => {
this.splitMeterData(data);
this.loaderService.hide();
console.log('Meter data:', data);
console.log("Meter data:", data);
},
error: (err) => {
error: (error: HttpErrorResponse) => {
this.errorService.handleError(error);
this.loaderService.hide();
console.error(err);
},
});
}
@@ -70,16 +69,6 @@ export class DashboardComponent {
}
initEnergyMeterData(): void {
// this.meterDataEnergy1Log = this.globalService.sortMeterData(
// this.meterDataEnergy1Log
// );
// this.meterDataEnergy1Hem = this.globalService.sortMeterData(
// this.meterDataEnergy1Hem
// );
// this.meterDataEnergyDTO1Log = this.meterDataEnergy1Log;
// this.meterDataEnergyDTO1Hem = this.meterDataEnergy1Hem;
this.meterDataEnergy = this.globalService.sortMeterData(
this.meterDataEnergy
);
@@ -103,8 +92,9 @@ export class DashboardComponent {
next: (meterData: MeterData) => {
console.log({ meterData });
},
error: (err) => {
console.log('add meterData error', { err });
error: (error: HttpErrorResponse) => {
this.errorService.handleError(error);
this.loaderService.hide();
},
});
}

View File

@@ -1,13 +1,14 @@
<div class="header-wrapper">
<div class="header-wrapper" *ngIf="userLoggedIn">
<div class="logo">
rossa-tech
</div>
<div class="nav">
<button type="button" class="btn btn-link" routerLink="/index">home</button>
<button type="button" class="btn btn-link" routerLink="/dashboard">dashboard</button>
</div>
<div class="account">
<button mat-button>logout</button>
<button mat-button (click)="onClickLogout()">logout</button>
</div>
</div>

View File

@@ -1,10 +1,76 @@
import { Component } from '@angular/core';
import { HttpErrorResponse } from "@angular/common/http";
import { Component, OnInit } from "@angular/core";
import { AuthService } from "src/app/auth/auth.service";
import { LoginService } from "src/app/auth/login.service";
import { ErrorService } from "src/app/services/error.service";
import { PageSecurityService } from "src/app/services/pageSecurity.service";
import { LoaderService } from "../loader/loader.service";
import { NotificationService } from "src/app/services/notification.service";
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
selector: "app-header",
templateUrl: "./header.component.html",
styleUrls: ["./header.component.scss"],
})
export class HeaderComponent {
export class HeaderComponent implements OnInit {
userLoggedIn: Boolean = false;
constructor(
private loginService: LoginService,
private pageSecurityService: PageSecurityService,
private errorService: ErrorService,
private loaderService: LoaderService,
private notificationService: NotificationService,
private authService: AuthService
) {}
ngOnInit(): void {
this.userLoggedIn = this.authService.checkUserLoggedIn();
}
public onClickLogout(): void {
this.loaderService.hide();
this.loginService.signout().subscribe({
next: (resp: any) => {
if (resp != null) {
if (resp.successful) {
// alert("Signed out successfully"); /// XXX
this.notificationService.showSnackbar(
"Signed out successfully",
3000,
"snackbar-success",
true,
"check"
);
this.loginService.removeSessionCurrentUser();
this.pageSecurityService.gotoLoginPage();
} else {
// alert("Signed out failed with error. " + resp.detailedMessage); /// XXX
this.notificationService.showSnackbar(
"Signed out failed with error. " + resp.detailedMessage,
3000,
"snackbar-warning",
true,
"information-slab-circle-outline"
);
}
} else {
// alert("Signed out failed with error. Unknown error."); /// XXX
this.notificationService.showSnackbar(
"Signed out failed with error. Unknown error.",
3000,
"snackbar-warning",
true,
"information-slab-circle-outline"
);
}
this.loaderService.hide();
},
error: (error: HttpErrorResponse) => {
this.errorService.handleError(error);
this.loaderService.hide();
},
});
}
}

View File

@@ -0,0 +1,3 @@
.link_click {
cursor:pointer;
}

View File

@@ -0,0 +1,28 @@
<div class="container">
<div class="row">
<div class="col">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Game Title</th>
<th scope="col">Publisher</th>
<th scope="col">Developed by</th>
<th scope="col">Publishing Year</th>
<th scope="col">Retail Price</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let title of allTitles; let i = index">
<td>{{i}}</td>
<td>{{title.gameTitleValue}}</td>
<td>{{title.publisherValue}}</td>
<td>{{title.devStudioNameValue}}</td>
<td>{{title.publishingYearValue}}</td>
<td>${{title.retailPriceValue}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

View File

@@ -0,0 +1,90 @@
import { Component, OnInit } from "@angular/core";
import { HttpErrorResponse } from "@angular/common/http";
// import { PageSecurityService } from "../common/pageSecurity.service";
import { GameTitlesService } from "../../services/gameTitles.service";
import { LoginService } from "../../auth/login.service";
import { GameTitle } from "../../dataModels/gameTitle.type";
import { PageSecurityService } from "src/app/services/pageSecurity.service";
import { AuthService } from "src/app/auth/auth.service";
@Component({
selector: "app-root",
templateUrl: "./index.component.html",
styleUrls: ["./index.component.css"],
})
export class IndexComponent implements OnInit {
private _allTitles: Array<GameTitle> = [];
public testArray: Array<String> = [];
constructor(
private loginService: LoginService,
private pageSecurityService: PageSecurityService,
private gameTitlesService: GameTitlesService,
private authService: AuthService
) {
this.testArray.push("Test1");
this.testArray.push("Test2");
this.testArray.push("Test3");
this.testArray.push("Test4");
this.testArray.push("Test5");
}
public get allTitles(): Array<GameTitle> {
return this._allTitles;
}
public set allTitles(val: Array<GameTitle>) {
this._allTitles = val;
}
ngOnInit(): void {
// let userLoggedIn: Boolean = this.authService.checkUserLoggedIn();
// if (!userLoggedIn) {
// this.pageSecurityService.gotoLoginPage();
// } else {
this.loadAllGameTitles();
// }
}
private loadAllGameTitles(): void {
let self = this;
self.gameTitlesService.getAllGameTitles().subscribe(
(resp: any) => {
if (resp && resp.length > 0) {
for (var itm of resp) {
if (itm) {
let titleToAdd: GameTitle = new GameTitle(
itm.gameTitle,
itm.publisher,
itm.devStudioName,
itm.publishingYear,
itm.retailPrice
);
self._allTitles.push(titleToAdd);
}
}
}
},
(error: HttpErrorResponse) => {
if (error != null) {
if (error.status === 0) {
// XXX
console.log("Client error.");
} else if (error.status === 401 || error.status === 403) {
// XXX
alert("You are not authorized.");
console.log("You are not authorized.");
self.loginService.removeSessionCurrentUser();
self.pageSecurityService.gotoLoginPage();
} else if (error.status === 500) {
alert("Server error.");
console.log("Server error occurred.");
} else {
alert("Unknown error.");
console.log("Unknown error: " + error.status);
}
}
}
);
}
}

View File

@@ -0,0 +1,23 @@
<div class="login-form-wrapper">
<mat-card>
<mat-card-content>
<form [formGroup]="loginForm" (ngSubmit)="login()">
<h2>Log In</h2>
<mat-form-field>
<input matInput placeholder="Email" formControlName="userName" name="username" required>
<mat-error>
Please provide a valid email address
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput type="password" placeholder="Password" formControlName="userPass" name="password" required>
<mat-error>
Please provide a valid password
</mat-error>
</mat-form-field>
<button mat-raised-button color="primary" [disabled]="!loginForm.valid">Login</button>
</form>
</mat-card-content>
</mat-card>
</div>

View File

@@ -0,0 +1,17 @@
mat-card {
max-width: 400px;
margin: 2em auto;
text-align: center;
color: #333333;
}
mat-form-field {
display: block;
}
login-form-wrapper {
display: flex;
flex-direction: column;
width: 100%;
justify-content: center;
}

View File

@@ -0,0 +1,95 @@
import { Component, OnInit } from "@angular/core";
import { HttpErrorResponse } from "@angular/common/http";
import { Router } from "@angular/router";
import { LoginUser } from "../../dataModels/loginUser.type";
import { LoginService } from "../../auth/login.service";
import { FormsService } from "../../services/forms.service";
import { AuthService } from "src/app/auth/auth.service";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { LoaderService } from "../loader/loader.service";
import { NotificationService } from "src/app/services/notification.service";
@Component({
selector: "app-root",
templateUrl: "./login.component.html",
styleUrls: ["./login.component.scss"],
})
export class LoginComponent implements OnInit {
loginForm: FormGroup = new FormGroup({
userName: new FormControl("", Validators.required),
userPass: new FormControl("", Validators.required),
});
constructor(
private loginService: LoginService,
private formsService: FormsService,
private authService: AuthService,
private loaderService: LoaderService,
private notificationService: NotificationService,
private router: Router
) {}
ngOnInit() {
let userLoggedIn: Boolean = this.authService.checkUserLoggedIn();
if (userLoggedIn) {
this.router.navigate(["/index"]);
}
}
public resetForm(): void {
this.loginForm.reset();
this.formsService.makeFormFieldsClean(this.loginForm);
}
public login(): void {
this.formsService.makeFormFieldsDirty(this.loginForm);
if (this.loginForm.valid) {
this.loaderService.show();
let userToLogin: LoginUser = new LoginUser(
this.loginForm.value.userName,
this.loginForm.value.userPass
);
this.loginService.login(userToLogin).subscribe({
next: (resp: any) => {
if (
resp != null &&
resp.userId != null &&
resp.userId.trim() !== "" &&
resp.tokenValue != null &&
resp.tokenValue.trim() !== ""
) {
this.loginService.setSessionCurrentUser(resp);
this.router.navigate(["/"]);
}
},
error: (error: HttpErrorResponse) => {
if (error != null) {
if (error.status === 0) {
console.log("Client error.");
this.notificationService.showSnackbar(
"Client error",
3000,
"snackbar-warning",
true,
"alert-circle-outline"
);
} else if (error.status === 401 || error.status === 403) {
this.loginForm.reset();
this.formsService.makeFormFieldsClean(this.loginForm);
console.log("You are not authorized.");
} else if (error.status === 500) {
console.log("Server error occurred.");
} else {
console.log("Unknown error: " + error.status);
}
this.loaderService.hide();
}
},
});
}
}
}

View File

@@ -0,0 +1,42 @@
snack-bar-container.mat-mdc-snack-bar-container {
background-color: white;
padding: 10px 16px 10px 12px;
border-radius: 3px;
box-shadow: 1px 2px 10px 2px rgba(0, 0, 0, 0.12);
min-width: 352px;
max-width: 544px;
}
div.snackbar {
color: #595959;
display: flex;
align-items: center;
mat-icon.snackbar-icon {
margin-right: 12px;
}
span.snackbar-text {
flex: 1;
}
mat-icon.snackbar-btn {
color: #595959;
height: 22px;
width: 22px;
cursor: pointer;
margin-left: 72px;
}
&.snackbar-warning {
color: red;
}
&.snackbar-success {
color: green;
}
&.snackbar-primary {
color: blue;
}
}

View File

@@ -0,0 +1,7 @@
<div class="snackbar" [ngClass]="data?.className">
<mat-icon class="snackbar-icon" svgIcon="{{data?.iconName}}" *ngIf="data?.icon"></mat-icon>
<span class="snackbar-text">
{{data?.message}}
</span>
<mat-icon svgIcon="close" class="snackbar-btn" (click)="snackBar.dismiss()"></mat-icon>
</div>

View File

@@ -0,0 +1,30 @@
import { Component, Inject } from "@angular/core";
import { MAT_SNACK_BAR_DATA, MatSnackBar } from "@angular/material/snack-bar";
@Component({
selector: "app-snackbar",
templateUrl: "./snackbar.component.html",
styleUrls: ["snackbar-component.scss"],
})
export class SnackbarComponent {
/*
* data = {
* message: string; snackbar text
* className: string; snackbar class
* btnLabel: string; Button label text
* icon: boolean; show icon
* iconName: string; name of the icon
* }
*
* icons:
* check
* alert-circle-outline
* information-slab-circle-outline
* server-off
*
*/
constructor(
@Inject(MAT_SNACK_BAR_DATA) public data: any,
public snackBar: MatSnackBar
) {}
}

View File

@@ -1,20 +1,43 @@
<ng-container *ngIf="type == usageTypes.ENERGY; else water">
<div style="display: flex; flex-direction: column">
<div>energy</div>
<div style="display: flex; flex-direction: row;">
<div>{{averageEnergy1Log}} kWh</div>
<div>{{averageEnergy1Hem}} kWh</div>
</div>
<h2>{{type}}</h2>
<mat-grid-list cols="2" rowHeight="50px">
<mat-grid-tile>
1LOG - Hausstrom
</mat-grid-tile>
<mat-grid-tile>
1HEM - Heizstrom
</mat-grid-tile>
<mat-grid-tile>
<div>{{averageEnergy1Log}} kWh</div>
</mat-grid-tile>
<mat-grid-tile>
<div>{{averageEnergy1Hem}} kWh</div>
</mat-grid-tile>
</mat-grid-list>
</div>
</ng-container>
<ng-template #water>
<div style="display: flex; flex-direction: column">
<h2>{{type}}</h2>
</ng-template>
<!-- <ng-container *ngIf="amount > 0; else noData">{{amount}} kWh</ng-container>
<ng-template #noData>keine Daten vorhanden</ng-template> -->
<mat-grid-list cols="2" rowHeight="50px">
<mat-grid-tile>
Wasser
</mat-grid-tile>
<mat-grid-tile>
Abwasser
</mat-grid-tile>
<mat-grid-tile>
<div>xxxxx</div>
</mat-grid-tile>
<mat-grid-tile>
<div>xxxxx</div>
</mat-grid-tile>
</mat-grid-list>
</div>
</ng-template>

View File

@@ -1,44 +1,46 @@
import { Component, Input, OnChanges } from '@angular/core';
import { Meters } from 'src/app/models/Meter';
import { MeterData } from 'src/app/models/Meterdata';
import { UsageType } from 'src/app/models/UsageType';
import { GlobalService } from 'src/app/services/global.service';
import { Component, Input, OnChanges } from "@angular/core";
import { Meters } from "src/app/dataModels/Meter";
import { MeterData } from "src/app/dataModels/Meterdata";
import { UsageType } from "src/app/dataModels/UsageType";
import { GlobalService } from "src/app/services/global.service";
@Component({
selector: 'app-consumption-last-year',
templateUrl: './consumption-last-year.component.html',
styleUrls: ['./consumption-last-year.component.scss'],
selector: "app-consumption-last-year",
templateUrl: "./consumption-last-year.component.html",
styleUrls: ["./consumption-last-year.component.scss"],
})
export class ConsumptionLastYearComponent implements OnChanges {
@Input() meterData: MeterData[];
@Input() type: UsageType;
@Input()
meterData!: MeterData[];
@Input()
type!: UsageType;
usageTypes = UsageType;
meters = Meters;
meterDataEnergy1Hem: MeterData[] = [];
averageEnergy1Hem: number;
averageEnergy1Hem!: number;
meterDataEnergy1Log: MeterData[] = [];
averageEnergy1Log: number;
averageEnergy1Log!: number;
meterDataWasser: MeterData[] = [];
averageWasser: number;
averageWasser!: number;
meterDataAbwasser: MeterData[] = [];
averageDirtyAbwasser: number;
averageDirtyAbwasser!: number;
constructor(private globalService: GlobalService) {}
ngOnChanges(): void {
if (this.type && this.type === this.usageTypes.ENERGY) {
console.log('count energy');
console.log("count energy");
if (this.meterData) {
this.meterData.forEach((data) => {
if (data.meter.name === this.meters['1LOG']) {
if (data.meter.name === this.meters["1LOG"]) {
this.meterDataEnergy1Log.push(data);
} else if (data.meter.name === this.meters['1HEM']) {
} else if (data.meter.name === this.meters["1HEM"]) {
this.meterDataEnergy1Hem.push(data);
}
});
@@ -61,13 +63,13 @@ export class ConsumptionLastYearComponent implements OnChanges {
);
}
} else if (this.type && this.type === this.usageTypes.WATER) {
console.log('count water');
console.log("count water");
if (this.meterData) {
this.meterData.forEach((data) => {
if (data.meter.name === this.meters['WASSER']) {
if (data.meter.name === this.meters["WASSER"]) {
this.meterDataWasser.push(data);
} else if (data.meter.name === this.meters['ABWASSER']) {
} else if (data.meter.name === this.meters["ABWASSER"]) {
this.meterDataAbwasser.push(data);
}
});

View File

@@ -1,5 +1,3 @@
<h2>{{type}}</h2>
<div class="meter-data-list-wrapper">
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">

View File

@@ -1,18 +1,20 @@
import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { UsageType } from 'src/app/models/UsageType';
import { MeterData } from 'src/app/models/Meterdata';
import { Component, Input, OnChanges, OnInit } from "@angular/core";
import { MatTableDataSource } from "@angular/material/table";
import { UsageType } from "src/app/dataModels/UsageType";
import { MeterData } from "src/app/dataModels/Meterdata";
@Component({
selector: 'app-meter-data-list',
templateUrl: './meter-data-list.component.html',
styleUrls: ['./meter-data-list.component.scss'],
selector: "app-meter-data-list",
templateUrl: "./meter-data-list.component.html",
styleUrls: ["./meter-data-list.component.scss"],
})
export class MeterDataListComponent implements OnInit, OnChanges {
@Input() meterData: MeterData[];
@Input() type: UsageType;
@Input()
meterData: MeterData[] = [];
@Input()
type: UsageType = UsageType.ENERGY;
displayedColumns: string[] = ['id', 'date', 'amount', 'meter'];
displayedColumns: string[] = ["id", "date", "amount", "meter"];
dataSource = new MatTableDataSource<MeterData>();
// dataSource = [

View File

@@ -1,16 +1,18 @@
import { Component, Input, OnChanges } from '@angular/core';
import { MeterData } from 'src/app/models/Meterdata';
import { UsageType } from 'src/app/models/UsageType';
import { GlobalService } from 'src/app/services/global.service';
import { Component, Input, OnChanges } from "@angular/core";
import { MeterData } from "src/app/dataModels/Meterdata";
import { UsageType } from "src/app/dataModels/UsageType";
import { GlobalService } from "src/app/services/global.service";
@Component({
selector: 'app-meter-data-wrapper',
templateUrl: './meter-data-wrapper.component.html',
styleUrls: ['./meter-data-wrapper.component.scss'],
selector: "app-meter-data-wrapper",
templateUrl: "./meter-data-wrapper.component.html",
styleUrls: ["./meter-data-wrapper.component.scss"],
})
export class MeterDataWrapperComponent /* implements OnChanges */ {
@Input() meterData: MeterData[];
@Input() type: UsageType;
@Input()
meterData: MeterData[] = [];
@Input()
type: UsageType = UsageType.ENERGY;
// usageTypes = UsageType;
// averageConsumptionLastYear: number;