Openstatus www.openstatus.dev

chore: remove next config flag (#836)

* chore: remove experiments flag

* wip: fix ref and add protected column

* fix: missing use client

* fix: sms schema

* fix: remove logs

* chore: update default parser value

authored by

Maximilian Kaske and committed by
GitHub
3aedd36a 4675021b

+67 -32
-4
apps/web/next.config.js
··· 15 15 // "better-sqlite3" 16 16 ], 17 17 optimizePackageImports: ["@tremor/react"], 18 - // FIXME: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout 19 - // TODO: https://nextjs.org/docs/app/api-reference/functions/use-search-params#static-rendering 20 - // TODO: https://nextjs.org/docs/messages/deopted-into-client-rendering 21 - missingSuspenseWithCSRBailout: false, 22 18 }, 23 19 logging: { 24 20 fetches: {
+2 -2
apps/web/src/app/pricing/page.tsx
··· 5 5 import { MarketingLayout } from "@/components/layout/marketing-layout"; 6 6 import { FAQs } from "@/components/marketing/faqs"; 7 7 import { EnterpricePlan } from "@/components/marketing/pricing/enterprice-plan"; 8 - import { PricingWrapper } from "@/components/marketing/pricing/pricing-wrapper"; 8 + import { PricingWrapperSuspense } from "@/components/marketing/pricing/pricing-wrapper"; 9 9 import { 10 10 defaultMetadata, 11 11 ogMetadata, ··· 37 37 All plans. Start free today, upgrade later. 38 38 </p> 39 39 </div> 40 - <PricingWrapper /> 40 + <PricingWrapperSuspense /> 41 41 <p className="text-muted-foreground text-sm"> 42 42 Learn more about the{" "} 43 43 <Link
+23 -2
apps/web/src/app/status-page/[domain]/_components/password-form.tsx
··· 3 3 import { zodResolver } from "@hookform/resolvers/zod"; 4 4 import { Eye, EyeOff } from "lucide-react"; 5 5 import { usePathname, useRouter, useSearchParams } from "next/navigation"; 6 - import { useEffect, useState, useTransition } from "react"; 6 + import { Suspense, useEffect, useState, useTransition } from "react"; 7 7 import { useForm } from "react-hook-form"; 8 8 import { z } from "zod"; 9 9 ··· 16 16 FormLabel, 17 17 FormMessage, 18 18 InputWithAddons, 19 + Skeleton, 19 20 } from "@openstatus/ui"; 20 21 21 22 import { LoadingAnimation } from "@/components/loading-animation"; ··· 34 35 35 36 type Schema = z.infer<typeof schema>; 36 37 37 - export function PasswordForm({ slug }: { slug: string }) { 38 + interface PasswordFormProps { 39 + slug: string; 40 + } 41 + 42 + export function PasswordForm({ slug }: PasswordFormProps) { 38 43 const form = useForm<Schema>({ 39 44 resolver: zodResolver(schema), 40 45 defaultValues: { password: "" }, ··· 129 134 </Form> 130 135 ); 131 136 } 137 + 138 + export function PasswordFormSuspense(props: PasswordFormProps) { 139 + return ( 140 + <Suspense 141 + fallback={ 142 + <div className="grid w-full gap-4"> 143 + <Skeleton className="h-4 w-8" /> 144 + <Skeleton className="h-10 w-full" /> 145 + <Skeleton className="h-8 w-full" /> 146 + </div> 147 + } 148 + > 149 + <PasswordForm {...props} /> 150 + </Suspense> 151 + ); 152 + }
+2 -2
apps/web/src/app/status-page/[domain]/_components/password-protected.tsx
··· 2 2 3 3 import { Shell } from "@/components/dashboard/shell"; 4 4 import { Footer } from "../_components/footer"; 5 - import { PasswordForm } from "../_components/password-form"; 5 + import { PasswordFormSuspense } from "../_components/password-form"; 6 6 7 7 export default function PasswordProtected({ 8 8 slug, ··· 22 22 <p className="text-center text-muted-foreground text-sm"> 23 23 Enter the password to access the status page. 24 24 </p> 25 - <PasswordForm slug={slug} /> 25 + <PasswordFormSuspense slug={slug} /> 26 26 </div> 27 27 </Shell> 28 28 </main>
+14 -2
apps/web/src/components/data-table/status-page/columns.tsx
··· 15 15 } from "@openstatus/ui"; 16 16 17 17 import { DataTableRowActions } from "./data-table-row-actions"; 18 + import { Check } from "lucide-react"; 18 19 19 20 export const columns: ColumnDef< 20 21 Page & { monitorsToPages: { monitor: { name: string } }[] } ··· 66 67 {lastMonitors.length > 0 ? ( 67 68 <TooltipProvider> 68 69 <Tooltip delayDuration={200}> 69 - <TooltipTrigger asChild> 70 + <TooltipTrigger> 70 71 <Badge variant="secondary" className="border"> 71 72 +{lastMonitors.length} 72 73 </Badge> ··· 91 92 header: "Favicon", 92 93 cell: ({ row }) => { 93 94 if (!row.getValue("icon")) { 94 - return <span className="text-muted-foreground">-</span>; 95 + return <span className="text-muted-foreground/50">-</span>; 95 96 } 96 97 return ( 97 98 <Image ··· 102 103 height={20} 103 104 /> 104 105 ); 106 + }, 107 + }, 108 + { 109 + accessorKey: "passwordProtected", 110 + header: "Protected", 111 + cell: ({ row }) => { 112 + const passwordProtected = Boolean(row.getValue("passwordProtected")); 113 + if (passwordProtected) { 114 + return <Check className="h-4 w-4 text-foreground" />; 115 + } 116 + return <span className="text-muted-foreground/50">-</span>; 105 117 }, 106 118 }, 107 119 // {
-3
apps/web/src/components/forms/status-page/section-monitor.tsx
··· 39 39 }); 40 40 const watchMonitors = form.watch("monitors"); 41 41 42 - console.log("fields", fields.length); 43 - console.log("monitors", monitors); 44 - 45 42 return ( 46 43 <div className="grid w-full gap-4"> 47 44 <SectionHeader
+4 -6
apps/web/src/components/forms/status-report/section-connect.tsx
··· 55 55 name="page" 56 56 checked={field.value?.includes(item.id)} 57 57 onCheckedChange={(checked) => { 58 - console.log(field, item.id, checked); 59 58 return checked 60 59 ? field.onChange([ 61 60 ...(field.value || []), ··· 63 62 ]) 64 63 : field.onChange( 65 64 field.value?.filter( 66 - (value) => value !== item.id 67 - ) 65 + (value) => value !== item.id, 66 + ), 68 67 ); 69 68 }} 70 69 > ··· 112 111 name="monitor" 113 112 checked={field.value?.includes(item.id)} 114 113 onCheckedChange={(checked) => { 115 - console.log(field, item.id, checked); 116 114 return checked 117 115 ? field.onChange([ 118 116 ...(field.value || []), ··· 120 118 ]) 121 119 : field.onChange( 122 120 field.value?.filter( 123 - (value) => value !== item.id 124 - ) 121 + (value) => value !== item.id, 122 + ), 125 123 ); 126 124 }} 127 125 >
+1 -5
apps/web/src/components/layout/app-menu.tsx
··· 1 1 "use client"; 2 2 3 3 import { ChevronsUpDown } from "lucide-react"; 4 - import { 5 - usePathname, 6 - useSearchParams, 7 - useSelectedLayoutSegment, 8 - } from "next/navigation"; 4 + import { useSelectedLayoutSegment } from "next/navigation"; 9 5 import * as React from "react"; 10 6 11 7 import {
+13
apps/web/src/components/marketing/pricing/pricing-wrapper.tsx
··· 6 6 7 7 import { PricingPlanRadio } from "./pricing-plan-radio"; 8 8 import { PricingTable } from "./pricing-table"; 9 + import { Suspense } from "react"; 9 10 10 11 export function PricingWrapper() { 11 12 const searchParams = useSearchParams(); ··· 23 24 </div> 24 25 ); 25 26 } 27 + 28 + // REMINDER: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout 29 + // REMINDER: https://nextjs.org/docs/app/api-reference/functions/use-search-params#static-rendering 30 + // REMINDER: https://nextjs.org/docs/messages/deopted-into-client-rendering 31 + // experiments.missingSuspenseWithCSRBailout: false, within next.config.js 32 + export function PricingWrapperSuspense() { 33 + return ( 34 + <Suspense> 35 + <PricingWrapper /> 36 + </Suspense> 37 + ); 38 + }
+2
apps/web/src/components/modals/failed-ping-alert-confirmation.tsx
··· 1 + "use client"; 2 + 1 3 import React from "react"; 2 4 3 5 import type { InsertMonitor } from "@openstatus/db/src/schema";
+1 -1
packages/header-analysis/src/parser/cache-control.ts
··· 61 61 case "stale-if-error": 62 62 return "Allows a cache to serve stale responses if the origin server is unavailable or returns an error."; 63 63 default: 64 - return ""; 64 + return "-"; 65 65 } 66 66 }
+1 -1
packages/header-analysis/src/parser/cf-cache-status.ts
··· 21 21 case "DYNAMIC": 22 22 return "This resource is not cached by default and there are no explicit settings configured to cache it. You will see this frequently when Cloudflare is handling a POST request. This request will always go to the origin."; 23 23 default: 24 - return ""; 24 + return "-"; 25 25 } 26 26 }
+1 -1
packages/header-analysis/src/parser/x-vercel-cache.ts
··· 21 21 case "REVLIDATED": 22 22 return "The response was served from the origin server and the cache was refreshed due to an authorization from the user in the incoming request."; 23 23 default: 24 - return ""; 24 + return "-"; 25 25 } 26 26 }
+2 -2
packages/notifications/twillio-sms/src/index.ts
··· 20 20 const { name } = monitor; 21 21 22 22 const body = new FormData(); 23 - body.set("To", notificationData.phoneNumber); 23 + body.set("To", notificationData.sms); 24 24 body.set("From", "+14807252613"); 25 25 body.set( 26 26 "Body", ··· 67 67 const { name } = monitor; 68 68 69 69 const body = new FormData(); 70 - body.set("To", notificationData.phoneNumber); 70 + body.set("To", notificationData.sms); 71 71 body.set("From", "+14807252613"); 72 72 body.set("Body", `Your monitor ${name} / ${monitor.url} is up again`); 73 73
+1 -1
packages/notifications/twillio-sms/src/schema/config.ts
··· 2 2 import { z } from "zod"; 3 3 4 4 export const SmsConfigurationSchema = z.object({ 5 - phoneNumber: z.string().refine(isMobilephone), 5 + sms: z.string().refine(isMobilephone), 6 6 });