diff --git a/typescript/Frontend/package-lock.json b/typescript/Frontend/package-lock.json
index d36bf3040..5b160b6da 100644
--- a/typescript/Frontend/package-lock.json
+++ b/typescript/Frontend/package-lock.json
@@ -57,7 +57,8 @@
"@formatjs/cli": "^6.0.3",
"@types/react-plotly.js": "^2.6.0",
"@types/react-window": "^1.8.5",
- "eslint-plugin-formatjs": "^4.10.1"
+ "eslint-plugin-formatjs": "^4.10.1",
+ "prettier": "^2.8.8"
}
},
"node_modules/@adobe/css-tools": {
@@ -19743,6 +19744,21 @@
"node": ">=0.10.0"
}
},
+ "node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
"node_modules/pretty-bytes": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
@@ -39706,6 +39722,12 @@
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
"integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg=="
},
+ "prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true
+ },
"pretty-bytes": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
diff --git a/typescript/Frontend/package.json b/typescript/Frontend/package.json
index 900de2c7a..e9719afc3 100644
--- a/typescript/Frontend/package.json
+++ b/typescript/Frontend/package.json
@@ -85,6 +85,7 @@
"@formatjs/cli": "^6.0.3",
"@types/react-plotly.js": "^2.6.0",
"@types/react-window": "^1.8.5",
- "eslint-plugin-formatjs": "^4.10.1"
+ "eslint-plugin-formatjs": "^4.10.1",
+ "prettier": "^2.8.8"
}
}
diff --git a/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx b/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx
index 334688921..89a559628 100644
--- a/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx
+++ b/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx
@@ -16,7 +16,7 @@ import { S3Access } from "../../../dataCache/S3/S3Access";
import DataCache, { FetchResult } from "../../../dataCache/dataCache";
import { LogContext } from "../../Context/LogContextProvider";
import { isDefined } from "../../../dataCache/utils/maybe";
-import { Data, Layout, PlotRelayoutEvent } from "plotly.js";
+import { Data, Icons, Layout, PlotRelayoutEvent, relayout } from "plotly.js";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { FormattedMessage } from "react-intl";
import DateRangePicker from "./DateRangePicker";
@@ -45,6 +45,7 @@ export const fetchData = (
return Promise.resolve(FetchResult.notAvailable);
} else if (r.status === 200) {
const text = await r.text();
+ console.log("parsecsv", text, parseCsv(text));
return parseCsv(text);
} else {
console.error("unexpected status code");
@@ -153,6 +154,7 @@ const ScalarGraph = () => {
const handleRelayout = useCallback(
(params: PlotRelayoutEvent) => {
+ console.log("relayout");
const xaxisRange0 = params["xaxis.range[0]"];
const xaxisRange1 = params["xaxis.range[1]"];
if (xaxisRange0 && xaxisRange1) {
@@ -169,11 +171,8 @@ const ScalarGraph = () => {
if (checkedToggles.length > 0) {
const coordinateTimeSeries = transformToGraphData(timeSeries);
const visibleGraphs = Object.keys(coordinateTimeSeries).filter((path) => {
- console.log('checkedToggles',coordinateTimeSeries, checkedToggles)
- return checkedToggles.find((toggle) => toggle === path)
- }
- );
- console.log('visibleGraphs', visibleGraphs)
+ return checkedToggles.find((toggle) => toggle === path);
+ });
if (visibleGraphs.length > 0) {
return (
@@ -186,6 +185,8 @@ const ScalarGraph = () => {
{visibleGraphs.map((path) => {
const isScalar = isNumeric(coordinateTimeSeries[path].y[0]);
+ console.log("graphdata", timeSeries, coordinateTimeSeries);
+
const data = isScalar
? [
{
@@ -203,7 +204,6 @@ const ScalarGraph = () => {
barnorm: "percent",
}
: {};
- console.log("graphdata", coordinateTimeSeries);
return (
{
"select2d",
"pan2d",
"autoScale2d",
+ "resetScale2d",
+ "zoom2d",
],
}}
onRelayout={handleRelayout}
diff --git a/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx b/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx
index 3eb85a039..9f6a87ac2 100644
--- a/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx
+++ b/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx
@@ -1,79 +1,86 @@
-import {Box} from "@mui/material";
-import {getBoxColor} from "../../../util/graph.util";
+import { Box } from "@mui/material";
+import { getBoxColor } from "../../../util/graph.util";
+
+export interface BoxDataValue {
+ unit: string;
+ value: string | number;
+}
export type BoxData = {
- label: string;
- values: (string | number)[];
- unit: string;
+ label: string;
+ values: BoxDataValue[];
};
export type TopologyBoxProps = {
- title?: string;
- data?: BoxData;
+ title?: string;
+ data?: BoxData;
};
const isInt = (value: number) => {
- return value % 1 === 0;
+ return value % 1 === 0;
};
export const BOX_SIZE = 85;
const TopologyBox = (props: TopologyBoxProps) => {
- const {titleColor, boxColor} = getBoxColor(props.title);
- return (
-
-
- {props.title}
-
-
- {props.data && (
- <>
- {props.data.values.map((value, index) => {
- return (
-
{`${
- props.data && props.data.values.length === 3
- ? "L" + (index + 1) + " "
- : ""
- }${
- !isInt(Number(value)) ? Number(value).toPrecision(4) : value
- }${props.data?.unit}`}
- );
- })}
- >
- )}
-
-
- );
+ const { titleColor, boxColor } = getBoxColor(props.title);
+ return (
+
+
+ {props.title}
+
+
+ {props.data && (
+ <>
+ {props.data.values.map((boxData, index) => {
+ console.log("boxData", boxData);
+ return (
+
{`${
+ props.data && props.data.values.length === 3
+ ? "L" + (index + 1) + " "
+ : ""
+ }${
+ !isInt(Number(boxData.value))
+ ? Number(boxData.value).toPrecision(4)
+ : boxData.value
+ }${boxData.unit}`}
+ );
+ })}
+ >
+ )}
+
+
+ );
};
export default TopologyBox;
diff --git a/typescript/Frontend/src/components/Installations/Log/TopologyFlow.tsx b/typescript/Frontend/src/components/Installations/Log/TopologyFlow.tsx
index 4f3912382..cc077eee4 100644
--- a/typescript/Frontend/src/components/Installations/Log/TopologyFlow.tsx
+++ b/typescript/Frontend/src/components/Installations/Log/TopologyFlow.tsx
@@ -43,9 +43,9 @@ const TopologyFlow = (props: TopologyFlowProps) => {
}}
>
{values
- ?.filter((value) => (value as number) !== 0)
+ ?.filter((boxData) => (boxData.value as number) !== 0)
.map(
- (value) => `${Math.round(value as number)} ${props.data?.unit}`
+ (boxData) => `${Math.round(boxData.value as number)} ${boxData.unit}`
)}
> {
const n = after.index - t;
const pn = p + n;
- let interpolated: Partial> = {};
+ let interpolated: Record = {};
//What about string nodes? like Alarms
for (const k of Object.keys(dataBefore)) {
- const beforeData = dataBefore[k].value;
- const afterData = Number(dataAfter[k].value);
- let foo = interpolated[k];
- if (foo) {
- foo.value = isNumber(beforeData)
- ? (beforeData * n + afterData * p) / pn
- : n < p
- ? afterData
- : beforeData;
+ const valueBefore = dataBefore[k].value;
+ const valueAfter = dataAfter[k]?.value as Maybe;
+
+ let value: number | string;
+
+ if (isUndefined(valueAfter)) {
+ value = valueBefore;
+ } else if (isNumber(valueBefore) && isNumber(valueAfter)) {
+ value = (valueBefore * n + valueAfter * p) / pn;
+ } else {
+ value = n < p ? valueAfter : valueBefore;
}
+
+ interpolated[k] = { value, unit: dataBefore[k].unit };
}
return interpolated as T;
diff --git a/typescript/Frontend/src/util/graph.util.tsx b/typescript/Frontend/src/util/graph.util.tsx
index 9df5afb52..2c081982d 100644
--- a/typescript/Frontend/src/util/graph.util.tsx
+++ b/typescript/Frontend/src/util/graph.util.tsx
@@ -1,11 +1,12 @@
import { Datum, TypedArray } from "plotly.js";
-import {
- TreeElement,
-} from "../components/Installations/Log/CheckboxTree";
+import { TreeElement } from "../components/Installations/Log/CheckboxTree";
import { TimeRange, UnixTime } from "../dataCache/time";
import { DataPoint, DataRecord } from "../dataCache/data";
import { isDefined } from "../dataCache/utils/maybe";
-import { BoxData } from "../components/Installations/Log/TopologyBox";
+import {
+ BoxData,
+ BoxDataValue,
+} from "../components/Installations/Log/TopologyBox";
export interface GraphCoordinates {
x: Datum[] | Datum[][] | TypedArray;
@@ -30,6 +31,7 @@ export const createTimes = (
);
return roundedRange.sample(oneSpan);
};
+
export interface GraphData {
[path: string]: GraphCoordinates;
}
@@ -95,6 +97,7 @@ interface BoxColor {
titleColor: string;
boxColor: string;
}
+
export const getBoxColor = (boxTitle?: string): BoxColor => {
switch (boxTitle) {
case "Grid":
@@ -138,18 +141,33 @@ export const extractTopologyValues = (
const timeSeriesValue = timeSeriesData.value;
if (isDefined(timeSeriesValue)) {
return Object.keys(topologyPaths).reduce((acc, topologyKey) => {
- let topologyValues: (string | number)[];
+ let topologyValues: BoxDataValue[];
const values = topologyPaths[topologyKey as keyof TopologyValues].map(
(topologyPath) => timeSeriesValue[topologyPath]
);
switch (topologyKey as keyof TopologyValues) {
case "gridToAcInConnection":
topologyValues = [
- values.reduce((acc, curr) => Number(acc) + Number(curr.value), 0),
+ values.reduce(
+ (acc, curr) => {
+ return {
+ value: Number(acc.value) + Number(curr.value),
+ unit: acc.unit,
+ };
+ },
+ { value: 0, unit: values[0].unit }
+ ),
];
break;
default:
- topologyValues = values.map((element) => element.value);
+ topologyValues = values
+ .filter((element) => element)
+ .map((element) => {
+ if (element) {
+ return { value: element.value, unit: element.unit };
+ }
+ return { value: 0, unit: "" };
+ });
}
return {
...acc,
@@ -158,7 +176,6 @@ export const extractTopologyValues = (
label: topologyPaths[topologyKey as keyof TopologyValues][0]
.split("/")
.pop(),
- unit: values[0].unit,
} as BoxData,
};
}, {} as TopologyValues);
@@ -171,16 +188,22 @@ export const getHighestConnectionValue = (values: TopologyValues) =>
.filter((value) => value.includes("Connection"))
.reduce((acc, curr) => {
const value = Math.abs(
- values[curr as keyof TopologyValues].values[0] as number
+ values[curr as keyof TopologyValues].values[0].value as number
);
return value > acc ? value : acc;
}, 0);
export const getAmount = (
highestConnectionValue: number,
- values: (string | number)[]
+ values: BoxDataValue[]
) => {
- return Math.abs(values[0] as number) / highestConnectionValue;
+ console.log(
+ "getamount",
+ Math.abs(values[0].value as number) / highestConnectionValue,
+ Math.abs(values[0].value as number),
+ highestConnectionValue
+ );
+ return Math.abs(values[0].value as number) / highestConnectionValue;
};
export interface CsvEntry {
@@ -189,23 +212,26 @@ export interface CsvEntry {
}
export const parseCsv = (text: string): DataRecord => {
+ console.log("parseText", text);
const y = text
.split(/\r?\n/)
.filter((split) => split.length > 0)
.map((l) => {
return l.split(";");
});
- const x = y
+ return y
.map((fields) => {
- if (fields[0] === "/AcDc/Warnings")
- console.log("warnings", fields[1], isNaN(+fields[1]));
+ if (fields[0].includes("LoadOnAcIsland")) {
+ console.log("fields", fields, {
+ [fields[0]]: { value: parseFloat(fields[1]), unit: fields[2] },
+ });
+ }
if (isNaN(Number(fields[1])) || fields[1] === "") {
return { [fields[0]]: { value: fields[1], unit: fields[2] } };
}
return { [fields[0]]: { value: parseFloat(fields[1]), unit: fields[2] } };
})
.reduce((acc, current) => ({ ...acc, ...current }), {} as DataRecord);
- return x;
};
export const insertTreeElements = (