Skip to content

Commit 1d56ace

Browse files
authored
Fix sync statuses on the fe (#7117)
Follows #6685
1 parent 02618b3 commit 1d56ace

File tree

12 files changed

+245
-47
lines changed

12 files changed

+245
-47
lines changed

packages/twenty-front/src/generated-metadata/graphql.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ export type BooleanFieldComparison = {
137137
isNot?: InputMaybe<Scalars['Boolean']['input']>;
138138
};
139139

140-
/** Visibility of the calendar channel */
141140
export enum CalendarChannelVisibility {
142141
Metadata = 'METADATA',
143142
ShareEverything = 'SHARE_EVERYTHING'
@@ -355,6 +354,7 @@ export type FieldConnection = {
355354
export enum FieldMetadataType {
356355
Actor = 'ACTOR',
357356
Address = 'ADDRESS',
357+
Array = 'ARRAY',
358358
Boolean = 'BOOLEAN',
359359
Currency = 'CURRENCY',
360360
Date = 'DATE',
@@ -376,8 +376,7 @@ export enum FieldMetadataType {
376376
RichText = 'RICH_TEXT',
377377
Select = 'SELECT',
378378
Text = 'TEXT',
379-
Uuid = 'UUID',
380-
Array = 'ARRAY'
379+
Uuid = 'UUID'
381380
}
382381

383382
export enum FileFolder {
@@ -432,7 +431,6 @@ export type LoginToken = {
432431
loginToken: AuthToken;
433432
};
434433

435-
/** Visibility of the message channel */
436434
export enum MessageChannelVisibility {
437435
Metadata = 'METADATA',
438436
ShareEverything = 'SHARE_EVERYTHING',

packages/twenty-front/src/generated/graphql.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ export type BooleanFieldComparison = {
130130
isNot?: InputMaybe<Scalars['Boolean']>;
131131
};
132132

133-
/** Visibility of the calendar channel */
134133
export enum CalendarChannelVisibility {
135134
Metadata = 'METADATA',
136135
ShareEverything = 'SHARE_EVERYTHING'
@@ -330,7 +329,6 @@ export type LoginToken = {
330329
loginToken: AuthToken;
331330
};
332331

333-
/** Visibility of the message channel */
334332
export enum MessageChannelVisibility {
335333
Metadata = 'METADATA',
336334
ShareEverything = 'SHARE_EVERYTHING',
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,39 @@
11
import { CalendarChannelVisibility } from '~/generated/graphql';
22

3+
export enum CalendarChannelSyncStatus {
4+
NOT_SYNCED = 'NOT_SYNCED',
5+
ONGOING = 'ONGOING',
6+
ACTIVE = 'ACTIVE',
7+
FAILED_INSUFFICIENT_PERMISSIONS = 'FAILED_INSUFFICIENT_PERMISSIONS',
8+
FAILED_UNKNOWN = 'FAILED_UNKNOWN',
9+
}
10+
11+
export enum CalendarChannelSyncStage {
12+
FULL_CALENDAR_EVENT_LIST_FETCH_PENDING = 'FULL_CALENDAR_EVENT_LIST_FETCH_PENDING',
13+
PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING = 'PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING',
14+
CALENDAR_EVENT_LIST_FETCH_ONGOING = 'CALENDAR_EVENT_LIST_FETCH_ONGOING',
15+
CALENDAR_EVENTS_IMPORT_PENDING = 'CALENDAR_EVENTS_IMPORT_PENDING',
16+
CALENDAR_EVENTS_IMPORT_ONGOING = 'CALENDAR_EVENTS_IMPORT_ONGOING',
17+
FAILED = 'FAILED',
18+
}
19+
20+
export enum CalendarChannelContactAutoCreationPolicy {
21+
AS_PARTICIPANT_AND_ORGANIZER = 'AS_PARTICIPANT_AND_ORGANIZER',
22+
AS_PARTICIPANT = 'AS_PARTICIPANT',
23+
AS_ORGANIZER = 'AS_ORGANIZER',
24+
NONE = 'NONE',
25+
}
326
export type CalendarChannel = {
427
id: string;
528
handle: string;
6-
isContactAutoCreationEnabled?: boolean;
7-
isSyncEnabled?: boolean;
29+
isContactAutoCreationEnabled: boolean;
30+
contactAutoCreationPolicy: CalendarChannelContactAutoCreationPolicy;
31+
isSyncEnabled: boolean;
832
visibility: CalendarChannelVisibility;
9-
syncStatus: string;
33+
syncStatus: CalendarChannelSyncStatus;
34+
syncStage: CalendarChannelSyncStage;
35+
syncCursor: string;
36+
syncStageStartedAt: Date;
37+
throttleFailureCount: number;
1038
__typename: 'CalendarChannel';
1139
};

packages/twenty-front/src/modules/accounts/types/MessageChannel.ts

+23-2
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,35 @@ export enum MessageChannelContactAutoCreationPolicy {
66
NONE = 'NONE',
77
}
88

9+
export enum MessageChannelSyncStatus {
10+
NOT_SYNCED = 'NOT_SYNCED',
11+
ONGOING = 'ONGOING',
12+
ACTIVE = 'ACTIVE',
13+
FAILED_INSUFFICIENT_PERMISSIONS = 'FAILED_INSUFFICIENT_PERMISSIONS',
14+
FAILED_UNKNOWN = 'FAILED_UNKNOWN',
15+
}
16+
17+
export enum MessageChannelSyncStage {
18+
FULL_MESSAGE_LIST_FETCH_PENDING = 'FULL_MESSAGE_LIST_FETCH_PENDING',
19+
PARTIAL_MESSAGE_LIST_FETCH_PENDING = 'PARTIAL_MESSAGE_LIST_FETCH_PENDING',
20+
MESSAGE_LIST_FETCH_ONGOING = 'MESSAGE_LIST_FETCH_ONGOING',
21+
MESSAGES_IMPORT_PENDING = 'MESSAGES_IMPORT_PENDING',
22+
MESSAGES_IMPORT_ONGOING = 'MESSAGES_IMPORT_ONGOING',
23+
FAILED = 'FAILED',
24+
}
25+
926
export type MessageChannel = {
1027
id: string;
1128
handle: string;
12-
contactAutoCreationPolicy?: MessageChannelContactAutoCreationPolicy;
29+
contactAutoCreationPolicy: MessageChannelContactAutoCreationPolicy;
1330
excludeNonProfessionalEmails: boolean;
1431
excludeGroupEmails: boolean;
1532
isSyncEnabled: boolean;
1633
visibility: MessageChannelVisibility;
17-
syncStatus: string;
34+
syncStatus: MessageChannelSyncStatus;
35+
syncStage: MessageChannelSyncStage;
36+
syncCursor: string;
37+
syncStageStartedAt: Date;
38+
throttleFailureCount: number;
1839
__typename: 'MessageChannel';
1940
};

packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsConnectedAccountsRowRightContainer.tsx

+12-24
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { ConnectedAccount } from '@/accounts/types/ConnectedAccount';
22
import { SettingsAccountsRowDropdownMenu } from '@/settings/accounts/components/SettingsAccountsRowDropdownMenu';
3+
import { SyncStatus } from '@/settings/accounts/constants/SyncStatus';
4+
import { computeSyncStatus } from '@/settings/accounts/utils/computeSyncStatus';
35
import { Status } from '@/ui/display/status/components/Status';
46
import styled from '@emotion/styled';
5-
import { useMemo } from 'react';
67

78
const StyledRowRightContainer = styled.div`
89
align-items: center;
@@ -15,39 +16,26 @@ export const SettingsAccountsConnectedAccountsRowRightContainer = ({
1516
}: {
1617
account: ConnectedAccount;
1718
}) => {
18-
const mCSyncStatus = account.messageChannels[0]?.syncStatus;
19-
const cCSyncStatus = account.calendarChannels[0]?.syncStatus;
19+
const messageChannelSyncStatus = account.messageChannels[0]?.syncStatus;
20+
const calendarChannelSyncStatus = account.calendarChannels[0]?.syncStatus;
2021

21-
const status = useMemo(() => {
22-
if (mCSyncStatus === 'ACTIVE' && cCSyncStatus === 'ACTIVE') {
23-
return 'Synced';
24-
} else if (mCSyncStatus === 'NOT_SYNCED' && cCSyncStatus === 'NOT_SYNCED') {
25-
return 'Not synced';
26-
} else if (mCSyncStatus === 'ONGOING' || cCSyncStatus === 'ONGOING') {
27-
return 'Importing';
28-
} else if (
29-
mCSyncStatus === 'FAILED' ||
30-
mCSyncStatus === 'FAILED_INSUFFICIENT_PERMISSIONS' ||
31-
cCSyncStatus === 'FAILED' ||
32-
cCSyncStatus === 'FAILED_INSUFFICIENT_PERMISSIONS'
33-
) {
34-
return 'Failed';
35-
}
36-
return '';
37-
}, [mCSyncStatus, cCSyncStatus]);
22+
const status = computeSyncStatus(
23+
messageChannelSyncStatus,
24+
calendarChannelSyncStatus,
25+
);
3826

3927
return (
4028
<StyledRowRightContainer>
41-
{status === 'Failed' && (
29+
{status === SyncStatus.FAILED && (
4230
<Status color="red" text="Sync failed" weight="medium" />
4331
)}
44-
{status === 'Synced' && (
32+
{status === SyncStatus.SYNCED && (
4533
<Status color="green" text="Synced" weight="medium" />
4634
)}
47-
{status === 'Not synced' && (
35+
{status === SyncStatus.NOT_SYNCED && (
4836
<Status color="orange" text="Not synced" weight="medium" />
4937
)}
50-
{status === 'Importing' && (
38+
{status === SyncStatus.IMPORTING && (
5139
<Status
5240
color="turquoise"
5341
text="Importing"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export enum SyncStatus {
2+
SYNCED = 'SYNCED',
3+
FAILED = 'FAILED',
4+
NOT_SYNCED = 'NOT_SYNCED',
5+
IMPORTING = 'IMPORTING',
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { CalendarChannelSyncStatus } from '@/accounts/types/CalendarChannel';
2+
import { MessageChannelSyncStatus } from '@/accounts/types/MessageChannel';
3+
import { SyncStatus } from '@/settings/accounts/constants/SyncStatus';
4+
import { computeSyncStatus } from '../computeSyncStatus';
5+
6+
describe('computeSyncStatus', () => {
7+
test('should return FAILED when both sync statuses are FAILED', () => {
8+
expect(
9+
computeSyncStatus(
10+
MessageChannelSyncStatus.FAILED_UNKNOWN,
11+
CalendarChannelSyncStatus.FAILED_UNKNOWN,
12+
),
13+
).toEqual(SyncStatus.FAILED);
14+
});
15+
16+
test('should return FAILED when message channel sync status is FAILED_UNKNOWN', () => {
17+
expect(
18+
computeSyncStatus(
19+
MessageChannelSyncStatus.FAILED_UNKNOWN,
20+
CalendarChannelSyncStatus.ACTIVE,
21+
),
22+
).toEqual(SyncStatus.FAILED);
23+
});
24+
25+
test('should return FAILED when message channel sync status is FAILED_INSUFFICIENT_PERMISSIONS', () => {
26+
expect(
27+
computeSyncStatus(
28+
MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS,
29+
CalendarChannelSyncStatus.ACTIVE,
30+
),
31+
).toEqual(SyncStatus.FAILED);
32+
});
33+
34+
test('should return FAILED when calendar channel sync status is FAILED_UNKNOWN', () => {
35+
expect(
36+
computeSyncStatus(
37+
MessageChannelSyncStatus.ACTIVE,
38+
CalendarChannelSyncStatus.FAILED_UNKNOWN,
39+
),
40+
).toEqual(SyncStatus.FAILED);
41+
});
42+
43+
test('should return FAILED when calendar channel sync status is FAILED_INSUFFICIENT_PERMISSIONS', () => {
44+
expect(
45+
computeSyncStatus(
46+
MessageChannelSyncStatus.ACTIVE,
47+
CalendarChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS,
48+
),
49+
).toEqual(SyncStatus.FAILED);
50+
});
51+
52+
test('should return IMPORTING when message channel sync status is ONGOING', () => {
53+
expect(
54+
computeSyncStatus(
55+
MessageChannelSyncStatus.ONGOING,
56+
CalendarChannelSyncStatus.ACTIVE,
57+
),
58+
).toEqual(SyncStatus.IMPORTING);
59+
});
60+
61+
test('should return IMPORTING when calendar channel sync status is ONGOING', () => {
62+
expect(
63+
computeSyncStatus(
64+
MessageChannelSyncStatus.ACTIVE,
65+
CalendarChannelSyncStatus.ONGOING,
66+
),
67+
).toEqual(SyncStatus.IMPORTING);
68+
});
69+
70+
test('should return SYNCED when one channel is ACTIVE and the other is NOT_SYNCED', () => {
71+
expect(
72+
computeSyncStatus(
73+
MessageChannelSyncStatus.NOT_SYNCED,
74+
CalendarChannelSyncStatus.ACTIVE,
75+
),
76+
).toEqual(SyncStatus.SYNCED);
77+
});
78+
79+
test('should return SYNCED when one channel is ACTIVE and the other is NOT_SYNCED', () => {
80+
expect(
81+
computeSyncStatus(
82+
MessageChannelSyncStatus.ACTIVE,
83+
CalendarChannelSyncStatus.NOT_SYNCED,
84+
),
85+
).toEqual(SyncStatus.SYNCED);
86+
});
87+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { CalendarChannelSyncStatus } from '@/accounts/types/CalendarChannel';
2+
import { MessageChannelSyncStatus } from '@/accounts/types/MessageChannel';
3+
import { SyncStatus } from '@/settings/accounts/constants/SyncStatus';
4+
5+
export const computeSyncStatus = (
6+
messageChannelSyncStatus: MessageChannelSyncStatus,
7+
calendarChannelSyncStatus: CalendarChannelSyncStatus,
8+
) => {
9+
if (
10+
messageChannelSyncStatus === MessageChannelSyncStatus.FAILED_UNKNOWN ||
11+
messageChannelSyncStatus ===
12+
MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS ||
13+
calendarChannelSyncStatus === CalendarChannelSyncStatus.FAILED_UNKNOWN ||
14+
calendarChannelSyncStatus ===
15+
CalendarChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS
16+
) {
17+
return SyncStatus.FAILED;
18+
}
19+
20+
if (
21+
messageChannelSyncStatus === MessageChannelSyncStatus.ONGOING ||
22+
calendarChannelSyncStatus === CalendarChannelSyncStatus.ONGOING
23+
) {
24+
return SyncStatus.IMPORTING;
25+
}
26+
27+
if (
28+
messageChannelSyncStatus === MessageChannelSyncStatus.NOT_SYNCED &&
29+
calendarChannelSyncStatus === CalendarChannelSyncStatus.NOT_SYNCED
30+
) {
31+
return SyncStatus.NOT_SYNCED;
32+
}
33+
34+
if (
35+
messageChannelSyncStatus === MessageChannelSyncStatus.ACTIVE ||
36+
calendarChannelSyncStatus === CalendarChannelSyncStatus.ACTIVE
37+
) {
38+
return SyncStatus.SYNCED;
39+
}
40+
41+
return SyncStatus.NOT_SYNCED;
42+
};

packages/twenty-server/src/engine/core-modules/calendar/dtos/timeline-calendar-event.dto.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
1+
import { Field, ObjectType } from '@nestjs/graphql';
22

33
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
44
import { TimelineCalendarEventParticipant } from 'src/engine/core-modules/calendar/dtos/timeline-calendar-event-participant.dto';
55
import { CalendarChannelVisibility } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
66

7-
registerEnumType(CalendarChannelVisibility, {
8-
name: 'CalendarChannelVisibility',
9-
description: 'Visibility of the calendar channel',
10-
});
11-
127
@ObjectType('LinkMetadata')
138
class LinkMetadata {
149
@Field()

packages/twenty-server/src/engine/core-modules/messaging/dtos/timeline-thread.dto.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
1+
import { Field, ObjectType } from '@nestjs/graphql';
22

33
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
44
import { TimelineThreadParticipant } from 'src/engine/core-modules/messaging/dtos/timeline-thread-participant.dto';
55
import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
66

7-
registerEnumType(MessageChannelVisibility, {
8-
name: 'MessageChannelVisibility',
9-
description: 'Visibility of the message channel',
10-
});
11-
127
@ObjectType('TimelineThread')
138
export class TimelineThread {
149
@Field(() => UUIDScalarType)

packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts

+18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { registerEnumType } from '@nestjs/graphql';
2+
13
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
24

35
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@@ -47,6 +49,22 @@ export enum CalendarChannelContactAutoCreationPolicy {
4749
NONE = 'NONE',
4850
}
4951

52+
registerEnumType(CalendarChannelVisibility, {
53+
name: 'CalendarChannelVisibility',
54+
});
55+
56+
registerEnumType(CalendarChannelSyncStatus, {
57+
name: 'CalendarChannelSyncStatus',
58+
});
59+
60+
registerEnumType(CalendarChannelSyncStage, {
61+
name: 'CalendarChannelSyncStage',
62+
});
63+
64+
registerEnumType(CalendarChannelContactAutoCreationPolicy, {
65+
name: 'CalendarChannelContactAutoCreationPolicy',
66+
});
67+
5068
@WorkspaceEntity({
5169
standardId: STANDARD_OBJECT_IDS.calendarChannel,
5270
namePlural: 'calendarChannels',

0 commit comments

Comments
 (0)