Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle unhealthy backend on frontend #2971

Merged
merged 3 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions keep-ui/app/(keep)/error.css

This file was deleted.

5 changes: 5 additions & 0 deletions keep-ui/app/(keep)/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"use client";

import { ErrorComponent } from "@/shared/ui";

export default ErrorComponent;
79 changes: 0 additions & 79 deletions keep-ui/app/(keep)/error.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion keep-ui/app/(keep)/loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function Loading({
}`}
>
<Image
className="animate-bounce"
className="animate-bounce -my-10"
src="/keep.svg"
alt="loading"
width={200}
Expand Down
12 changes: 9 additions & 3 deletions keep-ui/app/(keep)/settings/auth/users-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import UsersSidebar from "./users-sidebar";
import { User } from "@/app/(keep)/settings/models";
import { UsersTable } from "./users-table";
import { useApi } from "@/shared/lib/hooks/useApi";
import { showErrorToast } from "@/shared/ui";
import { showErrorToast, ErrorComponent } from "@/shared/ui";

interface Props {
currentUser?: AuthUser;
Expand All @@ -30,7 +30,7 @@ export default function UsersSettings({
userCreationAllowed,
}: Props) {
const api = useApi();
const { data: users, isLoading, mutate: mutateUsers } = useUsers();
const { data: users, isLoading, error, mutate: mutateUsers } = useUsers();
const { data: roles = [] } = useRoles();
const { data: groups } = useGroups();
const { data: configData } = useConfig();
Expand Down Expand Up @@ -74,7 +74,13 @@ export default function UsersSettings({
});
}, [users, filter]);

if (!users || isLoading || !roles || !groups) return <Loading />;
if (error) {
return <ErrorComponent error={error} />;
}

if ((!users || !roles || !groups) && !isLoading) {
return <Loading />;
}

const handleRowClick = (user: User) => {
setSelectedUser(user);
Expand Down
24 changes: 8 additions & 16 deletions keep-ui/app/(keep)/workflows/workflows.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,24 @@

import { useRef, useState } from "react";
import useSWR from "swr";
import { Callout, Subtitle } from "@tremor/react";
import { Subtitle } from "@tremor/react";
import {
ArrowUpOnSquareStackIcon,
ExclamationCircleIcon,
PlusCircleIcon,
} from "@heroicons/react/24/outline";
import { Workflow, MockWorkflow } from "./models";
import Loading from "@/app/(keep)/loading";
import React from "react";
import WorkflowsEmptyState from "./noworkflows";
import WorkflowTile, { WorkflowTileOld } from "./workflow-tile";
import WorkflowTile from "./workflow-tile";
import { Button, Card, Title } from "@tremor/react";
import { ArrowRightIcon } from "@radix-ui/react-icons";
import { useRouter } from "next/navigation";
import Modal from "@/components/ui/Modal";
import MockWorkflowCardSection from "./mockworkflows";
import { useApi } from "@/shared/lib/hooks/useApi";
import { KeepApiError } from "@/shared/api";
import { showErrorToast, Input } from "@/shared/ui";
import { showErrorToast, Input, ErrorComponent } from "@/shared/ui";

export default function WorkflowsPage() {
const api = useApi();
Expand Down Expand Up @@ -62,19 +61,12 @@ export default function WorkflowsPage() {
(url: string) => api.get(url)
);

if (isLoading || !data) return <Loading />;

if (error) {
return (
<Callout
className="mt-4"
title="Error"
icon={ExclamationCircleIcon}
color="rose"
>
Failed to load workflows
</Callout>
);
return <ErrorComponent error={error} reset={() => {}} />;
}

if (isLoading || !data) {
return <Loading />;
}

const onDrop = async (files: any) => {
Expand Down
14 changes: 2 additions & 12 deletions keep-ui/app/global-error.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
"use client";

import * as Sentry from "@sentry/nextjs";
import NextError from "next/error";
import { useEffect } from "react";
import { ErrorComponent } from "@/shared/ui";

export default function GlobalError({
error,
}: {
error: Error & { digest?: string };
}) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);

return (
<html>
<body>
{/* `NextError` is the default Next.js error page component. Its type
definition requires a `statusCode` prop. However, since the App Router
does not expose status codes for errors, we simply pass 0 to render a
generic error message. */}
<NextError statusCode={0} />
<ErrorComponent error={error} />
</body>
</html>
);
Expand Down
45 changes: 25 additions & 20 deletions keep-ui/components/navbar/UserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import { Session } from "next-auth";
import { useConfig } from "utils/hooks/useConfig";
import { AuthType } from "@/utils/authenticationType";
import Link from "next/link";
import { AiOutlineRight } from "react-icons/ai";
import { VscDebugDisconnect } from "react-icons/vsc";
import { useFloating } from "@floating-ui/react";
import { Icon, Subtitle } from "@tremor/react";
import { Subtitle } from "@tremor/react";
import UserAvatar from "./UserAvatar";
import * as Frigade from "@frigade/react";
import { useState } from "react";
Expand All @@ -27,16 +26,20 @@ type UserDropdownProps = {
};

const UserDropdown = ({ session }: UserDropdownProps) => {
const { userRole, user } = session;
const { name, image, email } = user;

const { data: configData } = useConfig();
const signOut = useSignOut();
const { refs, floatingStyles } = useFloating({
placement: "right-end",
strategy: "fixed",
});

if (!session || !session.user) {
return null;
}

const { userRole, user } = session;
const { name, image, email } = user;

const isNoAuth = configData?.AUTH_TYPE === AuthType.NOAUTH;
return (
<Menu as="li" ref={refs.setReference} className="w-full">
Expand Down Expand Up @@ -96,21 +99,23 @@ export const UserInfo = ({ session }: UserInfoProps) => {
return (
<>
<ul className="space-y-2 p-2">
{isMounted && !config?.FRIGADE_DISABLED && flow?.isCompleted === false && (
<li>
<Frigade.ProgressBadge
flowId={ONBOARDING_FLOW_ID}
onClick={() => setIsOnboardingOpen(true)}
/>
<Onboarding
isOpen={isOnboardingOpen}
toggle={() => setIsOnboardingOpen(false)}
variables={{
name: session?.user.name ?? session?.user.email,
}}
/>
</li>
)}
{isMounted &&
!config?.FRIGADE_DISABLED &&
flow?.isCompleted === false && (
<li>
<Frigade.ProgressBadge
flowId={ONBOARDING_FLOW_ID}
onClick={() => setIsOnboardingOpen(true)}
/>
<Onboarding
isOpen={isOnboardingOpen}
toggle={() => setIsOnboardingOpen(false)}
variables={{
name: session?.user?.name ?? session?.user?.email,
}}
/>
</li>
)}
<li>
<LinkWithIcon href="/providers" icon={VscDebugDisconnect}>
Providers
Expand Down
29 changes: 3 additions & 26 deletions keep-ui/features/incident-list/ui/incident-list-error.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Fragment } from "react";
import { Button, Subtitle, Title } from "@tremor/react";
"use client";
import NotAuthorized from "@/app/not-authorized";

import { ErrorComponent } from "@/shared/ui";
interface IncidentListErrorProps {
incidentError: any;
}
Expand All @@ -13,27 +12,5 @@ export const IncidentListError = ({
return <NotAuthorized message={incidentError.message} />;
}

return (
<Fragment>
<div className="flex flex-col items-center justify-center gap-y-8 h-full">
<div className="text-center space-y-3">
<Title className="text-2xl">Failed to load incidents</Title>
<Subtitle className="text-gray-400">
Error: {incidentError.message}
</Subtitle>
<Subtitle className="text-gray-400">
{incidentError.proposedResolution ||
"Please try again. If the issue persists, contact us"}
</Subtitle>
<Button
color="orange"
variant="secondary"
onClick={() => window.open("https://slack.keephq.dev/", "_blank")}
>
Slack Us
</Button>
</div>
</div>
</Fragment>
);
return <ErrorComponent error={incidentError} />;
};
12 changes: 2 additions & 10 deletions keep-ui/features/incident-list/ui/incident-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,20 +106,12 @@ export function IncidentList({

function renderIncidents() {
if (incidentsError) {
return (
<Card className="flex-grow">
<IncidentListError incidentError={incidentsError} />
</Card>
);
return <IncidentListError incidentError={incidentsError} />;
}

if (isLoading) {
// TODO: only show this on the initial load
return (
<Card className="flex-grow">
<Loading />
</Card>
);
return <Loading />;
}

if (incidents && (incidents.items.length > 0 || areFiltersApplied)) {
Expand Down
2 changes: 1 addition & 1 deletion keep-ui/shared/api/ApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export class ApiClient {
);
}
}
throw new Error("An error occurred while fetching the data.");
throw new Error("An error occurred while fetching the data");
}

if (response.headers.get("content-length") === "0") {
Expand Down
Loading
Loading