From 904bca0ef4a4565940d42376b52a0885a34735aa Mon Sep 17 00:00:00 2001 From: Maximilian Kaske <56969857+mxkaske@users.noreply.github.com> Date: Wed, 25 Feb 2026 22:07:27 +0100 Subject: [PATCH] chore: dashboard agents page (#1883) * chore: dashboard agents page * fix: test * feat: slack agent content for status-page product page --- .../src/app/(dashboard)/agents/breadcrumb.tsx | 10 ++ .../src/app/(dashboard)/agents/layout.tsx | 26 +++++ .../app/(dashboard)/agents/nav-actions.tsx | 33 +++++++ .../src/app/(dashboard)/agents/page.tsx | 95 +++++++++++++++++++ .../src/app/(dashboard)/overview/page.tsx | 9 +- .../settings/integrations/page.tsx | 45 +++------ .../settings/integrations/slack-card.tsx | 27 +++++- apps/dashboard/src/components/common/note.tsx | 10 +- .../src/components/nav/app-sidebar.tsx | 6 ++ apps/dashboard/src/data/plans.ts | 4 + apps/server/src/routes/slack/index.test.ts | 1 + .../src/content/pages/product/status-page.mdx | 17 ++++ pnpm-lock.yaml | 2 - 13 files changed, 244 insertions(+), 41 deletions(-) create mode 100644 apps/dashboard/src/app/(dashboard)/agents/breadcrumb.tsx create mode 100644 apps/dashboard/src/app/(dashboard)/agents/layout.tsx create mode 100644 apps/dashboard/src/app/(dashboard)/agents/nav-actions.tsx create mode 100644 apps/dashboard/src/app/(dashboard)/agents/page.tsx diff --git a/apps/dashboard/src/app/(dashboard)/agents/breadcrumb.tsx b/apps/dashboard/src/app/(dashboard)/agents/breadcrumb.tsx new file mode 100644 index 00000000..5ca9121b --- /dev/null +++ b/apps/dashboard/src/app/(dashboard)/agents/breadcrumb.tsx @@ -0,0 +1,10 @@ +"use client"; + +import { NavBreadcrumb } from "@/components/nav/nav-breadcrumb"; +import { Bot } from "lucide-react"; + +export function Breadcrumb() { + return ( + + ); +} diff --git a/apps/dashboard/src/app/(dashboard)/agents/layout.tsx b/apps/dashboard/src/app/(dashboard)/agents/layout.tsx new file mode 100644 index 00000000..affb067c --- /dev/null +++ b/apps/dashboard/src/app/(dashboard)/agents/layout.tsx @@ -0,0 +1,26 @@ +import { + AppHeader, + AppHeaderActions, + AppHeaderContent, +} from "@/components/nav/app-header"; +import { AppSidebarTrigger } from "@/components/nav/app-sidebar"; + +import { Breadcrumb } from "./breadcrumb"; +import { NavActions } from "./nav-actions"; + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( +
+ + + + + + + + + +
{children}
+
+ ); +} diff --git a/apps/dashboard/src/app/(dashboard)/agents/nav-actions.tsx b/apps/dashboard/src/app/(dashboard)/agents/nav-actions.tsx new file mode 100644 index 00000000..a2c5a63c --- /dev/null +++ b/apps/dashboard/src/app/(dashboard)/agents/nav-actions.tsx @@ -0,0 +1,33 @@ +import { NavFeedback } from "@/components/nav/nav-feedback"; +import { Button } from "@openstatus/ui/components/ui/button"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@openstatus/ui/components/ui/tooltip"; +import { Book } from "lucide-react"; + +export function NavActions() { + return ( +
+ + + + + + + View Documentation + + +
+ ); +} diff --git a/apps/dashboard/src/app/(dashboard)/agents/page.tsx b/apps/dashboard/src/app/(dashboard)/agents/page.tsx new file mode 100644 index 00000000..afe4b853 --- /dev/null +++ b/apps/dashboard/src/app/(dashboard)/agents/page.tsx @@ -0,0 +1,95 @@ +"use client"; + +import { Code } from "@/components/common/code"; +import { Link } from "@/components/common/link"; +import { Note } from "@/components/common/note"; +import { + SectionDescription, + SectionGroup, + SectionHeader, + SectionTitle, +} from "@/components/content/section"; +import { Section } from "@/components/content/section"; +import { useTRPC } from "@/lib/trpc/client"; +import { Button } from "@openstatus/ui/components/ui/button"; +import { useQuery } from "@tanstack/react-query"; +import { Info } from "lucide-react"; + +const messages = [ + { + message: + "@openstatus create an incident for the payment API – high latency detected.", + description: "Open a new incident and notify your subscribers.", + }, + { + message: + "@openstatus keep the status page updated that we are still monitoring the issue.", + description: "Update the status report to 'Monitoring'.", + }, + { + message: "@openstatus resolve the ongoing incident on my API status page.", + description: "Close an active incident and update your subscribers.", + }, + { + message: + "@openstatus schedule a maintenance window for my database next Friday from 2–3 PM.", + description: "Plan downtime so subscribers are informed in advance.", + }, +]; + +export default function Page() { + const trpc = useTRPC(); + const { data: workspace } = useQuery(trpc.workspace.get.queryOptions()); + return ( + +
+ + Agents + + Use our Slack agent to manage your status pages and incidents.{" "} + + Read more + + . + + + {!workspace?.limits["slack-agent"] ? ( + + + This is a paid feature. Upgrade your plan to use the Slack agent. + + ) : null} + +
+
+ + Messages + + Here are some examples of messages that the Slack agent can handle. + + + + + Mention the @openstatus bot to trigger a response. This keeps threads + clean without the bot spamming your team. + +
    + {messages.map((message, i) => ( +
  • +

    + {message.description} +

    + {message.message} +
  • + ))} +
+
+
+ ); +} diff --git a/apps/dashboard/src/app/(dashboard)/overview/page.tsx b/apps/dashboard/src/app/(dashboard)/overview/page.tsx index ca84641a..d329e268 100644 --- a/apps/dashboard/src/app/(dashboard)/overview/page.tsx +++ b/apps/dashboard/src/app/(dashboard)/overview/page.tsx @@ -27,8 +27,7 @@ import { useTRPC } from "@/lib/trpc/client"; import { cn } from "@/lib/utils"; import { useQuery } from "@tanstack/react-query"; import { formatDistanceToNowStrict } from "date-fns"; -import { List, Search } from "lucide-react"; -import { Terminal } from "lucide-react"; +import { Bot, List, Search } from "lucide-react"; import Link from "next/link"; import { DataTableStatusReports } from "./data-table-status-reports"; @@ -132,10 +131,10 @@ export default function Page() { return ( - - Use Monitoring as Code to manage your monitors with our CLI. + + Use our Slack agent to manage your status pages and incidents. - Learn more + Learn more
diff --git a/apps/dashboard/src/app/(dashboard)/settings/integrations/page.tsx b/apps/dashboard/src/app/(dashboard)/settings/integrations/page.tsx index acb08066..b87949ce 100644 --- a/apps/dashboard/src/app/(dashboard)/settings/integrations/page.tsx +++ b/apps/dashboard/src/app/(dashboard)/settings/integrations/page.tsx @@ -9,12 +9,6 @@ import { } from "@/components/content/section"; import { FormCardGroup } from "@/components/forms/form-card"; import { useTRPC } from "@/lib/trpc/client"; -import { - Card, - CardContent, - CardHeader, - CardTitle, -} from "@openstatus/ui/components/ui/card"; import { useQuery } from "@tanstack/react-query"; import { SlackIntegrationCard } from "./slack-card"; @@ -41,31 +35,20 @@ export default function Page() { - {workspace?.limits["slack-agent"] ? ( - - ) : ( - - - No integrations available - - - Upgrade to a paid plan to access integrations and connect your - workspace to slack. - - - )} +
diff --git a/apps/dashboard/src/app/(dashboard)/settings/integrations/slack-card.tsx b/apps/dashboard/src/app/(dashboard)/settings/integrations/slack-card.tsx index be2996d4..e8d89cda 100644 --- a/apps/dashboard/src/app/(dashboard)/settings/integrations/slack-card.tsx +++ b/apps/dashboard/src/app/(dashboard)/settings/integrations/slack-card.tsx @@ -1,17 +1,21 @@ "use client"; +import { Link } from "@/components/common/link"; import { FormCard, FormCardContent, FormCardDescription, FormCardFooter, + FormCardFooterInfo, FormCardHeader, FormCardTitle, + FormCardUpgrade, } from "@/components/forms/form-card"; import { useTRPC } from "@/lib/trpc/client"; import { Badge } from "@openstatus/ui/components/ui/badge"; import { Button } from "@openstatus/ui/components/ui/button"; import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { Lock } from "lucide-react"; import { useRouter } from "next/navigation"; const SERVER_URL = @@ -20,6 +24,7 @@ const SERVER_URL = : "http://localhost:3000"; interface SlackIntegrationCardProps { + locked?: boolean; integration: { id: number; externalId: string; @@ -28,6 +33,7 @@ interface SlackIntegrationCardProps { } export function SlackIntegrationCard({ + locked, integration, }: SlackIntegrationCardProps) { const router = useRouter(); @@ -65,6 +71,7 @@ export function SlackIntegrationCard({ return ( + {locked ? : null}
Slack @@ -88,7 +95,25 @@ export function SlackIntegrationCard({ )} - {isConnected ? ( + + Learn more about{" "} + + Slack Agent + + . + + {locked ? ( + + ) : isConnected ? (