@@ -73,6 +73,9 @@ export const baseUrlFromSpecInput = (input: string): string => {
7373 return parsed . origin ;
7474} ;
7575
76+ export const openApiPreviewFailureMessage = ( message : string | null | undefined ) : string =>
77+ `Couldn't load or parse this spec: ${ message && message . trim ( ) . length > 0 ? message : "unknown error" } ` ;
78+
7679// ---------------------------------------------------------------------------
7780// Component: single progressive form. Post-redesign: preview -> addSpec
7881// (register the integration catalog entry with ALL detected auth methods) →
@@ -289,7 +292,7 @@ export default function AddOpenApiSource(props: {
289292 return (
290293 < div className = "flex flex-1 flex-col gap-6" >
291294 < div >
292- < h1 className = "text-xl font-semibold text-foreground" > Add OpenAPI Integration </ h1 >
295+ < h1 className = "text-xl font-semibold text-foreground" > Add OpenAPI integration </ h1 >
293296 </ div >
294297
295298 { ! preview ? (
@@ -300,7 +303,10 @@ export default function AddOpenApiSource(props: {
300303 < div className = "relative" >
301304 < Textarea
302305 value = { specUrl }
303- onChange = { ( e ) => setSpecUrl ( ( e . target as HTMLTextAreaElement ) . value ) }
306+ onChange = { ( e ) => {
307+ setSpecUrl ( ( e . target as HTMLTextAreaElement ) . value ) ;
308+ setAnalyzeError ( null ) ;
309+ } }
304310 placeholder = "https://api.example.com/openapi.json"
305311 rows = { 3 }
306312 maxRows = { 10 }
@@ -315,6 +321,26 @@ export default function AddOpenApiSource(props: {
315321 < p className = "text-[11px] text-muted-foreground" >
316322 Paste a URL or raw JSON/YAML content.
317323 </ p >
324+ { analyzing && (
325+ < p className = "flex items-center gap-2 text-xs text-muted-foreground" >
326+ < IOSSpinner className = "size-3.5" />
327+ Checking spec…
328+ </ p >
329+ ) }
330+ { analyzeError && ! analyzing && (
331+ < div className = "flex flex-wrap items-center gap-2 text-xs text-destructive" >
332+ < span > { openApiPreviewFailureMessage ( analyzeError ) } </ span >
333+ < Button
334+ type = "button"
335+ variant = "ghost"
336+ size = "sm"
337+ className = "h-7 px-2"
338+ onClick = { ( ) => void handleAnalyze ( ) }
339+ >
340+ Retry
341+ </ Button >
342+ </ div >
343+ ) }
318344 </ div >
319345 </ CardStackContent >
320346 </ CardStack >
@@ -357,8 +383,6 @@ export default function AddOpenApiSource(props: {
357383 />
358384 ) : null }
359385
360- { analyzeError && < FormErrorAlert message = { analyzeError } /> }
361-
362386 { preview && (
363387 < AuthMethodListEditor
364388 list = { authMethodList }
@@ -375,11 +399,9 @@ export default function AddOpenApiSource(props: {
375399 < Button variant = "ghost" onClick = { ( ) => props . onCancel ( ) } disabled = { adding } >
376400 Cancel
377401 </ Button >
378- { preview && (
379- < Button onClick = { ( ) => void handleAdd ( ) } disabled = { ! canAdd } loading = { adding } >
380- Add integration
381- </ Button >
382- ) }
402+ < Button onClick = { ( ) => void handleAdd ( ) } disabled = { ! canAdd || analyzing } loading = { adding } >
403+ Add integration
404+ </ Button >
383405 </ FloatActions >
384406 </ div >
385407 ) ;
0 commit comments