mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(site): restore Add model button and fix header in Models/Providers sections (#22953)
## Problem The refactor in #22914 moved the `SectionHeader` rendering into `ConfigureAgentsDialog`, but `ModelsSection` and `ProvidersSection` only render their action buttons (including the "Add model" dropdown) inside their own `SectionHeader`, which is gated on the `sectionLabel` prop. Since the dialog stopped passing `sectionLabel`, the Add button disappeared entirely — there was no way to add a model. Additionally, when clicking a model to edit, the `ModelForm` was supposed to take over the full panel (the section early-returns the form without any header), but the outer `SectionHeader` from the dialog remained visible above it. ## Fix Remove the duplicate `SectionHeader` from `ConfigureAgentsDialog` for both the Providers and Models sections. Instead, pass `sectionLabel`, `sectionDescription`, and `sectionBadge` through `ChatModelAdminPanel` to the inner `ProvidersSection`/`ModelsSection` components, which render their own headers with the appropriate action buttons. This restores: 1. The "Add" model dropdown button in the top-right of the Models section 2. Proper header hiding when clicking into a model edit form 3. The AdminBadge and rich description text on each section header
This commit is contained in:
@@ -13,7 +13,7 @@ import type * as TypesGen from "api/typesGenerated";
|
||||
import { Alert, AlertDescription, AlertTitle } from "components/Alert/Alert";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Spinner } from "components/Spinner/Spinner";
|
||||
import { type FC, useMemo, useState } from "react";
|
||||
import { type FC, type ReactNode, useMemo, useState } from "react";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { cn } from "utils/cn";
|
||||
import { formatProviderLabel } from "../modelOptions";
|
||||
@@ -203,12 +203,16 @@ interface ChatModelAdminPanelProps {
|
||||
className?: string;
|
||||
section?: ChatModelAdminSection;
|
||||
sectionLabel?: string;
|
||||
sectionDescription?: string;
|
||||
sectionBadge?: ReactNode;
|
||||
}
|
||||
|
||||
export const ChatModelAdminPanel: FC<ChatModelAdminPanelProps> = ({
|
||||
className,
|
||||
section = "providers",
|
||||
sectionLabel,
|
||||
sectionDescription,
|
||||
sectionBadge,
|
||||
}) => {
|
||||
const queryClient = useQueryClient();
|
||||
const [requestedProvider, setRequestedProvider] = useState<string | null>(
|
||||
@@ -311,6 +315,8 @@ export const ChatModelAdminPanel: FC<ChatModelAdminPanelProps> = ({
|
||||
{section === "providers" ? (
|
||||
<ProvidersSection
|
||||
sectionLabel={sectionLabel}
|
||||
sectionDescription={sectionDescription}
|
||||
sectionBadge={sectionBadge}
|
||||
providerStates={providerStates}
|
||||
providerConfigsUnavailable={providerConfigsUnavailable}
|
||||
isProviderMutationPending={isProviderMutationPending}
|
||||
@@ -327,6 +333,8 @@ export const ChatModelAdminPanel: FC<ChatModelAdminPanelProps> = ({
|
||||
) : (
|
||||
<ModelsSection
|
||||
sectionLabel={sectionLabel}
|
||||
sectionDescription={sectionDescription}
|
||||
sectionBadge={sectionBadge}
|
||||
providerStates={providerStates}
|
||||
selectedProvider={selectedProvider}
|
||||
selectedProviderState={selectedProviderState}
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
PlusIcon,
|
||||
StarIcon,
|
||||
} from "lucide-react";
|
||||
import { type FC, useState } from "react";
|
||||
import { type FC, type ReactNode, useState } from "react";
|
||||
import { cn } from "utils/cn";
|
||||
import { SectionHeader } from "../SectionHeader";
|
||||
import type { ProviderState } from "./ChatModelAdminPanel";
|
||||
@@ -32,6 +32,8 @@ type ModelView =
|
||||
|
||||
interface ModelsSectionProps {
|
||||
sectionLabel?: string;
|
||||
sectionDescription?: string;
|
||||
sectionBadge?: ReactNode;
|
||||
providerStates: readonly ProviderState[];
|
||||
selectedProvider: string | null;
|
||||
selectedProviderState: ProviderState | null;
|
||||
@@ -53,6 +55,8 @@ interface ModelsSectionProps {
|
||||
|
||||
export const ModelsSection: FC<ModelsSectionProps> = ({
|
||||
sectionLabel,
|
||||
sectionDescription,
|
||||
sectionBadge,
|
||||
providerStates,
|
||||
selectedProvider,
|
||||
selectedProviderState,
|
||||
@@ -164,7 +168,10 @@ export const ModelsSection: FC<ModelsSectionProps> = ({
|
||||
{sectionLabel && (
|
||||
<SectionHeader
|
||||
label={sectionLabel}
|
||||
description="Manage models available to Agents."
|
||||
description={
|
||||
sectionDescription ?? "Manage models available to Agents."
|
||||
}
|
||||
badge={sectionBadge}
|
||||
action={addButton || undefined}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type * as TypesGen from "api/typesGenerated";
|
||||
import { CheckCircleIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
||||
import { type FC, useState } from "react";
|
||||
import { type FC, type ReactNode, useState } from "react";
|
||||
import { cn } from "utils/cn";
|
||||
import { SectionHeader } from "../SectionHeader";
|
||||
import type { ProviderState } from "./ChatModelAdminPanel";
|
||||
@@ -11,6 +11,8 @@ type ProviderView = { mode: "list" } | { mode: "detail"; provider: string };
|
||||
|
||||
interface ProvidersSectionProps {
|
||||
sectionLabel?: string;
|
||||
sectionDescription?: string;
|
||||
sectionBadge?: ReactNode;
|
||||
providerStates: readonly ProviderState[];
|
||||
providerConfigsUnavailable: boolean;
|
||||
isProviderMutationPending: boolean;
|
||||
@@ -27,6 +29,8 @@ interface ProvidersSectionProps {
|
||||
|
||||
export const ProvidersSection: FC<ProvidersSectionProps> = ({
|
||||
sectionLabel,
|
||||
sectionDescription,
|
||||
sectionBadge,
|
||||
providerStates,
|
||||
providerConfigsUnavailable,
|
||||
isProviderMutationPending,
|
||||
@@ -80,7 +84,10 @@ export const ProvidersSection: FC<ProvidersSectionProps> = ({
|
||||
{sectionLabel && (
|
||||
<SectionHeader
|
||||
label={sectionLabel}
|
||||
description="Configure AI providers to use with Agents."
|
||||
description={
|
||||
sectionDescription ?? "Configure AI providers to use with Agents."
|
||||
}
|
||||
badge={sectionBadge}
|
||||
/>
|
||||
)}
|
||||
<div>
|
||||
|
||||
@@ -338,24 +338,20 @@ export const ConfigureAgentsDialog: FC<ConfigureAgentsDialogProps> = ({
|
||||
</>
|
||||
)}
|
||||
{activeSection === "providers" && canManageChatModelConfigs && (
|
||||
<>
|
||||
<SectionHeader
|
||||
label="Providers"
|
||||
description="Connect third-party LLM services like OpenAI, Anthropic, or Google. Each provider supplies models that users can select for their chats."
|
||||
badge={<AdminBadge />}
|
||||
/>{" "}
|
||||
<ChatModelAdminPanel section="providers" />
|
||||
</>
|
||||
<ChatModelAdminPanel
|
||||
section="providers"
|
||||
sectionLabel="Providers"
|
||||
sectionDescription="Connect third-party LLM services like OpenAI, Anthropic, or Google. Each provider supplies models that users can select for their chats."
|
||||
sectionBadge={<AdminBadge />}
|
||||
/>
|
||||
)}
|
||||
{activeSection === "models" && canManageChatModelConfigs && (
|
||||
<>
|
||||
<SectionHeader
|
||||
label="Models"
|
||||
description="Choose which models from your configured providers are available for users to select. You can set a default and adjust context limits."
|
||||
badge={<AdminBadge />}
|
||||
/>{" "}
|
||||
<ChatModelAdminPanel section="models" />
|
||||
</>
|
||||
<ChatModelAdminPanel
|
||||
section="models"
|
||||
sectionLabel="Models"
|
||||
sectionDescription="Choose which models from your configured providers are available for users to select. You can set a default and adjust context limits."
|
||||
sectionBadge={<AdminBadge />}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</DialogContent>
|
||||
|
||||
Reference in New Issue
Block a user