diff --git a/ui/api/topics/actions.ts b/ui/api/topics/actions.ts index 49ad4a4f0..3a067118f 100644 --- a/ui/api/topics/actions.ts +++ b/ui/api/topics/actions.ts @@ -1,5 +1,15 @@ "use server"; -import { fetchData, patchData, postData, getHeaders, ApiResponse, filterEq, filterIn, filterLike, sortParam } from "@/api/api"; +import { + fetchData, + patchData, + postData, + getHeaders, + ApiResponse, + filterEq, + filterIn, + filterLike, + sortParam, +} from "@/api/api"; import { getKafkaCluster } from "@/api/kafka/actions"; import { describeTopicsQuery, @@ -56,10 +66,8 @@ export async function getTopics( }), ); - return fetchData( - `/api/kafkas/${kafkaId}/topics`, - sp, - (rawData: any) => TopicsResponseSchema.parse(rawData), + return fetchData(`/api/kafkas/${kafkaId}/topics`, sp, (rawData: any) => + TopicsResponseSchema.parse(rawData), ); } @@ -98,7 +106,7 @@ export async function createTopic( }, }, }, - (rawData) => TopicCreateResponseSchema.parse(rawData) + (rawData) => TopicCreateResponseSchema.parse(rawData), ); } @@ -122,7 +130,7 @@ export async function updateTopic( }, }, }, - _ => undefined + (_) => undefined, ); } @@ -154,6 +162,7 @@ export type ViewedTopic = { kafkaName: string; topicId: string; topicName: string; + topicStatus: TopicStatus; }; export async function getViewedTopics(): Promise { @@ -177,6 +186,7 @@ export async function setTopicAsViewed(kafkaId: string, topicId: string) { topicId, // name is included in the `fields[topics]` param list so we are sure it is present topicName: topic.attributes.name!, + topicStatus: topic.attributes.status!, }; if (viewedTopics.find((t) => t.topicId === viewedTopic.topicId)) { log.trace( diff --git a/ui/components/ClusterOverview/components/TopicsTable.stories.tsx b/ui/components/ClusterOverview/components/TopicsTable.stories.tsx index 3a50a83f0..9c1b0c72a 100644 --- a/ui/components/ClusterOverview/components/TopicsTable.stories.tsx +++ b/ui/components/ClusterOverview/components/TopicsTable.stories.tsx @@ -1,7 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; import { TopicsTable } from "./TopicsTable"; - const meta: Meta = { component: TopicsTable, args: { @@ -9,7 +8,6 @@ const meta: Meta = { }, } as Meta; - export default meta; type Story = StoryObj; @@ -20,32 +18,37 @@ export const Default: Story = { kafkaId: "1", kafkaName: "kafka1", topicId: "1", - topicName: "console_datagen_000-a" + topicName: "console_datagen_000-a", + topicStatus: "FullyReplicated", }, { kafkaId: "1", kafkaName: "kafka1", topicId: "3", - topicName: "console_datagen_000-b" + topicName: "console_datagen_000-b", + topicStatus: "UnderReplicated", }, { kafkaId: "2", kafkaName: "kafka2", topicId: "1", - topicName: "__consumer_offsets" + topicName: "__consumer_offsets", + topicStatus: "Unknown", }, { kafkaId: "2", kafkaName: "kafka2", topicId: "4", - topicName: "console_datagen_002-a" + topicName: "console_datagen_002-a", + topicStatus: "Offline", }, { kafkaId: "2", kafkaName: "kafka2", topicId: "6", - topicName: "console_datagen_002-b" + topicName: "console_datagen_002-b", + topicStatus: "FullyReplicated", }, - ] + ], }, }; diff --git a/ui/components/ClusterOverview/components/TopicsTable.tsx b/ui/components/ClusterOverview/components/TopicsTable.tsx index f410dadcc..2b3cdff53 100644 --- a/ui/components/ClusterOverview/components/TopicsTable.tsx +++ b/ui/components/ClusterOverview/components/TopicsTable.tsx @@ -5,8 +5,58 @@ import { Link } from "@/i18n/routing"; import { Truncate } from "@patternfly/react-core"; import { TableVariant } from "@patternfly/react-table"; import { useTranslations } from "next-intl"; +import { ReactNode } from "react"; +import { Icon } from "@/libs/patternfly/react-core"; +import { + CheckCircleIcon, + ExclamationCircleIcon, + ExclamationTriangleIcon, +} from "@/libs/patternfly/react-icons"; +import { TopicStatus } from "@/api/topics/schema"; -export const TopicsTableColumns = ["name", "cluster"] as const; +export const TopicsTableColumns = ["name", "status"] as const; +const StatusLabel: Record = { + FullyReplicated: ( + <> + + + +  Fully replicated + + ), + UnderReplicated: ( + <> + + + +  Under replicated + + ), + PartiallyOffline: ( + <> + + + +  Partially offline + + ), + Unknown: ( + <> + + + +  Unknown + + ), + Offline: ( + <> + + + +  Offline + + ), +}; export type TopicsTableProps = { topics: ViewedTopic[] | undefined; @@ -28,10 +78,10 @@ export function TopicsTable({ topics }: TopicsTableProps) { {t("recently_viewed_topics.topic_name")} ); - case "cluster": + case "status": return ( - - {t("recently_viewed_topics.cluster")} + + {t("recently_viewed_topics.topic_status")} ); } @@ -46,10 +96,10 @@ export function TopicsTable({ topics }: TopicsTableProps) { ); - case "cluster": + case "status": return ( - - {row.kafkaName} + + {StatusLabel[row.topicStatus!]} ); } diff --git a/ui/messages/en.json b/ui/messages/en.json index 1135f66fe..b209a4f36 100644 --- a/ui/messages/en.json +++ b/ui/messages/en.json @@ -168,7 +168,7 @@ }, "recently_viewed_topics": { "topic_name": "Name", - "cluster": "Cluster" + "topic_status": "Status" } }, "topic-creator": {