working graphs and toggles
This commit is contained in:
parent
b7c443fc93
commit
d722f42d99
|
@ -40,7 +40,6 @@ const Login = ({ setToken, setLanguage }: I_LoginProps) => {
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setToken(data.token);
|
setToken(data.token);
|
||||||
saveCurrentUser(data.user);
|
saveCurrentUser(data.user);
|
||||||
console.log(data.user);
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setLanguage(data.user.language);
|
setLanguage(data.user.language);
|
||||||
})
|
})
|
||||||
|
|
|
@ -34,7 +34,6 @@ const ResetPassword = () => {
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
saveCurrentUser(res.data);
|
saveCurrentUser(res.data);
|
||||||
console.log(res.data);
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
})
|
})
|
||||||
.catch((err) => setError(err));
|
.catch((err) => setError(err));
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { createContext, ReactNode, SetStateAction, useState } from "react";
|
||||||
|
import { TreeElement, ToggleElement } from "../Installations/Log/CheckboxTree";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
interface LogContextProviderProps {
|
||||||
|
toggles: TreeElement[] | null;
|
||||||
|
setToggles: (value: TreeElement[]) => void;
|
||||||
|
checkedToggles: ToggleElement | null;
|
||||||
|
setCheckedToggles: React.Dispatch<SetStateAction<ToggleElement | null>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LogContext = createContext<LogContextProviderProps>({
|
||||||
|
toggles: [],
|
||||||
|
setToggles: () => {},
|
||||||
|
checkedToggles: {},
|
||||||
|
setCheckedToggles: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const LogContextProvider = ({ children }: { children: ReactNode }) => {
|
||||||
|
const [toggles, setToggles] = useState<TreeElement[] | null>(null);
|
||||||
|
const [checkedToggles, setCheckedToggles] = useState<ToggleElement | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
console.log("provider", toggles);
|
||||||
|
return (
|
||||||
|
<LogContext.Provider
|
||||||
|
value={{
|
||||||
|
toggles,
|
||||||
|
setToggles,
|
||||||
|
checkedToggles,
|
||||||
|
setCheckedToggles,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</LogContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LogContextProvider;
|
|
@ -90,7 +90,6 @@ const UsersContextProvider = ({ children }: { children: ReactNode }) => {
|
||||||
|
|
||||||
const fetchAvailableUsers = async (): Promise<void> => {
|
const fetchAvailableUsers = async (): Promise<void> => {
|
||||||
return axiosConfig.get("/GetAllChildUsers").then((res) => {
|
return axiosConfig.get("/GetAllChildUsers").then((res) => {
|
||||||
console.log(res);
|
|
||||||
setAvailableUsers(res.data);
|
setAvailableUsers(res.data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,16 +8,20 @@ import InstallationContextProvider from "../Context/InstallationContextProvider"
|
||||||
import SearchSidebar from "../Layout/Search";
|
import SearchSidebar from "../Layout/Search";
|
||||||
import InstallationList from "./InstallationList";
|
import InstallationList from "./InstallationList";
|
||||||
import Installation from "./Installation";
|
import Installation from "./Installation";
|
||||||
|
import CheckboxTree from "./Log/CheckboxTree";
|
||||||
|
import LogContextProvider from "../Context/LogContextProvider";
|
||||||
|
|
||||||
const Installations = () => {
|
const Installations = () => {
|
||||||
return (
|
return (
|
||||||
<InstallationContextProvider>
|
<InstallationContextProvider>
|
||||||
|
<LogContextProvider>
|
||||||
<Grid container spacing={2} height="100%">
|
<Grid container spacing={2} height="100%">
|
||||||
<Grid item xs={3}>
|
<Grid item xs={3}>
|
||||||
<SearchSidebar
|
<SearchSidebar
|
||||||
id="installations-search-sidebar"
|
id="installations-search-sidebar"
|
||||||
listComponent={InstallationList}
|
listComponent={InstallationList}
|
||||||
/>
|
/>
|
||||||
|
<CheckboxTree />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={9}>
|
<Grid item xs={9}>
|
||||||
<InstallationTabs />
|
<InstallationTabs />
|
||||||
|
@ -32,6 +36,7 @@ const Installations = () => {
|
||||||
</Routes>
|
</Routes>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
</LogContextProvider>
|
||||||
</InstallationContextProvider>
|
</InstallationContextProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
import { TreeItem, TreeView } from "@mui/lab";
|
||||||
|
import { Checkbox, Divider } from "@mui/material";
|
||||||
|
import { useContext, ReactNode } from "react";
|
||||||
|
import { LogContext } from "../../Context/LogContextProvider";
|
||||||
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
|
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||||
|
import useRouteMatch from "../../../hooks/useRouteMatch";
|
||||||
|
import routes from "../../../routes.json";
|
||||||
|
|
||||||
|
export interface ToggleElement {
|
||||||
|
[key: string]: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TreeElement {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
children: TreeElement[];
|
||||||
|
checked?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CheckboxTree = () => {
|
||||||
|
const { toggles, setCheckedToggles, checkedToggles } = useContext(LogContext);
|
||||||
|
const routeMatch = useRouteMatch([
|
||||||
|
routes.installations + routes.list + routes.log + ":id",
|
||||||
|
]);
|
||||||
|
|
||||||
|
const getNodes = (element: TreeElement): null | ReactNode => {
|
||||||
|
return element.children.length > 0 ? renderTree(element.children) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCheckChildren = (children: TreeElement[], checked?: boolean) => {
|
||||||
|
if (children.length > 0) {
|
||||||
|
children.forEach((child) => {
|
||||||
|
setCheckedToggles((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
[child.id]: !checked,
|
||||||
|
}));
|
||||||
|
if (child.children.length > 0) {
|
||||||
|
handleCheckChildren(child.children, checked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClick = (
|
||||||
|
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
|
||||||
|
element: TreeElement,
|
||||||
|
checked?: boolean
|
||||||
|
) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
handleCheckChildren([element], checked);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExpandClick = (
|
||||||
|
event: React.MouseEvent<HTMLLIElement, MouseEvent>
|
||||||
|
) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderTree = (data: TreeElement[]): ReactNode => {
|
||||||
|
return data.map((element) => {
|
||||||
|
const checked = checkedToggles?.[element.id];
|
||||||
|
const splitName = element.name.split("/");
|
||||||
|
return (
|
||||||
|
<TreeItem
|
||||||
|
id={"checkbox-tree-" + element.name}
|
||||||
|
key={element.name}
|
||||||
|
nodeId={element.name}
|
||||||
|
onClick={handleExpandClick}
|
||||||
|
label={
|
||||||
|
<>
|
||||||
|
<Checkbox
|
||||||
|
checked={checked}
|
||||||
|
onClick={(e) => handleClick(e, element, checked)}
|
||||||
|
/>
|
||||||
|
{splitName[splitName.length - 1]}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
sx={{
|
||||||
|
".MuiTreeItem-content": { paddingY: "5px" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{getNodes(element)}
|
||||||
|
</TreeItem>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Divider sx={{ mt: 2 }} />
|
||||||
|
{toggles !== null && routeMatch !== null && (
|
||||||
|
<TreeView
|
||||||
|
aria-label="rich object"
|
||||||
|
defaultCollapseIcon={<ExpandMoreIcon />}
|
||||||
|
defaultExpandIcon={<ChevronRightIcon />}
|
||||||
|
sx={{
|
||||||
|
height: 480,
|
||||||
|
flexGrow: 1,
|
||||||
|
overflow: "auto",
|
||||||
|
overflowX: "hidden",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{renderTree(toggles)}
|
||||||
|
</TreeView>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CheckboxTree;
|
|
@ -1,15 +1,15 @@
|
||||||
import Plot from "react-plotly.js";
|
import Plot from "react-plotly.js";
|
||||||
import { RecordSeries } from "../../../dataCache/data";
|
import { RecordSeries } from "../../../dataCache/data";
|
||||||
import { parseCsv, transformToGraphData } from "../../../util/graph.util";
|
import { GraphData, mergeDeep, parseCsv } from "../../../util/graph.util";
|
||||||
import { TimeRange, TimeSpan, UnixTime } from "../../../dataCache/time";
|
import { TimeRange, TimeSpan, UnixTime } from "../../../dataCache/time";
|
||||||
import { ReactNode, useEffect, useMemo, useState } from "react";
|
import { useContext, useEffect, useMemo, useState } from "react";
|
||||||
import { BehaviorSubject, startWith, throttleTime, withLatestFrom } from "rxjs";
|
import { BehaviorSubject, startWith, throttleTime, withLatestFrom } from "rxjs";
|
||||||
import { S3Access } from "../../../dataCache/S3/S3Access";
|
import { S3Access } from "../../../dataCache/S3/S3Access";
|
||||||
import DataCache, { FetchResult } from "../../../dataCache/dataCache";
|
import DataCache, { FetchResult } from "../../../dataCache/dataCache";
|
||||||
import { TreeItem, TreeView } from "@mui/lab";
|
|
||||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
import { LogContext } from "../../Context/LogContextProvider";
|
||||||
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
import { TreeElement, ToggleElement } from "./CheckboxTree";
|
||||||
import { Checkbox } from "@mui/material";
|
import { isDefined } from "../../../dataCache/utils/maybe";
|
||||||
|
|
||||||
export const createTimes = (
|
export const createTimes = (
|
||||||
range: TimeRange,
|
range: TimeRange,
|
||||||
|
@ -27,16 +27,19 @@ const NUMBER_OF_NODES = 100;
|
||||||
|
|
||||||
const ScalarGraph = () => {
|
const ScalarGraph = () => {
|
||||||
const timeRange = createTimes(
|
const timeRange = createTimes(
|
||||||
UnixTime.fromTicks(1682085650).rangeBefore(TimeSpan.fromDays(1)),
|
UnixTime.fromTicks(1682085650).rangeBefore(TimeSpan.fromDays(4)),
|
||||||
NUMBER_OF_NODES
|
NUMBER_OF_NODES
|
||||||
);
|
);
|
||||||
const [timeSeries, setTimeSeries] = useState<RecordSeries>([]);
|
const [timeSeries, setTimeSeries] = useState<RecordSeries>([]);
|
||||||
const [uiRevision, setUiRevision] = useState(Math.random());
|
|
||||||
const [range, setRange] = useState([
|
const [range, setRange] = useState([
|
||||||
timeRange[0].toDate(),
|
timeRange[0].toDate(),
|
||||||
timeRange[timeRange.length - 1].toDate(),
|
timeRange[timeRange.length - 1].toDate(),
|
||||||
]);
|
]);
|
||||||
const [toggles, setToggles] = useState<TreeElement[] | null>(null);
|
const [uiRevision, setUiRevision] = useState(Math.random());
|
||||||
|
const [plotTitles, setPlotTitles] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const { toggles, setToggles, setCheckedToggles, checkedToggles } =
|
||||||
|
useContext(LogContext);
|
||||||
|
|
||||||
const times$ = useMemo(() => new BehaviorSubject(timeRange), []);
|
const times$ = useMemo(() => new BehaviorSubject(timeRange), []);
|
||||||
|
|
||||||
|
@ -49,23 +52,37 @@ const ScalarGraph = () => {
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
function insert(
|
const insert = (
|
||||||
children: TreeElement[] = [],
|
children: TreeElement[] = [],
|
||||||
[head, ...tail]: string[]
|
[head, ...tail]: string[]
|
||||||
): TreeElement[] {
|
): TreeElement[] => {
|
||||||
let child = children.find((child) => child.name === head);
|
let child = children.find((child) => child.name === head);
|
||||||
if (!child)
|
|
||||||
|
if (!child) {
|
||||||
children.push(
|
children.push(
|
||||||
(child = {
|
(child = {
|
||||||
id: head + tail.join("_"),
|
id: head,
|
||||||
name: head,
|
name: head,
|
||||||
checked: false,
|
|
||||||
children: [],
|
children: [],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
if (tail.length > 0) insert(child.children, tail);
|
|
||||||
return children;
|
|
||||||
}
|
}
|
||||||
|
if (tail.length > 0) {
|
||||||
|
insert(child.children, tail);
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
};
|
||||||
|
|
||||||
|
const flattenToggles = (toggles: TreeElement[]): ToggleElement => {
|
||||||
|
return toggles.reduce((acc, current) => {
|
||||||
|
if (current.children.length > 0) {
|
||||||
|
acc[current.id] = false;
|
||||||
|
return { ...acc, ...flattenToggles(current.children) };
|
||||||
|
}
|
||||||
|
acc[current.id] = false;
|
||||||
|
return acc;
|
||||||
|
}, {} as ToggleElement);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const subscription = cache.gotData
|
const subscription = cache.gotData
|
||||||
|
@ -78,79 +95,34 @@ const ScalarGraph = () => {
|
||||||
const timeSeries = cache.getSeries(times);
|
const timeSeries = cache.getSeries(times);
|
||||||
setTimeSeries(timeSeries);
|
setTimeSeries(timeSeries);
|
||||||
const toggleValues = timeSeries.find((timeStamp) => timeStamp.value);
|
const toggleValues = timeSeries.find((timeStamp) => timeStamp.value);
|
||||||
|
|
||||||
if (toggles === null && toggleValues && toggleValues.value) {
|
if (toggles === null && toggleValues && toggleValues.value) {
|
||||||
setToggles(
|
console.log("toggles inside", toggles);
|
||||||
Object.keys(toggleValues.value)
|
const treeElements = Object.keys(toggleValues.value)
|
||||||
.map((path) => path.split("/").slice(1))
|
.map((path) => {
|
||||||
|
return path
|
||||||
|
.split("/")
|
||||||
|
.map(
|
||||||
|
(split, i) =>
|
||||||
|
"/" +
|
||||||
|
path
|
||||||
|
.split("/")
|
||||||
|
.slice(1, i + 1)
|
||||||
|
.join("/")
|
||||||
|
)
|
||||||
|
.slice(1);
|
||||||
|
})
|
||||||
.reduce(
|
.reduce(
|
||||||
(children, path) => insert(children, path),
|
(children, path) => insert(children, path),
|
||||||
[] as TreeElement[]
|
[] as TreeElement[]
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
console.log("elements", treeElements);
|
||||||
|
setToggles(treeElements);
|
||||||
|
setCheckedToggles(flattenToggles(treeElements));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => subscription.unsubscribe();
|
return () => subscription.unsubscribe();
|
||||||
}, []);
|
}, [toggles]);
|
||||||
|
|
||||||
interface TreeElement {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
children: TreeElement[];
|
|
||||||
checked: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getNodes = (element: TreeElement): null | ReactNode => {
|
|
||||||
return element.children.length > 0 ? renderTree(element.children) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderTree = (data: TreeElement[]): ReactNode => {
|
|
||||||
return data.map((element) => {
|
|
||||||
return (
|
|
||||||
<TreeItem
|
|
||||||
id={"checkbox-tree-" + element.name}
|
|
||||||
key={element.name}
|
|
||||||
nodeId={element.name}
|
|
||||||
label={
|
|
||||||
<>
|
|
||||||
<Checkbox
|
|
||||||
checked={element.checked}
|
|
||||||
onClick={() => {
|
|
||||||
if (toggles) {
|
|
||||||
const togglesValue = toggles;
|
|
||||||
const index = toggles?.findIndex((toggle) => {
|
|
||||||
return element.id === toggle.id;
|
|
||||||
});
|
|
||||||
if (index > 0) {
|
|
||||||
togglesValue[index] = {
|
|
||||||
...element,
|
|
||||||
checked: !element.checked,
|
|
||||||
};
|
|
||||||
setToggles(togglesValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{element.name}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
sx={{
|
|
||||||
".MuiTreeItem-content": { paddingY: "12px" },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{getNodes(element)}
|
|
||||||
</TreeItem>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const round = (date: Date) => {
|
|
||||||
const minutes = 30;
|
|
||||||
const ms = 1000 * 60 * minutes;
|
|
||||||
|
|
||||||
return new Date(Math.round(date.getTime() / ms) * ms);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchData = (
|
const fetchData = (
|
||||||
timestamp: UnixTime
|
timestamp: UnixTime
|
||||||
|
@ -179,12 +151,60 @@ const ScalarGraph = () => {
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const transformToGraphData = (timeStampData: RecordSeries) => {
|
||||||
|
const graphData = timeStampData.reduce((acc, curr) => {
|
||||||
|
if (isDefined(curr.value)) {
|
||||||
|
const timeStampObj = Object.keys(curr.value).reduce(
|
||||||
|
(pathAcc, currPath) => {
|
||||||
|
if (currPath) {
|
||||||
|
return {
|
||||||
|
...pathAcc,
|
||||||
|
[currPath]: {
|
||||||
|
x: [new Date(curr.time.ticks * 1000)],
|
||||||
|
y: [curr.value ? curr.value[currPath] : 0],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return pathAcc;
|
||||||
|
},
|
||||||
|
{} as GraphData
|
||||||
|
);
|
||||||
|
if (plotTitles.length === 0) {
|
||||||
|
setPlotTitles(Object.keys(curr.value));
|
||||||
|
}
|
||||||
|
return mergeDeep(acc, timeStampObj);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {} as GraphData);
|
||||||
|
|
||||||
|
if (Object.keys(graphData).length > 0) {
|
||||||
|
return graphData;
|
||||||
|
}
|
||||||
|
return plotTitles.reduce(
|
||||||
|
(acc, curr) => ({
|
||||||
|
...acc,
|
||||||
|
[curr]: {
|
||||||
|
x: [],
|
||||||
|
y: [],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{} as GraphData
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const renderGraphs = () => {
|
const renderGraphs = () => {
|
||||||
|
if (checkedToggles) {
|
||||||
const coordinateTimeSeries = transformToGraphData(timeSeries);
|
const coordinateTimeSeries = transformToGraphData(timeSeries);
|
||||||
return Object.keys(coordinateTimeSeries).map((path) => {
|
console.log("coordinateTimeSeries", coordinateTimeSeries, checkedToggles);
|
||||||
|
return Object.keys(coordinateTimeSeries)
|
||||||
|
.filter((path) => {
|
||||||
|
return checkedToggles[path];
|
||||||
|
})
|
||||||
|
.map((path) => {
|
||||||
const data = coordinateTimeSeries[path] ?? { x: [], y: [] };
|
const data = coordinateTimeSeries[path] ?? { x: [], y: [] };
|
||||||
return (
|
return (
|
||||||
<Plot
|
<Plot
|
||||||
|
key={path}
|
||||||
data={[
|
data={[
|
||||||
{
|
{
|
||||||
...data,
|
...data,
|
||||||
|
@ -226,6 +246,7 @@ const ScalarGraph = () => {
|
||||||
),
|
),
|
||||||
NUMBER_OF_NODES
|
NUMBER_OF_NODES
|
||||||
);
|
);
|
||||||
|
console.log("times", times);
|
||||||
cache.getSeries(times);
|
cache.getSeries(times);
|
||||||
times$.next(times);
|
times$.next(times);
|
||||||
}
|
}
|
||||||
|
@ -233,27 +254,8 @@ const ScalarGraph = () => {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
return <>{renderGraphs()}</>;
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{renderGraphs()}
|
|
||||||
{toggles !== null && (
|
|
||||||
<TreeView
|
|
||||||
aria-label="rich object"
|
|
||||||
defaultCollapseIcon={<ExpandMoreIcon />}
|
|
||||||
defaultExpandIcon={<ChevronRightIcon />}
|
|
||||||
sx={{
|
|
||||||
height: 480,
|
|
||||||
flexGrow: 1,
|
|
||||||
overflow: "auto",
|
|
||||||
overflowX: "hidden",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{renderTree(toggles)}
|
|
||||||
</TreeView>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
export default ScalarGraph;
|
export default ScalarGraph;
|
||||||
|
|
|
@ -12,7 +12,7 @@ const SearchSidebar = (props: SearchSidebarProps) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ height: "100%" }}>
|
<div style={{ height: "500px", overflow: "hidden" }}>
|
||||||
<TextField
|
<TextField
|
||||||
id={id}
|
id={id}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
|
|
|
@ -22,30 +22,6 @@ export const mergeDeep = (...objects: any[]) => {
|
||||||
}, {} as GraphData);
|
}, {} as GraphData);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const transformToGraphData = (timeStampData: RecordSeries) => {
|
|
||||||
return timeStampData.reduce((acc, curr) => {
|
|
||||||
if (isDefined(curr.value)) {
|
|
||||||
const timeStampObj = Object.keys(curr.value).reduce(
|
|
||||||
(pathAcc, currPath) => {
|
|
||||||
if (currPath) {
|
|
||||||
return {
|
|
||||||
...pathAcc,
|
|
||||||
[currPath]: {
|
|
||||||
x: [new Date(curr.time.ticks * 1000)],
|
|
||||||
y: [curr.value ? curr.value[currPath] : 0],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return pathAcc;
|
|
||||||
},
|
|
||||||
{} as GraphData
|
|
||||||
);
|
|
||||||
return mergeDeep(acc, timeStampObj);
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, {} as GraphData);
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface GraphCoordinates {
|
export interface GraphCoordinates {
|
||||||
x: Datum[] | Datum[][] | TypedArray;
|
x: Datum[] | Datum[][] | TypedArray;
|
||||||
y: Datum[] | Datum[][] | TypedArray;
|
y: Datum[] | Datum[][] | TypedArray;
|
||||||
|
|
Loading…
Reference in New Issue