From 83d30f8b76265397d945b44af73929cdb62b5ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Tue, 7 Apr 2026 08:43:48 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20Send=20email=20from=20UI=20=E2=80=94=20?= =?UTF-8?q?inline=20reply=20composer=20&=20SendEmail=20mutation=20(#19363)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - **Inline email reply**: Replace external email client redirects (Gmail/Outlook deeplinks) with an in-app email composer. Users can reply to email threads directly from the email thread widget or via the command menu. - **SendEmail GraphQL mutation**: New backend mutation that reuses `EmailComposerService` for body sanitization, recipient validation, and SMTP dispatch via the existing outbound messaging infrastructure. - **Side panel compose page**: Command menu "Reply" action now opens a side-panel compose email page with pre-filled To, Subject, and In-Reply-To fields. ### Backend - `SendEmailResolver` with `SendEmailInput` / `SendEmailOutputDTO` - `SendEmailModule` wired into `CoreEngineModule` - Reuses `EmailComposerService` + `MessagingMessageOutboundService` ### Frontend - `EmailComposer` / `EmailComposerFields` components - `useSendEmail`, `useReplyContext`, `useEmailComposerState` hooks - `useOpenComposeEmailInSidePanel` + `SidePanelComposeEmailPage` - `EmailThreadWidget` inline Reply bar with toggle composer - `ReplyToEmailThreadCommand` now opens side-panel instead of external links ### Seeds - Added `handle` field to message participant seeds for realistic email addresses - Seed `connectedAccount` and `messageChannel` in correct batch order ## Test plan - [ ] Open an email thread on a person/company record → verify "Reply..." bar appears below the last message - [ ] Click "Reply..." → composer opens inline with pre-filled To and Subject - [ ] Type a message and click Send → email is sent via SMTP, composer closes - [ ] Use command menu Reply action → side panel opens with compose email page - [ ] Verify Send/Cancel buttons work correctly in side panel - [ ] Test with Cc/Bcc toggle in composer fields - [ ] Verify error handling: invalid recipients, missing connected account Made with [Cursor](https://cursor.com) --------- Co-authored-by: Claude Opus 4.6 --- .github/workflows/ci-front.yaml | 2 +- .../src/metadata/generated/schema.graphql | 45 +- .../src/metadata/generated/schema.ts | 106 +-- .../src/metadata/generated/types.ts | 620 ++++++++++-------- packages/twenty-front/codegen-metadata.cjs | 1 + packages/twenty-front/codegen.cjs | 3 +- .../src/generated-metadata/graphql.ts | 31 + .../emails/components/ComposeEmailButton.tsx | 91 +++ .../emails/components/EmailComposer.tsx | 81 +++ .../emails/components/EmailComposerFields.tsx | 117 ++++ .../emails/components/EmailThreadMessage.tsx | 16 +- .../emails/components/EmailsCard.tsx | 72 +- .../emails/graphql/mutations/sendEmail.ts | 10 + .../emails/hooks/useEmailComposerState.ts | 90 +++ .../activities/emails/hooks/useEmailThread.ts | 72 +- .../emails/hooks/useFirstConnectedAccount.ts | 17 + .../emails/hooks/useReplyContext.ts | 63 ++ .../activities/emails/hooks/useSendEmail.ts | 94 +++ .../emails/types/EmailComposerState.ts | 3 + .../emails/types/EmailThreadMessage.ts | 1 + .../activities/emails/types/ReplyContext.ts | 16 + ...RecordPageSidePanelCommandMenuDropdown.tsx | 35 +- ...EngineComponentKeyHeadlessComponentMap.tsx | 2 + .../global/components/ComposeEmailCommand.tsx | 31 + ...avigateToNextRecordSingleRecordCommand.tsx | 13 +- ...ateToPreviousRecordSingleRecordCommand.tsx | 11 +- .../components/ReplyToEmailThreadCommand.tsx | 68 +- .../CommandMenuContextProviderServerItems.tsx | 9 +- .../PageLayoutRecordPageRenderer.tsx | 44 +- .../components/EmailThreadComposer.tsx | 137 ++++ .../components/EmailThreadWidget.tsx | 69 +- .../components/SidePanelRecordInfo.tsx | 63 +- .../constants/SidePanelPagesConfig.tsx | 3 +- .../hooks/useOpenComposeEmailInSidePanel.ts | 78 +++ .../components/SidePanelComposeEmailPage.tsx | 103 +++ ...seEmailConnectedAccountIdComponentState.ts | 9 + ...poseEmailDefaultInReplyToComponentState.ts | 9 + ...omposeEmailDefaultSubjectComponentState.ts | 9 + .../composeEmailDefaultToComponentState.ts | 9 + .../sidePanelWidgetFooterActionsState.ts | 9 + .../side-panel/types/SidePanelFooterAction.ts | 12 + ...compose-email-command-menu-item.command.ts | 123 ++++ .../1-21-upgrade-version-command.module.ts | 3 + .../upgrade.command.ts | 3 + .../engine/core-modules/core-engine.module.ts | 2 + .../email-tool/email-composer.service.ts | 58 ++ .../tool/tools/email-tool/send-email-tool.ts | 29 +- .../email-tool/types/composed-email.type.ts | 2 + .../enums/engine-component-key.enum.ts | 1 + ...message-participant-data-seeds.constant.ts | 14 +- .../data/services/dev-seeder-data.service.ts | 20 +- .../standard-command-menu-item.constant.ts | 14 + .../gmail-message-outbound.service.ts | 24 +- .../imap-smtp-message-outbound.service.ts | 8 +- .../microsoft-message-outbound.service.ts | 41 +- .../dtos/send-email-output.dto.ts | 10 + .../dtos/send-email.input.ts | 25 + .../message-outbound-driver.interface.ts | 3 +- .../messaging-send-manager.module.ts | 10 +- .../resolvers/send-email.resolver.ts | 97 +++ .../send-email.module.ts | 16 + .../messaging-message-outbound.service.ts | 3 +- .../services/send-email.service.ts | 56 ++ .../sent-message-persistence.service.ts | 185 ++++++ .../types/send-message-input.type.ts | 1 + .../types/send-message-result.type.ts | 5 + .../extract-message-id-from-buffer.util.ts | 17 + .../twenty-shared/src/types/SidePanelPages.ts | 1 + 68 files changed, 2466 insertions(+), 579 deletions(-) create mode 100644 packages/twenty-front/src/modules/activities/emails/components/ComposeEmailButton.tsx create mode 100644 packages/twenty-front/src/modules/activities/emails/components/EmailComposer.tsx create mode 100644 packages/twenty-front/src/modules/activities/emails/components/EmailComposerFields.tsx create mode 100644 packages/twenty-front/src/modules/activities/emails/graphql/mutations/sendEmail.ts create mode 100644 packages/twenty-front/src/modules/activities/emails/hooks/useEmailComposerState.ts create mode 100644 packages/twenty-front/src/modules/activities/emails/hooks/useFirstConnectedAccount.ts create mode 100644 packages/twenty-front/src/modules/activities/emails/hooks/useReplyContext.ts create mode 100644 packages/twenty-front/src/modules/activities/emails/hooks/useSendEmail.ts create mode 100644 packages/twenty-front/src/modules/activities/emails/types/EmailComposerState.ts create mode 100644 packages/twenty-front/src/modules/activities/emails/types/ReplyContext.ts create mode 100644 packages/twenty-front/src/modules/command-menu-item/engine-command/global/components/ComposeEmailCommand.tsx create mode 100644 packages/twenty-front/src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx create mode 100644 packages/twenty-front/src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts create mode 100644 packages/twenty-front/src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx create mode 100644 packages/twenty-front/src/modules/side-panel/pages/compose-email/states/composeEmailConnectedAccountIdComponentState.ts create mode 100644 packages/twenty-front/src/modules/side-panel/pages/compose-email/states/composeEmailDefaultInReplyToComponentState.ts create mode 100644 packages/twenty-front/src/modules/side-panel/pages/compose-email/states/composeEmailDefaultSubjectComponentState.ts create mode 100644 packages/twenty-front/src/modules/side-panel/pages/compose-email/states/composeEmailDefaultToComponentState.ts create mode 100644 packages/twenty-front/src/modules/ui/layout/side-panel/states/sidePanelWidgetFooterActionsState.ts create mode 100644 packages/twenty-front/src/modules/ui/layout/side-panel/types/SidePanelFooterAction.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-add-compose-email-command-menu-item.command.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-outbound-manager/dtos/send-email-output.dto.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-outbound-manager/dtos/send-email.input.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-outbound-manager/resolvers/send-email.resolver.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-outbound-manager/send-email.module.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-outbound-manager/services/send-email.service.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-outbound-manager/services/sent-message-persistence.service.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-outbound-manager/types/send-message-result.type.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-outbound-manager/utils/extract-message-id-from-buffer.util.ts diff --git a/.github/workflows/ci-front.yaml b/.github/workflows/ci-front.yaml index debcdcc571..9bbb8e0ea5 100644 --- a/.github/workflows/ci-front.yaml +++ b/.github/workflows/ci-front.yaml @@ -158,7 +158,7 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest env: - NODE_OPTIONS: '--max-old-space-size=4096' + NODE_OPTIONS: '--max-old-space-size=6144' TASK_CACHE_KEY: front-task-${{ matrix.task }} strategy: matrix: diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql index c44f8d3306..ef36f1fa64 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql @@ -2639,6 +2639,7 @@ enum EngineComponentKey { TRIGGER_WORKFLOW_VERSION FRONT_COMPONENT_RENDERER REPLY_TO_EMAIL_THREAD + COMPOSE_EMAIL DELETE_SINGLE_RECORD DELETE_MULTIPLE_RECORDS RESTORE_SINGLE_RECORD @@ -2762,6 +2763,25 @@ type DuplicatedDashboard { updatedAt: String! } +type ConnectedAccountDTO { + id: UUID! + handle: String! + provider: String! + lastCredentialsRefreshedAt: DateTime + authFailedAt: DateTime + handleAliases: [String!] + scopes: [String!] + lastSignedInAt: DateTime + userWorkspaceId: UUID! + createdAt: DateTime! + updatedAt: DateTime! +} + +type SendEmailOutput { + success: Boolean! + error: String +} + type EventLogRecord { event: String! timestamp: DateTime! @@ -2930,20 +2950,6 @@ enum CalendarChannelContactAutoCreationPolicy { NONE } -type ConnectedAccountDTO { - id: UUID! - handle: String! - provider: String! - lastCredentialsRefreshedAt: DateTime - authFailedAt: DateTime - handleAliases: [String!] - scopes: [String!] - lastSignedInAt: DateTime - userWorkspaceId: UUID! - createdAt: DateTime! - updatedAt: DateTime! -} - type MessageChannel { id: UUID! visibility: MessageChannelVisibility! @@ -3552,6 +3558,7 @@ type Mutation { deleteSSOIdentityProvider(input: DeleteSsoInput!): DeleteSso! editSSOIdentityProvider(input: EditSsoInput!): EditSso! impersonate(userId: UUID!, workspaceId: UUID!): Impersonate! + sendEmail(input: SendEmailInput!): SendEmailOutput! startChannelSync(connectedAccountId: UUID!): ChannelSyncSuccess! saveImapSmtpCaldavAccount(accountOwnerId: UUID!, handle: String!, connectionParameters: EmailAccountConnectionParameters!, id: UUID): ImapSmtpCaldavConnectionSuccess! updateLabPublicFeatureFlag(input: UpdateLabPublicFeatureFlagInput!): FeatureFlag! @@ -4522,6 +4529,16 @@ input EditSsoInput { status: SSOIdentityProviderStatus! } +input SendEmailInput { + connectedAccountId: String! + to: String! + cc: String + bcc: String + subject: String! + body: String! + inReplyTo: String +} + input EmailAccountConnectionParameters { IMAP: ConnectionParameters SMTP: ConnectionParameters diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.ts b/packages/twenty-client-sdk/src/metadata/generated/schema.ts index 1ec9767dfd..1465e8ea94 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.ts @@ -2295,7 +2295,7 @@ export interface CommandMenuItem { __typename: 'CommandMenuItem' } -export type EngineComponentKey = 'NAVIGATE_TO_NEXT_RECORD' | 'NAVIGATE_TO_PREVIOUS_RECORD' | 'CREATE_NEW_RECORD' | 'DELETE_RECORDS' | 'RESTORE_RECORDS' | 'DESTROY_RECORDS' | 'ADD_TO_FAVORITES' | 'REMOVE_FROM_FAVORITES' | 'EXPORT_NOTE_TO_PDF' | 'EXPORT_RECORDS' | 'UPDATE_MULTIPLE_RECORDS' | 'MERGE_MULTIPLE_RECORDS' | 'IMPORT_RECORDS' | 'EXPORT_VIEW' | 'SEE_DELETED_RECORDS' | 'CREATE_NEW_VIEW' | 'HIDE_DELETED_RECORDS' | 'GO_TO_PEOPLE' | 'GO_TO_COMPANIES' | 'GO_TO_DASHBOARDS' | 'GO_TO_OPPORTUNITIES' | 'GO_TO_SETTINGS' | 'GO_TO_TASKS' | 'GO_TO_NOTES' | 'EDIT_RECORD_PAGE_LAYOUT' | 'EDIT_DASHBOARD_LAYOUT' | 'SAVE_DASHBOARD_LAYOUT' | 'CANCEL_DASHBOARD_LAYOUT' | 'DUPLICATE_DASHBOARD' | 'GO_TO_WORKFLOWS' | 'ACTIVATE_WORKFLOW' | 'DEACTIVATE_WORKFLOW' | 'DISCARD_DRAFT_WORKFLOW' | 'TEST_WORKFLOW' | 'SEE_ACTIVE_VERSION_WORKFLOW' | 'SEE_RUNS_WORKFLOW' | 'SEE_VERSIONS_WORKFLOW' | 'ADD_NODE_WORKFLOW' | 'TIDY_UP_WORKFLOW' | 'DUPLICATE_WORKFLOW' | 'GO_TO_RUNS' | 'SEE_VERSION_WORKFLOW_RUN' | 'SEE_WORKFLOW_WORKFLOW_RUN' | 'STOP_WORKFLOW_RUN' | 'SEE_RUNS_WORKFLOW_VERSION' | 'SEE_WORKFLOW_WORKFLOW_VERSION' | 'USE_AS_DRAFT_WORKFLOW_VERSION' | 'SEE_VERSIONS_WORKFLOW_VERSION' | 'SEARCH_RECORDS' | 'SEARCH_RECORDS_FALLBACK' | 'ASK_AI' | 'VIEW_PREVIOUS_AI_CHATS' | 'TRIGGER_WORKFLOW_VERSION' | 'FRONT_COMPONENT_RENDERER' | 'REPLY_TO_EMAIL_THREAD' | 'DELETE_SINGLE_RECORD' | 'DELETE_MULTIPLE_RECORDS' | 'RESTORE_SINGLE_RECORD' | 'RESTORE_MULTIPLE_RECORDS' | 'DESTROY_SINGLE_RECORD' | 'DESTROY_MULTIPLE_RECORDS' | 'EXPORT_FROM_RECORD_INDEX' | 'EXPORT_FROM_RECORD_SHOW' | 'EXPORT_MULTIPLE_RECORDS' +export type EngineComponentKey = 'NAVIGATE_TO_NEXT_RECORD' | 'NAVIGATE_TO_PREVIOUS_RECORD' | 'CREATE_NEW_RECORD' | 'DELETE_RECORDS' | 'RESTORE_RECORDS' | 'DESTROY_RECORDS' | 'ADD_TO_FAVORITES' | 'REMOVE_FROM_FAVORITES' | 'EXPORT_NOTE_TO_PDF' | 'EXPORT_RECORDS' | 'UPDATE_MULTIPLE_RECORDS' | 'MERGE_MULTIPLE_RECORDS' | 'IMPORT_RECORDS' | 'EXPORT_VIEW' | 'SEE_DELETED_RECORDS' | 'CREATE_NEW_VIEW' | 'HIDE_DELETED_RECORDS' | 'GO_TO_PEOPLE' | 'GO_TO_COMPANIES' | 'GO_TO_DASHBOARDS' | 'GO_TO_OPPORTUNITIES' | 'GO_TO_SETTINGS' | 'GO_TO_TASKS' | 'GO_TO_NOTES' | 'EDIT_RECORD_PAGE_LAYOUT' | 'EDIT_DASHBOARD_LAYOUT' | 'SAVE_DASHBOARD_LAYOUT' | 'CANCEL_DASHBOARD_LAYOUT' | 'DUPLICATE_DASHBOARD' | 'GO_TO_WORKFLOWS' | 'ACTIVATE_WORKFLOW' | 'DEACTIVATE_WORKFLOW' | 'DISCARD_DRAFT_WORKFLOW' | 'TEST_WORKFLOW' | 'SEE_ACTIVE_VERSION_WORKFLOW' | 'SEE_RUNS_WORKFLOW' | 'SEE_VERSIONS_WORKFLOW' | 'ADD_NODE_WORKFLOW' | 'TIDY_UP_WORKFLOW' | 'DUPLICATE_WORKFLOW' | 'GO_TO_RUNS' | 'SEE_VERSION_WORKFLOW_RUN' | 'SEE_WORKFLOW_WORKFLOW_RUN' | 'STOP_WORKFLOW_RUN' | 'SEE_RUNS_WORKFLOW_VERSION' | 'SEE_WORKFLOW_WORKFLOW_VERSION' | 'USE_AS_DRAFT_WORKFLOW_VERSION' | 'SEE_VERSIONS_WORKFLOW_VERSION' | 'SEARCH_RECORDS' | 'SEARCH_RECORDS_FALLBACK' | 'ASK_AI' | 'VIEW_PREVIOUS_AI_CHATS' | 'TRIGGER_WORKFLOW_VERSION' | 'FRONT_COMPONENT_RENDERER' | 'REPLY_TO_EMAIL_THREAD' | 'COMPOSE_EMAIL' | 'DELETE_SINGLE_RECORD' | 'DELETE_MULTIPLE_RECORDS' | 'RESTORE_SINGLE_RECORD' | 'RESTORE_MULTIPLE_RECORDS' | 'DESTROY_SINGLE_RECORD' | 'DESTROY_MULTIPLE_RECORDS' | 'EXPORT_FROM_RECORD_INDEX' | 'EXPORT_FROM_RECORD_SHOW' | 'EXPORT_MULTIPLE_RECORDS' export type CommandMenuItemAvailabilityType = 'GLOBAL' | 'RECORD_SELECTION' | 'FALLBACK' @@ -2416,6 +2416,27 @@ export interface DuplicatedDashboard { __typename: 'DuplicatedDashboard' } +export interface ConnectedAccountDTO { + id: Scalars['UUID'] + handle: Scalars['String'] + provider: Scalars['String'] + lastCredentialsRefreshedAt?: Scalars['DateTime'] + authFailedAt?: Scalars['DateTime'] + handleAliases?: Scalars['String'][] + scopes?: Scalars['String'][] + lastSignedInAt?: Scalars['DateTime'] + userWorkspaceId: Scalars['UUID'] + createdAt: Scalars['DateTime'] + updatedAt: Scalars['DateTime'] + __typename: 'ConnectedAccountDTO' +} + +export interface SendEmailOutput { + success: Scalars['Boolean'] + error?: Scalars['String'] + __typename: 'SendEmailOutput' +} + export interface EventLogRecord { event: Scalars['String'] timestamp: Scalars['DateTime'] @@ -2575,21 +2596,6 @@ export type CalendarChannelVisibility = 'METADATA' | 'SHARE_EVERYTHING' export type CalendarChannelContactAutoCreationPolicy = 'AS_PARTICIPANT_AND_ORGANIZER' | 'AS_PARTICIPANT' | 'AS_ORGANIZER' | 'NONE' -export interface ConnectedAccountDTO { - id: Scalars['UUID'] - handle: Scalars['String'] - provider: Scalars['String'] - lastCredentialsRefreshedAt?: Scalars['DateTime'] - authFailedAt?: Scalars['DateTime'] - handleAliases?: Scalars['String'][] - scopes?: Scalars['String'][] - lastSignedInAt?: Scalars['DateTime'] - userWorkspaceId: Scalars['UUID'] - createdAt: Scalars['DateTime'] - updatedAt: Scalars['DateTime'] - __typename: 'ConnectedAccountDTO' -} - export interface MessageChannel { id: Scalars['UUID'] visibility: MessageChannelVisibility @@ -2999,6 +3005,7 @@ export interface Mutation { deleteSSOIdentityProvider: DeleteSso editSSOIdentityProvider: EditSso impersonate: Impersonate + sendEmail: SendEmailOutput startChannelSync: ChannelSyncSuccess saveImapSmtpCaldavAccount: ImapSmtpCaldavConnectionSuccess updateLabPublicFeatureFlag: FeatureFlag @@ -5615,6 +5622,29 @@ export interface DuplicatedDashboardGenqlSelection{ __scalar?: boolean | number } +export interface ConnectedAccountDTOGenqlSelection{ + id?: boolean | number + handle?: boolean | number + provider?: boolean | number + lastCredentialsRefreshedAt?: boolean | number + authFailedAt?: boolean | number + handleAliases?: boolean | number + scopes?: boolean | number + lastSignedInAt?: boolean | number + userWorkspaceId?: boolean | number + createdAt?: boolean | number + updatedAt?: boolean | number + __typename?: boolean | number + __scalar?: boolean | number +} + +export interface SendEmailOutputGenqlSelection{ + success?: boolean | number + error?: boolean | number + __typename?: boolean | number + __scalar?: boolean | number +} + export interface EventLogRecordGenqlSelection{ event?: boolean | number timestamp?: boolean | number @@ -5782,22 +5812,6 @@ export interface CalendarChannelGenqlSelection{ __scalar?: boolean | number } -export interface ConnectedAccountDTOGenqlSelection{ - id?: boolean | number - handle?: boolean | number - provider?: boolean | number - lastCredentialsRefreshedAt?: boolean | number - authFailedAt?: boolean | number - handleAliases?: boolean | number - scopes?: boolean | number - lastSignedInAt?: boolean | number - userWorkspaceId?: boolean | number - createdAt?: boolean | number - updatedAt?: boolean | number - __typename?: boolean | number - __scalar?: boolean | number -} - export interface MessageChannelGenqlSelection{ id?: boolean | number visibility?: boolean | number @@ -6239,6 +6253,7 @@ export interface MutationGenqlSelection{ deleteSSOIdentityProvider?: (DeleteSsoGenqlSelection & { __args: {input: DeleteSsoInput} }) editSSOIdentityProvider?: (EditSsoGenqlSelection & { __args: {input: EditSsoInput} }) impersonate?: (ImpersonateGenqlSelection & { __args: {userId: Scalars['UUID'], workspaceId: Scalars['UUID']} }) + sendEmail?: (SendEmailOutputGenqlSelection & { __args: {input: SendEmailInput} }) startChannelSync?: (ChannelSyncSuccessGenqlSelection & { __args: {connectedAccountId: Scalars['UUID']} }) saveImapSmtpCaldavAccount?: (ImapSmtpCaldavConnectionSuccessGenqlSelection & { __args: {accountOwnerId: Scalars['UUID'], handle: Scalars['String'], connectionParameters: EmailAccountConnectionParameters, id?: (Scalars['UUID'] | null)} }) updateLabPublicFeatureFlag?: (FeatureFlagGenqlSelection & { __args: {input: UpdateLabPublicFeatureFlagInput} }) @@ -6589,6 +6604,8 @@ export interface DeleteSsoInput {identityProviderId: Scalars['UUID']} export interface EditSsoInput {id: Scalars['UUID'],status: SSOIdentityProviderStatus} +export interface SendEmailInput {connectedAccountId: Scalars['String'],to: Scalars['String'],cc?: (Scalars['String'] | null),bcc?: (Scalars['String'] | null),subject: Scalars['String'],body: Scalars['String'],inReplyTo?: (Scalars['String'] | null)} + export interface EmailAccountConnectionParameters {IMAP?: (ConnectionParameters | null),SMTP?: (ConnectionParameters | null),CALDAV?: (ConnectionParameters | null)} export interface ConnectionParameters {host: Scalars['String'],port: Scalars['Float'],username?: (Scalars['String'] | null),password: Scalars['String'],secure?: (Scalars['Boolean'] | null)} @@ -8496,6 +8513,22 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null + const ConnectedAccountDTO_possibleTypes: string[] = ['ConnectedAccountDTO'] + export const isConnectedAccountDTO = (obj?: { __typename?: any } | null): obj is ConnectedAccountDTO => { + if (!obj?.__typename) throw new Error('__typename is missing in "isConnectedAccountDTO"') + return ConnectedAccountDTO_possibleTypes.includes(obj.__typename) + } + + + + const SendEmailOutput_possibleTypes: string[] = ['SendEmailOutput'] + export const isSendEmailOutput = (obj?: { __typename?: any } | null): obj is SendEmailOutput => { + if (!obj?.__typename) throw new Error('__typename is missing in "isSendEmailOutput"') + return SendEmailOutput_possibleTypes.includes(obj.__typename) + } + + + const EventLogRecord_possibleTypes: string[] = ['EventLogRecord'] export const isEventLogRecord = (obj?: { __typename?: any } | null): obj is EventLogRecord => { if (!obj?.__typename) throw new Error('__typename is missing in "isEventLogRecord"') @@ -8624,14 +8657,6 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null - const ConnectedAccountDTO_possibleTypes: string[] = ['ConnectedAccountDTO'] - export const isConnectedAccountDTO = (obj?: { __typename?: any } | null): obj is ConnectedAccountDTO => { - if (!obj?.__typename) throw new Error('__typename is missing in "isConnectedAccountDTO"') - return ConnectedAccountDTO_possibleTypes.includes(obj.__typename) - } - - - const MessageChannel_possibleTypes: string[] = ['MessageChannel'] export const isMessageChannel = (obj?: { __typename?: any } | null): obj is MessageChannel => { if (!obj?.__typename) throw new Error('__typename is missing in "isMessageChannel"') @@ -9274,6 +9299,7 @@ export const enumEngineComponentKey = { TRIGGER_WORKFLOW_VERSION: 'TRIGGER_WORKFLOW_VERSION' as const, FRONT_COMPONENT_RENDERER: 'FRONT_COMPONENT_RENDERER' as const, REPLY_TO_EMAIL_THREAD: 'REPLY_TO_EMAIL_THREAD' as const, + COMPOSE_EMAIL: 'COMPOSE_EMAIL' as const, DELETE_SINGLE_RECORD: 'DELETE_SINGLE_RECORD' as const, DELETE_MULTIPLE_RECORDS: 'DELETE_MULTIPLE_RECORDS' as const, RESTORE_SINGLE_RECORD: 'RESTORE_SINGLE_RECORD' as const, diff --git a/packages/twenty-client-sdk/src/metadata/generated/types.ts b/packages/twenty-client-sdk/src/metadata/generated/types.ts index b9f1c07feb..1b37c43fb0 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/types.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/types.ts @@ -67,30 +67,30 @@ export default { 286, 296, 297, - 325, - 326, 327, 328, - 331, + 329, + 330, 332, 333, 334, 335, 336, 337, - 339, - 341, - 349, - 355, + 338, + 340, + 342, + 350, 356, 357, - 359, - 366, - 373, - 404, - 483, - 488, - 489 + 358, + 360, + 367, + 374, + 405, + 485, + 490, + 491 ], "types": { "BillingProductDTO": { @@ -5457,6 +5457,55 @@ export default { 1 ] }, + "ConnectedAccountDTO": { + "id": [ + 3 + ], + "handle": [ + 1 + ], + "provider": [ + 1 + ], + "lastCredentialsRefreshedAt": [ + 4 + ], + "authFailedAt": [ + 4 + ], + "handleAliases": [ + 1 + ], + "scopes": [ + 1 + ], + "lastSignedInAt": [ + 4 + ], + "userWorkspaceId": [ + 3 + ], + "createdAt": [ + 4 + ], + "updatedAt": [ + 4 + ], + "__typename": [ + 1 + ] + }, + "SendEmailOutput": { + "success": [ + 6 + ], + "error": [ + 1 + ], + "__typename": [ + 1 + ] + }, "EventLogRecord": { "event": [ 1 @@ -5496,13 +5545,13 @@ export default { }, "EventLogQueryResult": { "records": [ - 309 + 311 ], "totalCount": [ 21 ], "pageInfo": [ - 310 + 312 ], "__typename": [ 1 @@ -5629,7 +5678,7 @@ export default { }, "AISystemPromptPreview": { "sections": [ - 315 + 317 ], "estimatedTokenCount": [ 21 @@ -5676,7 +5725,7 @@ export default { }, "AgentChatThreadEdge": { "node": [ - 313 + 315 ], "cursor": [ 40 @@ -5690,7 +5739,7 @@ export default { 235 ], "edges": [ - 320 + 322 ], "__typename": [ 1 @@ -5727,10 +5776,10 @@ export default { 3 ], "evaluations": [ - 322 + 324 ], "messages": [ - 314 + 316 ], "createdAt": [ 4 @@ -5747,19 +5796,19 @@ export default { 1 ], "syncStatus": [ - 325 + 327 ], "syncStage": [ - 326 + 328 ], "visibility": [ - 327 + 329 ], "isContactAutoCreationEnabled": [ 6 ], "contactAutoCreationPolicy": [ - 328 + 330 ], "isSyncEnabled": [ 6 @@ -5790,65 +5839,27 @@ export default { "CalendarChannelSyncStage": {}, "CalendarChannelVisibility": {}, "CalendarChannelContactAutoCreationPolicy": {}, - "ConnectedAccountDTO": { - "id": [ - 3 - ], - "handle": [ - 1 - ], - "provider": [ - 1 - ], - "lastCredentialsRefreshedAt": [ - 4 - ], - "authFailedAt": [ - 4 - ], - "handleAliases": [ - 1 - ], - "scopes": [ - 1 - ], - "lastSignedInAt": [ - 4 - ], - "userWorkspaceId": [ - 3 - ], - "createdAt": [ - 4 - ], - "updatedAt": [ - 4 - ], - "__typename": [ - 1 - ] - }, "MessageChannel": { "id": [ 3 ], "visibility": [ - 331 + 332 ], "handle": [ 1 ], "type": [ - 332 + 333 ], "isContactAutoCreationEnabled": [ 6 ], "contactAutoCreationPolicy": [ - 333 + 334 ], "messageFolderImportPolicy": [ - 334 + 335 ], "excludeNonProfessionalEmails": [ 6 @@ -5857,7 +5868,7 @@ export default { 6 ], "pendingGroupEmailsAction": [ - 335 + 336 ], "isSyncEnabled": [ 6 @@ -5866,10 +5877,10 @@ export default { 4 ], "syncStatus": [ - 336 + 337 ], "syncStage": [ - 337 + 338 ], "syncStageStartedAt": [ 4 @@ -5920,7 +5931,7 @@ export default { 1 ], "pendingSyncAction": [ - 339 + 340 ], "messageChannelId": [ 3 @@ -5938,7 +5949,7 @@ export default { "MessageFolderPendingSyncAction": {}, "CollectionHash": { "collectionName": [ - 341 + 342 ], "hash": [ 1 @@ -6005,13 +6016,13 @@ export default { }, "MinimalMetadata": { "objectMetadataItems": [ - 342 - ], - "views": [ 343 ], + "views": [ + 344 + ], "collectionHashes": [ - 340 + 341 ], "__typename": [ 1 @@ -6177,7 +6188,7 @@ export default { 2, { "input": [ - 347, + 348, "GetApiKeyInput!" ] } @@ -6281,7 +6292,7 @@ export default { 32, { "input": [ - 348, + 349, "LogicFunctionIdInput!" ] } @@ -6293,7 +6304,7 @@ export default { 15, { "input": [ - 348, + 349, "LogicFunctionIdInput!" ] } @@ -6302,7 +6313,7 @@ export default { 1, { "input": [ - 348, + 349, "LogicFunctionIdInput!" ] } @@ -6385,7 +6396,7 @@ export default { 25, { "input": [ - 350, + 351, "AgentIdInput!" ] } @@ -6445,7 +6456,7 @@ export default { } ], "myMessageFolders": [ - 338, + 339, { "messageChannelId": [ 3 @@ -6453,7 +6464,7 @@ export default { } ], "myMessageChannels": [ - 330, + 331, { "connectedAccountId": [ 3 @@ -6461,13 +6472,13 @@ export default { } ], "myConnectedAccounts": [ - 329 + 309 ], "connectedAccounts": [ - 329 + 309 ], "myCalendarChannels": [ - 324, + 326, { "connectedAccountId": [ 3 @@ -6475,10 +6486,10 @@ export default { } ], "webhooks": [ - 345 + 346 ], "webhook": [ - 345, + 346, { "id": [ 3, @@ -6487,10 +6498,10 @@ export default { } ], "minimalMetadata": [ - 344 + 345 ], "chatThread": [ - 313, + 315, { "id": [ 3, @@ -6499,7 +6510,7 @@ export default { } ], "chatMessages": [ - 314, + 316, { "threadId": [ 3, @@ -6508,7 +6519,7 @@ export default { } ], "chatStreamCatchupChunks": [ - 317, + 319, { "threadId": [ 3, @@ -6517,13 +6528,13 @@ export default { } ], "getAISystemPromptPreview": [ - 316 + 318 ], "skills": [ - 312 + 314 ], "skill": [ - 312, + 314, { "id": [ 3, @@ -6532,24 +6543,24 @@ export default { } ], "chatThreads": [ - 321, + 323, { "paging": [ 39, "CursorPaging!" ], "filter": [ - 351, + 352, "AgentChatThreadFilter!" ], "sorting": [ - 354, + 355, "[AgentChatThreadSort!]!" ] } ], "agentTurns": [ - 323, + 325, { "agentId": [ 3, @@ -6558,10 +6569,10 @@ export default { } ], "eventLogs": [ - 311, + 313, { "input": [ - 358, + 359, "EventLogQueryInput!" ] } @@ -6570,7 +6581,7 @@ export default { 307, { "input": [ - 362, + 363, "PieChartDataInput!" ] } @@ -6579,7 +6590,7 @@ export default { 305, { "input": [ - 363, + 364, "LineChartDataInput!" ] } @@ -6588,7 +6599,7 @@ export default { 302, { "input": [ - 364, + 365, "BarChartDataInput!" ] } @@ -6853,7 +6864,7 @@ export default { 276, { "input": [ - 365 + 366 ] } ], @@ -6906,7 +6917,7 @@ export default { }, "LogicFunctionIdInput": { "id": [ - 349 + 350 ], "__typename": [ 1 @@ -6923,16 +6934,16 @@ export default { }, "AgentChatThreadFilter": { "and": [ - 351 + 352 ], "or": [ - 351 + 352 ], "id": [ 42 ], "updatedAt": [ - 352 + 353 ], "__typename": [ 1 @@ -6970,10 +6981,10 @@ export default { 4 ], "between": [ - 353 + 354 ], "notBetween": [ - 353 + 354 ], "__typename": [ 1 @@ -6992,14 +7003,14 @@ export default { }, "AgentChatThreadSort": { "field": [ - 355 - ], - "direction": [ 356 ], - "nulls": [ + "direction": [ 357 ], + "nulls": [ + 358 + ], "__typename": [ 1 ] @@ -7009,10 +7020,10 @@ export default { "SortNulls": {}, "EventLogQueryInput": { "table": [ - 359 + 360 ], "filters": [ - 360 + 361 ], "first": [ 21 @@ -7033,7 +7044,7 @@ export default { 1 ], "dateRange": [ - 361 + 362 ], "recordId": [ 1 @@ -7100,7 +7111,7 @@ export default { 1 ], "operationTypes": [ - 366 + 367 ], "__typename": [ 1 @@ -7112,7 +7123,7 @@ export default { 6, { "input": [ - 368, + 369, "AddQuerySubscriptionInput!" ] } @@ -7121,7 +7132,7 @@ export default { 6, { "input": [ - 369, + 370, "RemoveQueryFromEventStreamInput!" ] } @@ -7130,7 +7141,7 @@ export default { 146, { "inputs": [ - 370, + 371, "[CreateNavigationMenuItemInput!]!" ] } @@ -7139,7 +7150,7 @@ export default { 146, { "input": [ - 370, + 371, "CreateNavigationMenuItemInput!" ] } @@ -7148,7 +7159,7 @@ export default { 146, { "inputs": [ - 371, + 372, "[UpdateOneNavigationMenuItemInput!]!" ] } @@ -7157,7 +7168,7 @@ export default { 146, { "input": [ - 371, + 372, "UpdateOneNavigationMenuItemInput!" ] } @@ -7184,7 +7195,7 @@ export default { 142, { "file": [ - 373, + 374, "Upload!" ] } @@ -7193,7 +7204,7 @@ export default { 142, { "file": [ - 373, + 374, "Upload!" ] } @@ -7202,7 +7213,7 @@ export default { 142, { "file": [ - 373, + 374, "Upload!" ] } @@ -7211,7 +7222,7 @@ export default { 142, { "file": [ - 373, + 374, "Upload!" ] } @@ -7220,7 +7231,7 @@ export default { 142, { "file": [ - 373, + 374, "Upload!" ], "fieldMetadataId": [ @@ -7233,7 +7244,7 @@ export default { 142, { "file": [ - 373, + 374, "Upload!" ], "fieldMetadataUniversalIdentifier": [ @@ -7246,7 +7257,7 @@ export default { 52, { "input": [ - 374, + 375, "CreateViewFilterGroupInput!" ] } @@ -7259,7 +7270,7 @@ export default { "String!" ], "input": [ - 375, + 376, "UpdateViewFilterGroupInput!" ] } @@ -7286,7 +7297,7 @@ export default { 54, { "input": [ - 376, + 377, "CreateViewFilterInput!" ] } @@ -7295,7 +7306,7 @@ export default { 54, { "input": [ - 377, + 378, "UpdateViewFilterInput!" ] } @@ -7304,7 +7315,7 @@ export default { 54, { "input": [ - 379, + 380, "DeleteViewFilterInput!" ] } @@ -7313,7 +7324,7 @@ export default { 54, { "input": [ - 380, + 381, "DestroyViewFilterInput!" ] } @@ -7322,7 +7333,7 @@ export default { 60, { "input": [ - 381, + 382, "CreateViewInput!" ] } @@ -7335,7 +7346,7 @@ export default { "String!" ], "input": [ - 382, + 383, "UpdateViewInput!" ] } @@ -7362,7 +7373,7 @@ export default { 57, { "input": [ - 383, + 384, "CreateViewSortInput!" ] } @@ -7371,7 +7382,7 @@ export default { 57, { "input": [ - 384, + 385, "UpdateViewSortInput!" ] } @@ -7380,7 +7391,7 @@ export default { 6, { "input": [ - 386, + 387, "DeleteViewSortInput!" ] } @@ -7389,7 +7400,7 @@ export default { 6, { "input": [ - 387, + 388, "DestroyViewSortInput!" ] } @@ -7398,7 +7409,7 @@ export default { 50, { "input": [ - 388, + 389, "UpdateViewFieldInput!" ] } @@ -7407,7 +7418,7 @@ export default { 50, { "input": [ - 390, + 391, "CreateViewFieldInput!" ] } @@ -7416,7 +7427,7 @@ export default { 50, { "inputs": [ - 390, + 391, "[CreateViewFieldInput!]!" ] } @@ -7425,7 +7436,7 @@ export default { 50, { "input": [ - 391, + 392, "DeleteViewFieldInput!" ] } @@ -7434,7 +7445,7 @@ export default { 50, { "input": [ - 392, + 393, "DestroyViewFieldInput!" ] } @@ -7443,7 +7454,7 @@ export default { 59, { "input": [ - 393, + 394, "UpdateViewFieldGroupInput!" ] } @@ -7452,7 +7463,7 @@ export default { 59, { "input": [ - 395, + 396, "CreateViewFieldGroupInput!" ] } @@ -7461,7 +7472,7 @@ export default { 59, { "inputs": [ - 395, + 396, "[CreateViewFieldGroupInput!]!" ] } @@ -7470,7 +7481,7 @@ export default { 59, { "input": [ - 396, + 397, "DeleteViewFieldGroupInput!" ] } @@ -7479,7 +7490,7 @@ export default { 59, { "input": [ - 397, + 398, "DestroyViewFieldGroupInput!" ] } @@ -7488,7 +7499,7 @@ export default { 60, { "input": [ - 398, + 399, "UpsertFieldsWidgetInput!" ] } @@ -7497,7 +7508,7 @@ export default { 2, { "input": [ - 401, + 402, "CreateApiKeyInput!" ] } @@ -7506,7 +7517,7 @@ export default { 2, { "input": [ - 402, + 403, "UpdateApiKeyInput!" ] } @@ -7515,7 +7526,7 @@ export default { 2, { "input": [ - 403, + 404, "RevokeApiKeyInput!" ] } @@ -7557,7 +7568,7 @@ export default { 116, { "type": [ - 404, + 405, "AnalyticsType!" ], "name": [ @@ -7670,7 +7681,7 @@ export default { 141, { "input": [ - 405, + 406, "CreateApprovedAccessDomainInput!" ] } @@ -7679,7 +7690,7 @@ export default { 6, { "input": [ - 406, + 407, "DeleteApprovedAccessDomainInput!" ] } @@ -7688,7 +7699,7 @@ export default { 141, { "input": [ - 407, + 408, "ValidateApprovedAccessDomainInput!" ] } @@ -7697,7 +7708,7 @@ export default { 113, { "input": [ - 408, + 409, "CreatePageLayoutTabInput!" ] } @@ -7710,7 +7721,7 @@ export default { "String!" ], "input": [ - 409, + 410, "UpdatePageLayoutTabInput!" ] } @@ -7728,7 +7739,7 @@ export default { 114, { "input": [ - 410, + 411, "CreatePageLayoutInput!" ] } @@ -7741,7 +7752,7 @@ export default { "String!" ], "input": [ - 411, + 412, "UpdatePageLayoutInput!" ] } @@ -7763,7 +7774,7 @@ export default { "String!" ], "input": [ - 412, + 413, "UpdatePageLayoutWithTabsInput!" ] } @@ -7772,7 +7783,7 @@ export default { 75, { "input": [ - 416, + 417, "CreatePageLayoutWidgetInput!" ] } @@ -7785,7 +7796,7 @@ export default { "String!" ], "input": [ - 417, + 418, "UpdatePageLayoutWidgetInput!" ] } @@ -7803,7 +7814,7 @@ export default { 32, { "input": [ - 348, + 349, "LogicFunctionIdInput!" ] } @@ -7812,7 +7823,7 @@ export default { 32, { "input": [ - 418, + 419, "CreateLogicFunctionFromSourceInput!" ] } @@ -7821,7 +7832,7 @@ export default { 155, { "input": [ - 419, + 420, "ExecuteOneLogicFunctionInput!" ] } @@ -7830,7 +7841,7 @@ export default { 6, { "input": [ - 420, + 421, "UpdateLogicFunctionFromSourceInput!" ] } @@ -7839,7 +7850,7 @@ export default { 295, { "input": [ - 422, + 423, "CreateCommandMenuItemInput!" ] } @@ -7848,7 +7859,7 @@ export default { 295, { "input": [ - 423, + 424, "UpdateCommandMenuItemInput!" ] } @@ -7866,7 +7877,7 @@ export default { 252, { "input": [ - 424, + 425, "CreateFrontComponentInput!" ] } @@ -7875,7 +7886,7 @@ export default { 252, { "input": [ - 425, + 426, "UpdateFrontComponentInput!" ] } @@ -7893,7 +7904,7 @@ export default { 46, { "input": [ - 427, + 428, "CreateOneObjectInput!" ] } @@ -7902,7 +7913,7 @@ export default { 46, { "input": [ - 429, + 430, "DeleteOneObjectInput!" ] } @@ -7911,7 +7922,7 @@ export default { 46, { "input": [ - 430, + 431, "UpdateOneObjectInput!" ] } @@ -7920,7 +7931,7 @@ export default { 25, { "input": [ - 432, + 433, "CreateAgentInput!" ] } @@ -7929,7 +7940,7 @@ export default { 25, { "input": [ - 433, + 434, "UpdateAgentInput!" ] } @@ -7938,7 +7949,7 @@ export default { 25, { "input": [ - 350, + 351, "AgentIdInput!" ] } @@ -7960,7 +7971,7 @@ export default { 29, { "createRoleInput": [ - 434, + 435, "CreateRoleInput!" ] } @@ -7969,7 +7980,7 @@ export default { 29, { "updateRoleInput": [ - 435, + 436, "UpdateRoleInput!" ] } @@ -7987,7 +7998,7 @@ export default { 16, { "upsertObjectPermissionsInput": [ - 437, + 438, "UpsertObjectPermissionsInput!" ] } @@ -7996,7 +8007,7 @@ export default { 27, { "upsertPermissionFlagsInput": [ - 439, + 440, "UpsertPermissionFlagsInput!" ] } @@ -8005,7 +8016,7 @@ export default { 26, { "upsertFieldPermissionsInput": [ - 440, + 441, "UpsertFieldPermissionsInput!" ] } @@ -8014,7 +8025,7 @@ export default { 246, { "input": [ - 442, + 443, "UpsertRowLevelPermissionPredicatesInput!" ] } @@ -8045,7 +8056,7 @@ export default { 34, { "input": [ - 445, + 446, "CreateOneFieldMetadataInput!" ] } @@ -8054,7 +8065,7 @@ export default { 34, { "input": [ - 447, + 448, "UpdateOneFieldMetadataInput!" ] } @@ -8063,7 +8074,7 @@ export default { 34, { "input": [ - 449, + 450, "DeleteOneFieldInput!" ] } @@ -8072,7 +8083,7 @@ export default { 56, { "input": [ - 450, + 451, "CreateViewGroupInput!" ] } @@ -8081,7 +8092,7 @@ export default { 56, { "inputs": [ - 450, + 451, "[CreateViewGroupInput!]!" ] } @@ -8090,7 +8101,7 @@ export default { 56, { "input": [ - 451, + 452, "UpdateViewGroupInput!" ] } @@ -8099,7 +8110,7 @@ export default { 56, { "inputs": [ - 451, + 452, "[UpdateViewGroupInput!]!" ] } @@ -8108,7 +8119,7 @@ export default { 56, { "input": [ - 453, + 454, "DeleteViewGroupInput!" ] } @@ -8117,40 +8128,40 @@ export default { 56, { "input": [ - 454, + 455, "DestroyViewGroupInput!" ] } ], "updateMessageFolder": [ - 338, + 339, { "input": [ - 455, + 456, "UpdateMessageFolderInput!" ] } ], "updateMessageFolders": [ - 338, + 339, { "input": [ - 457, + 458, "UpdateMessageFoldersInput!" ] } ], "updateMessageChannel": [ - 330, + 331, { "input": [ - 458, + 459, "UpdateMessageChannelInput!" ] } ], "deleteConnectedAccount": [ - 329, + 309, { "id": [ 3, @@ -8159,34 +8170,34 @@ export default { } ], "updateCalendarChannel": [ - 324, + 326, { "input": [ - 460, + 461, "UpdateCalendarChannelInput!" ] } ], "createWebhook": [ - 345, + 346, { "input": [ - 462, + 463, "CreateWebhookInput!" ] } ], "updateWebhook": [ - 345, + 346, { "input": [ - 463, + 464, "UpdateWebhookInput!" ] } ], "deleteWebhook": [ - 345, + 346, { "id": [ 3, @@ -8195,10 +8206,10 @@ export default { } ], "createChatThread": [ - 313 + 315 ], "sendChatMessage": [ - 318, + 320, { "threadId": [ 3, @@ -8239,25 +8250,25 @@ export default { } ], "createSkill": [ - 312, + 314, { "input": [ - 465, + 466, "CreateSkillInput!" ] } ], "updateSkill": [ - 312, + 314, { "input": [ - 466, + 467, "UpdateSkillInput!" ] } ], "deleteSkill": [ - 312, + 314, { "id": [ 3, @@ -8266,7 +8277,7 @@ export default { } ], "activateSkill": [ - 312, + 314, { "id": [ 3, @@ -8275,7 +8286,7 @@ export default { } ], "deactivateSkill": [ - 312, + 314, { "id": [ 3, @@ -8284,7 +8295,7 @@ export default { } ], "evaluateAgentTurn": [ - 322, + 324, { "turnId": [ 3, @@ -8293,7 +8304,7 @@ export default { } ], "runEvaluationInput": [ - 323, + 325, { "agentId": [ 3, @@ -8318,7 +8329,7 @@ export default { 261, { "input": [ - 467, + 468, "GetAuthorizationUrlForSSOInput!" ] } @@ -8572,7 +8583,7 @@ export default { 217, { "input": [ - 468, + 469, "CreateApplicationRegistrationInput!" ] } @@ -8581,7 +8592,7 @@ export default { 7, { "input": [ - 469, + 470, "UpdateApplicationRegistrationInput!" ] } @@ -8608,7 +8619,7 @@ export default { 5, { "input": [ - 471, + 472, "CreateApplicationRegistrationVariableInput!" ] } @@ -8617,7 +8628,7 @@ export default { 5, { "input": [ - 472, + 473, "UpdateApplicationRegistrationVariableInput!" ] } @@ -8635,7 +8646,7 @@ export default { 7, { "file": [ - 373, + 374, "Upload!" ], "universalIdentifier": [ @@ -8731,7 +8742,7 @@ export default { 66, { "data": [ - 474, + 475, "ActivateWorkspaceInput!" ] } @@ -8740,7 +8751,7 @@ export default { 66, { "data": [ - 475, + 476, "UpdateWorkspaceInput!" ] } @@ -8755,7 +8766,7 @@ export default { 225, { "input": [ - 476, + 477, "SetupOIDCSsoInput!" ] } @@ -8764,7 +8775,7 @@ export default { 225, { "input": [ - 477, + 478, "SetupSAMLSsoInput!" ] } @@ -8773,7 +8784,7 @@ export default { 221, { "input": [ - 478, + 479, "DeleteSsoInput!" ] } @@ -8782,7 +8793,7 @@ export default { 222, { "input": [ - 479, + 480, "EditSsoInput!" ] } @@ -8800,6 +8811,15 @@ export default { ] } ], + "sendEmail": [ + 310, + { + "input": [ + 481, + "SendEmailInput!" + ] + } + ], "startChannelSync": [ 300, { @@ -8821,7 +8841,7 @@ export default { "String!" ], "connectionParameters": [ - 480, + 482, "EmailAccountConnectionParameters!" ], "id": [ @@ -8833,7 +8853,7 @@ export default { 200, { "input": [ - 482, + 484, "UpdateLabPublicFeatureFlagInput!" ] } @@ -8894,7 +8914,7 @@ export default { 6, { "role": [ - 483, + 485, "AiModelRole!" ], "modelId": [ @@ -9099,7 +9119,7 @@ export default { 68, { "input": [ - 484, + 486, "CreateOneAppTokenInput!" ] } @@ -9135,7 +9155,7 @@ export default { 6, { "workspaceMigration": [ - 486, + 488, "WorkspaceMigrationInput!" ] } @@ -9201,7 +9221,7 @@ export default { 279, { "file": [ - 373, + 374, "Upload!" ], "applicationUniversalIdentifier": [ @@ -9209,7 +9229,7 @@ export default { "String!" ], "fileFolder": [ - 489, + 491, "FileFolder!" ], "filePath": [ @@ -9315,7 +9335,7 @@ export default { 3 ], "update": [ - 372 + 373 ], "__typename": [ 1 @@ -9419,7 +9439,7 @@ export default { 3 ], "update": [ - 378 + 379 ], "__typename": [ 1 @@ -9592,7 +9612,7 @@ export default { 3 ], "update": [ - 385 + 386 ], "__typename": [ 1 @@ -9627,7 +9647,7 @@ export default { 3 ], "update": [ - 389 + 390 ], "__typename": [ 1 @@ -9703,7 +9723,7 @@ export default { 3 ], "update": [ - 394 + 395 ], "__typename": [ 1 @@ -9767,10 +9787,10 @@ export default { 3 ], "groups": [ - 399 + 400 ], "fields": [ - 400 + 401 ], "__typename": [ 1 @@ -9790,7 +9810,7 @@ export default { 6 ], "fields": [ - 400 + 401 ], "__typename": [ 1 @@ -9959,7 +9979,7 @@ export default { 3 ], "tabs": [ - 413 + 414 ], "__typename": [ 1 @@ -9982,7 +10002,7 @@ export default { 79 ], "widgets": [ - 414 + 415 ], "__typename": [ 1 @@ -10005,7 +10025,7 @@ export default { 3 ], "gridPosition": [ - 415 + 416 ], "position": [ 15 @@ -10051,7 +10071,7 @@ export default { 3 ], "gridPosition": [ - 415 + 416 ], "position": [ 15 @@ -10074,7 +10094,7 @@ export default { 3 ], "gridPosition": [ - 415 + 416 ], "position": [ 15 @@ -10143,7 +10163,7 @@ export default { 3 ], "update": [ - 421 + 422 ], "__typename": [ 1 @@ -10294,7 +10314,7 @@ export default { 3 ], "update": [ - 426 + 427 ], "__typename": [ 1 @@ -10313,7 +10333,7 @@ export default { }, "CreateOneObjectInput": { "object": [ - 428 + 429 ], "__typename": [ 1 @@ -10373,7 +10393,7 @@ export default { }, "UpdateOneObjectInput": { "update": [ - 431 + 432 ], "id": [ 3 @@ -10545,7 +10565,7 @@ export default { }, "UpdateRoleInput": { "update": [ - 436 + 437 ], "id": [ 3 @@ -10600,7 +10620,7 @@ export default { 3 ], "objectPermissions": [ - 438 + 439 ], "__typename": [ 1 @@ -10642,7 +10662,7 @@ export default { 3 ], "fieldPermissions": [ - 441 + 442 ], "__typename": [ 1 @@ -10673,10 +10693,10 @@ export default { 3 ], "predicates": [ - 443 + 444 ], "predicateGroups": [ - 444 + 445 ], "__typename": [ 1 @@ -10736,7 +10756,7 @@ export default { }, "CreateOneFieldMetadataInput": { "field": [ - 446 + 447 ], "__typename": [ 1 @@ -10809,7 +10829,7 @@ export default { 3 ], "update": [ - 448 + 449 ], "__typename": [ 1 @@ -10901,7 +10921,7 @@ export default { 3 ], "update": [ - 452 + 453 ], "__typename": [ 1 @@ -10945,7 +10965,7 @@ export default { 3 ], "update": [ - 456 + 457 ], "__typename": [ 1 @@ -10964,7 +10984,7 @@ export default { 3 ], "update": [ - 456 + 457 ], "__typename": [ 1 @@ -10975,7 +10995,7 @@ export default { 3 ], "update": [ - 459 + 460 ], "__typename": [ 1 @@ -10983,16 +11003,16 @@ export default { }, "UpdateMessageChannelInputUpdates": { "visibility": [ - 331 + 332 ], "isContactAutoCreationEnabled": [ 6 ], "contactAutoCreationPolicy": [ - 333 + 334 ], "messageFolderImportPolicy": [ - 334 + 335 ], "isSyncEnabled": [ 6 @@ -11012,7 +11032,7 @@ export default { 3 ], "update": [ - 461 + 462 ], "__typename": [ 1 @@ -11020,13 +11040,13 @@ export default { }, "UpdateCalendarChannelInputUpdates": { "visibility": [ - 327 + 329 ], "isContactAutoCreationEnabled": [ 6 ], "contactAutoCreationPolicy": [ - 328 + 330 ], "isSyncEnabled": [ 6 @@ -11060,7 +11080,7 @@ export default { 3 ], "update": [ - 464 + 465 ], "__typename": [ 1 @@ -11165,7 +11185,7 @@ export default { 1 ], "update": [ - 470 + 471 ], "__typename": [ 1 @@ -11213,7 +11233,7 @@ export default { 1 ], "update": [ - 473 + 474 ], "__typename": [ 1 @@ -11371,15 +11391,41 @@ export default { 1 ] }, + "SendEmailInput": { + "connectedAccountId": [ + 1 + ], + "to": [ + 1 + ], + "cc": [ + 1 + ], + "bcc": [ + 1 + ], + "subject": [ + 1 + ], + "body": [ + 1 + ], + "inReplyTo": [ + 1 + ], + "__typename": [ + 1 + ] + }, "EmailAccountConnectionParameters": { "IMAP": [ - 481 + 483 ], "SMTP": [ - 481 + 483 ], "CALDAV": [ - 481 + 483 ], "__typename": [ 1 @@ -11419,7 +11465,7 @@ export default { "AiModelRole": {}, "CreateOneAppTokenInput": { "appToken": [ - 485 + 487 ], "__typename": [ 1 @@ -11435,7 +11481,7 @@ export default { }, "WorkspaceMigrationInput": { "actions": [ - 487 + 489 ], "__typename": [ 1 @@ -11443,10 +11489,10 @@ export default { }, "WorkspaceMigrationDeleteActionInput": { "type": [ - 488 + 490 ], "metadataName": [ - 341 + 342 ], "universalIdentifier": [ 1 @@ -11471,13 +11517,13 @@ export default { 253, { "input": [ - 491, + 493, "LogicFunctionLogsInput!" ] } ], "onAgentChatEvent": [ - 319, + 321, { "threadId": [ 3, diff --git a/packages/twenty-front/codegen-metadata.cjs b/packages/twenty-front/codegen-metadata.cjs index 637755e405..fe5170958f 100644 --- a/packages/twenty-front/codegen-metadata.cjs +++ b/packages/twenty-front/codegen-metadata.cjs @@ -29,6 +29,7 @@ module.exports = { './src/modules/front-components/graphql/**/*.{ts,tsx}', './src/modules/page-layout/widgets/**/graphql/**/*.{ts,tsx}', + './src/modules/activities/emails/graphql/mutations/**/*.{ts,tsx}', './src/modules/dashboards/graphql/**/*.{ts,tsx}', './src/modules/page-layout/graphql/**/*.{ts,tsx}', diff --git a/packages/twenty-front/codegen.cjs b/packages/twenty-front/codegen.cjs index 9c5729b0f2..7de2479823 100644 --- a/packages/twenty-front/codegen.cjs +++ b/packages/twenty-front/codegen.cjs @@ -6,7 +6,8 @@ module.exports = { '/graphql', documents: [ './src/modules/workflow/**/graphql/**/*.{ts,tsx}', - './src/modules/activities/emails/graphql/**/*.{ts,tsx}', + './src/modules/activities/emails/graphql/queries/**/*.{ts,tsx}', + './src/modules/activities/emails/graphql/operation-signatures/**/*.{ts,tsx}', './src/modules/activities/calendar/graphql/**/*.{ts,tsx}', './src/modules/search/graphql/**/*.{ts,tsx}', './src/modules/command-menu/graphql/**/*.{ts,tsx}', diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 503b78b1c3..5b15978f52 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1575,6 +1575,7 @@ export enum EngineComponentKey { ADD_TO_FAVORITES = 'ADD_TO_FAVORITES', ASK_AI = 'ASK_AI', CANCEL_DASHBOARD_LAYOUT = 'CANCEL_DASHBOARD_LAYOUT', + COMPOSE_EMAIL = 'COMPOSE_EMAIL', CREATE_NEW_RECORD = 'CREATE_NEW_RECORD', CREATE_NEW_VIEW = 'CREATE_NEW_VIEW', DEACTIVATE_WORKFLOW = 'DEACTIVATE_WORKFLOW', @@ -2636,6 +2637,7 @@ export type Mutation = { runWorkspaceMigration: Scalars['Boolean']; saveImapSmtpCaldavAccount: ImapSmtpCaldavConnectionSuccess; sendChatMessage: SendChatMessageResult; + sendEmail: SendEmailOutput; sendInvitations: SendInvitations; setAdminAiModelEnabled: Scalars['Boolean']; setAdminAiModelRecommended: Scalars['Boolean']; @@ -3353,6 +3355,11 @@ export type MutationSendChatMessageArgs = { }; +export type MutationSendEmailArgs = { + input: SendEmailInput; +}; + + export type MutationSendInvitationsArgs = { emails: Array; roleId?: InputMaybe; @@ -4986,6 +4993,22 @@ export type SendChatMessageResult = { streamId?: Maybe; }; +export type SendEmailInput = { + bcc?: InputMaybe; + body: Scalars['String']; + cc?: InputMaybe; + connectedAccountId: Scalars['String']; + inReplyTo?: InputMaybe; + subject: Scalars['String']; + to: Scalars['String']; +}; + +export type SendEmailOutput = { + __typename?: 'SendEmailOutput'; + error?: Maybe; + success: Scalars['Boolean']; +}; + export type SendInvitations = { __typename?: 'SendInvitations'; errors: Array; @@ -6240,6 +6263,13 @@ export type WorkspaceUrlsAndId = { workspaceUrls: WorkspaceUrls; }; +export type SendEmailMutationVariables = Exact<{ + input: SendEmailInput; +}>; + + +export type SendEmailMutation = { __typename?: 'Mutation', sendEmail: { __typename?: 'SendEmailOutput', success: boolean, error?: string | null } }; + export type AgentFieldsFragment = { __typename?: 'Agent', id: string, name: string, label: string, description?: string | null, icon?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: string | null, isCustom: boolean, modelConfiguration?: any | null, evaluationInputs: Array, applicationId?: string | null, createdAt: string, updatedAt: string }; export type SkillFieldsFragment = { __typename?: 'Skill', id: string, name: string, label: string, description?: string | null, icon?: string | null, content: string, isCustom: boolean, isActive: boolean, createdAt: string, updatedAt: string }; @@ -8248,6 +8278,7 @@ export const ViewFilterGroupFragmentFragmentDoc = {"kind":"Document","definition export const ViewSortFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewSortFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewSort"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"direction"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const ViewGroupFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewGroupFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"fieldValue"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}}]} as unknown as DocumentNode; export const ViewFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"View"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"objectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"isCompact"}},{"kind":"Field","name":{"kind":"Name","value":"openRecordIn"}},{"kind":"Field","name":{"kind":"Name","value":"kanbanAggregateOperation"}},{"kind":"Field","name":{"kind":"Name","value":"kanbanAggregateOperationFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"mainGroupByFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"shouldHideEmptyGroups"}},{"kind":"Field","name":{"kind":"Name","value":"anyFieldFilterValue"}},{"kind":"Field","name":{"kind":"Name","value":"calendarFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"calendarLayout"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"createdByUserWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"viewFields"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFieldFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewFieldGroups"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFieldGroupFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewFilters"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFilterFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewFilterGroups"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFilterGroupFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewSorts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewSortFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewGroups"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewGroupFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFieldFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewField"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"size"}},{"kind":"Field","name":{"kind":"Name","value":"aggregateOperation"}},{"kind":"Field","name":{"kind":"Name","value":"viewFieldGroupId"}},{"kind":"Field","name":{"kind":"Name","value":"isOverridden"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFieldGroupFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewFieldGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"isOverridden"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}},{"kind":"Field","name":{"kind":"Name","value":"viewFields"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFieldFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFilterFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewFilter"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"operand"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"viewFilterGroupId"}},{"kind":"Field","name":{"kind":"Name","value":"positionInViewFilterGroup"}},{"kind":"Field","name":{"kind":"Name","value":"subFieldName"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFilterGroupFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewFilterGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"parentViewFilterGroupId"}},{"kind":"Field","name":{"kind":"Name","value":"logicalOperator"}},{"kind":"Field","name":{"kind":"Name","value":"positionInViewFilterGroup"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewSortFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewSort"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"direction"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewGroupFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"fieldValue"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}}]} as unknown as DocumentNode; +export const SendEmailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SendEmail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SendEmailInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"sendEmail"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"success"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]} as unknown as DocumentNode; export const ActivateSkillDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ActivateSkill"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activateSkill"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SkillFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SkillFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Skill"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const AssignRoleToAgentDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AssignRoleToAgent"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"agentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"roleId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignRoleToAgent"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"agentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"agentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"roleId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"roleId"}}}]}]}}]} as unknown as DocumentNode; export const CreateChatThreadDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateChatThread"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createChatThread"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/modules/activities/emails/components/ComposeEmailButton.tsx b/packages/twenty-front/src/modules/activities/emails/components/ComposeEmailButton.tsx new file mode 100644 index 0000000000..9b7467886c --- /dev/null +++ b/packages/twenty-front/src/modules/activities/emails/components/ComposeEmailButton.tsx @@ -0,0 +1,91 @@ +import { useFirstConnectedAccount } from '@/activities/emails/hooks/useFirstConnectedAccount'; +import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; +import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; +import { useOpenComposeEmailInSidePanel } from '@/side-panel/hooks/useOpenComposeEmailInSidePanel'; +import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord'; +import { CoreObjectNameSingular, SettingsPath } from 'twenty-shared/types'; +import { isDefined } from 'twenty-shared/utils'; +import { IconPlus } from 'twenty-ui/display'; +import { LightIconButton } from 'twenty-ui/input'; +import { useNavigateSettings } from '~/hooks/useNavigateSettings'; + +export const ComposeEmailButton = () => { + const targetRecord = useTargetRecord(); + const { openComposeEmailInSidePanel } = useOpenComposeEmailInSidePanel(); + const navigateSettings = useNavigateSettings(); + const { connectedAccountId, loading: accountLoading } = + useFirstConnectedAccount(); + + const isPerson = + targetRecord.targetObjectNameSingular === CoreObjectNameSingular.Person; + const isCompany = + targetRecord.targetObjectNameSingular === CoreObjectNameSingular.Company; + const isOpportunity = + targetRecord.targetObjectNameSingular === + CoreObjectNameSingular.Opportunity; + + const { record: personRecord } = useFindOneRecord({ + objectNameSingular: CoreObjectNameSingular.Person, + objectRecordId: targetRecord.id, + recordGqlFields: { id: true, emails: { primaryEmail: true } }, + skip: !isPerson, + }); + + const { records: companyPeople } = useFindManyRecords({ + objectNameSingular: CoreObjectNameSingular.Person, + filter: { companyId: { eq: targetRecord.id } }, + recordGqlFields: { id: true, emails: { primaryEmail: true } }, + limit: 1, + skip: !isCompany, + }); + + const { record: opportunityRecord } = useFindOneRecord({ + objectNameSingular: CoreObjectNameSingular.Opportunity, + objectRecordId: targetRecord.id, + recordGqlFields: { + id: true, + pointOfContact: { id: true, emails: { primaryEmail: true } }, + company: { id: true }, + }, + skip: !isOpportunity, + }); + + const resolveDefaultTo = (): string => { + if (isPerson) { + return personRecord?.emails?.primaryEmail ?? ''; + } + if (isCompany) { + return companyPeople[0]?.emails?.primaryEmail ?? ''; + } + if (isOpportunity) { + return opportunityRecord?.pointOfContact?.emails?.primaryEmail ?? ''; + } + return ''; + }; + + const handleClick = () => { + if (!isDefined(connectedAccountId)) { + navigateSettings(SettingsPath.NewAccount); + + return; + } + + openComposeEmailInSidePanel({ + connectedAccountId, + defaultTo: resolveDefaultTo(), + }); + }; + + if (accountLoading) { + return null; + } + + return ( + + ); +}; diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailComposer.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailComposer.tsx new file mode 100644 index 0000000000..8d98f0c651 --- /dev/null +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailComposer.tsx @@ -0,0 +1,81 @@ +import { styled } from '@linaria/react'; + +import { EmailComposerFields } from '@/activities/emails/components/EmailComposerFields'; +import { useEmailComposerState } from '@/activities/emails/hooks/useEmailComposerState'; +import { t } from '@lingui/core/macro'; +import { IconArrowBackUp } from 'twenty-ui/display'; +import { Button } from 'twenty-ui/input'; +import { themeCssVariables } from 'twenty-ui/theme-constants'; + +const StyledComposerContainer = styled.div` + background: ${themeCssVariables.background.primary}; + display: flex; + flex-direction: column; +`; + +const StyledFooter = styled.div` + align-items: center; + border-top: 1px solid ${themeCssVariables.border.color.light}; + display: flex; + justify-content: flex-end; + padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[4]}; +`; + +const StyledFooterActions = styled.div` + align-items: center; + display: flex; + gap: ${themeCssVariables.spacing[2]}; +`; + +type EmailComposerProps = { + connectedAccountId: string; + defaultTo?: string; + defaultSubject?: string; + defaultInReplyTo?: string; + onClose?: () => void; + onSent?: () => void; +}; + +export const EmailComposer = ({ + connectedAccountId, + defaultTo = '', + defaultSubject = '', + defaultInReplyTo, + onClose, + onSent, +}: EmailComposerProps) => { + const composerState = useEmailComposerState({ + connectedAccountId, + defaultTo, + defaultSubject, + defaultInReplyTo, + onSent, + }); + + return ( + + + + + {onClose && ( +