Init app
This commit is contained in:
18
rossa-tech-cli/src/app/app-routing.module.ts
Normal file
18
rossa-tech-cli/src/app/app-routing.module.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { DashboardComponent } from 'src/app/components/dashboard/dashboard.component';
|
||||
import { LoginComponent } from './components/login/login.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: 'dashboard', component: DashboardComponent },
|
||||
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
||||
{ path: '**', redirectTo: '/dashboard', pathMatch: 'full' },
|
||||
// { path: 'login', component: LoginComponent },
|
||||
// { path: '', component: LoginComponent },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
3
rossa-tech-cli/src/app/app.component.html
Normal file
3
rossa-tech-cli/src/app/app.component.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<app-loader></app-loader>
|
||||
<app-header></app-header>
|
||||
<router-outlet></router-outlet>
|
||||
0
rossa-tech-cli/src/app/app.component.scss
Normal file
0
rossa-tech-cli/src/app/app.component.scss
Normal file
35
rossa-tech-cli/src/app/app.component.spec.ts
Normal file
35
rossa-tech-cli/src/app/app.component.spec.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'rossa-tech-cli'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('rossa-tech-cli');
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('.content span')?.textContent).toContain('rossa-tech-cli app is running!');
|
||||
});
|
||||
});
|
||||
10
rossa-tech-cli/src/app/app.component.ts
Normal file
10
rossa-tech-cli/src/app/app.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'rossa-tech-cli';
|
||||
}
|
||||
91
rossa-tech-cli/src/app/app.module.ts
Normal file
91
rossa-tech-cli/src/app/app.module.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule, DomSanitizer } from '@angular/platform-browser';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { DashboardComponent } from './components/dashboard/dashboard.component';
|
||||
import { MetersComponent } from './components/meters/meters.component';
|
||||
|
||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatIconModule, MatIconRegistry } from '@angular/material/icon';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { LoaderComponent } from './components/loader/loader.component';
|
||||
import { HeaderComponent } from './components/header/header.component';
|
||||
import { MeterDataListComponent } from './components/subcomponents/meter-data-list/meter-data-list.component';
|
||||
import { MatGridListModule } from '@angular/material/grid-list';
|
||||
import { ConsumptionLastYearComponent } from './components/subcomponents/consumption-last-year/consumption-last-year.component';
|
||||
import { MeterDataWrapperComponent } from './components/subcomponents/meter-data-wrapper/meter-data-wrapper.component';
|
||||
import { MeterDataAddDialogComponent } from './components/dialogs/meter-data-add-dialog/meter-data-add-dialog.component';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
import { LoginComponent } from './components/login/login.component';
|
||||
import { LogoutComponent } from './components/logout/logout.component';
|
||||
// import { HttpInterceptorService } from './components/interceptors/httpInterceptor.service';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
DashboardComponent,
|
||||
MetersComponent,
|
||||
LoaderComponent,
|
||||
HeaderComponent,
|
||||
MeterDataListComponent,
|
||||
ConsumptionLastYearComponent,
|
||||
MeterDataWrapperComponent,
|
||||
MeterDataAddDialogComponent,
|
||||
LoginComponent,
|
||||
LogoutComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
HttpClientModule,
|
||||
BrowserAnimationsModule,
|
||||
FormsModule,
|
||||
AppRoutingModule,
|
||||
MatCardModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatSelectModule,
|
||||
MatTableModule,
|
||||
MatProgressBarModule,
|
||||
MatToolbarModule,
|
||||
MatSidenavModule,
|
||||
MatIconModule,
|
||||
MatListModule,
|
||||
MatGridListModule,
|
||||
MatDialogModule,
|
||||
MatButtonModule,
|
||||
ReactiveFormsModule,
|
||||
MatDatepickerModule,
|
||||
MatNativeDateModule,
|
||||
],
|
||||
providers: [
|
||||
MatDatepickerModule,
|
||||
// {
|
||||
// provide: HTTP_INTERCEPTORS,
|
||||
// useClass: HttpInterceptorService,
|
||||
// multi: true,
|
||||
// },
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule {
|
||||
constructor(matIconRegistry: MatIconRegistry, domSanitizer: DomSanitizer) {
|
||||
matIconRegistry.addSvgIconSet(
|
||||
domSanitizer.bypassSecurityTrustResourceUrl('./assets/mdi.svg')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<div class="content">
|
||||
<div class="content-header">
|
||||
content header
|
||||
<p>dashboard works!</p>
|
||||
</div>
|
||||
|
||||
<button mat-raised-button color="primary" (click)="addMeterData()">addMeterData</button>
|
||||
|
||||
<mat-grid-list cols="2" rowHeight="400px">
|
||||
<mat-grid-tile>
|
||||
<app-meter-data-wrapper class="full-width" [meterData]="meterDataEnergyDTO"
|
||||
[type]="usageTypes.ENERGY"></app-meter-data-wrapper>
|
||||
</mat-grid-tile>
|
||||
|
||||
<mat-grid-tile>
|
||||
<app-meter-data-wrapper class="full-width" [meterData]="meterDataWaterDTO"
|
||||
[type]="usageTypes.WATER"></app-meter-data-wrapper>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
|
||||
describe('DashboardComponent', () => {
|
||||
let component: DashboardComponent;
|
||||
let fixture: ComponentFixture<DashboardComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ DashboardComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(DashboardComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,113 @@
|
||||
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';
|
||||
|
||||
@Component({
|
||||
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[] = [];
|
||||
|
||||
energyAverageAmountLastYear1Log: number = 0;
|
||||
energyAverageAmountLastYear1Hem: number = 0;
|
||||
waterAverageAmountLastYear: number = 0;
|
||||
|
||||
displayedColumns: string[] = ['date', 'amount', 'meter'];
|
||||
|
||||
constructor(
|
||||
private dataService: DatabaseService,
|
||||
private loaderService: LoaderService,
|
||||
private globalService: GlobalService,
|
||||
private dialog: MatDialog
|
||||
) {
|
||||
this.loadMeterData();
|
||||
}
|
||||
|
||||
loadMeterData(): void {
|
||||
this.loaderService.show();
|
||||
this.dataService.getMeterData().subscribe({
|
||||
next: (data) => {
|
||||
this.splitMeterData(data);
|
||||
this.loaderService.hide();
|
||||
console.log('Meter data:', data);
|
||||
},
|
||||
error: (err) => {
|
||||
this.loaderService.hide();
|
||||
console.error(err);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
splitMeterData(meterData: MeterData[]): void {
|
||||
if (meterData) {
|
||||
meterData.forEach((data) => {
|
||||
if (data.type === this.usageTypes.ENERGY) {
|
||||
this.meterDataEnergy.push(data);
|
||||
} else if (data.type === this.usageTypes.WATER) {
|
||||
this.meterDataWater.push(data);
|
||||
}
|
||||
});
|
||||
this.initEnergyMeterData();
|
||||
this.initWaterMeterDate();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
this.meterDataEnergyDTO = this.meterDataEnergy;
|
||||
}
|
||||
|
||||
initWaterMeterDate(): void {
|
||||
this.meterDataWater = this.globalService.sortMeterData(this.meterDataWater);
|
||||
|
||||
this.meterDataWaterDTO = this.meterDataWater;
|
||||
}
|
||||
|
||||
addMeterData(): void {
|
||||
const dialogRef = this.dialog.open(MeterDataAddDialogComponent);
|
||||
|
||||
dialogRef.afterClosed().subscribe((newMeterData: MeterData) => {
|
||||
console.log({ newMeterData });
|
||||
|
||||
if (newMeterData) {
|
||||
this.dataService.addMeterData(newMeterData).subscribe({
|
||||
next: (meterData: MeterData) => {
|
||||
console.log({ meterData });
|
||||
},
|
||||
error: (err) => {
|
||||
console.log('add meterData error', { err });
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<h1 mat-dialog-title>Neuer Eintrag - Typ: {{usageType}}</h1>
|
||||
<form [formGroup]="form">
|
||||
<div mat-dialog-content>
|
||||
<mat-form-field>
|
||||
<input matInput [matDatepicker]="picker" formControlName="date">
|
||||
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>Meter</mat-label>
|
||||
<mat-select formControlName="meter" (valueChange)="setUsageType($event.name)">
|
||||
<mat-option *ngFor="let el of meters" [value]="el">{{el.name}}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<input matInput type="number" formControlName="amount">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div mat-dialog-actions>
|
||||
<button mat-raised-button color="primary" (click)="submit()">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MeterDataAddDialogComponent } from './meter-data-add-dialog.component';
|
||||
|
||||
describe('MeterDataAddDialogComponent', () => {
|
||||
let component: MeterDataAddDialogComponent;
|
||||
let fixture: ComponentFixture<MeterDataAddDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ MeterDataAddDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MeterDataAddDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { Meter, Meters } from 'src/app/models/Meter';
|
||||
import { MeterData } from 'src/app/models/Meterdata';
|
||||
import { UsageType } from 'src/app/models/UsageType';
|
||||
import { DatabaseService } from 'src/app/services/database.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-meter-data-add-dialog',
|
||||
templateUrl: './meter-data-add-dialog.component.html',
|
||||
styleUrls: ['./meter-data-add-dialog.component.scss'],
|
||||
})
|
||||
export class MeterDataAddDialogComponent implements OnInit {
|
||||
meters: Meter[];
|
||||
usageTypes = UsageType;
|
||||
usageType: UsageType;
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private dialogRef: MatDialogRef<MeterDataAddDialogComponent>,
|
||||
private dataService: DatabaseService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.form = this.fb.group({
|
||||
date: [new Date(), Validators.required],
|
||||
meter: ['', Validators.required],
|
||||
amount: ['', Validators.required],
|
||||
});
|
||||
|
||||
this.dataService.getMeters().subscribe({
|
||||
next: (meters: Meter[]) => {
|
||||
console.log({ meters });
|
||||
this.meters = meters;
|
||||
},
|
||||
error: (err) => {
|
||||
console.log('get meters error', { err });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
submit() {
|
||||
if (this.form.valid) {
|
||||
const formValues = this.form.value;
|
||||
const newMeterData: MeterData = {
|
||||
amount: formValues.amount,
|
||||
date: formValues.date,
|
||||
meter: formValues.meter,
|
||||
type: this.usageType,
|
||||
};
|
||||
|
||||
this.dialogRef.close(newMeterData);
|
||||
}
|
||||
}
|
||||
|
||||
setUsageType(meterName: string): void {
|
||||
if (meterName === Meters['1HEM'] || meterName === Meters['1LOG']) {
|
||||
this.usageType = this.usageTypes.ENERGY;
|
||||
} else if (meterName === Meters.ABWASSER || meterName === Meters.WASSER) {
|
||||
this.usageType = this.usageTypes.WATER;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<div class="header-wrapper">
|
||||
<div class="logo">
|
||||
rossa-tech
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="account">
|
||||
<button mat-button>logout</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HeaderComponent } from './header.component';
|
||||
|
||||
describe('HeaderComponent', () => {
|
||||
let component: HeaderComponent;
|
||||
let fixture: ComponentFixture<HeaderComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ HeaderComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(HeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
10
rossa-tech-cli/src/app/components/header/header.component.ts
Normal file
10
rossa-tech-cli/src/app/components/header/header.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
templateUrl: './header.component.html',
|
||||
styleUrls: ['./header.component.scss']
|
||||
})
|
||||
export class HeaderComponent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// import {
|
||||
// HttpInterceptor,
|
||||
// HttpRequest,
|
||||
// HttpHandler,
|
||||
// HttpEvent,
|
||||
// HttpHeaders,
|
||||
// } from '@angular/common/http';
|
||||
// import { Injectable } from '@angular/core';
|
||||
// import { Observable } from 'rxjs';
|
||||
// import { AuthenticationService } from 'src/app/services/auth.service';
|
||||
|
||||
// @Injectable()
|
||||
// export class HttpInterceptorService implements HttpInterceptor {
|
||||
// constructor(private authenticationService: AuthenticationService) {}
|
||||
|
||||
// intercept(
|
||||
// req: HttpRequest<any>,
|
||||
// next: HttpHandler
|
||||
// ): Observable<HttpEvent<any>> {
|
||||
// console.log(
|
||||
// this.authenticationService.username,
|
||||
// this.authenticationService.password
|
||||
// );
|
||||
// if (
|
||||
// this.authenticationService.isUserLoggedIn() &&
|
||||
// req.url.indexOf('basicauth') === -1
|
||||
// ) {
|
||||
// console.log('if');
|
||||
// const authReq = req.clone({
|
||||
// headers: new HttpHeaders({
|
||||
// 'Content-Type': 'application/json',
|
||||
// Authorization: `Basic ${window.btoa('pezi:Password123!')}`,
|
||||
// // headers: new HttpHeaders({
|
||||
// // 'Content-Type': 'application/json',
|
||||
// // Authorization: `Basic ${window.btoa(
|
||||
// // this.authenticationService.username +
|
||||
// // ':' +
|
||||
// // this.authenticationService.password
|
||||
// // )}`,
|
||||
// }),
|
||||
// });
|
||||
// console.log(authReq);
|
||||
// return next.handle(authReq);
|
||||
// } else {
|
||||
// console.log('else');
|
||||
// return next.handle(req);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="loading-indicator" *ngIf="loaderService.isLoading | async">
|
||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||
</div>
|
||||
@@ -0,0 +1,21 @@
|
||||
/* Absolute Center Spinner */
|
||||
.loading-indicator {
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* Transparent Overlay */
|
||||
.loading-indicator:before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoaderComponent } from './loader.component';
|
||||
|
||||
describe('LoaderComponent', () => {
|
||||
let component: LoaderComponent;
|
||||
let fixture: ComponentFixture<LoaderComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ LoaderComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(LoaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
13
rossa-tech-cli/src/app/components/loader/loader.component.ts
Normal file
13
rossa-tech-cli/src/app/components/loader/loader.component.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { LoaderService } from './loader.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-loader',
|
||||
templateUrl: './loader.component.html',
|
||||
styleUrls: ['./loader.component.scss']
|
||||
})
|
||||
export class LoaderComponent {
|
||||
constructor(public loaderService: LoaderService) {
|
||||
}
|
||||
|
||||
}
|
||||
25
rossa-tech-cli/src/app/components/loader/loader.service.ts
Normal file
25
rossa-tech-cli/src/app/components/loader/loader.service.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LoaderService {
|
||||
/* --- VARIABLEN --- */
|
||||
public isLoading: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(
|
||||
false
|
||||
);
|
||||
|
||||
/* --- CONSTRUCTOR --- */
|
||||
constructor() {
|
||||
}
|
||||
|
||||
/* --- FUNCTIONS --- */
|
||||
show(): void {
|
||||
this.isLoading.next(true);
|
||||
}
|
||||
|
||||
hide(): void {
|
||||
this.isLoading.next(false);
|
||||
}
|
||||
}
|
||||
22
rossa-tech-cli/src/app/components/login/login.component.html
Normal file
22
rossa-tech-cli/src/app/components/login/login.component.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<div class="container col-lg-6">
|
||||
<h1 class="text-center">Login</h1>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form class="form-group">
|
||||
<div class="alert alert-warning" *ngIf='invalidLogin'>{{errorMessage}}</div>
|
||||
<div class="alert alert-success" *ngIf='loginSuccess'>{{successMessage}}</div>
|
||||
<div class="form-group">
|
||||
<label for="email">User Name :</label>
|
||||
<input type="text" class="form-control" id="username" [(ngModel)]="username" placeholder="Enter User Name"
|
||||
name="username">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pwd">Password:</label>
|
||||
<input type="password" class="form-control" [(ngModel)]="password" id="password" placeholder="Enter password"
|
||||
name="password">
|
||||
</div>
|
||||
<button (click)=handleLogin() class="btn btn-success">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoginComponent } from './login.component';
|
||||
|
||||
describe('LoginComponent', () => {
|
||||
let component: LoginComponent;
|
||||
let fixture: ComponentFixture<LoginComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ LoginComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(LoginComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
42
rossa-tech-cli/src/app/components/login/login.component.ts
Normal file
42
rossa-tech-cli/src/app/components/login/login.component.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { AuthenticationService } from 'src/app/services/auth.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: ['./login.component.scss'],
|
||||
})
|
||||
export class LoginComponent implements OnInit {
|
||||
username: string;
|
||||
password: string;
|
||||
errorMessage = 'Invalid Credentials';
|
||||
successMessage: string;
|
||||
invalidLogin = false;
|
||||
loginSuccess = false;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private authenticationService: AuthenticationService
|
||||
) {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
handleLogin() {
|
||||
this.authenticationService
|
||||
.authenticationService(this.username, this.password)
|
||||
.subscribe(
|
||||
(result) => {
|
||||
this.invalidLogin = false;
|
||||
this.loginSuccess = true;
|
||||
this.successMessage = 'Login Successful.';
|
||||
this.router.navigate(['/dashboard']);
|
||||
},
|
||||
() => {
|
||||
this.invalidLogin = true;
|
||||
this.loginSuccess = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<p>logout works!</p>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LogoutComponent } from './logout.component';
|
||||
|
||||
describe('LogoutComponent', () => {
|
||||
let component: LogoutComponent;
|
||||
let fixture: ComponentFixture<LogoutComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ LogoutComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(LogoutComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
10
rossa-tech-cli/src/app/components/logout/logout.component.ts
Normal file
10
rossa-tech-cli/src/app/components/logout/logout.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-logout',
|
||||
templateUrl: './logout.component.html',
|
||||
styleUrls: ['./logout.component.scss']
|
||||
})
|
||||
export class LogoutComponent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<p>meters works!</p>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MetersComponent } from './meters.component';
|
||||
|
||||
describe('MetersComponent', () => {
|
||||
let component: MetersComponent;
|
||||
let fixture: ComponentFixture<MetersComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ MetersComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MetersComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
10
rossa-tech-cli/src/app/components/meters/meters.component.ts
Normal file
10
rossa-tech-cli/src/app/components/meters/meters.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-meters',
|
||||
templateUrl: './meters.component.html',
|
||||
styleUrls: ['./meters.component.scss']
|
||||
})
|
||||
export class MetersComponent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<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>
|
||||
</div>
|
||||
|
||||
|
||||
</ng-container>
|
||||
<ng-template #water>
|
||||
|
||||
|
||||
</ng-template>
|
||||
|
||||
|
||||
<!-- <ng-container *ngIf="amount > 0; else noData">{{amount}} kWh</ng-container>
|
||||
<ng-template #noData>keine Daten vorhanden</ng-template> -->
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ConsumptionLastYearComponent } from './consumption-last-year.component';
|
||||
|
||||
describe('ConsumptionLastYearComponent', () => {
|
||||
let component: ConsumptionLastYearComponent;
|
||||
let fixture: ComponentFixture<ConsumptionLastYearComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ConsumptionLastYearComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ConsumptionLastYearComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,126 @@
|
||||
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';
|
||||
|
||||
@Component({
|
||||
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;
|
||||
|
||||
usageTypes = UsageType;
|
||||
meters = Meters;
|
||||
|
||||
meterDataEnergy1Hem: MeterData[] = [];
|
||||
averageEnergy1Hem: number;
|
||||
|
||||
meterDataEnergy1Log: MeterData[] = [];
|
||||
averageEnergy1Log: number;
|
||||
|
||||
meterDataWasser: MeterData[] = [];
|
||||
averageWasser: number;
|
||||
|
||||
meterDataAbwasser: MeterData[] = [];
|
||||
averageDirtyAbwasser: number;
|
||||
|
||||
constructor(private globalService: GlobalService) {}
|
||||
|
||||
ngOnChanges(): void {
|
||||
if (this.type && this.type === this.usageTypes.ENERGY) {
|
||||
console.log('count energy');
|
||||
|
||||
if (this.meterData) {
|
||||
this.meterData.forEach((data) => {
|
||||
if (data.meter.name === this.meters['1LOG']) {
|
||||
this.meterDataEnergy1Log.push(data);
|
||||
} else if (data.meter.name === this.meters['1HEM']) {
|
||||
this.meterDataEnergy1Hem.push(data);
|
||||
}
|
||||
});
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
this.meterDataEnergy1Log = this.globalService.sortMeterData(
|
||||
this.meterDataEnergy1Log
|
||||
);
|
||||
this.averageEnergy1Log = this.countAverageAmountForYear(
|
||||
this.meterDataEnergy1Log,
|
||||
currentYear - 1
|
||||
);
|
||||
|
||||
this.meterDataEnergy1Hem = this.globalService.sortMeterData(
|
||||
this.meterDataEnergy1Hem
|
||||
);
|
||||
this.averageEnergy1Hem = this.countAverageAmountForYear(
|
||||
this.meterDataEnergy1Hem,
|
||||
currentYear - 1
|
||||
);
|
||||
}
|
||||
} else if (this.type && this.type === this.usageTypes.WATER) {
|
||||
console.log('count water');
|
||||
|
||||
if (this.meterData) {
|
||||
this.meterData.forEach((data) => {
|
||||
if (data.meter.name === this.meters['WASSER']) {
|
||||
this.meterDataWasser.push(data);
|
||||
} else if (data.meter.name === this.meters['ABWASSER']) {
|
||||
this.meterDataAbwasser.push(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// countAverageAmountForLastYear(meterData: MeterData[]): number {
|
||||
// const currentYear = new Date().getFullYear();
|
||||
|
||||
// let lastYear = meterData.filter(
|
||||
// (data) => new Date(data.date).getFullYear() === currentYear - 1
|
||||
// );
|
||||
|
||||
// lastYear = this.globalService.sortMeterData(lastYear);
|
||||
// if (lastYear.length > 0) {
|
||||
// const end = lastYear[0];
|
||||
|
||||
// const startIdx =
|
||||
// meterData.findIndex((el) => el === lastYear[lastYear.length - 1]) + 1;
|
||||
// const start = meterData[startIdx];
|
||||
|
||||
// console.log({ end: end.amount, startIdx, startAm: start.amount, start });
|
||||
|
||||
// return end.amount - start.amount;
|
||||
// }
|
||||
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
/* FOR TEST*/
|
||||
countAverageAmountForYear(meterData: MeterData[], year: number): number {
|
||||
// const currentYear = new Date().getFullYear();
|
||||
|
||||
let filteredData = meterData.filter(
|
||||
(data) => new Date(data.date).getFullYear() === year
|
||||
);
|
||||
|
||||
filteredData = this.globalService.sortMeterData(filteredData);
|
||||
if (filteredData.length > 0) {
|
||||
const end = filteredData[0];
|
||||
|
||||
const startIdx =
|
||||
meterData.findIndex(
|
||||
(el) => el === filteredData[filteredData.length - 1]
|
||||
) + 1;
|
||||
const start = meterData[startIdx];
|
||||
|
||||
console.log({ end: end.amount, startIdx, startAm: start.amount, start });
|
||||
|
||||
return end.amount - start.amount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<h2>{{type}}</h2>
|
||||
|
||||
<div class="meter-data-list-wrapper">
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||
|
||||
<ng-container matColumnDef="id">
|
||||
<th mat-header-cell *matHeaderCellDef> id </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.id}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="date">
|
||||
<th mat-header-cell *matHeaderCellDef> date </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.date | date:
|
||||
"dd.MM.y"}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef> amount </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.amount}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="meter">
|
||||
<th mat-header-cell *matHeaderCellDef> meter </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.meter.name}} </td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MeterDataListComponent } from './meter-data-list.component';
|
||||
|
||||
describe('MeterDataListComponent', () => {
|
||||
let component: MeterDataListComponent;
|
||||
let fixture: ComponentFixture<MeterDataListComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ MeterDataListComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MeterDataListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,108 @@
|
||||
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';
|
||||
|
||||
@Component({
|
||||
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;
|
||||
|
||||
displayedColumns: string[] = ['id', 'date', 'amount', 'meter'];
|
||||
|
||||
dataSource = new MatTableDataSource<MeterData>();
|
||||
// dataSource = [
|
||||
// {
|
||||
// id: 1,
|
||||
// type: 'WATER',
|
||||
// date: '2023-03-24T08:47:52.000+0000',
|
||||
// amount: 2224,
|
||||
// meter: {
|
||||
// id: 1,
|
||||
// name: '1LOG',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: 3,
|
||||
// type: 'ENERGY',
|
||||
// date: '2023-03-24T08:47:52.000+0000',
|
||||
// amount: 2224,
|
||||
// meter: {
|
||||
// id: 1,
|
||||
// name: '1LOG',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: 1,
|
||||
// type: 'WATER',
|
||||
// date: '2023-03-24T08:47:52.000+0000',
|
||||
// amount: 2224,
|
||||
// meter: {
|
||||
// id: 1,
|
||||
// name: '1LOG',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: 3,
|
||||
// type: 'ENERGY',
|
||||
// date: '2023-03-24T08:47:52.000+0000',
|
||||
// amount: 2224,
|
||||
// meter: {
|
||||
// id: 1,
|
||||
// name: '1LOG',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: 1,
|
||||
// type: 'WATER',
|
||||
// date: '2023-03-24T08:47:52.000+0000',
|
||||
// amount: 2224,
|
||||
// meter: {
|
||||
// id: 1,
|
||||
// name: '1LOG',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: 3,
|
||||
// type: 'ENERGY',
|
||||
// date: '2023-03-24T08:47:52.000+0000',
|
||||
// amount: 2224,
|
||||
// meter: {
|
||||
// id: 1,
|
||||
// name: '1LOG',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: 1,
|
||||
// type: 'WATER',
|
||||
// date: '2023-03-24T08:47:52.000+0000',
|
||||
// amount: 2224,
|
||||
// meter: {
|
||||
// id: 1,
|
||||
// name: '1LOG',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: 3,
|
||||
// type: 'ENERGY',
|
||||
// date: '2023-03-24T08:47:52.000+0000',
|
||||
// amount: 2224,
|
||||
// meter: {
|
||||
// id: 1,
|
||||
// name: '1LOG',
|
||||
// },
|
||||
// },
|
||||
// ];
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnInit(): void {}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.dataSource = new MatTableDataSource(this.meterData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<app-consumption-last-year [meterData]="meterData" [type]="type"></app-consumption-last-year>
|
||||
|
||||
<app-meter-data-list [meterData]="meterData" [type]="type"></app-meter-data-list>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MeterDataWrapperComponent } from './meter-data-wrapper.component';
|
||||
|
||||
describe('MeterDataWrapperComponent', () => {
|
||||
let component: MeterDataWrapperComponent;
|
||||
let fixture: ComponentFixture<MeterDataWrapperComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ MeterDataWrapperComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MeterDataWrapperComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
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';
|
||||
|
||||
@Component({
|
||||
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;
|
||||
|
||||
// usageTypes = UsageType;
|
||||
// averageConsumptionLastYear: number;
|
||||
|
||||
constructor() {}
|
||||
|
||||
// ngOnChanges(): void {
|
||||
// this.averageConsumptionLastYear = this.countAverageAmountForLastYear(
|
||||
// this.meterData
|
||||
// );
|
||||
// }
|
||||
}
|
||||
1
rossa-tech-cli/src/app/constants.ts
Normal file
1
rossa-tech-cli/src/app/constants.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const METERS = ['1LOG', '1HEM', 'WASSER', 'ABWASSER'];
|
||||
16
rossa-tech-cli/src/app/models/Meter.ts
Normal file
16
rossa-tech-cli/src/app/models/Meter.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export class Meter {
|
||||
id: number;
|
||||
name: '1LOG' | '1HEM' | 'WASSER' | 'ABWASSER';
|
||||
|
||||
constructor(id: number, name: '1LOG' | '1HEM' | 'WASSER' | 'ABWASSER') {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
export enum Meters {
|
||||
'1LOG' = '1LOG',
|
||||
'1HEM' = '1HEM',
|
||||
'WASSER' = 'WASSER',
|
||||
'ABWASSER' = 'ABWASSER',
|
||||
}
|
||||
22
rossa-tech-cli/src/app/models/Meterdata.ts
Normal file
22
rossa-tech-cli/src/app/models/Meterdata.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Meter } from './Meter';
|
||||
export class MeterData {
|
||||
id?: number;
|
||||
type: 'ENERGY' | 'WATER';
|
||||
date: Date;
|
||||
amount: number;
|
||||
meter: Meter;
|
||||
|
||||
constructor(
|
||||
type: 'ENERGY' | 'WATER',
|
||||
date: Date,
|
||||
amount: number,
|
||||
meter: Meter,
|
||||
id?: number
|
||||
) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.date = date;
|
||||
this.amount = amount;
|
||||
this.meter = meter;
|
||||
}
|
||||
}
|
||||
4
rossa-tech-cli/src/app/models/UsageType.ts
Normal file
4
rossa-tech-cli/src/app/models/UsageType.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export enum UsageType {
|
||||
ENERGY = 'ENERGY',
|
||||
WATER = 'WATER'
|
||||
}
|
||||
15
rossa-tech-cli/src/app/models/info.md
Normal file
15
rossa-tech-cli/src/app/models/info.md
Normal file
@@ -0,0 +1,15 @@
|
||||
CREATE TABLE meter (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE meterdata (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
type ENUM('energy', 'water') NOT NULL,
|
||||
date DATETIME NOT NULL,
|
||||
amount FLOAT NOT NULL,
|
||||
meter_id INT NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (meter_id) REFERENCES meter(id)
|
||||
);
|
||||
16
rossa-tech-cli/src/app/services/auth.service.spec.ts
Normal file
16
rossa-tech-cli/src/app/services/auth.service.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
describe('AuthService', () => {
|
||||
let service: AuthService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(AuthService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
65
rossa-tech-cli/src/app/services/auth.service.ts
Normal file
65
rossa-tech-cli/src/app/services/auth.service.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AuthenticationService {
|
||||
// BASE_PATH: 'http://localhost:8080'
|
||||
USER_NAME_SESSION_ATTRIBUTE_NAME = 'authenticatedUser';
|
||||
|
||||
public username: string | undefined;
|
||||
public password: string | undefined;
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
authenticationService(username: string, password: string) {
|
||||
// return this.http
|
||||
// .get(`http://localhost:8080/authenticate`, {
|
||||
// // .get(`http://localhost:8080/`, {
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json',
|
||||
// Authorization: this.createBasicAuthToken(username, password),
|
||||
// },
|
||||
// })
|
||||
return this.http
|
||||
.post<any>('http://localhost:8080/hello', {
|
||||
userName: username,
|
||||
userPass: password,
|
||||
})
|
||||
.pipe(
|
||||
map((res) => {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.registerSuccessfulLogin(username, password);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
createBasicAuthToken(username: string, password: string) {
|
||||
return 'Basic ' + window.btoa(username + ':' + password);
|
||||
}
|
||||
|
||||
registerSuccessfulLogin(username: string, password: string) {
|
||||
sessionStorage.setItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME, username);
|
||||
}
|
||||
|
||||
logout() {
|
||||
sessionStorage.removeItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME);
|
||||
this.username = undefined;
|
||||
this.password = undefined;
|
||||
}
|
||||
|
||||
isUserLoggedIn() {
|
||||
let user = sessionStorage.getItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME);
|
||||
if (user === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
getLoggedInUserName() {
|
||||
let user = sessionStorage.getItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME);
|
||||
if (user === undefined) return '';
|
||||
return user;
|
||||
}
|
||||
}
|
||||
16
rossa-tech-cli/src/app/services/database.service.spec.ts
Normal file
16
rossa-tech-cli/src/app/services/database.service.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DatabaseService } from './database.service';
|
||||
|
||||
describe('DatabaseService', () => {
|
||||
let service: DatabaseService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(DatabaseService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
55
rossa-tech-cli/src/app/services/database.service.ts
Normal file
55
rossa-tech-cli/src/app/services/database.service.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { MeterData } from './../models/Meterdata';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { Meter } from 'src/app/models/Meter';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class DatabaseService {
|
||||
private baseUrl = environment.hostUrl + '/v1';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getMeterData(): Observable<MeterData[]> {
|
||||
const url = `${this.baseUrl}/meter-data`;
|
||||
return this.http.get<MeterData[]>(url).pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
getMeterDataByType(usageType: string): Observable<MeterData[]> {
|
||||
const url = `${this.baseUrl}/meter-data?usageType=${usageType}`;
|
||||
return this.http.get<MeterData[]>(url).pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
addMeterData(meterData: MeterData): Observable<MeterData> {
|
||||
const url = `${this.baseUrl}/meter-data`;
|
||||
return this.http
|
||||
.post<MeterData>(url, meterData)
|
||||
.pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
getMeters(): Observable<Meter[]> {
|
||||
const url = `${this.baseUrl}/meters`;
|
||||
return this.http.get<Meter[]>(url).pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
private handleError(error: HttpErrorResponse): Observable<never> {
|
||||
// https://stackoverflow.com/questions/68655492/throwerrorerror-is-now-deprecated-but-there-is-no-new-errorhttperrorresponse
|
||||
|
||||
if (error.error instanceof ErrorEvent) {
|
||||
// A client-side or network error occurred. Handle it accordingly.
|
||||
console.error('An error occurred:', error.error.message);
|
||||
} else {
|
||||
// The backend returned an unsuccessful response code.
|
||||
// The response body may contain clues as to what went wrong.
|
||||
console.error(
|
||||
`Backend returned code ${error.status}, ` + `body was: ${error.error}`
|
||||
);
|
||||
}
|
||||
// Return an observable with a user-facing error message.
|
||||
return throwError(() => error);
|
||||
}
|
||||
}
|
||||
16
rossa-tech-cli/src/app/services/global.service.spec.ts
Normal file
16
rossa-tech-cli/src/app/services/global.service.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GlobalService } from './global.service';
|
||||
|
||||
describe('GlobalService', () => {
|
||||
let service: GlobalService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(GlobalService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
20
rossa-tech-cli/src/app/services/global.service.ts
Normal file
20
rossa-tech-cli/src/app/services/global.service.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MeterData } from '../models/Meterdata';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class GlobalService {
|
||||
constructor() {}
|
||||
|
||||
sortMeterData(meterData: MeterData[]): MeterData[] {
|
||||
if (meterData.length > 0) {
|
||||
meterData.sort(
|
||||
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
|
||||
);
|
||||
return meterData;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TokenStorageService } from './token-storage.service';
|
||||
|
||||
describe('TokenStorageService', () => {
|
||||
let service: TokenStorageService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(TokenStorageService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
9
rossa-tech-cli/src/app/services/token-storage.service.ts
Normal file
9
rossa-tech-cli/src/app/services/token-storage.service.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TokenStorageService {
|
||||
|
||||
constructor() { }
|
||||
}
|
||||
16
rossa-tech-cli/src/app/services/user.service.spec.ts
Normal file
16
rossa-tech-cli/src/app/services/user.service.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UserService } from './user.service';
|
||||
|
||||
describe('UserService', () => {
|
||||
let service: UserService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(UserService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
9
rossa-tech-cli/src/app/services/user.service.ts
Normal file
9
rossa-tech-cli/src/app/services/user.service.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UserService {
|
||||
|
||||
constructor() { }
|
||||
}
|
||||
0
rossa-tech-cli/src/assets/.gitkeep
Normal file
0
rossa-tech-cli/src/assets/.gitkeep
Normal file
5
rossa-tech-cli/src/environments/environment.prod.ts
Normal file
5
rossa-tech-cli/src/environments/environment.prod.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export const environment = {
|
||||
production: true,
|
||||
env: 'prod',
|
||||
hostUrl: 'http://192.168.178.21:8182/api',
|
||||
};
|
||||
17
rossa-tech-cli/src/environments/environment.ts
Normal file
17
rossa-tech-cli/src/environments/environment.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
// This file can be replaced during build by using the `fileReplacements` array.
|
||||
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
export const environment = {
|
||||
production: true,
|
||||
env: 'prod',
|
||||
hostUrl: 'http://localhost:8080/',
|
||||
};
|
||||
/*
|
||||
* For easier debugging in development mode, you can import the following file
|
||||
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
|
||||
*
|
||||
* This import should be commented out in production mode because it will have a negative impact
|
||||
* on performance if an error is thrown.
|
||||
*/
|
||||
import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
||||
BIN
rossa-tech-cli/src/favicon.ico
Normal file
BIN
rossa-tech-cli/src/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 948 B |
17
rossa-tech-cli/src/index.html
Normal file
17
rossa-tech-cli/src/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>RossaTechCli</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||
</head>
|
||||
|
||||
<body class="mat-typography">
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
7
rossa-tech-cli/src/main.ts
Normal file
7
rossa-tech-cli/src/main.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
||||
8
rossa-tech-cli/src/proxy.conf.json
Normal file
8
rossa-tech-cli/src/proxy.conf.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"/api": {
|
||||
"target": "http://localhost:8080",
|
||||
"secure": false,
|
||||
"changeOrigin": true,
|
||||
"logLevel": "debug"
|
||||
}
|
||||
}
|
||||
446
rossa-tech-cli/src/styles.scss
Normal file
446
rossa-tech-cli/src/styles.scss
Normal file
@@ -0,0 +1,446 @@
|
||||
@use '@angular/material' as mat;
|
||||
|
||||
@import 'https://fonts.googleapis.com/icon?family=Material+Icons';
|
||||
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500&display=swap');
|
||||
|
||||
$mat-primary: (
|
||||
50: #e0edf7,
|
||||
100: #b3d2ec,
|
||||
200: #80b4df,
|
||||
300: #4d96d2,
|
||||
400: #2680c9,
|
||||
500: #0069bf,
|
||||
600: #0061b9,
|
||||
700: #0056b1,
|
||||
800: #004ca9,
|
||||
900: #003b9b,
|
||||
A100: #c6d7ff,
|
||||
A200: #93b3ff,
|
||||
A400: #6090ff,
|
||||
A700: #477eff,
|
||||
contrast: (
|
||||
50: #333333,
|
||||
100: #333333,
|
||||
200: #333333,
|
||||
300: #333333,
|
||||
400: #ffffff,
|
||||
500: #ffffff,
|
||||
600: #ffffff,
|
||||
700: #ffffff,
|
||||
800: #ffffff,
|
||||
900: #ffffff,
|
||||
A100: #333333,
|
||||
A200: #333333,
|
||||
A400: #333333,
|
||||
A700: #ffffff,
|
||||
),
|
||||
);
|
||||
|
||||
$mat-accent: (
|
||||
50: #f1f8e5,
|
||||
100: #ddedbf,
|
||||
200: #c6e194,
|
||||
300: #afd469,
|
||||
400: #9dcb49,
|
||||
500: #8cc229,
|
||||
600: #84bc24,
|
||||
700: #79b41f,
|
||||
800: #6fac19,
|
||||
900: #5c9f0f,
|
||||
A100: #e7ffcf,
|
||||
A200: #cdff9c,
|
||||
A400: #b3ff69,
|
||||
A700: #a6ff4f,
|
||||
contrast: (
|
||||
50: #333333,
|
||||
100: #333333,
|
||||
200: #333333,
|
||||
300: #333333,
|
||||
400: #333333,
|
||||
500: #333333,
|
||||
600: #333333,
|
||||
700: #333333,
|
||||
800: #333333,
|
||||
900: #ffffff,
|
||||
A100: #333333,
|
||||
A200: #333333,
|
||||
A400: #333333,
|
||||
A700: #333333,
|
||||
),
|
||||
);
|
||||
|
||||
$mat-warn: (
|
||||
50: #fde8e8,
|
||||
100: #f9c6c6,
|
||||
200: #f6a0a0,
|
||||
300: #f27a7a,
|
||||
400: #ef5e5e,
|
||||
500: #ec4141,
|
||||
600: #ea3b3b,
|
||||
700: #e73232,
|
||||
800: #e42a2a,
|
||||
900: #df1c1c,
|
||||
A100: #ffffff,
|
||||
A200: #ffe0e0,
|
||||
A400: #ffadad,
|
||||
A700: #ff9494,
|
||||
contrast: (
|
||||
50: #333333,
|
||||
100: #333333,
|
||||
200: #333333,
|
||||
300: #333333,
|
||||
400: #333333,
|
||||
500: #ffffff,
|
||||
600: #ffffff,
|
||||
700: #ffffff,
|
||||
800: #ffffff,
|
||||
900: #ffffff,
|
||||
A100: #333333,
|
||||
A200: #333333,
|
||||
A400: #333333,
|
||||
A700: #333333,
|
||||
),
|
||||
);
|
||||
|
||||
// http://material-angular-dashboard.creativeit.io/
|
||||
|
||||
// define-typography-level(font-size, line-height, font-weight, letter-spacing)
|
||||
$typography: mat.define-typography-config(
|
||||
$font-family: 'Open Sans',
|
||||
$body-1: mat.define-typography-level(14px, 20px, 400, $letter-spacing: normal),
|
||||
$button: mat.define-typography-level(16px, 20px, 400, $letter-spacing: normal),
|
||||
);
|
||||
|
||||
// $fontConfig: (
|
||||
// display-4: mat.define-typography-level(112px, 112px, 300, 'Open Sans', -0.0134em),
|
||||
// display-3: mat.define-typography-level(56px, 56px, 400, 'Open Sans', -0.0089em),
|
||||
// display-2: mat.define-typography-level(45px, 48px, 400, 'Open Sans', 0.0000em),
|
||||
// display-1: mat.define-typography-level(34px, 40px, 400, 'Open Sans', 0.0074em),
|
||||
// headline: mat.define-typography-level(24px, 32px, 400, 'Open Sans', 0.0000em),
|
||||
// title: mat.define-typography-level(20px, 32px, 500, 'Open Sans', 0.0075em),
|
||||
// subheading-2: mat.define-typography-level(16px, 28px, 400, 'Open Sans', 0.0094em),
|
||||
// subheading-1: mat.define-typography-level(15px, 24px, 500, 'Open Sans', 0.0067em),
|
||||
// body-2: mat.define-typography-level(14px, 24px, 500, 'Open Sans', 0.0179em),
|
||||
// body-1: mat.define-typography-level(14px, 20px, 400, 'Open Sans', 0.0179em),
|
||||
// button: mat.define-typography-level(14px, 14px, 500, 'Open Sans', 0.0893em),
|
||||
// caption: mat.define-typography-level(12px, 20px, 400, 'Open Sans', 0.0333em),
|
||||
// input: mat.define-typography-level(inherit, 1.125, 400, 'Open Sans', 1.5px)
|
||||
// );
|
||||
|
||||
$primary: mat.define-palette($mat-primary);
|
||||
$accent: mat.define-palette($mat-accent);
|
||||
$warn: mat.define-palette($mat-warn);
|
||||
|
||||
$theme: mat.define-light-theme(
|
||||
(
|
||||
color: (
|
||||
primary: $primary,
|
||||
accent: $accent,
|
||||
warn: $warn,
|
||||
),
|
||||
typography: $typography,
|
||||
)
|
||||
);
|
||||
|
||||
@include mat.core();
|
||||
@include mat.core-theme($theme);
|
||||
@include mat.all-component-themes($theme);
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
background-color: #2f2f2f;
|
||||
color: #ffffffcc;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
//prevent scroll on dialog open
|
||||
html.cdk-global-scrollblock {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
// margin: 0;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
// height: 100vh;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.mat-grid-tile-content {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.header-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
|
||||
height: 56px;
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
// grid list
|
||||
div.mat-grid-tile-content {
|
||||
align-items: unset;
|
||||
}
|
||||
|
||||
//meter-data-list
|
||||
.meter-data-list-wrapper {
|
||||
height: 270px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
/*--------------------------------------------------*/
|
||||
|
||||
// /**
|
||||
// * Generated theme by Material Theme Generator
|
||||
// * https://materialtheme.arcsine.dev
|
||||
// * Fork at: https://materialtheme.arcsine.dev/?c=YHBhbGV0dGU$YHByaW1hcnk$YF48IzQ0NDQ0NCIsIj9lcjwjYzdjN2M3IiwiO2VyPCMyZDJkMmR$LCIlPmBePCMyYTdhYWIiLCI~ZXI8I2JmZDdlNiIsIjtlcjwjMTk1ZDkxfiwid2Fybj5gXjwjZjE4ZTU0IiwiP2VyPCNmYmRkY2MiLCI7ZXI8I2ViNzEzYX4sIj9UZXh0PCMyYzJjMmMiLCI~PTwjZTllNGU0IiwiO1RleHQ8I2U5ZTRlNCIsIjs9PCMyYzJjMmN$LCJmb250cz5bYEA8KC00IiwiZmFtaWx5PE9wZW4gU2Fuc34sYEA8KC0zIiwiZmFtaWx5PE9wZW4gU2Fuc34sYEA8KC0yIiwiZmFtaWx5PE9wZW4gU2Fuc34sYEA8KC0xIiwiZmFtaWx5PE9wZW4gU2Fuc34sYEA8aGVhZGxpbmUiLCJmYW1pbHk8T3BlbiBTYW5zfixgQDx0aXRsZSIsImZhbWlseTxPcGVuIFNhbnN$LGBAPHN1YiktMiIsImZhbWlseTxPcGVuIFNhbnN$LGBAPHN1YiktMSIsImZhbWlseTxPcGVuIFNhbnN$LGBAPGJvZHktMiIsImZhbWlseTxPcGVuIFNhbnN$LGBAPGJvZHktMSIsImZhbWlseTxPcGVuIFNhbnN$LGBAPGJ1dHRvbiIsImZhbWlseTxPcGVuIFNhbnN$LGBAPGNhcHRpb24iLCJmYW1pbHk8T3BlbiBTYW5zfixgQDxpbnB1dCIsImZhbWlseTxPcGVuIFNhbnMiLCJzaXplPm51bGx9XSwiaWNvbnM8RmlsbGVkIiwiP25lc3M$ZmFsc2UsInZlcnNpb24$MTN9
|
||||
// */
|
||||
|
||||
// @use '@angular/material' as mat;
|
||||
|
||||
// // Include the common styles for Angular Material. We include this here so that you only
|
||||
// // have to load a single css file for Angular Material in your app.
|
||||
|
||||
// // Fonts
|
||||
|
||||
// // Foreground Elements
|
||||
|
||||
// // Light Theme Text
|
||||
// $dark-text: #2c2c2c;
|
||||
// $dark-primary-text: rgba($dark-text, 0.87);
|
||||
// $dark-accent-text: rgba($dark-primary-text, 0.54);
|
||||
// $dark-disabled-text: rgba($dark-primary-text, 0.38);
|
||||
// $dark-dividers: rgba($dark-primary-text, 0.12);
|
||||
// $dark-focused: rgba($dark-primary-text, 0.12);
|
||||
|
||||
// $mat-light-theme-foreground: (
|
||||
// base: black,
|
||||
// divider: $dark-dividers,
|
||||
// dividers: $dark-dividers,
|
||||
// disabled: $dark-disabled-text,
|
||||
// disabled-button: rgba($dark-text, 0.26),
|
||||
// disabled-text: $dark-disabled-text,
|
||||
// elevation: black,
|
||||
// secondary-text: $dark-accent-text,
|
||||
// hint-text: $dark-disabled-text,
|
||||
// accent-text: $dark-accent-text,
|
||||
// icon: $dark-accent-text,
|
||||
// icons: $dark-accent-text,
|
||||
// text: $dark-primary-text,
|
||||
// slider-min: $dark-primary-text,
|
||||
// slider-off: rgba($dark-text, 0.26),
|
||||
// slider-off-active: $dark-disabled-text,
|
||||
// );
|
||||
|
||||
// // Dark Theme text
|
||||
// $light-text: #e9e4e4;
|
||||
// $light-primary-text: $light-text;
|
||||
// $light-accent-text: rgba($light-primary-text, 0.7);
|
||||
// $light-disabled-text: rgba($light-primary-text, 0.5);
|
||||
// $light-dividers: rgba($light-primary-text, 0.12);
|
||||
// $light-focused: rgba($light-primary-text, 0.12);
|
||||
|
||||
// $mat-dark-theme-foreground: (
|
||||
// base: $light-text,
|
||||
// divider: $light-dividers,
|
||||
// dividers: $light-dividers,
|
||||
// disabled: $light-disabled-text,
|
||||
// disabled-button: rgba($light-text, 0.3),
|
||||
// disabled-text: $light-disabled-text,
|
||||
// elevation: black,
|
||||
// hint-text: $light-disabled-text,
|
||||
// secondary-text: $light-accent-text,
|
||||
// accent-text: $light-accent-text,
|
||||
// icon: $light-text,
|
||||
// icons: $light-text,
|
||||
// text: $light-text,
|
||||
// slider-min: $light-text,
|
||||
// slider-off: rgba($light-text, 0.3),
|
||||
// slider-off-active: rgba($light-text, 0.3),
|
||||
// );
|
||||
|
||||
// // Background config
|
||||
// // Light bg
|
||||
// $light-background: #e9e4e4;
|
||||
// $light-bg-darker-5: darken($light-background, 5%);
|
||||
// $light-bg-darker-10: darken($light-background, 10%);
|
||||
// $light-bg-darker-20: darken($light-background, 20%);
|
||||
// $light-bg-darker-30: darken($light-background, 30%);
|
||||
// $light-bg-lighter-5: lighten($light-background, 5%);
|
||||
// $dark-bg-tooltip: lighten(#2c2c2c, 20%);
|
||||
// $dark-bg-alpha-4: rgba(#2c2c2c, 0.04);
|
||||
// $dark-bg-alpha-12: rgba(#2c2c2c, 0.12);
|
||||
|
||||
// $mat-light-theme-background: (
|
||||
// background: $light-background,
|
||||
// status-bar: $light-bg-darker-20,
|
||||
// app-bar: $light-bg-darker-5,
|
||||
// hover: $dark-bg-alpha-4,
|
||||
// card: $light-bg-lighter-5,
|
||||
// dialog: $light-bg-lighter-5,
|
||||
// tooltip: $dark-bg-tooltip,
|
||||
// disabled-button: $dark-bg-alpha-12,
|
||||
// raised-button: $light-bg-lighter-5,
|
||||
// focused-button: $dark-focused,
|
||||
// selected-button: $light-bg-darker-20,
|
||||
// selected-disabled-button: $light-bg-darker-30,
|
||||
// disabled-button-toggle: $light-bg-darker-10,
|
||||
// unselected-chip: $light-bg-darker-10,
|
||||
// disabled-list-option: $light-bg-darker-10,
|
||||
// );
|
||||
|
||||
// // Dark bg
|
||||
// $dark-background: #2c2c2c;
|
||||
// $dark-bg-lighter-5: lighten($dark-background, 5%);
|
||||
// $dark-bg-lighter-10: lighten($dark-background, 10%);
|
||||
// $dark-bg-lighter-20: lighten($dark-background, 20%);
|
||||
// $dark-bg-lighter-30: lighten($dark-background, 30%);
|
||||
// $light-bg-alpha-4: rgba(#e9e4e4, 0.04);
|
||||
// $light-bg-alpha-12: rgba(#e9e4e4, 0.12);
|
||||
|
||||
// // Background palette for dark themes.
|
||||
// $mat-dark-theme-background: (
|
||||
// background: $dark-background,
|
||||
// status-bar: $dark-bg-lighter-20,
|
||||
// app-bar: $dark-bg-lighter-5,
|
||||
// hover: $light-bg-alpha-4,
|
||||
// card: $dark-bg-lighter-5,
|
||||
// dialog: $dark-bg-lighter-5,
|
||||
// tooltip: $dark-bg-lighter-20,
|
||||
// disabled-button: $light-bg-alpha-12,
|
||||
// raised-button: $dark-bg-lighter-5,
|
||||
// focused-button: $light-focused,
|
||||
// selected-button: $dark-bg-lighter-20,
|
||||
// selected-disabled-button: $dark-bg-lighter-30,
|
||||
// disabled-button-toggle: $dark-bg-lighter-10,
|
||||
// unselected-chip: $dark-bg-lighter-20,
|
||||
// disabled-list-option: $dark-bg-lighter-10,
|
||||
// );
|
||||
|
||||
// // Compute font config
|
||||
// @include mat.core();
|
||||
// // @include mat.core($fontConfig);
|
||||
|
||||
// // Theme Config
|
||||
|
||||
// body {
|
||||
// --primary-color: #444444;
|
||||
// --primary-lighter-color: #c7c7c7;
|
||||
// --primary-darker-color: #2d2d2d;
|
||||
// --text-primary-color: #{$light-primary-text};
|
||||
// --text-primary-lighter-color: #{$dark-primary-text};
|
||||
// --text-primary-darker-color: #{$light-primary-text};
|
||||
// }
|
||||
// $mat-primary: (
|
||||
// main: #444444,
|
||||
// lighter: #c7c7c7,
|
||||
// darker: #2d2d2d,
|
||||
// 200: #444444, // For slide toggle,
|
||||
// contrast : (
|
||||
// main: $light-primary-text,
|
||||
// lighter: $dark-primary-text,
|
||||
// darker: $light-primary-text,
|
||||
// )
|
||||
// );
|
||||
// $theme-primary: mat.define-palette($mat-primary, main, lighter, darker);
|
||||
|
||||
// body {
|
||||
// --accent-color: #2a7aab;
|
||||
// --accent-lighter-color: #bfd7e6;
|
||||
// --accent-darker-color: #195d91;
|
||||
// --text-accent-color: #{$light-primary-text};
|
||||
// --text-accent-lighter-color: #{$dark-primary-text};
|
||||
// --text-accent-darker-color: #{$light-primary-text};
|
||||
// }
|
||||
// $mat-accent: (
|
||||
// main: #2a7aab,
|
||||
// lighter: #bfd7e6,
|
||||
// darker: #195d91,
|
||||
// 200: #2a7aab, // For slide toggle,
|
||||
// contrast : (
|
||||
// main: $light-primary-text,
|
||||
// lighter: $dark-primary-text,
|
||||
// darker: $light-primary-text,
|
||||
// )
|
||||
// );
|
||||
// $theme-accent: mat.define-palette($mat-accent, main, lighter, darker);
|
||||
|
||||
// body {
|
||||
// --warn-color: #f18e54;
|
||||
// --warn-lighter-color: #fbddcc;
|
||||
// --warn-darker-color: #eb713a;
|
||||
// --text-warn-color: #{$dark-primary-text};
|
||||
// --text-warn-lighter-color: #{$dark-primary-text};
|
||||
// --text-warn-darker-color: #{$dark-primary-text};
|
||||
// }
|
||||
// $mat-warn: (
|
||||
// main: #f18e54,
|
||||
// lighter: #fbddcc,
|
||||
// darker: #eb713a,
|
||||
// 200: #f18e54, // For slide toggle,
|
||||
// contrast : (
|
||||
// main: $dark-primary-text,
|
||||
// lighter: $dark-primary-text,
|
||||
// darker: $dark-primary-text,
|
||||
// )
|
||||
// );
|
||||
// $theme-warn: mat.define-palette($mat-warn, main, lighter, darker);
|
||||
// ;
|
||||
|
||||
// $theme: (
|
||||
// primary: $theme-primary,
|
||||
// accent: $theme-accent,
|
||||
// warn: $theme-warn,
|
||||
// is-dark: true,
|
||||
// foreground: $mat-dark-theme-foreground,
|
||||
// background: $mat-dark-theme-background,
|
||||
// );
|
||||
// $altTheme: (
|
||||
// primary: $theme-primary,
|
||||
// accent: $theme-accent,
|
||||
// warn: $theme-warn,
|
||||
// is-dark: false,
|
||||
// foreground: $mat-light-theme-foreground,
|
||||
// background: $mat-light-theme-background,
|
||||
// );
|
||||
|
||||
// // Theme Init
|
||||
// @include mat.all-component-themes($theme);
|
||||
|
||||
// .theme-alternate {
|
||||
// @include mat.all-component-themes($altTheme);
|
||||
// }
|
||||
|
||||
// // Specific component overrides, pieces that are not in line with the general theming
|
||||
|
||||
// // Handle buttons appropriately, with respect to line-height
|
||||
// .mat-raised-button, .mat-stroked-button, .mat-flat-button {
|
||||
// padding: 0 1.15em;
|
||||
// margin: 0 .65em;
|
||||
// min-width: 3em;
|
||||
// line-height: 36.4px
|
||||
// }
|
||||
|
||||
// .mat-standard-chip {
|
||||
// padding: .5em .85em;
|
||||
// min-height: 2.5em;
|
||||
// }
|
||||
|
||||
// .material-icons {
|
||||
// font-size: 24px;
|
||||
// font-family: 'Material Icons', 'Material Icons';
|
||||
// .mat-badge-content {
|
||||
// font-family: 'Open Sans';
|
||||
// }
|
||||
// }
|
||||
Reference in New Issue
Block a user