Show the provider credential form inline under the selected provider
This commit is contained in:
1 parent
b9fa049494
commit
5388165016
2 files changed
+49
-21
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
import { useMemo, useState, type FormEvent } from "react";
|
import { Fragment, useMemo, useState, type FormEvent } from "react";
|
||||||
import {
|
import {
|
||||||
PROVIDER_AUTH_TYPE,
|
PROVIDER_AUTH_TYPE,
|
||||||
type AppSnapshot,
|
type AppSnapshot,
|
||||||
@@ -249,8 +249,6 @@ function ProviderStep({
|
|||||||
}) {
|
}) {
|
||||||
const selected = providers.find((entry) => entry.key === draft.providerKey) ?? providers[0];
|
const selected = providers.find((entry) => entry.key === draft.providerKey) ?? providers[0];
|
||||||
if (!selected) throw new Error("No provider available for onboarding.");
|
if (!selected) throw new Error("No provider available for onboarding.");
|
||||||
const isOAuthLike = selected.authType === "oauth_pkce" || selected.authType === "account_subscription";
|
|
||||||
const isCustom = Boolean(selected.customEndpoint);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="form-grid">
|
<div className="form-grid">
|
||||||
@@ -260,25 +258,47 @@ function ProviderStep({
|
|||||||
</p>
|
</p>
|
||||||
<div className="option-grid">
|
<div className="option-grid">
|
||||||
{providers.map((provider) => (
|
{providers.map((provider) => (
|
||||||
<button
|
<Fragment key={provider.key}>
|
||||||
key={provider.key}
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`option-card ${draft.providerKey === provider.key ? "active" : ""}`.trim()}
|
className={`option-card ${draft.providerKey === provider.key ? "active" : ""}`.trim()}
|
||||||
onClick={() => onChange({
|
onClick={() => onChange({
|
||||||
providerKey: provider.key,
|
providerKey: provider.key,
|
||||||
providerModel: provider.defaultModel ?? provider.models[0]?.id ?? "",
|
providerModel: provider.defaultModel ?? provider.models[0]?.id ?? "",
|
||||||
providerSecret: "",
|
providerSecret: "",
|
||||||
providerBaseUrl: "",
|
providerBaseUrl: "",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="opt-title" style={{ flex: 1 }}>{provider.label}</div>
|
<div className="opt-title" style={{ flex: 1 }}>{provider.label}</div>
|
||||||
<Pill tone="violet">{authBadge(provider.authType)}</Pill>
|
<Pill tone="violet">{authBadge(provider.authType)}</Pill>
|
||||||
</div>
|
</div>
|
||||||
<div className="opt-sub">{provider.capabilityTags.join(" · ") || authBadge(provider.authType)}</div>
|
<div className="opt-sub">{provider.capabilityTags.join(" · ") || authBadge(provider.authType)}</div>
|
||||||
</button>
|
</button>
|
||||||
|
{provider.key === selected.key && (
|
||||||
|
<ProviderCredentialFields selected={selected} draft={draft} onChange={onChange} />
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
<Actions onBack={onBack} onNext={onNext} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ProviderCredentialFields({
|
||||||
|
selected,
|
||||||
|
draft,
|
||||||
|
onChange,
|
||||||
|
}: {
|
||||||
|
selected: ProviderCatalogEntry;
|
||||||
|
draft: Draft;
|
||||||
|
onChange: (patch: Partial<Draft>) => void;
|
||||||
|
}) {
|
||||||
|
const isOAuthLike = selected.authType === "oauth_pkce" || selected.authType === "account_subscription";
|
||||||
|
const isCustom = Boolean(selected.customEndpoint);
|
||||||
|
return (
|
||||||
|
<div className="provider-inline-form">
|
||||||
{selected.credentialHelp && (
|
{selected.credentialHelp && (
|
||||||
<div style={{ fontSize: 12.5, color: "var(--text-3)", lineHeight: 1.5 }}>{selected.credentialHelp}</div>
|
<div style={{ fontSize: 12.5, color: "var(--text-3)", lineHeight: 1.5 }}>{selected.credentialHelp}</div>
|
||||||
)}
|
)}
|
||||||
@@ -336,7 +356,6 @@ function ProviderStep({
|
|||||||
<input className="input" value={draft.providerModel} onChange={(event) => onChange({ providerModel: event.target.value })} />
|
<input className="input" value={draft.providerModel} onChange={(event) => onChange({ providerModel: event.target.value })} />
|
||||||
)}
|
)}
|
||||||
</Field>
|
</Field>
|
||||||
<Actions onBack={onBack} onNext={onNext} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,15 @@
|
|||||||
.option-card.active { border-color: var(--text-1); box-shadow: inset 0 0 0 1px var(--text-1); }
|
.option-card.active { border-color: var(--text-1); box-shadow: inset 0 0 0 1px var(--text-1); }
|
||||||
.option-card .opt-title { font-size: 13.5px; font-weight: 540; }
|
.option-card .opt-title { font-size: 13.5px; font-weight: 540; }
|
||||||
.option-card .opt-sub { font-size: 12px; color: var(--text-3); margin-top: 4px; }
|
.option-card .opt-sub { font-size: 12px; color: var(--text-3); margin-top: 4px; }
|
||||||
|
.provider-inline-form {
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 14px 16px 16px;
|
||||||
|
margin: 2px 0 6px 12px;
|
||||||
|
border-left: 2px solid var(--text-1);
|
||||||
|
border-radius: 0 var(--r-sm) var(--r-sm) 0;
|
||||||
|
background: var(--panel-2);
|
||||||
|
}
|
||||||
|
|
||||||
.popover-anchor { position: relative; display: inline-flex; }
|
.popover-anchor { position: relative; display: inline-flex; }
|
||||||
.popover-panel {
|
.popover-panel {
|
||||||
|
|||||||
Reference in new issue
Block a user