4971 add issyncenabled toggle in messaging settings (#4995)
- Closes #4971 - Fix calendar import to take isSyncEnabled into account
This commit is contained in:
@ -4,6 +4,6 @@ export type MessageChannel = {
|
|||||||
id: string;
|
id: string;
|
||||||
handle: string;
|
handle: string;
|
||||||
isContactAutoCreationEnabled?: boolean;
|
isContactAutoCreationEnabled?: boolean;
|
||||||
isSynced?: boolean;
|
isSyncEnabled: boolean;
|
||||||
visibility: InboxSettingsVisibilityValue;
|
visibility: InboxSettingsVisibilityValue;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -57,7 +57,9 @@ export const SettingsAccountsMessageChannelsListCard = () => {
|
|||||||
...messageChannel,
|
...messageChannel,
|
||||||
syncStatus: messageChannel.connectedAccount?.authFailedAt
|
syncStatus: messageChannel.connectedAccount?.authFailedAt
|
||||||
? 'failed'
|
? 'failed'
|
||||||
: 'synced',
|
: messageChannel.isSyncEnabled
|
||||||
|
? 'synced'
|
||||||
|
: 'notSynced',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import { IconSettings, IconUser } from 'twenty-ui';
|
import { IconRefresh, IconSettings, IconUser } from 'twenty-ui';
|
||||||
|
|
||||||
import { MessageChannel } from '@/accounts/types/MessageChannel';
|
import { MessageChannel } from '@/accounts/types/MessageChannel';
|
||||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||||
@ -52,6 +52,15 @@ export const SettingsAccountsEmailsInboxSettings = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleIsSyncEnabledToggle = (value: boolean) => {
|
||||||
|
updateOneRecord({
|
||||||
|
idToUpdate: messageChannelId,
|
||||||
|
updateOneRecordInput: {
|
||||||
|
isSyncEnabled: value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!loading && !messageChannel) navigate(AppPath.NotFound);
|
if (!loading && !messageChannel) navigate(AppPath.NotFound);
|
||||||
}, [loading, messageChannel, navigate]);
|
}, [loading, messageChannel, navigate]);
|
||||||
@ -68,7 +77,6 @@ export const SettingsAccountsEmailsInboxSettings = () => {
|
|||||||
{ children: messageChannel.handle || '' },
|
{ children: messageChannel.handle || '' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
{/* TODO : discuss the desired sync behaviour and add Synchronization section */}
|
|
||||||
<Section>
|
<Section>
|
||||||
<H2Title
|
<H2Title
|
||||||
title="Email visibility"
|
title="Email visibility"
|
||||||
@ -98,6 +106,25 @@ export const SettingsAccountsEmailsInboxSettings = () => {
|
|||||||
onToggle={handleContactAutoCreationToggle}
|
onToggle={handleContactAutoCreationToggle}
|
||||||
/>
|
/>
|
||||||
</Section>
|
</Section>
|
||||||
|
<Section>
|
||||||
|
<H2Title
|
||||||
|
title="Synchronization"
|
||||||
|
description="Past and future emails will automatically be synced to this workspace"
|
||||||
|
/>
|
||||||
|
<SettingsAccountsToggleSettingCard
|
||||||
|
cardMedia={
|
||||||
|
<SettingsAccountsCardMedia>
|
||||||
|
<IconRefresh
|
||||||
|
size={theme.icon.size.sm}
|
||||||
|
stroke={theme.icon.stroke.lg}
|
||||||
|
/>
|
||||||
|
</SettingsAccountsCardMedia>
|
||||||
|
}
|
||||||
|
title="Sync emails"
|
||||||
|
value={!!messageChannel.isSyncEnabled}
|
||||||
|
onToggle={handleIsSyncEnabledToggle}
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
</SettingsPageContainer>
|
</SettingsPageContainer>
|
||||||
</SubMenuTopBarContainer>
|
</SubMenuTopBarContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -35,7 +35,8 @@ import { DeleteConnectedAccountAssociatedCalendarDataJob } from 'src/modules/cal
|
|||||||
import { GoogleCalendarSyncJob } from 'src/modules/calendar/jobs/google-calendar-sync.job';
|
import { GoogleCalendarSyncJob } from 'src/modules/calendar/jobs/google-calendar-sync.job';
|
||||||
import { CalendarEventCleanerModule } from 'src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.module';
|
import { CalendarEventCleanerModule } from 'src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.module';
|
||||||
import { CalendarEventParticipantModule } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.module';
|
import { CalendarEventParticipantModule } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.module';
|
||||||
import { GoogleCalendarSyncModule } from 'src/modules/calendar/services/google-calendar-sync.module';
|
import { GoogleCalendarSyncModule } from 'src/modules/calendar/services/google-calendar-sync/google-calendar-sync.module';
|
||||||
|
import { WorkspaceGoogleCalendarSyncModule } from 'src/modules/calendar/services/workspace-google-calendar-sync/workspace-google-calendar-sync.module';
|
||||||
import { AutoCompaniesAndContactsCreationModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module';
|
import { AutoCompaniesAndContactsCreationModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module';
|
||||||
import { CreateCompanyAndContactJob } from 'src/modules/connected-account/auto-companies-and-contacts-creation/jobs/create-company-and-contact.job';
|
import { CreateCompanyAndContactJob } from 'src/modules/connected-account/auto-companies-and-contacts-creation/jobs/create-company-and-contact.job';
|
||||||
import { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module';
|
import { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module';
|
||||||
@ -63,6 +64,7 @@ import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-obj
|
|||||||
EnvironmentModule,
|
EnvironmentModule,
|
||||||
HttpModule,
|
HttpModule,
|
||||||
GoogleCalendarSyncModule,
|
GoogleCalendarSyncModule,
|
||||||
|
WorkspaceGoogleCalendarSyncModule,
|
||||||
ObjectMetadataModule,
|
ObjectMetadataModule,
|
||||||
StripeModule,
|
StripeModule,
|
||||||
ThreadCleanerModule,
|
ThreadCleanerModule,
|
||||||
|
|||||||
@ -170,6 +170,7 @@ export const messageChannelStandardFieldIds = {
|
|||||||
type: '20202020-ae95-42d9-a3f1-797a2ea22122',
|
type: '20202020-ae95-42d9-a3f1-797a2ea22122',
|
||||||
isContactAutoCreationEnabled: '20202020-fabd-4f14-b7c6-3310f6d132c6',
|
isContactAutoCreationEnabled: '20202020-fabd-4f14-b7c6-3310f6d132c6',
|
||||||
messageChannelMessageAssociations: '20202020-49b8-4766-88fd-75f1e21b3d5f',
|
messageChannelMessageAssociations: '20202020-49b8-4766-88fd-75f1e21b3d5f',
|
||||||
|
isSyncEnabled: '20202020-d9a6-48e9-990b-b97fdf22e8dd',
|
||||||
syncCursor: '20202020-79d1-41cf-b738-bcf5ed61e256',
|
syncCursor: '20202020-79d1-41cf-b738-bcf5ed61e256',
|
||||||
syncedAt: '20202020-263d-4c6b-ad51-137ada56f7d4',
|
syncedAt: '20202020-263d-4c6b-ad51-137ada56f7d4',
|
||||||
syncStatus: '20202020-56a1-4f7e-9880-a8493bb899cc',
|
syncStatus: '20202020-56a1-4f7e-9880-a8493bb899cc',
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
|||||||
|
|
||||||
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
import { GoogleCalendarSyncCommand } from 'src/modules/calendar/commands/google-calendar-sync.command';
|
import { GoogleCalendarSyncCommand } from 'src/modules/calendar/commands/google-calendar-sync.command';
|
||||||
|
import { WorkspaceGoogleCalendarSyncModule } from 'src/modules/calendar/services/workspace-google-calendar-sync/workspace-google-calendar-sync.module';
|
||||||
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
|
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
|
||||||
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/st
|
|||||||
ConnectedAccountObjectMetadata,
|
ConnectedAccountObjectMetadata,
|
||||||
CalendarChannelObjectMetadata,
|
CalendarChannelObjectMetadata,
|
||||||
]),
|
]),
|
||||||
|
WorkspaceGoogleCalendarSyncModule,
|
||||||
],
|
],
|
||||||
providers: [GoogleCalendarSyncCommand],
|
providers: [GoogleCalendarSyncCommand],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,18 +1,6 @@
|
|||||||
import { Inject } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { Command, CommandRunner, Option } from 'nest-commander';
|
import { Command, CommandRunner, Option } from 'nest-commander';
|
||||||
|
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { WorkspaceGoogleCalendarSyncService } from 'src/modules/calendar/services/workspace-google-calendar-sync/workspace-google-calendar-sync.service';
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
|
||||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
|
||||||
import {
|
|
||||||
GoogleCalendarSyncJobData,
|
|
||||||
GoogleCalendarSyncJob,
|
|
||||||
} from 'src/modules/calendar/jobs/google-calendar-sync.job';
|
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
|
||||||
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
|
||||||
import { CalendarChannelRepository } from 'src/modules/calendar/repositories/calendar-channel.repository';
|
|
||||||
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
|
|
||||||
|
|
||||||
interface GoogleCalendarSyncOptions {
|
interface GoogleCalendarSyncOptions {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
@ -25,25 +13,11 @@ interface GoogleCalendarSyncOptions {
|
|||||||
})
|
})
|
||||||
export class GoogleCalendarSyncCommand extends CommandRunner {
|
export class GoogleCalendarSyncCommand extends CommandRunner {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(MessageQueue.messagingQueue)
|
private readonly workspaceGoogleCalendarSyncService: WorkspaceGoogleCalendarSyncService,
|
||||||
private readonly messageQueueService: MessageQueueService,
|
|
||||||
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
|
||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
|
||||||
@InjectObjectMetadataRepository(CalendarChannelObjectMetadata)
|
|
||||||
private readonly calendarChannelRepository: CalendarChannelRepository,
|
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
async run(
|
|
||||||
_passedParam: string[],
|
|
||||||
options: GoogleCalendarSyncOptions,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.fetchWorkspaceCalendars(options.workspaceId);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Option({
|
@Option({
|
||||||
flags: '-w, --workspace-id [workspace_id]',
|
flags: '-w, --workspace-id [workspace_id]',
|
||||||
description: 'workspace id',
|
description: 'workspace id',
|
||||||
@ -53,31 +27,14 @@ export class GoogleCalendarSyncCommand extends CommandRunner {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async fetchWorkspaceCalendars(workspaceId: string): Promise<void> {
|
async run(
|
||||||
const connectedAccounts =
|
_passedParam: string[],
|
||||||
await this.connectedAccountRepository.getAll(workspaceId);
|
options: GoogleCalendarSyncOptions,
|
||||||
|
): Promise<void> {
|
||||||
|
await this.workspaceGoogleCalendarSyncService.startWorkspaceGoogleCalendarSync(
|
||||||
|
options.workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
for (const connectedAccount of connectedAccounts) {
|
return;
|
||||||
const calendarChannel =
|
|
||||||
await this.calendarChannelRepository.getFirstByConnectedAccountId(
|
|
||||||
connectedAccount.id,
|
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!calendarChannel?.isSyncEnabled) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.messageQueueService.add<GoogleCalendarSyncJobData>(
|
|
||||||
GoogleCalendarSyncJob.name,
|
|
||||||
{
|
|
||||||
workspaceId,
|
|
||||||
connectedAccountId: connectedAccount.id,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
retryLimit: 2,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,10 +11,7 @@ import {
|
|||||||
} from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
} from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { WorkspaceGoogleCalendarSyncService } from 'src/modules/calendar/services/workspace-google-calendar-sync/workspace-google-calendar-sync.service';
|
||||||
import { CalendarChannelRepository } from 'src/modules/calendar/repositories/calendar-channel.repository';
|
|
||||||
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
|
|
||||||
import { GoogleCalendarSyncService } from 'src/modules/calendar/services/google-calendar-sync.service';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GoogleCalendarSyncCronJob implements MessageQueueJob<undefined> {
|
export class GoogleCalendarSyncCronJob implements MessageQueueJob<undefined> {
|
||||||
@ -23,11 +20,9 @@ export class GoogleCalendarSyncCronJob implements MessageQueueJob<undefined> {
|
|||||||
private readonly workspaceRepository: Repository<Workspace>,
|
private readonly workspaceRepository: Repository<Workspace>,
|
||||||
@InjectRepository(DataSourceEntity, 'metadata')
|
@InjectRepository(DataSourceEntity, 'metadata')
|
||||||
private readonly dataSourceRepository: Repository<DataSourceEntity>,
|
private readonly dataSourceRepository: Repository<DataSourceEntity>,
|
||||||
@InjectObjectMetadataRepository(CalendarChannelObjectMetadata)
|
|
||||||
private readonly calendarChannelRepository: CalendarChannelRepository,
|
|
||||||
@InjectRepository(FeatureFlagEntity, 'core')
|
@InjectRepository(FeatureFlagEntity, 'core')
|
||||||
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
||||||
private readonly googleCalendarSyncService: GoogleCalendarSyncService,
|
private readonly workspaceGoogleCalendarSyncService: WorkspaceGoogleCalendarSyncService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(): Promise<void> {
|
async handle(): Promise<void> {
|
||||||
@ -62,20 +57,8 @@ export class GoogleCalendarSyncCronJob implements MessageQueueJob<undefined> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (const workspaceId of workspaceIdsWithDataSources) {
|
for (const workspaceId of workspaceIdsWithDataSources) {
|
||||||
await this.startWorkspaceGoogleCalendarSync(workspaceId);
|
await this.workspaceGoogleCalendarSyncService.startWorkspaceGoogleCalendarSync(
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async startWorkspaceGoogleCalendarSync(
|
|
||||||
workspaceId: string,
|
|
||||||
): Promise<void> {
|
|
||||||
const calendarChannels =
|
|
||||||
await this.calendarChannelRepository.getAll(workspaceId);
|
|
||||||
|
|
||||||
for (const calendarChannel of calendarChannels) {
|
|
||||||
await this.googleCalendarSyncService.startGoogleCalendarSync(
|
|
||||||
workspaceId,
|
workspaceId,
|
||||||
calendarChannel.connectedAccountId,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
||||||
|
|
||||||
import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service';
|
import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service';
|
||||||
import { GoogleCalendarSyncService } from 'src/modules/calendar/services/google-calendar-sync.service';
|
import { GoogleCalendarSyncService } from 'src/modules/calendar/services/google-calendar-sync/google-calendar-sync.service';
|
||||||
|
|
||||||
export type GoogleCalendarSyncJobData = {
|
export type GoogleCalendarSyncJobData = {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repos
|
|||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
import { CalendarEventCleanerModule } from 'src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.module';
|
import { CalendarEventCleanerModule } from 'src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.module';
|
||||||
import { CalendarEventParticipantModule } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.module';
|
import { CalendarEventParticipantModule } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.module';
|
||||||
import { GoogleCalendarSyncService } from 'src/modules/calendar/services/google-calendar-sync.service';
|
import { GoogleCalendarSyncService } from 'src/modules/calendar/services/google-calendar-sync/google-calendar-sync.service';
|
||||||
import { CalendarProvidersModule } from 'src/modules/calendar/services/providers/calendar-providers.module';
|
import { CalendarProvidersModule } from 'src/modules/calendar/services/providers/calendar-providers.module';
|
||||||
import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata';
|
import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata';
|
||||||
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
|
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { WorkspaceGoogleCalendarSyncService } from 'src/modules/calendar/services/workspace-google-calendar-sync/workspace-google-calendar-sync.service';
|
||||||
|
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([CalendarChannelObjectMetadata]),
|
||||||
|
],
|
||||||
|
providers: [WorkspaceGoogleCalendarSyncService],
|
||||||
|
exports: [WorkspaceGoogleCalendarSyncService],
|
||||||
|
})
|
||||||
|
export class WorkspaceGoogleCalendarSyncModule {}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator';
|
||||||
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import {
|
||||||
|
GoogleCalendarSyncJobData,
|
||||||
|
GoogleCalendarSyncJob,
|
||||||
|
} from 'src/modules/calendar/jobs/google-calendar-sync.job';
|
||||||
|
import { CalendarChannelRepository } from 'src/modules/calendar/repositories/calendar-channel.repository';
|
||||||
|
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class WorkspaceGoogleCalendarSyncService {
|
||||||
|
constructor(
|
||||||
|
@InjectObjectMetadataRepository(CalendarChannelObjectMetadata)
|
||||||
|
private readonly calendarChannelRepository: CalendarChannelRepository,
|
||||||
|
@InjectMessageQueue(MessageQueue.calendarQueue)
|
||||||
|
private readonly messageQueueService: MessageQueueService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async startWorkspaceGoogleCalendarSync(
|
||||||
|
workspaceId: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const calendarChannels =
|
||||||
|
await this.calendarChannelRepository.getAll(workspaceId);
|
||||||
|
|
||||||
|
for (const calendarChannel of calendarChannels) {
|
||||||
|
if (!calendarChannel?.isSyncEnabled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.messageQueueService.add<GoogleCalendarSyncJobData>(
|
||||||
|
GoogleCalendarSyncJob.name,
|
||||||
|
{
|
||||||
|
workspaceId,
|
||||||
|
connectedAccountId: calendarChannel.connectedAccountId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
retryLimit: 2,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,17 +5,17 @@ import { Repository, In } from 'typeorm';
|
|||||||
|
|
||||||
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
||||||
|
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
|
||||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
|
||||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
|
||||||
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
|
||||||
import {
|
import {
|
||||||
GmailPartialSyncJob as GmailPartialSyncJob,
|
GmailPartialSyncJobData,
|
||||||
GmailPartialSyncJobData as GmailPartialSyncJobData,
|
GmailPartialSyncJob,
|
||||||
} from 'src/modules/messaging/jobs/gmail-partial-sync.job';
|
} from 'src/modules/messaging/jobs/gmail-partial-sync.job';
|
||||||
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GmailPartialSyncCronJob implements MessageQueueJob<undefined> {
|
export class GmailPartialSyncCronJob implements MessageQueueJob<undefined> {
|
||||||
@ -28,8 +28,8 @@ export class GmailPartialSyncCronJob implements MessageQueueJob<undefined> {
|
|||||||
private readonly dataSourceRepository: Repository<DataSourceEntity>,
|
private readonly dataSourceRepository: Repository<DataSourceEntity>,
|
||||||
@Inject(MessageQueue.messagingQueue)
|
@Inject(MessageQueue.messagingQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
@InjectObjectMetadataRepository(MessageChannelObjectMetadata)
|
||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
private readonly messageChannelRepository: MessageChannelRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(): Promise<void> {
|
async handle(): Promise<void> {
|
||||||
@ -59,15 +59,22 @@ export class GmailPartialSyncCronJob implements MessageQueueJob<undefined> {
|
|||||||
|
|
||||||
private async enqueuePartialSyncs(workspaceId: string): Promise<void> {
|
private async enqueuePartialSyncs(workspaceId: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const connectedAccounts =
|
const messageChannels =
|
||||||
await this.connectedAccountRepository.getAll(workspaceId);
|
await this.messageChannelRepository.getAll(workspaceId);
|
||||||
|
|
||||||
|
for (const messageChannel of messageChannels) {
|
||||||
|
if (!messageChannel?.isSyncEnabled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (const connectedAccount of connectedAccounts) {
|
|
||||||
await this.messageQueueService.add<GmailPartialSyncJobData>(
|
await this.messageQueueService.add<GmailPartialSyncJobData>(
|
||||||
GmailPartialSyncJob.name,
|
GmailPartialSyncJob.name,
|
||||||
{
|
{
|
||||||
workspaceId,
|
workspaceId,
|
||||||
connectedAccountId: connectedAccount.id,
|
connectedAccountId: messageChannel.connectedAccountId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
retryLimit: 2,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,7 +63,9 @@ export class GmailFetchMessageContentFromCacheService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectedAccount.authFailedAt) {
|
const { accessToken, refreshToken, authFailedAt } = connectedAccount;
|
||||||
|
|
||||||
|
if (authFailedAt) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Connected account ${connectedAccountId} in workspace ${workspaceId} is in a failed state. Skipping...`,
|
`Connected account ${connectedAccountId} in workspace ${workspaceId} is in a failed state. Skipping...`,
|
||||||
);
|
);
|
||||||
@ -71,9 +73,6 @@ export class GmailFetchMessageContentFromCacheService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const accessToken = connectedAccount.accessToken;
|
|
||||||
const refreshToken = connectedAccount.refreshToken;
|
|
||||||
|
|
||||||
if (!refreshToken) {
|
if (!refreshToken) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`No refresh token found for connected account ${connectedAccountId} in workspace ${workspaceId}`,
|
`No refresh token found for connected account ${connectedAccountId} in workspace ${workspaceId}`,
|
||||||
|
|||||||
@ -127,6 +127,16 @@ export class MessageChannelObjectMetadata extends BaseObjectMetadata {
|
|||||||
})
|
})
|
||||||
isContactAutoCreationEnabled: boolean;
|
isContactAutoCreationEnabled: boolean;
|
||||||
|
|
||||||
|
@FieldMetadata({
|
||||||
|
standardId: messageChannelStandardFieldIds.isSyncEnabled,
|
||||||
|
type: FieldMetadataType.BOOLEAN,
|
||||||
|
label: 'Is Sync Enabled',
|
||||||
|
description: 'Is Sync Enabled',
|
||||||
|
icon: 'IconRefresh',
|
||||||
|
defaultValue: true,
|
||||||
|
})
|
||||||
|
isSyncEnabled: boolean;
|
||||||
|
|
||||||
@FieldMetadata({
|
@FieldMetadata({
|
||||||
standardId:
|
standardId:
|
||||||
messageChannelStandardFieldIds.messageChannelMessageAssociations,
|
messageChannelStandardFieldIds.messageChannelMessageAssociations,
|
||||||
|
|||||||
Reference in New Issue
Block a user