Skip to content

Commit 36e5c0b

Browse files
committed
Keep OpenAPI submit visible while checking specs
1 parent 4aed3f7 commit 36e5c0b

2 files changed

Lines changed: 46 additions & 10 deletions

File tree

packages/plugins/openapi/src/react/AddOpenApiSource.test.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, expect, it } from "@effect/vitest";
22

3-
import { baseUrlFromSpecInput } from "./AddOpenApiSource";
3+
import { baseUrlFromSpecInput, openApiPreviewFailureMessage } from "./AddOpenApiSource";
44

55
describe("baseUrlFromSpecInput", () => {
66
it("defaults URL-hosted specs to their origin", () => {
@@ -13,3 +13,17 @@ describe("baseUrlFromSpecInput", () => {
1313
expect(baseUrlFromSpecInput('{"openapi":"3.0.0"}')).toBe("");
1414
});
1515
});
16+
17+
describe("openApiPreviewFailureMessage", () => {
18+
it("uses the server message when one is available", () => {
19+
expect(openApiPreviewFailureMessage("bad yaml")).toBe(
20+
"Couldn't load or parse this spec: bad yaml",
21+
);
22+
});
23+
24+
it("falls back when the server message is blank", () => {
25+
expect(openApiPreviewFailureMessage("")).toBe(
26+
"Couldn't load or parse this spec: unknown error",
27+
);
28+
});
29+
});

packages/plugins/openapi/src/react/AddOpenApiSource.tsx

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)