@@ -12,7 +12,11 @@ import {
1212} from "@/components/forms/form-card" ;
1313import { useTRPC } from "@/lib/trpc/client" ;
1414import { zodResolver } from "@hookform/resolvers/zod" ;
15- import { InstatusIcon , StatuspageIcon } from "@openstatus/icons" ;
15+ import {
16+ BetterstackIcon ,
17+ InstatusIcon ,
18+ StatuspageIcon ,
19+ } from "@openstatus/icons" ;
1620import type { ImportSummary } from "@openstatus/importers/types" ;
1721import { Badge } from "@openstatus/ui/components/ui/badge" ;
1822import { Button } from "@openstatus/ui/components/ui/button" ;
@@ -40,10 +44,12 @@ import { toast } from "sonner";
4044import { z } from "zod" ;
4145
4246const schema = z . object ( {
43- provider : z . enum ( [ "statuspage" , "instatus" ] ) ,
47+ provider : z . enum ( [ "statuspage" , "betterstack" , " instatus"] ) ,
4448 apiKey : z . string ( ) . min ( 1 , "API key is required" ) ,
4549 statuspagePageId : z . string ( ) . optional ( ) ,
50+ betterstackStatusPageId : z . string ( ) . optional ( ) ,
4651 instatusPageId : z . string ( ) . optional ( ) ,
52+ includeMonitors : z . boolean ( ) ,
4753 includeStatusReports : z . boolean ( ) ,
4854 includeSubscribers : z . boolean ( ) ,
4955 includeComponents : z . boolean ( ) ,
@@ -56,7 +62,10 @@ function getPhaseCount(preview: ImportSummary, phase: string): number {
5662}
5763
5864const PHASE_LABELS : Record < string , string > = {
65+ monitors : "Monitors" ,
5966 componentGroups : "Component Groups" ,
67+ monitorGroups : "Monitor Groups" ,
68+ sections : "Sections" ,
6069 components : "Components" ,
6170 incidents : "Status Reports" ,
6271 maintenances : "Maintenances" ,
@@ -76,7 +85,9 @@ export function FormImport({
7685 provider : undefined ,
7786 apiKey : "" ,
7887 statuspagePageId : "" ,
88+ betterstackStatusPageId : "" ,
7989 instatusPageId : "" ,
90+ includeMonitors : true ,
8091 includeStatusReports : true ,
8192 includeSubscribers : false ,
8293 includeComponents : true ,
@@ -87,6 +98,7 @@ export function FormImport({
8798 const watchProvider = form . watch ( "provider" ) ;
8899 const watchApiKey = form . watch ( "apiKey" ) ;
89100 const watchStatuspagePageId = form . watch ( "statuspagePageId" ) ;
101+ const watchBetterstackStatusPageId = form . watch ( "betterstackStatusPageId" ) ;
90102 const watchInstatusPageId = form . watch ( "instatusPageId" ) ;
91103
92104 const previewMutation = useMutation (
@@ -114,6 +126,10 @@ export function FormImport({
114126 watchProvider === "statuspage"
115127 ? watchStatuspagePageId || undefined
116128 : undefined ,
129+ betterstackStatusPageId :
130+ watchProvider === "betterstack"
131+ ? watchBetterstackStatusPageId || undefined
132+ : undefined ,
117133 instatusPageId :
118134 watchProvider === "instatus"
119135 ? watchInstatusPageId || undefined
@@ -188,6 +204,21 @@ export function FormImport({
188204 Atlassian Statuspage
189205 </ FormLabel >
190206 </ FormItem >
207+ < FormItem className = "relative flex cursor-pointer flex-row items-center gap-3 rounded-md border border-input px-2 py-3 text-center shadow-xs outline-none transition-[color,box-shadow] has-data-[state=checked]:border-primary/50 has-focus-visible:border-ring has-focus-visible:ring-[3px] has-focus-visible:ring-ring/50" >
208+ < FormControl >
209+ < RadioGroupItem
210+ value = "betterstack"
211+ className = "sr-only"
212+ />
213+ </ FormControl >
214+ < BetterstackIcon
215+ className = "size-4 shrink-0 text-foreground"
216+ aria-hidden = "true"
217+ />
218+ < FormLabel className = "cursor-pointer font-medium text-foreground text-xs leading-none after:absolute after:inset-0" >
219+ Better Stack
220+ </ FormLabel >
221+ </ FormItem >
191222 < FormItem className = "relative flex cursor-pointer flex-row items-center gap-3 rounded-md border border-input px-2 py-3 text-center shadow-xs outline-none transition-[color,box-shadow] has-data-[state=checked]:border-primary/50 has-focus-visible:border-ring has-focus-visible:ring-[3px] has-focus-visible:ring-ring/50" >
192223 < FormControl >
193224 < RadioGroupItem
@@ -228,18 +259,22 @@ export function FormImport({
228259 < Input
229260 type = "password"
230261 placeholder = {
231- watchProvider === "instatus"
232- ? "Bearer API key"
233- : "OAuth API key"
262+ watchProvider === "betterstack"
263+ ? "Bearer token"
264+ : watchProvider === "instatus"
265+ ? "Bearer API key"
266+ : "OAuth API key"
234267 }
235268 { ...field }
236269 />
237270 </ FormControl >
238271 < FormMessage />
239272 < FormDescription >
240- { watchProvider === "instatus"
241- ? "Your Instatus API key. Found in your Instatus account under Settings > API."
242- : "Your Statuspage API key. Found in your Statuspage account under Manage Account > API." }
273+ { watchProvider === "betterstack"
274+ ? "Your Better Stack API token. Found in Better Stack \u2192 API tokens."
275+ : watchProvider === "instatus"
276+ ? "Your Instatus API key. Found in your Instatus account under Settings > API."
277+ : "Your Statuspage API key. Found in your Statuspage account under Manage Account > API." }
243278 </ FormDescription >
244279 </ FormItem >
245280 ) }
@@ -262,6 +297,24 @@ export function FormImport({
262297 ) }
263298 />
264299 ) : null }
300+ { watchProvider === "betterstack" ? (
301+ < FormField
302+ control = { form . control }
303+ name = "betterstackStatusPageId"
304+ render = { ( { field } ) => (
305+ < FormItem >
306+ < FormLabel > Status Page ID (optional)</ FormLabel >
307+ < FormControl >
308+ < Input placeholder = "e.g. 123456789" { ...field } />
309+ </ FormControl >
310+ < FormDescription >
311+ Import a specific status page. Leave empty to use the
312+ first available.
313+ </ FormDescription >
314+ </ FormItem >
315+ ) }
316+ />
317+ ) : null }
265318 { watchProvider === "instatus" ? (
266319 < FormField
267320 control = { form . control }
@@ -319,6 +372,29 @@ export function FormImport({
319372 </ p >
320373 </ Note >
321374 ) : null }
375+ { watchProvider === "betterstack" ? (
376+ < FormField
377+ control = { form . control }
378+ name = "includeMonitors"
379+ render = { ( { field } ) => (
380+ < FormItem className = "flex flex-row items-center justify-between" >
381+ < div className = "space-y-0.5" >
382+ < FormLabel > Monitors</ FormLabel >
383+ < FormDescription >
384+ Import monitors with their URL, frequency, and
385+ regions.
386+ </ FormDescription >
387+ </ div >
388+ < FormControl >
389+ < Switch
390+ checked = { field . value }
391+ onCheckedChange = { field . onChange }
392+ />
393+ </ FormControl >
394+ </ FormItem >
395+ ) }
396+ />
397+ ) : null }
322398 < FormField
323399 control = { form . control }
324400 name = "includeStatusReports"
@@ -360,26 +436,28 @@ export function FormImport({
360436 </ FormItem >
361437 ) }
362438 />
363- < FormField
364- control = { form . control }
365- name = "includeSubscribers"
366- render = { ( { field } ) => (
367- < FormItem className = "flex flex-row items-center justify-between" >
368- < div className = "space-y-0.5" >
369- < FormLabel > Subscribers</ FormLabel >
370- < FormDescription >
371- Import email subscribers.
372- </ FormDescription >
373- </ div >
374- < FormControl >
375- < Switch
376- checked = { field . value }
377- onCheckedChange = { field . onChange }
378- />
379- </ FormControl >
380- </ FormItem >
381- ) }
382- />
439+ { watchProvider !== "betterstack" ? (
440+ < FormField
441+ control = { form . control }
442+ name = "includeSubscribers"
443+ render = { ( { field } ) => (
444+ < FormItem className = "flex flex-row items-center justify-between" >
445+ < div className = "space-y-0.5" >
446+ < FormLabel > Subscribers</ FormLabel >
447+ < FormDescription >
448+ Import email subscribers.
449+ </ FormDescription >
450+ </ div >
451+ < FormControl >
452+ < Switch
453+ checked = { field . value }
454+ onCheckedChange = { field . onChange }
455+ />
456+ </ FormControl >
457+ </ FormItem >
458+ ) }
459+ />
460+ ) : null }
383461 </ FormCardContent >
384462 </ >
385463 ) : null }
0 commit comments