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'}
);