diff --git a/packages/twenty-front/src/modules/accounts/types/CalendarChannel.ts b/packages/twenty-front/src/modules/accounts/types/CalendarChannel.ts new file mode 100644 index 000000000..173bf3c92 --- /dev/null +++ b/packages/twenty-front/src/modules/accounts/types/CalendarChannel.ts @@ -0,0 +1,12 @@ +export enum CalendarChannelVisibility { + Everything = 'SHARE_EVERYTHING', + Metadata = 'METADATA', +} + +export type CalendarChannel = { + id: string; + handle: string; + isContactAutoCreationEnabled?: boolean; + isSyncEnabled?: boolean; + visibility: CalendarChannelVisibility; +}; diff --git a/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts b/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts index 9886f09b7..18405ff22 100644 --- a/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts +++ b/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts @@ -4,6 +4,7 @@ export enum CoreObjectNameSingular { ApiKey = 'apiKey', Attachment = 'attachment', Blocklist = 'blocklist', + CalendarChannel = 'calendarChannel', CalendarEvent = 'calendarEvent', Comment = 'comment', Company = 'company', diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarAccountsListCard.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarChannelsListCard.tsx similarity index 56% rename from packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarAccountsListCard.tsx rename to packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarChannelsListCard.tsx index 542597631..e59476ce0 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarAccountsListCard.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarChannelsListCard.tsx @@ -2,6 +2,7 @@ import { useNavigate } from 'react-router-dom'; import styled from '@emotion/styled'; import { useRecoilValue } from 'recoil'; +import { CalendarChannel } from '@/accounts/types/CalendarChannel'; import { ConnectedAccount } from '@/accounts/types/ConnectedAccount'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; @@ -11,7 +12,6 @@ import { SettingsAccountsSynchronizationStatus } from '@/settings/accounts/compo import { IconChevronRight } from '@/ui/display/icon'; import { IconGoogleCalendar } from '@/ui/display/icon/components/IconGoogleCalendar'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; -import { mockedConnectedAccounts } from '~/testing/mock-data/accounts'; const StyledRowRightContainer = styled.div` align-items: center; @@ -19,30 +19,43 @@ const StyledRowRightContainer = styled.div` gap: ${({ theme }) => theme.spacing(1)}; `; -export const SettingsAccountsCalendarAccountsListCard = () => { +export const SettingsAccountsCalendarChannelsListCard = () => { const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const navigate = useNavigate(); - const { records: _accounts, loading } = useFindManyRecords({ - objectNameSingular: CoreObjectNameSingular.ConnectedAccount, - filter: { - accountOwnerId: { - eq: currentWorkspaceMember?.id, + const { records: accounts, loading: accountsLoading } = + useFindManyRecords({ + objectNameSingular: CoreObjectNameSingular.ConnectedAccount, + filter: { + accountOwnerId: { + eq: currentWorkspaceMember?.id, + }, }, - }, - }); + }); + + const { records: calendarChannels, loading: calendarChannelsLoading } = + useFindManyRecords({ + objectNameSingular: CoreObjectNameSingular.CalendarChannel, + filter: { + connectedAccountId: { + in: accounts.map((account) => account.id), + }, + }, + }); return ( - navigate(`/settings/accounts/calendars/${account.id}`) + items={calendarChannels} + isLoading={accountsLoading || calendarChannelsLoading} + onRowClick={(calendarChannel) => + navigate(`/settings/accounts/calendars/${calendarChannel.id}`) } RowIcon={IconGoogleCalendar} - RowRightComponent={({ account: _account }) => ( + RowRightComponent={({ item: calendarChannel }) => ( - + )} diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarVisibilitySettingsCard.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarVisibilitySettingsCard.tsx index 412d21fc4..1ae15b9b1 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarVisibilitySettingsCard.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarVisibilitySettingsCard.tsx @@ -1,16 +1,12 @@ import styled from '@emotion/styled'; +import { CalendarChannelVisibility } from '@/accounts/types/CalendarChannel'; import { SettingsAccountsRadioSettingsCard } from '@/settings/accounts/components/SettingsAccountsRadioSettingsCard'; import { SettingsAccountsVisibilitySettingCardMedia } from '@/settings/accounts/components/SettingsAccountsVisibilitySettingCardMedia'; -export enum EventSettingsVisibilityValue { - Everything = 'share_everything', - Metadata = 'metadata', -} - type SettingsAccountsEventVisibilitySettingsCardProps = { - onChange: (nextValue: EventSettingsVisibilityValue) => void; - value?: EventSettingsVisibilityValue; + onChange: (nextValue: CalendarChannelVisibility) => void; + value?: CalendarChannelVisibility; }; const StyledCardMedia = styled(SettingsAccountsVisibilitySettingCardMedia)` @@ -21,20 +17,20 @@ const eventSettingsVisibilityOptions = [ { title: 'Everything', description: 'The whole event details will be shared with your team.', - value: EventSettingsVisibilityValue.Everything, + value: CalendarChannelVisibility.Everything, cardMedia: , }, { title: 'Metadata', description: 'Only date & participants will be shared with your team.', - value: EventSettingsVisibilityValue.Metadata, + value: CalendarChannelVisibility.Metadata, cardMedia: , }, ]; export const SettingsAccountsEventVisibilitySettingsCard = ({ onChange, - value = EventSettingsVisibilityValue.Everything, + value = CalendarChannelVisibility.Everything, }: SettingsAccountsEventVisibilitySettingsCardProps) => ( , -> = { - accounts: Account[]; +type SettingsAccountsListCardItem = { + handle: string; + id: string; +}; + +type SettingsAccountsListCardProps = { + items: T[]; hasFooter?: boolean; isLoading?: boolean; - onRowClick?: (account: Account) => void; + onRowClick?: (item: T) => void; RowIcon?: IconComponent; - RowRightComponent: ComponentType<{ account: Account }>; + RowRightComponent: ComponentType<{ item: T }>; }; export const SettingsAccountsListCard = < - Account extends Pick = ConnectedAccount, + T extends SettingsAccountsListCardItem, >({ - accounts, + items, hasFooter, isLoading, onRowClick, RowIcon = IconGoogle, RowRightComponent, -}: SettingsAccountsListCardProps) => { +}: SettingsAccountsListCardProps) => { const theme = useTheme(); const navigate = useNavigate(); if (isLoading === true) return ; - if (!accounts.length) return ; + if (!items.length) return ; return ( - {accounts.map((account, index) => ( + {items.map((item, index) => ( } - divider={index < accounts.length - 1} - onClick={() => onRowClick?.(account)} + account={item} + rightComponent={} + divider={index < items.length - 1} + onClick={() => onRowClick?.(item)} /> ))} {hasFooter && ( diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsAccountsListCard.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsListCard.tsx similarity index 93% rename from packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsAccountsListCard.tsx rename to packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsListCard.tsx index 2fc6154f1..103bd86fd 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsAccountsListCard.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsListCard.tsx @@ -19,7 +19,7 @@ const StyledRowRightContainer = styled.div` gap: ${({ theme }) => theme.spacing(1)}; `; -export const SettingsAccountsEmailsAccountsListCard = () => { +export const SettingsAccountsMessageChannelsListCard = () => { const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const navigate = useNavigate(); @@ -52,13 +52,13 @@ export const SettingsAccountsEmailsAccountsListCard = () => { return ( navigate(`/settings/accounts/emails/${messageChannel.id}`) } RowIcon={IconGmail} - RowRightComponent={({ account: messageChannel }) => ( + RowRightComponent={({ item: messageChannel }) => ( ; + item: Pick; className?: string; }; export const SettingsAccountsRowDropdownMenu = ({ - account, + item: account, className, }: SettingsAccountsRowDropdownMenuProps) => { const dropdownId = `settings-account-row-${account.id}`; diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx index 227ad97de..48103bf3a 100644 --- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx +++ b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx @@ -1,13 +1,14 @@ import { addMinutes, endOfDay, min, startOfDay } from 'date-fns'; import { useRecoilValue } from 'recoil'; +import { CalendarChannel } from '@/accounts/types/CalendarChannel'; import { ConnectedAccount } from '@/accounts/types/ConnectedAccount'; import { CalendarMonthCard } from '@/activities/calendar/components/CalendarMonthCard'; import { CalendarContext } from '@/activities/calendar/contexts/CalendarContext'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; -import { SettingsAccountsCalendarAccountsListCard } from '@/settings/accounts/components/SettingsAccountsCalendarAccountsListCard'; +import { SettingsAccountsCalendarChannelsListCard } from '@/settings/accounts/components/SettingsAccountsCalendarChannelsListCard'; import { SettingsAccountsCalendarDisplaySettings } from '@/settings/accounts/components/SettingsAccountsCalendarDisplaySettings'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; @@ -21,11 +22,10 @@ import { TimelineCalendarEvent, TimelineCalendarEventVisibility, } from '~/generated-metadata/graphql'; -import { mockedConnectedAccounts } from '~/testing/mock-data/accounts'; export const SettingsAccountsCalendars = () => { const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); - const { records: _accounts } = useFindManyRecords({ + const { records: accounts } = useFindManyRecords({ objectNameSingular: CoreObjectNameSingular.ConnectedAccount, filter: { accountOwnerId: { @@ -34,6 +34,15 @@ export const SettingsAccountsCalendars = () => { }, }); + const { records: calendarChannels } = useFindManyRecords({ + objectNameSingular: CoreObjectNameSingular.CalendarChannel, + filter: { + connectedAccountId: { + in: accounts.map((account) => account.id), + }, + }, + }); + const exampleStartDate = new Date(); const exampleEndDate = min([ addMinutes(exampleStartDate, 30), @@ -85,10 +94,9 @@ export const SettingsAccountsCalendars = () => { title="Calendar settings" description="Sync your calendars and set your preferences" /> - + - {/* TODO: retrieve connected accounts data from back-end when the Calendar feature is ready. */} - {!!mockedConnectedAccounts.length && ( + {!!calendarChannels.length && ( <>
theme.spacing(6)}; @@ -24,10 +29,52 @@ const StyledCardMedia = styled(SettingsAccountsCardMedia)` export const SettingsAccountsCalendarsSettings = () => { const theme = useTheme(); - const { accountUuid = '' } = useParams(); - const connectedAccount = mockedConnectedAccounts.find( - ({ id }) => id === accountUuid, - ); + const navigate = useNavigate(); + + const { accountUuid: calendarChannelId = '' } = useParams(); + + const { record: calendarChannel, loading } = + useFindOneRecord({ + objectNameSingular: CoreObjectNameSingular.CalendarChannel, + objectRecordId: calendarChannelId, + }); + + const { updateOneRecord } = useUpdateOneRecord({ + objectNameSingular: CoreObjectNameSingular.CalendarChannel, + }); + + const handleVisibilityChange = (value: CalendarChannelVisibility) => { + updateOneRecord({ + idToUpdate: calendarChannelId, + updateOneRecordInput: { + visibility: value, + }, + }); + }; + + const handleContactAutoCreationToggle = (value: boolean) => { + updateOneRecord({ + idToUpdate: calendarChannelId, + updateOneRecordInput: { + isContactAutoCreationEnabled: value, + }, + }); + }; + + const handleSyncEventsToggle = (value: boolean) => { + updateOneRecord({ + idToUpdate: calendarChannelId, + updateOneRecordInput: { + isSyncEnabled: value, + }, + }); + }; + + useEffect(() => { + if (!loading && !calendarChannel) navigate(AppPath.NotFound); + }, [loading, calendarChannel, navigate]); + + if (!calendarChannel) return null; return ( @@ -42,7 +89,7 @@ export const SettingsAccountsCalendarsSettings = () => { children: 'Calendars', href: getSettingsPagePath(SettingsPath.AccountsCalendars), }, - { children: connectedAccount?.handle || '' }, + { children: calendarChannel?.handle || '' }, ]} />
@@ -51,8 +98,8 @@ export const SettingsAccountsCalendarsSettings = () => { description="Define what will be visible to other users in your workspace" /> {}} + value={calendarChannel.visibility} + onChange={handleVisibilityChange} />
@@ -70,8 +117,8 @@ export const SettingsAccountsCalendarsSettings = () => { } title="Auto-creation" - value={false} - onToggle={(_value) => {}} + value={!!calendarChannel.isContactAutoCreationEnabled} + onToggle={handleContactAutoCreationToggle} />
@@ -89,8 +136,8 @@ export const SettingsAccountsCalendarsSettings = () => { } title="Sync events" - value={false} - onToggle={(_value) => {}} + value={!!calendarChannel.isSyncEnabled} + onToggle={handleSyncEventsToggle} />
diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx index 6aececd6a..5acc9461e 100644 --- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx +++ b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx @@ -1,4 +1,4 @@ -import { SettingsAccountsEmailsAccountsListCard } from '@/settings/accounts/components/SettingsAccountsEmailsAccountsListCard'; +import { SettingsAccountsMessageChannelsListCard } from '@/settings/accounts/components/SettingsAccountsMessageChannelsListCard'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { IconSettings } from '@/ui/display/icon'; import { H2Title } from '@/ui/display/typography/components/H2Title'; @@ -20,7 +20,7 @@ export const SettingsAccountsEmails = () => ( title="Emails sync" description="Sync your inboxes and set your privacy settings" /> - +