From 5cf2811bfdc64308045c1d05bbd732bab3f1aa0a Mon Sep 17 00:00:00 2001 From: Muhammad Ibrahim Date: Wed, 8 Oct 2025 09:40:02 +0100 Subject: [PATCH 1/9] Fix BulkAssignModal: add missing bulkHostGroupId variable --- frontend/src/pages/Hosts.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/pages/Hosts.jsx b/frontend/src/pages/Hosts.jsx index 462c543..83f8543 100644 --- a/frontend/src/pages/Hosts.jsx +++ b/frontend/src/pages/Hosts.jsx @@ -1570,6 +1570,7 @@ const BulkAssignModal = ({ isLoading, }) => { const [selectedGroupId, setSelectedGroupId] = useState(""); + const bulkHostGroupId = useId(); // Fetch host groups for selection const { data: hostGroups } = useQuery({ From 93534ebe52080717ac3bc00aa70467629ea328f1 Mon Sep 17 00:00:00 2001 From: Muhammad Ibrahim Date: Wed, 8 Oct 2025 09:40:38 +0100 Subject: [PATCH 2/9] Add dark mode support to BulkAssignModal --- frontend/src/pages/Hosts.jsx | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/frontend/src/pages/Hosts.jsx b/frontend/src/pages/Hosts.jsx index 83f8543..7c5f34d 100644 --- a/frontend/src/pages/Hosts.jsx +++ b/frontend/src/pages/Hosts.jsx @@ -1589,28 +1589,31 @@ const BulkAssignModal = ({ return (
-
+
-

+

Assign to Host Group

-

+

Assigning {selectedHosts.length} host {selectedHosts.length !== 1 ? "s" : ""}:

-
+
{selectedHostNames.map((friendlyName) => ( -
+
• {friendlyName}
))} @@ -1621,7 +1624,7 @@ const BulkAssignModal = ({
@@ -1629,7 +1632,7 @@ const BulkAssignModal = ({ id={bulkHostGroupId} value={selectedGroupId} onChange={(e) => setSelectedGroupId(e.target.value)} - className="w-full px-3 py-2 border border-secondary-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500" + className="w-full px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary-500" > {hostGroups?.map((group) => ( @@ -1638,7 +1641,7 @@ const BulkAssignModal = ({ ))} -

+

Select a group to assign these hosts to, or leave ungrouped.

From 6d3f2d94ba407bb1f472bce06215b0d55a1ae987 Mon Sep 17 00:00:00 2001 From: Muhammad Ibrahim Date: Wed, 8 Oct 2025 09:43:41 +0100 Subject: [PATCH 3/9] Add dark mode support and logout functionality to mobile menu --- frontend/src/components/Layout.jsx | 50 +++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/Layout.jsx b/frontend/src/components/Layout.jsx index 3a08bfb..e6f7f6b 100644 --- a/frontend/src/components/Layout.jsx +++ b/frontend/src/components/Layout.jsx @@ -316,7 +316,7 @@ const Layout = ({ children }) => { onClick={() => setSidebarOpen(false)} aria-label="Close sidebar" /> -
+
+
+
From 561c78fb0896ae7cec15527a90466866b1989fe7 Mon Sep 17 00:00:00 2001 From: Muhammad Ibrahim Date: Wed, 8 Oct 2025 09:44:26 +0100 Subject: [PATCH 4/9] Remove coming soon items from mobile menu navigation --- frontend/src/components/Layout.jsx | 178 +++++++++++++++-------------- 1 file changed, 91 insertions(+), 87 deletions(-) diff --git a/frontend/src/components/Layout.jsx b/frontend/src/components/Layout.jsx index e6f7f6b..f6f2399 100644 --- a/frontend/src/components/Layout.jsx +++ b/frontend/src/components/Layout.jsx @@ -369,76 +369,78 @@ const Layout = ({ children }) => { {item.section}
- {item.items.map((subItem) => ( -
- {subItem.name === "Hosts" && canManageHosts() ? ( - // Special handling for Hosts item with integrated + button (mobile) - setSidebarOpen(false)} - > - - - {subItem.name} - {subItem.name === "Hosts" && - stats?.cards?.totalHosts !== undefined && ( - - {stats.cards.totalHosts} - - )} - - - - ) : ( - // Standard navigation item (mobile) - e.preventDefault() - : () => setSidebarOpen(false) - } - > - - - {subItem.name} - {subItem.name === "Hosts" && - stats?.cards?.totalHosts !== undefined && ( - - {stats.cards.totalHosts} + + + {subItem.name} + {subItem.name === "Hosts" && + stats?.cards?.totalHosts !== undefined && ( + + {stats.cards.totalHosts} + + )} + + + + ) : ( + // Standard navigation item (mobile) + e.preventDefault() + : () => setSidebarOpen(false) + } + > + + + {subItem.name} + {subItem.name === "Hosts" && + stats?.cards?.totalHosts !== undefined && ( + + {stats.cards.totalHosts} + + )} + {subItem.comingSoon && ( + + Soon )} - {subItem.comingSoon && ( - - Soon - - )} - - - )} -
- ))} + + + )} +
+ ))}
); @@ -453,26 +455,28 @@ const Layout = ({ children }) => { return (
- {item.items.map((subItem) => ( - setSidebarOpen(false)} - > - - - {subItem.name} - {subItem.showUpgradeIcon && ( - - )} - - - ))} + {item.items + .filter((subItem) => !subItem.comingSoon) + .map((subItem) => ( + setSidebarOpen(false)} + > + + + {subItem.name} + {subItem.showUpgradeIcon && ( + + )} + + + ))}
); From daa31973f94cdff0f9fcd88fb354080d0fe01af2 Mon Sep 17 00:00:00 2001 From: Muhammad Ibrahim Date: Wed, 8 Oct 2025 09:45:31 +0100 Subject: [PATCH 5/9] Fix mobile menu dark mode styling for Dashboard and navigation items --- frontend/src/components/Layout.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Layout.jsx b/frontend/src/components/Layout.jsx index f6f2399..621e8dd 100644 --- a/frontend/src/components/Layout.jsx +++ b/frontend/src/components/Layout.jsx @@ -352,8 +352,8 @@ const Layout = ({ children }) => { to={item.href} className={`group flex items-center px-2 py-2 text-sm font-medium rounded-md ${ isActive(item.href) - ? "bg-primary-100 text-primary-900" - : "text-secondary-600 hover:bg-secondary-50 hover:text-secondary-900" + ? "bg-primary-100 dark:bg-primary-600 text-primary-900 dark:text-white" + : "text-secondary-600 dark:text-secondary-300 hover:bg-secondary-50 dark:hover:bg-secondary-700 hover:text-secondary-900 dark:hover:text-white" }`} onClick={() => setSidebarOpen(false)} > @@ -365,7 +365,7 @@ const Layout = ({ children }) => { // Section with items return (
-

+

{item.section}

@@ -379,8 +379,8 @@ const Layout = ({ children }) => { to={subItem.href} className={`group flex items-center px-2 py-2 text-sm font-medium rounded-md ${ isActive(subItem.href) - ? "bg-primary-100 text-primary-900" - : "text-secondary-600 hover:bg-secondary-50 hover:text-secondary-900" + ? "bg-primary-100 dark:bg-primary-600 text-primary-900 dark:text-white" + : "text-secondary-600 dark:text-secondary-300 hover:bg-secondary-50 dark:hover:bg-secondary-700 hover:text-secondary-900 dark:hover:text-white" }`} onClick={() => setSidebarOpen(false)} > @@ -389,7 +389,7 @@ const Layout = ({ children }) => { {subItem.name} {subItem.name === "Hosts" && stats?.cards?.totalHosts !== undefined && ( - + {stats.cards.totalHosts} )} From 54872063844fc8c848a2869c4e37597366ef99f3 Mon Sep 17 00:00:00 2001 From: Muhammad Ibrahim Date: Wed, 8 Oct 2025 09:46:04 +0100 Subject: [PATCH 6/9] Fix hamburger menu icon and separator dark mode styling --- frontend/src/components/Layout.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Layout.jsx b/frontend/src/components/Layout.jsx index 621e8dd..94dcbe8 100644 --- a/frontend/src/components/Layout.jsx +++ b/frontend/src/components/Layout.jsx @@ -919,14 +919,14 @@ const Layout = ({ children }) => {
{/* Separator */} -
+
From a8668ee3f341e323a9672efa52e2c0babadb29ba Mon Sep 17 00:00:00 2001 From: Muhammad Ibrahim Date: Wed, 8 Oct 2025 09:47:10 +0100 Subject: [PATCH 7/9] Hide Dashboard text in header to give more space to search bar --- frontend/src/components/Layout.jsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Layout.jsx b/frontend/src/components/Layout.jsx index 94dcbe8..6ee89db 100644 --- a/frontend/src/components/Layout.jsx +++ b/frontend/src/components/Layout.jsx @@ -929,14 +929,19 @@ const Layout = ({ children }) => {
-
-

- {getPageTitle()} -

-
+ {/* Page title - hidden on dashboard to give more space to search */} + {location.pathname !== "/" && ( +
+

+ {getPageTitle()} +

+
+ )} {/* Global Search Bar */} -
+
From 5e4c628110121ba523bc099f91dd644094547f2c Mon Sep 17 00:00:00 2001 From: Muhammad Ibrahim Date: Wed, 8 Oct 2025 09:53:03 +0100 Subject: [PATCH 8/9] Dashboard Card ecit --- frontend/src/pages/Dashboard.jsx | 96 ++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 24 deletions(-) diff --git a/frontend/src/pages/Dashboard.jsx b/frontend/src/pages/Dashboard.jsx index 922d98a..fcfc20c 100644 --- a/frontend/src/pages/Dashboard.jsx +++ b/frontend/src/pages/Dashboard.jsx @@ -1150,23 +1150,46 @@ const Dashboard = () => { callbacks: { title: (context) => { const label = context[0].label; + + // Handle empty or invalid labels + if (!label || typeof label !== "string") { + return "Unknown Date"; + } + // Format hourly labels (e.g., "2025-10-07T14" -> "Oct 7, 2:00 PM") if (label.includes("T")) { - const date = new Date(`${label}:00:00`); + try { + const date = new Date(`${label}:00:00`); + // Check if date is valid + if (isNaN(date.getTime())) { + return label; // Return original label if date is invalid + } + return date.toLocaleDateString("en-US", { + month: "short", + day: "numeric", + hour: "numeric", + minute: "2-digit", + hour12: true, + }); + } catch (error) { + return label; // Return original label if parsing fails + } + } + + // Format daily labels (e.g., "2025-10-07" -> "Oct 7") + try { + const date = new Date(label); + // Check if date is valid + if (isNaN(date.getTime())) { + return label; // Return original label if date is invalid + } return date.toLocaleDateString("en-US", { month: "short", day: "numeric", - hour: "numeric", - minute: "2-digit", - hour12: true, }); + } catch (error) { + return label; // Return original label if parsing fails } - // Format daily labels (e.g., "2025-10-07" -> "Oct 7") - const date = new Date(label); - return date.toLocaleDateString("en-US", { - month: "short", - day: "numeric", - }); }, }, }, @@ -1186,24 +1209,49 @@ const Dashboard = () => { }, callback: function (value, _index, _ticks) { const label = this.getLabelForValue(value); + + // Handle empty or invalid labels + if (!label || typeof label !== "string") { + return "Unknown"; + } + // Format hourly labels (e.g., "2025-10-07T14" -> "2 PM") if (label.includes("T")) { - const hour = label.split("T")[1]; - const hourNum = parseInt(hour, 10); - return hourNum === 0 - ? "12 AM" - : hourNum < 12 - ? `${hourNum} AM` - : hourNum === 12 - ? "12 PM" - : `${hourNum - 12} PM`; + try { + const hour = label.split("T")[1]; + const hourNum = parseInt(hour, 10); + + // Validate hour number + if (isNaN(hourNum) || hourNum < 0 || hourNum > 23) { + return hour; // Return original hour if invalid + } + + return hourNum === 0 + ? "12 AM" + : hourNum < 12 + ? `${hourNum} AM` + : hourNum === 12 + ? "12 PM" + : `${hourNum - 12} PM`; + } catch (error) { + return label; // Return original label if parsing fails + } } + // Format daily labels (e.g., "2025-10-07" -> "Oct 7") - const date = new Date(label); - return date.toLocaleDateString("en-US", { - month: "short", - day: "numeric", - }); + try { + const date = new Date(label); + // Check if date is valid + if (isNaN(date.getTime())) { + return label; // Return original label if date is invalid + } + return date.toLocaleDateString("en-US", { + month: "short", + day: "numeric", + }); + } catch (error) { + return label; // Return original label if parsing fails + } }, }, grid: { From ac4415e1dca62e09ac957c13866dd9018654200f Mon Sep 17 00:00:00 2001 From: Muhammad Ibrahim Date: Wed, 8 Oct 2025 16:24:35 +0100 Subject: [PATCH 9/9] Added support for Oracle Linux 9 --- agents/patchmon-agent.sh | 10 +++++++--- frontend/src/utils/osIcons.jsx | 7 +++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/agents/patchmon-agent.sh b/agents/patchmon-agent.sh index 53b3c2a..8d16809 100755 --- a/agents/patchmon-agent.sh +++ b/agents/patchmon-agent.sh @@ -234,6 +234,10 @@ detect_os() { "rocky"|"almalinux") OS_TYPE="rhel" ;; + "ol") + # Keep Oracle Linux as 'ol' for proper frontend identification + OS_TYPE="ol" + ;; esac elif [[ -f /etc/redhat-release ]]; then @@ -261,7 +265,7 @@ get_repository_info() { "ubuntu"|"debian") get_apt_repositories repos_json first ;; - "centos"|"rhel"|"fedora") + "centos"|"rhel"|"fedora"|"ol") get_yum_repositories repos_json first ;; *) @@ -588,11 +592,11 @@ get_package_info() { "ubuntu"|"debian") get_apt_packages packages_json first ;; - "centos"|"rhel"|"fedora") + "centos"|"rhel"|"fedora"|"ol") get_yum_packages packages_json first ;; *) - error "Unsupported OS type: $OS_TYPE" + warning "Unsupported OS type: $OS_TYPE - returning empty package list" ;; esac diff --git a/frontend/src/utils/osIcons.jsx b/frontend/src/utils/osIcons.jsx index 1bc6b42..a6c33e3 100644 --- a/frontend/src/utils/osIcons.jsx +++ b/frontend/src/utils/osIcons.jsx @@ -29,12 +29,11 @@ export const getOSIcon = (osType) => { os.includes("rhel") || os.includes("red hat") || os.includes("almalinux") || - os.includes("rocky") || - os === "ol" || - os.includes("oraclelinux") || - os.includes("oracle linux") + os.includes("rocky") ) return SiCentos; + if (os === "ol" || os.includes("oraclelinux") || os.includes("oracle linux")) + return SiLinux; // Use generic Linux icon for Oracle Linux if (os.includes("fedora")) return SiFedora; if (os.includes("arch")) return SiArchlinux; if (os.includes("alpine")) return SiAlpinelinux;