From 3a26acfdf5c1a6b3366b46bded809f21e57ffb8b Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Thu, 5 Dec 2024 09:47:34 +0300 Subject: [PATCH 01/10] added maintenance banner, fixed sidebar, use skip for pagination --- netmanager/src/config/urls/authService.js | 2 + .../src/utils/hooks/useMaintenanceStatus.js | 28 +++++++++++++ netmanager/src/views/apis/authService.js | 9 ++++- .../MaintenanceBanner/MaintenanceBanner.js | 39 +++++++++++++++++++ netmanager/src/views/layouts/Main.js | 2 + .../views/layouts/common/Sidebar/Sidebar.js | 4 -- .../views/pages/UserList/AvailableUserList.js | 27 +++++++------ .../src/views/pages/UserList/UserList.js | 25 ++++++------ 8 files changed, 105 insertions(+), 31 deletions(-) create mode 100644 netmanager/src/utils/hooks/useMaintenanceStatus.js create mode 100644 netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js diff --git a/netmanager/src/config/urls/authService.js b/netmanager/src/config/urls/authService.js index 7ba256d6d3..449ecfa2e5 100644 --- a/netmanager/src/config/urls/authService.js +++ b/netmanager/src/config/urls/authService.js @@ -29,3 +29,5 @@ export const USER_FEEDBACK_URI = `${BASE_AUTH_SERVICE_URL_V2}/users/feedback`; export const GET_ACCESS_TOKEN = `${BASE_AUTH_SERVICE_URL_V2}/users/tokens`; export const GET_LOGS = `${BASE_AUTH_SERVICE_URL_V2}/users/logs`; + +export const GET_MAINTENANCE_STATUS = `${BASE_AUTH_SERVICE_URL_V2}/users/maintenances/analytics`; diff --git a/netmanager/src/utils/hooks/useMaintenanceStatus.js b/netmanager/src/utils/hooks/useMaintenanceStatus.js new file mode 100644 index 0000000000..7b2aa51dda --- /dev/null +++ b/netmanager/src/utils/hooks/useMaintenanceStatus.js @@ -0,0 +1,28 @@ +import { useState, useEffect } from 'react'; +import { getMaintenanceStatusApi } from 'views/apis/authService'; + +export const useMaintenanceStatus = () => { + const [maintenance, setMaintenance] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const checkMaintenanceStatus = async () => { + try { + const response = await getMaintenanceStatusApi(); + setMaintenance(response.maintenance); + } catch (err) { + setError(err); + } finally { + setLoading(false); + } + }; + + checkMaintenanceStatus(); + // Check every 5 minutes + const interval = setInterval(checkMaintenanceStatus, 5 * 60 * 1000); + return () => clearInterval(interval); + }, []); + + return { maintenance, loading, error }; +}; diff --git a/netmanager/src/views/apis/authService.js b/netmanager/src/views/apis/authService.js index ff77a1a4bd..a385db5f8d 100644 --- a/netmanager/src/views/apis/authService.js +++ b/netmanager/src/views/apis/authService.js @@ -5,7 +5,8 @@ import { REGISTER_USER_URI, CHART_DEFAULTS_URI, USER_FEEDBACK_URI, - GET_LOGS + GET_LOGS, + GET_MAINTENANCE_STATUS } from 'config/urls/authService'; import createAxiosInstance from './axiosConfig'; import { BASE_AUTH_SERVICE_URL_V2 } from '../../config/urls/authService'; @@ -109,3 +110,9 @@ export const updateDefaultSelectedSiteApi = async (siteId, siteData) => { .put(`${BASE_AUTH_SERVICE_URL_V2}/users/preferences/selected-sites/${siteId}`, siteData) .then((response) => response.data); }; + +export const getMaintenanceStatusApi = async () => { + return await createAxiosInstance() + .get(GET_MAINTENANCE_STATUS) + .then((response) => response.data); +}; diff --git a/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js b/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js new file mode 100644 index 0000000000..8d77ce4655 --- /dev/null +++ b/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js @@ -0,0 +1,39 @@ +import React from 'react'; +import { makeStyles } from '@material-ui/styles'; +import { Alert } from '@material-ui/lab'; +import { useMaintenanceStatus } from 'utils/hooks/useMaintenanceStatus'; +import { formatDateString } from '../../../utils/dateTime'; + +const useStyles = makeStyles((theme) => ({ + banner: { + position: 'fixed', + top: 0, + left: 0, + right: 0, + zIndex: 9999, + '& .MuiAlert-message': { + width: '100%', + textAlign: 'center' + } + } +})); + +const MaintenanceBanner = () => { + const classes = useStyles(); + const { maintenance, loading } = useMaintenanceStatus(); + + if (loading || !maintenance || !maintenance.active) { + return null; + } + + return ( + + {maintenance.message || + 'System maintenance in progress. SoformatDate(me features may be unavailable.'} + Estimated downtime: {formatDateString(maintenance.startDate)} -{' '} + {formatDateString(maintenance.endDate)} + + ); +}; + +export default MaintenanceBanner; diff --git a/netmanager/src/views/layouts/Main.js b/netmanager/src/views/layouts/Main.js index bbaadf3e91..10babc7f5b 100644 --- a/netmanager/src/views/layouts/Main.js +++ b/netmanager/src/views/layouts/Main.js @@ -19,6 +19,7 @@ import { } from '../../redux/AccessControl/operations'; import { LargeCircularLoader } from '../components/Loader/CircularLoader'; import { updateMainAlert } from '../../redux/MainAlert/operations'; +import MaintenanceBanner from 'views/components/MaintenanceBanner/MaintenanceBanner'; const useStyles = makeStyles((theme) => ({ root: { @@ -164,6 +165,7 @@ const Main = (props) => { [classes.shiftContent]: isDesktop })} > +
diff --git a/netmanager/src/views/layouts/common/Sidebar/Sidebar.js b/netmanager/src/views/layouts/common/Sidebar/Sidebar.js index a878695f2a..089ea4bb71 100644 --- a/netmanager/src/views/layouts/common/Sidebar/Sidebar.js +++ b/netmanager/src/views/layouts/common/Sidebar/Sidebar.js @@ -248,10 +248,6 @@ const Sidebar = (props) => { // check whether user has a role const currentUser = JSON.parse(localStorage.getItem('currentUser')); - if (isEmpty(currentUser)) { - return; - } - if (!isEmpty(currentUser)) { if (!isEmpty(currentRole)) { if (currentRole.role_permissions) { diff --git a/netmanager/src/views/pages/UserList/AvailableUserList.js b/netmanager/src/views/pages/UserList/AvailableUserList.js index 7a294cb535..5ee1b51ff3 100644 --- a/netmanager/src/views/pages/UserList/AvailableUserList.js +++ b/netmanager/src/views/pages/UserList/AvailableUserList.js @@ -5,7 +5,6 @@ import PropTypes from 'prop-types'; import usrsStateConnector from 'views/stateConnectors/usersStateConnector'; import ErrorBoundary from 'views/ErrorBoundary/ErrorBoundary'; import { useDispatch, useSelector } from 'react-redux'; -import { isEmpty } from 'underscore'; import { withPermission } from '../../containers/PageAccess'; import AvailableUsersTable from './components/UsersTable/AvailableUsersTable'; import { getAvailableNetworkUsersListApi } from 'views/apis/accessControl'; @@ -26,17 +25,17 @@ const AvailableUserList = (props) => { const [loading, setLoading] = useState(false); const [users, setUsers] = useState([]); const [totalCount, setTotalCount] = useState(0); - const [pageSize, setPageSize] = useState(10); - const [currentPage, setCurrentPage] = useState(0); + const [limit, setLimit] = useState(10); + const [skip, setSkip] = useState(0); const activeNetwork = useSelector((state) => state.accessControl.activeNetwork); - const fetchUsers = async (page, limit) => { + const fetchUsers = async (skipCount, limitCount) => { if (!activeNetwork) return; setLoading(true); try { const res = await getAvailableNetworkUsersListApi(activeNetwork._id, { - page: page + 1, // API expects 1-based pages - limit + skip: skipCount, + limit: limitCount }); setUsers(res.available_users); setTotalCount(res.total || 0); @@ -61,15 +60,15 @@ const AvailableUserList = (props) => { } }; - // Initial load useEffect(() => { - fetchUsers(currentPage, pageSize); + fetchUsers(skip, limit); }, [activeNetwork]); - const handlePageChange = (newPage, newPageSize) => { - setCurrentPage(newPage); - setPageSize(newPageSize); - fetchUsers(newPage, newPageSize); + const handlePageChange = (page, pageSize) => { + const newSkip = page * pageSize; + setSkip(newSkip); + setLimit(pageSize); + fetchUsers(newSkip, pageSize); }; return ( @@ -80,8 +79,8 @@ const AvailableUserList = (props) => { users={users} loadData={loading} totalCount={totalCount} - pageSize={pageSize} - currentPage={currentPage} + pageSize={limit} + currentPage={skip / limit} onPageChange={handlePageChange} />
diff --git a/netmanager/src/views/pages/UserList/UserList.js b/netmanager/src/views/pages/UserList/UserList.js index b134e13694..18708e8a20 100644 --- a/netmanager/src/views/pages/UserList/UserList.js +++ b/netmanager/src/views/pages/UserList/UserList.js @@ -28,8 +28,8 @@ const UserList = (props) => { const [loading, setLoading] = useState(false); const [users, setUsers] = useState([]); const [totalCount, setTotalCount] = useState(0); - const [pageSize, setPageSize] = useState(10); - const [currentPage, setCurrentPage] = useState(0); + const [limit, setLimit] = useState(10); + const [skip, setSkip] = useState(0); const roles = useSelector((state) => state.accessControl.rolesSummary); const activeNetwork = useSelector((state) => state.accessControl.activeNetwork); @@ -38,13 +38,13 @@ const UserList = (props) => { dispatch(loadRolesSummary(activeNetwork._id)); }, []); - const fetchUsers = async (page, limit) => { + const fetchUsers = async (skipCount, limitCount) => { if (!activeNetwork) return; setLoading(true); try { const res = await getNetworkUsersListApi(activeNetwork._id, { - page: page + 1, - limit + skip: skipCount, + limit: limitCount }); setUsers(res.assigned_users); setTotalCount(res.total || 0); @@ -71,13 +71,14 @@ const UserList = (props) => { // Initial load useEffect(() => { - fetchUsers(currentPage, pageSize); + fetchUsers(skip, limit); }, [activeNetwork]); - const handlePageChange = (newPage, newPageSize) => { - setCurrentPage(newPage); - setPageSize(newPageSize); - fetchUsers(newPage, newPageSize); + const handlePageChange = (page, pageSize) => { + const newSkip = page * pageSize; + setSkip(newSkip); + setLimit(pageSize); + fetchUsers(newSkip, pageSize); }; return ( @@ -90,8 +91,8 @@ const UserList = (props) => { users={users} loadData={loading} totalCount={totalCount} - pageSize={pageSize} - currentPage={currentPage} + pageSize={limit} + currentPage={skip / limit} onPageChange={handlePageChange} /> From fdebe17f1684fc2b7589bdf469b1861fef9616c9 Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Thu, 5 Dec 2024 09:56:38 +0300 Subject: [PATCH 02/10] export data body field name fix --- netmanager/src/views/pages/ExportData/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netmanager/src/views/pages/ExportData/index.js b/netmanager/src/views/pages/ExportData/index.js index d8647a213a..5b2b8c4f88 100644 --- a/netmanager/src/views/pages/ExportData/index.js +++ b/netmanager/src/views/pages/ExportData/index.js @@ -530,7 +530,7 @@ const ExportData = (props) => { startDateTime: roundToStartOfDay(new Date(startDate).toISOString()), endDateTime: roundToEndOfDay(new Date(endDate).toISOString()), sites: sitesList, - device: getValues(selectedDevices), + devices: getValues(selectedDevices), airqlouds: getValues(selectedAirqlouds), network: activeNetwork.net_name, datatype: dataType.value, From 2a7597d36ac840c804fa3305d47fbda1e3744663 Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:00:16 +0300 Subject: [PATCH 03/10] Update index.js --- netmanager/src/views/pages/ExportData/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netmanager/src/views/pages/ExportData/index.js b/netmanager/src/views/pages/ExportData/index.js index 5b2b8c4f88..8dc29cc600 100644 --- a/netmanager/src/views/pages/ExportData/index.js +++ b/netmanager/src/views/pages/ExportData/index.js @@ -530,7 +530,7 @@ const ExportData = (props) => { startDateTime: roundToStartOfDay(new Date(startDate).toISOString()), endDateTime: roundToEndOfDay(new Date(endDate).toISOString()), sites: sitesList, - devices: getValues(selectedDevices), + device_ids: getValues(selectedDevices), airqlouds: getValues(selectedAirqlouds), network: activeNetwork.net_name, datatype: dataType.value, From 3caa5ecf548b01428a09d44718b2bcfb74271f3e Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:05:15 +0300 Subject: [PATCH 04/10] Update index.js --- netmanager/src/views/pages/ExportData/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netmanager/src/views/pages/ExportData/index.js b/netmanager/src/views/pages/ExportData/index.js index 8dc29cc600..5b2b8c4f88 100644 --- a/netmanager/src/views/pages/ExportData/index.js +++ b/netmanager/src/views/pages/ExportData/index.js @@ -530,7 +530,7 @@ const ExportData = (props) => { startDateTime: roundToStartOfDay(new Date(startDate).toISOString()), endDateTime: roundToEndOfDay(new Date(endDate).toISOString()), sites: sitesList, - device_ids: getValues(selectedDevices), + devices: getValues(selectedDevices), airqlouds: getValues(selectedAirqlouds), network: activeNetwork.net_name, datatype: dataType.value, From 22970300844710c311cce165641b9e6f2d08e470 Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:13:08 +0300 Subject: [PATCH 05/10] Update MaintenanceBanner.js --- .../views/components/MaintenanceBanner/MaintenanceBanner.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js b/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js index 8d77ce4655..d042089e36 100644 --- a/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js +++ b/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js @@ -28,8 +28,7 @@ const MaintenanceBanner = () => { return ( - {maintenance.message || - 'System maintenance in progress. SoformatDate(me features may be unavailable.'} + {maintenance.message || 'System maintenance in progress. Some features may be unavailable.'} Estimated downtime: {formatDateString(maintenance.startDate)} -{' '} {formatDateString(maintenance.endDate)} From 6e7eeac6965b044fa4d96ae282ea6db819e7e8f4 Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:34:59 +0300 Subject: [PATCH 06/10] add skip, limit params to api --- .../src/redux/AccessControl/operations.js | 60 +++++++++++-------- .../src/redux/AccessControl/reducers.js | 26 ++++++-- netmanager/src/views/apis/accessControl.js | 8 +-- 3 files changed, 60 insertions(+), 34 deletions(-) diff --git a/netmanager/src/redux/AccessControl/operations.js b/netmanager/src/redux/AccessControl/operations.js index 8fbea958bd..9a1661200c 100644 --- a/netmanager/src/redux/AccessControl/operations.js +++ b/netmanager/src/redux/AccessControl/operations.js @@ -77,36 +77,44 @@ export const addActiveNetwork = (data) => (dispatch) => { }); }; -export const fetchNetworkUsers = (networkId) => async (dispatch) => { - return await getNetworkUsersListApi(networkId) - .then((resData) => { - dispatch({ - type: LOAD_NETWORK_USERS_SUCCESS, - payload: resData.assigned_users - }); - }) - .catch((err) => { - dispatch({ - type: LOAD_NETWORK_USERS_FAILURE, - payload: err - }); +export const fetchNetworkUsers = (networkId, params) => async (dispatch) => { + try { + const resData = await getNetworkUsersListApi(networkId, params); + dispatch({ + type: LOAD_NETWORK_USERS_SUCCESS, + payload: { + users: resData.assigned_users, + total: resData.total + } + }); + return resData; + } catch (err) { + dispatch({ + type: LOAD_NETWORK_USERS_FAILURE, + payload: err }); + throw err; + } }; -export const fetchAvailableNetworkUsers = (networkId) => async (dispatch) => { - return await getAvailableNetworkUsersListApi(networkId) - .then((resData) => { - dispatch({ - type: LOAD_AVAILABLE_USERS_SUCCESS, - payload: resData.available_users - }); - }) - .catch((err) => { - dispatch({ - type: LOAD_AVAILABLE_USERS_FAILURE, - payload: err - }); +export const fetchAvailableNetworkUsers = (networkId, params) => async (dispatch) => { + try { + const resData = await getAvailableNetworkUsersListApi(networkId, params); + dispatch({ + type: LOAD_AVAILABLE_USERS_SUCCESS, + payload: { + users: resData.available_users, + total: resData.total + } + }); + return resData; + } catch (err) { + dispatch({ + type: LOAD_AVAILABLE_USERS_FAILURE, + payload: err }); + throw err; + } }; export const addUserGroupSummary = (data) => (dispatch) => { diff --git a/netmanager/src/redux/AccessControl/reducers.js b/netmanager/src/redux/AccessControl/reducers.js index e39efcc562..f0986304f5 100644 --- a/netmanager/src/redux/AccessControl/reducers.js +++ b/netmanager/src/redux/AccessControl/reducers.js @@ -15,9 +15,15 @@ const initialState = { currentRole: {}, userNetworks: null, activeNetwork: {}, - networkUsers: null, + networkUsers: { + users: null, + total: 0 + }, rolesSummary: null, - availableUsers: null, + availableUsers: { + users: null, + total: 0 + }, groupsSummary: null }; @@ -32,11 +38,23 @@ export default function accessControlReducer(state = initialState, action) { case LOAD_CURRENT_NETWORK_SUCCESS: return { ...state, activeNetwork: action.payload }; case LOAD_NETWORK_USERS_SUCCESS: - return { ...state, networkUsers: action.payload }; + return { + ...state, + networkUsers: { + users: action.payload.users, + total: action.payload.total + } + }; case LOAD_ROLES_SUMMARY_SUCCESS: return { ...state, rolesSummary: action.payload }; case LOAD_AVAILABLE_USERS_SUCCESS: - return { ...state, availableUsers: action.payload }; + return { + ...state, + availableUsers: { + users: action.payload.users, + total: action.payload.total + } + }; case LOAD_GROUPS_SUMMARY_SUCCESS: return { ...state, groupsSummary: action.payload }; default: diff --git a/netmanager/src/views/apis/accessControl.js b/netmanager/src/views/apis/accessControl.js index f2af7a6f6c..130b188a99 100644 --- a/netmanager/src/views/apis/accessControl.js +++ b/netmanager/src/views/apis/accessControl.js @@ -81,9 +81,9 @@ export const assignUserNetworkApi = async (networkID, userID) => { .then((response) => response.data); }; -export const getAvailableNetworkUsersListApi = async (networkID) => { +export const getAvailableNetworkUsersListApi = async (networkId, params = {}) => { return await createAxiosInstance() - .get(`${GET_NETWORKS_URI}/${networkID}/available-users`) + .get(`${GET_NETWORKS_URI}/${networkId}/available-users`, { params }) .then((response) => response.data); }; @@ -111,9 +111,9 @@ export const updatePermissionsToRoleApi = async (roleID, data) => { .then((response) => response.data); }; -export const getNetworkUsersListApi = async (networkID) => { +export const getNetworkUsersListApi = async (networkId, params = {}) => { return await createAxiosInstance() - .get(`${GET_NETWORKS_URI}/${networkID}/assigned-users`) + .get(`${GET_NETWORKS_URI}/${networkId}/assigned-users`, { params }) .then((response) => response.data); }; From 89362b92d0ca354855eaf064a6daeed16f010eeb Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:37:01 +0300 Subject: [PATCH 07/10] get total number of users --- netmanager/src/redux/AccessControl/operations.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netmanager/src/redux/AccessControl/operations.js b/netmanager/src/redux/AccessControl/operations.js index 9a1661200c..5ad144250b 100644 --- a/netmanager/src/redux/AccessControl/operations.js +++ b/netmanager/src/redux/AccessControl/operations.js @@ -84,7 +84,7 @@ export const fetchNetworkUsers = (networkId, params) => async (dispatch) => { type: LOAD_NETWORK_USERS_SUCCESS, payload: { users: resData.assigned_users, - total: resData.total + total: resData.total_assigned_users } }); return resData; @@ -104,7 +104,7 @@ export const fetchAvailableNetworkUsers = (networkId, params) => async (dispatch type: LOAD_AVAILABLE_USERS_SUCCESS, payload: { users: resData.available_users, - total: resData.total + total: resData.total_available_users } }); return resData; From f92c09d5d5f1b0f58deb59e210e4aaf861022d3a Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:20:32 +0300 Subject: [PATCH 08/10] fix banner --- .../components/MaintenanceBanner/MaintenanceBanner.js | 2 +- netmanager/src/views/layouts/Main.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js b/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js index d042089e36..7374824fff 100644 --- a/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js +++ b/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js @@ -22,7 +22,7 @@ const MaintenanceBanner = () => { const classes = useStyles(); const { maintenance, loading } = useMaintenanceStatus(); - if (loading || !maintenance || !maintenance.active) { + if (loading || !maintenance || !maintenance.isActive) { return null; } diff --git a/netmanager/src/views/layouts/Main.js b/netmanager/src/views/layouts/Main.js index 10babc7f5b..9c74f4ba27 100644 --- a/netmanager/src/views/layouts/Main.js +++ b/netmanager/src/views/layouts/Main.js @@ -165,7 +165,6 @@ const Main = (props) => { [classes.shiftContent]: isDesktop })} > -
@@ -176,7 +175,11 @@ const Main = (props) => { open={shouldOpenSidebar} variant={isDesktop ? 'persistent' : 'temporary'} /> -
{children}
+ +
+ + {children} +
); From 86fdb647e1f096d1bf423b64abaa800f8b3d99c3 Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:51:23 +0300 Subject: [PATCH 09/10] maintenance banner date formatting --- .../src/utils/hooks/useMaintenanceStatus.js | 9 ++- .../MaintenanceBanner/MaintenanceBanner.js | 57 ++++++++++++++----- netmanager/src/views/layouts/Main.js | 2 +- 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/netmanager/src/utils/hooks/useMaintenanceStatus.js b/netmanager/src/utils/hooks/useMaintenanceStatus.js index 7b2aa51dda..ae201587a7 100644 --- a/netmanager/src/utils/hooks/useMaintenanceStatus.js +++ b/netmanager/src/utils/hooks/useMaintenanceStatus.js @@ -10,9 +10,16 @@ export const useMaintenanceStatus = () => { const checkMaintenanceStatus = async () => { try { const response = await getMaintenanceStatusApi(); - setMaintenance(response.maintenance); + if (response.success && response.maintenance?.length > 0) { + // Get the first active maintenance + const activeMaintenance = response.maintenance.find((m) => m.isActive); + setMaintenance(activeMaintenance || null); + } else { + setMaintenance(null); + } } catch (err) { setError(err); + setMaintenance(null); } finally { setLoading(false); } diff --git a/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js b/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js index 7374824fff..35bfe08961 100644 --- a/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js +++ b/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js @@ -1,20 +1,39 @@ import React from 'react'; import { makeStyles } from '@material-ui/styles'; -import { Alert } from '@material-ui/lab'; +import { Paper, Typography, Box } from '@material-ui/core'; +import { Warning as WarningIcon } from '@material-ui/icons'; import { useMaintenanceStatus } from 'utils/hooks/useMaintenanceStatus'; import { formatDateString } from '../../../utils/dateTime'; +import { format } from 'date-fns'; const useStyles = makeStyles((theme) => ({ banner: { - position: 'fixed', - top: 0, - left: 0, - right: 0, - zIndex: 9999, - '& .MuiAlert-message': { - width: '100%', - textAlign: 'center' - } + padding: theme.spacing(2), + backgroundColor: '#fff3e0', // Light warning color + border: '1px solid #ffb74d', // Warning border + borderRadius: '4px', + marginBottom: theme.spacing(2), + margin: 5 + }, + content: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + gap: theme.spacing(2) + }, + icon: { + color: '#f57c00' // Warning icon color + }, + message: { + color: '#424242', // Dark text for readability + fontWeight: 'bold', + fontSize: 18 + }, + timeInfo: { + marginTop: theme.spacing(1), + color: '#616161', // Slightly lighter text for secondary info + fontSize: '0.875rem', + textAlign: 'center' } })); @@ -27,11 +46,19 @@ const MaintenanceBanner = () => { } return ( - - {maintenance.message || 'System maintenance in progress. Some features may be unavailable.'} - Estimated downtime: {formatDateString(maintenance.startDate)} -{' '} - {formatDateString(maintenance.endDate)} - + + + + + {maintenance.message || + 'System maintenance in progress. Some features may be unavailable.'} + + + + Estimated downtime: {format(new Date(maintenance.startDate), 'MMM d, yyyy h:mm a')} -{' '} + {format(new Date(maintenance.endDate), 'MMM d, yyyy h:mm a')} + + ); }; diff --git a/netmanager/src/views/layouts/Main.js b/netmanager/src/views/layouts/Main.js index 9c74f4ba27..4c12651857 100644 --- a/netmanager/src/views/layouts/Main.js +++ b/netmanager/src/views/layouts/Main.js @@ -150,7 +150,7 @@ const Main = (props) => { justifyContent: 'center', alignItems: 'center', height: '100vh', - width: '100vw' + width: '100%' }} > From 2826c4095025db1f7f1549f4bd698cc060e0c903 Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:57:02 +0300 Subject: [PATCH 10/10] Update MaintenanceBanner.js --- .../components/MaintenanceBanner/MaintenanceBanner.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js b/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js index 35bfe08961..1b49f27f50 100644 --- a/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js +++ b/netmanager/src/views/components/MaintenanceBanner/MaintenanceBanner.js @@ -3,7 +3,6 @@ import { makeStyles } from '@material-ui/styles'; import { Paper, Typography, Box } from '@material-ui/core'; import { Warning as WarningIcon } from '@material-ui/icons'; import { useMaintenanceStatus } from 'utils/hooks/useMaintenanceStatus'; -import { formatDateString } from '../../../utils/dateTime'; import { format } from 'date-fns'; const useStyles = makeStyles((theme) => ({ @@ -55,8 +54,14 @@ const MaintenanceBanner = () => { - Estimated downtime: {format(new Date(maintenance.startDate), 'MMM d, yyyy h:mm a')} -{' '} - {format(new Date(maintenance.endDate), 'MMM d, yyyy h:mm a')} + Estimated downtime:{' '} + {maintenance.startDate && !isNaN(new Date(maintenance.startDate)) + ? format(new Date(maintenance.startDate), 'MMM d, yyyy h:mm a') + : 'Invalid start date'}{' '} + -{' '} + {maintenance.endDate && !isNaN(new Date(maintenance.endDate)) + ? format(new Date(maintenance.endDate), 'MMM d, yyyy h:mm a') + : 'Invalid end date'} );