mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-24 06:42:21 +08:00
feat: watsonx Orchestrate deployment UI polish (#12621)
* feat: add credentials help link to deployment stepper and add-provider modal Add a descriptive hint below the watsonx Orchestrate provider card in both the deployment stepper and the add-provider modal, linking users to the IBM docs to find their credentials. * feat: add Beta badge to deployments tab and provider card * fix: keep provider selector visible when selected provider has no deployments The environment dropdown was hidden whenever deployments.length was 0, stranding users on the empty state with no way to switch providers. * feat: use watsonx Orchestrate logo in deployment provider UI Replaces the generic Bot icon with a dedicated WatsonxOrchestrate SVG in the deployment stepper and add-environment modal, wired through the existing IBM icon barrel and the eager/lazy icon registries. * fix: tighten Beta badge styling in main page header Constrain height, padding, font size and color so the Beta badge renders consistently alongside the tab label instead of inheriting oversized default sizing. * fix: rename "Deployment Providers" tab to "Deployment Environments" Aligns the sub-tab label with the environment-centric terminology introduced in #12551.
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import SvgIBM from "./ibm/IBM";
|
||||
import SvgWatsonxAI from "./watsonx/WatsonxAI";
|
||||
import SvgWatsonxOrchestrate from "./watsonx/WatsonxOrchestrate";
|
||||
|
||||
export const WatsonxAiIcon = forwardRef<
|
||||
SVGSVGElement,
|
||||
@ -9,6 +10,13 @@ export const WatsonxAiIcon = forwardRef<
|
||||
return <SvgWatsonxAI ref={ref} {...props} />;
|
||||
});
|
||||
|
||||
export const WatsonxOrchestrateIcon = forwardRef<
|
||||
SVGSVGElement,
|
||||
React.PropsWithChildren<{}>
|
||||
>((props, ref) => {
|
||||
return <SvgWatsonxOrchestrate ref={ref} {...props} />;
|
||||
});
|
||||
|
||||
export const IBMIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <SvgIBM ref={ref} {...props} />;
|
||||
|
||||
18
src/frontend/src/icons/IBM/watsonx/WatsonxOrchestrate.jsx
Normal file
18
src/frontend/src/icons/IBM/watsonx/WatsonxOrchestrate.jsx
Normal file
@ -0,0 +1,18 @@
|
||||
const SvgWatsonxOrchestrate = (props) => (
|
||||
<svg
|
||||
fill={props.isDark ? "#ffffff" : "#0A0A0A"}
|
||||
fillRule="evenodd"
|
||||
style={{ flex: "none", lineHeight: 1 }}
|
||||
viewBox="0 0 32 32"
|
||||
width="1em"
|
||||
height="1em"
|
||||
{...props}
|
||||
>
|
||||
<path d="m27.9248,19.4282c-1.123,1.6104-2.9641,2.5718-4.9248,2.5718-2.1233,0-4.0464-1.0874-5.1438-2.9092l-1.7129,1.0322c1.4624,2.4277,4.0256,3.877,6.8567,3.877,1.4231,0,2.7925-.3911,3.9922-1.0835-2.3442,3.6958-6.4814,6.0835-10.9922,6.0835-5.7104,0-10.8347-3.8184-12.4617-9.2852l-1.917.5703c1.8774,6.3086,7.79,10.7148,14.3787,10.7148s12.5012-4.4062,14.3787-10.7148l-2.4539-.8569Z" />
|
||||
<circle cx="30" cy="16" r="2" />
|
||||
<circle cx="2" cy="16" r="2" />
|
||||
<circle cx="16" cy="16" r="2" />
|
||||
<path d="m16,1C9.4114,1,3.4988,5.4062,1.6213,11.7148l2.4539.8569c1.123-1.6104,2.9641-2.5718,4.9248-2.5718s3.8018.9614,4.9248,2.5718l1.6406-1.144c-1.4971-2.1465-3.9514-3.4277-6.5654-3.4277-1.4231,0-2.7925.3911-3.9922,1.0835,2.3442-3.6953,6.4814-6.0835,10.9922-6.0835,5.7104,0,10.8347,3.8184,12.4617,9.2852l1.917-.5703c-1.8774-6.3086-7.79-10.7148-14.3787-10.7148Z" />
|
||||
</svg>
|
||||
);
|
||||
export default SvgWatsonxOrchestrate;
|
||||
@ -52,7 +52,7 @@ import { HCDIcon } from "@/icons/HCD";
|
||||
import { HomeAssistantIcon } from "@/icons/HomeAssistant";
|
||||
import { HuggingFaceIcon } from "@/icons/HuggingFace";
|
||||
import { HackerNewsIcon } from "@/icons/hackerNews";
|
||||
import { IBMIcon, WatsonxAiIcon } from "@/icons/IBM";
|
||||
import { IBMIcon, WatsonxAiIcon, WatsonxOrchestrateIcon } from "@/icons/IBM";
|
||||
import { IcosaIcon } from "@/icons/Icosa";
|
||||
import { IFixIcon } from "@/icons/IFixIt";
|
||||
import { JSIcon } from "@/icons/JSicon";
|
||||
@ -235,6 +235,7 @@ export const eagerIconsMapping = {
|
||||
VertexAI: VertexAIIcon,
|
||||
vLLM: VllmIcon,
|
||||
WatsonxAI: WatsonxAiIcon,
|
||||
WatsonxOrchestrate: WatsonxOrchestrateIcon,
|
||||
Weaviate: WeaviateIcon,
|
||||
Wikipedia: WikipediaIcon,
|
||||
Windsurf: WindsurfIcon,
|
||||
|
||||
@ -290,6 +290,10 @@ export const lazyIconsMapping = {
|
||||
import("@/icons/IBM").then((mod) => ({
|
||||
default: mod.WatsonxAiIcon,
|
||||
})),
|
||||
WatsonxOrchestrate: () =>
|
||||
import("@/icons/IBM").then((mod) => ({
|
||||
default: mod.WatsonxOrchestrateIcon,
|
||||
})),
|
||||
Icosa: () =>
|
||||
import("@/icons/Icosa").then((mod) => ({ default: mod.IcosaIcon })),
|
||||
IFixIt: () =>
|
||||
|
||||
@ -3,6 +3,7 @@ import { useCallback, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ForwardedIconComponent from "@/components/common/genericIconComponent";
|
||||
import ShadTooltip from "@/components/common/shadTooltipComponent";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { SidebarTrigger } from "@/components/ui/sidebar";
|
||||
@ -151,10 +152,24 @@ const HeaderComponent = ({
|
||||
: "border-border text-muted-foreground hover:text-foreground"
|
||||
} text-nowrap px-2 pb-2 pt-1 text-mmd`}
|
||||
>
|
||||
<div className={flowType === type ? "-mb-px" : ""}>
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center gap-1.5",
|
||||
flowType === type && "-mb-px",
|
||||
)}
|
||||
>
|
||||
{type === "mcp"
|
||||
? t("mainPage.mcpServer")
|
||||
: type.charAt(0).toUpperCase() + type.slice(1)}
|
||||
{type === "deployments" && (
|
||||
<Badge
|
||||
variant="purpleStatic"
|
||||
size="xq"
|
||||
className="h-auto shrink-0 rounded px-1 py-px text-[11px] leading-none text-accent-purple-foreground"
|
||||
>
|
||||
Beta
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
</Button>
|
||||
))}
|
||||
|
||||
@ -251,7 +251,7 @@ describe("Create mode — step navigation", () => {
|
||||
id: "watsonx",
|
||||
type: "watsonx",
|
||||
name: "watsonx Orchestrate",
|
||||
icon: "Bot",
|
||||
icon: "WatsonxOrchestrate",
|
||||
},
|
||||
initialInstance: makeInstance(),
|
||||
});
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import ForwardedIconComponent from "@/components/common/genericIconComponent";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
@ -71,17 +72,35 @@ export default function AddProviderModal({
|
||||
<DialogTitle data-testid="add-provider-modal-title">
|
||||
Add Environment
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Configure your watsonx Orchestrate credentials below.
|
||||
<DialogDescription className="sr-only">
|
||||
Add a new watsonx Orchestrate environment.
|
||||
</DialogDescription>
|
||||
|
||||
<div className="flex flex-col gap-4 pt-2">
|
||||
<div className="flex items-center gap-3 rounded-lg border border-border bg-muted p-3">
|
||||
<ForwardedIconComponent
|
||||
name="Bot"
|
||||
className="h-8 w-8 text-foreground"
|
||||
/>
|
||||
<span className="text-sm font-medium">watsonx Orchestrate</span>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center gap-3 rounded-lg border border-border bg-muted p-3">
|
||||
<ForwardedIconComponent
|
||||
name="WatsonxOrchestrate"
|
||||
className="h-8 w-8 text-foreground"
|
||||
/>
|
||||
<span className="text-sm font-medium">watsonx Orchestrate</span>
|
||||
<Badge variant="purpleStatic" size="xq" className="shrink-0">
|
||||
Beta
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Configure your watsonx Orchestrate credentials below. Sign in or
|
||||
sign up to{" "}
|
||||
<a
|
||||
href="https://www.ibm.com/docs/en/watsonx/watson-orchestrate/base?topic=api-getting-started"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-medium text-primary hover:underline"
|
||||
>
|
||||
find your credentials
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ProviderCredentialsForm
|
||||
|
||||
@ -80,7 +80,7 @@ export default function DeploymentsContent({
|
||||
|
||||
return (
|
||||
<>
|
||||
{providers.length >= 1 && deployments.length > 0 && (
|
||||
{providers.length >= 1 && (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-muted-foreground">Environment:</span>
|
||||
<Select
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import ForwardedIconComponent from "@/components/common/genericIconComponent";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { useGetProviderAccounts } from "@/controllers/API/queries/deployment-provider-accounts/use-get-provider-accounts";
|
||||
import { cn } from "@/utils/utils";
|
||||
import { useDeploymentStepper } from "../contexts/deployment-stepper-context";
|
||||
@ -12,7 +13,7 @@ const PROVIDERS: DeploymentProvider[] = [
|
||||
id: "watsonx",
|
||||
type: "watsonx",
|
||||
name: "watsonx Orchestrate",
|
||||
icon: "Bot",
|
||||
icon: "WatsonxOrchestrate",
|
||||
},
|
||||
];
|
||||
|
||||
@ -126,12 +127,30 @@ export default function StepProvider() {
|
||||
<div className="flex h-full w-full flex-col gap-6 overflow-y-auto py-3">
|
||||
<h2 className="text-lg font-semibold">Provider</h2>
|
||||
|
||||
<div className="flex items-center gap-3 rounded-lg border border-border bg-muted p-3">
|
||||
<ForwardedIconComponent
|
||||
name={provider.icon}
|
||||
className="h-8 w-8 text-foreground"
|
||||
/>
|
||||
<span className="text-sm font-medium">{provider.name}</span>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center gap-3 rounded-lg border border-border bg-muted p-3">
|
||||
<ForwardedIconComponent
|
||||
name={provider.icon}
|
||||
className="h-8 w-8 text-foreground"
|
||||
/>
|
||||
<span className="text-sm font-medium">{provider.name}</span>
|
||||
<Badge variant="purpleStatic" size="xq" className="shrink-0">
|
||||
Beta
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Configure your watsonx Orchestrate credentials below. Sign in or sign
|
||||
up to{" "}
|
||||
<a
|
||||
href="https://www.ibm.com/docs/en/watsonx/watson-orchestrate/base?topic=api-getting-started"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-medium text-primary hover:underline"
|
||||
>
|
||||
find your credentials
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{hasEnvironments ? (
|
||||
|
||||
@ -10,7 +10,7 @@ interface SubTabToggleProps {
|
||||
|
||||
const tabs: { value: DeploymentSubTab; label: string }[] = [
|
||||
{ value: "deployments", label: "Deployments" },
|
||||
{ value: "providers", label: "Deployment Providers" },
|
||||
{ value: "providers", label: "Deployment Environments" },
|
||||
];
|
||||
|
||||
export default function SubTabToggle({
|
||||
|
||||
Reference in New Issue
Block a user