diff --git a/packages/twenty-front/src/App.tsx b/packages/twenty-front/src/App.tsx
index 956a6c59e..fff38bef2 100644
--- a/packages/twenty-front/src/App.tsx
+++ b/packages/twenty-front/src/App.tsx
@@ -55,7 +55,6 @@ import { SettingsAccounts } from '~/pages/settings/accounts/SettingsAccounts';
import { SettingsAccountsCalendars } from '~/pages/settings/accounts/SettingsAccountsCalendars';
import { SettingsAccountsCalendarsSettings } from '~/pages/settings/accounts/SettingsAccountsCalendarsSettings';
import { SettingsAccountsEmails } from '~/pages/settings/accounts/SettingsAccountsEmails';
-import { SettingsAccountsEmailsInboxSettings } from '~/pages/settings/accounts/SettingsAccountsEmailsInboxSettings';
import { SettingsNewAccount } from '~/pages/settings/accounts/SettingsNewAccount';
import { SettingsNewObject } from '~/pages/settings/data-model/SettingsNewObject';
import { SettingsObjectDetail } from '~/pages/settings/data-model/SettingsObjectDetail';
@@ -188,10 +187,6 @@ const createRouter = (isBillingEnabled?: boolean) =>
path={SettingsPath.AccountsEmails}
element={}
/>
- }
- />
}
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistInput.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsBlocklistInput.tsx
similarity index 94%
rename from packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistInput.tsx
rename to packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsBlocklistInput.tsx
index 1794eb1d4..9bb4fdd98 100644
--- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistInput.tsx
+++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsBlocklistInput.tsx
@@ -19,7 +19,7 @@ const StyledLinkContainer = styled.div`
margin-right: ${({ theme }) => theme.spacing(2)};
`;
-type SettingsAccountsEmailsBlocklistInputProps = {
+type SettingsAccountsBlocklistInputProps = {
updateBlockedEmailList: (email: string) => void;
blockedEmailOrDomainList: string[];
};
@@ -50,10 +50,10 @@ type FormInput = {
emailOrDomain: string;
};
-export const SettingsAccountsEmailsBlocklistInput = ({
+export const SettingsAccountsBlocklistInput = ({
updateBlockedEmailList,
blockedEmailOrDomainList,
-}: SettingsAccountsEmailsBlocklistInputProps) => {
+}: SettingsAccountsBlocklistInputProps) => {
const { reset, handleSubmit, control, formState } = useForm({
mode: 'onSubmit',
resolver: zodResolver(validationSchema(blockedEmailOrDomainList)),
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistSection.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsBlocklistSection.tsx
similarity index 81%
rename from packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistSection.tsx
rename to packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsBlocklistSection.tsx
index 39b789fae..51ff642b1 100644
--- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistSection.tsx
+++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsBlocklistSection.tsx
@@ -7,11 +7,11 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
-import { SettingsAccountsEmailsBlocklistInput } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistInput';
-import { SettingsAccountsEmailsBlocklistTable } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistTable';
+import { SettingsAccountsBlocklistInput } from '@/settings/accounts/components/SettingsAccountsBlocklistInput';
+import { SettingsAccountsBlocklistTable } from '@/settings/accounts/components/SettingsAccountsBlocklistTable';
import { Section } from '@/ui/layout/section/components/Section';
-export const SettingsAccountsEmailsBlocklistSection = () => {
+export const SettingsAccountsBlocklistSection = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { records: blocklist } = useFindManyRecords({
@@ -44,11 +44,11 @@ export const SettingsAccountsEmailsBlocklistSection = () => {
title="Blocklist"
description="Exclude the following people and domains from my email sync"
/>
- item.handle)}
updateBlockedEmailList={updateBlockedEmailList}
/>
-
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistTable.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsBlocklistTable.tsx
similarity index 79%
rename from packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistTable.tsx
rename to packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsBlocklistTable.tsx
index a238ef6e5..a4c9f5306 100644
--- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistTable.tsx
+++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsBlocklistTable.tsx
@@ -1,13 +1,13 @@
import styled from '@emotion/styled';
import { BlocklistItem } from '@/accounts/types/BlocklistItem';
-import { SettingsAccountsEmailsBlocklistTableRow } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistTableRow';
+import { SettingsAccountsBlocklistTableRow } from '@/settings/accounts/components/SettingsAccountsBlocklistTableRow';
import { Table } from '@/ui/layout/table/components/Table';
import { TableBody } from '@/ui/layout/table/components/TableBody';
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { TableRow } from '@/ui/layout/table/components/TableRow';
-type SettingsAccountsEmailsBlocklistTableProps = {
+type SettingsAccountsBlocklistTableProps = {
blocklist: BlocklistItem[];
handleBlockedEmailRemove: (id: string) => void;
};
@@ -20,10 +20,10 @@ const StyledTableBody = styled(TableBody)`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
`;
-export const SettingsAccountsEmailsBlocklistTable = ({
+export const SettingsAccountsBlocklistTable = ({
blocklist,
handleBlockedEmailRemove,
-}: SettingsAccountsEmailsBlocklistTableProps) => {
+}: SettingsAccountsBlocklistTableProps) => {
return (
<>
{blocklist.length > 0 && (
@@ -35,7 +35,7 @@ export const SettingsAccountsEmailsBlocklistTable = ({
{blocklist.map((blocklistItem) => (
- void;
};
-export const SettingsAccountsEmailsBlocklistTableRow = ({
+export const SettingsAccountsBlocklistTableRow = ({
blocklistItem,
onRemove,
-}: SettingsAccountsEmailsBlocklistTableRowProps) => {
+}: SettingsAccountsBlocklistTableRowProps) => {
return (
{blocklistItem.handle}
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelDetails.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelDetails.tsx
new file mode 100644
index 000000000..ad3b912db
--- /dev/null
+++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelDetails.tsx
@@ -0,0 +1,116 @@
+import { useTheme } from '@emotion/react';
+import styled from '@emotion/styled';
+import { H2Title, IconRefresh, IconUser } from 'twenty-ui';
+
+import { MessageChannel } from '@/accounts/types/MessageChannel';
+import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
+import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
+import { SettingsAccountsCardMedia } from '@/settings/accounts/components/SettingsAccountsCardMedia';
+import { SettingsAccountsInboxVisibilitySettingsCard } from '@/settings/accounts/components/SettingsAccountsInboxVisibilitySettingsCard';
+import { SettingsAccountsToggleSettingCard } from '@/settings/accounts/components/SettingsAccountsToggleSettingCard';
+import { Section } from '@/ui/layout/section/components/Section';
+import { MessageChannelVisibility } from '~/generated-metadata/graphql';
+
+type SettingsAccountsMessageChannelDetailsProps = {
+ messageChannel: Pick<
+ MessageChannel,
+ 'id' | 'visibility' | 'isContactAutoCreationEnabled' | 'isSyncEnabled'
+ >;
+};
+
+const StyledDetailsContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: ${({ theme }) => theme.spacing(6)};
+ padding-top: ${({ theme }) => theme.spacing(6)};
+`;
+
+export const SettingsAccountsMessageChannelDetails = ({
+ messageChannel,
+}: SettingsAccountsMessageChannelDetailsProps) => {
+ const theme = useTheme();
+
+ const { updateOneRecord } = useUpdateOneRecord({
+ objectNameSingular: CoreObjectNameSingular.MessageChannel,
+ });
+
+ const handleVisibilityChange = (value: MessageChannelVisibility) => {
+ updateOneRecord({
+ idToUpdate: messageChannel.id,
+ updateOneRecordInput: {
+ visibility: value,
+ },
+ });
+ };
+
+ const handleContactAutoCreationToggle = (value: boolean) => {
+ updateOneRecord({
+ idToUpdate: messageChannel.id,
+ updateOneRecordInput: {
+ isContactAutoCreationEnabled: value,
+ },
+ });
+ };
+
+ const handleIsSyncEnabledToggle = (value: boolean) => {
+ updateOneRecord({
+ idToUpdate: messageChannel.id,
+ updateOneRecordInput: {
+ isSyncEnabled: value,
+ },
+ });
+ };
+
+ return (
+
+
+
+
+
+
+
+ }
+ title="Auto-creation"
+ value={!!messageChannel.isContactAutoCreationEnabled}
+ onToggle={handleContactAutoCreationToggle}
+ />
+
+
+
+
+
+
+ }
+ title="Sync emails"
+ value={!!messageChannel.isSyncEnabled}
+ onToggle={handleIsSyncEnabledToggle}
+ />
+
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsContainer.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsContainer.tsx
new file mode 100644
index 000000000..95f462e06
--- /dev/null
+++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsContainer.tsx
@@ -0,0 +1,71 @@
+import { useRecoilValue } from 'recoil';
+
+import { ConnectedAccount } from '@/accounts/types/ConnectedAccount';
+import { MessageChannel } from '@/accounts/types/MessageChannel';
+import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
+import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
+import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
+import { SettingsAccountsListEmptyStateCard } from '@/settings/accounts/components/SettingsAccountsListEmptyStateCard';
+import { SettingsAccountsMessageChannelDetails } from '@/settings/accounts/components/SettingsAccountsMessageChannelDetails';
+import { SETTINGS_ACCOUNT_MESSAGE_CHANNELS_TAB_LIST_COMPONENT_ID } from '@/settings/accounts/constants/SettingsAccountMessageChannelsTabListComponentId';
+import { TabList } from '@/ui/layout/tab/components/TabList';
+import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
+
+export const SettingsAccountsMessageChannelsContainer = () => {
+ const { activeTabIdState } = useTabList(
+ SETTINGS_ACCOUNT_MESSAGE_CHANNELS_TAB_LIST_COMPONENT_ID,
+ );
+ const activeTabId = useRecoilValue(activeTabIdState);
+ const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
+
+ const { records: accounts } = useFindManyRecords({
+ objectNameSingular: CoreObjectNameSingular.ConnectedAccount,
+ filter: {
+ accountOwnerId: {
+ eq: currentWorkspaceMember?.id,
+ },
+ },
+ });
+
+ const { records: messageChannels } = useFindManyRecords<
+ MessageChannel & {
+ connectedAccount: ConnectedAccount;
+ }
+ >({
+ objectNameSingular: CoreObjectNameSingular.MessageChannel,
+ filter: {
+ connectedAccountId: {
+ in: accounts.map((account) => account.id),
+ },
+ },
+ });
+
+ const tabs = [
+ ...messageChannels.map((messageChannel) => ({
+ id: messageChannel.id,
+ title: messageChannel.handle,
+ })),
+ ];
+
+ if (!messageChannels.length) {
+ return ;
+ }
+
+ return (
+ <>
+
+ {messageChannels.map((messageChannel) => (
+ <>
+ {messageChannel.id === activeTabId && (
+
+ )}
+ >
+ ))}
+ >
+ );
+};
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsListCard.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsListCard.tsx
deleted file mode 100644
index addc376b4..000000000
--- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsListCard.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-import { useNavigate } from 'react-router-dom';
-import styled from '@emotion/styled';
-import { useRecoilValue } from 'recoil';
-import { IconChevronRight, IconGmail } from 'twenty-ui';
-
-import { ConnectedAccount } from '@/accounts/types/ConnectedAccount';
-import { MessageChannel } from '@/accounts/types/MessageChannel';
-import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
-import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
-import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
-import { SettingsAccountsListEmptyStateCard } from '@/settings/accounts/components/SettingsAccountsListEmptyStateCard';
-import {
- SettingsAccountsSynchronizationStatus,
- SettingsAccountsSynchronizationStatusProps,
-} from '@/settings/accounts/components/SettingsAccountsSynchronizationStatus';
-import { SettingsListCard } from '@/settings/components/SettingsListCard';
-import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
-
-const StyledRowRightContainer = styled.div`
- align-items: center;
- display: flex;
- gap: ${({ theme }) => theme.spacing(1)};
-`;
-
-export const SettingsAccountsMessageChannelsListCard = () => {
- const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
- const navigate = useNavigate();
-
- const { records: accounts, loading: accountsLoading } =
- useFindManyRecords({
- objectNameSingular: CoreObjectNameSingular.ConnectedAccount,
- filter: {
- accountOwnerId: {
- eq: currentWorkspaceMember?.id,
- },
- },
- });
-
- const { records: messageChannels, loading: messageChannelsLoading } =
- useFindManyRecords<
- MessageChannel & {
- connectedAccount: ConnectedAccount;
- }
- >({
- objectNameSingular: CoreObjectNameSingular.MessageChannel,
- filter: {
- connectedAccountId: {
- in: accounts.map((account) => account.id),
- },
- },
- });
-
- const messageChannelsWithSyncedEmails: (MessageChannel & {
- connectedAccount: ConnectedAccount;
- } & SettingsAccountsSynchronizationStatusProps)[] = messageChannels.map(
- (messageChannel) => ({
- ...messageChannel,
- syncStatus: messageChannel.syncStatus,
- }),
- );
-
- if (!messageChannelsWithSyncedEmails.length) {
- return ;
- }
-
- return (
- messageChannel.handle}
- isLoading={accountsLoading || messageChannelsLoading}
- onRowClick={(messageChannel) =>
- navigate(`/settings/accounts/emails/${messageChannel.id}`)
- }
- RowIcon={IconGmail}
- RowRightComponent={({ item: messageChannel }) => (
-
-
-
-
- )}
- />
- );
-};
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistInput.stories.tsx b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistInput.stories.tsx
similarity index 77%
rename from packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistInput.stories.tsx
rename to packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistInput.stories.tsx
index 3ceef7405..48a52896b 100644
--- a/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistInput.stories.tsx
+++ b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistInput.stories.tsx
@@ -2,7 +2,7 @@ import { Decorator, Meta, StoryObj } from '@storybook/react';
import { expect, fn, userEvent, within } from '@storybook/test';
import { ComponentDecorator } from 'twenty-ui';
-import { SettingsAccountsEmailsBlocklistInput } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistInput';
+import { SettingsAccountsBlocklistInput } from '@/settings/accounts/components/SettingsAccountsBlocklistInput';
const updateBlockedEmailListJestFn = fn();
@@ -13,10 +13,9 @@ const ClearMocksDecorator: Decorator = (Story, context) => {
return ;
};
-const meta: Meta = {
- title:
- 'Modules/Settings/Accounts/Blocklist/SettingsAccountsEmailsBlocklistInput',
- component: SettingsAccountsEmailsBlocklistInput,
+const meta: Meta = {
+ title: 'Modules/Settings/Accounts/Blocklist/SettingsAccountsBlocklistInput',
+ component: SettingsAccountsBlocklistInput,
decorators: [ComponentDecorator, ClearMocksDecorator],
args: {
updateBlockedEmailList: updateBlockedEmailListJestFn,
@@ -31,7 +30,7 @@ const meta: Meta = {
};
export default meta;
-type Story = StoryObj;
+type Story = StoryObj;
export const Default: Story = {};
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistSection.stories.tsx b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistSection.stories.tsx
new file mode 100644
index 000000000..bc3f9cb72
--- /dev/null
+++ b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistSection.stories.tsx
@@ -0,0 +1,16 @@
+import { Meta, StoryObj } from '@storybook/react';
+import { ComponentDecorator } from 'twenty-ui';
+
+import { SettingsAccountsBlocklistInput } from '@/settings/accounts/components/SettingsAccountsBlocklistInput';
+import { SettingsAccountsBlocklistSection } from '@/settings/accounts/components/SettingsAccountsBlocklistSection';
+
+const meta: Meta = {
+ title: 'Modules/Settings/Accounts/Blocklist/SettingsAccountsBlocklistSection',
+ component: SettingsAccountsBlocklistInput,
+ decorators: [ComponentDecorator],
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistTable.stories.tsx b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistTable.stories.tsx
similarity index 81%
rename from packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistTable.stories.tsx
rename to packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistTable.stories.tsx
index 7ab7f1c9b..71126ba4e 100644
--- a/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistTable.stories.tsx
+++ b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistTable.stories.tsx
@@ -3,7 +3,7 @@ import { expect, fn, userEvent, within } from '@storybook/test';
import { ComponentDecorator } from 'twenty-ui';
import { mockedBlocklist } from '@/settings/accounts/components/__stories__/mockedBlocklist';
-import { SettingsAccountsEmailsBlocklistTable } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistTable';
+import { SettingsAccountsBlocklistTable } from '@/settings/accounts/components/SettingsAccountsBlocklistTable';
import { formatToHumanReadableDate } from '~/utils/date-utils';
const handleBlockedEmailRemoveJestFn = fn();
@@ -15,10 +15,9 @@ const ClearMocksDecorator: Decorator = (Story, context) => {
return ;
};
-const meta: Meta = {
- title:
- 'Modules/Settings/Accounts/Blocklist/SettingsAccountsEmailsBlocklistTable',
- component: SettingsAccountsEmailsBlocklistTable,
+const meta: Meta = {
+ title: 'Modules/Settings/Accounts/Blocklist/SettingsAccountsBlocklistTable',
+ component: SettingsAccountsBlocklistTable,
decorators: [ComponentDecorator, ClearMocksDecorator],
args: {
blocklist: mockedBlocklist,
@@ -34,7 +33,7 @@ const meta: Meta = {
};
export default meta;
-type Story = StoryObj;
+type Story = StoryObj;
export const Default: Story = {
play: async ({ canvasElement }) => {
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistTableRow.stories.tsx b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistTableRow.stories.tsx
similarity index 80%
rename from packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistTableRow.stories.tsx
rename to packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistTableRow.stories.tsx
index f24b0033f..b4a1991e6 100644
--- a/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistTableRow.stories.tsx
+++ b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsBlocklistTableRow.stories.tsx
@@ -3,7 +3,7 @@ import { expect, fn, userEvent, within } from '@storybook/test';
import { ComponentDecorator } from 'twenty-ui';
import { mockedBlocklist } from '@/settings/accounts/components/__stories__/mockedBlocklist';
-import { SettingsAccountsEmailsBlocklistTableRow } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistTableRow';
+import { SettingsAccountsBlocklistTableRow } from '@/settings/accounts/components/SettingsAccountsBlocklistTableRow';
import { formatToHumanReadableDate } from '~/utils/date-utils';
const onRemoveJestFn = fn();
@@ -15,10 +15,10 @@ const ClearMocksDecorator: Decorator = (Story, context) => {
return ;
};
-const meta: Meta = {
+const meta: Meta = {
title:
- 'Modules/Settings/Accounts/Blocklist/SettingsAccountsEmailsBlocklistTableRow',
- component: SettingsAccountsEmailsBlocklistTableRow,
+ 'Modules/Settings/Accounts/Blocklist/SettingsAccountsBlocklistTableRow',
+ component: SettingsAccountsBlocklistTableRow,
decorators: [ComponentDecorator, ClearMocksDecorator],
args: {
blocklistItem: mockedBlocklist[0],
@@ -34,7 +34,7 @@ const meta: Meta = {
};
export default meta;
-type Story = StoryObj;
+type Story = StoryObj;
export const Default: Story = {
play: async ({ canvasElement }) => {
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistSection.stories.tsx b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistSection.stories.tsx
deleted file mode 100644
index 7fa2183aa..000000000
--- a/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistSection.stories.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { Meta, StoryObj } from '@storybook/react';
-import { ComponentDecorator } from 'twenty-ui';
-
-import { SettingsAccountsEmailsBlocklistInput } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistInput';
-import { SettingsAccountsEmailsBlocklistSection } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistSection';
-
-const meta: Meta = {
- title:
- 'Modules/Settings/Accounts/Blocklist/SettingsAccountsEmailsBlocklistSection',
- component: SettingsAccountsEmailsBlocklistInput,
- decorators: [ComponentDecorator],
-};
-
-export default meta;
-type Story = StoryObj;
-
-export const Default: Story = {};
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsMessageChannelDetails.stories.tsx b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsMessageChannelDetails.stories.tsx
new file mode 100644
index 000000000..e1472836e
--- /dev/null
+++ b/packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsMessageChannelDetails.stories.tsx
@@ -0,0 +1,30 @@
+import { Meta, StoryObj } from '@storybook/react';
+import { ComponentDecorator } from 'twenty-ui';
+
+import { SettingsAccountsMessageChannelDetails } from '@/settings/accounts/components/SettingsAccountsMessageChannelDetails';
+import { MessageChannelVisibility } from '~/generated/graphql';
+
+const meta: Meta = {
+ title:
+ 'Modules/Settings/Accounts/MessageChannels/SettingsAccountsMessageChannelDetails',
+ component: SettingsAccountsMessageChannelDetails,
+ decorators: [ComponentDecorator],
+ args: {
+ messageChannel: {
+ id: '20202020-ef5a-4822-9e08-ce6e6a4dcb6a',
+ isContactAutoCreationEnabled: true,
+ isSyncEnabled: true,
+ visibility: MessageChannelVisibility.ShareEverything,
+ },
+ },
+ argTypes: {
+ messageChannel: { control: false },
+ },
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {
+ play: async () => {},
+};
diff --git a/packages/twenty-front/src/modules/settings/accounts/constants/SettingsAccountMessageChannelsTabListComponentId.ts b/packages/twenty-front/src/modules/settings/accounts/constants/SettingsAccountMessageChannelsTabListComponentId.ts
new file mode 100644
index 000000000..31f4638d7
--- /dev/null
+++ b/packages/twenty-front/src/modules/settings/accounts/constants/SettingsAccountMessageChannelsTabListComponentId.ts
@@ -0,0 +1,2 @@
+export const SETTINGS_ACCOUNT_MESSAGE_CHANNELS_TAB_LIST_COMPONENT_ID =
+ 'settings-account-message-channels-tab-list';
diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx
index 484a0a681..0a46dfbe9 100644
--- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx
+++ b/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx
@@ -8,8 +8,8 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { SettingsAccountLoader } from '@/settings/accounts/components/SettingsAccountLoader';
+import { SettingsAccountsBlocklistSection } from '@/settings/accounts/components/SettingsAccountsBlocklistSection';
import { SettingsAccountsConnectedAccountsListCard } from '@/settings/accounts/components/SettingsAccountsConnectedAccountsListCard';
-import { SettingsAccountsEmailsBlocklistSection } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistSection';
import { SettingsAccountsSettingsSection } from '@/settings/accounts/components/SettingsAccountsSettingsSection';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
@@ -55,7 +55,7 @@ export const SettingsAccounts = () => {
loading={loading}
/>
- {isBlocklistEnabled && }
+ {isBlocklistEnabled && }
>
)}
diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx
index d2827187f..b972ad215 100644
--- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx
+++ b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx
@@ -1,6 +1,6 @@
-import { H2Title, IconSettings } from 'twenty-ui';
+import { IconSettings } from 'twenty-ui';
-import { SettingsAccountsMessageChannelsListCard } from '@/settings/accounts/components/SettingsAccountsMessageChannelsListCard';
+import { SettingsAccountsMessageChannelsContainer } from '@/settings/accounts/components/SettingsAccountsMessageChannelsContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
@@ -16,11 +16,7 @@ export const SettingsAccountsEmails = () => (
]}
/>
diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmailsInboxSettings.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmailsInboxSettings.tsx
deleted file mode 100644
index afef0c498..000000000
--- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmailsInboxSettings.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import { useEffect } from 'react';
-import { useNavigate, useParams } from 'react-router-dom';
-import { useTheme } from '@emotion/react';
-import { H2Title, IconRefresh, IconSettings, IconUser } from 'twenty-ui';
-
-import { MessageChannel } from '@/accounts/types/MessageChannel';
-import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
-import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
-import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
-import { SettingsAccountsCardMedia } from '@/settings/accounts/components/SettingsAccountsCardMedia';
-import { SettingsAccountsInboxVisibilitySettingsCard } from '@/settings/accounts/components/SettingsAccountsInboxVisibilitySettingsCard';
-import { SettingsAccountsToggleSettingCard } from '@/settings/accounts/components/SettingsAccountsToggleSettingCard';
-import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
-import { AppPath } from '@/types/AppPath';
-import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
-import { Section } from '@/ui/layout/section/components/Section';
-import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
-import { MessageChannelVisibility } from '~/generated/graphql';
-
-export const SettingsAccountsEmailsInboxSettings = () => {
- const theme = useTheme();
- const navigate = useNavigate();
- const { accountUuid: messageChannelId = '' } = useParams();
-
- const { record: messageChannel, loading } = useFindOneRecord({
- objectNameSingular: CoreObjectNameSingular.MessageChannel,
- objectRecordId: messageChannelId,
- });
-
- const { updateOneRecord } = useUpdateOneRecord({
- objectNameSingular: CoreObjectNameSingular.MessageChannel,
- });
-
- const handleVisibilityChange = (value: MessageChannelVisibility) => {
- updateOneRecord({
- idToUpdate: messageChannelId,
- updateOneRecordInput: {
- visibility: value,
- },
- });
- };
-
- const handleContactAutoCreationToggle = (value: boolean) => {
- updateOneRecord({
- idToUpdate: messageChannelId,
- updateOneRecordInput: {
- isContactAutoCreationEnabled: value,
- },
- });
- };
-
- const handleIsSyncEnabledToggle = (value: boolean) => {
- updateOneRecord({
- idToUpdate: messageChannelId,
- updateOneRecordInput: {
- isSyncEnabled: value,
- },
- });
- };
-
- useEffect(() => {
- if (!loading && !messageChannel) navigate(AppPath.NotFound);
- }, [loading, messageChannel, navigate]);
-
- if (!messageChannel) return null;
-
- return (
-
-
-
-
-
-
-
-
-
- }
- title="Auto-creation"
- value={!!messageChannel.isContactAutoCreationEnabled}
- onToggle={handleContactAutoCreationToggle}
- />
-
-
-
-
-
-
- }
- title="Sync emails"
- value={!!messageChannel.isSyncEnabled}
- onToggle={handleIsSyncEnabledToggle}
- />
-
-
-
- );
-};
diff --git a/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccountsEmails.stories.tsx b/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccountsEmails.stories.tsx
index 21bede0eb..bde4ce31d 100644
--- a/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccountsEmails.stories.tsx
+++ b/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccountsEmails.stories.tsx
@@ -1,4 +1,5 @@
import { Meta, StoryObj } from '@storybook/react';
+import { graphql, HttpResponse } from 'msw';
import {
PageDecorator,
@@ -25,4 +26,120 @@ export default meta;
export type Story = StoryObj;
-export const Default: Story = {};
+export const NoConnectedAccount: Story = {};
+
+export const TwoConnectedAccounts: Story = {
+ parameters: {
+ msw: {
+ handlers: [
+ ...graphqlMocks.handlers,
+ graphql.query('FindManyConnectedAccounts', () => {
+ return HttpResponse.json({
+ data: {
+ connectedAccounts: {
+ __typename: 'ConnectedAccountConnection',
+ totalCount: 1,
+ pageInfo: {
+ __typename: 'PageInfo',
+ hasNextPage: false,
+ startCursor: '',
+ endCursor: '',
+ },
+ edges: [
+ {
+ __typename: 'ConnectedAccountEdge',
+ cursor: '',
+ node: {
+ __typename: 'ConnectedAccount',
+ accessToken: '',
+ refreshToken: '',
+ updatedAt: '2024-07-03T20:03:35.064Z',
+ createdAt: '2024-07-03T20:03:35.064Z',
+ id: '20202020-954c-4d76-9a87-e5f072d4b7ef',
+ provider: 'google',
+ accountOwnerId: '20202020-03f2-4d83-b0d5-2ec2bcee72d4',
+ lastSyncHistoryId: '',
+ emailAliases: '',
+ handle: 'test.test@gmail.com',
+ authFailedAt: null,
+ },
+ },
+ ],
+ },
+ },
+ });
+ }),
+ graphql.query('FindManyMessageChannels', () => {
+ return HttpResponse.json({
+ data: {
+ messageChannels: {
+ __typename: 'MessageChannelConnection',
+ totalCount: 2,
+ pageInfo: {
+ __typename: 'PageInfo',
+ hasNextPage: false,
+ startCursor: '',
+ endCursor: '',
+ },
+ edges: [
+ {
+ __typename: 'MessageChannelEdge',
+ cursor: '',
+ node: {
+ __typename: 'MessageChannel',
+ handle: 'test.test@gmail.com',
+ excludeNonProfessionalEmails: true,
+ syncStageStartedAt: null,
+ id: '20202020-ef5a-4822-9e08-ce6e6a4dcb6f',
+ updatedAt: '2024-07-03T20:03:11.903Z',
+ createdAt: '2024-07-03T20:03:11.903Z',
+ connectedAccountId:
+ '20202020-954c-4d76-9a87-e5f072d4b7ef',
+ contactAutoCreationPolicy: 'SENT',
+ syncStage: 'PARTIAL_MESSAGE_LIST_FETCH_PENDING',
+ type: 'email',
+ isContactAutoCreationEnabled: true,
+ syncCursor: '1562764',
+ excludeGroupEmails: true,
+ throttleFailureCount: 0,
+ isSyncEnabled: true,
+ visibility: 'SHARE_EVERYTHING',
+ syncStatus: 'COMPLETED',
+ syncedAt: '2024-07-04T16:25:04.960Z',
+ },
+ },
+ {
+ __typename: 'MessageChannelEdge',
+ cursor: '',
+ node: {
+ __typename: 'MessageChannel',
+ handle: 'test.test2@gmail.com',
+ excludeNonProfessionalEmails: true,
+ syncStageStartedAt: null,
+ id: '20202020-ef5a-4822-9e08-ce6e6a4dcb6a',
+ updatedAt: '2024-07-03T20:03:11.903Z',
+ createdAt: '2024-07-03T20:03:11.903Z',
+ connectedAccountId:
+ '20202020-954c-4d76-9a87-e5f072d4b7ef',
+ contactAutoCreationPolicy: 'SENT',
+ syncStage: 'PARTIAL_MESSAGE_LIST_FETCH_PENDING',
+ type: 'email',
+ isContactAutoCreationEnabled: true,
+ syncCursor: '1562764',
+ excludeGroupEmails: true,
+ throttleFailureCount: 0,
+ isSyncEnabled: true,
+ visibility: 'SHARE_EVERYTHING',
+ syncStatus: 'COMPLETED',
+ syncedAt: '2024-07-04T16:25:04.960Z',
+ },
+ },
+ ],
+ },
+ },
+ });
+ }),
+ ],
+ },
+ },
+};
diff --git a/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccountsEmailsInboxSettings.stories.tsx b/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccountsEmailsInboxSettings.stories.tsx
deleted file mode 100644
index 6c23dd71c..000000000
--- a/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccountsEmailsInboxSettings.stories.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import { Meta, StoryObj } from '@storybook/react';
-import { within } from '@storybook/test';
-import { graphql, HttpResponse } from 'msw';
-
-import { MessageChannelVisibility } from '~/generated/graphql';
-import { SettingsAccountsEmailsInboxSettings } from '~/pages/settings/accounts/SettingsAccountsEmailsInboxSettings';
-import {
- PageDecorator,
- PageDecoratorArgs,
-} from '~/testing/decorators/PageDecorator';
-import { graphqlMocks } from '~/testing/graphqlMocks';
-
-const meta: Meta = {
- title: 'Pages/Settings/Accounts/SettingsAccountsEmailsInboxSettings',
- component: SettingsAccountsEmailsInboxSettings,
- decorators: [PageDecorator],
- args: {
- routePath: '/settings/accounts/emails/:accountUuid',
- routeParams: { ':accountUuid': '123' },
- },
- parameters: {
- layout: 'fullscreen',
- msw: {
- handlers: [
- graphql.query('FindOneMessageChannel', () => {
- return HttpResponse.json({
- data: {
- messageChannel: {
- id: '1',
- visibility: MessageChannelVisibility.ShareEverything,
- messageThreads: { edges: [] },
- createdAt: '2021-08-27T12:00:00Z',
- type: 'email',
- updatedAt: '2021-08-27T12:00:00Z',
- targetUrl: 'https://example.com/webhook',
- connectedAccountId: '1',
- handle: 'handle',
- connectedAccount: {
- id: '1',
- handle: 'handle',
- updatedAt: '2021-08-27T12:00:00Z',
- accessToken: 'accessToken',
- messageChannels: { edges: [] },
- refreshToken: 'refreshToken',
- __typename: 'ConnectedAccount',
- accountOwner: { id: '1', __typename: 'WorkspaceMember' },
- provider: 'provider',
- createdAt: '2021-08-27T12:00:00Z',
- accountOwnerId: '1',
- },
- __typename: 'MessageChannel',
- },
- },
- });
- }),
- graphqlMocks.handlers,
- ],
- },
- },
-};
-
-export default meta;
-
-export type Story = StoryObj;
-
-export const Default: Story = {
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
-
- await canvas.findByText('Email visibility');
- await canvas.findByText(
- 'Define what will be visible to other users in your workspace',
- );
- await canvas.findByText('Contact auto-creation');
- await canvas.findByText(
- 'Automatically create contacts for people you’ve sent emails to',
- );
- },
-};