Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3889 activate settingsaccountsemailsinboxsettings #3962

Merged
merged 32 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f5b6ded
update email visibility in settings
bosiraphael Feb 8, 2024
74e0f37
improve styling
bosiraphael Feb 8, 2024
507ebb6
Add contact auto creation toggle to inbox settings
bosiraphael Feb 9, 2024
321a864
re
bosiraphael Feb 9, 2024
a61cd70
update Icon
bosiraphael Feb 9, 2024
a99ff9c
create job
bosiraphael Feb 9, 2024
76bffe2
Add logic to create contacts and companies for message participants w…
bosiraphael Feb 9, 2024
b082c0f
Merge branch 'main' into 3889-activate-settingsaccountsemailsinboxset…
bosiraphael Feb 12, 2024
18e2fb3
add listener
bosiraphael Feb 12, 2024
ea397f8
wip
bosiraphael Feb 12, 2024
ebc0309
wip
bosiraphael Feb 12, 2024
12ad146
Merge branch 'main' into 3889-activate-settingsaccountsemailsinboxset…
bosiraphael Feb 13, 2024
11ca600
refactoring
bosiraphael Feb 13, 2024
c3072f7
improve structure
bosiraphael Feb 13, 2024
5d2af85
Add isContactAutoCreationEnabled method to MessageChannelService
bosiraphael Feb 13, 2024
b3a328a
wip
bosiraphael Feb 13, 2024
6e8f44b
wip
bosiraphael Feb 13, 2024
6ed7862
clean
bosiraphael Feb 13, 2024
78e3780
add job
bosiraphael Feb 13, 2024
824b35d
fix bug
bosiraphael Feb 13, 2024
e3c7090
contact creation is working
bosiraphael Feb 13, 2024
1ba267c
wip
bosiraphael Feb 13, 2024
3b39052
working
bosiraphael Feb 14, 2024
14e55b2
improve code
bosiraphael Feb 14, 2024
6f61c76
improve typing
bosiraphael Feb 14, 2024
c779661
Merge branch 'main' into 3889-activate-settingsaccountsemailsinboxset…
bosiraphael Feb 14, 2024
8980d8b
resolve conflicts
bosiraphael Feb 14, 2024
3415af2
fix
bosiraphael Feb 14, 2024
e5a8c05
create company repository
bosiraphael Feb 14, 2024
20f42a5
move util
bosiraphael Feb 14, 2024
8f95279
wip
bosiraphael Feb 14, 2024
7950170
fix
bosiraphael Feb 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styled from '@emotion/styled';

