working version before refactore

This commit is contained in:
Sina Blattmann 2023-05-31 08:49:51 +02:00
parent 9844c7a0ad
commit ca05fd5b3e
9 changed files with 935 additions and 469 deletions

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,6 @@
"@mui/lab": "^5.0.0-alpha.120", "@mui/lab": "^5.0.0-alpha.120",
"@mui/material": "^5.11.7", "@mui/material": "^5.11.7",
"@mui/x-date-pickers": "^6.5.0", "@mui/x-date-pickers": "^6.5.0",
"@mui/x-date-pickers-pro": "^6.5.0",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
@ -60,7 +59,15 @@
"extends": [ "extends": [
"react-app", "react-app",
"react-app/jest" "react-app/jest"
] ],
"plugins": [
"formatjs"
],
"rules": {
"formatjs/enforce-default-message": "warn",
"formatjs/enforce-id": "warn",
"formatjs/no-literal-string-in-jsx": "warn"
}
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
@ -76,6 +83,7 @@
}, },
"devDependencies": { "devDependencies": {
"@formatjs/cli": "^6.0.3", "@formatjs/cli": "^6.0.3",
"@types/react-plotly.js": "^2.6.0" "@types/react-plotly.js": "^2.6.0",
"eslint-plugin-formatjs": "^4.10.1"
} }
} }

View File

