diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts index 27d05b4410..af2069711c 100644 --- a/ui/src/app/app.component.ts +++ b/ui/src/app/app.component.ts @@ -21,7 +21,7 @@ export class AppComponent implements OnInit, OnDestroy { public environment = environment; public backUrl: string | boolean = "/"; - public enableSideMenu: boolean; + public enableSideMenu: boolean = false; public isSystemLogEnabled: boolean = false; protected isUserAllowedToSeeOverview: boolean = false; diff --git a/ui/src/app/edge/history/abstracthistorychart.ts b/ui/src/app/edge/history/abstracthistorychart.ts index 7c8c70ec7b..607d4b5cff 100644 --- a/ui/src/app/edge/history/abstracthistorychart.ts +++ b/ui/src/app/edge/history/abstracthistorychart.ts @@ -57,6 +57,10 @@ export abstract class AbstractHistoryChart { borderColor: "rgba(128,128,0,1)", }; + + private activeQueryData: string = ""; + private debounceTimeout: any | null = null; + constructor( public readonly spinnerId: string, protected service: Service, diff --git a/ui/src/app/edge/history/abstracthistorywidget.ts b/ui/src/app/edge/history/abstracthistorywidget.ts index 2af3a49bc4..0000cb5edb 100644 --- a/ui/src/app/edge/history/abstracthistorywidget.ts +++ b/ui/src/app/edge/history/abstracthistorywidget.ts @@ -10,7 +10,7 @@ import { calculateResolution } from "./shared"; // NOTE: Auto-refresh of widgets is currently disabled to reduce server load export abstract class AbstractHistoryWidget { - private activeQueryData: string; + private activeQueryData: string = ""; //observable is used to fetch new widget data every 5 minutes // private refreshWidgetData = interval(600000); diff --git a/ui/src/app/edge/history/historydataservice.ts b/ui/src/app/edge/history/historydataservice.ts index 5abba259cc..914530c05b 100644 --- a/ui/src/app/edge/history/historydataservice.ts +++ b/ui/src/app/edge/history/historydataservice.ts @@ -16,7 +16,7 @@ export class HistoryDataService extends DataService { public queryChannelsTimeout: ReturnType | null = null; protected override timestamps: string[] = []; - private activeQueryData: string; + private activeQueryData: string = ""; private channelAddresses: { [sourceId: string]: ChannelAddress } = {}; constructor( diff --git a/ui/src/app/edge/live/common/autarchy/flat/flat.ts b/ui/src/app/edge/live/common/autarchy/flat/flat.ts index e9620384f0..a11b7f3da4 100644 --- a/ui/src/app/edge/live/common/autarchy/flat/flat.ts +++ b/ui/src/app/edge/live/common/autarchy/flat/flat.ts @@ -1,4 +1,3 @@ -// @ts-strict-ignore import { Component } from "@angular/core"; import { AbstractFlatWidget } from "src/app/shared/components/flat/abstract-flat-widget"; import { ChannelAddress, CurrentData, Utils } from "src/app/shared/shared"; @@ -10,7 +9,7 @@ import { ModalComponent } from "../modal/modal"; }) export class FlatComponent extends AbstractFlatWidget { - public percentageValue: number; + public percentageValue: number = 0; async presentModal() { const modal = await this.modalController.create({ diff --git a/ui/src/app/edge/live/common/consumption/flat/flat.ts b/ui/src/app/edge/live/common/consumption/flat/flat.ts index 58c13f9631..4bb5c8d879 100644 --- a/ui/src/app/edge/live/common/consumption/flat/flat.ts +++ b/ui/src/app/edge/live/common/consumption/flat/flat.ts @@ -13,8 +13,8 @@ export class FlatComponent extends AbstractFlatWidget { public evcss: EdgeConfig.Component[] | null = null; public consumptionMeters: EdgeConfig.Component[] | null = null; public sumActivePower: number = 0; - public evcsSumOfChargePower: number; - public otherPower: number; + public evcsSumOfChargePower: number = 0; + public otherPower: number = 0; public readonly CONVERT_WATT_TO_KILOWATT = Utils.CONVERT_WATT_TO_KILOWATT; async presentModal() { diff --git a/ui/src/app/edge/live/common/grid/flat/flat.ts b/ui/src/app/edge/live/common/grid/flat/flat.ts index 64bc50f0ff..83ac47cf19 100644 --- a/ui/src/app/edge/live/common/grid/flat/flat.ts +++ b/ui/src/app/edge/live/common/grid/flat/flat.ts @@ -1,4 +1,3 @@ -// @ts-strict-ignore import { Component } from "@angular/core"; import { AbstractFlatWidget } from "src/app/shared/components/flat/abstract-flat-widget"; import { Converter } from "src/app/shared/components/shared/converter"; @@ -20,11 +19,11 @@ export class FlatComponent extends AbstractFlatWidget { public readonly CONVERT_WATT_TO_KILOWATT = Utils.CONVERT_WATT_TO_KILOWATT; public readonly GridMode = GridMode; - public gridBuyPower: number; - public gridSellPower: number; + public gridBuyPower: number = 0; + public gridSellPower: number = 0; - protected gridMode: number; - protected gridState: string; + protected gridMode: number = 0; + protected gridState: string = ""; protected icon: Icon | null = null; protected isActivated: boolean = false; diff --git a/ui/src/app/edge/live/common/selfconsumption/flat/flat.ts b/ui/src/app/edge/live/common/selfconsumption/flat/flat.ts index f1bf518f2b..0c563e87cf 100644 --- a/ui/src/app/edge/live/common/selfconsumption/flat/flat.ts +++ b/ui/src/app/edge/live/common/selfconsumption/flat/flat.ts @@ -11,7 +11,7 @@ import { ModalComponent } from "../modal/modal"; }) export class FlatComponent extends AbstractFlatWidget { - public calculatedSelfConsumption: number; + public calculatedSelfConsumption: number = 0; async presentModal() { const modal = await this.modalController.create({ diff --git a/ui/src/app/edge/live/common/storage/modal/modal.component.ts b/ui/src/app/edge/live/common/storage/modal/modal.component.ts index 6ce266a140..1cb57f604e 100644 --- a/ui/src/app/edge/live/common/storage/modal/modal.component.ts +++ b/ui/src/app/edge/live/common/storage/modal/modal.component.ts @@ -25,7 +25,7 @@ export class StorageModalComponent implements OnInit, OnDestroy { public isLastElement = Utils.isLastElement; public formGroup: FormGroup = new FormGroup({}); - protected isAtLeastInstaller: boolean; + protected isAtLeastInstaller: boolean = false; protected isTargetTimeInValid: Map = new Map(); protected controllerIsRequiredEdgeVersion: boolean = false; diff --git a/ui/src/app/shared/components/header/header.component.ts b/ui/src/app/shared/components/header/header.component.ts index 1a4fe4dbf7..1c93c6e1d3 100644 --- a/ui/src/app/shared/components/header/header.component.ts +++ b/ui/src/app/shared/components/header/header.component.ts @@ -20,7 +20,7 @@ export class HeaderComponent implements OnInit, OnDestroy, AfterViewChecked { public environment = environment; public backUrl: string | boolean = "/"; - public enableSideMenu: boolean; + public enableSideMenu: boolean = false; public currentPage: "EdgeSettings" | "Other" | "IndexLive" | "IndexHistory" = "Other"; public isSystemLogEnabled: boolean = false; diff --git a/ui/src/app/shared/service/service.ts b/ui/src/app/shared/service/service.ts index cc997a4d76..0e164caff0 100644 --- a/ui/src/app/shared/service/service.ts +++ b/ui/src/app/shared/service/service.ts @@ -12,7 +12,7 @@ import { environment } from "src/environments"; import { ChartConstants } from "../components/chart/chart.constants"; import { Edge } from "../components/edge/edge"; import { EdgeConfig } from "../components/edge/edgeconfig"; -import { JsonrpcResponseError } from "../jsonrpc/base"; +import { JsonrpcResponseError, JsonrpcResponseSuccess } from "../jsonrpc/base"; import { GetEdgeRequest } from "../jsonrpc/request/getEdgeRequest"; import { GetEdgesRequest } from "../jsonrpc/request/getEdgesRequest"; import { QueryHistoricTimeseriesEnergyRequest } from "../jsonrpc/request/queryHistoricTimeseriesEnergyRequest"; @@ -56,12 +56,12 @@ export class Service extends AbstractService { public deviceWidth: number = 0; public isSmartphoneResolution: boolean = false; public isSmartphoneResolutionSubject: Subject = new Subject(); - public activeQueryData: string; + public activeQueryData: string = ""; /** * Holds the currenty selected Page Title. */ - public currentPageTitle: string; + public currentPageTitle: string = ""; /** * Holds reference to Websocket. This is set by Websocket in constructor. @@ -70,14 +70,14 @@ export class Service extends AbstractService { /** * Holds the currently selected Edge. */ - public readonly currentEdge: BehaviorSubject = new BehaviorSubject(null); +public readonly currentEdge: BehaviorSubject = new BehaviorSubject(null); /** * Holds references of Edge-IDs (=key) to Edge objects (=value) */ public readonly metadata: BehaviorSubject<{ user: User, edges: { [edgeId: string]: Edge } - }> = new BehaviorSubject(null); + } | null> = new BehaviorSubject(null); public currentUser: User | null = null; @@ -87,7 +87,7 @@ export class Service extends AbstractService { private currentActivatedRoute: ActivatedRoute | null = null; private queryEnergyQueue: { - fromDate: Date, toDate: Date, channels: ChannelAddress[], promises: { resolve, reject }[] + fromDate: Date, toDate: Date, channels: ChannelAddress[], promises: { resolve: (value?: JsonrpcResponseSuccess) => void; reject: (reason: any) => void }[] }[] = []; private queryEnergyTimeout: any = null; @@ -108,7 +108,9 @@ export class Service extends AbstractService { // React on Language Change and update language translate.onLangChange.subscribe((event: LangChangeEvent) => { - this.setLang(Language.getByKey(event.lang)); + if (event.lang) { + this.setLang(Language.getByKey(event.lang)); + } }); } @@ -215,8 +217,12 @@ export class Service extends AbstractService { } public onLogout() { - this.currentEdge.next(null); - this.metadata.next(null); + if (this.currentEdge) { + this.currentEdge.next(null); + } + if (this.metadata) { + this.metadata.next(null); + } this.websocket.state.set(States.NOT_AUTHENTICATED); this.router.navigate(["/login"]); } @@ -251,7 +257,7 @@ export class Service extends AbstractService { fromDate: Date, toDate: Date, channels: ChannelAddress[], - promises: { resolve, reject }[]; + promises: { resolve: (value: any) => void; reject: (reason: any) => void }[] }[] = []; let request; diff --git a/ui/src/app/shared/service/utils.ts b/ui/src/app/shared/service/utils.ts index 837e37acc5..e0f1183c10 100644 --- a/ui/src/app/shared/service/utils.ts +++ b/ui/src/app/shared/service/utils.ts @@ -82,7 +82,7 @@ export class Utils { */ public static absSafely(value: number | null): number | null { if (value == null) { - return value; + return null; } else { return Math.abs(value); } @@ -94,7 +94,7 @@ export class Utils { * @param v1 * @param v2 */ - public static addSafely(v1: number, v2: number): number { + public static addSafely(v1: number | null, v2: number | null): number | null { if (v1 == null) { return v2; } else if (v2 == null) { @@ -114,6 +114,9 @@ export class Utils { return values .filter(value => value !== null && value !== undefined) .reduce((sum, curr) => { + if (curr == null) { + return sum; + } if (sum == null) { sum = curr; } else { @@ -161,7 +164,7 @@ export class Utils { * @param v2 * @returns */ - public static compareArraysSafely(v1: T[] | null, v2: T[] | null): boolean { + public static compareArraysSafely(v1: T[] | null, v2: T[] | null): boolean | null { if (v1 == null || v2 == null) { return null; } @@ -214,7 +217,7 @@ export class Utils { * @param orElse the default value * @returns the value or the default value */ - public static orElse(v: number, orElse: number): number { + public static orElse(v: number | null, orElse: number): number { if (v == null) { return orElse; } else { @@ -552,7 +555,7 @@ export class Utils { } public static isDataEmpty(arg: JsonrpcResponseSuccess): boolean { - return Object.values(arg.result["data"])?.map(element => element as number[])?.every(element => element?.every(elem => elem == null) ?? true); + return Object.values(arg.result["data"] || {})?.map(element => element as number[])?.every(element => element?.every(elem => elem == null) ?? true); } /** @@ -593,7 +596,7 @@ export class Utils { * @param consumptionMeterComponents the consumptionMeterComponents * @returns the other consumption */ - public static calculateOtherConsumption(channelData: HistoryUtils.ChannelData, evcsComponents: EdgeConfig.Component[], consumptionMeterComponents: EdgeConfig.Component[]): number[] { + public static calculateOtherConsumption(channelData: HistoryUtils.ChannelData, evcsComponents: EdgeConfig.Component[], consumptionMeterComponents: EdgeConfig.Component[]): number[] | null{ const totalEvcsConsumption: number[] = []; const totalMeteredConsumption: number[] = []; @@ -784,14 +787,14 @@ export namespace HistoryUtils { export namespace ValueConverter { - export const NEGATIVE_AS_ZERO = (value) => { + export const NEGATIVE_AS_ZERO = (value: number | null): number | null => { if (value == null) { return null; } return Math.max(0, value); }; - export const NON_NEGATIVE = (value) => { + export const NON_NEGATIVE = (value: number | null): number | null => { if (value >= 0) { return value; } else { @@ -862,7 +865,7 @@ export namespace TimeOfUseTariffUtils { // Error handling: Return undefined if value is not valid if (value === undefined || value === null || Number.isNaN(Number.parseInt(value.toString()))) { - return; + return ""; } const socLabel = translate.instant("General.soc"); diff --git a/ui/src/app/shared/shared.module.ts b/ui/src/app/shared/shared.module.ts index 75cca82971..9394e9f19c 100644 --- a/ui/src/app/shared/shared.module.ts +++ b/ui/src/app/shared/shared.module.ts @@ -49,11 +49,11 @@ export function SubnetmaskValidator(control: FormControl): ValidationErrors { return /^(255)\.(0|128|192|224|240|248|252|254|255)\.(0|128|192|224|240|248|252|254|255)\.(0|128|192|224|240|248|252|254|255)/.test(control.value) ? null : { "subnetmask": true }; } -export function IpValidatorMessage(err, field: FormlyFieldConfig) { +export function IpValidatorMessage(err: any, field: FormlyFieldConfig) { return `"${field.formControl.value}" is not a valid IP Address`; } -export function SubnetmaskValidatorMessage(err, field: FormlyFieldConfig) { +export function SubnetmaskValidatorMessage(err: any, field: FormlyFieldConfig) { return `"${field.formControl.value}" is not a valid Subnetmask`; } diff --git a/ui/src/app/shared/type/widget.ts b/ui/src/app/shared/type/widget.ts index 5f72e25e0c..f6524e7173 100644 --- a/ui/src/app/shared/type/widget.ts +++ b/ui/src/app/shared/type/widget.ts @@ -48,8 +48,8 @@ export type Icon = { }; export class Widget { - public name: WidgetNature | WidgetFactory | string; - public componentId: string; + public name: WidgetNature | WidgetFactory | string = ""; + public componentId: string = ""; } export class Widgets { diff --git a/ui/src/app/user/user.component.ts b/ui/src/app/user/user.component.ts index 694549cf3b..f3a717cbd9 100644 --- a/ui/src/app/user/user.component.ts +++ b/ui/src/app/user/user.component.ts @@ -199,7 +199,9 @@ export class UserComponent implements OnInit { public enableAndDisableFormFields(): boolean { this.userInformationFields = this.userInformationFields.map(field => { - field.props.disabled = !field.props.disabled; + if (field.props) { + field.props.disabled = !field.props.disabled; + } return field; });