import { MessageChannel } from '@/accounts/types/MessageChannel';
import { SettingsAccountsInboxSettingsCardMedia } from '@/settings/accounts/components/SettingsAccountsInboxSettingsCardMedia';
import { IconSend } from '@/ui/display/icon';
import { IconUser } from '@/ui/display/icon';
import { H2Title } from '@/ui/display/typography/components/H2Title';
import { Toggle } from '@/ui/input/components/Toggle';
import { Card } from '@/ui/layout/card/components/Card';
Expand Down Expand Up @@ -43,7 +43,7 @@ export const SettingsAccountsInboxSettingsContactAutoCreateSection = ({
<Card>
<StyledCardContent>
<SettingsAccountsInboxSettingsCardMedia>
<IconSend size={theme.icon.size.sm} stroke={theme.icon.stroke.lg} />
<IconUser size={theme.icon.size.sm} stroke={theme.icon.stroke.lg} />
</SettingsAccountsInboxSettingsCardMedia>
<StyledTitle>Auto-creation</StyledTitle>
<Toggle
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import styled from '@emotion/styled';
import { SoonPill } from 'tsup.ui.index';

import { SettingsAccountsInboxSettingsCardMedia } from '@/settings/accounts/components/SettingsAccountsInboxSettingsCardMedia';
import { H2Title } from '@/ui/display/typography/components/H2Title';
Expand All @@ -23,7 +22,11 @@ const StyledCardContent = styled(CardContent)`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(4)};
opacity: 0.56;
cursor: pointer;

&:hover {
background: ${({ theme }) => theme.background.transparent.lighter};
}
`;

const StyledCardMedia = styled(SettingsAccountsInboxSettingsCardMedia)`
Expand Down Expand Up @@ -61,16 +64,6 @@ const StyledRadio = styled(Radio)`
margin-left: auto;
`;

const StyledSoonPill = styled(SoonPill)`
position: absolute;
right: 0;
top: 0;
`;

const StyledSection = styled(Section)`
position: relative;
`;

const inboxSettingsVisibilityOptions = [
{
title: 'Everything',
Expand Down Expand Up @@ -108,12 +101,11 @@ export const SettingsAccountsInboxSettingsVisibilitySection = ({
onChange,
value = InboxSettingsVisibilityValue.Everything,
}: SettingsAccountsInboxSettingsVisibilitySectionProps) => (
<StyledSection>
<Section>
<H2Title
title="Email visibility"
description="Define what will be visible to other users in your workspace"
/>
<StyledSoonPill />
<Card>
{inboxSettingsVisibilityOptions.map(
(
Expand All @@ -123,6 +115,7 @@ export const SettingsAccountsInboxSettingsVisibilitySection = ({
<StyledCardContent
key={optionValue}
divider={index < inboxSettingsVisibilityOptions.length - 1}
onClick={() => onChange(optionValue)}
>
<StyledCardMedia>
<StyledMetadataSkeleton isActive={visibleElements.metadata} />
Expand All @@ -137,11 +130,10 @@ export const SettingsAccountsInboxSettingsVisibilitySection = ({
value={optionValue}
onCheckedChange={() => onChange(optionValue)}
checked={value === optionValue}
disabled={true}
/>
</StyledCardContent>
),
)}
</Card>
</StyledSection>
</Section>
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useNavigate, useParams } from 'react-router-dom';
import { MessageChannel } from '@/accounts/types/MessageChannel';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { SettingsAccountsInboxSettingsContactAutoCreateSection } from '@/settings/accounts/components/SettingsAccountsInboxSettingsContactAutoCreationSection';
import {
InboxSettingsVisibilityValue,
SettingsAccountsInboxSettingsVisibilitySection,
Expand Down Expand Up @@ -36,6 +37,15 @@ export const SettingsAccountsEmailsInboxSettings = () => {
});
};

const handleContactAutoCreationToggle = (value: boolean) => {
updateOneRecord({
idToUpdate: messageChannelId,
updateOneRecordInput: {
isContactAutoCreationEnabled: value,
},
});
};

useEffect(() => {
if (!loading && !messageChannel) navigate(AppPath.NotFound);
}, [loading, messageChannel, navigate]);
Expand All @@ -61,11 +71,10 @@ export const SettingsAccountsEmailsInboxSettings = () => {
value={messageChannel?.visibility}
onChange={handleVisibilityChange}
/>
{/* TODO : Add this section when the backend will be ready to auto create contacts */}
{/* <SettingsAccountsInboxSettingsContactAutoCreateSection
<SettingsAccountsInboxSettingsContactAutoCreateSection
messageChannel={messageChannel}
onToggle={handleContactAutoCreationToggle}
/> */}
/>
</SettingsPageContainer>
</SubMenuTopBarContainer>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ export class GoogleGmailService {
);

await manager.query(
`INSERT INTO ${dataSourceMetadata.schema}."messageChannel" ("visibility", "handle", "connectedAccountId", "type") VALUES ($1, $2, $3, $4)`,
['share_everything', handle, connectedAccountId, 'email'],
`INSERT INTO ${dataSourceMetadata.schema}."messageChannel" ("visibility", "handle", "connectedAccountId", "type", "isContactAutoCreationEnabled") VALUES ($1, $2, $3, $4, $5)`,
['share_everything', handle, connectedAccountId, 'email', true],
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import { FeatureFlagEntity } from 'src/core/feature-flag/feature-flag.entity';
import { FetchAllWorkspacesMessagesJob } from 'src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.job';
import { ConnectedAccountModule } from 'src/workspace/messaging/repositories/connected-account/connected-account.module';
import { MatchMessageParticipantJob } from 'src/workspace/messaging/jobs/match-message-participant.job';
import { CreateCompaniesAndContactsAfterSyncJob } from 'src/workspace/messaging/jobs/create-companies-and-contacts-after-sync.job';
import { CreateCompaniesAndContactsModule } from 'src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.module';
import { MessageChannelModule } from 'src/workspace/messaging/repositories/message-channel/message-channel.module';
import { MessageParticipantModule } from 'src/workspace/messaging/repositories/message-participant/message-participant.module';

@Module({
Expand All @@ -36,6 +39,8 @@ import { MessageParticipantModule } from 'src/workspace/messaging/repositories/m
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
ConnectedAccountModule,
MessageParticipantModule,
CreateCompaniesAndContactsModule,
MessageChannelModule,
],
providers: [
{
Expand Down Expand Up @@ -67,6 +72,10 @@ import { MessageParticipantModule } from 'src/workspace/messaging/repositories/m
provide: MatchMessageParticipantJob.name,
useClass: MatchMessageParticipantJob,
},
{
provide: CreateCompaniesAndContactsAfterSyncJob.name,
useClass: CreateCompaniesAndContactsAfterSyncJob,
},
],
})
export class JobsModule {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Injectable, Logger } from '@nestjs/common';

import { CreateContactsAndCompaniesAfterSyncJobData } from 'packages/twenty-server/dist/src/workspace/messaging/jobs/create-contacts-and-companies-after-sync.job';

import { MessageQueueJob } from 'src/integrations/message-queue/interfaces/message-queue-job.interface';

import { CreateCompaniesAndContactsService } from 'src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service';
import { MessageChannelService } from 'src/workspace/messaging/repositories/message-channel/message-channel.service';
import { MessageParticipantService } from 'src/workspace/messaging/repositories/message-participant/message-participant.service';

export type CreateCompaniesAndContactsAfterSyncJobData = {
workspaceId: string;
messageChannelId: string;
};

@Injectable()
export class CreateCompaniesAndContactsAfterSyncJob
implements MessageQueueJob<CreateCompaniesAndContactsAfterSyncJobData>
{
private readonly logger = new Logger(
CreateCompaniesAndContactsAfterSyncJob.name,
);
constructor(
private readonly createCompaniesAndContactsService: CreateCompaniesAndContactsService,
private readonly messageChannelService: MessageChannelService,
private readonly messageParticipantService: MessageParticipantService,
) {}

async handle(
data: CreateContactsAndCompaniesAfterSyncJobData,
): Promise<void> {
this.logger.log(
`create contacts and companies after sync for workspace ${data.workspaceId} and messageChannel ${data.messageChannelId}`,
);
const { workspaceId, messageChannelId } = data;

const isContactAutoCreationEnabled =
await this.messageChannelService.getIsContactAutoCreationEnabledByMessageChannelId(
messageChannelId,
workspaceId,
);

if (!isContactAutoCreationEnabled) {
return;
}

const messageParticipantsWithoutPersonIdAndWorkspaceMemberId =
await this.messageParticipantService.getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberId(
messageChannelId,
workspaceId,
);

await this.createCompaniesAndContactsService.createCompaniesAndContacts(
messageParticipantsWithoutPersonIdAndWorkspaceMemberId,
workspaceId,
);

await this.messageParticipantService.updateMessageParticipantsAfterPeopleCreation(
messageParticipantsWithoutPersonIdAndWorkspaceMemberId,
workspaceId,
);

this.logger.log(
`create contacts and companies after sync for workspace ${data.workspaceId} and messageChannel ${data.messageChannelId} done`,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Injectable, Inject } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';

import { CreateContactsAndCompaniesAfterSyncJobData } from 'packages/twenty-server/dist/src/workspace/messaging/jobs/create-contacts-and-companies-after-sync.job';

import { ObjectRecordUpdateEvent } from 'src/integrations/event-emitter/types/object-record-update.event';
import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service';
import { MessageChannelObjectMetadata } from 'src/workspace/workspace-sync-metadata/standard-objects/message-channel.object-metadata';
import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/integrations/event-emitter/utils/object-record-changed-properties.util';
import { CreateCompaniesAndContactsAfterSyncJob } from 'src/workspace/messaging/jobs/create-companies-and-contacts-after-sync.job';

@Injectable()
export class IsContactAutoCreationEnabledListener {
constructor(
@Inject(MessageQueue.messagingQueue)
private readonly messageQueueService: MessageQueueService,
) {}

@OnEvent('messageChannel.updated')
handleUpdatedEvent(
payload: ObjectRecordUpdateEvent<MessageChannelObjectMetadata>,
) {
if (
objectRecordUpdateEventChangedProperties(
payload.previousRecord,
payload.updatedRecord,
).includes('isContactAutoCreationEnabled') &&
payload.updatedRecord.isContactAutoCreationEnabled
) {
this.messageQueueService.add<CreateContactsAndCompaniesAfterSyncJobData>(
CreateCompaniesAndContactsAfterSyncJob.name,
{
workspaceId: payload.workspaceId,
messageChannelId: payload.updatedRecord.id,
},
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ import { GmailRefreshAccessTokenService } from 'src/workspace/messaging/services
import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module';
import { MessageParticipantModule } from 'src/workspace/messaging/repositories/message-participant/message-participant.module';
import { MessagingWorkspaceMemberListener } from 'src/workspace/messaging/listeners/messaging-workspace-member.listener';
import { IsContactAutoCreationEnabledListener } from 'src/workspace/messaging/listeners/is-contact-auto-creation-enabled-listener';
import { MessagingMessageChannelListener } from 'src/workspace/messaging/listeners/messaging-message-channel.listener';
import { MessageService } from 'src/workspace/messaging/repositories/message/message.service';
import { WorkspaceMemberModule } from 'src/workspace/messaging/repositories/workspace-member/workspace-member.module';
import { FeatureFlagEntity } from 'src/core/feature-flag/feature-flag.entity';
import { CreateCompaniesAndContactsModule } from 'src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.module';
import { CompanyModule } from 'src/workspace/messaging/repositories/company/company.module';
import { PersonModule } from 'src/workspace/messaging/repositories/person/person.module';
@Module({
imports: [
EnvironmentModule,
Expand All @@ -32,8 +36,11 @@ import { FeatureFlagEntity } from 'src/core/feature-flag/feature-flag.entity';
MessageModule,
MessageThreadModule,
MessageParticipantModule,
CreateCompaniesAndContactsModule,
WorkspaceMemberModule,
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
CompanyModule,
PersonModule,
],
providers: [
GmailFullSyncService,
Expand All @@ -45,6 +52,7 @@ import { FeatureFlagEntity } from 'src/core/feature-flag/feature-flag.entity';
CreateCompanyService,
MessagingPersonListener,
MessagingWorkspaceMemberListener,
IsContactAutoCreationEnabledListener,
MessagingMessageChannelListener,
MessageService,
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';

import { CompanyService } from 'src/workspace/messaging/repositories/company/company.service';
import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module';

// TODO: Move outside of the messaging module
@Module({
imports: [WorkspaceDataSourceModule],
providers: [CompanyService],
exports: [CompanyService],
})
export class CompanyModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Injectable } from '@nestjs/common';

import { EntityManager } from 'typeorm';

import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service';

// TODO: Move outside of the messaging module
@Injectable()
export class CompanyService {
constructor(
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
) {}

public async getExistingCompaniesByDomainNames(
domainNames: string[],
workspaceId: string,
transactionManager?: EntityManager,
): Promise<{ id: string; domainName: string }[]> {
const dataSourceSchema =
this.workspaceDataSourceService.getSchemaName(workspaceId);

const existingCompanies =
await this.workspaceDataSourceService.executeRawQuery(
`SELECT id, "domainName" FROM ${dataSourceSchema}.company WHERE "domainName" = ANY($1)`,
[domainNames],
workspaceId,
transactionManager,
);

return existingCompanies;
}

public async createCompany(
id: string,
name: string,
domainName: string,
city: string,
workspaceId: string,
transactionManager?: EntityManager,
): Promise<void> {
const dataSourceSchema =
this.workspaceDataSourceService.getSchemaName(workspaceId);

await this.workspaceDataSourceService.executeRawQuery(
`INSERT INTO ${dataSourceSchema}.company (id, name, "domainName", address)
VALUES ($1, $2, $3, $4)`,
[id, name, domainName, city],
workspaceId,
transactionManager,
);
}
}
Loading
Loading