Skip to content

Commit

Permalink
7417 workflows i can send emails using the email account (#7431)
Browse files Browse the repository at this point in the history
- update `send-email.workflow-action.ts` so it send email via the google
sdk
- remove useless `workflow-action.email.ts`
- add `send` authorization to google api scopes
- update the front workflow email step form to provide a
`connectedAccountId` from the available connected accounts
- update the permissions of connected accounts: ask users to reconnect
when selecting missing send permission


![image](https://github.com/user-attachments/assets/fe3c329d-fd67-4d0d-8450-099c35933645)
  • Loading branch information
martmull authored Oct 8, 2024
1 parent 444cd3f commit f138a1c
Show file tree
Hide file tree
Showing 30 changed files with 444 additions and 160 deletions.
29 changes: 0 additions & 29 deletions packages/twenty-emails/src/emails/workflow-action.email.tsx

This file was deleted.

1 change: 0 additions & 1 deletion packages/twenty-emails/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@ export * from './emails/delete-inactive-workspaces.email';
export * from './emails/password-reset-link.email';
export * from './emails/password-update-notify.email';
export * from './emails/send-invite-link.email';
export * from './emails/workflow-action.email';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const GMAIL_SEND_SCOPE = 'https://www.googleapis.com/auth/gmail.send';
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ export type ConnectedAccount = {
authFailedAt: Date | null;
messageChannels: MessageChannel[];
calendarChannels: CalendarChannel[];
scopes: string[] | null;
__typename: 'ConnectedAccount';
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ export const useTriggerGoogleApisOAuth = () => {
const [generateTransientToken] = useGenerateTransientTokenMutation();

const triggerGoogleApisOAuth = useCallback(
async (
redirectLocation?: AppPath,
messageVisibility?: MessageChannelVisibility,
calendarVisibility?: CalendarChannelVisibility,
) => {
async ({
redirectLocation,
messageVisibility,
calendarVisibility,
loginHint,
}: {
redirectLocation?: AppPath | string;
messageVisibility?: MessageChannelVisibility;
calendarVisibility?: CalendarChannelVisibility;
loginHint?: string;
} = {}) => {
const authServerUrl = REACT_APP_SERVER_BASE_URL;

const transientToken = await generateTransientToken();
Expand All @@ -38,6 +44,8 @@ export const useTriggerGoogleApisOAuth = () => {
? `&messageVisibility=${messageVisibility}`
: '';

params += loginHint ? `&loginHint=${loginHint}` : '';

window.location.href = `${authServerUrl}/auth/google-apis?${params}`;
},
[generateTransientToken],
Expand Down
31 changes: 27 additions & 4 deletions packages/twenty-front/src/modules/ui/input/components/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useMemo, useRef, useState } from 'react';
import React, { MouseEvent, useMemo, useRef, useState } from 'react';
import { IconChevronDown, IconComponent } from 'twenty-ui';

import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
Expand All @@ -11,13 +11,20 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';

import { SelectHotkeyScope } from '../types/SelectHotkeyScope';
import { isDefined } from '~/utils/isDefined';

export type SelectOption<Value extends string | number | null> = {
value: Value;
label: string;
Icon?: IconComponent;
};

type CallToActionButton = {
text: string;
onClick: (event: MouseEvent<HTMLDivElement>) => void;
Icon?: IconComponent;
};

export type SelectProps<Value extends string | number | null> = {
className?: string;
disabled?: boolean;
Expand All @@ -32,6 +39,7 @@ export type SelectProps<Value extends string | number | null> = {
options: SelectOption<Value>[];
value?: Value;
withSearchInput?: boolean;
callToActionButton?: CallToActionButton;
};

const StyledContainer = styled.div<{ fullWidth?: boolean }>`
Expand Down Expand Up @@ -89,6 +97,7 @@ export const Select = <Value extends string | number | null>({
options,
value,
withSearchInput,
callToActionButton,
}: SelectProps<Value>) => {
const selectContainerRef = useRef<HTMLDivElement>(null);

Expand All @@ -97,8 +106,8 @@ export const Select = <Value extends string | number | null>({

const selectedOption =
options.find(({ value: key }) => key === value) ||
options[0] ||
emptyOption;
emptyOption ||
options[0];
const filteredOptions = useMemo(
() =>
searchInputValue
Expand All @@ -109,7 +118,9 @@ export const Select = <Value extends string | number | null>({
[options, searchInputValue],
);

const isDisabled = disabledFromProps || options.length <= 1;
const isDisabled =
disabledFromProps ||
(options.length <= 1 && !isDefined(callToActionButton));

const { closeDropdown } = useDropdown(dropdownId);

Expand Down Expand Up @@ -177,6 +188,18 @@ export const Select = <Value extends string | number | null>({
))}
</DropdownMenuItemsContainer>
)}
{!!callToActionButton && !!filteredOptions.length && (
<DropdownMenuSeparator />
)}
{!!callToActionButton && (
<DropdownMenuItemsContainer hasMaxHeight>
<MenuItem
onClick={callToActionButton.onClick}
LeftIcon={callToActionButton.Icon}
text={callToActionButton.text}
/>
</DropdownMenuItemsContainer>
)}
</>
}
dropdownHotkeyScope={{ scope: SelectHotkeyScope.Select }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { userEvent, within } from '@storybook/test';
import { ComponentDecorator } from 'twenty-ui';

import { Select, SelectProps } from '../Select';
import { IconPlus } from 'packages/twenty-ui';

type RenderProps = SelectProps<string | number | null>;

Expand Down Expand Up @@ -56,3 +57,13 @@ export const Disabled: Story = {
export const WithSearch: Story = {
args: { withSearchInput: true },
};

export const CallToActionButton: Story = {
args: {
callToActionButton: {
onClick: () => {},
Icon: IconPlus,
text: 'Add action',
},
},
};
Loading

0 comments on commit f138a1c

Please sign in to comment.