Openstatus www.openstatus.dev

🔥 External Status (#478)

* 🔥 External Status

* 🔥 External Status

authored by

Thibault Le Ouay and committed by
GitHub
8b6b1132 3173cce9

+79
+74
apps/web/src/app/status/page.tsx
··· 1 + import Link from "next/link"; 2 + import { z } from "zod"; 3 + 4 + import { 5 + Card, 6 + CardDescription, 7 + CardFooter, 8 + CardHeader, 9 + CardTitle, 10 + } from "@openstatus/ui"; 11 + 12 + import { Icons } from "@/components/icons"; 13 + import { MarketingLayout } from "@/components/layout/marketing-layout"; 14 + import { env } from "@/env"; 15 + 16 + const ExternalStatus = z.object({ 17 + id: z.number(), 18 + name: z.string(), 19 + url: z.string(), 20 + external_id: z.string(), 21 + last_updated_at: z.string().datetime({ offset: true }), 22 + time_zone: z.string(), 23 + status_indicator: z.string(), 24 + status_description: z.string(), 25 + created_at: z.string(), 26 + updated_at: z.string().datetime(), 27 + }); 28 + 29 + const ExternalStatusPage = async () => { 30 + console.log(env.EXTERNAL_API_URL); 31 + const res = await fetch(env.EXTERNAL_API_URL); 32 + const data = await res.json(); 33 + const openSourceFriends = z.array(ExternalStatus).parse(data); 34 + 35 + return ( 36 + <MarketingLayout> 37 + <h1 className="text-foreground font-cal mb-4 text-4xl"> 38 + Is my external service down? 39 + </h1> 40 + <div className="text-muted-foreground mb-6"> 41 + Easily check if your external providers is working properly 42 + </div> 43 + <div className="grid w-full grid-cols-1 gap-6 md:grid-cols-2"> 44 + {openSourceFriends.map((status) => ( 45 + <Card key={status.name} className="group flex flex-col"> 46 + <CardHeader className="flex-1"> 47 + <div className="flex items-center gap-2"> 48 + <CardTitle> 49 + <Link 50 + href={status.url} 51 + target="_blank" 52 + className="group-hover:underline" 53 + > 54 + {status.name} 55 + </Link> 56 + </CardTitle> 57 + </div> 58 + <CardDescription>{status.status_description}</CardDescription> 59 + </CardHeader> 60 + <CardFooter> 61 + <div className="flex items-center gap-2.5"> 62 + <Link href={status.url} target="_blank"> 63 + <Icons.globe className="text-muted-foreground h-5 w-5 hover:text-black" /> 64 + </Link> 65 + </div> 66 + </CardFooter> 67 + </Card> 68 + ))} 69 + </div> 70 + </MarketingLayout> 71 + ); 72 + }; 73 + 74 + export default ExternalStatusPage;
+1
apps/web/src/components/layout/marketing-footer.tsx
··· 29 29 <FooterLink href="/changelog" label="Changelog" /> 30 30 <FooterLink href="https://docs.openstatus.dev" label="Docs" /> 31 31 <FooterLink href="/oss-friends" label="OSS Friends" /> 32 + <FooterLink href="/status" label="External Providers Monitoring" /> 32 33 </div> 33 34 <div className="order-3 flex flex-col gap-3 text-sm md:order-4"> 34 35 <p className="text-foreground font-semibold">Legal</p>
+2
apps/web/src/env.ts
··· 22 22 GCP_CLIENT_EMAIL: z.string(), 23 23 GCP_PRIVATE_KEY: z.string(), 24 24 CRON_SECRET: z.string(), 25 + EXTERNAL_API_URL: z.string().url(), 25 26 }, 26 27 client: { 27 28 NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1), ··· 61 62 GCP_CLIENT_EMAIL: process.env.GCP_CLIENT_EMAIL, 62 63 GCP_PRIVATE_KEY: process.env.GCP_PRIVATE_KEY, 63 64 CRON_SECRET: process.env.CRON_SECRET, 65 + EXTERNAL_API_URL: process.env.EXTERNAL_API_URL, 64 66 }, 65 67 });
+2
apps/web/src/middleware.ts
··· 72 72 "/api/checker/cron/10m", 73 73 "/blog", 74 74 "/blog/(.*)", 75 + "/status", 76 + "/status/(.*)", 75 77 "/changelog", 76 78 "/changelog/(.*)", 77 79 "/legal/(.*)",