@ -32,10 +32,6 @@ const CheckboxTree = () => {
if (children.length > 0) { if (children.length > 0) {
children.forEach((child) => { children.forEach((child) => {
setCheckedToggles((prevState) => { setCheckedToggles((prevState) => {
console.log("setChecked", {
...prevState,
[child.id]: !checked,
});
return { return {
...prevState, ...prevState,
[child.id]: !checked, [child.id]: !checked,
@ -63,7 +59,6 @@ const CheckboxTree = () => {
event.stopPropagation(); event.stopPropagation();
}; };
const renderTree = (data: TreeElement[]): ReactNode => { const renderTree = (data: TreeElement[]): ReactNode => {
console.log("checkedToggles", checkedToggles);
return data.map((element) => { return data.map((element) => {
const checked = checkedToggles?.[element.id]; const checked = checkedToggles?.[element.id];
const splitName = element.name.split("/"); const splitName = element.name.split("/");
@ -98,7 +93,6 @@ const CheckboxTree = () => {
<> <>
<Divider sx={{ mt: 2 }} /> <Divider sx={{ mt: 2 }} />
<TreeView <TreeView
aria-label="rich object"
defaultCollapseIcon={<ExpandMoreIcon />} defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />} defaultExpandIcon={<ChevronRightIcon />}
sx={{ sx={{

View File

@ -1,62 +1,80 @@
import * as React from "react"; import * as React from "react";
import dayjs, { Dayjs } from "dayjs"; import { Button, Dialog, DialogContent, DialogTitle } from "@mui/material";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { useState } from "react";
import { UnixTime, TimeSpan } from "../../../dataCache/time";
import { createTimes } from "../../../util/graph.util";
import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { StaticDateRangePicker } from "@mui/x-date-pickers-pro/StaticDateRangePicker"; import dayjs from "dayjs";
import { PickersShortcutsItem } from "@mui/x-date-pickers/PickersShortcuts"; import InnovenergyButton from "../../Layout/InnovenergyButton";
import { DateRange } from "@mui/x-date-pickers-pro";
const shortcutsItems: PickersShortcutsItem<DateRange<Dayjs>>[] = [ interface DateRangePickerProps {
{ setRange: (value: Date[]) => void;
label: "This Week", range: Date[];
getValue: () => { getCacheSeries: (xaxisRange0: number, xaxisRange1: number) => void;
const today = dayjs();
return [today.startOf("week"), today.endOf("week")];
},
},
{
label: "Last Week",
getValue: () => {
const today = dayjs();
const prevWeek = today.subtract(7, "day");
return [prevWeek.startOf("week"), prevWeek.endOf("week")];
},
},
{
label: "Last 7 Days",
getValue: () => {
const today = dayjs();
return [today.subtract(7, "day"), today];
},
},
{
label: "Current Month",
getValue: () => {
const today = dayjs();
return [today.startOf("month"), today.endOf("month")];
},
},
{
label: "Next Month",
getValue: () => {
const today = dayjs();
const startOfNextMonth = today.endOf("month").add(1, "day");
return [startOfNextMonth, startOfNextMonth.endOf("month")];
},
},
{ label: "Reset", getValue: () => [null, null] },
];
export default function BasicRangeShortcuts() {
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<StaticDateRangePicker
slotProps={{
shortcuts: {
items: shortcutsItems,
},
}}
/>
</LocalizationProvider>
);
} }
const DateRangePicker = (props: DateRangePickerProps) => {
const { setRange, range, getCacheSeries } = props;
const [open, setOpen] = useState(false);
return (
<>
<InnovenergyButton onClick={() => setOpen(true)}>
Set range
</InnovenergyButton>
<Dialog open={open} maxWidth="lg" onClose={() => setOpen(false)}>
<DialogTitle id="dialog-title">Set range</DialogTitle>
<DialogContent>
<div>
<Button
onClick={() => {
const weekRange = createTimes(
UnixTime.now().rangeBefore(TimeSpan.fromDays(7)),
100
);
setRange([
weekRange[0].toDate(),
weekRange[weekRange.length - 1].toDate(),
]);
getCacheSeries(
weekRange[0].ticks,
weekRange[weekRange.length - 1].ticks
);
}}
>
Last week
</Button>
</div>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
label="From date"
value={dayjs(range[0])}
onChange={(newValue) => {
if (newValue) {
const fromDate = newValue.toDate();
const toDate = range[1];
setRange([fromDate, toDate]);
getCacheSeries(+fromDate, +toDate);
}
}}
/>
<DatePicker
label="To date"
value={dayjs(range[1])}
onChange={(newValue) => {
if (newValue) {
const fromDate = newValue.toDate();
const toDate = range[1];
setRange([fromDate, toDate]);
getCacheSeries(+fromDate, +toDate);
}
}}
/>
</LocalizationProvider>
</DialogContent>
</Dialog>
</>
);
};
export default DateRangePicker;

View File

@ -19,14 +19,17 @@ import { LogContext } from "../../Context/LogContextProvider";
import { TreeElement } from "./CheckboxTree"; import { TreeElement } from "./CheckboxTree";
import { isDefined } from "../../../dataCache/utils/maybe"; import { isDefined } from "../../../dataCache/utils/maybe";
import { Data, Layout } from "plotly.js"; import { Data, Layout } from "plotly.js";
import { Alert } from "@mui/material"; import { Alert, Button, ToggleButton, ToggleButtonGroup } from "@mui/material";
import DateRangePicker from "./DateRangePicker";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
const NUMBER_OF_NODES = 100; const NUMBER_OF_NODES = 100;
const ScalarGraph = () => { const ScalarGraph = () => {
const timeRange = createTimes( const timeRange = createTimes(
UnixTime.now() /* .fromTicks(1682085650) */ UnixTime.now() /* .fromTicks(1682085650) */
.earlier(TimeSpan.fromDays(2)) .earlier(TimeSpan.fromDays(7))
.rangeBefore(TimeSpan.fromDays(4)), .rangeBefore(TimeSpan.fromDays(4)),
NUMBER_OF_NODES NUMBER_OF_NODES
); );
@ -149,6 +152,18 @@ const ScalarGraph = () => {
); );
}; };
const getCacheSeries = (xaxisRange0: number, xaxisRange1: number) => {
const times = createTimes(
TimeRange.fromTimes(
UnixTime.fromDate(new Date(xaxisRange0)),
UnixTime.fromDate(new Date(xaxisRange1))
),
NUMBER_OF_NODES
);
cache.getSeries(times);
times$.next(times);
};
const renderGraphs = () => { const renderGraphs = () => {
if (checkedToggles) { if (checkedToggles) {
const coordinateTimeSeries = transformToGraphData(timeSeries); const coordinateTimeSeries = transformToGraphData(timeSeries);
@ -156,74 +171,81 @@ const ScalarGraph = () => {
return checkedToggles[path]; return checkedToggles[path];
}); });
if (visibleGraphs.length > 0) { if (visibleGraphs.length > 0) {
return visibleGraphs.map((path) => { return (
const isScalar = isNumeric(coordinateTimeSeries[path].y[0]); <>
const data = isScalar <LocalizationProvider dateAdapter={AdapterDayjs}>
? [ <DateRangePicker
{ setRange={setRange}
...coordinateTimeSeries[path], range={range}
type: "scatter", getCacheSeries={getCacheSeries}
mode: "lines+markers", />
fill: "tozeroy", </LocalizationProvider>
}, {visibleGraphs.map((path) => {
] const isScalar = isNumeric(coordinateTimeSeries[path].y[0]);
: transformToBarGraphData(coordinateTimeSeries[path]); const data = isScalar
const barGraphLayout: Partial<Layout> = !isScalar ? [
? { {
bargap: 0, ...coordinateTimeSeries[path],
barmode: "stack", type: "scatter",
barnorm: "percent", mode: "lines+markers",
} fill: "tozeroy",
: {}; },
]
: transformToBarGraphData(coordinateTimeSeries[path]);
const barGraphLayout: Partial<Layout> = !isScalar
? {
bargap: 0,
barmode: "stack",
barnorm: "percent",
}
: {};
return ( return (
<Plot <Plot
key={path} key={path}
data={data as Data[]} data={data as Data[]}
layout={{ layout={{
width: 1000, width: 1000,
height: 500, height: 500,
title: path, title: path,
uirevision: uiRevision, uirevision: uiRevision,
xaxis: { xaxis: {
autorange: false, autorange: false,
range: range, range: range,
type: "date", type: "date",
}, },
yaxis: { yaxis: {
rangemode: "tozero", rangemode: "tozero",
}, },
...barGraphLayout, ...barGraphLayout,
}} }}
config={{ config={{
modeBarButtonsToRemove: [ modeBarButtonsToRemove: [
"lasso2d", "lasso2d",
"select2d", "select2d",
"pan2d", "pan2d",
"autoScale2d", "autoScale2d",
], ],
}} }}
onRelayout={(params) => { onRelayout={(params) => {
const xaxisRange0 = params["xaxis.range[0]"]; console.log("relayout");
const xaxisRange1 = params["xaxis.range[1]"]; const xaxisRange0 = params["xaxis.range[0]"];
const xaxisRange1 = params["xaxis.range[1]"];
if (xaxisRange0 && xaxisRange1) { if (xaxisRange0 && xaxisRange1) {
setRange([new Date(xaxisRange0), new Date(xaxisRange1)]); setRange([new Date(xaxisRange0), new Date(xaxisRange1)]);
setUiRevision(Math.random()); setUiRevision(Math.random());
const times = createTimes( console.log("ranges", xaxisRange0);
TimeRange.fromTimes( getCacheSeries(xaxisRange0, xaxisRange1);
UnixTime.fromDate(new Date(xaxisRange0)), }
UnixTime.fromDate(new Date(xaxisRange1)) }}
), onRestyle={() => "event restyle"}
NUMBER_OF_NODES onRedraw={() => "event restyle"}
); />
cache.getSeries(times); );
times$.next(times); })}
} </>
}} );
/>
);
});
} }
return ( return (
<Alert sx={{ mt: 2 }} severity="info"> <Alert sx={{ mt: 2 }} severity="info">

View File

@ -36,7 +36,7 @@ const rows = [
const BasicTable = () => { const BasicTable = () => {
return ( return (
<TableContainer component={Paper}> <TableContainer component={Paper}>
<Table aria-label="simple table"> {/* <Table aria-label="simple table">
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell>Device</TableCell> <TableCell>Device</TableCell>
@ -57,7 +57,7 @@ const BasicTable = () => {
</TableRow> </TableRow>
))} ))}
</TableBody> </TableBody>
</Table> </Table> */}
</TableContainer> </TableContainer>
); );
}; };

View File

@ -9,11 +9,11 @@ import UserForm from "./UserForm";
const AddUser = () => { const AddUser = () => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const { locale } = useIntl(); const intl = useIntl();
const handleSubmit = (data: Partial<I_User>) => { const handleSubmit = (data: Partial<I_User>) => {
return axiosConfig return axiosConfig
.post("/CreateUser", { ...data, password: "", language: locale }) .post("/CreateUser", { ...data, password: "", language: intl.locale })
.then((res) => { .then((res) => {
setOpen(false); setOpen(false);
return res; return res;
@ -42,12 +42,14 @@ const AddUser = () => {
maxWidth="sm" maxWidth="sm"
> >
<DialogTitle> <DialogTitle>
Create new user <FormattedMessage
id="createNewUser"
defaultMessage="Create new user"
/>
<IconButton <IconButton
edge="start" edge="start"
color="inherit" color="inherit"
onClick={() => setOpen(false)} onClick={() => setOpen(false)}
aria-label="close"
sx={{ sx={{
position: "absolute", position: "absolute",
right: 8, right: 8,

View File

@ -17,7 +17,10 @@ const UserTabs = () => {
<AntTabs <AntTabs
id="users-tabs" id="users-tabs"
value={routeMatch?.pattern?.path ?? routes.user + ":id"} value={routeMatch?.pattern?.path ?? routes.user + ":id"}
aria-label="user tabs" aria-label={intl.formatMessage({
id: "userTabs",
defaultMessage: "user tabs",
})}
> >
<StyledTab <StyledTab
id="users-tab-user" id="users-tab-user"

View File

@ -38,9 +38,6 @@ export const parseCsv = (text: string) => {
.split(/\r?\n/) .split(/\r?\n/)
.filter((split) => split.length > 0) .filter((split) => split.length > 0)
.map((l) => { .map((l) => {
if (l.length === 0) {
console.log("splitting", l, l.split(";"));
}
return l.split(";"); return l.split(";");
}); });