Skip to content

Commit

Permalink
UI for reconciliation
Browse files Browse the repository at this point in the history
Signed-off-by: hemahg <[email protected]>
  • Loading branch information
hemahg committed Oct 24, 2024
1 parent e3125a2 commit b3b6b93
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ export function ConnectButton({ clusterId }: { clusterId: string }) {
const { isReconciliationPaused, setReconciliationPaused } =
useReconciliationContext();

const updateReconciliation = async (reconciliationPaused: boolean) => {
const onClickUpdate = async (pausedState: boolean) => {
try {
const success = await updateKafkaCluster(clusterId, reconciliationPaused);
const success = await updateKafkaCluster(clusterId, pausedState);

if (success) {
setReconciliationPaused(pausedState);
setIsModalOpen(false);
setReconciliationPaused(reconciliationPaused);
}
} catch (e: unknown) {
console.log("Unknown error occurred");
Expand All @@ -38,7 +38,7 @@ export function ConnectButton({ clusterId }: { clusterId: string }) {
variant="secondary"
onClick={
isReconciliationPaused
? () => updateReconciliation(false)
? () => onClickUpdate(false)
: () => setIsModalOpen(true)
}
>
Expand All @@ -57,7 +57,7 @@ export function ConnectButton({ clusterId }: { clusterId: string }) {
<ReconciliationModal
isModalOpen={isModalOpen}
onClickClose={() => setIsModalOpen(false)}
onClickPauseReconciliation={() => updateReconciliation(true)}
onClickPauseReconciliation={() => onClickUpdate(true)}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ async function ConnectedHeader({
if (!cluster) {
notFound();
}

return <OverviewHeader params={{ kafkaId }} />;
}

Expand Down
25 changes: 20 additions & 5 deletions ui/app/[locale]/(authorized)/kafka/[kafkaId]/ClusterLinks.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { getKafkaCluster } from "@/api/kafka/actions";
import { NavItemLink } from "@/components/Navigation/NavItemLink";
import { NavGroup, NavList } from "@/libs/patternfly/react-core";
import { useTranslations } from "next-intl";
import { ClusterDetail } from "@/api/kafka/schema";
import { Suspense } from "react";

export function ClusterLinks({ kafkaCluster }: { kafkaCluster: ClusterDetail; }) {
export function ClusterLinks({ kafkaId }: { kafkaId: string }) {
const t = useTranslations();
const kafkaId = kafkaCluster.id;

return (
<NavList>
<NavGroup
title={ kafkaCluster?.attributes.name ?? `Cluster ${kafkaId}` }
title={
(
<Suspense>
<ClusterName kafkaId={kafkaId} />
</Suspense>
) as unknown as string
}
>
<NavItemLink url={`/kafka/${kafkaId}/overview`}>
{t("AppLayout.cluster_overview")}
Expand All @@ -21,10 +26,20 @@ export function ClusterLinks({ kafkaCluster }: { kafkaCluster: ClusterDetail; })
<NavItemLink url={`/kafka/${kafkaId}/nodes`}>
{t("AppLayout.brokers")}
</NavItemLink>
{/*
<NavItemLink url={`/kafka/${kafkaId}/service-registry`}>
Service registry
</NavItemLink>
*/}
<NavItemLink url={`/kafka/${kafkaId}/consumer-groups`}>
{t("AppLayout.consumer_groups")}
</NavItemLink>
</NavGroup>
</NavList>
);
}

async function ClusterName({ kafkaId }: { kafkaId: string }) {
const cluster = await getKafkaCluster(kafkaId);
return cluster?.attributes.name ?? `Cluster ${kafkaId}`;
}
20 changes: 11 additions & 9 deletions ui/app/[locale]/(authorized)/kafka/[kafkaId]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { notFound } from "next/navigation";
import { getKafkaCluster } from "@/api/kafka/actions";
import { ClusterLinks } from "@/app/[locale]/(authorized)/kafka/[kafkaId]/ClusterLinks";
import { getAuthOptions } from "@/app/api/auth/[...nextauth]/route";
import { AppLayout } from "@/components/AppLayout";
Expand All @@ -10,9 +8,11 @@ import {
PageGroup,
} from "@/libs/patternfly/react-core";
import { getServerSession } from "next-auth";
import { useTranslations } from "next-intl";
import { PropsWithChildren, ReactNode, Suspense } from "react";
import { KafkaParams } from "./kafka.params";
import { ClusterDetail } from "@/api/kafka/schema";
import { notFound } from "next/navigation";
import { getKafkaCluster } from "@/api/kafka/actions";

export default async function AsyncLayout({
children,
Expand All @@ -28,6 +28,7 @@ export default async function AsyncLayout({
}>) {
const authOptions = await getAuthOptions();
const session = await getServerSession(authOptions);

const cluster = await getKafkaCluster(kafkaId);

if (!cluster) {
Expand All @@ -36,8 +37,8 @@ export default async function AsyncLayout({

return (
<Layout
username={(session?.user?.name ?? session?.user?.email) ?? "User"}
kafkaCluster={cluster}
username={(session?.user?.name || session?.user?.email) ?? "User"}
kafkaId={kafkaId}
activeBreadcrumb={activeBreadcrumb}
header={header}
modal={modal}
Expand All @@ -52,21 +53,22 @@ function Layout({
activeBreadcrumb,
header,
modal,
kafkaCluster,
kafkaId,
username,
}: PropsWithChildren<{
kafkaCluster: ClusterDetail;
kafkaId: string;
username: string;
header: ReactNode;
activeBreadcrumb: ReactNode;
modal: ReactNode;
}>) {
const t = useTranslations();
return (
<AppLayoutProvider>
<AppLayout
username={username}
sidebar={<ClusterLinks kafkaCluster={kafkaCluster} />}
kafkaCluster={kafkaCluster}
kafkaId={kafkaId}
sidebar={<ClusterLinks kafkaId={kafkaId} />}
>
<PageGroup stickyOnBreakpoint={{ default: "top" }}>
<PageBreadcrumb>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export async function ConnectedClusterCard({
brokersTotal={undefined}
kafkaVersion={res?.cluster.attributes.kafkaVersion ?? "n/a"}
kafkaId={res?.cluster.id}
reconciliationPaused={res?.cluster.meta?.reconciliationPaused ?? false}
/>
);
}
Expand Down Expand Up @@ -58,7 +57,6 @@ export async function ConnectedClusterCard({
brokersTotal={brokersTotal}
kafkaVersion={res?.cluster.attributes.kafkaVersion ?? "n/a"}
kafkaId={res.cluster.id}
reconciliationPaused={res?.cluster.meta?.reconciliationPaused ?? false}
/>
);
}
12 changes: 4 additions & 8 deletions ui/components/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useTranslations } from "next-intl";
import { PropsWithChildren, ReactNode } from "react";
import { AppMasthead } from "./AppMasthead";
import { AppSidebar } from "./AppSidebar";
import { ClusterDetail } from "@/api/kafka/schema";
import { ClusterDrawer } from "./ClusterDrawer";

import { ClusterDrawerProvider } from "./ClusterDrawerProvider";
Expand All @@ -13,15 +12,14 @@ import { ReconciliationPausedBanner } from "./ReconciliationPausedBanner";
export function AppLayout({
username,
sidebar,
kafkaCluster,
children,
kafkaId,
}: PropsWithChildren<{
username?: string;
sidebar?: ReactNode;
kafkaCluster?: ClusterDetail;
kafkaId?: string;
}>) {
const t = useTranslations();

return (
<Page
header={<AppMasthead username={username} showSidebarToggle={!!sidebar} />}
Expand All @@ -37,10 +35,8 @@ export function AppLayout({
>
{/*<HelpContainer>*/}
<ClusterDrawerProvider>
<ReconciliationProvider>
{kafkaCluster && (
<ReconciliationPausedBanner kafkaCluster={kafkaCluster} />
)}
<ReconciliationProvider kafkaId={kafkaId || ""}>
<ReconciliationPausedBanner kafkaId={kafkaId || ""} />
<ClusterDrawer>{children}</ClusterDrawer>
</ReconciliationProvider>
</ClusterDrawerProvider>
Expand Down
27 changes: 17 additions & 10 deletions ui/components/ClusterOverview/ClusterCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ type ClusterCardProps = {
consumerGroups?: number;
kafkaVersion: string;
kafkaId: string | undefined;
reconciliationPaused: boolean;
messages: Array<{
variant: "danger" | "warning";
subject: { type: string; name: string; id: string };
Expand All @@ -60,7 +59,6 @@ export function ClusterCard({
kafkaVersion,
messages,
kafkaId,
reconciliationPaused,
}:
| ({
isLoading: false;
Expand All @@ -71,8 +69,6 @@ export function ClusterCard({
const { isReconciliationPaused, setReconciliationPaused } =
useReconciliationContext();

setReconciliationPaused(reconciliationPaused as boolean);

const resumeReconciliation = async () => {
if (!kafkaId) {
console.log("kafkaId is undefined");
Expand Down Expand Up @@ -236,7 +232,7 @@ export function ClusterCard({
))
) : (
<>
{messages.length === 0 && (
{isReconciliationPaused && messages.length === 0 && (
<DataListItem aria-labelledby={`no-messages`}>
<DataListItemRow>
<DataListItemCells
Expand Down Expand Up @@ -281,14 +277,25 @@ export function ClusterCard({
"pf-v5-u-display-none pf-v5-u-display-block-on-md"
}
>
<Truncate content={ m.subject.type === 'ReconciliationPaused'
? t("reconciliation.reconciliation_paused_warning",)
: m.message}
<Truncate
content={
m.subject.type ===
"ReconciliationPaused"
? t(
"reconciliation.reconciliation_paused_warning",
)
: m.message
}
/>
{m.subject.type === 'ReconciliationPaused' && (
{m.subject.type ===
"ReconciliationPaused" && (
<>
&nbsp;
<Button variant="link" isInline onClick={resumeReconciliation}>
<Button
variant="link"
isInline
onClick={resumeReconciliation}
>
{t("reconciliation.resume")}
</Button>
</>
Expand Down
63 changes: 30 additions & 33 deletions ui/components/ReconciliationPausedBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,51 @@

"use client";

import { Banner, Bullseye, Button, FlexItem, Flex } from "@/libs/patternfly/react-core";
import {
Banner,
Bullseye,
Button,
Flex,
FlexItem,
} from "@/libs/patternfly/react-core";
import { useTranslations } from "next-intl";
import { useReconciliationContext } from "./ReconciliationContext";
import { updateKafkaCluster } from "@/api/kafka/actions";
import { ClusterDetail } from "@/api/kafka/schema";

export function ReconciliationPausedBanner({ kafkaCluster }: { kafkaCluster: ClusterDetail; }) {
export function ReconciliationPausedBanner({ kafkaId }: { kafkaId: string }) {
const t = useTranslations();

const { isReconciliationPaused, setReconciliationPaused } = useReconciliationContext();

setReconciliationPaused(kafkaCluster.meta?.reconciliationPaused ?? false);
const { isReconciliationPaused, setReconciliationPaused } =
useReconciliationContext();

const resumeReconciliation = async () => {
if (!kafkaCluster) {
console.log("kafkaCluster is undefined");
return;
}

try {
const success = await updateKafkaCluster(kafkaCluster.id, false);
const success = await updateKafkaCluster(kafkaId, false);

if (success) {
setReconciliationPaused(false);
}
} catch (e: unknown) {
console.log("Unknown error occurred");
}
}
};

if (!isReconciliationPaused) return null;

return (
isReconciliationPaused && (
<Banner variant="gold">
<Bullseye>
<Flex>
<FlexItem spacer={{ default: "spacerNone" }}>
{t("reconciliation.reconciliation_paused_warning")}
</FlexItem>
&nbsp;
<FlexItem spacer={{ default: "spacerLg" }}>
<Button variant="link" isInline onClick={resumeReconciliation}>
{t("reconciliation.resume")}
</Button>
</FlexItem>
</Flex>
</Bullseye>
</Banner>
)
)
<Banner variant="gold">
<Bullseye>
<Flex>
<FlexItem spacer={{ default: "spacerNone" }}>
{t("reconciliation.reconciliation_paused_warning")}
</FlexItem>
&nbsp;
<FlexItem spacer={{ default: "spacerLg" }}>
<Button variant="link" isInline onClick={resumeReconciliation}>
{t("reconciliation.resume")}
</Button>
</FlexItem>
</Flex>
</Bullseye>
</Banner>
);
}

Loading

0 comments on commit b3b6b93

Please sign in to comment.