localStorage: locationId, energyPercent, locationConfig
This commit is contained in:
parent
aa71616961
commit
20bb84da63
@ -1,14 +1,22 @@
|
|||||||
<div class="MainMenu NoUserSelect">
|
<div class="MainMenu NoUserSelect">
|
||||||
<div class="MainMenuBar">
|
<div class="MainMenuBar">
|
||||||
|
|
||||||
<div class="MainMenuItem MainMenuButton" (click)="showDrawer = !showDrawer">
|
<div class="MainMenuItem MainMenuButton" (click)="showDrawer = !showDrawer">
|
||||||
<fa-icon [icon]="faBars"></fa-icon>
|
<fa-icon [icon]="faBars"></fa-icon>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="MainMenuItem MainMenuTitle">
|
<div class="MainMenuItem MainMenuTitle">
|
||||||
{{ menuService.title }}
|
{{ menuService.title }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="MainMenuItem" routerLink="/Settings">
|
||||||
|
<fa-icon [icon]="faGears"></fa-icon>
|
||||||
|
</div>
|
||||||
|
|
||||||
@if (!ws.connected) {
|
@if (!ws.connected) {
|
||||||
<div class="MainMenuItem MainMenuNotConnected">NICHT VERBUNDEN</div>
|
<div class="MainMenuItem MainMenuNotConnected">NICHT VERBUNDEN</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import {Routes} from '@angular/router';
|
import {Routes} from '@angular/router';
|
||||||
import {LocationList} from './location/list/location-list';
|
|
||||||
import {LocationDetail} from './location/detail/location-detail';
|
import {LocationDetail} from './location/detail/location-detail';
|
||||||
|
import {SettingsComponent} from './settings/settings-component';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{path: 'Location/:id', component: LocationDetail},
|
{path: 'Location/:id', component: LocationDetail},
|
||||||
{path: 'Location', component: LocationList},
|
{path: 'Location', component: LocationDetail},
|
||||||
|
{path: 'Settings', component: SettingsComponent},
|
||||||
{path: '**', redirectTo: '/Location'},
|
{path: '**', redirectTo: '/Location'},
|
||||||
];
|
];
|
||||||
|
|||||||
@ -1,15 +1,17 @@
|
|||||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||||
import {Router, RouterLinkActive, RouterOutlet} from '@angular/router';
|
import {Router, RouterLink, RouterLinkActive, RouterOutlet} from '@angular/router';
|
||||||
import {FaIconComponent} from '@fortawesome/angular-fontawesome';
|
import {FaIconComponent} from '@fortawesome/angular-fontawesome';
|
||||||
import {faBars} from '@fortawesome/free-solid-svg-icons';
|
import {faBars, faBookmark as faBookmarkSolid, faGear, faGears} from '@fortawesome/free-solid-svg-icons';
|
||||||
import {MenuService} from './menu-service';
|
import {MenuService} from './menu-service';
|
||||||
import {Location} from './location/Location';
|
import {Location} from './location/Location';
|
||||||
import {LocationService} from './location/location-service';
|
import {LocationService} from './location/location-service';
|
||||||
import {WebsocketService} from './common';
|
import {WebsocketService} from './common';
|
||||||
|
import {ConfigService} from './config.service';
|
||||||
|
import {faBookmark as faBookmarkRegular} from '@fortawesome/free-regular-svg-icons';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
imports: [RouterOutlet, FaIconComponent, RouterLinkActive],
|
imports: [RouterOutlet, FaIconComponent, RouterLinkActive, RouterLink],
|
||||||
templateUrl: './app.html',
|
templateUrl: './app.html',
|
||||||
styleUrl: './app.less'
|
styleUrl: './app.less'
|
||||||
})
|
})
|
||||||
@ -23,6 +25,7 @@ export class App implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly locationService: LocationService,
|
readonly locationService: LocationService,
|
||||||
|
readonly configService: ConfigService,
|
||||||
readonly menuService: MenuService,
|
readonly menuService: MenuService,
|
||||||
readonly router: Router,
|
readonly router: Router,
|
||||||
readonly ws: WebsocketService,
|
readonly ws: WebsocketService,
|
||||||
@ -45,4 +48,11 @@ export class App implements OnInit, OnDestroy {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected readonly faBookmarkRegular = faBookmarkRegular;
|
||||||
|
|
||||||
|
protected readonly faBookmarkSolid = faBookmarkSolid;
|
||||||
|
|
||||||
|
protected readonly faGear = faGear;
|
||||||
|
|
||||||
|
protected readonly faGears = faGears;
|
||||||
}
|
}
|
||||||
|
|||||||
106
src/main/angular/src/app/config.service.ts
Normal file
106
src/main/angular/src/app/config.service.ts
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ConfigService {
|
||||||
|
|
||||||
|
private readonly LOCATION_ID_KEY = "locationId";
|
||||||
|
|
||||||
|
private readonly ENERGY_PERCENT_KEY = "energyPercent";
|
||||||
|
|
||||||
|
private readonly ENERGY_PERCENT_FALLBACK = false;
|
||||||
|
|
||||||
|
private readonly LOCATION_CONFIG_KEY = "locationConfig";
|
||||||
|
|
||||||
|
private readonly LOCATION_CONFIG_FALLBACK = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._locationId = this.readNumberOrNull(this.LOCATION_ID_KEY);
|
||||||
|
this._energyPercent = this.readBoolean(this.ENERGY_PERCENT_KEY, this.ENERGY_PERCENT_FALLBACK);
|
||||||
|
this._locationConfig = this.readBoolean(this.LOCATION_CONFIG_KEY, this.LOCATION_CONFIG_FALLBACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readNumberOrNull(key: string): number | null {
|
||||||
|
const value = this.read(key);
|
||||||
|
if (value === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const number = parseInt(value);
|
||||||
|
return isNaN(number) ? null : number;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readBoolean(key: string, fallback: boolean): boolean {
|
||||||
|
const value = this.read(key);
|
||||||
|
if (value === "true") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (value === "false") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
private read(key: string): string | null {
|
||||||
|
const value = localStorage.getItem(key);
|
||||||
|
console.log("LOAD", key, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private writeBoolean(key: string, value: boolean | null): void {
|
||||||
|
console.log("STORE", key, value);
|
||||||
|
if (value !== null && value !== undefined) {
|
||||||
|
localStorage.setItem(key, value + "");
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// locationId -----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private _locationId: number | null = null;
|
||||||
|
|
||||||
|
get locationId(): number | null {
|
||||||
|
return this._locationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
set locationId(value: number | null) {
|
||||||
|
this._locationId = value;
|
||||||
|
if (value !== null && value !== undefined) {
|
||||||
|
localStorage.setItem(this.LOCATION_ID_KEY, value + "");
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(this.LOCATION_ID_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// energyPercent -----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private _energyPercent: boolean = this.ENERGY_PERCENT_FALLBACK;
|
||||||
|
|
||||||
|
get energyPercent(): boolean {
|
||||||
|
return this._energyPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
set energyPercent(value: boolean) {
|
||||||
|
this._energyPercent = value;
|
||||||
|
this.writeBoolean(this.ENERGY_PERCENT_KEY, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// locationConfig -----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private _locationConfig: boolean = this.LOCATION_CONFIG_FALLBACK;
|
||||||
|
|
||||||
|
get locationConfig(): boolean {
|
||||||
|
return this._locationConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
set locationConfig(value: boolean) {
|
||||||
|
this._locationConfig = value;
|
||||||
|
if (value !== null && value !== undefined) {
|
||||||
|
localStorage.setItem(this.LOCATION_CONFIG_KEY, value + "");
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(this.LOCATION_CONFIG_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -28,6 +28,7 @@
|
|||||||
</ng-content>
|
</ng-content>
|
||||||
</app-location-energy>
|
</app-location-energy>
|
||||||
|
|
||||||
|
@if (configService.locationConfig) {
|
||||||
<div class="Section">
|
<div class="Section">
|
||||||
<div class="SectionHeading">
|
<div class="SectionHeading">
|
||||||
<div class="SectionHeadingText">
|
<div class="SectionHeadingText">
|
||||||
@ -189,3 +190,5 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import {Component, Inject, LOCALE_ID, OnDestroy, OnInit} from '@angular/core';
|
import {Component, Inject, LOCALE_ID, OnDestroy, OnInit} from '@angular/core';
|
||||||
import {LocationService} from '../location-service';
|
import {LocationService} from '../location-service';
|
||||||
import {ActivatedRoute} from '@angular/router';
|
import {ActivatedRoute, Params, Router} from '@angular/router';
|
||||||
import {Location} from '../Location';
|
import {Location} from '../Location';
|
||||||
import {Text} from '../../shared/text/text';
|
import {Text} from '../../shared/text/text';
|
||||||
import {Number} from '../../shared/number/number';
|
import {Number} from '../../shared/number/number';
|
||||||
@ -14,6 +14,19 @@ import {Series} from '../../series/Series';
|
|||||||
import {SeriesType} from '../../series/SeriesType';
|
import {SeriesType} from '../../series/SeriesType';
|
||||||
import {DateService} from '../../date.service';
|
import {DateService} from '../../date.service';
|
||||||
import {LocationPower} from '../power/location-power';
|
import {LocationPower} from '../power/location-power';
|
||||||
|
import {ConfigService} from '../../config.service';
|
||||||
|
|
||||||
|
export function paramNumberOrNull(params: Params, key: string): number | null {
|
||||||
|
const param = params[key];
|
||||||
|
if (param === null || param === undefined) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const value = parseInt(param);
|
||||||
|
if (isNaN(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-location-detail',
|
selector: 'app-location-detail',
|
||||||
@ -58,6 +71,8 @@ export class LocationDetail implements OnInit, OnDestroy {
|
|||||||
readonly activatedRoute: ActivatedRoute,
|
readonly activatedRoute: ActivatedRoute,
|
||||||
readonly menuService: MenuService,
|
readonly menuService: MenuService,
|
||||||
readonly dateService: DateService,
|
readonly dateService: DateService,
|
||||||
|
readonly configService: ConfigService,
|
||||||
|
readonly router: Router,
|
||||||
@Inject(LOCALE_ID) readonly locale: string,
|
@Inject(LOCALE_ID) readonly locale: string,
|
||||||
) {
|
) {
|
||||||
this.datePipe = new DatePipe(locale);
|
this.datePipe = new DatePipe(locale);
|
||||||
@ -65,7 +80,14 @@ export class LocationDetail implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.locationService.id = null;
|
this.locationService.id = null;
|
||||||
this.subs.push(this.activatedRoute.params.subscribe(params => this.locationService.id = params['id'] || null));
|
this.subs.push(this.activatedRoute.params.subscribe(params => {
|
||||||
|
const id = paramNumberOrNull(params, "id");
|
||||||
|
if (id === null && this.configService.locationId !== null) {
|
||||||
|
this.router.navigate(["Location/" + this.configService.locationId]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.locationService.id = id;
|
||||||
|
}));
|
||||||
this.subs.push(this.locationService.location$.subscribe(this.onLocationChange));
|
this.subs.push(this.locationService.location$.subscribe(this.onLocationChange));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,10 +14,12 @@
|
|||||||
<div class="SectionBody COLOR_FONT_PURCHASE">
|
<div class="SectionBody COLOR_FONT_PURCHASE">
|
||||||
{{ purchase.toValueString(null) }}
|
{{ purchase.toValueString(null) }}
|
||||||
</div>
|
</div>
|
||||||
|
@if (configService.energyPercent) {
|
||||||
<div class="SectionBody COLOR_FONT_PURCHASE percent">
|
<div class="SectionBody COLOR_FONT_PURCHASE percent">
|
||||||
{{ purchasePercentConsume.toValueString(null) }}
|
{{ purchasePercentConsume.toValueString(null) }}
|
||||||
<sub class="subscript">Verbrauch</sub>
|
<sub class="subscript">Verbrauch</sub>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="Section4">
|
<div class="Section4">
|
||||||
@ -27,10 +29,12 @@
|
|||||||
<div class="SectionBody COLOR_FONT_PRODUCE">
|
<div class="SectionBody COLOR_FONT_PRODUCE">
|
||||||
{{ produce.toValueString(null) }}
|
{{ produce.toValueString(null) }}
|
||||||
</div>
|
</div>
|
||||||
|
@if (configService.energyPercent) {
|
||||||
<div class="SectionBody COLOR_FONT_PRODUCE percent">
|
<div class="SectionBody COLOR_FONT_PRODUCE percent">
|
||||||
{{ producePercentConsume.toValueString(null) }}
|
{{ producePercentConsume.toValueString(null) }}
|
||||||
<sub class="subscript">Verbrauch</sub>
|
<sub class="subscript">Verbrauch</sub>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="Section4">
|
<div class="Section4">
|
||||||
@ -40,6 +44,7 @@
|
|||||||
<div class="SectionBody COLOR_FONT_SELF">
|
<div class="SectionBody COLOR_FONT_SELF">
|
||||||
{{ self.toValueString(null) }}
|
{{ self.toValueString(null) }}
|
||||||
</div>
|
</div>
|
||||||
|
@if (configService.energyPercent) {
|
||||||
<div class="SectionBody COLOR_FONT_SELF percent">
|
<div class="SectionBody COLOR_FONT_SELF percent">
|
||||||
{{ selfPercentConsume.toValueString(null) }}
|
{{ selfPercentConsume.toValueString(null) }}
|
||||||
<sub class="subscript">Verbrauch</sub>
|
<sub class="subscript">Verbrauch</sub>
|
||||||
@ -48,6 +53,7 @@
|
|||||||
{{ selfPercentProduce.toValueString(null) }}
|
{{ selfPercentProduce.toValueString(null) }}
|
||||||
<sub class="subscript">Produktion</sub>
|
<sub class="subscript">Produktion</sub>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="Section4">
|
<div class="Section4">
|
||||||
@ -66,6 +72,7 @@
|
|||||||
<div class="SectionBody COLOR_FONT_DELIVER">
|
<div class="SectionBody COLOR_FONT_DELIVER">
|
||||||
{{ deliver.toValueString(null) }}
|
{{ deliver.toValueString(null) }}
|
||||||
</div>
|
</div>
|
||||||
|
@if (configService.energyPercent) {
|
||||||
<div class="SectionBody COLOR_FONT_DELIVER percent">
|
<div class="SectionBody COLOR_FONT_DELIVER percent">
|
||||||
{{ deliveryPercentConsume.toValueString(null) }}
|
{{ deliveryPercentConsume.toValueString(null) }}
|
||||||
<sub class="subscript">Verbrauch</sub>
|
<sub class="subscript">Verbrauch</sub>
|
||||||
@ -74,6 +81,7 @@
|
|||||||
{{ deliveryPercentProduce.toValueString(null) }}
|
{{ deliveryPercentProduce.toValueString(null) }}
|
||||||
<sub class="subscript">Produktion</sub>
|
<sub class="subscript">Produktion</sub>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import {AfterViewInit, Component, Input, OnDestroy, OnInit, signal} from '@angular/core';
|
import {AfterViewInit, Component, Input, OnDestroy, OnInit} from '@angular/core';
|
||||||
import {Location} from '../Location';
|
import {Location} from '../Location';
|
||||||
import {Series} from '../../series/Series';
|
import {Series} from '../../series/Series';
|
||||||
import {Next} from '../../common';
|
import {Next} from '../../common';
|
||||||
@ -8,6 +8,7 @@ import {SeriesService} from '../../series/series-service';
|
|||||||
import {Subscription} from 'rxjs';
|
import {Subscription} from 'rxjs';
|
||||||
import {Value} from '../../series/Value';
|
import {Value} from '../../series/Value';
|
||||||
import EnergyCharts from './charts/energy-charts';
|
import EnergyCharts from './charts/energy-charts';
|
||||||
|
import {ConfigService} from '../../config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-location-energy',
|
selector: 'app-location-energy',
|
||||||
@ -20,8 +21,6 @@ import EnergyCharts from './charts/energy-charts';
|
|||||||
})
|
})
|
||||||
export class LocationEnergy implements OnInit, AfterViewInit, OnDestroy {
|
export class LocationEnergy implements OnInit, AfterViewInit, OnDestroy {
|
||||||
|
|
||||||
protected readonly signal = signal;
|
|
||||||
|
|
||||||
protected readonly Interval = Interval;
|
protected readonly Interval = Interval;
|
||||||
|
|
||||||
private readonly subs: Subscription[] = [];
|
private readonly subs: Subscription[] = [];
|
||||||
@ -75,6 +74,7 @@ export class LocationEnergy implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
constructor(
|
constructor(
|
||||||
readonly pointService: PointService,
|
readonly pointService: PointService,
|
||||||
readonly serieService: SeriesService,
|
readonly serieService: SeriesService,
|
||||||
|
readonly configService: ConfigService,
|
||||||
) {
|
) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
<div class="List LocationList NoUserSelect">
|
|
||||||
@for (location of list; track location.id) {
|
|
||||||
<div class="ListItem Location" routerLink="/Location/{{location.id}}">
|
|
||||||
{{ location.name }}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
|
||||||
import {LocationService} from '../location-service';
|
|
||||||
import {Location} from '../Location';
|
|
||||||
import {RouterLink} from '@angular/router';
|
|
||||||
import {MenuService} from '../../menu-service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-location-list',
|
|
||||||
imports: [
|
|
||||||
RouterLink
|
|
||||||
],
|
|
||||||
templateUrl: './location-list.html',
|
|
||||||
styleUrl: './location-list.less',
|
|
||||||
})
|
|
||||||
export class LocationList implements OnInit, OnDestroy {
|
|
||||||
|
|
||||||
protected list: Location[] = [];
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
readonly locationService: LocationService,
|
|
||||||
readonly menuService: MenuService,
|
|
||||||
) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.locationService.findAll(list => this.list = list);
|
|
||||||
this.menuService.title = "Orte";
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
|
||||||
this.menuService.title = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -25,9 +25,15 @@ export class LocationService extends CrudService<Location> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set id(id: number | null) {
|
set id(id: number | null) {
|
||||||
|
if (this._id !== id) {
|
||||||
this._id = id;
|
this._id = id;
|
||||||
this.fetch();
|
this.fetch();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get id(): number | null {
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
private readonly fetch = () => {
|
private readonly fetch = () => {
|
||||||
if (this._id === null) {
|
if (this._id === null) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<div class="Section3">
|
<div class="Section3">
|
||||||
<div class="SectionHeading">
|
<div class="SectionHeading">
|
||||||
<div class="SectionHeadingText">
|
<div class="SectionHeadingText">
|
||||||
Aktuelle Leistung
|
Aktuell
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="SectionBody">
|
<div class="SectionBody">
|
||||||
@ -13,10 +13,12 @@
|
|||||||
<div class="SectionBody COLOR_FONT_PURCHASE">
|
<div class="SectionBody COLOR_FONT_PURCHASE">
|
||||||
{{ location.powerPurchase?.value?.toValueString(dateService.now) }}
|
{{ location.powerPurchase?.value?.toValueString(dateService.now) }}
|
||||||
</div>
|
</div>
|
||||||
|
@if (configService.energyPercent) {
|
||||||
<div class="SectionBody COLOR_FONT_PURCHASE percent">
|
<div class="SectionBody COLOR_FONT_PURCHASE percent">
|
||||||
{{ location.powerPurchasePercentConsume.toValueString(dateService.now) }}
|
{{ location.powerPurchasePercentConsume.toValueString(dateService.now) }}
|
||||||
<sub class="subscript">Verbrauch</sub>
|
<sub class="subscript">Verbrauch</sub>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="Section4">
|
<div class="Section4">
|
||||||
@ -26,10 +28,12 @@
|
|||||||
<div class="SectionBody COLOR_FONT_PRODUCE">
|
<div class="SectionBody COLOR_FONT_PRODUCE">
|
||||||
{{ location.powerProduce?.value?.toValueString(dateService.now) }}
|
{{ location.powerProduce?.value?.toValueString(dateService.now) }}
|
||||||
</div>
|
</div>
|
||||||
|
@if (configService.energyPercent) {
|
||||||
<div class="SectionBody COLOR_FONT_PRODUCE percent">
|
<div class="SectionBody COLOR_FONT_PRODUCE percent">
|
||||||
{{ location.powerProducePercentConsume.toValueString(dateService.now) }}
|
{{ location.powerProducePercentConsume.toValueString(dateService.now) }}
|
||||||
<sub class="subscript">Verbrauch</sub>
|
<sub class="subscript">Verbrauch</sub>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="Section4">
|
<div class="Section4">
|
||||||
@ -39,6 +43,7 @@
|
|||||||
<div class="SectionBody COLOR_FONT_SELF">
|
<div class="SectionBody COLOR_FONT_SELF">
|
||||||
{{ location.powerSelf.toValueString(dateService.now) }}
|
{{ location.powerSelf.toValueString(dateService.now) }}
|
||||||
</div>
|
</div>
|
||||||
|
@if (configService.energyPercent) {
|
||||||
<div class="SectionBody COLOR_FONT_SELF percent">
|
<div class="SectionBody COLOR_FONT_SELF percent">
|
||||||
{{ location.powerSelfPercentConsume.toValueString(dateService.now) }}
|
{{ location.powerSelfPercentConsume.toValueString(dateService.now) }}
|
||||||
<sub class="subscript">Verbrauch</sub>
|
<sub class="subscript">Verbrauch</sub>
|
||||||
@ -47,6 +52,7 @@
|
|||||||
{{ location.powerSelfPercentProduce.toValueString(dateService.now) }}
|
{{ location.powerSelfPercentProduce.toValueString(dateService.now) }}
|
||||||
<sub class="subscript">Produktion</sub>
|
<sub class="subscript">Produktion</sub>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="Section4">
|
<div class="Section4">
|
||||||
@ -65,6 +71,7 @@
|
|||||||
<div class="SectionBody COLOR_FONT_DELIVER">
|
<div class="SectionBody COLOR_FONT_DELIVER">
|
||||||
{{ location.powerDeliver?.value?.toValueString(dateService.now) }}
|
{{ location.powerDeliver?.value?.toValueString(dateService.now) }}
|
||||||
</div>
|
</div>
|
||||||
|
@if (configService.energyPercent) {
|
||||||
<div class="SectionBody COLOR_FONT_DELIVER percent">
|
<div class="SectionBody COLOR_FONT_DELIVER percent">
|
||||||
{{ location.powerDeliveryPercentConsume.toValueString(dateService.now) }}
|
{{ location.powerDeliveryPercentConsume.toValueString(dateService.now) }}
|
||||||
<sub class="subscript">Verbrauch</sub>
|
<sub class="subscript">Verbrauch</sub>
|
||||||
@ -73,6 +80,7 @@
|
|||||||
{{ location.powerDeliveryPercentProduce.toValueString(dateService.now) }}
|
{{ location.powerDeliveryPercentProduce.toValueString(dateService.now) }}
|
||||||
<sub class="subscript">Produktion</sub>
|
<sub class="subscript">Produktion</sub>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {Location} from '../Location';
|
import {Location} from '../Location';
|
||||||
import {DateService} from '../../date.service';
|
import {DateService} from '../../date.service';
|
||||||
|
import {ConfigService} from '../../config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-location-power',
|
selector: 'app-location-power',
|
||||||
@ -15,6 +16,7 @@ export class LocationPower {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly dateService: DateService,
|
readonly dateService: DateService,
|
||||||
|
readonly configService: ConfigService,
|
||||||
) {
|
) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,18 @@
|
|||||||
|
<div
|
||||||
|
class="container NoUserSelect"
|
||||||
|
[ngClass]="classes()"
|
||||||
|
(mouseenter)="showPen = true"
|
||||||
|
(mouseleave)="showPen = false"
|
||||||
|
>
|
||||||
|
<select [(ngModel)]="model" (ngModelChange)="changed($event)">
|
||||||
|
<option [ngValue]="null">-</option>
|
||||||
|
@for (location of locations; track location.id) {
|
||||||
|
<option [ngValue]="location.id">
|
||||||
|
{{ location.name }}
|
||||||
|
</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
@if (showPen) {
|
||||||
|
<fa-icon [icon]="faPen"></fa-icon>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.container:hover {
|
||||||
|
background-color: #0002;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
all: unset;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invalid {
|
||||||
|
background-color: red !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changed {
|
||||||
|
background-color: yellow !important;
|
||||||
|
}
|
||||||
80
src/main/angular/src/app/location/select/location-select.ts
Normal file
80
src/main/angular/src/app/location/select/location-select.ts
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||||
|
import {FaIconComponent} from '@fortawesome/angular-fontawesome';
|
||||||
|
import {FormsModule} from '@angular/forms';
|
||||||
|
import {NgClass} from '@angular/common';
|
||||||
|
import {faPen} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import {Location} from '../Location';
|
||||||
|
import {LocationService} from '../location-service';
|
||||||
|
import {DateService} from '../../date.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-location-select',
|
||||||
|
imports: [
|
||||||
|
FaIconComponent,
|
||||||
|
FormsModule,
|
||||||
|
NgClass
|
||||||
|
],
|
||||||
|
templateUrl: './location-select.html',
|
||||||
|
styleUrl: './location-select.less',
|
||||||
|
})
|
||||||
|
export class LocationSelect implements OnInit {
|
||||||
|
|
||||||
|
protected readonly faPen = faPen;
|
||||||
|
|
||||||
|
private _initial: number | null = null;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
locations!: Location[];
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
allowEmpty: boolean = true;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
filter: (location: Location) => boolean = () => true;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
readonly onChange = new EventEmitter<number | null>();
|
||||||
|
|
||||||
|
protected showPen: boolean = false;
|
||||||
|
|
||||||
|
protected model: number | null = null;
|
||||||
|
|
||||||
|
protected readonly Location = Location;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly locationService: LocationService,
|
||||||
|
readonly dateService: DateService,
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.locationService.findAll(list => this.locations = list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set initial(value: number | null) {
|
||||||
|
this._initial = value;
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly reset = (): void => {
|
||||||
|
this.model = this._initial;
|
||||||
|
};
|
||||||
|
|
||||||
|
protected classes(): {} {
|
||||||
|
return {
|
||||||
|
"changed": this.model !== this._initial,
|
||||||
|
"invalid": !this.allowEmpty && this.model === null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected changed(id: number | null) {
|
||||||
|
if (this.allowEmpty || id !== null) {
|
||||||
|
this.onChange.emit(id);
|
||||||
|
} else {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -16,10 +16,6 @@ select {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unchanged {
|
|
||||||
background-color: lightgreen !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.invalid {
|
.invalid {
|
||||||
background-color: red !important;
|
background-color: red !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,7 +78,6 @@ export class SeriesSelect implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
protected classes(): {} {
|
protected classes(): {} {
|
||||||
return {
|
return {
|
||||||
"unchanged": this.model === this._initial,
|
|
||||||
"changed": this.model !== or(this._initial, i => i.id, null),
|
"changed": this.model !== or(this._initial, i => i.id, null),
|
||||||
"invalid": !this.allowEmpty && this.model === null,
|
"invalid": !this.allowEmpty && this.model === null,
|
||||||
};
|
};
|
||||||
|
|||||||
32
src/main/angular/src/app/settings/settings-component.html
Normal file
32
src/main/angular/src/app/settings/settings-component.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<div class="Section3">
|
||||||
|
<div class="SectionHeading">
|
||||||
|
<div class="SectionHeadingText">
|
||||||
|
Favorit
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<app-location-select [initial]="configService.locationId" (onChange)="configService.locationId = $event"></app-location-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="Section3">
|
||||||
|
<div class="SectionHeading">
|
||||||
|
<div class="SectionHeadingText">
|
||||||
|
Anzeige
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" #checkbox [checked]="configService.energyPercent" (change)="configService.energyPercent = checkbox.checked">
|
||||||
|
Energie Prozentsätze
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" #checkbox [checked]="configService.locationConfig" (change)="configService.locationConfig = checkbox.checked">
|
||||||
|
Ort Konfiguration
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
30
src/main/angular/src/app/settings/settings-component.ts
Normal file
30
src/main/angular/src/app/settings/settings-component.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {LocationSelect} from '../location/select/location-select';
|
||||||
|
import {LocationService} from '../location/location-service';
|
||||||
|
import {Location} from '../location/Location'
|
||||||
|
import {ConfigService} from '../config.service';
|
||||||
|
import {config} from 'rxjs';
|
||||||
|
import {FormsModule} from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-settings-component',
|
||||||
|
imports: [
|
||||||
|
LocationSelect,
|
||||||
|
FormsModule
|
||||||
|
],
|
||||||
|
templateUrl: './settings-component.html',
|
||||||
|
styleUrl: './settings-component.less',
|
||||||
|
})
|
||||||
|
export class SettingsComponent {
|
||||||
|
|
||||||
|
protected location: Location | null = null;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly locationService: LocationService,
|
||||||
|
readonly configService: ConfigService,
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
protected readonly config = config;
|
||||||
|
}
|
||||||
@ -62,7 +62,8 @@ div {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.Section3 {
|
.Section3 {
|
||||||
border: 1px solid gray;
|
border: 1px solid lightgray;
|
||||||
|
border-radius: 0.25em;
|
||||||
margin: 1em 0.5em 0.5em;
|
margin: 1em 0.5em 0.5em;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user