Showing the changes to plugins/openapi (2 of 17 files). Show all
Unified · Split
| @@ -15,7 +15,6 @@ import { · 14 unmodified lines | ||
| 15 | 15 | import { |
| 16 | 16 | Alert, |
| 17 | 17 | Button, |
| 18 | − Card, | |
| 19 | 18 | DocumentPanel, |
| 20 | 19 | IconPencil, |
| 21 | 20 | Input, |
| @@ -149,7 +148,7 @@ const Section = (props: { · 127 unmodified lines | ||
| 149 | 148 | children: ReactNode; |
| 150 | 149 | }) => ( |
| 151 | 150 | <section> |
| 152 | − <h2 className="mb-3 text-sm font-semibold text-foreground">{props.title}</h2> | |
| 151 | + <h2 className="mb-3 text-xs font-semibold uppercase tracking-wider text-muted-foreground">{props.title}</h2> | |
| 153 | 152 | {props.children} |
| 154 | 153 | </section> |
| 155 | 154 | ); |
| @@ -387,7 +386,7 @@ function OpenApiSourceForm(props: { · 231 unmodified lines | ||
| 387 | 386 | }; |
| 388 | 387 | |
| 389 | 388 | return ( |
| 390 | − <Card className="space-y-6 p-6"> | |
| 389 | + <div className="space-y-6 rounded-lg border border-border bg-card p-6 text-sm ring-1 ring-foreground/[0.04]"> | |
| 391 | 390 | <Section title="Connection"> |
| 392 | 391 | <div className="grid gap-4"> |
| 393 | 392 | <div className="grid gap-2"> |
| @@ -477,59 +476,47 @@ function OpenApiSourceForm(props: { · 83 unmodified lines | ||
| 477 | 476 | </div> |
| 478 | 477 | </Section> |
| 479 | 478 | |
| 480 | − <Section title="Preview"> | |
| 481 | − <div className="flex items-center gap-3"> | |
| 482 | − <Button | |
| 483 | − variant="outline" | |
| 484 | − type="button" | |
| 485 | − onClick={() => { | |
| 486 | − void runPreview({ mode: "manual" }); | |
| 487 | − }} | |
| 488 | − disabled={previewMutation.status === "pending" || submitMutation.status === "pending"} | |
| 489 | − > | |
| 490 | − {previewMutation.status === "pending" ? "Previewing..." : "Preview Spec"} | |
| 491 | − </Button> | |
| 492 | − {preview && ( | |
| 493 | − <div className="text-xs text-muted-foreground"> | |
| 494 | − {preview.operationCount} operations | |
| 495 | − {preview.version ? ` · v${preview.version}` : ""} | |
| 479 | + {(preview || previewMutation.status === "pending") && ( | |
| 480 | + <Section title="Preview"> | |
| 481 | + {previewMutation.status === "pending" ? ( | |
| 482 | + <div className="text-xs text-muted-foreground">Loading preview...</div> | |
| 483 | + ) : preview && ( | |
| 484 | + <div className="rounded-lg border border-border bg-muted/30 px-4 py-3 text-sm"> | |
| 485 | + <dl className="grid grid-cols-[auto_1fr] gap-x-4 gap-y-1.5 text-xs"> | |
| 486 | + <dt className="font-medium text-foreground">Title</dt> | |
| 487 | + <dd className="text-muted-foreground">{preview.title ?? "—"}</dd> | |
| 488 | + <dt className="font-medium text-foreground">Version</dt> | |
| 489 | + <dd className="text-muted-foreground">{preview.version ?? "—"}</dd> | |
| 490 | + <dt className="font-medium text-foreground">Operations</dt> | |
| 491 | + <dd className="text-muted-foreground">{preview.operationCount}</dd> | |
| 492 | + <dt className="font-medium text-foreground">Base URL</dt> | |
| 493 | + <dd className="font-mono text-muted-foreground">{preview.baseUrl ?? "—"}</dd> | |
| 494 | + {preview.namespace && ( | |
| 495 | + <> | |
| 496 | + <dt className="font-medium text-foreground">Namespace</dt> | |
| 497 | + <dd className="text-muted-foreground">{preview.namespace}</dd> | |
| 498 | + </> | |
| 499 | + )} | |
| 500 | + {preview.securitySchemes.length > 0 && ( | |
| 501 | + <> | |
| 502 | + <dt className="font-medium text-foreground">Auth</dt> | |
| 503 | + <dd className="text-muted-foreground"> | |
| 504 | + {preview.securitySchemes | |
| 505 | + .map((scheme) => `${scheme.name} (${previewSecuritySchemeLabel(scheme)})`) | |
| 506 | + .join(", ")} | |
| 507 | + </dd> | |
| 508 | + </> | |
| 509 | + )} | |
| 510 | + </dl> | |
| 511 | + {preview.warnings.length > 0 && ( | |
| 512 | + <Alert variant="warning" className="mt-3 text-xs"> | |
| 513 | + {preview.warnings.join(" ")} | |
| 514 | + </Alert> | |
| 515 | + )} | |
| 496 | 516 | </div> |
| 497 | 517 | )} |
| 498 | − </div> | |
| 499 | − {preview && ( | |
| 500 | − <div className="mt-3 rounded-lg border border-border bg-muted/30 px-4 py-3 text-sm"> | |
| 501 | − <dl className="grid grid-cols-[auto_1fr] gap-x-4 gap-y-1.5 text-xs"> | |
| 502 | − <dt className="font-medium text-foreground">Title</dt> | |
| 503 | − <dd className="text-muted-foreground">{preview.title ?? "—"}</dd> | |
| 504 | − <dt className="font-medium text-foreground">Version</dt> | |
| 505 | − <dd className="text-muted-foreground">{preview.version ?? "—"}</dd> | |
| 506 | − <dt className="font-medium text-foreground">Base URL</dt> | |
| 507 | − <dd className="font-mono text-muted-foreground">{preview.baseUrl ?? "—"}</dd> | |
| 508 | − {preview.namespace && ( | |
| 509 | − <> | |
| 510 | − <dt className="font-medium text-foreground">Namespace</dt> | |
| 511 | − <dd className="text-muted-foreground">{preview.namespace}</dd> | |
| 512 | − </> | |
| 513 | − )} | |
| 514 | − {preview.securitySchemes.length > 0 && ( | |
| 515 | − <> | |
| 516 | − <dt className="font-medium text-foreground">Auth</dt> | |
| 517 | − <dd className="text-muted-foreground"> | |
| 518 | − {preview.securitySchemes | |
| 519 | − .map((scheme) => `${scheme.name} (${previewSecuritySchemeLabel(scheme)})`) | |
| 520 | − .join(", ")} | |
| 521 | − </dd> | |
| 522 | − </> | |
| 523 | − )} | |
| 524 | − </dl> | |
| 525 | − {preview.warnings.length > 0 && ( | |
| 526 | − <Alert variant="warning" className="mt-3 text-xs"> | |
| 527 | − {preview.warnings.join(" ")} | |
| 528 | − </Alert> | |
| 529 | − )} | |
| 530 | − </div> | |
| 531 | − )} | |
| 532 | − </Section> | |
| 518 | + </Section> | |
| 519 | + )} | |
| 533 | 520 | |
| 534 | 521 | {error && ( |
| 535 | 522 | <Alert variant="destructive"> |
| @@ -548,7 +535,7 @@ function OpenApiSourceForm(props: { · 12 unmodified lines | ||
| 548 | 535 | {submitMutation.status === "pending" ? props.busyLabel : props.submitLabel} |
| 549 | 536 | </Button> |
| 550 | 537 | </div> |
| 551 | − </Card> | |
| 538 | + </div> | |
| 552 | 539 | ); |
| 553 | 540 | } |
| 554 | 541 | |
| @@ -564,35 +551,50 @@ export function OpenApiAddSourcePage() { · 9 unmodified lines | ||
| 564 | 551 | |
| 565 | 552 | if (!workspace.enabled) { |
| 566 | 553 | return ( |
| 567 | − <Section title="Add Source"> | |
| 568 | − <div className="text-sm text-muted-foreground">Loading workspace...</div> | |
| 569 | − </Section> | |
| 554 | + <div className="min-h-0 flex-1 overflow-y-auto"> | |
| 555 | + <div className="mx-auto w-full max-w-3xl px-6 py-10"> | |
| 556 | + <div className="text-sm text-muted-foreground">Loading workspace...</div> | |
| 557 | + </div> | |
| 558 | + </div> | |
| 570 | 559 | ); |
| 571 | 560 | } |
| 572 | 561 | |
| 573 | 562 | return ( |
| 574 | − <OpenApiSourceForm | |
| 575 | − mode="create" | |
| 576 | − workspaceId={workspace.workspaceId} | |
| 577 | − initialValue={initialValue} | |
| 578 | − submitLabel="Create Source" | |
| 579 | − busyLabel="Creating..." | |
| 580 | − onSubmit={async (payload) => { | |
| 581 | − const source = await createSource({ | |
| 582 | − path: { workspaceId: workspace.workspaceId }, | |
| 583 | − payload, | |
| 584 | − reactivityKeys: { | |
| 585 | − sources: [workspace.workspaceId], | |
| 586 | − }, | |
| 587 | − }); | |
| 588 | − | |
| 589 | − startTransition(() => { | |
| 590 | − void navigation.detail(source.id, { | |
| 591 | − tab: "model", | |
| 592 | − }); | |
| 593 | − }); | |
| 594 | − }} | |
| 595 | − /> | |
| 563 | + <div className="min-h-0 flex-1 overflow-y-auto"> | |
| 564 | + <div className="mx-auto w-full max-w-3xl px-6 py-10"> | |
| 565 | + <div className="mb-8"> | |
| 566 | + <h1 className="font-display text-2xl tracking-tight text-foreground"> | |
| 567 | + Add OpenAPI Source | |
| 568 | + </h1> | |
| 569 | + <p className="mt-1.5 text-sm leading-6 text-muted-foreground"> | |
| 570 | + Import operations from an OpenAPI specification as callable tools. | |
| 571 | + </p> | |
| 572 | + </div> | |
| 573 | + | |
| 574 | + <OpenApiSourceForm | |
| 575 | + mode="create" | |
| 576 | + workspaceId={workspace.workspaceId} | |
| 577 | + initialValue={initialValue} | |
| 578 | + submitLabel="Create Source" | |
| 579 | + busyLabel="Creating..." | |
| 580 | + onSubmit={async (payload) => { | |
| 581 | + const source = await createSource({ | |
| 582 | + path: { workspaceId: workspace.workspaceId }, | |
| 583 | + payload, | |
| 584 | + reactivityKeys: { | |
| 585 | + sources: [workspace.workspaceId], | |
| 586 | + }, | |
| 587 | + }); | |
| 588 | + | |
| 589 | + startTransition(() => { | |
| 590 | + void navigation.detail(source.id, { | |
| 591 | + tab: "model", | |
| 592 | + }); | |
| 593 | + }); | |
| 594 | + }} | |
| 595 | + /> | |
| 596 | + </div> | |
| 597 | + </div> | |
| 596 | 598 | ); |
| 597 | 599 | } |
| 598 | 600 | |
| @@ -603,9 +605,11 @@ export function OpenApiEditSourcePage(props: { · 4 unmodified lines | ||
| 603 | 605 | |
| 604 | 606 | if (!workspace.enabled) { |
| 605 | 607 | return ( |
| 606 | − <Section title="Edit Source"> | |
| 607 | − <div className="text-sm text-muted-foreground">Loading workspace...</div> | |
| 608 | − </Section> | |
| 608 | + <div className="min-h-0 flex-1 overflow-y-auto"> | |
| 609 | + <div className="mx-auto w-full max-w-3xl px-6 py-10"> | |
| 610 | + <div className="text-sm text-muted-foreground">Loading workspace...</div> | |
| 611 | + </div> | |
| 612 | + </div> | |
| 609 | 613 | ); |
| 610 | 614 | } |
| 611 | 615 | |
| @@ -641,53 +645,64 @@ function OpenApiEditSourcePageReady(props: { · 29 unmodified lines | ||
| 641 | 645 | ); |
| 642 | 646 | |
| 643 | 647 | if (!Result.isSuccess(configResult)) { |
| 644 | − if (Result.isFailure(configResult)) { | |
| 645 | − return ( | |
| 646 | − <Section title="Edit Source"> | |
| 647 | − <Alert variant="destructive"> | |
| 648 | − Failed loading source configuration. | |
| 649 | − </Alert> | |
| 650 | − </Section> | |
| 651 | − ); | |
| 652 | − } | |
| 653 | − | |
| 654 | 648 | return ( |
| 655 | − <Section title="Edit Source"> | |
| 656 | − <div className="text-sm text-muted-foreground">Loading configuration...</div> | |
| 657 | − </Section> | |
| 649 | + <div className="min-h-0 flex-1 overflow-y-auto"> | |
| 650 | + <div className="mx-auto w-full max-w-3xl px-6 py-10"> | |
| 651 | + {Result.isFailure(configResult) ? ( | |
| 652 | + <Alert variant="destructive"> | |
| 653 | + Failed loading source configuration. | |
| 654 | + </Alert> | |
| 655 | + ) : ( | |
| 656 | + <div className="text-sm text-muted-foreground">Loading configuration...</div> | |
| 657 | + )} | |
| 658 | + </div> | |
| 659 | + </div> | |
| 658 | 660 | ); |
| 659 | 661 | } |
| 660 | 662 | |
| 661 | 663 | return ( |
| 662 | − <OpenApiSourceForm | |
| 663 | − mode="edit" | |
| 664 | − workspaceId={props.workspaceId} | |
| 665 | − initialValue={inputFromConfig(configResult.value)} | |
| 666 | − submitLabel="Save Changes" | |
| 667 | − busyLabel="Saving..." | |
| 668 | − onSubmit={async (config) => { | |
| 669 | − const source = await updateSource({ | |
| 670 | − path: { | |
| 671 | − workspaceId: props.workspaceId, | |
| 672 | − sourceId: props.source.id, | |
| 673 | − }, | |
| 674 | − payload: config, | |
| 675 | − reactivityKeys: { | |
| 676 | − sources: [props.workspaceId], | |
| 677 | − source: [props.workspaceId, props.source.id], | |
| 678 | − sourceInspection: [props.workspaceId, props.source.id], | |
| 679 | − sourceInspectionTool: [props.workspaceId, props.source.id], | |
| 680 | − sourceDiscovery: [props.workspaceId, props.source.id], | |
| 681 | − }, | |
| 682 | − }); | |
| 683 | − | |
| 684 | − startTransition(() => { | |
| 685 | − void navigation.detail(source.id, { | |
| 686 | − tab: "model", | |
| 687 | − }); | |
| 688 | − }); | |
| 689 | − }} | |
| 690 | − /> | |
| 664 | + <div className="min-h-0 flex-1 overflow-y-auto"> | |
| 665 | + <div className="mx-auto w-full max-w-3xl px-6 py-10"> | |
| 666 | + <div className="mb-8"> | |
| 667 | + <h1 className="font-display text-2xl tracking-tight text-foreground"> | |
| 668 | + Edit OpenAPI Source | |
| 669 | + </h1> | |
| 670 | + <p className="mt-1.5 text-sm leading-6 text-muted-foreground"> | |
| 671 | + Update the connection settings for {props.source.name}. | |
| 672 | + </p> | |
| 673 | + </div> | |
| 674 | + | |
| 675 | + <OpenApiSourceForm | |
| 676 | + mode="edit" | |
| 677 | + workspaceId={props.workspaceId} | |
| 678 | + initialValue={inputFromConfig(configResult.value)} | |
| 679 | + submitLabel="Save Changes" | |
| 680 | + busyLabel="Saving..." | |
| 681 | + onSubmit={async (config) => { | |
| 682 | + const source = await updateSource({ | |
| 683 | + path: { | |
| 684 | + workspaceId: props.workspaceId, | |
| 685 | + sourceId: props.source.id, | |
| 686 | + }, | |
| 687 | + payload: config, | |
| 688 | + reactivityKeys: { | |
| 689 | + sources: [props.workspaceId], | |
| 690 | + source: [props.workspaceId, props.source.id], | |
| 691 | + sourceInspection: [props.workspaceId, props.source.id], | |
| 692 | + sourceInspectionTool: [props.workspaceId, props.source.id], | |
| 693 | + sourceDiscovery: [props.workspaceId, props.source.id], | |
| 694 | + }, | |
| 695 | + }); | |
| 696 | + | |
| 697 | + startTransition(() => { | |
| 698 | + void navigation.detail(source.id, { | |
| 699 | + tab: "model", | |
| 700 | + }); | |
| 701 | + }); | |
| 702 | + }} | |
| 703 | + /> | |
| 704 | + </div> | |
| 705 | + </div> | |
| 691 | 706 | ); |
| 692 | 707 | } |
| 693 | 708 | |
| @@ -1,4 +1,7 @@ | ||
| 1 | −import { defineExecutorFrontendPlugin } from "@executor/react/plugins"; | |
| 1 | +import { | |
| 2 | + defineExecutorFrontendPlugin, | |
| 3 | + liveFrontendPluginComponent, | |
| 4 | +} from "@executor/react/plugins"; | |
| 2 | 5 | |
| 3 | 6 | import { |
| 4 | 7 | OpenApiAddSourcePage, |
| @@ -13,17 +16,17 @@ export const OpenApiReactPlugin = defineExecutorFrontendPlugin({ · 8 unmodified lines | ||
| 13 | 16 | { |
| 14 | 17 | key: "add", |
| 15 | 18 | path: "add", |
| 16 | − component: OpenApiAddSourcePage, | |
| 19 | + component: liveFrontendPluginComponent(() => OpenApiAddSourcePage), | |
| 17 | 20 | }, |
| 18 | 21 | { |
| 19 | 22 | key: "detail", |
| 20 | 23 | path: "sources/$sourceId", |
| 21 | − component: OpenApiDetailRoute, | |
| 24 | + component: liveFrontendPluginComponent(() => OpenApiDetailRoute), | |
| 22 | 25 | }, |
| 23 | 26 | { |
| 24 | 27 | key: "edit", |
| 25 | 28 | path: "sources/$sourceId/edit", |
| 26 | − component: OpenApiEditRoute, | |
| 29 | + component: liveFrontendPluginComponent(() => OpenApiEditRoute), | |
| 27 | 30 | }, |
| 28 | 31 | ], |
| 29 | 32 | }); |