feat: Implement cluster count fetching and enhance Kubernetes monitoring UI with installation guidance

This commit is contained in:
Nawaz Dhandala
2026-03-18 09:11:20 +00:00
parent 2d56a56650
commit ef7ce703dd
2 changed files with 84 additions and 15 deletions

View File

@@ -3,14 +3,77 @@ import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import PageComponentProps from "../PageComponentProps";
import Route from "Common/Types/API/Route";
import KubernetesCluster from "Common/Models/DatabaseModels/KubernetesCluster";
import React, { Fragment, FunctionComponent, ReactElement } from "react";
import React, {
Fragment,
FunctionComponent,
ReactElement,
useEffect,
useState,
} from "react";
import ModelTable from "Common/UI/Components/ModelTable/ModelTable";
import FieldType from "Common/UI/Components/Types/FieldType";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import MarkdownViewer from "Common/UI/Components/Markdown.tsx/MarkdownViewer";
import { getKubernetesInstallationMarkdown } from "./Utils/DocumentationMarkdown";
import ModelAPI from "Common/UI/Utils/ModelAPI/ModelAPI";
import API from "Common/UI/Utils/API/API";
import PageLoader from "Common/UI/Components/Loader/PageLoader";
import ErrorMessage from "Common/UI/Components/ErrorMessage/ErrorMessage";
import Card from "Common/UI/Components/Card/Card";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
const KubernetesClusters: FunctionComponent<
PageComponentProps
> = (): ReactElement => {
const [clusterCount, setClusterCount] = useState<number | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [error, setError] = useState<string>("");
const fetchClusterCount: PromiseVoidFunction = async (): Promise<void> => {
setIsLoading(true);
try {
const count: number = await ModelAPI.count({
modelType: KubernetesCluster,
query: {},
});
setClusterCount(count);
} catch (err) {
setError(API.getFriendlyMessage(err));
}
setIsLoading(false);
};
useEffect(() => {
fetchClusterCount().catch((err: Error) => {
setError(API.getFriendlyMessage(err));
});
}, []);
if (isLoading) {
return <PageLoader isVisible={true} />;
}
if (error) {
return <ErrorMessage message={error} />;
}
if (clusterCount === 0) {
return (
<Fragment>
<Card
title="Getting Started with Kubernetes Monitoring"
description="No Kubernetes clusters connected yet. Install the agent using the guide below and your cluster will appear here automatically."
>
<div className="px-4 pb-6">
<MarkdownViewer
text={getKubernetesInstallationMarkdown("my-cluster")}
/>
</div>
</Card>
</Fragment>
);
}
return (
<Fragment>
<ModelTable<KubernetesCluster>
@@ -28,7 +91,6 @@ const KubernetesClusters: FunctionComponent<
description:
"Clusters being monitored in this project. Install the OneUptime kubernetes-agent Helm chart to connect a cluster.",
}}
noItemsMessage="No Kubernetes clusters connected yet."
showViewIdButton={true}
formFields={[
{

View File

@@ -397,21 +397,28 @@ const MarkdownViewer: FunctionComponent<ComponentProps> = (
blockquote: ({ children, ...props }: any) => {
return (
<blockquote
className="flex items-start gap-3 rounded-lg border border-blue-200 bg-blue-50/70 pl-4 pr-4 py-3 my-4 text-sm text-gray-600 not-italic shadow-sm"
className="rounded-lg border border-blue-200 bg-blue-50/70 my-4 not-italic shadow-sm overflow-hidden"
{...props}
>
<svg
className="mt-0.5 h-5 w-5 flex-shrink-0 text-blue-400"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
clipRule="evenodd"
/>
</svg>
<div className="flex-1">{children}</div>
<div className="flex items-center gap-2 px-4 py-2 bg-blue-100/60 border-b border-blue-200/60">
<svg
className="h-4 w-4 flex-shrink-0 text-blue-500"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
clipRule="evenodd"
/>
</svg>
<span className="text-xs font-semibold uppercase tracking-wider text-blue-600">
Note
</span>
</div>
<div className="px-4 py-3 text-sm text-gray-600 leading-relaxed [&>p]:mt-0 [&>p]:mb-0 [&>p>strong:first-child]:hidden">
{children}
</div>
</blockquote>
);
},