Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 102 additions & 138 deletions apps/web/src/components/settings/ProviderInstanceCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,11 @@ export function ProviderInstanceCard({
compatibility.status !== "supported" &&
compatibility.status !== "unknown";
const VersionAdvisoryIcon = hasCompatibilityWarning ? AlertTriangleIcon : ArrowUpCircleIcon;
const onRunVersionAction = versionAdvisory?.targetVersion ? onInstallRecommended : onRunUpdate;
const onRunVersionAction = readOnly
? undefined
: versionAdvisory?.targetVersion
? onInstallRecommended
: onRunUpdate;
const urlAuthAction = liveProvider?.auth.action;
const displayName =
instance.displayName?.trim() || driverOption?.label || String(instance.driver);
Expand Down Expand Up @@ -765,6 +769,101 @@ export function ProviderInstanceCard({
) : null}
</>
);
const versionAdvisoryNode = versionAdvisory ? (
<Popover>
<Tooltip>
<TooltipTrigger
render={
<PopoverTrigger
render={
<Button
type="button"
size={mode === "list" ? "icon-micro" : "icon-xs"}
variant="ghost-muted"
className={mode === "list" ? "pointer-events-auto relative shrink-0" : undefined}
aria-label={`${versionAdvisory.title} — view details`}
>
<VersionAdvisoryIcon
className={cn(
mode === "list" && "size-3.5",
hasCompatibilityWarning && "text-warning",
)}
/>
</Button>
}
/>
}
/>
<TooltipPopup side="top">{versionAdvisory.title}</TooltipPopup>
</Tooltip>
<PopoverPopup side="bottom" align="end" width="md" aria-label={versionAdvisory.title}>
<div className="grid min-w-0 gap-3">
<div className="grid gap-0.5">
<p className="text-sm font-semibold leading-tight text-foreground">
{versionAdvisory.title}
</p>
<p
className={cn(
"text-xs leading-snug",
versionAdvisory.emphasis === "strong" ? "text-warning" : "text-muted-foreground",
)}
>
{versionAdvisory.detail}
</p>
</div>
{onRunVersionAction ? (
<Button
type="button"
size="xs"
variant="outline"
className="w-full"
disabled={isUpdating}
onClick={onRunVersionAction}
>
{isUpdating ? <Spinner /> : <DownloadIcon />}
{isUpdating
? "Updating"
: versionAdvisory.targetVersion
? `Install ${getProviderVersionLabel(versionAdvisory.targetVersion)}`
: "Update now"}
</Button>
) : null}
{onRunVersionAction && updateCommand ? (
<div className="flex items-center gap-2 text-3xs font-medium uppercase tracking-wider text-muted-foreground">
<span aria-hidden className="h-px flex-1 bg-border" />
or, update manually using
<span aria-hidden className="h-px flex-1 bg-border" />
</div>
) : null}
{updateCommand ? (
<div className="flex min-w-0 items-center gap-1 rounded-md border border-border/70 bg-muted/40 py-0.5 pr-0.5 pl-2">
<code className="min-w-0 flex-1 truncate font-mono text-2xs text-foreground">
{updateCommand}
</code>
<Tooltip>
<TooltipTrigger
render={
<Button
type="button"
size="icon-xs"
variant="ghost-muted"
className="shrink-0"
onClick={() => copyToClipboard(updateCommand, { providerName: displayName })}
aria-label="Copy update command"
>
<CopyIcon className="size-3" />
</Button>
}
/>
<TooltipPopup side="top">Copy command</TooltipPopup>
</Tooltip>
</div>
) : null}
</div>
</PopoverPopup>
</Popover>
) : null;

if (mode === "list") {
return (
<div
Expand Down Expand Up @@ -796,49 +895,7 @@ export function ProviderInstanceCard({
{versionLabel}
</code>
) : null}
{versionAdvisory ? (
hasCompatibilityWarning ? (
<Tooltip>
<TooltipTrigger
render={
<span
tabIndex={0}
role="img"
aria-label={versionAdvisory.title}
className="pointer-events-auto relative inline-flex shrink-0 text-warning"
>
<VersionAdvisoryIcon className="size-3.5" />
</span>
}
/>
<TooltipPopup side="top">{versionAdvisory.detail}</TooltipPopup>
</Tooltip>
) : updateCommand ? (
<Tooltip>
<TooltipTrigger
render={
<Button
type="button"
size="icon-micro"
variant="ghost-muted"
className="pointer-events-auto relative shrink-0"
aria-label={`Copy ${displayName} update command`}
onClick={() =>
copyToClipboard(updateCommand, { providerName: displayName })
}
>
<ArrowUpCircleIcon className="size-3.5" />
</Button>
}
/>
<TooltipPopup side="top">Copy update command</TooltipPopup>
</Tooltip>
) : (
<span role="img" aria-label="Update available" className="inline-flex shrink-0">
<ArrowUpCircleIcon className="size-3.5 text-muted-foreground" />
</span>
)
) : null}
{versionAdvisoryNode}
</span>
<span className="mt-0.5 flex items-start gap-1.5 text-xs leading-normal text-muted-foreground/80">
{statusDotNode ? (
Expand Down Expand Up @@ -876,105 +933,12 @@ export function ProviderInstanceCard({
</Badge>
) : null}
{versionCodeNode}
{versionAdvisoryNode}
<span
inert={readOnly}
aria-disabled={readOnly || undefined}
className={cn("inline-flex items-center gap-1", readOnly && "opacity-50")}
>
{versionAdvisory ? (
<Popover>
<Tooltip>
<TooltipTrigger
render={
<PopoverTrigger
render={
<Button
type="button"
size="icon-xs"
variant="ghost-muted"
aria-label={`${versionAdvisory.title} — view details`}
>
<VersionAdvisoryIcon
className={cn(hasCompatibilityWarning && "text-warning")}
/>
</Button>
}
/>
}
/>
<TooltipPopup side="top">{versionAdvisory.title}</TooltipPopup>
</Tooltip>
<PopoverPopup side="bottom" align="end" width="md">
<div className="grid min-w-0 gap-3">
<div className="grid gap-0.5">
<p className="text-sm font-semibold leading-tight text-foreground">
{versionAdvisory.title}
</p>
<p
className={cn(
"text-xs leading-snug",
versionAdvisory.emphasis === "strong"
? "text-warning"
: "text-muted-foreground",
)}
>
{versionAdvisory.detail}
</p>
</div>
{onRunVersionAction ? (
<Button
type="button"
size="xs"
variant="outline"
className="w-full"
disabled={isUpdating}
onClick={onRunVersionAction}
>
{isUpdating ? <Spinner /> : <DownloadIcon />}
{isUpdating
? "Updating"
: versionAdvisory.targetVersion
? `Install ${getProviderVersionLabel(versionAdvisory.targetVersion)}`
: "Update now"}
</Button>
) : null}
{onRunVersionAction && updateCommand ? (
<div className="flex items-center gap-2 text-3xs font-medium uppercase tracking-wider text-muted-foreground">
<span aria-hidden className="h-px flex-1 bg-border" />
or, update manually using
<span aria-hidden className="h-px flex-1 bg-border" />
</div>
) : null}
{updateCommand ? (
<div className="flex min-w-0 items-center gap-1 rounded-md border border-border/70 bg-muted/40 py-0.5 pr-0.5 pl-2">
<code className="min-w-0 flex-1 truncate font-mono text-2xs text-foreground">
{updateCommand}
</code>
<Tooltip>
<TooltipTrigger
render={
<Button
type="button"
size="icon-xs"
variant="ghost-muted"
className="shrink-0"
onClick={() =>
copyToClipboard(updateCommand, { providerName: displayName })
}
aria-label="Copy update command"
>
<CopyIcon className="size-3" />
</Button>
}
/>
<TooltipPopup side="top">Copy command</TooltipPopup>
</Tooltip>
</div>
) : null}
</div>
</PopoverPopup>
</Popover>
) : null}
{titleTailNode}
{onDelete ? (
<Button
Expand Down
6 changes: 3 additions & 3 deletions apps/web/src/components/settings/ProviderSettingsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1164,7 +1164,7 @@ export function EnvironmentProviderSettings({
})
}
onInstallRecommended={
mode === "editor" &&
!readOnly &&
liveProvider?.compatibilityAdvisory?.message &&
liveProvider.compatibilityAdvisory.recommendedVersion &&
liveProvider.versionAdvisory?.canInstallVersion
Expand All @@ -1177,13 +1177,13 @@ export function EnvironmentProviderSettings({
: undefined
}
onRunUpdate={
mode === "editor" && showInlineUpdateButton && updateCandidate
!readOnly && showInlineUpdateButton && updateCandidate
? () => {
if (canRunInlineUpdate) void runProviderUpdate(updateCandidate);
}
: undefined
}
isUpdating={mode === "editor" ? isInstanceUpdateRunning : undefined}
isUpdating={isInstanceUpdateRunning}
/>
);
};
Expand Down
Loading