From 22cb7bf30a07bf01ea638a19f2143c5d64a32b4f Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Tue, 25 Feb 2025 19:56:30 +0530 Subject: [PATCH 1/4] feat: add gmail component --- .../langflow/components/composio/__init__.py | 3 +- .../langflow/components/composio/gmail_api.py | 270 ++++++++++++++++++ src/frontend/src/icons/gmail/gmail.jsx | 4 + src/frontend/src/icons/gmail/gmail.svg | 1 + src/frontend/src/icons/gmail/index.tsx | 9 + src/frontend/src/utils/styleUtils.ts | 3 + 6 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 src/backend/base/langflow/components/composio/gmail_api.py create mode 100644 src/frontend/src/icons/gmail/gmail.jsx create mode 100644 src/frontend/src/icons/gmail/gmail.svg create mode 100644 src/frontend/src/icons/gmail/index.tsx diff --git a/src/backend/base/langflow/components/composio/__init__.py b/src/backend/base/langflow/components/composio/__init__.py index 24e438134a44..12d4ecac72af 100644 --- a/src/backend/base/langflow/components/composio/__init__.py +++ b/src/backend/base/langflow/components/composio/__init__.py @@ -1,3 +1,4 @@ from .composio_api import ComposioAPIComponent +from .gmail_api import GmailAPIComponent -__all__ = ["ComposioAPIComponent"] +__all__ = ["ComposioAPIComponent", "GmailAPIComponent"] diff --git a/src/backend/base/langflow/components/composio/gmail_api.py b/src/backend/base/langflow/components/composio/gmail_api.py new file mode 100644 index 000000000000..89e048749a71 --- /dev/null +++ b/src/backend/base/langflow/components/composio/gmail_api.py @@ -0,0 +1,270 @@ +# Third-party imports +import json +from typing import Any + +import requests +from composio.client.collections import AppAuthScheme +from composio.client.exceptions import NoItemsFound +from composio_langchain import Action, ComposioToolSet +from langchain_core.tools import Tool +from loguru import logger + +# Local imports +from langflow.base.langchain_utilities.model import LCToolComponent +from langflow.inputs import ( + DropdownInput, + IntInput, + LinkInput, + MessageTextInput, + MultiselectInput, + SecretStrInput, + StrInput, +) +from langflow.io import Output +from langflow.schema.message import Message + + +class GmailAPIComponent(LCToolComponent): + display_name: str = "Gmail" + description: str = "Use Gmail API to send emails, create drafts, fetch emails get user profile info" + name = "GmailAPI" + icon = "Gmail" + documentation: str = "https://docs.composio.dev" + + inputs = [ + MessageTextInput( + name="entity_id", + display_name="Entity ID", + value="default", + advanced=True, + tool_mode=True, # Enable tool mode toggle + ), + SecretStrInput( + name="api_key", + display_name="Composio API Key", + required=True, + info="Refer to https://docs.composio.dev/faq/api_key/api_key", + real_time_refresh=True, + ), + LinkInput( + name="auth_link", + display_name="Authentication Link", + value="", + info="Click to authenticate with OAuth2", + dynamic=True, + show=False, + placeholder="Click to authenticate", + ), + StrInput( + name="auth_status", + display_name="Auth Status", + value="Not Connected", + info="Current authentication status", + dynamic=True, + show=False, + refresh_button=True, + ), + MultiselectInput( + name="actions", + display_name="Actions", + required=True, + options=[], + value=[], + info="The actions to pass to agent to execute", + dynamic=True, + show=False, + ), + # Non-tool mode inputs - explicitly set show=True + DropdownInput( + name="action", + display_name="Action", + options=[], + value="", + info="Select Gmail action to perform", + show=True, + real_time_refresh=True, + ), + MessageTextInput( + name="recipient_email", + display_name="Recipient Email", + required=True, + info="Email address of the recipient", + show=False, + tool_mode=True, + ), + MessageTextInput( + name="subject", + display_name="Subject", + required=True, + info="Subject of the email", + show=False, + tool_mode=True, + ), + MessageTextInput( + name="body", + display_name="Body", + required=True, + info="Content of the email", + show=False, + tool_mode=True, + ), + IntInput( + name="max_results", + display_name="Max Results", + required=True, + info="Maximum number of emails to be returned", + show=False, + tool_mode=True, + ), + ] + + outputs = [ + Output(name="text", display_name="Result", method="process_action"), + ] + + def process_action(self) -> Message: + """Process Gmail action and return result as Message.""" + toolset = self._build_wrapper() + + try: + enum_name = getattr(Action, self.action) + result = toolset.execute_action( + action=enum_name, + params={"recipient_email": self.recipient_email, "subject": self.subject, "body": self.body}, + ) + self.status = result + return Message(text=str(result)) + except Exception as e: + logger.error(f"Error executing action: {e}") + msg = f"Failed to execute {self.action}: {e!s}" + raise ValueError(msg) from e + + def get_gmail_actions(self) -> list[str]: + url = "https://backend.composio.dev/api/v2/actions/list/all" + querystring = {"apps": "gmail"} + headers = {"x-api-key": self.api_key} + + response = requests.request("GET", url, headers=headers, params=querystring, timeout=30) + data = json.loads(response.text) + + return [item["enum"] for item in data["items"]] + + def update_build_config(self, build_config: dict, field_value: Any, field_name: str | None = None) -> dict: + dynamic_fields = ["max_results", "body", "subject", "recipient_email"] + # Always show auth status + build_config["auth_status"]["show"] = True + build_config["auth_status"]["advanced"] = False + + if field_name == "tool_mode": + if field_value: + build_config["action"]["show"] = False + build_config["actions"]["show"] = True + + gmail_actions = self.get_gmail_actions() + + if build_config["actions"]["options"] != gmail_actions: + build_config["actions"]["options"] = self.get_gmail_actions() + build_config["actions"]["value"] = [gmail_actions[0]] + + for field in dynamic_fields: + build_config[field]["show"] = False + + else: + build_config["action"]["show"] = True + build_config["actions"]["show"] = False + + if field_name == "action": + if field_value == "GMAIL_SEND_EMAIL": + # show - email sending fields + build_config["recipient_email"]["show"] = True + build_config["subject"]["show"] = True + build_config["body"]["show"] = True + + # Hide - fetch email fields + build_config["max_results"]["show"] = False + # clear value + build_config["max_results"]["value"] = "" + elif field_value == "GMAIL_FETCH_EMAILS": + # Hide - email sending fields + build_config["recipient_email"]["show"] = False + build_config["subject"]["show"] = False + build_config["body"]["show"] = False + # clear value + build_config["recipient_email"]["value"] = "" + build_config["subject"]["value"] = "" + build_config["body"]["value"] = "" + + # Show - fetch email fields + build_config["max_results"]["show"] = True + + # Handle authentication checks if API key is present + if hasattr(self, "api_key") and self.api_key != "": + build_config["action"]["options"] = ["GMAIL_SEND_EMAIL", "GMAIL_FETCH_EMAILS"] + try: + toolset = self._build_wrapper() + entity = toolset.client.get_entity(id=self.entity_id) + + try: + # Check if already connected + entity.get_connection(app="gmail") + build_config["auth_status"]["value"] = "✅" + build_config["auth_link"]["show"] = False + + except NoItemsFound: + # Handle authentication + auth_scheme = self._get_auth_scheme("gmail") + if auth_scheme.auth_mode == "OAUTH2": + build_config["auth_link"]["show"] = True + build_config["auth_link"]["advanced"] = False + auth_url = self._initiate_default_connection(entity, "gmail") + build_config["auth_link"]["value"] = auth_url + build_config["auth_status"]["value"] = "Click link to authenticate" + + except (ValueError, ConnectionError) as e: + logger.error(f"Error checking auth status: {e}") + build_config["auth_status"]["value"] = f"Error: {e!s}" + + return build_config + + def _get_auth_scheme(self, app_name: str) -> AppAuthScheme: + """Get the primary auth scheme for an app. + + Args: + app_name (str): The name of the app to get auth scheme for. + + Returns: + AppAuthScheme: The auth scheme details. + """ + toolset = self._build_wrapper() + try: + return toolset.get_auth_scheme_for_app(app=app_name.lower()) + except Exception: # noqa: BLE001 + logger.exception(f"Error getting auth scheme for {app_name}") + return None + + def _initiate_default_connection(self, entity: Any, app: str) -> str: + connection = entity.initiate_connection(app_name=app, use_composio_auth=True, force_new_integration=True) + return connection.redirectUrl + + def _build_wrapper(self) -> ComposioToolSet: + """Build the Composio toolset wrapper. + + Returns: + ComposioToolSet: The initialized toolset. + + Raises: + ValueError: If the API key is not found or invalid. + """ + try: + if not self.api_key: + msg = "Composio API Key is required" + raise ValueError(msg) + return ComposioToolSet(api_key=self.api_key) + except ValueError as e: + logger.error(f"Error building Composio wrapper: {e}") + msg = "Please provide a valid Composio API Key in the component settings" + raise ValueError(msg) from e + + async def to_toolkit(self) -> list[Tool]: + toolset = self._build_wrapper() + return toolset.get_tools(actions=self.actions) diff --git a/src/frontend/src/icons/gmail/gmail.jsx b/src/frontend/src/icons/gmail/gmail.jsx new file mode 100644 index 000000000000..ed6579adb4d3 --- /dev/null +++ b/src/frontend/src/icons/gmail/gmail.jsx @@ -0,0 +1,4 @@ +const Icon = (props) => ( + +); +export default Icon; diff --git a/src/frontend/src/icons/gmail/gmail.svg b/src/frontend/src/icons/gmail/gmail.svg new file mode 100644 index 000000000000..ec261c01d4e7 --- /dev/null +++ b/src/frontend/src/icons/gmail/gmail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/src/icons/gmail/index.tsx b/src/frontend/src/icons/gmail/index.tsx new file mode 100644 index 000000000000..3e5a81c2b1aa --- /dev/null +++ b/src/frontend/src/icons/gmail/index.tsx @@ -0,0 +1,9 @@ +import React, { forwardRef } from "react"; +import GmailIconSVG from "./gmail"; + +export const GmailIcon = forwardRef< + SVGSVGElement, + React.PropsWithChildren<{}> +>((props, ref) => { + return ; +}); \ No newline at end of file diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index 05b950e5da19..963549938b10 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -1,3 +1,4 @@ +import { GmailIcon } from "../icons/Gmail"; import { AIMLIcon } from "@/icons/AIML"; import { DuckDuckGoIcon } from "@/icons/DuckDuckGo"; import { ExaIcon } from "@/icons/Exa"; @@ -522,6 +523,7 @@ export const SIDEBAR_CATEGORIES = [ ]; export const SIDEBAR_BUNDLES = [ + { display_name: "Gmail", name: "gmail", icon: "Gmail" }, // Add apify { display_name: "Apify", name: "apify", icon: "Apify" }, { display_name: "LangChain", name: "langchain_utilities", icon: "LangChain" }, @@ -607,6 +609,7 @@ export const nodeIconsLucide: iconsType = { ChatInput: MessagesSquare, ChatOutput: MessagesSquare, //Integration Icons + Gmail: GmailIcon, LMStudio: LMStudioIcon, Notify: Bell, ListFlows: Group, From 634ab8c170d0cc1d90b87e58f95813a8e9412f43 Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Tue, 25 Feb 2025 21:35:12 +0530 Subject: [PATCH 2/4] fix: lint --- .../langflow/components/composio/gmail_api.py | 66 +++++++------------ 1 file changed, 25 insertions(+), 41 deletions(-) diff --git a/src/backend/base/langflow/components/composio/gmail_api.py b/src/backend/base/langflow/components/composio/gmail_api.py index 89e048749a71..b15ae3bd3571 100644 --- a/src/backend/base/langflow/components/composio/gmail_api.py +++ b/src/backend/base/langflow/components/composio/gmail_api.py @@ -1,4 +1,3 @@ -# Third-party imports import json from typing import Any @@ -30,6 +29,10 @@ class GmailAPIComponent(LCToolComponent): name = "GmailAPI" icon = "Gmail" documentation: str = "https://docs.composio.dev" + _local_storage: dict = { + "GMAIL_SEND_EMAIL": ["recipient_email", "subject", "body"], + "GMAIL_FETCH_EMAILS": ["max_results"], + } inputs = [ MessageTextInput( @@ -37,7 +40,7 @@ class GmailAPIComponent(LCToolComponent): display_name="Entity ID", value="default", advanced=True, - tool_mode=True, # Enable tool mode toggle + tool_mode=True, # Using tool mode field here to use tool mode feat ), SecretStrInput( name="api_key", @@ -74,7 +77,7 @@ class GmailAPIComponent(LCToolComponent): dynamic=True, show=False, ), - # Non-tool mode inputs - explicitly set show=True + # Non-tool mode inputs DropdownInput( name="action", display_name="Action", @@ -90,31 +93,17 @@ class GmailAPIComponent(LCToolComponent): required=True, info="Email address of the recipient", show=False, - tool_mode=True, ), MessageTextInput( - name="subject", - display_name="Subject", - required=True, - info="Subject of the email", - show=False, - tool_mode=True, - ), - MessageTextInput( - name="body", - display_name="Body", - required=True, - info="Content of the email", - show=False, - tool_mode=True, + name="subject", display_name="Subject", required=True, info="Subject of the email", show=False ), + MessageTextInput(name="body", display_name="Body", required=True, info="Content of the email", show=False), IntInput( name="max_results", display_name="Max Results", required=True, info="Maximum number of emails to be returned", show=False, - tool_mode=True, ), ] @@ -149,6 +138,20 @@ def get_gmail_actions(self) -> list[str]: return [item["enum"] for item in data["items"]] + def show_hide_fields(self, build_config: dict, field_value: Any): + all_fields = set() + for fields in self._local_storage.values(): + all_fields.update(fields) + + for field in all_fields: + build_config[field]["show"] = False + build_config[field]["value"] = "" + + # Show only the fields for the selected action + if field_value in self._local_storage: + for field in self._local_storage[field_value]: + build_config[field]["show"] = True + def update_build_config(self, build_config: dict, field_value: Any, field_name: str | None = None) -> dict: dynamic_fields = ["max_results", "body", "subject", "recipient_email"] # Always show auth status @@ -166,6 +169,7 @@ def update_build_config(self, build_config: dict, field_value: Any, field_name: build_config["actions"]["options"] = self.get_gmail_actions() build_config["actions"]["value"] = [gmail_actions[0]] + # hide all action input fields for field in dynamic_fields: build_config[field]["show"] = False @@ -173,29 +177,9 @@ def update_build_config(self, build_config: dict, field_value: Any, field_name: build_config["action"]["show"] = True build_config["actions"]["show"] = False + # updating fields show status based on selected action if field_name == "action": - if field_value == "GMAIL_SEND_EMAIL": - # show - email sending fields - build_config["recipient_email"]["show"] = True - build_config["subject"]["show"] = True - build_config["body"]["show"] = True - - # Hide - fetch email fields - build_config["max_results"]["show"] = False - # clear value - build_config["max_results"]["value"] = "" - elif field_value == "GMAIL_FETCH_EMAILS": - # Hide - email sending fields - build_config["recipient_email"]["show"] = False - build_config["subject"]["show"] = False - build_config["body"]["show"] = False - # clear value - build_config["recipient_email"]["value"] = "" - build_config["subject"]["value"] = "" - build_config["body"]["value"] = "" - - # Show - fetch email fields - build_config["max_results"]["show"] = True + self.show_hide_fields(build_config, field_value) # Handle authentication checks if API key is present if hasattr(self, "api_key") and self.api_key != "": From b87679ab1bed6e783dfb79da1ede3f696a7373fe Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Wed, 26 Feb 2025 00:28:38 +0530 Subject: [PATCH 3/4] fix: lint --- .../langflow/components/composio/gmail_api.py | 123 +++++++++++------- 1 file changed, 79 insertions(+), 44 deletions(-) diff --git a/src/backend/base/langflow/components/composio/gmail_api.py b/src/backend/base/langflow/components/composio/gmail_api.py index b15ae3bd3571..6de7fa321f7c 100644 --- a/src/backend/base/langflow/components/composio/gmail_api.py +++ b/src/backend/base/langflow/components/composio/gmail_api.py @@ -1,14 +1,11 @@ -import json from typing import Any -import requests from composio.client.collections import AppAuthScheme from composio.client.exceptions import NoItemsFound from composio_langchain import Action, ComposioToolSet from langchain_core.tools import Tool from loguru import logger -# Local imports from langflow.base.langchain_utilities.model import LCToolComponent from langflow.inputs import ( DropdownInput, @@ -25,13 +22,23 @@ class GmailAPIComponent(LCToolComponent): display_name: str = "Gmail" - description: str = "Use Gmail API to send emails, create drafts, fetch emails get user profile info" + description: str = "Gmail API" name = "GmailAPI" icon = "Gmail" documentation: str = "https://docs.composio.dev" - _local_storage: dict = { + _actions_data: dict = { "GMAIL_SEND_EMAIL": ["recipient_email", "subject", "body"], - "GMAIL_FETCH_EMAILS": ["max_results"], + "GMAIL_FETCH_EMAILS": ["max_results", "query"], + "GMAIL_GET_PROFILE": [], + "GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID": ["message_id"], + "GMAIL_CREATE_EMAIL_DRAFT": ["recipient_email", "subject", "body"], + "GMAIL_FETCH_MESSAGE_BY_THREAD_ID": ["thread_id"], + "GMAIL_LIST_THREADS": ["max_results", "query"], + "GMAIL_REPLY_TO_THREAD": ["thread_id", "message_body", "recipient_email"], + "GMAIL_LIST_LABELS": [], + "GMAIL_CREATE_LABEL": ["label_name"], + "GMAIL_GET_PEOPLE": [], + "GMAIL_REMOVE_LABEL": ["label_id"], } inputs = [ @@ -40,7 +47,7 @@ class GmailAPIComponent(LCToolComponent): display_name="Entity ID", value="default", advanced=True, - tool_mode=True, # Using tool mode field here to use tool mode feat + tool_mode=True, # Intentionally setting tool_mode=True to make this Component support both tool and non-tool functionality # noqa: E501 ), SecretStrInput( name="api_key", @@ -77,27 +84,33 @@ class GmailAPIComponent(LCToolComponent): dynamic=True, show=False, ), - # Non-tool mode inputs + # Non tool-mode input fields DropdownInput( name="action", display_name="Action", options=[], value="", - info="Select Gmail action to perform", + info="Select Gmail action to pass to the agent", show=True, real_time_refresh=True, ), MessageTextInput( name="recipient_email", display_name="Recipient Email", - required=True, info="Email address of the recipient", show=False, + required=True, + ), + MessageTextInput( + name="subject", display_name="Subject", info="Subject of the email", show=False, required=True ), MessageTextInput( - name="subject", display_name="Subject", required=True, info="Subject of the email", show=False + name="body", + display_name="Body", + required=True, + info="Content of the email", + show=False, ), - MessageTextInput(name="body", display_name="Body", required=True, info="Content of the email", show=False), IntInput( name="max_results", display_name="Max Results", @@ -105,21 +118,60 @@ class GmailAPIComponent(LCToolComponent): info="Maximum number of emails to be returned", show=False, ), + StrInput( + name="message_id", + display_name="Message ID", + info="The ID of the specific email message", + show=False, + required=True, + ), + StrInput( + name="thread_id", display_name="Thread ID", info="The ID of the email thread", show=False, required=True + ), + StrInput( + name="query", + display_name="Query", + info="Search query to filter emails (e.g., 'from:someone@email.com' or 'subject:hello')", + show=False, + ), + StrInput( + name="message_body", + display_name="Message Body", + info="The body content of the message to be sent", + show=False, + ), + StrInput( + name="label_name", + display_name="Label Name", + info="Name of the Gmail label to create, modify, or filter by", + show=False, + ), + StrInput( + name="label_id", + display_name="Label ID", + info="The ID of the Gmail label", + show=False, + ), ] outputs = [ - Output(name="text", display_name="Result", method="process_action"), + Output(name="text", display_name="Response", method="execute_action"), ] - def process_action(self) -> Message: - """Process Gmail action and return result as Message.""" + def execute_action(self) -> Message: + """Execute Gmail action and return response as Message.""" toolset = self._build_wrapper() try: enum_name = getattr(Action, self.action) + params = {} + if self.action in self._actions_data: + for field in self._actions_data[self.action]: + params[field] = getattr(self, field) + result = toolset.execute_action( action=enum_name, - params={"recipient_email": self.recipient_email, "subject": self.subject, "body": self.body}, + params=params, ) self.status = result return Message(text=str(result)) @@ -128,33 +180,20 @@ def process_action(self) -> Message: msg = f"Failed to execute {self.action}: {e!s}" raise ValueError(msg) from e - def get_gmail_actions(self) -> list[str]: - url = "https://backend.composio.dev/api/v2/actions/list/all" - querystring = {"apps": "gmail"} - headers = {"x-api-key": self.api_key} - - response = requests.request("GET", url, headers=headers, params=querystring, timeout=30) - data = json.loads(response.text) - - return [item["enum"] for item in data["items"]] - def show_hide_fields(self, build_config: dict, field_value: Any): all_fields = set() - for fields in self._local_storage.values(): + for fields in self._actions_data.values(): all_fields.update(fields) for field in all_fields: build_config[field]["show"] = False build_config[field]["value"] = "" - # Show only the fields for the selected action - if field_value in self._local_storage: - for field in self._local_storage[field_value]: + if field_value in self._actions_data: + for field in self._actions_data[field_value]: build_config[field]["show"] = True def update_build_config(self, build_config: dict, field_value: Any, field_name: str | None = None) -> dict: - dynamic_fields = ["max_results", "body", "subject", "recipient_email"] - # Always show auth status build_config["auth_status"]["show"] = True build_config["auth_status"]["advanced"] = False @@ -163,39 +202,35 @@ def update_build_config(self, build_config: dict, field_value: Any, field_name: build_config["action"]["show"] = False build_config["actions"]["show"] = True - gmail_actions = self.get_gmail_actions() - - if build_config["actions"]["options"] != gmail_actions: - build_config["actions"]["options"] = self.get_gmail_actions() - build_config["actions"]["value"] = [gmail_actions[0]] + gmail_actions = list(self._actions_data.keys()) + build_config["actions"]["options"] = gmail_actions + build_config["actions"]["value"] = [gmail_actions[0]] - # hide all action input fields - for field in dynamic_fields: + all_fields = set() + for fields in self._actions_data.values(): + all_fields.update(fields) + for field in all_fields: build_config[field]["show"] = False else: build_config["action"]["show"] = True build_config["actions"]["show"] = False - # updating fields show status based on selected action if field_name == "action": self.show_hide_fields(build_config, field_value) - # Handle authentication checks if API key is present if hasattr(self, "api_key") and self.api_key != "": - build_config["action"]["options"] = ["GMAIL_SEND_EMAIL", "GMAIL_FETCH_EMAILS"] + build_config["action"]["options"] = list(self._actions_data.keys()) try: toolset = self._build_wrapper() entity = toolset.client.get_entity(id=self.entity_id) try: - # Check if already connected entity.get_connection(app="gmail") build_config["auth_status"]["value"] = "✅" build_config["auth_link"]["show"] = False except NoItemsFound: - # Handle authentication auth_scheme = self._get_auth_scheme("gmail") if auth_scheme.auth_mode == "OAUTH2": build_config["auth_link"]["show"] = True From 909a06c5d5f7651d8daa8b45bd42d573ea2d665e Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Wed, 26 Feb 2025 00:52:58 +0530 Subject: [PATCH 4/4] fix: pretty frontend --- src/frontend/src/icons/gmail/gmail.jsx | 28 +++++++++++++++++++++++++- src/frontend/src/icons/gmail/index.tsx | 11 +++++----- src/frontend/src/utils/styleUtils.ts | 2 +- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/frontend/src/icons/gmail/gmail.jsx b/src/frontend/src/icons/gmail/gmail.jsx index ed6579adb4d3..d92728117f22 100644 --- a/src/frontend/src/icons/gmail/gmail.jsx +++ b/src/frontend/src/icons/gmail/gmail.jsx @@ -1,4 +1,30 @@ const Icon = (props) => ( - + + + + + + + ); export default Icon; diff --git a/src/frontend/src/icons/gmail/index.tsx b/src/frontend/src/icons/gmail/index.tsx index 3e5a81c2b1aa..87ea0c51907b 100644 --- a/src/frontend/src/icons/gmail/index.tsx +++ b/src/frontend/src/icons/gmail/index.tsx @@ -1,9 +1,8 @@ import React, { forwardRef } from "react"; import GmailIconSVG from "./gmail"; -export const GmailIcon = forwardRef< - SVGSVGElement, - React.PropsWithChildren<{}> ->((props, ref) => { - return ; -}); \ No newline at end of file +export const GmailIcon = forwardRef>( + (props, ref) => { + return ; + }, +); diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index 963549938b10..fff41c4a8334 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -1,4 +1,3 @@ -import { GmailIcon } from "../icons/Gmail"; import { AIMLIcon } from "@/icons/AIML"; import { DuckDuckGoIcon } from "@/icons/DuckDuckGo"; import { ExaIcon } from "@/icons/Exa"; @@ -16,6 +15,7 @@ import { ZepMemoryIcon } from "@/icons/ZepMemory"; import { AthenaIcon } from "@/icons/athena/index"; import { freezeAllIcon } from "@/icons/freezeAll"; import { GlobeOkIcon } from "@/icons/globe-ok"; +import { GmailIcon } from "@/icons/gmail"; import { ThumbDownIconCustom, ThumbUpIconCustom } from "@/icons/thumbs"; import { TwitterLogoIcon } from "@radix-ui/react-icons"; import {