Persistent logging (erros and warning)
This commit is contained in:
parent
ac8f874255
commit
1204a28ab5
|
@ -446,6 +446,41 @@ public class Controller : ControllerBase
|
|||
return installation.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(session!.User).HideWriteKeyIfUserIsNotAdmin(session.User.HasWriteAccess);
|
||||
}
|
||||
|
||||
[HttpPost(nameof(AcknowledgeError))]
|
||||
public ActionResult AcknowledgeError(Int64 id, Token authToken)
|
||||
{
|
||||
var session = Db.GetSession(authToken);
|
||||
|
||||
if (session == null)
|
||||
return Unauthorized();
|
||||
|
||||
var error=Db.Errors
|
||||
.FirstOrDefault(error => error.Id == id);
|
||||
|
||||
error.Seen = true;
|
||||
|
||||
return Db.Update(error)
|
||||
? Ok()
|
||||
: Unauthorized();
|
||||
}
|
||||
|
||||
[HttpPost(nameof(AcknowledgeWarning))]
|
||||
public ActionResult AcknowledgeWarning(Int64 id, Token authToken)
|
||||
{
|
||||
var session = Db.GetSession(authToken);
|
||||
|
||||
if (session == null)
|
||||
return Unauthorized();
|
||||
|
||||
var warning=Db.Warnings
|
||||
.FirstOrDefault(warning => warning.Id == id);
|
||||
|
||||
warning.Seen = true;
|
||||
|
||||
return Db.Update(warning)
|
||||
? Ok()
|
||||
: Unauthorized();
|
||||
}
|
||||
|
||||
[HttpPut(nameof(UpdateFolder))]
|
||||
public ActionResult<Folder> UpdateFolder([FromBody] Folder folder, Token authToken)
|
||||
|
|
|
@ -7,9 +7,10 @@ public abstract class LogEntry
|
|||
[PrimaryKey, AutoIncrement]
|
||||
public Int64 Id { get; set; }
|
||||
public Int64 InstallationId { get; set; }
|
||||
public String Description { get; set; } = null!;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public String DeviceCreatedTheMessage { get; set; } = null!;
|
||||
public String Description { get; set; } = null!;
|
||||
public String Date { get; set; } = null!;
|
||||
public String Time { get; set; } = null!;
|
||||
public String DeviceCreatedTheMessage{ get; set; } = null!;
|
||||
public Boolean Seen { get; set; }
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ public static partial class Db
|
|||
{
|
||||
var oldestError =
|
||||
Errors.Where(error => error.InstallationId == installationId)
|
||||
.OrderBy(error => error.CreatedAt)
|
||||
.OrderBy(error => error.Date)
|
||||
.FirstOrDefault();
|
||||
|
||||
//Remove the old error
|
||||
|
@ -96,7 +96,7 @@ public static partial class Db
|
|||
{
|
||||
var oldestWarning =
|
||||
Warnings.Where(warning => warning.InstallationId == installationId)
|
||||
.OrderBy(warning => warning.CreatedAt)
|
||||
.OrderBy(warning => warning.Date)
|
||||
.FirstOrDefault();
|
||||
|
||||
//Remove the old error
|
||||
|
|
|
@ -16,6 +16,17 @@ public static partial class Db
|
|||
{
|
||||
return Update(obj: folder);
|
||||
}
|
||||
|
||||
public static Boolean Update(Error error)
|
||||
{
|
||||
return Update(obj: error);
|
||||
}
|
||||
|
||||
|
||||
public static Boolean Update(Warning warning)
|
||||
{
|
||||
return Update(obj: warning);
|
||||
}
|
||||
|
||||
public static Boolean Update(Installation installation)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"Key": "EXOea18f5a82bd358896154c783",
|
||||
"Secret": "lYtzU7R5e0L6XKOgBaLVPFr41nEBDxDdXU47zBAEI6M"
|
||||
"Key": "EXO4d838d1360ba9fb7d51648b0",
|
||||
"Secret": "_bmrp6ewWAvNwdAQoeJuC-9y02Lsx7NV6zD-WjljzCU"
|
||||
}
|
|
@ -3,7 +3,8 @@ public class StatusMessage
|
|||
{
|
||||
public required int InstallationId { get; init; }
|
||||
public required int Status { get; init; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public String Date { get; set; } = null!;
|
||||
public String Time { get; set; } = null!;
|
||||
public String Description { get; init; } = null!;
|
||||
public String CreatedBy { get; init; } = null!;
|
||||
}
|
|
@ -100,7 +100,8 @@ public static class WebsocketManager
|
|||
{
|
||||
InstallationId = receivedStatusMessage.InstallationId,
|
||||
Description = receivedStatusMessage.Description,
|
||||
CreatedAt = receivedStatusMessage.CreatedAt,
|
||||
Date = receivedStatusMessage.Date,
|
||||
Time = receivedStatusMessage.Time,
|
||||
DeviceCreatedTheMessage = receivedStatusMessage.CreatedBy,
|
||||
Seen = false
|
||||
};
|
||||
|
@ -115,7 +116,8 @@ public static class WebsocketManager
|
|||
{
|
||||
InstallationId = receivedStatusMessage.InstallationId,
|
||||
Description = receivedStatusMessage.Description,
|
||||
CreatedAt = receivedStatusMessage.CreatedAt,
|
||||
Date = receivedStatusMessage.Date,
|
||||
Time = receivedStatusMessage.Time,
|
||||
DeviceCreatedTheMessage = receivedStatusMessage.CreatedBy,
|
||||
Seen = false
|
||||
};
|
||||
|
|
|
@ -6,7 +6,8 @@ public class StatusMessage
|
|||
|
||||
public required int InstallationId { get; set; }
|
||||
public required int Status { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public String Date { get; set; } = null!;
|
||||
public String Time { get; set; } = null!;
|
||||
public String Description { get; set; } = null!;
|
||||
public String CreatedBy { get; set; } = null!;
|
||||
}
|
|
@ -356,13 +356,15 @@ internal static class Program
|
|||
|
||||
if (status == 2)
|
||||
{
|
||||
jsonObject.CreatedAt = DateTime.Now;
|
||||
jsonObject.Description = "Battery Temperature High";
|
||||
jsonObject.CreatedBy = "Battery/1";
|
||||
jsonObject.Date = DateTime.Now.ToString("yyyy-MM-dd");
|
||||
jsonObject.Time = DateTime.Now.ToString("HH:mm:ss");
|
||||
jsonObject.Description = "Battery Overvoltage";
|
||||
jsonObject.CreatedBy = "Battery/4";
|
||||
}
|
||||
else if (status == 1)
|
||||
{
|
||||
jsonObject.CreatedAt = DateTime.Now;
|
||||
jsonObject.Date = DateTime.Now.ToString("yyyy-MM-dd");
|
||||
jsonObject.Time = DateTime.Now.ToString("HH:mm:ss");
|
||||
jsonObject.Description = "Temp warning message";
|
||||
jsonObject.CreatedBy = "Battery/4";
|
||||
}
|
||||
|
|
|
@ -27,7 +27,17 @@ public static class TaskUtils
|
|||
return await task; // await the task to bubble up any errors etc
|
||||
}
|
||||
|
||||
public static void SupressAwaitWarning(this Task task)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public static void SupressAwaitWarning<T>(this Task<T> task)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static Task WhenAny(this IEnumerable<Task> tasks)
|
||||
{
|
||||
|
|
|
@ -6,12 +6,6 @@ import {
|
|||
Divider,
|
||||
Grid,
|
||||
IconButton,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
useTheme
|
||||
} from '@mui/material';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
@ -25,6 +19,8 @@ import { useNavigate } from 'react-router-dom';
|
|||
import { TokenContext } from '../../../contexts/tokenContext';
|
||||
import { ErrorMessage } from '../../../interfaces/S3Types';
|
||||
import Button from '@mui/material/Button';
|
||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||
import Checkbox from '@mui/material/Checkbox';
|
||||
|
||||
interface LogProps {
|
||||
errorLoadingS3Data: boolean;
|
||||
|
@ -37,7 +33,7 @@ function Log(props: LogProps) {
|
|||
const [errors, setErrors] = useState<ErrorMessage[]>([]);
|
||||
const [errorButtonPressed, setErrorButtonPressed] = useState(false);
|
||||
const [warningButtonPressed, setWarningButtonPressed] = useState(false);
|
||||
|
||||
const [updateCount, setUpdateCount] = useState(0);
|
||||
const navigate = useNavigate();
|
||||
const tokencontext = useContext(TokenContext);
|
||||
const { removeToken } = tokencontext;
|
||||
|
@ -66,7 +62,7 @@ function Log(props: LogProps) {
|
|||
navigate(routes.login);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
}, [updateCount]);
|
||||
|
||||
const handleErrorButtonPressed = () => {
|
||||
setErrorButtonPressed(!errorButtonPressed);
|
||||
|
@ -76,6 +72,34 @@ function Log(props: LogProps) {
|
|||
setWarningButtonPressed(!warningButtonPressed);
|
||||
};
|
||||
|
||||
const handleErrorAcknowledgeButtonPressed = (errorId: number) => {
|
||||
axiosConfig
|
||||
.post(`/AcknowledgeError?id=${errorId}`)
|
||||
.then((res: AxiosResponse<ErrorMessage[]>) => {
|
||||
setUpdateCount(updateCount + 1);
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
if (err.response && err.response.status == 401) {
|
||||
removeToken();
|
||||
navigate(routes.login);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleWarningAcknowledgeButtonPressed = (warningId: number) => {
|
||||
axiosConfig
|
||||
.post(`/AcknowledgeWarning?id=${warningId}`)
|
||||
.then((res: AxiosResponse<ErrorMessage[]>) => {
|
||||
setUpdateCount(updateCount + 1);
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
if (err.response && err.response.status == 401) {
|
||||
removeToken();
|
||||
navigate(routes.login);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Container maxWidth="xl">
|
||||
<Grid container>
|
||||
|
@ -91,97 +115,278 @@ function Log(props: LogProps) {
|
|||
{errorButtonPressed && errors.length > 0 && (
|
||||
<Card sx={{ marginTop: '10px' }}>
|
||||
<Divider />
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<FormattedMessage id="type" defaultMessage="Type" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage
|
||||
id="description"
|
||||
defaultMessage="Description"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage id="device" defaultMessage="Device" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage id="date" defaultMessage="Date" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage id="seen" defaultMessage="Seen" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{errors.map((error, index) => (
|
||||
<TableRow hover key={index}>
|
||||
<TableCell>
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
height: '40px',
|
||||
marginBottom: '10px',
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage id="type" defaultMessage="Type" />
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage
|
||||
id="description"
|
||||
defaultMessage="Description"
|
||||
/>
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage id="device" defaultMessage="Device" />
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage id="date" defaultMessage="Date" />
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage id="time" defaultMessage="Time" />
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage id="seen" defaultMessage="Seen" />
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
<Divider />
|
||||
<div style={{ maxHeight: '400px', overflowY: 'auto' }}>
|
||||
{errors.map((error, index) => (
|
||||
<>
|
||||
<Divider />
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
height: '40px',
|
||||
marginBottom: '10px',
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '10px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<ErrorIcon
|
||||
sx={{
|
||||
color: 'red',
|
||||
width: 25,
|
||||
height: 25,
|
||||
marginLeft: '5px',
|
||||
marginTop: '8px'
|
||||
height: 25
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px', verticalAlign: 'middle' }}
|
||||
>
|
||||
{error.description}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px', verticalAlign: 'middle' }}
|
||||
>
|
||||
{error.deviceCreatedTheMessage}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px', verticalAlign: 'middle' }}
|
||||
>
|
||||
{error.createdAt}
|
||||
{error.date}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px', verticalAlign: 'middle' }}
|
||||
>
|
||||
{error.seen == false ? 'No' : 'Yes'}
|
||||
{error.time}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={error.seen}
|
||||
onChange={() =>
|
||||
error.seen === false &&
|
||||
handleErrorAcknowledgeButtonPressed(error.id)
|
||||
}
|
||||
sx={{
|
||||
marginLeft: '25px'
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
sx={{ marginTop: 1 }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
|
@ -224,99 +429,280 @@ function Log(props: LogProps) {
|
|||
{warningButtonPressed && warnings.length > 0 && (
|
||||
<Card sx={{ marginTop: '10px' }}>
|
||||
<Divider />
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<FormattedMessage id="type" defaultMessage="Type" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage
|
||||
id="description"
|
||||
defaultMessage="Description"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage id="device" defaultMessage="Device" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage id="date" defaultMessage="Date" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage id="seen" defaultMessage="Seen" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{warnings.map((warning, index) => {
|
||||
return (
|
||||
<TableRow hover key={index}>
|
||||
<TableCell>
|
||||
<WarningIcon
|
||||
sx={{
|
||||
color: 'orange',
|
||||
width: 25,
|
||||
height: 25,
|
||||
marginLeft: '5px',
|
||||
marginTop: '8px'
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px', verticalAlign: 'middle' }}
|
||||
>
|
||||
{warning.description}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px' }}
|
||||
>
|
||||
{warning.deviceCreatedTheMessage}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px', verticalAlign: 'middle' }}
|
||||
>
|
||||
{warning.createdAt}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px', verticalAlign: 'middle' }}
|
||||
>
|
||||
{warning.seen == false ? 'No' : 'Yes'}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
height: '40px',
|
||||
marginBottom: '10px',
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage id="type" defaultMessage="Type" />
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage
|
||||
id="description"
|
||||
defaultMessage="Description"
|
||||
/>
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage id="device" defaultMessage="Device" />
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage id="date" defaultMessage="Date" />
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage id="time" defaultMessage="Time" />
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="dimgrey"
|
||||
fontWeight="bold"
|
||||
fontSize="1rem"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
<FormattedMessage id="seen" defaultMessage="Seen" />
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
<Divider />
|
||||
<div style={{ maxHeight: '400px', overflowY: 'auto' }}>
|
||||
{warnings.map((warning, index) => (
|
||||
<>
|
||||
<Divider />
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
height: '40px',
|
||||
marginBottom: '10px',
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '10px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<WarningIcon
|
||||
sx={{
|
||||
color: 'orange',
|
||||
width: 25,
|
||||
height: 25
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
{warning.description}
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
{warning.deviceCreatedTheMessage}
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
{warning.date}
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
>
|
||||
{warning.time}
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={warning.seen}
|
||||
onChange={() =>
|
||||
warning.seen === false &&
|
||||
handleWarningAcknowledgeButtonPressed(
|
||||
warning.id
|
||||
)
|
||||
}
|
||||
sx={{
|
||||
marginLeft: '25px'
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
sx={{ marginTop: 1 }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import {
|
||||
Alert,
|
||||
FormControl,
|
||||
Grid,
|
||||
IconButton,
|
||||
InputAdornment,
|
||||
TextField,
|
||||
useTheme
|
||||
|
@ -13,6 +15,7 @@ import Button from '@mui/material/Button';
|
|||
import UserForm from './userForm';
|
||||
import { UserContext } from '../../../contexts/userContext';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Close as CloseIcon } from '@mui/icons-material';
|
||||
|
||||
function UsersSearch() {
|
||||
const theme = useTheme();
|
||||
|
@ -21,6 +24,8 @@ function UsersSearch() {
|
|||
const [filteredData, setFilteredData] = useState(availableUsers);
|
||||
const [openModal, setOpenModal] = useState(false);
|
||||
const context = useContext(UserContext);
|
||||
const [userCreated, setUserCreated] = useState(false);
|
||||
const [errorOccured, setErrorOccured] = useState(false);
|
||||
const { currentUser, setUser } = context;
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -43,13 +48,27 @@ function UsersSearch() {
|
|||
};
|
||||
const handleUserFormSubmit = () => {
|
||||
setOpenModal(false);
|
||||
setUserCreated(true);
|
||||
|
||||
fetchAvailableUsers();
|
||||
|
||||
setTimeout(() => {
|
||||
setUserCreated(false);
|
||||
}, 8000);
|
||||
};
|
||||
|
||||
const handleUserFormCancel = () => {
|
||||
setOpenModal(false);
|
||||
};
|
||||
|
||||
const handleUserError = () => {
|
||||
setOpenModal(false);
|
||||
setErrorOccured(true);
|
||||
setTimeout(() => {
|
||||
setErrorOccured(false);
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
const isMobile = window.innerWidth <= 1490;
|
||||
|
||||
return (
|
||||
|
@ -63,8 +82,67 @@ function UsersSearch() {
|
|||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
{userCreated && (
|
||||
<Grid container spacing={1}>
|
||||
<Grid item xs={12} md={3}>
|
||||
<Alert
|
||||
severity="success"
|
||||
sx={{
|
||||
mt: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="successfullyCreatedUser"
|
||||
defaultMessage="Successfully Updated User"
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
onClick={() => setUserCreated(false)}
|
||||
sx={{ marginLeft: '4px' }}
|
||||
>
|
||||
<CloseIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Alert>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
{errorOccured && (
|
||||
<Grid container spacing={1}>
|
||||
<Grid item xs={12} md={3}>
|
||||
<Alert
|
||||
severity="error"
|
||||
sx={{
|
||||
mt: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="errorOccured"
|
||||
defaultMessage="An error has occurred"
|
||||
/>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
onClick={() => setErrorOccured(false)}
|
||||
sx={{ marginLeft: '4px' }}
|
||||
>
|
||||
<CloseIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Alert>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
{openModal && (
|
||||
<UserForm cancel={handleUserFormCancel} submit={handleUserFormSubmit} />
|
||||
<UserForm
|
||||
cancel={handleUserFormCancel}
|
||||
submit={handleUserFormSubmit}
|
||||
error={handleUserError}
|
||||
/>
|
||||
)}
|
||||
<Grid container spacing={1} sx={{ marginTop: '1px' }}>
|
||||
<Grid item xs={12} md={isMobile ? 5 : 3}>
|
||||
|
|
|
@ -25,6 +25,7 @@ import { FormattedMessage } from 'react-intl';
|
|||
interface userFormProps {
|
||||
cancel: () => void;
|
||||
submit: () => void;
|
||||
error: () => void;
|
||||
}
|
||||
|
||||
function userForm(props: userFormProps) {
|
||||
|
@ -106,44 +107,67 @@ function userForm(props: userFormProps) {
|
|||
const isMobile = window.innerWidth <= 1490;
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
const res = await axiosConfig.post('/CreateUser', {
|
||||
...formValues,
|
||||
password: '',
|
||||
language: 'english'
|
||||
});
|
||||
const res = await axiosConfig
|
||||
.post('/CreateUser', {
|
||||
...formValues,
|
||||
password: '',
|
||||
language: 'english'
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false);
|
||||
if (err.response) {
|
||||
props.error();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
for (const folderName of selectedFolderNames) {
|
||||
const folder = folders.find((folder) => folder.name === folderName);
|
||||
if (res) {
|
||||
try {
|
||||
for (const folderName of selectedFolderNames) {
|
||||
const folder = folders.find((folder) => folder.name === folderName);
|
||||
|
||||
await axiosConfig.post(
|
||||
`/GrantUserAccessToFolder?UserId=${res.data.id}&FolderId=${folder.id}`
|
||||
);
|
||||
await axiosConfig
|
||||
.post(
|
||||
`/GrantUserAccessToFolder?UserId=${res.data.id}&FolderId=${folder.id}`
|
||||
)
|
||||
.catch((err) => {
|
||||
setLoading(false);
|
||||
if (err.response) {
|
||||
props.error();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (const installationName of selectedInstallationNames) {
|
||||
const installation = installations.find(
|
||||
(installation) => installation.name === installationName
|
||||
);
|
||||
|
||||
await axiosConfig
|
||||
.post(
|
||||
`/GrantUserAccessToInstallation?UserId=${res.data.id}&InstallationId=${installation.id}`
|
||||
)
|
||||
.catch((err) => {
|
||||
setLoading(false);
|
||||
if (err.response) {
|
||||
props.error();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
props.submit();
|
||||
} catch (error) {
|
||||
await axiosConfig
|
||||
.delete(`/DeleteUser?userId=${res.data.id}`)
|
||||
.then((response) => {
|
||||
setLoading(false);
|
||||
setErrorMessage('An error has occured');
|
||||
setError(true);
|
||||
setTimeout(() => {
|
||||
props.cancel();
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
for (const installationName of selectedInstallationNames) {
|
||||
const installation = installations.find(
|
||||
(installation) => installation.name === installationName
|
||||
);
|
||||
|
||||
await axiosConfig.post(
|
||||
`/GrantUserAccessToInstallation?UserId=${res.data.id}&InstallationId=${installation.id}`
|
||||
);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
props.submit();
|
||||
} catch (error) {
|
||||
await axiosConfig
|
||||
.delete(`/DeleteUser?userId=${res.data.id}`)
|
||||
.then((response) => {
|
||||
setLoading(false);
|
||||
setErrorMessage('An error has occured');
|
||||
setError(true);
|
||||
setTimeout(() => {
|
||||
props.cancel();
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -7,9 +7,11 @@ export interface I_S3Credentials {
|
|||
}
|
||||
|
||||
export interface ErrorMessage {
|
||||
id: number;
|
||||
installationId: number;
|
||||
description: string;
|
||||
createdAt: Date;
|
||||
date: string;
|
||||
time: string;
|
||||
deviceCreatedTheMessage: string;
|
||||
seen: boolean;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue