Fixed Issues with RHEL based systems not sending their repos to PatchMon

This commit is contained in:
Muhammad Ibrahim
2025-10-08 18:46:39 +01:00
parent 84cf31869b
commit cfc91243eb
3 changed files with 194 additions and 9 deletions

View File

@@ -8,6 +8,7 @@ import {
Clock,
Copy,
Cpu,
Database,
Eye,
EyeOff,
HardDrive,
@@ -31,6 +32,7 @@ import {
dashboardAPI,
formatDate,
formatRelativeTime,
repositoryAPI,
settingsAPI,
} from "../utils/api";
import { OSIcon } from "../utils/osIcons.jsx";
@@ -64,6 +66,15 @@ const HostDetail = () => {
refetchOnWindowFocus: false, // Don't refetch when window regains focus
});
// Fetch repository count for this host
const { data: repositories, isLoading: isLoadingRepos } = useQuery({
queryKey: ["host-repositories", hostId],
queryFn: () => repositoryAPI.getByHost(hostId).then((res) => res.data),
staleTime: 5 * 60 * 1000, // 5 minutes - data stays fresh longer
refetchOnWindowFocus: false, // Don't refetch when window regains focus
enabled: !!hostId,
});
// Tab change handler
const handleTabChange = (tabName) => {
setActiveTab(tabName);
@@ -290,7 +301,7 @@ const HostDetail = () => {
</div>
{/* Package Statistics Cards */}
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4 mb-6">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<button
type="button"
onClick={() => navigate(`/packages?host=${hostId}`)}
@@ -347,6 +358,25 @@ const HostDetail = () => {
</div>
</div>
</button>
<button
type="button"
onClick={() => navigate(`/repositories?host=${hostId}`)}
className="card p-4 cursor-pointer hover:shadow-card-hover dark:hover:shadow-card-hover-dark transition-shadow duration-200 text-left w-full"
title="View repositories for this host"
>
<div className="flex items-center">
<Database className="h-5 w-5 text-blue-600 mr-2" />
<div>
<p className="text-sm text-secondary-500 dark:text-white">
Repos
</p>
<p className="text-xl font-semibold text-secondary-900 dark:text-white">
{isLoadingRepos ? "..." : repositories?.length || 0}
</p>
</div>
</div>
</button>
</div>
{/* Main Content - Full Width */}

View File

@@ -18,21 +18,31 @@ import {
Unlock,
X,
} from "lucide-react";
import { useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import { repositoryAPI } from "../utils/api";
import { useEffect, useMemo, useState } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { dashboardAPI, repositoryAPI } from "../utils/api";
const Repositories = () => {
const queryClient = useQueryClient();
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const [searchTerm, setSearchTerm] = useState("");
const [filterType, setFilterType] = useState("all"); // all, secure, insecure
const [filterStatus, setFilterStatus] = useState("all"); // all, active, inactive
const [hostFilter, setHostFilter] = useState("");
const [sortField, setSortField] = useState("name");
const [sortDirection, setSortDirection] = useState("asc");
const [showColumnSettings, setShowColumnSettings] = useState(false);
const [deleteModalData, setDeleteModalData] = useState(null);
// Handle host filter from URL parameter
useEffect(() => {
const hostParam = searchParams.get("host");
if (hostParam) {
setHostFilter(hostParam);
}
}, [searchParams]);
// Column configuration
const [columnConfig, setColumnConfig] = useState(() => {
const defaultConfig = [
@@ -82,6 +92,17 @@ const Repositories = () => {
queryFn: () => repositoryAPI.getStats().then((res) => res.data),
});
// Fetch host information when filtering by host
const { data: hosts } = useQuery({
queryKey: ["hosts"],
queryFn: () => dashboardAPI.getHosts().then((res) => res.data),
staleTime: 5 * 60 * 1000,
enabled: !!hostFilter,
});
// Get the filtered host information
const filteredHost = hosts?.find((host) => host.id === hostFilter);
// Delete repository mutation
const deleteRepositoryMutation = useMutation({
mutationFn: (repositoryId) => repositoryAPI.delete(repositoryId),
@@ -202,7 +223,11 @@ const Repositories = () => {
(filterStatus === "active" && repo.is_active === true) ||
(filterStatus === "inactive" && repo.is_active === false);
return matchesSearch && matchesType && matchesStatus;
// Filter by host if hostFilter is set
const matchesHost =
!hostFilter || repo.hosts?.some((host) => host.id === hostFilter);
return matchesSearch && matchesType && matchesStatus && matchesHost;
});
// Sort repositories
@@ -237,6 +262,7 @@ const Repositories = () => {
filterStatus,
sortField,
sortDirection,
hostFilter,
]);
if (isLoading) {
@@ -421,6 +447,31 @@ const Repositories = () => {
</div>
</div>
{/* Host Filter Indicator */}
{hostFilter && filteredHost && (
<div className="flex items-center gap-2 px-3 py-2 bg-primary-50 dark:bg-primary-900 border border-primary-200 dark:border-primary-700 rounded-md">
<Server className="h-4 w-4 text-primary-600 dark:text-primary-400" />
<span className="text-sm text-primary-700 dark:text-primary-300">
Filtered by: {filteredHost.friendly_name}
</span>
<button
type="button"
onClick={() => {
setHostFilter("");
// Update URL to remove host parameter
const newSearchParams = new URLSearchParams(searchParams);
newSearchParams.delete("host");
navigate(`/repositories?${newSearchParams.toString()}`, {
replace: true,
});
}}
className="text-primary-500 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-200"
>
<X className="h-4 w-4" />
</button>
</div>
)}
{/* Security Filter */}
<div className="sm:w-48">
<select