@iotready/nextjs-components-library 1.0.0-preview25 → 1.0.0-preview27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/charts/TrendChart.d.ts +17 -5
- package/components/charts/TrendChart.js +5 -5
- package/components/groups/GroupsDevices.d.ts +3 -2
- package/components/groups/GroupsDevices.js +63 -15
- package/components/settings/DynamicMenu.d.ts +1 -0
- package/components/settings/DynamicMenu.js +2 -1
- package/package.json +1 -1
- package/server-actions/influx.d.ts +16 -4
- package/server-actions/influx.js +10 -10
|
@@ -10,15 +10,27 @@ type Measure = {
|
|
|
10
10
|
unit: string;
|
|
11
11
|
stepped: boolean;
|
|
12
12
|
};
|
|
13
|
-
declare const TrendChart: ({
|
|
14
|
-
|
|
13
|
+
declare const TrendChart: ({ filter, measures1, annotationsDataFn, measures2, enableDatePicker, handleGetInfluxData, handleGetDwSlotsCB, handleExportDataCB, theme, initialTimeStart, initialTimeEnd }: {
|
|
14
|
+
filter: {
|
|
15
|
+
field: string;
|
|
16
|
+
value: string;
|
|
17
|
+
};
|
|
15
18
|
annotationsDataFn?: () => Promise<any>;
|
|
16
19
|
measures1?: Array<Measure>;
|
|
17
20
|
measures2?: Array<Measure>;
|
|
18
21
|
enableDatePicker: boolean;
|
|
19
|
-
handleGetInfluxData: (measure: string, timeStart: number, timeEnd: number,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
handleGetInfluxData: (measure: string, timeStart: number, timeEnd: number, filter: {
|
|
23
|
+
field: string;
|
|
24
|
+
value: string;
|
|
25
|
+
}, timeGroup: string, raw: boolean, fill?: InfluxFillType, filterTag?: number, includeTag?: FilterTagMode) => Promise<any>;
|
|
26
|
+
handleGetDwSlotsCB?: (timeStart: number, timeEnd: number, filter: {
|
|
27
|
+
field: string;
|
|
28
|
+
value: string;
|
|
29
|
+
}) => Promise<any>;
|
|
30
|
+
handleExportDataCB?: (measure: string, timeStart: number, timeEnd: number, filter: {
|
|
31
|
+
field: string;
|
|
32
|
+
value: string;
|
|
33
|
+
}) => Promise<any>;
|
|
22
34
|
theme: Theme;
|
|
23
35
|
initialTimeStart?: number;
|
|
24
36
|
initialTimeEnd?: number;
|
|
@@ -184,7 +184,7 @@ function getCsvData(data, measures) {
|
|
|
184
184
|
.join('\n');
|
|
185
185
|
}
|
|
186
186
|
// eslint-disable-next-line no-unused-vars
|
|
187
|
-
const TrendChart = ({
|
|
187
|
+
const TrendChart = ({ filter, measures1, annotationsDataFn, measures2, enableDatePicker, handleGetInfluxData, handleGetDwSlotsCB, handleExportDataCB, theme, initialTimeStart, initialTimeEnd }) => {
|
|
188
188
|
const [chartJsLoaded, setChartJsLoaded] = useState(false);
|
|
189
189
|
// Dichiarazione di annotationsData come funzione che ritorna una Promise<any>
|
|
190
190
|
const [annotationsData, setAnnotationsData] = useState(null);
|
|
@@ -297,7 +297,7 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
|
|
|
297
297
|
setLoadingButton(true);
|
|
298
298
|
if (handleExportDataCB) {
|
|
299
299
|
const data = await Promise.all(measures.map(async (measure) => {
|
|
300
|
-
return await handleExportDataCB(measure.name, timeStart, timeEnd,
|
|
300
|
+
return await handleExportDataCB(measure.name, timeStart, timeEnd, filter);
|
|
301
301
|
}));
|
|
302
302
|
const csvData = getCsvData(data, measures);
|
|
303
303
|
setCsvData(csvData);
|
|
@@ -336,7 +336,7 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
|
|
|
336
336
|
const rawQuery = intervalInSeconds < 86400;
|
|
337
337
|
let tempSlots = [];
|
|
338
338
|
if (handleGetDwSlotsCB) {
|
|
339
|
-
const dwValues = await handleGetDwSlotsCB(timeStart, timeEnd,
|
|
339
|
+
const dwValues = await handleGetDwSlotsCB(timeStart, timeEnd, filter);
|
|
340
340
|
tempSlots = getDwSlotsFromValues(dwValues);
|
|
341
341
|
}
|
|
342
342
|
// Combine measures and track their source
|
|
@@ -351,7 +351,7 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
|
|
|
351
351
|
if (measure.dwPolltime) {
|
|
352
352
|
const dwPolltime = getPollTime(intervalInSeconds, measure.dwPolltime);
|
|
353
353
|
// Query DW solo tag=100
|
|
354
|
-
const rawDwPoints = await handleGetInfluxData(measure.name, timeStart, timeEnd,
|
|
354
|
+
const rawDwPoints = await handleGetInfluxData(measure.name, timeStart, timeEnd, filter, dwPolltime, false, "previous", 100, FilterTagMode.DW);
|
|
355
355
|
dwSlots = tempSlots;
|
|
356
356
|
if (dwSlots.length > 0) {
|
|
357
357
|
dwPoints = rawDwPoints.filter((p) => dwSlots.some(slot => p.x >= slot.start && p.x <= slot.end));
|
|
@@ -360,7 +360,7 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
|
|
|
360
360
|
dwPoints = rawDwPoints;
|
|
361
361
|
}
|
|
362
362
|
}
|
|
363
|
-
const stdPoints = await handleGetInfluxData(measure.name, timeStart, timeEnd,
|
|
363
|
+
const stdPoints = await handleGetInfluxData(measure.name, timeStart, timeEnd, filter, polltime, !measure.polltime && rawQuery, !measure.polltime ? "none" : "null", 100, FilterTagMode.Exclude);
|
|
364
364
|
const filtered = dwSlots.length
|
|
365
365
|
? stdPoints.filter((p) => !dwSlots.some(slot => p.x >= slot.start && p.x <= slot.end))
|
|
366
366
|
: stdPoints;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Theme } from "@emotion/react";
|
|
2
2
|
import { UserType, AssetType, DevicePositionType, TrackleDeviceType } from "../../types";
|
|
3
|
-
declare const GroupsDevices: ({ userInfo, handleGetUsersList, handleAddUserToGroup, handleRemoveUserFromGroup, handleGetGroups, handleGetUsersGroup, handleGetDevices, handleUpdateDevice, handleGetPositions, handleAddDevicesToGroup, handleRemoveDevicesFromGroup, handleCreateGroup, handleDeleteGroup, handleUpdateGroup, group, columnsArray, containerDataGrid, props, propsDatagrid, loadingComponent, containerProps, enableMaps, mapsHeight, mapsClickCallback, theme, confirmMui, propsHeaderGroups, forceGetDevices, groupsLabelAll }: {
|
|
3
|
+
declare const GroupsDevices: ({ userInfo, handleGetUsersList, handleAddUserToGroup, handleRemoveUserFromGroup, handleGetGroups, handleGetUsersGroup, handleGetDevices, handleUpdateDevice, handleGetPositions, handleAddDevicesToGroup, handleRemoveDevicesFromGroup, handleCreateGroup, handleDeleteGroup, handleUpdateGroup, group, columnsArray, containerDataGrid, props, propsDatagrid, loadingComponent, containerProps, enableMaps, mapsHeight, mapsClickCallback, theme, confirmMui, propsHeaderGroups, forceGetDevices, customToolbar, groupsLabelAll }: {
|
|
4
4
|
userInfo: UserType;
|
|
5
5
|
handleGetUsersList: ({ page, pageSize }: {
|
|
6
6
|
page: number;
|
|
@@ -33,7 +33,8 @@ declare const GroupsDevices: ({ userInfo, handleGetUsersList, handleAddUserToGro
|
|
|
33
33
|
mapsClickCallback?: (position: DevicePositionType) => void;
|
|
34
34
|
theme: Theme;
|
|
35
35
|
confirmMui?: (options?: any) => Promise<void>;
|
|
36
|
-
forceGetDevices
|
|
36
|
+
forceGetDevices?: number;
|
|
37
|
+
customToolbar?: string[];
|
|
37
38
|
groupsLabelAll?: string;
|
|
38
39
|
}) => string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<import("react").ReactNode> | Promise<import("react").AwaitedReactNode> | null;
|
|
39
40
|
export default GroupsDevices;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { Box, CircularProgress, Autocomplete, TextField, Input, IconButton, Button, Card, CardContent, CardHeader, Modal, Typography, Stack, Tab } from "@mui/material";
|
|
4
|
-
import { cloneElement, isValidElement, useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { cloneElement, isValidElement, useEffect, useMemo, useRef, useState } from "react";
|
|
5
5
|
import AddIcon from '@mui/icons-material/Add';
|
|
6
6
|
import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd';
|
|
7
7
|
import EditIcon from '@mui/icons-material/Edit';
|
|
@@ -10,12 +10,12 @@ import ReadMoreIcon from '@mui/icons-material/ReadMore';
|
|
|
10
10
|
import PlaylistRemoveIcon from '@mui/icons-material/PlaylistRemove';
|
|
11
11
|
import CloseIcon from '@mui/icons-material/Close';
|
|
12
12
|
import { LoadingButton, TabContext, TabList, TabPanel } from "@mui/lab";
|
|
13
|
-
import { DataGrid, GridToolbar } from "@mui/x-data-grid";
|
|
13
|
+
import { DataGrid, GridToolbar, GridToolbarExport, GridToolbarQuickFilter } from "@mui/x-data-grid";
|
|
14
14
|
import GroupUpdate from "./GroupUpdate";
|
|
15
15
|
import BackIcon from '@mui/icons-material/ArrowBack';
|
|
16
16
|
import dynamic from "next/dynamic";
|
|
17
17
|
import { ThemeProvider } from '@mui/material/styles';
|
|
18
|
-
const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, handleRemoveUserFromGroup, handleGetGroups, handleGetUsersGroup, handleGetDevices, handleUpdateDevice, handleGetPositions, handleAddDevicesToGroup, handleRemoveDevicesFromGroup, handleCreateGroup, handleDeleteGroup, handleUpdateGroup, group = 'all', columnsArray = [], containerDataGrid = 'Card', props = {}, propsDatagrid = {}, loadingComponent = _jsx(CircularProgress, {}), containerProps = {}, enableMaps = true, mapsHeight = '400px', mapsClickCallback = () => { }, theme, confirmMui, propsHeaderGroups, forceGetDevices, groupsLabelAll }) => {
|
|
18
|
+
const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, handleRemoveUserFromGroup, handleGetGroups, handleGetUsersGroup, handleGetDevices, handleUpdateDevice, handleGetPositions, handleAddDevicesToGroup, handleRemoveDevicesFromGroup, handleCreateGroup, handleDeleteGroup, handleUpdateGroup, group = 'all', columnsArray = [], containerDataGrid = 'Card', props = {}, propsDatagrid = {}, loadingComponent = _jsx(CircularProgress, {}), containerProps = {}, enableMaps = true, mapsHeight = '400px', mapsClickCallback = () => { }, theme, confirmMui, propsHeaderGroups, forceGetDevices, customToolbar, groupsLabelAll }) => {
|
|
19
19
|
const [devices, setDevices] = useState([]);
|
|
20
20
|
const [positions, setPositions] = useState([]);
|
|
21
21
|
const [loadingDevices, setLoadingDevices] = useState(false);
|
|
@@ -24,6 +24,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
24
24
|
const [editGroup, setEditGroup] = useState(false);
|
|
25
25
|
const [checkboxSelection, setCheckboxSelection] = useState(false);
|
|
26
26
|
const [devicesToAdd, setDevicesToAdd] = useState([]);
|
|
27
|
+
const [deviceSelectedObjs, setDeviceSelectedObjs] = useState([]);
|
|
27
28
|
const [currentGroup, setCurrentGroup] = useState(group);
|
|
28
29
|
const [selectedGroup, setSelectedGroup] = useState(group);
|
|
29
30
|
const [groups, setGroups] = useState(null);
|
|
@@ -35,6 +36,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
35
36
|
const [description, setDescription] = useState('');
|
|
36
37
|
const [groupUpdateVisible, setGroupUpdateVisible] = useState(false);
|
|
37
38
|
const [valueTab, setValueTab] = useState('1');
|
|
39
|
+
const clickedIdRef = useRef(null);
|
|
38
40
|
const handleChangeTab = (event, newValue) => {
|
|
39
41
|
setValueTab(newValue);
|
|
40
42
|
};
|
|
@@ -178,8 +180,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
178
180
|
const addToSelectedGroup = async () => {
|
|
179
181
|
setLoadingGroups(true);
|
|
180
182
|
try {
|
|
181
|
-
|
|
182
|
-
await handleAddDevicesToGroup(userInfo, selectedGroup, devicesToPatch);
|
|
183
|
+
await handleAddDevicesToGroup(userInfo, selectedGroup, deviceSelectedObjs);
|
|
183
184
|
setLoadingGroups(false);
|
|
184
185
|
setCurrentGroup(selectedGroup);
|
|
185
186
|
setDevicesToAdd([...[]]);
|
|
@@ -195,8 +196,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
195
196
|
const removeFromCurrentGroup = async () => {
|
|
196
197
|
setLoadingGroups(true);
|
|
197
198
|
try {
|
|
198
|
-
|
|
199
|
-
await handleRemoveDevicesFromGroup(userInfo, selectedGroup, devicesToRemove);
|
|
199
|
+
await handleRemoveDevicesFromGroup(userInfo, selectedGroup, deviceSelectedObjs);
|
|
200
200
|
setLoadingGroups(false);
|
|
201
201
|
setDevicesToAdd([]);
|
|
202
202
|
fetchDevices(currentGroup, selectedGroup);
|
|
@@ -216,14 +216,62 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
216
216
|
setCheckboxSelection(!checkboxSelection);
|
|
217
217
|
};
|
|
218
218
|
const renderMaps = (_jsx(Map, { positions: positions, mapsClickCallback: mapsClickCallback, height: mapsHeight }));
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
219
|
+
useEffect(() => {
|
|
220
|
+
if (devicesToAdd.length <= 0) {
|
|
221
|
+
setDeviceSelectedObjs([]);
|
|
222
|
+
}
|
|
223
|
+
}, [devicesToAdd]);
|
|
224
|
+
const CustomToolbar = () => (_jsxs("div", { style: { display: 'flex', padding: '8px', justifyContent: 'space-between', paddingTop: '2px' }, children: [_jsxs("div", { style: { display: 'flex', gap: 8, marginRight: '20px' }, children: [customToolbar && customToolbar.includes('filters') ?
|
|
225
|
+
_jsx(GridToolbarExport, { sx: { mr: 2 } })
|
|
226
|
+
: '', customToolbar && customToolbar.includes('export') ?
|
|
227
|
+
_jsx(GridToolbarExport, {})
|
|
228
|
+
: ''] }), customToolbar && customToolbar.includes('quickfilter') && _jsx(GridToolbarQuickFilter, {})] }));
|
|
229
|
+
const renderDataGrid = (_jsx("div", { style: { display: 'flex', flexDirection: 'column', minHeight: 323 }, children: _jsx(DataGrid, { checkboxSelection: checkboxSelection,
|
|
230
|
+
// Se siamo in modalità aggiunta, includi gli ID già nel gruppo
|
|
231
|
+
rowSelectionModel: (checkboxSelection && currentGroup === 'all')
|
|
232
|
+
? [
|
|
233
|
+
...devices
|
|
234
|
+
.filter(d => d.groups?.includes(selectedGroup))
|
|
235
|
+
.map(d => d.id.toString()),
|
|
236
|
+
...devicesToAdd,
|
|
237
|
+
]
|
|
238
|
+
: devicesToAdd,
|
|
239
|
+
// Se siamo in modalità aggiunta, disabilita la selezione per i già nel gruppo
|
|
240
|
+
isRowSelectable: params => {
|
|
241
|
+
return (checkboxSelection && currentGroup === 'all')
|
|
242
|
+
? !params.row.groups?.includes(selectedGroup)
|
|
243
|
+
: true;
|
|
244
|
+
}, onCellClick: (params) => {
|
|
245
|
+
clickedIdRef.current = params.id.toString(); // aggiornamento immediato
|
|
246
|
+
}, onRowSelectionModelChange: (ids) => {
|
|
247
|
+
if (!checkboxSelection || !clickedIdRef.current)
|
|
248
|
+
return;
|
|
249
|
+
const clickedId = clickedIdRef.current;
|
|
250
|
+
clickedIdRef.current = null; // resetta subito dopo l’uso
|
|
251
|
+
setDevicesToAdd(prevIds => {
|
|
252
|
+
const updated = prevIds.includes(clickedId)
|
|
253
|
+
? prevIds.filter(id => id !== clickedId)
|
|
254
|
+
: [...prevIds, clickedId];
|
|
255
|
+
return updated;
|
|
256
|
+
});
|
|
257
|
+
setDeviceSelectedObjs(prevObjs => {
|
|
258
|
+
const isDeselecting = prevObjs.some(d => d.id.toString() === clickedId);
|
|
259
|
+
if (isDeselecting) {
|
|
260
|
+
return prevObjs.filter(d => d.id.toString() !== clickedId);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
const device = devices.find(d => d.id.toString() === clickedId);
|
|
264
|
+
return device ? [...prevObjs, device] : prevObjs;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
}, disableDensitySelector: true, disableColumnSelector: true, disableRowSelectionOnClick: true, loading: loadingDevices, rows: devices, columns: checkboxSelection
|
|
268
|
+
? columnsArray.filter(col => col.field !== 'id')
|
|
269
|
+
: columnsArray, slots: {
|
|
270
|
+
noRowsOverlay: () => (_jsx(Stack, { height: "100%", alignItems: "center", justifyContent: "center", children: currentGroup !== 'all'
|
|
271
|
+
? (_jsxs(_Fragment, { children: [_jsx(Box, { children: "No devices in group" }), editGroup && (_jsxs(Button, { onClick: addDevicesToCurrentGroup, variant: "outlined", color: "primary", size: "small", sx: { mt: 2 }, children: [_jsx(PlaylistAddIcon, { fontSize: "small", sx: { mr: 1 } }), "Add devices"] }))] }))
|
|
272
|
+
: "No devices" })),
|
|
225
273
|
noResultsOverlay: () => (_jsx(Stack, { height: "100%", alignItems: "center", justifyContent: "center", children: "Filter returns no result" })),
|
|
226
|
-
toolbar: GridToolbar,
|
|
274
|
+
toolbar: customToolbar && customToolbar.length ? CustomToolbar : GridToolbar,
|
|
227
275
|
}, slotProps: {
|
|
228
276
|
toolbar: {
|
|
229
277
|
showQuickFilter: true,
|
|
@@ -234,7 +282,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
234
282
|
sorting: {
|
|
235
283
|
sortModel: [{ field: 'online', sort: 'desc' }],
|
|
236
284
|
},
|
|
237
|
-
pagination: { paginationModel: { pageSize: 100 } }
|
|
285
|
+
pagination: { paginationModel: { pageSize: 100 } },
|
|
238
286
|
}, ...propsDatagrid }) }));
|
|
239
287
|
const renderTabContext = (_jsxs(TabContext, { value: valueTab, children: [_jsx(Box, { sx: { borderBottom: 1, borderColor: 'divider' }, children: _jsxs(TabList, { onChange: handleChangeTab, sx: { minHeight: 20 }, children: [_jsx(Tab, { label: "List", value: "1", sx: { minHeight: 20 } }), _jsx(Tab, { label: "Map", value: "2", sx: { minHeight: 20 } })] }) }), _jsx(TabPanel, { value: "1", sx: { p: 0 }, children: renderDataGrid }), _jsx(TabPanel, { value: "2", sx: { p: 0 }, children: renderMaps })] }));
|
|
240
288
|
const renderDatagridAndMaps = (enableMaps ?
|
|
@@ -4,6 +4,7 @@ import { createElement, useState } from "react";
|
|
|
4
4
|
import { Box, Card, CardContent, List, ListItemButton, ListItemText, styled, ThemeProvider } from "@mui/material";
|
|
5
5
|
import Grid from "@mui/material/Grid2";
|
|
6
6
|
import NavigateNextIcon from "@mui/icons-material/NavigateNext";
|
|
7
|
+
import React from "react";
|
|
7
8
|
const ListItemButtonSettings = styled(ListItemButton)(({ theme, selected }) => ({
|
|
8
9
|
backgroundColor: theme.palette.primary.main,
|
|
9
10
|
color: theme.palette.primary.contrastText,
|
|
@@ -37,6 +38,6 @@ const DynamicMenu = ({ menuItems, selectedIndex = null, theme }) => {
|
|
|
37
38
|
const handleMenuClick = (index) => {
|
|
38
39
|
setSelected(index); // Assicurati di non chiamarlo nel rendering
|
|
39
40
|
};
|
|
40
|
-
return (_jsx(ThemeProvider, { theme: theme, children: _jsx(Grid, { container: true, spacing: 2, sx: { width: '100%' }, children: _jsx(Grid, { size: { xs: 12, lg: 9 }, children: _jsx(Card, { sx: { borderRadius: 2 }, children: _jsx(CardContent, { sx: { p: 0, "&:last-child": { p: 0 } }, children: _jsxs(Grid, { container: true, spacing: 2, children: [_jsx(Grid, { size: { xs: 12, sm: 4 }, sx: { display: { xs: selected !== null ? 'none' : 'block', sm: 'block' } }, children: _jsx(List, { sx: { p: 0, height: "100%", backgroundColor: "primary.main" }, children: menuItems.map((item, index) => (_jsxs(ListItemButtonSettings, { selected: selected === index, onClick: () => handleMenuClick(index), children: [item.icon && _jsx(Box, { sx: { mr: 2 }, children: item.icon }), _jsx(ListItemText, { primary: _jsx("b", { children: item.name }), secondary: item.description }), _jsx(NavigateNextIcon, { sx: { display: { xs: "block", sm: "none" } } })] }, index))) }) }), _jsx(Grid, { size: { xs: 12, sm: 8, md: 6 }, sx: { display: { xs: selected === null ? 'none' : 'block', sm: 'block' } }, children: _jsx(Box, { component: "div", sx: { p: { xs: 2 }, py: { sm: 3 } }, children: selected !== null ? createElement(menuItems[selected].page, { handleBack: () => { setSelected(null); } }) : "" }) })] }) }) }) }) }) }));
|
|
41
|
+
return (_jsx(ThemeProvider, { theme: theme, children: _jsx(Grid, { container: true, spacing: 2, sx: { width: '100%' }, children: _jsx(Grid, { size: { xs: 12, lg: 9 }, children: _jsx(Card, { sx: { borderRadius: 2 }, children: _jsx(CardContent, { sx: { p: 0, "&:last-child": { p: 0 } }, children: _jsxs(Grid, { container: true, spacing: 2, children: [_jsx(Grid, { size: { xs: 12, sm: 4 }, sx: { display: { xs: selected !== null ? 'none' : 'block', sm: 'block' } }, children: _jsx(List, { sx: { p: 0, height: "100%", backgroundColor: "primary.main" }, children: menuItems.map((item, index) => (_jsxs(ListItemButtonSettings, { selected: selected === index, onClick: () => handleMenuClick(index), children: [item.icon && _jsx(Box, { sx: { mr: 2 }, children: React.isValidElement(item.icon) ? item.icon : null }), _jsx(ListItemText, { primary: _jsx("b", { children: item.name }), secondary: item.description }), _jsx(NavigateNextIcon, { sx: { display: { xs: "block", sm: "none" } } })] }, index))) }) }), _jsx(Grid, { size: { xs: 12, sm: 8, md: 6 }, sx: { display: { xs: selected === null ? 'none' : 'block', sm: 'block' } }, children: _jsx(Box, { component: "div", sx: { p: { xs: 2 }, py: { sm: 3 } }, children: selected !== null ? createElement(menuItems[selected].page, { handleBack: () => { setSelected(null); } }) : "" }) })] }) }) }) }) }) }));
|
|
41
42
|
};
|
|
42
43
|
export default DynamicMenu;
|
package/package.json
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { FilterTagMode, InfluxConfig, InfluxFillType } from "./types";
|
|
2
|
-
export declare function getInfluxAlerts(influxConfig: InfluxConfig, fields: string[], limit: number, offset: number, sort: any,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
export declare function getInfluxAlerts(influxConfig: InfluxConfig, fields: string[], limit: number, offset: number, sort: any, filter: {
|
|
3
|
+
field: string;
|
|
4
|
+
value: string;
|
|
5
|
+
}, timeStart: number, timeEnd: number): Promise<any>;
|
|
6
|
+
export declare function getDwSlots(influxConfig: InfluxConfig, timeStart: number, timeEnd: number, filter: {
|
|
7
|
+
field: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}): Promise<any>;
|
|
10
|
+
export declare function getInfluxDataV1(influxConfig: InfluxConfig, field: string, timeStart: number, timeEnd: number, filter: {
|
|
11
|
+
field: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}, timeGroup: string, raw: boolean, fill?: InfluxFillType, filterTag?: number, tagInclude?: FilterTagMode): Promise<any>;
|
|
14
|
+
export declare function exportDataV1(influxConfig: InfluxConfig, field: string, timeStart: number, timeEnd: number, filter: {
|
|
15
|
+
field: string;
|
|
16
|
+
value: string;
|
|
17
|
+
}): Promise<any>;
|
package/server-actions/influx.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { parse } from "csv-parse";
|
|
3
3
|
import moment from "moment";
|
|
4
4
|
import { FilterTagMode } from "./types";
|
|
5
|
-
export async function getInfluxAlerts(influxConfig, fields, limit, offset, sort,
|
|
5
|
+
export async function getInfluxAlerts(influxConfig, fields, limit, offset, sort, filter, timeStart, timeEnd) {
|
|
6
6
|
const conditions = fields
|
|
7
7
|
.map((field) => `r["valueName"] == "${field}"`)
|
|
8
8
|
.join(" or ");
|
|
@@ -13,7 +13,7 @@ export async function getInfluxAlerts(influxConfig, fields, limit, offset, sort,
|
|
|
13
13
|
query += ` |> range(start: ${timeStart}, stop: ${timeEnd})`;
|
|
14
14
|
}
|
|
15
15
|
query += `
|
|
16
|
-
|> filter(fn: (r) => r["_measurement"] == "${influxConfig.measurement}" and r["
|
|
16
|
+
|> filter(fn: (r) => r["_measurement"] == "${influxConfig.measurement}" and r["${filter.field}"] == "${filter.value}" and (${conditions}))
|
|
17
17
|
`;
|
|
18
18
|
// Add filter for tag d === 3
|
|
19
19
|
query += `
|
|
@@ -80,11 +80,11 @@ export async function getInfluxAlerts(influxConfig, fields, limit, offset, sort,
|
|
|
80
80
|
count: countData
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
|
-
export async function getDwSlots(influxConfig, timeStart, timeEnd,
|
|
83
|
+
export async function getDwSlots(influxConfig, timeStart, timeEnd, filter) {
|
|
84
84
|
const field = "dw";
|
|
85
85
|
const query = `
|
|
86
86
|
SELECT ("value") FROM "${influxConfig.measurement}"
|
|
87
|
-
WHERE "
|
|
87
|
+
WHERE "${filter.field}" = '${filter.value}'
|
|
88
88
|
AND "valueName" = '${field}'
|
|
89
89
|
AND time >= '${moment.unix(timeStart).toISOString()}'
|
|
90
90
|
AND time <= '${moment.unix(timeEnd).toISOString()}'
|
|
@@ -116,7 +116,7 @@ export async function getDwSlots(influxConfig, timeStart, timeEnd, deviceID) {
|
|
|
116
116
|
}
|
|
117
117
|
return data; // stessa struttura di Influx, con values modificati
|
|
118
118
|
}
|
|
119
|
-
export async function getInfluxDataV1(influxConfig, field, timeStart, timeEnd,
|
|
119
|
+
export async function getInfluxDataV1(influxConfig, field, timeStart, timeEnd, filter, timeGroup, raw, fill, filterTag, tagInclude = FilterTagMode.Include) {
|
|
120
120
|
let query;
|
|
121
121
|
let preStartValue = null;
|
|
122
122
|
// Costruzione filtro tag
|
|
@@ -135,12 +135,12 @@ export async function getInfluxDataV1(influxConfig, field, timeStart, timeEnd, d
|
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
if (raw) {
|
|
138
|
-
query = `SELECT ("value") FROM "${influxConfig.measurement}" WHERE "
|
|
138
|
+
query = `SELECT ("value") FROM "${influxConfig.measurement}" WHERE "${filter.field}" = '${filter.value}' AND "valueName" = '${field}'${filterTagCondition} AND time >= '${moment
|
|
139
139
|
.unix(timeStart)
|
|
140
140
|
.toISOString()}' AND time <= '${moment.unix(timeEnd).toISOString()}'`;
|
|
141
141
|
}
|
|
142
142
|
else {
|
|
143
|
-
query = `SELECT last("value") FROM "${influxConfig.measurement}" WHERE "
|
|
143
|
+
query = `SELECT last("value") FROM "${influxConfig.measurement}" WHERE "${filter.field}" = '${filter.value}' AND "valueName" = '${field}'${filterTagCondition} AND time >= '${moment
|
|
144
144
|
.unix(timeStart)
|
|
145
145
|
.toISOString()}' AND time <= '${moment
|
|
146
146
|
.unix(timeEnd)
|
|
@@ -157,7 +157,7 @@ export async function getInfluxDataV1(influxConfig, field, timeStart, timeEnd, d
|
|
|
157
157
|
}
|
|
158
158
|
if (fill !== "null") {
|
|
159
159
|
// Query to get the last data point before timeStart
|
|
160
|
-
const preStartQuery = `SELECT last("value") FROM "${influxConfig.measurement}" WHERE "
|
|
160
|
+
const preStartQuery = `SELECT last("value") FROM "${influxConfig.measurement}" WHERE "${filter.field}" = '${filter.value}' AND "valueName" = '${field}'${filterTagCondition} AND time < '${moment
|
|
161
161
|
.unix(timeStart)
|
|
162
162
|
.toISOString()}'`;
|
|
163
163
|
const preStartResponse = await fetch(encodeURI(`${influxConfig.url}/query?db=${influxConfig.dbName}&epoch=s&q=${preStartQuery}`), {
|
|
@@ -215,8 +215,8 @@ export async function getInfluxDataV1(influxConfig, field, timeStart, timeEnd, d
|
|
|
215
215
|
}
|
|
216
216
|
return data;
|
|
217
217
|
}
|
|
218
|
-
export async function exportDataV1(influxConfig, field, timeStart, timeEnd,
|
|
219
|
-
const query = `SELECT ("value") FROM "${influxConfig.measurement}" WHERE "
|
|
218
|
+
export async function exportDataV1(influxConfig, field, timeStart, timeEnd, filter) {
|
|
219
|
+
const query = `SELECT ("value") FROM "${influxConfig.measurement}" WHERE "${filter.field}" = '${filter.value}' AND "valueName" = '${field}' AND time >= '${moment
|
|
220
220
|
.unix(timeStart)
|
|
221
221
|
.toISOString()}' AND time <= '${moment.unix(timeEnd).toISOString()}'`;
|
|
222
222
|
const response = await fetch(encodeURI(`${influxConfig.url}/query?db=${influxConfig.dbName}&epoch=s&q=${query}`), {
|