@iotready/nextjs-components-library 1.0.0-preview25 → 1.0.0-preview26

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.
@@ -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: number;
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
- const devicesToPatch = devices.filter((row) => devicesToAdd.includes(row.id));
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
- const devicesToRemove = devices.filter((row) => devicesToAdd.includes(row.id));
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
- const renderDataGrid = (_jsx("div", { style: { display: 'flex', flexDirection: 'column', minHeight: 323 }, children: _jsx(DataGrid, { checkboxSelection: checkboxSelection, onRowSelectionModelChange: (ids) => {
220
- if (checkboxSelection) {
221
- setDevicesToAdd(ids);
222
- }
223
- }, rowSelectionModel: devicesToAdd, disableDensitySelector: true, disableColumnSelector: true, disableRowSelectionOnClick: true, loading: loadingDevices, rows: devices, columns: checkboxSelection ? columnsArray.filter(col => col.field !== 'id') : columnsArray, slots: {
224
- noRowsOverlay: () => (_jsx(Stack, { height: "100%", alignItems: "center", justifyContent: "center", children: currentGroup !== 'all' ? _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"] }) : ''] }) : "No devices" })),
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 ?
@@ -1,5 +1,6 @@
1
1
  import { SvgIconProps } from "@mui/material/SvgIcon";
2
2
  import { Theme } from "@emotion/react";
3
+ import React from "react";
3
4
  interface MenuItem {
4
5
  name: string;
5
6
  description: string;
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "@iotready/nextjs-components-library",
3
- "version": "1.0.0-preview25",
3
+ "version": "1.0.0-preview26",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "build": "rm -rf dist && tsc --project tsconfig.build.json && cp package.json dist/",