@iotready/nextjs-components-library 1.0.0-preview1
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/accounts/AccountMenu.d.ts +9 -0
- package/components/accounts/AccountMenu.js +37 -0
- package/components/accounts/AccountProfile.d.ts +15 -0
- package/components/accounts/AccountProfile.js +153 -0
- package/components/accounts/index.d.ts +2 -0
- package/components/accounts/index.js +2 -0
- package/components/charts/TrendChart.d.ts +17 -0
- package/components/charts/TrendChart.js +454 -0
- package/components/charts/index.d.ts +1 -0
- package/components/charts/index.js +1 -0
- package/components/groups/GroupUpdate.d.ts +24 -0
- package/components/groups/GroupUpdate.js +134 -0
- package/components/groups/GroupsDevices.d.ts +37 -0
- package/components/groups/GroupsDevices.js +299 -0
- package/components/groups/Map.d.ts +14 -0
- package/components/groups/Map.js +17 -0
- package/components/groups/index.d.ts +3 -0
- package/components/groups/index.js +3 -0
- package/components/index.d.ts +5 -0
- package/components/index.js +5 -0
- package/components/settings/DynamicMenu.d.ts +17 -0
- package/components/settings/DynamicMenu.js +42 -0
- package/components/settings/index.d.ts +1 -0
- package/components/settings/index.js +1 -0
- package/components/users/UserUpdate.d.ts +11 -0
- package/components/users/UserUpdate.js +26 -0
- package/components/users/UsersDataGrid.d.ts +23 -0
- package/components/users/UsersDataGrid.js +76 -0
- package/components/users/index.d.ts +2 -0
- package/components/users/index.js +2 -0
- package/index.d.ts +3 -0
- package/index.js +4 -0
- package/package.json +45 -0
- package/server-actions/groups.d.ts +22 -0
- package/server-actions/groups.js +109 -0
- package/server-actions/index.d.ts +4 -0
- package/server-actions/index.js +5 -0
- package/server-actions/influx.d.ts +13 -0
- package/server-actions/influx.js +145 -0
- package/server-actions/logto.d.ts +39 -0
- package/server-actions/logto.js +194 -0
- package/server-actions/trackle.d.ts +35 -0
- package/server-actions/trackle.js +158 -0
- package/types/index.d.ts +1 -0
- package/types/index.js +1 -0
- package/types/user.d.ts +12 -0
- package/types/user.js +1 -0
@@ -0,0 +1,9 @@
|
|
1
|
+
import { UserType } from '../../types/user';
|
2
|
+
import { Theme } from "@emotion/react";
|
3
|
+
export default function UserMenuAccount({ userInfo, handleClick, handleSignOut, accountRoute, theme }: {
|
4
|
+
userInfo: UserType;
|
5
|
+
handleClick: () => Promise<void>;
|
6
|
+
handleSignOut: () => Promise<void>;
|
7
|
+
accountRoute?: string;
|
8
|
+
theme: Theme;
|
9
|
+
}): import("react/jsx-runtime").JSX.Element;
|
@@ -0,0 +1,37 @@
|
|
1
|
+
"use client";
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
3
|
+
import { useState } from 'react';
|
4
|
+
import { Box, Typography, IconButton, Menu, MenuItem, Tooltip, Avatar, ListItem, ListItemIcon } from '@mui/material';
|
5
|
+
import { Logout, Person } from "@mui/icons-material";
|
6
|
+
import { useRouter } from 'next/navigation';
|
7
|
+
import { ThemeProvider } from '@mui/material/styles';
|
8
|
+
export default function UserMenuAccount({ userInfo, handleClick, handleSignOut, accountRoute = '/account', theme }) {
|
9
|
+
const [anchorEl, setAnchorEl] = useState(null);
|
10
|
+
const router = useRouter();
|
11
|
+
const handleAccountClick = (event) => {
|
12
|
+
event.preventDefault();
|
13
|
+
setAnchorEl(event.currentTarget);
|
14
|
+
};
|
15
|
+
const handleClose = () => {
|
16
|
+
setAnchorEl(null);
|
17
|
+
};
|
18
|
+
return (_jsx(ThemeProvider, { theme: theme, children: _jsxs(Box, { children: [_jsxs(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleClose, anchorOrigin: {
|
19
|
+
vertical: 'top',
|
20
|
+
horizontal: 'right',
|
21
|
+
}, transformOrigin: {
|
22
|
+
vertical: 'bottom',
|
23
|
+
horizontal: 'left',
|
24
|
+
}, slotProps: {
|
25
|
+
paper: {
|
26
|
+
elevation: 0,
|
27
|
+
sx: {
|
28
|
+
overflow: 'visible',
|
29
|
+
filter: 'drop-shadow(0px 2px 8px rgba(0,0,0,0.32))',
|
30
|
+
'& .MuiAvatar-root': {
|
31
|
+
width: 32,
|
32
|
+
height: 32
|
33
|
+
}
|
34
|
+
},
|
35
|
+
}
|
36
|
+
}, children: [_jsxs(ListItem, { sx: { display: 'flex', alignItems: 'center' }, children: [_jsx(ListItemIcon, { sx: { minWidth: 46 }, children: _jsx(Avatar, {}) }), _jsxs(Box, { children: [_jsx(Typography, { variant: "subtitle2", children: userInfo.name?.replace('/', ' ') }), _jsx(Typography, { variant: "subtitle2", sx: { fontWeight: 'normal' }, children: userInfo.email })] })] }), _jsxs(MenuItem, { onClick: () => { router.push(accountRoute); handleClick(); handleClose(); }, sx: { py: 1 }, children: [_jsx(ListItemIcon, { sx: { mr: 1 }, children: _jsx(Person, { fontSize: "small" }) }), " Manage account"] }), _jsxs(MenuItem, { onClick: async () => await handleSignOut(), sx: { py: 1 }, children: [_jsx(ListItemIcon, { sx: { mr: 1 }, children: _jsx(Logout, { fontSize: "small" }) }), " Sign Out"] })] }), _jsx(Tooltip, { title: "Open menu", children: _jsx(IconButton, { onClick: handleAccountClick, children: _jsx(Avatar, { sx: { bgcolor: 'secondary.main', color: 'secondary.contrastText' }, alt: userInfo.name || userInfo.email, src: userInfo.picture, children: userInfo.picture ? '' : userInfo.name?.charAt(0).toUpperCase() || userInfo.email?.charAt(0).toUpperCase() }) }) })] }) }));
|
37
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { UserType } from '../../types/user';
|
2
|
+
import { Theme } from "@emotion/react";
|
3
|
+
declare const AccountProfile: ({ userAccount, handleSignOut, handleUpdateUser, handleUpdatePassword, handleDeleteUser, container, containerProps, theme, afterUpdateCallback, confirmMui }: {
|
4
|
+
userAccount: UserType;
|
5
|
+
handleSignOut: () => Promise<void>;
|
6
|
+
handleUpdateUser: (id: string, user: Partial<UserType>) => Promise<void>;
|
7
|
+
handleUpdatePassword: (id: string, password: string) => Promise<void>;
|
8
|
+
handleDeleteUser: (id: string) => Promise<void>;
|
9
|
+
container?: "Card" | "Box";
|
10
|
+
containerProps: any;
|
11
|
+
theme: Theme;
|
12
|
+
afterUpdateCallback: (user: Partial<UserType>) => void;
|
13
|
+
confirmMui?: (options?: any) => Promise<void>;
|
14
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
15
|
+
export default AccountProfile;
|
@@ -0,0 +1,153 @@
|
|
1
|
+
"use client";
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
3
|
+
import { useState } from 'react';
|
4
|
+
import { Alert, Box, Button, Card, CardContent, IconButton, InputAdornment, TextField, Typography } from '@mui/material';
|
5
|
+
import { LoadingButton } from '@mui/lab';
|
6
|
+
import { VisibilityOff, Visibility, Delete } from '@mui/icons-material';
|
7
|
+
import Grid from '@mui/material/Grid2';
|
8
|
+
import { ThemeProvider } from '@mui/material/styles';
|
9
|
+
const AccountProfile = ({ userAccount, handleSignOut, handleUpdateUser, handleUpdatePassword, handleDeleteUser, container = 'Box', containerProps = {}, theme, afterUpdateCallback = () => { }, confirmMui }) => {
|
10
|
+
const [userInfo, setUserInfo] = useState(userAccount);
|
11
|
+
const [loadingUdateButton, setLoadingUpdateButton] = useState(false);
|
12
|
+
const [loadingSaveButton, setLoadingSaveButton] = useState(false);
|
13
|
+
const [loadingDeleteButton, setLoadingDeleteButton] = useState(false);
|
14
|
+
// const [loadingUnlinkButton, setLoadingUnlinkButton] = useState(false);
|
15
|
+
const [showEditPassword, setShowEditPassword] = useState(false);
|
16
|
+
const [showNewPassword, setShowNewPassword] = useState(false);
|
17
|
+
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
|
18
|
+
const [confirmPassword, setConfirmPassword] = useState("");
|
19
|
+
const [password, setPassword] = useState("");
|
20
|
+
const [error, setError] = useState('');
|
21
|
+
const handleChange = (event) => {
|
22
|
+
const newUser = {
|
23
|
+
...userInfo,
|
24
|
+
[event.target.name]: event.target.value,
|
25
|
+
};
|
26
|
+
const name = `${newUser.firstname} ${newUser.lastname}`;
|
27
|
+
setUserInfo({
|
28
|
+
...newUser,
|
29
|
+
name
|
30
|
+
});
|
31
|
+
};
|
32
|
+
const handleClickShowPassword = () => setShowNewPassword((show) => !show);
|
33
|
+
const handleMouseDownPassword = (event) => {
|
34
|
+
event.preventDefault();
|
35
|
+
};
|
36
|
+
const handleClickShowConfirmPassword = () => setShowConfirmPassword((show) => !show);
|
37
|
+
const handleMouseDownConfirmPassword = (event) => {
|
38
|
+
event.preventDefault();
|
39
|
+
};
|
40
|
+
const savePassword = async () => {
|
41
|
+
if (password === "") {
|
42
|
+
setError('Password is required');
|
43
|
+
return;
|
44
|
+
}
|
45
|
+
if (confirmPassword === "") {
|
46
|
+
setError('Confirm password is required');
|
47
|
+
return;
|
48
|
+
}
|
49
|
+
if (password !== confirmPassword) {
|
50
|
+
setError('Password and Confirmation password must be the same');
|
51
|
+
return;
|
52
|
+
}
|
53
|
+
const passwordRegex = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ ]).{8,}$/;
|
54
|
+
if (!passwordRegex.test(password)) {
|
55
|
+
setError(`Password must be longer than 8 characters and must contain 1 uppercase letter (A-Z), 1 lowercase letter (a-z), 1 digit (0-9) e 1 special symbol (!"#$%&'()*+,-./:;<=>?@[\]^_{|}~ ).`);
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
setLoadingSaveButton(true);
|
59
|
+
if (userInfo) {
|
60
|
+
try {
|
61
|
+
await handleUpdatePassword(userInfo.id, password);
|
62
|
+
setError("");
|
63
|
+
setShowEditPassword(false);
|
64
|
+
alert('Password updated');
|
65
|
+
}
|
66
|
+
catch (err) {
|
67
|
+
console.log(err);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
setError('');
|
71
|
+
setLoadingSaveButton(false);
|
72
|
+
};
|
73
|
+
const handleUpdate = async () => {
|
74
|
+
setLoadingUpdateButton(true);
|
75
|
+
if (userInfo) {
|
76
|
+
try {
|
77
|
+
await handleUpdateUser(userInfo.id, { name: userInfo.name, firstname: userInfo.firstname, lastname: userInfo.lastname });
|
78
|
+
if (afterUpdateCallback) {
|
79
|
+
afterUpdateCallback(userInfo);
|
80
|
+
}
|
81
|
+
alert('User updated');
|
82
|
+
}
|
83
|
+
catch (err) {
|
84
|
+
console.log(err);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
setLoadingUpdateButton(false);
|
88
|
+
};
|
89
|
+
const handleDelete = async () => {
|
90
|
+
if (userInfo) {
|
91
|
+
try {
|
92
|
+
if (confirmMui) {
|
93
|
+
await confirmMui({ description: "Are you sure you want to delete the account?", confirmationText: "Yes, remove", confirmationButtonProps: { variant: 'contained', color: 'error' } });
|
94
|
+
}
|
95
|
+
else {
|
96
|
+
confirm("Are you sure you want to delete the account?");
|
97
|
+
}
|
98
|
+
setLoadingDeleteButton(true);
|
99
|
+
await handleDeleteUser(userInfo.id);
|
100
|
+
await handleSignOut();
|
101
|
+
}
|
102
|
+
catch (err) {
|
103
|
+
if (err && err.message) {
|
104
|
+
console.log(err);
|
105
|
+
}
|
106
|
+
}
|
107
|
+
finally {
|
108
|
+
setLoadingDeleteButton(false);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
};
|
112
|
+
/*const handleUnlinkSocial = async (target: string) => {
|
113
|
+
setLoadingUnlinkButton(true);
|
114
|
+
if (userObject) {
|
115
|
+
try {
|
116
|
+
await confirm({ description: "Are you sure to unlink the connected identity?" });
|
117
|
+
const userResponse = await fetch(`/api/users/unlink`, {
|
118
|
+
method: 'PUT',
|
119
|
+
body: JSON.stringify({ target, userId: userObject.id }),
|
120
|
+
});
|
121
|
+
const responseData = await userResponse.json();
|
122
|
+
if (responseData.ok) {
|
123
|
+
enqueueSnackbar('Identity unlinked successfully', {
|
124
|
+
variant: 'success',
|
125
|
+
});
|
126
|
+
login(userObject)
|
127
|
+
}
|
128
|
+
setLoadingUnlinkButton(false);
|
129
|
+
} catch (err: any) {
|
130
|
+
if (err && err.message) {
|
131
|
+
enqueueSnackbar(err.message, {
|
132
|
+
variant: 'error',
|
133
|
+
});
|
134
|
+
}
|
135
|
+
setLoadingUnlinkButton(false);
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}*/
|
139
|
+
const renderAccountProfile = (_jsxs(Box, { component: "div", children: [!userInfo.name ?
|
140
|
+
_jsx(Alert, { severity: "warning", sx: { mb: 2 }, children: "Please complete the informations below" })
|
141
|
+
: '', _jsx(Grid, { container: true, spacing: 2, children: _jsxs(Grid, { size: { xs: 12, md: 9, lg: 6 }, children: [_jsxs(Box, { component: "div", children: [_jsx(Typography, { variant: "h6", children: "Profile name" }), _jsx(Box, { component: "div", sx: { mt: 2, mb: 0 }, children: _jsx(TextField, { fullWidth: true, label: "First name", name: "firstname", value: userInfo.firstname, onChange: handleChange, error: !userInfo.firstname || userInfo.firstname === "" ? true : false, helperText: !userInfo.firstname || userInfo.firstname === "" ? "Enter your first name" : '', size: "small" }) }), _jsx(Box, { component: "div", sx: { mt: 2, mb: 0 }, children: _jsx(TextField, { fullWidth: true, label: "Last name", name: "lastname", value: userInfo.lastname, onChange: handleChange, error: !userInfo.lastname || userInfo.lastname === "" ? true : false, helperText: !userInfo.lastname || userInfo.lastname === "" ? "Enter your last name" : '', size: "small" }) }), _jsx(Box, { component: "div", sx: { mt: 2, mb: 0 }, children: _jsx(LoadingButton, { variant: "contained", color: "primary", loading: loadingUdateButton, onClick: () => handleUpdate(), disabled: !userInfo.firstname || userInfo.firstname === "" || !userInfo.lastname || userInfo.lastname === "", children: "Update" }) })] }), _jsxs(Box, { component: "div", sx: { mt: 4 }, children: [_jsx(Typography, { variant: "h6", children: "Security" }), !showEditPassword ? _jsx(Box, { component: "div", sx: { mt: 2, mb: 0 }, children: _jsx(Button, { variant: 'outlined', onClick: () => setShowEditPassword(!showEditPassword), children: "Set or edit your password" }) }) : '', showEditPassword ?
|
142
|
+
_jsxs(Box, { component: "div", sx: { mt: 2, mb: 0 }, children: [_jsx(TextField, { required: true, fullWidth: true, name: "password", label: "New Password", type: showNewPassword ? 'text' : 'password', id: "password", size: 'small', autoComplete: "current-password", onChange: (e) => setPassword(e.target.value), value: password, slotProps: {
|
143
|
+
input: {
|
144
|
+
endAdornment: _jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { "aria-label": "toggle password visibility", onClick: handleClickShowPassword, onMouseDown: handleMouseDownPassword, edge: "end", children: showNewPassword ? _jsx(VisibilityOff, {}) : _jsx(Visibility, {}) }) }),
|
145
|
+
}
|
146
|
+
} }), _jsx(TextField, { sx: { mt: 2 }, required: true, fullWidth: true, label: "Confirm Password", type: showConfirmPassword ? 'text' : 'password', id: "confirm-password", size: 'small', autoComplete: "confirm-password", onChange: (e) => setConfirmPassword(e.target.value), value: confirmPassword, slotProps: {
|
147
|
+
input: {
|
148
|
+
endAdornment: _jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { "aria-label": "toggle password visibility", onClick: handleClickShowConfirmPassword, onMouseDown: handleMouseDownConfirmPassword, edge: "end", children: showConfirmPassword ? _jsx(VisibilityOff, {}) : _jsx(Visibility, {}) }) }),
|
149
|
+
}
|
150
|
+
} }), error !== '' ? _jsx(Box, { component: 'div', sx: { mt: 1 }, children: _jsx(Typography, { variant: 'subtitle2', color: 'error', children: error }) }) : '', _jsxs(Box, { component: "div", sx: { mt: 3 }, children: [_jsx(Button, { variant: "contained", color: "inherit", onClick: () => setShowEditPassword(false), sx: { mr: 2 }, children: "Cancel" }), _jsx(LoadingButton, { loading: loadingSaveButton, type: "submit", variant: "contained", color: "primary", onClick: () => savePassword(), children: "Save" })] })] }) : ''] }), _jsxs(Box, { component: "div", sx: { mt: 4 }, children: [_jsx(Typography, { variant: 'h6', children: "Delete account" }), _jsx(Box, { component: "div", sx: { mt: 2, mb: 0 }, children: _jsx(Alert, { severity: "error", sx: { mt: 2 }, action: _jsxs(LoadingButton, { variant: "contained", color: "error", loading: loadingDeleteButton, onClick: () => handleDelete(), size: 'small', children: [_jsx(Delete, { fontSize: "small", sx: { mr: 1 } }), " Delete"] }), children: "This action cannot be undone" }) })] })] }, 3) })] }));
|
151
|
+
return _jsx(ThemeProvider, { theme: theme, children: container === "Card" ? (_jsx(Card, { ...containerProps, children: _jsx(CardContent, { children: renderAccountProfile }) })) : (_jsx(Box, { ...containerProps, children: renderAccountProfile })) });
|
152
|
+
};
|
153
|
+
export default AccountProfile;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import 'chartjs-adapter-moment';
|
2
|
+
import 'moment/locale/it';
|
3
|
+
import { Theme } from "@emotion/react";
|
4
|
+
type Measure = {
|
5
|
+
name: string;
|
6
|
+
polltime: number;
|
7
|
+
unit: string;
|
8
|
+
};
|
9
|
+
declare const TrendChart: ({ deviceId, measures, enableExportData, enableDatePicker, handleGetInfluxData, handleGetFirstTimestamp, theme, ...props }: {
|
10
|
+
deviceId: string;
|
11
|
+
measures: Array<Measure>;
|
12
|
+
enableenableExportData: boolean;
|
13
|
+
enableDatePicker: boolean;
|
14
|
+
handleGetInfluxData: (measure: string, timeStart: number, timeEnd: number, deviceId: string, timeGroup: string, raw: boolean) => Promise<any>;
|
15
|
+
theme: Theme;
|
16
|
+
} & any) => import("react/jsx-runtime").JSX.Element;
|
17
|
+
export default TrendChart;
|