From ebe20e131b42344ac9b514caeee5dabf5d1d52d8 Mon Sep 17 00:00:00 2001 From: Mike Fortman Date: Tue, 15 Apr 2025 11:00:16 -0500 Subject: [PATCH] refactor: Implement Lazy loading for icons in cloud deployments (#7218) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * init add lazy loading for icons * Add more icon fixes * [autofix.ci] apply automated fixes * cleanup * [autofix.ci] apply automated fixes * add change to user management modal * Add eager loading for common icons * add fallback for flow id * [autofix.ci] apply automated fixes * ♻️ (GenericNode/index.tsx): refactor selectedNodes to selectedNodesCount for better readability and performance optimization * add one more icon * add missing icon * cleanup * [autofix.ci] apply automated fixes * fallback fixes * [autofix.ci] apply automated fixes * move lucide imports * [autofix.ci] apply automated fixes * conditional lazy loading for cloud only * [autofix.ci] apply automated fixes * fix imports * [autofix.ci] apply automated fixes * up the shards * add a bit of a timeout * group icon fix and reduce playground button rerenders * and new icons to lazy load * [autofix.ci] apply automated fixes * warning cleanup * iconExists fix * cleanup * [autofix.ci] apply automated fixes * move icon --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com> Co-authored-by: cristhianzl --- .../GenericNode/components/nodeIcon/index.tsx | 12 +- .../common/genericIconComponent/index.tsx | 98 +- .../components/playground-button.tsx | 71 +- .../API/queries/_builds/use-get-builds.ts | 7 +- .../src/icons/Anthropic/Anthropic.jsx | 4 +- .../src/icons/GradientSparkles/index.tsx | 14 +- src/frontend/src/icons/Perplexity/index.tsx | 2 +- src/frontend/src/icons/eagerIconImports.ts | 228 ++++ src/frontend/src/icons/lazyIconImports.ts | 271 +++++ src/frontend/src/icons/lucideIcons.ts | 467 ++++++++ .../src/modals/userManagementModal/index.tsx | 7 +- .../components/DisclosureComponent/index.tsx | 6 +- .../ParentDisclosureComponent/index.tsx | 4 +- .../SidebarCategoryComponent/index.tsx | 6 +- .../extraSidebarComponent/index.tsx | 5 +- .../pages/MainPage/components/grid/index.tsx | 10 +- .../pages/MainPage/components/list/index.tsx | 10 +- .../MainPage/utils/get-template-style.ts | 8 +- src/frontend/src/types/components/index.ts | 4 +- src/frontend/src/utils/styleUtils.ts | 1032 ++++------------- 20 files changed, 1377 insertions(+), 889 deletions(-) create mode 100644 src/frontend/src/icons/eagerIconImports.ts create mode 100644 src/frontend/src/icons/lazyIconImports.ts create mode 100644 src/frontend/src/icons/lucideIcons.ts diff --git a/src/frontend/src/CustomNodes/GenericNode/components/nodeIcon/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/nodeIcon/index.tsx index c165122c9..bfa14afb4 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/nodeIcon/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/nodeIcon/index.tsx @@ -1,11 +1,12 @@ import { useTypesStore } from "@/stores/typesStore"; import { BG_NOISE, + iconExists, nodeColors, - nodeIconsLucide, toolModeGradient, } from "@/utils/styleUtils"; import emojiRegex from "emoji-regex"; +import { useEffect, useState } from "react"; import { ICON_STROKE_WIDTH } from "@/constants/constants"; import { checkLucideIcons } from "@/CustomNodes/helpers/check-lucide-icons"; @@ -26,7 +27,14 @@ export function NodeIcon({ hasToolMode: boolean; }) { const types = useTypesStore((state) => state.types); - const name = nodeIconsLucide[dataType] ? dataType : types[dataType]; + const [name, setName] = useState(types[dataType]); + + useEffect(() => { + iconExists(dataType).then((exists) => { + setName(exists ? dataType : types[dataType]); + }); + }, [dataType, types]); + const isEmoji = emojiRegex().test(icon ?? ""); const iconColor = nodeColors[types[dataType]]; const iconName = icon || (isGroup ? "group_components" : name); diff --git a/src/frontend/src/components/common/genericIconComponent/index.tsx b/src/frontend/src/components/common/genericIconComponent/index.tsx index 5f55df1a7..bd9c98b40 100644 --- a/src/frontend/src/components/common/genericIconComponent/index.tsx +++ b/src/frontend/src/components/common/genericIconComponent/index.tsx @@ -1,11 +1,10 @@ -import dynamicIconImports from "lucide-react/dynamicIconImports"; -import { Suspense, forwardRef, lazy, memo } from "react"; +import React, { Suspense, forwardRef, lazy, memo } from "react"; import { IconComponentProps } from "../../../types/components"; -import { nodeIconsLucide } from "../../../utils/styleUtils"; +import { getNodeIcon } from "../../../utils/styleUtils"; import { cn } from "../../../utils/utils"; -import Loading from "../../ui/loading"; -import { useEffect, useState } from "react"; +import { Skeleton } from "@/components/ui/skeleton"; +import { useCallback, useEffect, useState } from "react"; export const ForwardedIconComponent = memo( forwardRef( @@ -23,28 +22,32 @@ export const ForwardedIconComponent = memo( ref, ) => { const [showFallback, setShowFallback] = useState(false); + const [iconError, setIconError] = useState(false); + const [TargetIcon, setTargetIcon] = useState(null); useEffect(() => { + // Reset states when icon name changes + setIconError(false); + setTargetIcon(null); + const timer = setTimeout(() => { setShowFallback(true); }, 30); - return () => clearTimeout(timer); - }, []); + // Load the icon if we have a name + if (name && typeof name === "string") { + getNodeIcon(name) + .then((component) => { + setTargetIcon(component); + }) + .catch((error) => { + console.error(`Error loading icon ${name}:`, error); + setIconError(true); + }); + } - let TargetIcon = - nodeIconsLucide[name] || - nodeIconsLucide[ - name - ?.split("-") - ?.map((x) => String(x[0])?.toUpperCase() + String(x).slice(1)) - ?.join("") - ]; - if (!TargetIcon) { - if (!dynamicIconImports[name]) { - TargetIcon = nodeIconsLucide["unknown"]; - } else TargetIcon = lazy(dynamicIconImports[name]); - } + return () => clearTimeout(timer); + }, [name]); const style = { strokeWidth: strokeWidth ?? 1.5, @@ -52,13 +55,30 @@ export const ForwardedIconComponent = memo( ...(iconColor && { color: iconColor, stroke: stroke }), }; - if (!TargetIcon) { - return null; // Render nothing until the icon is loaded + // Handler for when the Suspense component throws + const handleError = useCallback(() => { + setIconError(true); + }, []); + + if (!TargetIcon || iconError) { + // Return a placeholder div or null depending on settings + return skipFallback ? null : ( +
+ ); } const fallback = showFallback ? (
- +
) : (
@@ -66,18 +86,34 @@ export const ForwardedIconComponent = memo( return ( - + + + ); }, ), ); +// Simple error boundary component for catching lazy load errors +class ErrorBoundary extends React.Component<{ + children: React.ReactNode; + onError: () => void; +}> { + componentDidCatch(error: any) { + this.props.onError(); + } + + render() { + return this.props.children; + } +} + export default ForwardedIconComponent; diff --git a/src/frontend/src/components/core/flowToolbarComponent/components/playground-button.tsx b/src/frontend/src/components/core/flowToolbarComponent/components/playground-button.tsx index 16424b5c3..cff294259 100644 --- a/src/frontend/src/components/core/flowToolbarComponent/components/playground-button.tsx +++ b/src/frontend/src/components/core/flowToolbarComponent/components/playground-button.tsx @@ -1,41 +1,54 @@ import ForwardedIconComponent from "@/components/common/genericIconComponent"; import ShadTooltip from "@/components/common/shadTooltipComponent"; import { PLAYGROUND_BUTTON_NAME } from "@/constants/constants"; +import { ENABLE_PUBLISH } from "@/customization/feature-flags"; import IOModal from "@/modals/IOModal/new-modal"; -const PlaygroundButton = ({ hasIO, open, setOpen, canvasOpen }) => { - const PlayIcon = () => ( - - ); +interface PlaygroundButtonProps { + hasIO: boolean; + open: boolean; + setOpen: (open: boolean) => void; + canvasOpen: boolean; +} - const ButtonLabel = () => ( - {PLAYGROUND_BUTTON_NAME} - ); +const PlayIcon = () => ( + +); - const ActiveButton = () => ( -
- - -
- ); +const ButtonLabel = () => ( + {PLAYGROUND_BUTTON_NAME} +); - const DisabledButton = () => ( -
- - -
- ); +const ActiveButton = () => ( +
+ + +
+); +const DisabledButton = () => ( +
+ + +
+); + +const PlaygroundButton = ({ + hasIO, + open, + setOpen, + canvasOpen, +}: PlaygroundButtonProps) => { return hasIO ? ( > = (params) => { const { query } = UseRequestProcessor(); + const { id: routeFlowId } = useParams(); const setFlowPool = useFlowStore((state) => state.setFlowPool); const currentFlow = useFlowStore((state) => state.currentFlow); const responseFn = async () => { const config = {}; - config["params"] = { flow_id: params.flowId }; + config["params"] = { + flow_id: + !params.flowId || params.flowId === "" ? routeFlowId : params.flowId, + }; const response = await api.get(`${getURL("BUILDS")}`, config); diff --git a/src/frontend/src/icons/Anthropic/Anthropic.jsx b/src/frontend/src/icons/Anthropic/Anthropic.jsx index 790d7f5c3..235f52762 100644 --- a/src/frontend/src/icons/Anthropic/Anthropic.jsx +++ b/src/frontend/src/icons/Anthropic/Anthropic.jsx @@ -1,5 +1,5 @@ -const SvgAnthropicBox = (props) => { - return props.isDark ? ( +const SvgAnthropicBox = ({ isDark, ...props }) => { + return isDark ? ( { ); }; -export const GradientUngroup = (props) => { +export const GradientUngroup = forwardRef< + SVGSVGElement, + React.PropsWithChildren<{}> +>((props, ref) => { return ( <> @@ -68,7 +71,12 @@ export const GradientUngroup = (props) => { - + ); -}; +}); diff --git a/src/frontend/src/icons/Perplexity/index.tsx b/src/frontend/src/icons/Perplexity/index.tsx index d6103437c..74b7dcbe1 100644 --- a/src/frontend/src/icons/Perplexity/index.tsx +++ b/src/frontend/src/icons/Perplexity/index.tsx @@ -1,5 +1,5 @@ import React, { forwardRef } from "react"; -import PerplexitySVG from "./perplexity"; +import PerplexitySVG from "./Perplexity"; export const PerplexityIcon = forwardRef< SVGSVGElement, diff --git a/src/frontend/src/icons/eagerIconImports.ts b/src/frontend/src/icons/eagerIconImports.ts new file mode 100644 index 000000000..b9c197235 --- /dev/null +++ b/src/frontend/src/icons/eagerIconImports.ts @@ -0,0 +1,228 @@ +import { AgentQLIcon } from "@/icons/AgentQL"; +import { AIMLIcon } from "@/icons/AIML"; +import { AirbyteIcon } from "@/icons/Airbyte"; +import { AnthropicIcon } from "@/icons/Anthropic"; +import { ApifyIcon, ApifyWhiteIcon } from "@/icons/Apify"; +import { ArizeIcon } from "@/icons/Arize"; +import { ArXivIcon } from "@/icons/ArXiv"; +import { AssemblyAIIcon } from "@/icons/AssemblyAI"; +import { AstraDBIcon } from "@/icons/AstraDB"; +import { AthenaIcon } from "@/icons/athena/index"; +import { AWSIcon } from "@/icons/AWS"; +import { AWSInvertedIcon } from "@/icons/AWSInverted"; +import { AzureIcon } from "@/icons/Azure"; +import { BingIcon } from "@/icons/Bing"; +import { BotMessageSquareIcon } from "@/icons/BotMessageSquare"; +import { BWPythonIcon } from "@/icons/BW python"; +import { CassandraIcon } from "@/icons/Cassandra"; +import { ChromaIcon } from "@/icons/ChromaIcon"; +import { ClickhouseIcon } from "@/icons/Clickhouse"; +import { CloudflareIcon } from "@/icons/Cloudflare"; +import { CohereIcon } from "@/icons/Cohere"; +import { ComposioIcon } from "@/icons/Composio"; +import { ConfluenceIcon } from "@/icons/Confluence"; +import { CouchbaseIcon } from "@/icons/Couchbase"; +import { CrewAiIcon } from "@/icons/CrewAI"; +import { DeepSeekIcon } from "@/icons/DeepSeek"; +import { DropboxIcon } from "@/icons/Dropbox"; +import { DuckDuckGoIcon } from "@/icons/DuckDuckGo"; +import { ElasticsearchIcon } from "@/icons/ElasticsearchStore"; +import { EvernoteIcon } from "@/icons/Evernote"; +import { ExaIcon } from "@/icons/Exa"; +import { FBIcon } from "@/icons/FacebookMessenger"; +import { FirecrawlIcon } from "@/icons/Firecrawl"; +import { freezeAllIcon } from "@/icons/freezeAll"; +import { GitBookIcon } from "@/icons/GitBook"; +import { GitLoaderIcon } from "@/icons/GitLoader"; +import { GleanIcon } from "@/icons/Glean"; +import { GlobeOkIcon } from "@/icons/globe-ok"; +import { GmailIcon } from "@/icons/gmail"; +import { GoogleIcon } from "@/icons/Google"; +import { GoogleDriveIcon } from "@/icons/GoogleDrive"; +import { GoogleGenerativeAIIcon } from "@/icons/GoogleGenerativeAI"; +import { + GradientInfinity, + GradientSave, + GradientUngroup, +} from "@/icons/GradientSparkles"; +import { GridHorizontalIcon } from "@/icons/GridHorizontal"; +import { GroqIcon } from "@/icons/Groq"; +import { HackerNewsIcon } from "@/icons/hackerNews"; +import { HCDIcon } from "@/icons/HCD"; +import { HomeAssistantIcon } from "@/icons/HomeAssistant"; +import { HuggingFaceIcon } from "@/icons/HuggingFace"; +import { WatsonxAiIcon } from "@/icons/IBMWatsonx"; +import { IcosaIcon } from "@/icons/Icosa"; +import { IFixIcon } from "@/icons/IFixIt"; +import { JSIcon } from "@/icons/JSicon"; +import { LangChainIcon } from "@/icons/LangChain"; +import { LangwatchIcon } from "@/icons/Langwatch"; +import { LMStudioIcon } from "@/icons/LMStudio"; +import { MaritalkIcon } from "@/icons/Maritalk"; +import { Mem0 } from "@/icons/Mem0"; +import { MetaIcon } from "@/icons/Meta"; +import { MidjourneyIcon } from "@/icons/Midjorney"; +import { MilvusIcon } from "@/icons/Milvus"; +import { MistralIcon } from "@/icons/mistral"; +import { MongoDBIcon } from "@/icons/MongoDB"; +import { NeedleIcon } from "@/icons/Needle"; +import { NotDiamondIcon } from "@/icons/NotDiamond"; +import { NotionIcon } from "@/icons/Notion"; +import { NovitaIcon } from "@/icons/Novita"; +import { NvidiaIcon } from "@/icons/Nvidia"; +import { OlivyaIcon } from "@/icons/Olivya"; +import { OllamaIcon } from "@/icons/Ollama"; +import { OneDriveIcon } from "@/icons/OneDrive"; +import { OpenAiIcon } from "@/icons/OpenAi"; +import { OpenRouterIcon } from "@/icons/OpenRouter"; +import { OpenSearch } from "@/icons/OpenSearch"; +import { PerplexityIcon } from "@/icons/Perplexity"; +import { PineconeIcon } from "@/icons/Pinecone"; +import { PostgresIcon } from "@/icons/Postgres"; +import { PythonIcon } from "@/icons/Python"; +import { QDrantIcon } from "@/icons/QDrant"; +import { QianFanChatIcon } from "@/icons/QianFanChat"; +import { RedisIcon } from "@/icons/Redis"; +import { SambaNovaIcon } from "@/icons/SambaNova"; +import { ScrapeGraph } from "@/icons/ScrapeGraphAI"; +import { SearchAPIIcon } from "@/icons/SearchAPI"; +import { SearchHybridIcon } from "@/icons/SearchHybrid"; +import { SearchLexicalIcon } from "@/icons/SearchLexical"; +import { SearchVectorIcon } from "@/icons/SearchVector"; +import { SearxIcon } from "@/icons/Searx"; +import { SerperIcon } from "@/icons/Serper"; +import { SerpSearchIcon } from "@/icons/SerpSearch"; +import { ShareIcon } from "@/icons/Share"; +import { Share2Icon } from "@/icons/Share2"; +import { SlackIcon } from "@/icons/Slack"; +import { SpiderIcon } from "@/icons/Spider"; +import { Streamlit } from "@/icons/Streamlit"; +import { SupabaseIcon } from "@/icons/supabase"; +import { TavilyIcon } from "@/icons/Tavily"; +import { ThumbDownIconCustom, ThumbUpIconCustom } from "@/icons/thumbs"; +import { UnstructuredIcon } from "@/icons/Unstructured"; +import { UpstashSvgIcon } from "@/icons/Upstash"; +import { VectaraIcon } from "@/icons/VectaraIcon"; +import { VertexAIIcon } from "@/icons/VertexAI"; +import { WeaviateIcon } from "@/icons/Weaviate"; +import { WikipediaIcon } from "@/icons/Wikipedia"; +import { WolframIcon } from "@/icons/Wolfram"; +import { XAIIcon } from "@/icons/xAI"; +import { YouTubeSvgIcon as YouTubeIcon } from "@/icons/Youtube"; +import { ZepMemoryIcon } from "@/icons/ZepMemory"; + +// Export the eagerly loaded icons map +export const eagerIconsMapping = { + "AI/ML": AIMLIcon, + AgentQL: AgentQLIcon, + Airbyte: AirbyteIcon, + Anthropic: AnthropicIcon, + Apify: ApifyIcon, + ApifyWhite: ApifyWhiteIcon, + ArXiv: ArXivIcon, + Arize: ArizeIcon, + AssemblyAI: AssemblyAIIcon, + AstraDB: AstraDBIcon, + Athena: AthenaIcon, + AWS: AWSIcon, + AWSInverted: AWSInvertedIcon, + Azure: AzureIcon, + Bing: BingIcon, + BotMessageSquare: BotMessageSquareIcon, + BWPython: BWPythonIcon, + Cassandra: CassandraIcon, + Chroma: ChromaIcon, + Clickhouse: ClickhouseIcon, + Cloudflare: CloudflareIcon, + Cohere: CohereIcon, + Composio: ComposioIcon, + Confluence: ConfluenceIcon, + Couchbase: CouchbaseIcon, + CrewAI: CrewAiIcon, + DeepSeek: DeepSeekIcon, + Dropbox: DropboxIcon, + DuckDuckGo: DuckDuckGoIcon, + ElasticsearchStore: ElasticsearchIcon, + Evernote: EvernoteIcon, + Exa: ExaIcon, + FacebookMessenger: FBIcon, + Firecrawl: FirecrawlIcon, + FreezeAll: freezeAllIcon, + GitBook: GitBookIcon, + GitLoader: GitLoaderIcon, + Glean: GleanIcon, + GlobeOk: GlobeOkIcon, + Google: GoogleIcon, + GoogleDrive: GoogleDriveIcon, + GoogleGenerativeAI: GoogleGenerativeAIIcon, + Gmail: GmailIcon, + GradientInfinity: GradientInfinity, + GradientSave: GradientSave, + GradientUngroup: GradientUngroup, + GridHorizontal: GridHorizontalIcon, + Groq: GroqIcon, + HackerNews: HackerNewsIcon, + HCD: HCDIcon, + HomeAssistant: HomeAssistantIcon, + HuggingFace: HuggingFaceIcon, + Icosa: IcosaIcon, + IFixIt: IFixIcon, + javascript: JSIcon, + LangChain: LangChainIcon, + Langwatch: LangwatchIcon, + LMStudio: LMStudioIcon, + Maritalk: MaritalkIcon, + Mem0: Mem0, + Meta: MetaIcon, + Midjourney: MidjourneyIcon, + Milvus: MilvusIcon, + Mistral: MistralIcon, + MongoDB: MongoDBIcon, + Needle: NeedleIcon, + NotDiamond: NotDiamondIcon, + Notion: NotionIcon, + Novita: NovitaIcon, + NVIDIA: NvidiaIcon, + Olivya: OlivyaIcon, + Ollama: OllamaIcon, + OneDrive: OneDriveIcon, + OpenAI: OpenAiIcon, + OpenRouter: OpenRouterIcon, + OpenSearch: OpenSearch, + Perplexity: PerplexityIcon, + Pinecone: PineconeIcon, + Postgres: PostgresIcon, + Python: PythonIcon, + QDrant: QDrantIcon, + QianFanChat: QianFanChatIcon, + Redis: RedisIcon, + SambaNova: SambaNovaIcon, + ScrapeGraph: ScrapeGraph, + SearchAPI: SearchAPIIcon, + SearchLexical: SearchLexicalIcon, + SearchHybrid: SearchHybridIcon, + SearchVector: SearchVectorIcon, + Searx: SearxIcon, + SerpSearch: SerpSearchIcon, + Serper: SerperIcon, + Share: ShareIcon, + Share2: Share2Icon, + Slack: SlackIcon, + Spider: SpiderIcon, + Streamlit: Streamlit, + Supabase: SupabaseIcon, + Tavily: TavilyIcon, + ThumbDownCustom: ThumbDownIconCustom, + ThumbUpCustom: ThumbUpIconCustom, + Unstructured: UnstructuredIcon, + Upstash: UpstashSvgIcon, + Vectara: VectaraIcon, + VertexAI: VertexAIIcon, + WatsonxAI: WatsonxAiIcon, + Weaviate: WeaviateIcon, + Wikipedia: WikipediaIcon, + Wolfram: WolframIcon, + xAI: XAIIcon, + YouTube: YouTubeIcon, + ZepMemory: ZepMemoryIcon, +}; diff --git a/src/frontend/src/icons/lazyIconImports.ts b/src/frontend/src/icons/lazyIconImports.ts new file mode 100644 index 000000000..7d9b71c09 --- /dev/null +++ b/src/frontend/src/icons/lazyIconImports.ts @@ -0,0 +1,271 @@ +// Export the lazy loading mapping for icons +export const lazyIconsMapping = { + "AI/ML": () => + import("@/icons/AIML").then((mod) => ({ default: mod.AIMLIcon })), + AgentQL: () => + import("@/icons/AgentQL").then((mod) => ({ default: mod.AgentQLIcon })), + Airbyte: () => + import("@/icons/Airbyte").then((mod) => ({ default: mod.AirbyteIcon })), + Anthropic: () => + import("@/icons/Anthropic").then((mod) => ({ default: mod.AnthropicIcon })), + Apify: () => + import("@/icons/Apify").then((mod) => ({ default: mod.ApifyIcon })), + ApifyWhite: () => + import("@/icons/Apify").then((mod) => ({ default: mod.ApifyWhiteIcon })), + ArXiv: () => + import("@/icons/ArXiv").then((mod) => ({ default: mod.ArXivIcon })), + Arize: () => + import("@/icons/Arize").then((mod) => ({ default: mod.ArizeIcon })), + AssemblyAI: () => + import("@/icons/AssemblyAI").then((mod) => ({ + default: mod.AssemblyAIIcon, + })), + AstraDB: () => + import("@/icons/AstraDB").then((mod) => ({ default: mod.AstraDBIcon })), + Athena: () => + import("@/icons/athena").then((mod) => ({ default: mod.AthenaIcon })), + AWS: () => import("@/icons/AWS").then((mod) => ({ default: mod.AWSIcon })), + Azure: () => + import("@/icons/Azure").then((mod) => ({ default: mod.AzureIcon })), + Bing: () => import("@/icons/Bing").then((mod) => ({ default: mod.BingIcon })), + BWPython: () => + import("@/icons/BW python").then((mod) => ({ default: mod.BWPythonIcon })), + Cassandra: () => + import("@/icons/Cassandra").then((mod) => ({ default: mod.CassandraIcon })), + Chroma: () => + import("@/icons/ChromaIcon").then((mod) => ({ default: mod.ChromaIcon })), + Clickhouse: () => + import("@/icons/Clickhouse").then((mod) => ({ + default: mod.ClickhouseIcon, + })), + Cloudflare: () => + import("@/icons/Cloudflare").then((mod) => ({ + default: mod.CloudflareIcon, + })), + Cohere: () => + import("@/icons/Cohere").then((mod) => ({ default: mod.CohereIcon })), + Composio: () => + import("@/icons/Composio").then((mod) => ({ default: mod.ComposioIcon })), + Confluence: () => + import("@/icons/Confluence").then((mod) => ({ + default: mod.ConfluenceIcon, + })), + Couchbase: () => + import("@/icons/Couchbase").then((mod) => ({ default: mod.CouchbaseIcon })), + CrewAI: () => + import("@/icons/CrewAI").then((mod) => ({ default: mod.CrewAiIcon })), + DeepSeek: () => + import("@/icons/DeepSeek").then((mod) => ({ default: mod.DeepSeekIcon })), + Dropbox: () => + import("@/icons/Dropbox").then((mod) => ({ default: mod.DropboxIcon })), + DuckDuckGo: () => + import("@/icons/DuckDuckGo").then((mod) => ({ + default: mod.DuckDuckGoIcon, + })), + ElasticsearchStore: () => + import("@/icons/ElasticsearchStore").then((mod) => ({ + default: mod.ElasticsearchIcon, + })), + Evernote: () => + import("@/icons/Evernote").then((mod) => ({ default: mod.EvernoteIcon })), + Exa: () => import("@/icons/Exa").then((mod) => ({ default: mod.ExaIcon })), + FacebookMessenger: () => + import("@/icons/FacebookMessenger").then((mod) => ({ + default: mod.FBIcon, + })), + Firecrawl: () => + import("@/icons/Firecrawl").then((mod) => ({ default: mod.FirecrawlIcon })), + FreezeAll: () => + import("@/icons/freezeAll").then((mod) => ({ default: mod.freezeAllIcon })), + GitBook: () => + import("@/icons/GitBook").then((mod) => ({ default: mod.GitBookIcon })), + GitLoader: () => + import("@/icons/GitLoader").then((mod) => ({ default: mod.GitLoaderIcon })), + Glean: () => + import("@/icons/Glean").then((mod) => ({ default: mod.GleanIcon })), + GlobeOk: () => + import("@/icons/globe-ok").then((mod) => ({ default: mod.GlobeOkIcon })), + Google: () => + import("@/icons/Google").then((mod) => ({ default: mod.GoogleIcon })), + GoogleDrive: () => + import("@/icons/GoogleDrive").then((mod) => ({ + default: mod.GoogleDriveIcon, + })), + GoogleGenerativeAI: () => + import("@/icons/GoogleGenerativeAI").then((mod) => ({ + default: mod.GoogleGenerativeAIIcon, + })), + Gmail: () => + import("@/icons/gmail").then((mod) => ({ default: mod.GmailIcon })), + GradientInfinity: () => + import("@/icons/GradientSparkles").then((mod) => ({ + default: mod.GradientInfinity, + })), + GradientUngroup: () => + import("@/icons/GradientSparkles").then((mod) => ({ + default: mod.GradientUngroup, + })), + GridHorizontal: () => + import("@/icons/GridHorizontal").then((mod) => ({ + default: mod.GridHorizontalIcon, + })), + Groq: () => import("@/icons/Groq").then((mod) => ({ default: mod.GroqIcon })), + HackerNews: () => + import("@/icons/hackerNews").then((mod) => ({ + default: mod.HackerNewsIcon, + })), + HCD: () => import("@/icons/HCD").then((mod) => ({ default: mod.HCDIcon })), + HomeAssistant: () => + import("@/icons/HomeAssistant").then((mod) => ({ + default: mod.HomeAssistantIcon, + })), + HuggingFace: () => + import("@/icons/HuggingFace").then((mod) => ({ + default: mod.HuggingFaceIcon, + })), + Icosa: () => + import("@/icons/Icosa").then((mod) => ({ default: mod.IcosaIcon })), + IFixIt: () => + import("@/icons/IFixIt").then((mod) => ({ default: mod.IFixIcon })), + javascript: () => + import("@/icons/JSicon").then((mod) => ({ default: mod.JSIcon })), + LangChain: () => + import("@/icons/LangChain").then((mod) => ({ default: mod.LangChainIcon })), + Langwatch: () => + import("@/icons/Langwatch").then((mod) => ({ default: mod.LangwatchIcon })), + LMStudio: () => + import("@/icons/LMStudio").then((mod) => ({ default: mod.LMStudioIcon })), + Maritalk: () => + import("@/icons/Maritalk").then((mod) => ({ default: mod.MaritalkIcon })), + Mem0: () => import("@/icons/Mem0").then((mod) => ({ default: mod.Mem0 })), + Meta: () => import("@/icons/Meta").then((mod) => ({ default: mod.MetaIcon })), + Midjourney: () => + import("@/icons/Midjorney").then((mod) => ({ + default: mod.MidjourneyIcon, + })), + Milvus: () => + import("@/icons/Milvus").then((mod) => ({ default: mod.MilvusIcon })), + Mistral: () => + import("@/icons/mistral").then((mod) => ({ default: mod.MistralIcon })), + MongoDB: () => + import("@/icons/MongoDB").then((mod) => ({ default: mod.MongoDBIcon })), + Needle: () => + import("@/icons/Needle").then((mod) => ({ default: mod.NeedleIcon })), + NotDiamond: () => + import("@/icons/NotDiamond").then((mod) => ({ + default: mod.NotDiamondIcon, + })), + Notion: () => + import("@/icons/Notion").then((mod) => ({ default: mod.NotionIcon })), + Novita: () => + import("@/icons/Novita").then((mod) => ({ default: mod.NovitaIcon })), + NVIDIA: () => + import("@/icons/Nvidia").then((mod) => ({ default: mod.NvidiaIcon })), + Olivya: () => + import("@/icons/Olivya").then((mod) => ({ default: mod.OlivyaIcon })), + Ollama: () => + import("@/icons/Ollama").then((mod) => ({ default: mod.OllamaIcon })), + OpenAI: () => + import("@/icons/OpenAi").then((mod) => ({ default: mod.OpenAiIcon })), + OpenRouter: () => + import("@/icons/OpenRouter").then((mod) => ({ + default: mod.OpenRouterIcon, + })), + OpenSearch: () => + import("@/icons/OpenSearch").then((mod) => ({ default: mod.OpenSearch })), + Perplexity: () => + import("@/icons/Perplexity").then((mod) => ({ + default: mod.PerplexityIcon, + })), + Pinecone: () => + import("@/icons/Pinecone").then((mod) => ({ default: mod.PineconeIcon })), + Postgres: () => + import("@/icons/Postgres").then((mod) => ({ default: mod.PostgresIcon })), + Python: () => + import("@/icons/Python").then((mod) => ({ default: mod.PythonIcon })), + QDrant: () => + import("@/icons/QDrant").then((mod) => ({ default: mod.QDrantIcon })), + QianFanChat: () => + import("@/icons/QianFanChat").then((mod) => ({ + default: mod.QianFanChatIcon, + })), + Redis: () => + import("@/icons/Redis").then((mod) => ({ default: mod.RedisIcon })), + SambaNova: () => + import("@/icons/SambaNova").then((mod) => ({ default: mod.SambaNovaIcon })), + ScrapeGraph: () => + import("@/icons/ScrapeGraphAI").then((mod) => ({ + default: mod.ScrapeGraph, + })), + SearchAPI: () => + import("@/icons/SearchAPI").then((mod) => ({ default: mod.SearchAPIIcon })), + SearchLexical: () => + import("@/icons/SearchLexical").then((mod) => ({ + default: mod.SearchLexicalIcon, + })), + SearchHybrid: () => + import("@/icons/SearchHybrid").then((mod) => ({ + default: mod.SearchHybridIcon, + })), + SearchVector: () => + import("@/icons/SearchVector").then((mod) => ({ + default: mod.SearchVectorIcon, + })), + Searx: () => + import("@/icons/Searx").then((mod) => ({ default: mod.SearxIcon })), + SerpSearch: () => + import("@/icons/SerpSearch").then((mod) => ({ + default: mod.SerpSearchIcon, + })), + Serper: () => + import("@/icons/Serper").then((mod) => ({ default: mod.SerperIcon })), + Share: () => + import("@/icons/Share").then((mod) => ({ default: mod.ShareIcon })), + Share2: () => + import("@/icons/Share2").then((mod) => ({ default: mod.Share2Icon })), + Slack: () => + import("@/icons/Slack/SlackIcon").then((mod) => ({ default: mod.default })), + Spider: () => + import("@/icons/Spider").then((mod) => ({ default: mod.SpiderIcon })), + Streamlit: () => + import("@/icons/Streamlit").then((mod) => ({ default: mod.Streamlit })), + Supabase: () => + import("@/icons/supabase").then((mod) => ({ default: mod.SupabaseIcon })), + Tavily: () => + import("@/icons/Tavily").then((mod) => ({ default: mod.TavilyIcon })), + ThumbDownCustom: () => + import("@/icons/thumbs").then((mod) => ({ + default: mod.ThumbDownIconCustom, + })), + ThumbUpCustom: () => + import("@/icons/thumbs").then((mod) => ({ + default: mod.ThumbUpIconCustom, + })), + Unstructured: () => + import("@/icons/Unstructured").then((mod) => ({ + default: mod.UnstructuredIcon, + })), + Upstash: () => + import("@/icons/Upstash").then((mod) => ({ default: mod.UpstashSvgIcon })), + Vectara: () => + import("@/icons/VectaraIcon").then((mod) => ({ default: mod.VectaraIcon })), + VertexAI: () => + import("@/icons/VertexAI").then((mod) => ({ default: mod.VertexAIIcon })), + WatsonxAI: () => + import("@/icons/IBMWatsonx").then((mod) => ({ + default: mod.WatsonxAiIcon, + })), + Weaviate: () => + import("@/icons/Weaviate").then((mod) => ({ default: mod.WeaviateIcon })), + Wikipedia: () => + import("@/icons/Wikipedia/Wikipedia").then((mod) => ({ + default: mod.default, + })), + Wolfram: () => + import("@/icons/Wolfram/Wolfram").then((mod) => ({ default: mod.default })), + xAI: () => import("@/icons/xAI").then((mod) => ({ default: mod.XAIIcon })), + YouTube: () => + import("@/icons/Youtube").then((mod) => ({ default: mod.YouTubeSvgIcon })), + ZepMemory: () => + import("@/icons/ZepMemory").then((mod) => ({ default: mod.ZepMemoryIcon })), +}; diff --git a/src/frontend/src/icons/lucideIcons.ts b/src/frontend/src/icons/lucideIcons.ts new file mode 100644 index 000000000..7b03a979e --- /dev/null +++ b/src/frontend/src/icons/lucideIcons.ts @@ -0,0 +1,467 @@ +import { + AlertCircle, + AlertTriangle, + ArrowBigUp, + ArrowLeft, + ArrowRight, + ArrowRightLeft, + ArrowUpRight, + ArrowUpToLine, + AudioLines, + Bell, + Binary, + Blocks, + BookMarked, + BookOpenText, + BookmarkPlus, + Bot, + BotMessageSquare, + Boxes, + Braces, + BrainCircuit, + ChartNetwork, + Check, + CheckCheck, + CheckCircle2, + ChevronDown, + ChevronLeft, + ChevronRight, + ChevronRightSquare, + ChevronUp, + ChevronsDownUp, + ChevronsLeft, + ChevronsRight, + ChevronsUpDown, + ChevronsUpDownIcon, + Circle, + CircleCheckBig, + CircleDot, + CircleOff, + Clipboard, + CloudDownload, + Code, + Code2, + CodeXml, + Cog, + Columns2, + Combine, + Command, + Compass, + Copy, + CopyPlus, + CornerDownLeft, + Cpu, + Database, + DatabaseZap, + Delete, + DollarSign, + Dot, + Download, + DownloadCloud, + Edit, + Ellipsis, + EllipsisVertical, + Eraser, + ExternalLink, + Eye, + EyeOff, + File, + FileChartColumn, + FileClock, + FileCode2, + FileDown, + FileJson, + FilePen, + FileQuestion, + FileSearch, + FileSearch2, + FileSliders, + FileText, + FileType, + FileType2, + FileUp, + Filter, + FlaskConical, + FolderIcon, + FolderPlus, + FolderPlusIcon, + FolderSync, + FolderUp, + FormInput, + Forward, + Gift, + GitBranchPlus, + GitFork, + GithubIcon, + Globe, + GripVertical, + Group, + Hammer, + Heart, + HelpCircle, + Home, + Image, + Infinity, + Info, + InstagramIcon, + Key, + Keyboard, + Laptop2, + Layers, + LayoutGrid, + LayoutPanelTop, + Link, + Link2, + List, + ListChecks, + ListFilter, + ListOrdered, + ListX, + Loader2, + Lock, + LockOpen, + LogIn, + LogOut, + LucideSend, + Maximize2, + Menu, + MessageCircle, + MessageSquare, + MessageSquareMore, + MessagesSquare, + Mic, + Mic2, + MicOff, + Minimize2, + Minus, + Monitor, + Moon, + MoonIcon, + MoreHorizontal, + Network, + Newspaper, + NotebookPen, + OctagonAlert, + OptionIcon, + Package2, + Palette, + PanelLeftClose, + PanelLeftOpen, + PanelRightClose, + PanelRightOpen, + Paperclip, + PaperclipIcon, + Pen, + Pencil, + PencilLine, + PencilRuler, + PieChart, + Pin, + Plane, + Play, + Plus, + PlusCircle, + PlusSquare, + PocketKnife, + Radio, + Redo, + RefreshCcw, + RefreshCcwDot, + Repeat, + Replace, + RotateCcw, + Save, + SaveAll, + Scan, + ScanEye, + Scissors, + ScreenShare, + Scroll, + ScrollText, + Search, + Settings, + Settings2, + Share, + Share2, + Shield, + Sigma, + Sliders, + SlidersHorizontal, + Snowflake, + Sparkles, + Square, + SquareArrowOutUpRight, + SquareCode, + SquarePen, + SquarePlay, + StickyNote, + Store, + Sun, + SunIcon, + Table, + Tags, + TerminalIcon, + TerminalSquare, + TextCursorInput, + TextSearch, + TextSearchIcon, + ThumbsDown, + ThumbsUp, + ToyBrick, + Trash2, + Type, + Undo, + Ungroup, + UnlinkIcon, + Unplug, + Upload, + User, + UserCog2, + UserMinus2, + UserPlus2, + Users, + Users2, + Variable, + Wand2, + Workflow, + Wrench, + X, + XCircle, + Zap, + ZoomIn, + ZoomOut, +} from "lucide-react"; + +// Create a map of eagerly loaded Lucide icons +export const lucideIcons = { + AlertCircle, + AlertTriangle, + ArrowBigUp, + ArrowLeft, + ArrowRight, + ArrowRightLeft, + ArrowUpRight, + ArrowUpToLine, + AudioLines, + Bell, + Binary, + Blocks, + BookMarked, + BookOpenText, + BookmarkPlus, + Bot, + BotMessageSquare, + Boxes, + Braces, + BrainCircuit, + ChartNetwork, + Check, + CheckCheck, + CheckCircle2, + ChevronDown, + ChevronLeft, + ChevronRight, + ChevronRightSquare, + ChevronUp, + ChevronsDownUp, + ChevronsLeft, + ChevronsRight, + ChevronsUpDown, + ChevronsUpDownIcon, + Circle, + CircleCheckBig, + CircleDot, + CircleOff, + Clipboard, + CloudDownload, + Code, + Code2, + CodeXml, + Cog, + Columns2, + Combine, + Command, + Compass, + Copy, + CopyPlus, + CornerDownLeft, + Cpu, + Database, + DatabaseZap, + Delete, + DollarSign, + Dot, + Download, + DownloadCloud, + Edit, + Ellipsis, + EllipsisVertical, + Eraser, + ExternalLink, + Eye, + EyeOff, + File, + FileChartColumn, + FileClock, + FileCode2, + FileDown, + FileJson, + FilePen, + FileQuestion, + FileSearch, + FileSearch2, + FileSliders, + FileText, + FileType, + FileType2, + FileUp, + Filter, + FlaskConical, + FolderIcon, + FolderPlus, + FolderPlusIcon, + FolderSync, + FolderUp, + FormInput, + Forward, + Gift, + GitBranchPlus, + GitFork, + GithubIcon, + Globe, + GripVertical, + Group, + Hammer, + Heart, + HelpCircle, + Home, + Image, + Infinity, + Info, + Key, + Keyboard, + Laptop2, + Layers, + LayoutGrid, + LayoutPanelTop, + Link, + Link2, + List, + ListChecks, + ListFilter, + ListOrdered, + ListX, + Loader2, + Lock, + LockOpen, + LogIn, + LogOut, + LucideSend, + Maximize2, + Menu, + MessageCircle, + MessageSquare, + MessageSquareMore, + MessagesSquare, + Mic, + Mic2, + MicOff, + Minimize2, + Minus, + Monitor, + Moon, + MoonIcon, + MoreHorizontal, + Network, + Newspaper, + NotebookPen, + OctagonAlert, + OptionIcon, + Package2, + Palette, + PanelLeftClose, + PanelLeftOpen, + PanelRightClose, + PanelRightOpen, + Paperclip, + PaperclipIcon, + Pen, + Pencil, + PencilLine, + PencilRuler, + PieChart, + Pin, + Plane, + Play, + Plus, + PlusCircle, + PlusSquare, + PocketKnife, + Radio, + Redo, + RefreshCcw, + RefreshCcwDot, + Repeat, + Replace, + RotateCcw, + Save, + SaveAll, + Scan, + ScanEye, + Scissors, + ScreenShare, + Scroll, + ScrollText, + Search, + Settings, + Settings2, + Share, + Share2, + Shield, + Sigma, + Sliders, + SlidersHorizontal, + Snowflake, + Sparkles, + Square, + SquareArrowOutUpRight, + SquareCode, + SquarePen, + SquarePlay, + StickyNote, + Store, + Sun, + SunIcon, + Table, + Tags, + TerminalIcon, + TerminalSquare, + TextCursorInput, + TextSearch, + TextSearchIcon, + ThumbsDown, + ThumbsUp, + ToyBrick, + Trash2, + Type, + Undo, + Ungroup, + UnlinkIcon, + Unplug, + Upload, + User, + UserCog2, + UserMinus2, + UserPlus2, + Users, + Users2, + Variable, + Wand2, + Workflow, + Wrench, + X, + XCircle, + Zap, + ZoomIn, + ZoomOut, +}; diff --git a/src/frontend/src/modals/userManagementModal/index.tsx b/src/frontend/src/modals/userManagementModal/index.tsx index f4ebaf791..31b8f8d86 100644 --- a/src/frontend/src/modals/userManagementModal/index.tsx +++ b/src/frontend/src/modals/userManagementModal/index.tsx @@ -1,3 +1,4 @@ +import IconComponent from "@/components/common/genericIconComponent"; import * as Form from "@radix-ui/react-form"; import { Eye, EyeOff } from "lucide-react"; import { useContext, useEffect, useState } from "react"; @@ -10,7 +11,6 @@ import { UserManagementType, inputHandlerEventType, } from "../../types/components"; -import { nodeIconsLucide } from "../../utils/styleUtils"; import BaseModal from "../baseModal"; export default function UserManagementModal({ @@ -25,7 +25,6 @@ export default function UserManagementModal({ onConfirm, asChild, }: UserManagementType) { - const Icon: any = nodeIconsLucide[icon]; const [pwdVisible, setPwdVisible] = useState(false); const [confirmPwdVisible, setConfirmPwdVisible] = useState(false); const [open, setOpen] = useState(false); @@ -72,8 +71,8 @@ export default function UserManagementModal({ {children} {title} -