diff --git a/web/src/app/admin/connectors/[connector]/AddConnectorPage.tsx b/web/src/app/admin/connectors/[connector]/AddConnectorPage.tsx index c7999f7dfd5..a9ac1a0411f 100644 --- a/web/src/app/admin/connectors/[connector]/AddConnectorPage.tsx +++ b/web/src/app/admin/connectors/[connector]/AddConnectorPage.tsx @@ -498,172 +498,166 @@ export default function AddConnector({ } }} > - {(formikProps) => { - return ( -
- {popup} - - {uploading && } - - {creatingConnector && } - - } - title={displayName} - farRightElement={undefined} - /> - - {formStep == 0 && ( - - Select a credential - - {connector == ValidSources.Gmail ? ( - - ) : ( - <> - - {!createCredentialFormToggle && ( -
- {/* Button to pop up a form to manually enter credentials */} - - {/* Button to sign in via OAuth */} - {oauthSupportedSources.includes(connector) && - (NEXT_PUBLIC_CLOUD_ENABLED || - NEXT_PUBLIC_TEST_ENV) && ( - - )} -
- )} - - {createCredentialFormToggle && ( - - setCreateCredentialFormToggle(false) - } + } else { + setCreateCredentialFormToggle( + (createConnectorToggle) => !createConnectorToggle + ); + } + }} > - {oauthDetailsLoading ? ( - - ) : ( - <> - - Create a {getSourceDisplayName(connector)}{" "} - credential - - {oauthDetails && oauthDetails.oauth_enabled ? ( - - ) : ( - - setCreateCredentialFormToggle(false) - } - /> - )} - + Create New + + {/* Button to sign in via OAuth */} + {oauthSupportedSources.includes(connector) && + (NEXT_PUBLIC_CLOUD_ENABLED || NEXT_PUBLIC_TEST_ENV) && ( + )} - - )} - - )} -
- )} - - {formStep == 1 && ( - - - - )} - - {formStep === 2 && ( - - - - )} - - -
- ); - }} + + )} + + {createCredentialFormToggle && ( + + setCreateCredentialFormToggle(false) + } + > + {oauthDetailsLoading ? ( + + ) : ( + <> + + Create a {getSourceDisplayName(connector)}{" "} + credential + + {oauthDetails && oauthDetails.oauth_enabled ? ( + + ) : ( + + setCreateCredentialFormToggle(false) + } + /> + )} + + )} + + )} + + )} + + )} + + {formStep == 1 && ( + + + + )} + + {formStep === 2 && ( + + + + )} + + + + )} ); } diff --git a/web/src/app/admin/connectors/[connector]/pages/Advanced.tsx b/web/src/app/admin/connectors/[connector]/pages/Advanced.tsx index 4a4f417a7dc..d366efdec65 100644 --- a/web/src/app/admin/connectors/[connector]/pages/Advanced.tsx +++ b/web/src/app/admin/connectors/[connector]/pages/Advanced.tsx @@ -3,7 +3,7 @@ import NumberInput from "./ConnectorInput/NumberInput"; import { TextFormField } from "@/components/Field"; import { TrashIcon } from "@/components/icons/icons"; -const AdvancedFormPage = () => { +export default function AdvancedFormPage() { return (

@@ -42,6 +42,4 @@ const AdvancedFormPage = () => {

); -}; - -export default AdvancedFormPage; +} diff --git a/web/src/app/admin/connectors/[connector]/pages/DynamicConnectorCreationForm.tsx b/web/src/app/admin/connectors/[connector]/pages/DynamicConnectorCreationForm.tsx index 1dc9dd47f7c..86b3b232ba7 100644 --- a/web/src/app/admin/connectors/[connector]/pages/DynamicConnectorCreationForm.tsx +++ b/web/src/app/admin/connectors/[connector]/pages/DynamicConnectorCreationForm.tsx @@ -1,4 +1,4 @@ -import React, { FC, useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import CredentialSubText from "@/components/credentials/CredentialFields"; import { ConnectionConfiguration } from "@/lib/connectors/connectors"; import { TextFormField } from "@/components/Field"; @@ -17,12 +17,12 @@ export interface DynamicConnectionFormProps { currentCredential: Credential | null; } -const DynamicConnectionForm: FC = ({ +export default function DynamicConnectionForm({ config, values, connector, currentCredential, -}) => { +}: DynamicConnectionFormProps) { const { setFieldValue } = useFormikContext(); // Get Formik's context functions const [showAdvancedOptions, setShowAdvancedOptions] = useState(false); @@ -97,6 +97,4 @@ const DynamicConnectionForm: FC = ({ )} ); -}; - -export default DynamicConnectionForm; +} diff --git a/web/src/components/icons/icons.tsx b/web/src/components/icons/icons.tsx index 8b5f6b30fb9..92cb416949e 100644 --- a/web/src/components/icons/icons.tsx +++ b/web/src/components/icons/icons.tsx @@ -30,6 +30,7 @@ import { FiCpu, FiInfo, FiBarChart2, + FiMail, } from "react-icons/fi"; import { SiBookstack } from "react-icons/si"; import { StaticImageData } from "next/image"; @@ -1006,6 +1007,11 @@ export const LightSettingsIcon = ({ ); }; +export const EmailIcon = ({ + size = 24, + className = defaultTailwindCSSBlue, +}: IconProps) => ; + // COMPANY LOGOS export const LoopioIcon = ({ diff --git a/web/src/lib/connectors/connectors.tsx b/web/src/lib/connectors/connectors.tsx index 3a871031764..04ca5074a9e 100644 --- a/web/src/lib/connectors/connectors.tsx +++ b/web/src/lib/connectors/connectors.tsx @@ -1333,6 +1333,39 @@ For example, specifying .*-support.* as a "channel" will cause the connector to ], advanced_values: [], }, + imap: { + description: "Configure Email connector", + values: [ + { + type: "text", + query: "Enter the IMAP server host:", + label: "IMAP Server Host", + name: "host", + optional: false, + description: + "The IMAP server hostname (e.g., imap.gmail.com, outlook.office365.com)", + }, + { + type: "number", + query: "Enter the IMAP server port:", + label: "IMAP Server Port", + name: "port", + optional: true, + default: 993, + description: "The IMAP server port (default: 993 for SSL)", + }, + { + type: "list", + query: "Enter mailboxes to include:", + label: "Mailboxes", + name: "mailboxes", + optional: true, + description: + "Specify mailboxes to index (e.g., INBOX, Sent, Drafts). Leave empty to index all mailboxes.", + }, + ], + advanced_values: [], + }, }; export function createConnectorInitialValues( connector: ConfigurableSources @@ -1631,3 +1664,9 @@ export interface MediaWikiConfig extends MediaWikiBaseConfig { } export interface WikipediaConfig extends MediaWikiBaseConfig {} + +export interface ImapConfig { + host: string; + port?: number; + mailboxes?: string[]; +} diff --git a/web/src/lib/connectors/credentials.ts b/web/src/lib/connectors/credentials.ts index 99c6713508b..c4f0371e771 100644 --- a/web/src/lib/connectors/credentials.ts +++ b/web/src/lib/connectors/credentials.ts @@ -244,6 +244,11 @@ export interface HighspotCredentialJson { highspot_secret: string; } +export interface ImapCredentialJson { + imap_username: string; + imap_password: string; +} + export const credentialTemplates: Record = { github: { github_access_token: "" } as GithubCredentialJson, gitlab: { @@ -400,6 +405,10 @@ export const credentialTemplates: Record = { highspot_key: "", highspot_secret: "", } as HighspotCredentialJson, + imap: { + imap_username: "", + imap_password: "", + } as ImapCredentialJson, }; export const credentialDisplayNames: Record = { @@ -485,6 +494,10 @@ export const credentialDisplayNames: Record = { r2_access_key_id: "R2 Access Key ID", r2_secret_access_key: "R2 Secret Access Key", + // IMAP + imap_username: "IMAP Username", + imap_password: "IMAP Password", + // S3 aws_access_key_id: "AWS Access Key ID", aws_secret_access_key: "AWS Secret Access Key", diff --git a/web/src/lib/sources.ts b/web/src/lib/sources.ts index 48a5c44ddaf..61c622446bb 100644 --- a/web/src/lib/sources.ts +++ b/web/src/lib/sources.ts @@ -44,6 +44,7 @@ import { FileIcon2, GitbookIcon, HighspotIcon, + EmailIcon, } from "@/components/icons/icons"; import { ValidSources } from "./types"; import { SourceCategory, SourceMetadata } from "./search/interfaces"; @@ -345,6 +346,11 @@ export const SOURCE_METADATA_MAP: SourceMap = { category: SourceCategory.Wiki, docs: "https://docs.onyx.app/connectors/highspot", }, + imap: { + icon: EmailIcon, + displayName: "Email", + category: SourceCategory.Messaging, + }, // currently used for the Internet Search tool docs, which is why // a globe is used not_applicable: { diff --git a/web/src/lib/types.ts b/web/src/lib/types.ts index 70912588982..1555f3b20a8 100644 --- a/web/src/lib/types.ts +++ b/web/src/lib/types.ts @@ -434,6 +434,7 @@ export enum ValidSources { Airtable = "airtable", Gitbook = "gitbook", Highspot = "highspot", + Imap = "imap", // Federated Connectors FederatedSlack = "federated_slack",