From 44f9fb7f7d1cb9cfc7e8c14bc3e911469a9145ce Mon Sep 17 00:00:00 2001 From: Noe Date: Thu, 18 Jul 2024 11:38:15 +0200 Subject: [PATCH] Fixed bug in database backup. Updated view with icons in history actions Increased performance when deleting an action --- csharp/App/Backend/Controller.cs | 4 +- .../App/Backend/DataTypes/Methods/Session.cs | 8 +- csharp/App/Backend/Database/Create.cs | 2 +- .../update_all_cerbo_installations.sh | 2 +- .../BatteryView/DetailedBatteryView.tsx | 76 +- .../content/dashboards/History/History.tsx | 737 ++++++++---------- .../dashboards/Installations/Installation.tsx | 38 +- .../SalidomoInstallations/Installation.tsx | 32 +- .../SalidomoInstallations/index.tsx | 8 +- 9 files changed, 472 insertions(+), 435 deletions(-) diff --git a/csharp/App/Backend/Controller.cs b/csharp/App/Backend/Controller.cs index 76fe02908..85311d24b 100644 --- a/csharp/App/Backend/Controller.cs +++ b/csharp/App/Backend/Controller.cs @@ -808,10 +808,10 @@ public class Controller : ControllerBase [HttpPost(nameof(DeleteAction))] - public async Task>> DeleteAction([FromBody] UserAction action, Token authToken) + public async Task>> DeleteAction(Int64 actionId, Token authToken) { var session = Db.GetSession(authToken); - var actionSuccess = await session.DeleteUserAction(action); + var actionSuccess = await session.DeleteUserAction(actionId); return actionSuccess ? Ok() : Unauthorized(); } diff --git a/csharp/App/Backend/DataTypes/Methods/Session.cs b/csharp/App/Backend/DataTypes/Methods/Session.cs index 27603db4f..417fc690f 100644 --- a/csharp/App/Backend/DataTypes/Methods/Session.cs +++ b/csharp/App/Backend/DataTypes/Methods/Session.cs @@ -151,22 +151,20 @@ public static class SessionMethods if (user is null || user.UserType == 0) return false; - - action.UserName = user.Name; - + Db.UpdateAction(action); return true; } - public static async Task DeleteUserAction(this Session? session, UserAction action) + public static async Task DeleteUserAction(this Session? session, Int64 actionId) { var user = session?.User; if (user is null || user.UserType == 0) return false; + var action = Db.GetActionById(actionId); - action.UserName = user.Name; Db.Delete(action); Console.WriteLine("---------------Deleted the Action in the database-----------------"); diff --git a/csharp/App/Backend/Database/Create.cs b/csharp/App/Backend/Database/Create.cs index ae6a3e5f5..c2f8c6665 100644 --- a/csharp/App/Backend/Database/Create.cs +++ b/csharp/App/Backend/Database/Create.cs @@ -115,7 +115,7 @@ public static partial class Db { existingAction.Description = updatedAction.Description; existingAction.Timestamp = updatedAction.Timestamp; - //Update(existingAction); + Update(existingAction); Console.WriteLine("---------------Updated the Action in the database-----------------"); } } diff --git a/firmware/Cerbo_Release/CerboReleaseFiles/dbus-fzsonick-48tl/update_all_cerbo_installations.sh b/firmware/Cerbo_Release/CerboReleaseFiles/dbus-fzsonick-48tl/update_all_cerbo_installations.sh index b308cec6d..169d76719 100755 --- a/firmware/Cerbo_Release/CerboReleaseFiles/dbus-fzsonick-48tl/update_all_cerbo_installations.sh +++ b/firmware/Cerbo_Release/CerboReleaseFiles/dbus-fzsonick-48tl/update_all_cerbo_installations.sh @@ -7,7 +7,7 @@ set -e 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" ) diff --git a/typescript/frontend-marios2/src/content/dashboards/BatteryView/DetailedBatteryView.tsx b/typescript/frontend-marios2/src/content/dashboards/BatteryView/DetailedBatteryView.tsx index 4d688ed8f..65e09e4bf 100644 --- a/typescript/frontend-marios2/src/content/dashboards/BatteryView/DetailedBatteryView.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/BatteryView/DetailedBatteryView.tsx @@ -37,8 +37,12 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) { const [openModalFirmwareUpdate, setOpenModalFirmwareUpdate] = useState(false); const [openModalResultFirmwareUpdate, setOpenModalResultFirmwareUpdate] = useState(false); - const [openModalDownloadBatteryLog, setOpenModalDownloadBatteryLog] = useState(false); - const [openModalStartDownloadBatteryLog, setOpenModalStartDownloadBatteryLog] = useState(false); + const [openModalDownloadBatteryLog, setOpenModalDownloadBatteryLog] = + useState(false); + const [ + openModalStartDownloadBatteryLog, + setOpenModalStartDownloadBatteryLog + ] = useState(false); const [openModalError, setOpenModalError] = useState(false); const [errorMessage, setErrorMessage] = useState(''); @@ -153,7 +157,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) { setOpenModalDownloadBatteryLog(false); }; - const DownloadBatteryLogModalHandleProceed = async () => { setOpenModalDownloadBatteryLog(false); setOpenModalStartDownloadBatteryLog(true); @@ -161,7 +164,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) { try { // Start the job to generate the battery log 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) { @@ -170,27 +175,29 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) { // Polling to check the job status const checkJobStatus = async () => { try { - const statusRes = await axiosConfig.get(`/GetJobResult?jobId=${jobId}`); + const statusRes = await axiosConfig.get( + `/GetJobResult?jobId=${jobId}` + ); if (statusRes.status === 200) { const jobStatus = statusRes.data.status; switch (jobStatus) { - case "Completed": + case 'Completed': return statusRes.data.fileName; // Return FileName upon completion - case "Failed": - throw new Error("Job processing failed."); - case "Processing": - await new Promise(resolve => setTimeout(resolve, 60000)); // Wait for 60 seconds before next check + case 'Failed': + throw new Error('Job processing failed.'); + case 'Processing': + await new Promise((resolve) => setTimeout(resolve, 60000)); // Wait for 60 seconds before next check return checkJobStatus(); default: - throw new Error("Unknown download battery log job status."); + throw new Error('Unknown download battery log job status.'); } } else { - throw new Error("Unexpected error occurred."); + throw new Error('Unexpected error occurred.'); } } 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(); // Once job is completed, download the file - const res = await axiosConfig.get(`/DownloadBatteryLog?jobId=${jobId}`, { - responseType: 'blob', - }); + const res = await axiosConfig.get( + `/DownloadBatteryLog?jobId=${jobId}`, + { + responseType: 'blob' + } + ); const finalFileName = fileName || 'unknown_file_name'; // Default filename if not received console.log('Downloaded file name:', finalFileName); @@ -216,10 +226,13 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) { // Delete the file after successful download console.log('Deleted file name:', finalFileName); - await axiosConfig.delete(`/DeleteBatteryLog`, { params: { fileName: finalFileName } }); - + await axiosConfig.delete(`/DeleteBatteryLog`, { + params: { fileName: finalFileName } + }); } 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) { console.error('Error:', error.message); @@ -322,7 +335,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) { - 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.
- 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...
- 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.
-
+
- - {editMode && ( - - )}
)} - {!openModalAddAction && ( - + + - - - - - - - - {history.length > 0 && ( - // - // - //
- //
- //
- // - // - // - //
- // - //
- // - // - // - //
- //
- // - // - // - //
- //
- // - // - // - //
- //
- // - //
- // {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 ( - // - // - //
- //
- // - // {action.userName} - // - //
- // - //
- // - // {datePart} - // - //
- //
- // - // {timePart} - // - //
- // - //
- // - // {action.description} - // - //
- //
- //
- // ); - // })} - //
- //
- //
- - - - - - - User - Date - Time - Description - - - - {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 ( - handleSelectOneAction(action)} - onMouseEnter={() => handleRowMouseEnter(action.id)} - onMouseLeave={handleRowMouseLeave} - > - {action.userName} - {datePart} - {timePart} - {action.description} - - ); - })} - -
-
-
- )} - - {!props.errorLoadingS3Data && history.length == 0 && ( - - - - - )} + +
- - {props.errorLoadingS3Data && ( + + {history.length > 0 && ( + + +
+
+
+ + + +
+ +
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+ {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 ( + + +
+
+ + {action.userName} + +
+ +
+ + {datePart} + +
+
+ + {timePart} + +
+ +
+ + {action.description} + +
+ +
+ handleEdit(action)} + disabled={action.userName != currentUser.name} + > + + + HandleDelete(action)} + disabled={action.userName != currentUser.name} + > + + +
+
+
+ ); + })} +
+
+
+ )} + + {!props.errorLoadingS3Data && history.length == 0 && ( )}
-
- )} + + + + {props.errorLoadingS3Data && ( + + + + + )} + +
); } diff --git a/typescript/frontend-marios2/src/content/dashboards/Installations/Installation.tsx b/typescript/frontend-marios2/src/content/dashboards/Installations/Installation.tsx index 28dc59a27..eeefc86ee 100644 --- a/typescript/frontend-marios2/src/content/dashboards/Installations/Installation.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/Installations/Installation.tsx @@ -1,5 +1,11 @@ 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 { UserContext } from 'src/contexts/userContext'; import AccessContextProvider from 'src/contexts/AccessContextProvider'; @@ -45,6 +51,7 @@ function Installation(props: singleInstallationProps) { const [values, setValues] = useState(null); const status = getStatus(props.current_installation.id); const [connected, setConnected] = useState(true); + const [loading, setLoading] = useState(true); const { testModeMap } = useTestMode(); if (props.current_installation == undefined) { @@ -94,9 +101,11 @@ function Installation(props: singleInstallationProps) { if (i <= 0) { setConnected(false); + setLoading(false); return false; } setConnected(true); + setLoading(false); const timestamp = Object.keys(res)[Object.keys(res).length - 1]; @@ -133,9 +142,11 @@ function Installation(props: singleInstallationProps) { if (i <= 0) { setConnected(false); + setLoading(false); return false; } setConnected(true); + setLoading(false); console.log('NUMBER OF FILES=' + Object.keys(res).length); while (continueFetching.current) { @@ -259,6 +270,7 @@ function Installation(props: singleInstallationProps) { {props.current_installation.name}
+ {currentTab == 'live' && values && (
)}
+ {loading && currentTab != 'information' && currentTab != 'history' && ( + + + + Connecting to the device... + + + )} + + + + Connecting to the device... + + + )} ) }, - // { - // value: 'overview', - // label: - // }, + { + value: 'overview', + label: + }, { value: 'log', label: