working version before refactore
This commit is contained in:
parent
9844c7a0ad
commit
ca05fd5b3e
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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={{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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(";");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue