Fixed bug in database backup.
Updated view with icons in history actions Increased performance when deleting an action
This commit is contained in:
parent
ce50b7ef3e
commit
44f9fb7f7d
|
@ -808,10 +808,10 @@ public class Controller : ControllerBase
|
||||||
|
|
||||||
|
|
||||||
[HttpPost(nameof(DeleteAction))]
|
[HttpPost(nameof(DeleteAction))]
|
||||||
public async Task<ActionResult<IEnumerable<Object>>> DeleteAction([FromBody] UserAction action, Token authToken)
|
public async Task<ActionResult<IEnumerable<Object>>> DeleteAction(Int64 actionId, Token authToken)
|
||||||
{
|
{
|
||||||
var session = Db.GetSession(authToken);
|
var session = Db.GetSession(authToken);
|
||||||
var actionSuccess = await session.DeleteUserAction(action);
|
var actionSuccess = await session.DeleteUserAction(actionId);
|
||||||
return actionSuccess ? Ok() : Unauthorized();
|
return actionSuccess ? Ok() : Unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,22 +151,20 @@ public static class SessionMethods
|
||||||
|
|
||||||
if (user is null || user.UserType == 0)
|
if (user is null || user.UserType == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
action.UserName = user.Name;
|
|
||||||
|
|
||||||
Db.UpdateAction(action);
|
Db.UpdateAction(action);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static async Task<Boolean> DeleteUserAction(this Session? session, UserAction action)
|
public static async Task<Boolean> DeleteUserAction(this Session? session, Int64 actionId)
|
||||||
{
|
{
|
||||||
var user = session?.User;
|
var user = session?.User;
|
||||||
|
|
||||||
if (user is null || user.UserType == 0)
|
if (user is null || user.UserType == 0)
|
||||||
return false;
|
return false;
|
||||||
|
var action = Db.GetActionById(actionId);
|
||||||
|
|
||||||
action.UserName = user.Name;
|
|
||||||
|
|
||||||
Db.Delete(action);
|
Db.Delete(action);
|
||||||
Console.WriteLine("---------------Deleted the Action in the database-----------------");
|
Console.WriteLine("---------------Deleted the Action in the database-----------------");
|
||||||
|
|
|
@ -115,7 +115,7 @@ public static partial class Db
|
||||||
{
|
{
|
||||||
existingAction.Description = updatedAction.Description;
|
existingAction.Description = updatedAction.Description;
|
||||||
existingAction.Timestamp = updatedAction.Timestamp;
|
existingAction.Timestamp = updatedAction.Timestamp;
|
||||||
//Update(existingAction);
|
Update(existingAction);
|
||||||
Console.WriteLine("---------------Updated the Action in the database-----------------");
|
Console.WriteLine("---------------Updated the Action in the database-----------------");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ set -e
|
||||||
|
|
||||||
|
|
||||||
echo -e "\n============================ Deploy ============================\n"
|
echo -e "\n============================ Deploy ============================\n"
|
||||||
ip_addresses_usb0=("10.2.2.118" "10.2.4.155" "10.2.3.244" "10.2.4.127")
|
ip_addresses_usb0=("10.2.2.118" "10.2.4.155" "10.2.3.244" "10.2.4.127" "10.2.4.96")
|
||||||
ip_addresses_usb1=("10.2.0.179" )
|
ip_addresses_usb1=("10.2.0.179" )
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,12 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
const [openModalFirmwareUpdate, setOpenModalFirmwareUpdate] = useState(false);
|
const [openModalFirmwareUpdate, setOpenModalFirmwareUpdate] = useState(false);
|
||||||
const [openModalResultFirmwareUpdate, setOpenModalResultFirmwareUpdate] =
|
const [openModalResultFirmwareUpdate, setOpenModalResultFirmwareUpdate] =
|
||||||
useState(false);
|
useState(false);
|
||||||
const [openModalDownloadBatteryLog, setOpenModalDownloadBatteryLog] = useState(false);
|
const [openModalDownloadBatteryLog, setOpenModalDownloadBatteryLog] =
|
||||||
const [openModalStartDownloadBatteryLog, setOpenModalStartDownloadBatteryLog] = useState(false);
|
useState(false);
|
||||||
|
const [
|
||||||
|
openModalStartDownloadBatteryLog,
|
||||||
|
setOpenModalStartDownloadBatteryLog
|
||||||
|
] = useState(false);
|
||||||
const [openModalError, setOpenModalError] = useState(false);
|
const [openModalError, setOpenModalError] = useState(false);
|
||||||
const [errorMessage, setErrorMessage] = useState('');
|
const [errorMessage, setErrorMessage] = useState('');
|
||||||
|
|
||||||
|
@ -153,7 +157,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
setOpenModalDownloadBatteryLog(false);
|
setOpenModalDownloadBatteryLog(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const DownloadBatteryLogModalHandleProceed = async () => {
|
const DownloadBatteryLogModalHandleProceed = async () => {
|
||||||
setOpenModalDownloadBatteryLog(false);
|
setOpenModalDownloadBatteryLog(false);
|
||||||
setOpenModalStartDownloadBatteryLog(true);
|
setOpenModalStartDownloadBatteryLog(true);
|
||||||
|
@ -161,7 +164,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
try {
|
try {
|
||||||
// Start the job to generate the battery log
|
// Start the job to generate the battery log
|
||||||
const startRes = await axiosConfig.post(
|
const startRes = await axiosConfig.post(
|
||||||
`/StartDownloadBatteryLog?batteryNode=${props.batteryData.BatteryId.toString()}&installationId=${props.installationId}`
|
`/StartDownloadBatteryLog?batteryNode=${props.batteryData.BatteryId.toString()}&installationId=${
|
||||||
|
props.installationId
|
||||||
|
}`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (startRes.status === 200) {
|
if (startRes.status === 200) {
|
||||||
|
@ -170,27 +175,29 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
// Polling to check the job status
|
// Polling to check the job status
|
||||||
const checkJobStatus = async () => {
|
const checkJobStatus = async () => {
|
||||||
try {
|
try {
|
||||||
const statusRes = await axiosConfig.get(`/GetJobResult?jobId=${jobId}`);
|
const statusRes = await axiosConfig.get(
|
||||||
|
`/GetJobResult?jobId=${jobId}`
|
||||||
|
);
|
||||||
|
|
||||||
if (statusRes.status === 200) {
|
if (statusRes.status === 200) {
|
||||||
const jobStatus = statusRes.data.status;
|
const jobStatus = statusRes.data.status;
|
||||||
|
|
||||||
switch (jobStatus) {
|
switch (jobStatus) {
|
||||||
case "Completed":
|
case 'Completed':
|
||||||
return statusRes.data.fileName; // Return FileName upon completion
|
return statusRes.data.fileName; // Return FileName upon completion
|
||||||
case "Failed":
|
case 'Failed':
|
||||||
throw new Error("Job processing failed.");
|
throw new Error('Job processing failed.');
|
||||||
case "Processing":
|
case 'Processing':
|
||||||
await new Promise(resolve => setTimeout(resolve, 60000)); // Wait for 60 seconds before next check
|
await new Promise((resolve) => setTimeout(resolve, 60000)); // Wait for 60 seconds before next check
|
||||||
return checkJobStatus();
|
return checkJobStatus();
|
||||||
default:
|
default:
|
||||||
throw new Error("Unknown download battery log job status.");
|
throw new Error('Unknown download battery log job status.');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Unexpected error occurred.");
|
throw new Error('Unexpected error occurred.');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error("Failed to fetch job status."); // Catch errors from status check
|
throw new Error('Failed to fetch job status.'); // Catch errors from status check
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,9 +205,12 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
const fileName = await checkJobStatus();
|
const fileName = await checkJobStatus();
|
||||||
|
|
||||||
// Once job is completed, download the file
|
// Once job is completed, download the file
|
||||||
const res = await axiosConfig.get(`/DownloadBatteryLog?jobId=${jobId}`, {
|
const res = await axiosConfig.get(
|
||||||
responseType: 'blob',
|
`/DownloadBatteryLog?jobId=${jobId}`,
|
||||||
});
|
{
|
||||||
|
responseType: 'blob'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const finalFileName = fileName || 'unknown_file_name'; // Default filename if not received
|
const finalFileName = fileName || 'unknown_file_name'; // Default filename if not received
|
||||||
console.log('Downloaded file name:', finalFileName);
|
console.log('Downloaded file name:', finalFileName);
|
||||||
|
@ -216,10 +226,13 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
|
|
||||||
// Delete the file after successful download
|
// Delete the file after successful download
|
||||||
console.log('Deleted file name:', finalFileName);
|
console.log('Deleted file name:', finalFileName);
|
||||||
await axiosConfig.delete(`/DeleteBatteryLog`, { params: { fileName: finalFileName } });
|
await axiosConfig.delete(`/DeleteBatteryLog`, {
|
||||||
|
params: { fileName: finalFileName }
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error('Failed to start downloading battery log in the backend.');
|
console.error(
|
||||||
|
'Failed to start downloading battery log in the backend.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error.message);
|
console.error('Error:', error.message);
|
||||||
|
@ -322,7 +335,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Typography variant="body1" gutterBottom>
|
<Typography variant="body1" gutterBottom>
|
||||||
This action requires the battery service to be stopped for around 10-15 minutes.
|
This action requires the battery service to be stopped for around
|
||||||
|
10-15 minutes.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -389,7 +403,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
gutterBottom
|
gutterBottom
|
||||||
sx={{ fontWeight: 'bold' }}
|
sx={{ fontWeight: 'bold' }}
|
||||||
>
|
>
|
||||||
The battery log is getting downloaded. It will be saved in the Downloads folder. Please wait...
|
The battery log is getting downloaded. It will be saved in the
|
||||||
|
Downloads folder. Please wait...
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -429,7 +444,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
top: '50%',
|
top: '50%',
|
||||||
left: '50%',
|
left: '50%',
|
||||||
transform: 'translate(-50%, -50%)',
|
transform: 'translate(-50%, -50%)',
|
||||||
width: 420,
|
width: 500,
|
||||||
bgcolor: 'background.paper',
|
bgcolor: 'background.paper',
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
boxShadow: 24,
|
boxShadow: 24,
|
||||||
|
@ -448,7 +463,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Typography variant="body1" gutterBottom>
|
<Typography variant="body1" gutterBottom>
|
||||||
This action requires the battery service to be stopped for around 10-15 minutes.
|
This action requires the battery service to be stopped for around
|
||||||
|
10-15 minutes.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -518,9 +534,17 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
{errorMessage}
|
{errorMessage}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', marginTop: 10 }}>
|
<div
|
||||||
|
style={{ display: 'flex', alignItems: 'center', marginTop: 10 }}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
sx={{ marginTop: 2, textTransform: 'none', bgcolor: '#ffc04d', color: '#111111', '&:hover': { bgcolor: '#f7b34d' } }}
|
sx={{
|
||||||
|
marginTop: 2,
|
||||||
|
textTransform: 'none',
|
||||||
|
bgcolor: '#ffc04d',
|
||||||
|
color: '#111111',
|
||||||
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
|
}}
|
||||||
onClick={ErrorModalHandleOk}
|
onClick={ErrorModalHandleOk}
|
||||||
>
|
>
|
||||||
Ok
|
Ok
|
||||||
|
@ -581,7 +605,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
marginLeft: '20px',
|
marginLeft: '20px',
|
||||||
backgroundColor: '#ffc04d',
|
backgroundColor: '#ffc04d',
|
||||||
color: '#000000',
|
color: '#000000',
|
||||||
'&:hover': { bgcolor: '#f7b34d' },
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Download Battery Log
|
Download Battery Log
|
||||||
|
|
|
@ -5,14 +5,13 @@ import {
|
||||||
Card,
|
Card,
|
||||||
Container,
|
Container,
|
||||||
Divider,
|
Divider,
|
||||||
|
FormControlLabel,
|
||||||
Grid,
|
Grid,
|
||||||
IconButton,
|
IconButton,
|
||||||
Modal,
|
Modal,
|
||||||
TextField,
|
|
||||||
useTheme,
|
|
||||||
Switch,
|
Switch,
|
||||||
FormControlLabel,
|
TextField,
|
||||||
Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper
|
useTheme
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
@ -27,7 +26,9 @@ import Button from '@mui/material/Button';
|
||||||
import { DateTimePicker, LocalizationProvider } from '@mui/x-date-pickers';
|
import { DateTimePicker, LocalizationProvider } from '@mui/x-date-pickers';
|
||||||
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { UserContext } from 'src/contexts/userContext';
|
import EditIcon from '@mui/icons-material/Edit';
|
||||||
|
import DeleteIcon from '@mui/icons-material/Delete';
|
||||||
|
import { UserContext } from '../../../contexts/userContext';
|
||||||
|
|
||||||
interface HistoryProps {
|
interface HistoryProps {
|
||||||
errorLoadingS3Data: boolean;
|
errorLoadingS3Data: boolean;
|
||||||
|
@ -37,14 +38,13 @@ interface HistoryProps {
|
||||||
function HistoryOfActions(props: HistoryProps) {
|
function HistoryOfActions(props: HistoryProps) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const searchParams = new URLSearchParams(location.search);
|
const searchParams = new URLSearchParams(location.search);
|
||||||
const context = useContext(UserContext);
|
|
||||||
const { currentUser } = context;
|
|
||||||
const [history, setHistory] = useState<Action[]>([]);
|
const [history, setHistory] = useState<Action[]>([]);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const tokencontext = useContext(TokenContext);
|
const tokencontext = useContext(TokenContext);
|
||||||
const [actionDate, setActionDate] = useState(dayjs());
|
const [actionDate, setActionDate] = useState(dayjs());
|
||||||
const { removeToken } = tokencontext;
|
const { removeToken } = tokencontext;
|
||||||
const [openModalAddAction, setOpenModalAddAction] = useState(false);
|
const [openModalAddAction, setOpenModalAddAction] = useState(false);
|
||||||
|
|
||||||
const requiredFields = ['description', 'timestamp'];
|
const requiredFields = ['description', 'timestamp'];
|
||||||
const [newAction, setNewAction] = useState<Partial<Action>>({
|
const [newAction, setNewAction] = useState<Partial<Action>>({
|
||||||
installationId: props.id,
|
installationId: props.id,
|
||||||
|
@ -53,12 +53,15 @@ function HistoryOfActions(props: HistoryProps) {
|
||||||
});
|
});
|
||||||
const { testModeMap, setTestMode } = useTestMode();
|
const { testModeMap, setTestMode } = useTestMode();
|
||||||
const isTestMode = testModeMap[props.id] || false;
|
const isTestMode = testModeMap[props.id] || false;
|
||||||
|
const context = useContext(UserContext);
|
||||||
|
const { currentUser, setUser } = context;
|
||||||
const [isRowHovered, setHoveredRow] = useState(-1);
|
const [isRowHovered, setHoveredRow] = useState(-1);
|
||||||
const [selectedAction, setSelectedAction] = useState<number>(-1);
|
const [selectedAction, setSelectedAction] = useState<number>(-1);
|
||||||
const [editMode, setEditMode] = useState(false);
|
const [editMode, setEditMode] = useState(false);
|
||||||
const handleTestModeToggle = () => {
|
const handleTestModeToggle = () => {
|
||||||
setTestMode(props.id,!isTestMode);
|
setTestMode(props.id, !isTestMode);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDateChange = (newdate) => {
|
const handleDateChange = (newdate) => {
|
||||||
setActionDate(newdate);
|
setActionDate(newdate);
|
||||||
setNewAction({
|
setNewAction({
|
||||||
|
@ -76,33 +79,36 @@ function HistoryOfActions(props: HistoryProps) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetNewAction = () => {
|
const resetNewAction = () => {
|
||||||
console.log("Reset action to default");
|
console.log('Reset action to default');
|
||||||
setActionDate(dayjs());
|
setActionDate(dayjs());
|
||||||
setNewAction({
|
setNewAction({
|
||||||
...newAction,
|
...newAction,
|
||||||
['description']: '',
|
['description']: ''
|
||||||
});
|
});
|
||||||
setEditMode(false);
|
setEditMode(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddActionButton = () => {
|
const handleAddActionButton = () => {
|
||||||
resetNewAction();
|
resetNewAction();
|
||||||
//setOpenModalAddAction(!openModalAddAction);
|
|
||||||
setOpenModalAddAction(true);
|
setOpenModalAddAction(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const SumbitNewAction = () => {
|
const handleEdit = (action) => {
|
||||||
|
setEditMode(true);
|
||||||
|
setNewAction(action);
|
||||||
|
setOpenModalAddAction(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SumbitNewAction = async () => {
|
||||||
const endpoint = editMode ? `/UpdateAction` : `/InsertNewAction`;
|
const endpoint = editMode ? `/UpdateAction` : `/InsertNewAction`;
|
||||||
console.log("Add an action", endpoint);
|
//console.log('Add an action', endpoint);
|
||||||
const res=axiosConfig.post(endpoint,newAction).catch((err)=>{
|
const res = await axiosConfig.post(endpoint, newAction).catch((err) => {
|
||||||
if (err.response) {
|
if (err.response) {
|
||||||
// setError(true);
|
|
||||||
// setLoading(false);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res){
|
if (res) {
|
||||||
//setOpenModalAddAction(!openModalAddAction);
|
getHistory();
|
||||||
setOpenModalAddAction(false);
|
setOpenModalAddAction(false);
|
||||||
setEditMode(false);
|
setEditMode(false);
|
||||||
}
|
}
|
||||||
|
@ -113,19 +119,16 @@ function HistoryOfActions(props: HistoryProps) {
|
||||||
setEditMode(false);
|
setEditMode(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const HandleDelete = (e) => {
|
const HandleDelete = async (action) => {
|
||||||
console.log("Delete this action");
|
const res = await axiosConfig
|
||||||
const res = axiosConfig.post(`/DeleteAction`, newAction).catch((err) => {
|
.post(`/DeleteAction?actionId=${action.id}`)
|
||||||
if (err.response) {
|
.catch((err) => {
|
||||||
// setError(true);
|
if (err.response) {
|
||||||
// setLoading(false);
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
console.log("Delete this action is successful");
|
getHistory();
|
||||||
setOpenModalAddAction(false);
|
|
||||||
setEditMode(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -138,34 +141,7 @@ function HistoryOfActions(props: HistoryProps) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectOneAction = (action) => {
|
const getHistory = () => {
|
||||||
if (selectedAction != action.id) {
|
|
||||||
setSelectedAction(action.id);
|
|
||||||
setSelectedAction(-1);
|
|
||||||
if (action.userName === currentUser.name){
|
|
||||||
console.log("Select this action");
|
|
||||||
setActionDate(dayjs(action.timestamp));
|
|
||||||
setNewAction({ description: action.description, timestamp: action.timestamp });
|
|
||||||
setEditMode(true);
|
|
||||||
setOpenModalAddAction(true);
|
|
||||||
} else {
|
|
||||||
console.log('The user is not authorized to edit this action.');
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
setSelectedAction(-1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleRowMouseEnter = (id) => {
|
|
||||||
setHoveredRow(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleRowMouseLeave = () => {
|
|
||||||
setHoveredRow(-1);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
axiosConfig
|
axiosConfig
|
||||||
.get(`/GetHistoryForInstallation?id=${props.id}`)
|
.get(`/GetHistoryForInstallation?id=${props.id}`)
|
||||||
.then((res: AxiosResponse<Action[]>) => {
|
.then((res: AxiosResponse<Action[]>) => {
|
||||||
|
@ -177,7 +153,10 @@ function HistoryOfActions(props: HistoryProps) {
|
||||||
navigate(routes.login);
|
navigate(routes.login);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log("Update the tab:", openModalAddAction);
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getHistory();
|
||||||
}, [openModalAddAction]);
|
}, [openModalAddAction]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -206,27 +185,27 @@ function HistoryOfActions(props: HistoryProps) {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{/*<DateTimePicker*/}
|
|
||||||
{/* label="Select Action Date"*/}
|
|
||||||
{/* name="timestamp"*/}
|
|
||||||
{/* value={actionDate}*/}
|
|
||||||
{/* onChange={(newDate) => handleDateChange(newDate)}*/}
|
|
||||||
{/* sx={{*/}
|
|
||||||
{/* width: 450,*/}
|
|
||||||
{/* marginTop: 2*/}
|
|
||||||
{/* }}*/}
|
|
||||||
{/*/>*/}
|
|
||||||
<DateTimePicker
|
<DateTimePicker
|
||||||
label="Select Action Date"
|
label="Select Action Date"
|
||||||
value={actionDate}
|
name="timestamp"
|
||||||
onChange={handleDateChange}
|
value={editMode ? dayjs(newAction.timestamp) : actionDate}
|
||||||
renderInput={(params) => (
|
onChange={(newDate) => handleDateChange(newDate)}
|
||||||
<TextField
|
sx={{
|
||||||
{...params}
|
width: 450,
|
||||||
sx={{ width: 450, marginTop: 2 }}
|
marginTop: 2
|
||||||
/>
|
}}
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
|
{/*<DateTimePicker*/}
|
||||||
|
{/* label="Select Action Date"*/}
|
||||||
|
{/* value={actionDate}*/}
|
||||||
|
{/* onChange={handleDateChange}*/}
|
||||||
|
{/* renderInput={(params) => (*/}
|
||||||
|
{/* <TextField*/}
|
||||||
|
{/* {...params}*/}
|
||||||
|
{/* sx={{ width: 450, marginTop: 2 }}*/}
|
||||||
|
{/* />*/}
|
||||||
|
{/* )}*/}
|
||||||
|
{/*/>*/}
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
label="Description"
|
label="Description"
|
||||||
|
@ -252,7 +231,12 @@ function HistoryOfActions(props: HistoryProps) {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={<Switch checked={isTestMode} onChange={handleTestModeToggle} />}
|
control={
|
||||||
|
<Switch
|
||||||
|
checked={isTestMode}
|
||||||
|
onChange={handleTestModeToggle}
|
||||||
|
/>
|
||||||
|
}
|
||||||
label="Test Mode"
|
label="Test Mode"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -282,328 +266,272 @@ function HistoryOfActions(props: HistoryProps) {
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{editMode && (
|
|
||||||
<Button
|
|
||||||
sx={{
|
|
||||||
marginLeft: 2,
|
|
||||||
textTransform: 'none',
|
|
||||||
bgcolor: '#ffc04d',
|
|
||||||
color: '#111111',
|
|
||||||
'&:hover': { bgcolor: '#f7b34d' }
|
|
||||||
}}
|
|
||||||
onClick={HandleDelete}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
</LocalizationProvider>
|
</LocalizationProvider>
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!openModalAddAction && (
|
<Container maxWidth="xl">
|
||||||
<Container maxWidth="xl">
|
<Grid container>
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid container>
|
<Grid item xs={6} md={6}>
|
||||||
<Grid item xs={6} md={6}>
|
<Button
|
||||||
<Button
|
variant="contained"
|
||||||
variant="contained"
|
onClick={handleAddActionButton}
|
||||||
onClick={handleAddActionButton}
|
sx={{
|
||||||
sx={{
|
marginTop: '20px',
|
||||||
marginTop: '20px',
|
backgroundColor: '#ffc04d',
|
||||||
backgroundColor: '#ffc04d',
|
color: '#000000',
|
||||||
color: '#000000',
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
'&:hover': { bgcolor: '#f7b34d' }
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<FormattedMessage
|
||||||
<FormattedMessage
|
id="add_action"
|
||||||
id="add_action"
|
defaultMessage="Add New Action"
|
||||||
defaultMessage="Add New Action"
|
/>
|
||||||
/>
|
</Button>
|
||||||
</Button>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid item xs={12} md={12}>
|
|
||||||
{history.length > 0 && (
|
|
||||||
// <Card sx={{ marginTop: '10px' }}>
|
|
||||||
// <Divider />
|
|
||||||
// <div>
|
|
||||||
// <div
|
|
||||||
// style={{
|
|
||||||
// height: '40px',
|
|
||||||
// marginBottom: '10px',
|
|
||||||
// display: 'flex',
|
|
||||||
// alignItems: 'center'
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// <div
|
|
||||||
// style={{
|
|
||||||
// flex: 2,
|
|
||||||
// marginTop: '15px',
|
|
||||||
// display: 'flex',
|
|
||||||
// alignItems: 'center',
|
|
||||||
// justifyContent: 'center'
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// <Typography
|
|
||||||
// variant="body1"
|
|
||||||
// color="dimgrey"
|
|
||||||
// fontWeight="bold"
|
|
||||||
// fontSize="1rem"
|
|
||||||
// gutterBottom
|
|
||||||
// noWrap
|
|
||||||
// >
|
|
||||||
// <FormattedMessage id="user" defaultMessage="User" />
|
|
||||||
// </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: 6,
|
|
||||||
// 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>
|
|
||||||
// <Divider />
|
|
||||||
// <div style={{ maxHeight: '400px', overflowY: 'auto' }}>
|
|
||||||
// {history.map((action, index) => {
|
|
||||||
// // Parse the timestamp string to a Date object
|
|
||||||
// const date = new Date(action.timestamp);
|
|
||||||
//
|
|
||||||
// // Extract the date part (e.g., "2023-05-31")
|
|
||||||
// const datePart = date.toLocaleDateString();
|
|
||||||
//
|
|
||||||
// // Extract the time part (e.g., "12:34:56")
|
|
||||||
// const timePart = date.toLocaleTimeString();
|
|
||||||
//
|
|
||||||
// return (
|
|
||||||
// <React.Fragment key={index}>
|
|
||||||
// <Divider />
|
|
||||||
// <div
|
|
||||||
// style={{
|
|
||||||
// minHeight: '40px',
|
|
||||||
// marginBottom: '10px',
|
|
||||||
// display: 'flex',
|
|
||||||
// alignItems: 'center'
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// <div
|
|
||||||
// style={{
|
|
||||||
// flex: 2,
|
|
||||||
// marginTop: '15px',
|
|
||||||
// display: 'flex',
|
|
||||||
// alignItems: 'center',
|
|
||||||
// justifyContent: 'center'
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// <Typography
|
|
||||||
// variant="body1"
|
|
||||||
// fontWeight="bold"
|
|
||||||
// color="text.primary"
|
|
||||||
// gutterBottom
|
|
||||||
// >
|
|
||||||
// {action.userName}
|
|
||||||
// </Typography>
|
|
||||||
// </div>
|
|
||||||
//
|
|
||||||
// <div
|
|
||||||
// style={{
|
|
||||||
// flex: 1,
|
|
||||||
// marginTop: '15px',
|
|
||||||
// display: 'flex',
|
|
||||||
// alignItems: 'center',
|
|
||||||
// justifyContent: 'center'
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// <Typography
|
|
||||||
// variant="body1"
|
|
||||||
// fontWeight="bold"
|
|
||||||
// color="text.primary"
|
|
||||||
// gutterBottom
|
|
||||||
// >
|
|
||||||
// {datePart}
|
|
||||||
// </Typography>
|
|
||||||
// </div>
|
|
||||||
// <div
|
|
||||||
// style={{
|
|
||||||
// flex: 1,
|
|
||||||
// marginTop: '15px',
|
|
||||||
// display: 'flex',
|
|
||||||
// alignItems: 'center',
|
|
||||||
// justifyContent: 'center'
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// <Typography
|
|
||||||
// variant="body1"
|
|
||||||
// fontWeight="bold"
|
|
||||||
// color="text.primary"
|
|
||||||
// gutterBottom
|
|
||||||
// >
|
|
||||||
// {timePart}
|
|
||||||
// </Typography>
|
|
||||||
// </div>
|
|
||||||
//
|
|
||||||
// <div
|
|
||||||
// style={{
|
|
||||||
// flex: 6,
|
|
||||||
// display: 'flex',
|
|
||||||
// marginTop: '15px',
|
|
||||||
// alignItems: 'center',
|
|
||||||
// justifyContent: 'center'
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// <Typography
|
|
||||||
// variant="body1"
|
|
||||||
// fontWeight="bold"
|
|
||||||
// color="text.primary"
|
|
||||||
// gutterBottom
|
|
||||||
// style={{
|
|
||||||
// whiteSpace: 'normal',
|
|
||||||
// wordBreak: 'break-word'
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// {action.description}
|
|
||||||
// </Typography>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </React.Fragment>
|
|
||||||
// );
|
|
||||||
// })}
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </Card>
|
|
||||||
<Card sx={{ marginTop: '10px' }}>
|
|
||||||
<Divider />
|
|
||||||
<TableContainer component={Paper}>
|
|
||||||
<Table>
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell>User</TableCell>
|
|
||||||
<TableCell>Date</TableCell>
|
|
||||||
<TableCell>Time</TableCell>
|
|
||||||
<TableCell>Description</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{history.map((action, index) => {
|
|
||||||
const isActionSelected =
|
|
||||||
action.id === selectedAction;
|
|
||||||
const date = new Date(action.timestamp);
|
|
||||||
const datePart = date.toLocaleDateString();
|
|
||||||
const timePart = date.toLocaleTimeString();
|
|
||||||
|
|
||||||
const rowStyles = isRowHovered === action.id
|
|
||||||
? { cursor: 'pointer', backgroundColor: 'lightgray' }
|
|
||||||
: {};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TableRow
|
|
||||||
hover
|
|
||||||
key={action.id}
|
|
||||||
selected={isActionSelected}
|
|
||||||
style={rowStyles}
|
|
||||||
onClick={() => handleSelectOneAction(action)}
|
|
||||||
onMouseEnter={() => handleRowMouseEnter(action.id)}
|
|
||||||
onMouseLeave={handleRowMouseLeave}
|
|
||||||
>
|
|
||||||
<TableCell>{action.userName}</TableCell>
|
|
||||||
<TableCell>{datePart}</TableCell>
|
|
||||||
<TableCell>{timePart}</TableCell>
|
|
||||||
<TableCell>{action.description}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!props.errorLoadingS3Data && history.length == 0 && (
|
|
||||||
<Alert
|
|
||||||
severity="error"
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginTop: '20px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
|
||||||
id="nohistory"
|
|
||||||
defaultMessage="There is no history of actions"
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
color="inherit"
|
|
||||||
size="small"
|
|
||||||
sx={{ marginLeft: '4px' }}
|
|
||||||
></IconButton>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} md={12} style={{ marginBottom: '20px' }}>
|
<Grid item xs={12} md={12}>
|
||||||
{props.errorLoadingS3Data && (
|
{history.length > 0 && (
|
||||||
|
<Card sx={{ marginTop: '10px' }}>
|
||||||
|
<Divider />
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: '40px',
|
||||||
|
marginBottom: '10px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 2,
|
||||||
|
marginTop: '15px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
color="dimgrey"
|
||||||
|
fontWeight="bold"
|
||||||
|
fontSize="1rem"
|
||||||
|
gutterBottom
|
||||||
|
noWrap
|
||||||
|
>
|
||||||
|
<FormattedMessage id="user" defaultMessage="User" />
|
||||||
|
</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: 6,
|
||||||
|
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>
|
||||||
|
<Divider />
|
||||||
|
<div style={{ maxHeight: '600px', overflowY: 'auto' }}>
|
||||||
|
{history.map((action, index) => {
|
||||||
|
// Parse the timestamp string to a Date object
|
||||||
|
const date = new Date(action.timestamp);
|
||||||
|
|
||||||
|
// Extract the date part (e.g., "2023-05-31")
|
||||||
|
const datePart = date.toLocaleDateString();
|
||||||
|
|
||||||
|
// Extract the time part (e.g., "12:34:56")
|
||||||
|
const timePart = date.toLocaleTimeString();
|
||||||
|
const iconStyle =
|
||||||
|
action.userName === currentUser.name
|
||||||
|
? {}
|
||||||
|
: { color: 'rgba(0, 0, 0, 0.26)' };
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment key={index}>
|
||||||
|
<Divider />
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
minHeight: '40px',
|
||||||
|
marginBottom: '10px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 2,
|
||||||
|
marginTop: '15px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
fontWeight="bold"
|
||||||
|
color="text.primary"
|
||||||
|
gutterBottom
|
||||||
|
>
|
||||||
|
{action.userName}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
marginTop: '15px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
fontWeight="bold"
|
||||||
|
color="text.primary"
|
||||||
|
gutterBottom
|
||||||
|
>
|
||||||
|
{datePart}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
marginTop: '15px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
fontWeight="bold"
|
||||||
|
color="text.primary"
|
||||||
|
gutterBottom
|
||||||
|
>
|
||||||
|
{timePart}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 6,
|
||||||
|
display: 'flex',
|
||||||
|
marginTop: '15px',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
fontWeight="bold"
|
||||||
|
color="text.primary"
|
||||||
|
gutterBottom
|
||||||
|
style={{
|
||||||
|
whiteSpace: 'normal',
|
||||||
|
wordBreak: 'break-word'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{action.description}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
marginTop: '15px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
style={iconStyle}
|
||||||
|
onClick={() => handleEdit(action)}
|
||||||
|
disabled={action.userName != currentUser.name}
|
||||||
|
>
|
||||||
|
<EditIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
style={iconStyle}
|
||||||
|
onClick={() => HandleDelete(action)}
|
||||||
|
disabled={action.userName != currentUser.name}
|
||||||
|
>
|
||||||
|
<DeleteIcon />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!props.errorLoadingS3Data && history.length == 0 && (
|
||||||
<Alert
|
<Alert
|
||||||
severity="error"
|
severity="error"
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -613,8 +541,8 @@ function HistoryOfActions(props: HistoryProps) {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="cannotloadloggingdata"
|
id="nohistory"
|
||||||
defaultMessage="Cannot load logging data"
|
defaultMessage="There is no history of actions"
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
color="inherit"
|
color="inherit"
|
||||||
|
@ -624,8 +552,31 @@ function HistoryOfActions(props: HistoryProps) {
|
||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Container>
|
</Grid>
|
||||||
)}
|
|
||||||
|
<Grid item xs={12} md={12} style={{ marginBottom: '20px' }}>
|
||||||
|
{props.errorLoadingS3Data && (
|
||||||
|
<Alert
|
||||||
|
severity="error"
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: '20px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="cannotloadloggingdata"
|
||||||
|
defaultMessage="Cannot load logging data"
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
color="inherit"
|
||||||
|
size="small"
|
||||||
|
sx={{ marginLeft: '4px' }}
|
||||||
|
></IconButton>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Container>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||||
import { Card, CircularProgress, Grid, Typography } from '@mui/material';
|
import {
|
||||||
|
Card,
|
||||||
|
CircularProgress,
|
||||||
|
Container,
|
||||||
|
Grid,
|
||||||
|
Typography
|
||||||
|
} from '@mui/material';
|
||||||
import { I_Installation } from 'src/interfaces/InstallationTypes';
|
import { I_Installation } from 'src/interfaces/InstallationTypes';
|
||||||
import { UserContext } from 'src/contexts/userContext';
|
import { UserContext } from 'src/contexts/userContext';
|
||||||
import AccessContextProvider from 'src/contexts/AccessContextProvider';
|
import AccessContextProvider from 'src/contexts/AccessContextProvider';
|
||||||
|
@ -45,6 +51,7 @@ function Installation(props: singleInstallationProps) {
|
||||||
const [values, setValues] = useState<TopologyValues | null>(null);
|
const [values, setValues] = useState<TopologyValues | null>(null);
|
||||||
const status = getStatus(props.current_installation.id);
|
const status = getStatus(props.current_installation.id);
|
||||||
const [connected, setConnected] = useState(true);
|
const [connected, setConnected] = useState(true);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
const { testModeMap } = useTestMode();
|
const { testModeMap } = useTestMode();
|
||||||
|
|
||||||
if (props.current_installation == undefined) {
|
if (props.current_installation == undefined) {
|
||||||
|
@ -94,9 +101,11 @@ function Installation(props: singleInstallationProps) {
|
||||||
|
|
||||||
if (i <= 0) {
|
if (i <= 0) {
|
||||||
setConnected(false);
|
setConnected(false);
|
||||||
|
setLoading(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
setConnected(true);
|
setConnected(true);
|
||||||
|
setLoading(false);
|
||||||
|
|
||||||
const timestamp = Object.keys(res)[Object.keys(res).length - 1];
|
const timestamp = Object.keys(res)[Object.keys(res).length - 1];
|
||||||
|
|
||||||
|
@ -133,9 +142,11 @@ function Installation(props: singleInstallationProps) {
|
||||||
|
|
||||||
if (i <= 0) {
|
if (i <= 0) {
|
||||||
setConnected(false);
|
setConnected(false);
|
||||||
|
setLoading(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
setConnected(true);
|
setConnected(true);
|
||||||
|
setLoading(false);
|
||||||
console.log('NUMBER OF FILES=' + Object.keys(res).length);
|
console.log('NUMBER OF FILES=' + Object.keys(res).length);
|
||||||
|
|
||||||
while (continueFetching.current) {
|
while (continueFetching.current) {
|
||||||
|
@ -259,6 +270,7 @@ function Installation(props: singleInstallationProps) {
|
||||||
{props.current_installation.name}
|
{props.current_installation.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{currentTab == 'live' && values && (
|
{currentTab == 'live' && values && (
|
||||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
<Typography
|
<Typography
|
||||||
|
@ -359,13 +371,35 @@ function Installation(props: singleInstallationProps) {
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
marginLeft: status === -1 || status === -2 ? '-23px' : '2px',
|
marginLeft: status === -1 || status === -2 ? '-23px' : '2px'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{loading && currentTab != 'information' && currentTab != 'history' && (
|
||||||
|
<Container
|
||||||
|
maxWidth="xl"
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
height: '70vh'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CircularProgress size={60} style={{ color: '#ffc04d' }} />
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
style={{ color: 'black', fontWeight: 'bold' }}
|
||||||
|
mt={2}
|
||||||
|
>
|
||||||
|
Connecting to the device...
|
||||||
|
</Typography>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
|
||||||
<Card variant="outlined">
|
<Card variant="outlined">
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||||
import { Card, CircularProgress, Grid, Typography } from '@mui/material';
|
import {
|
||||||
|
Card,
|
||||||
|
CircularProgress,
|
||||||
|
Container,
|
||||||
|
Grid,
|
||||||
|
Typography
|
||||||
|
} from '@mui/material';
|
||||||
import { I_Installation } from 'src/interfaces/InstallationTypes';
|
import { I_Installation } from 'src/interfaces/InstallationTypes';
|
||||||
import { UserContext } from 'src/contexts/userContext';
|
import { UserContext } from 'src/contexts/userContext';
|
||||||
import { TimeSpan, UnixTime } from 'src/dataCache/time';
|
import { TimeSpan, UnixTime } from 'src/dataCache/time';
|
||||||
|
@ -39,6 +45,7 @@ function Installation(props: singleInstallationProps) {
|
||||||
setFailedToCommunicateWithInstallation
|
setFailedToCommunicateWithInstallation
|
||||||
] = useState(0);
|
] = useState(0);
|
||||||
const [connected, setConnected] = useState(true);
|
const [connected, setConnected] = useState(true);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
if (props.current_installation == undefined) {
|
if (props.current_installation == undefined) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -90,9 +97,11 @@ function Installation(props: singleInstallationProps) {
|
||||||
|
|
||||||
if (i <= 0) {
|
if (i <= 0) {
|
||||||
setConnected(false);
|
setConnected(false);
|
||||||
|
setLoading(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
setConnected(true);
|
setConnected(true);
|
||||||
|
setLoading(false);
|
||||||
console.log('NUMBER OF FILES=' + Object.keys(res).length);
|
console.log('NUMBER OF FILES=' + Object.keys(res).length);
|
||||||
|
|
||||||
while (continueFetching.current) {
|
while (continueFetching.current) {
|
||||||
|
@ -267,6 +276,27 @@ function Installation(props: singleInstallationProps) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{loading && currentTab != 'information' && currentTab != 'overview' && (
|
||||||
|
<Container
|
||||||
|
maxWidth="xl"
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
height: '70vh'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CircularProgress size={60} style={{ color: '#ffc04d' }} />
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
style={{ color: 'black', fontWeight: 'bold' }}
|
||||||
|
mt={2}
|
||||||
|
>
|
||||||
|
Connecting to the device...
|
||||||
|
</Typography>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
|
||||||
<Card variant="outlined">
|
<Card variant="outlined">
|
||||||
<Grid
|
<Grid
|
||||||
|
|
|
@ -92,10 +92,10 @@ function SalidomoInstallationTabs() {
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// value: 'overview',
|
value: 'overview',
|
||||||
// label: <FormattedMessage id="overview" defaultMessage="Overview" />
|
label: <FormattedMessage id="overview" defaultMessage="Overview" />
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
value: 'log',
|
value: 'log',
|
||||||
label: <FormattedMessage id="log" defaultMessage="Log" />
|
label: <FormattedMessage id="log" defaultMessage="Log" />
|
||||||
|
|
Loading…
Reference in New Issue