Fix sync statuses on the fe (#7117)

Follows #6685
This commit is contained in:
Raphaël Bosi
2024-09-18 18:46:39 +02:00
committed by GitHub
parent 02618b3e6a
commit 1d56ace2af
12 changed files with 245 additions and 47 deletions

View File

@ -137,7 +137,6 @@ export type BooleanFieldComparison = {
isNot?: InputMaybe<Scalars['Boolean']['input']>; isNot?: InputMaybe<Scalars['Boolean']['input']>;
}; };
/** Visibility of the calendar channel */
export enum CalendarChannelVisibility { export enum CalendarChannelVisibility {
Metadata = 'METADATA', Metadata = 'METADATA',
ShareEverything = 'SHARE_EVERYTHING' ShareEverything = 'SHARE_EVERYTHING'
@ -355,6 +354,7 @@ export type FieldConnection = {
export enum FieldMetadataType { export enum FieldMetadataType {
Actor = 'ACTOR', Actor = 'ACTOR',
Address = 'ADDRESS', Address = 'ADDRESS',
Array = 'ARRAY',
Boolean = 'BOOLEAN', Boolean = 'BOOLEAN',
Currency = 'CURRENCY', Currency = 'CURRENCY',
Date = 'DATE', Date = 'DATE',
@ -376,8 +376,7 @@ export enum FieldMetadataType {
RichText = 'RICH_TEXT', RichText = 'RICH_TEXT',
Select = 'SELECT', Select = 'SELECT',
Text = 'TEXT', Text = 'TEXT',
Uuid = 'UUID', Uuid = 'UUID'
Array = 'ARRAY'
} }
export enum FileFolder { export enum FileFolder {
@ -432,7 +431,6 @@ export type LoginToken = {
loginToken: AuthToken; loginToken: AuthToken;
}; };
/** Visibility of the message channel */
export enum MessageChannelVisibility { export enum MessageChannelVisibility {
Metadata = 'METADATA', Metadata = 'METADATA',
ShareEverything = 'SHARE_EVERYTHING', ShareEverything = 'SHARE_EVERYTHING',

View File

@ -130,7 +130,6 @@ export type BooleanFieldComparison = {
isNot?: InputMaybe<Scalars['Boolean']>; isNot?: InputMaybe<Scalars['Boolean']>;
}; };
/** Visibility of the calendar channel */
export enum CalendarChannelVisibility { export enum CalendarChannelVisibility {
Metadata = 'METADATA', Metadata = 'METADATA',
ShareEverything = 'SHARE_EVERYTHING' ShareEverything = 'SHARE_EVERYTHING'
@ -330,7 +329,6 @@ export type LoginToken = {
loginToken: AuthToken; loginToken: AuthToken;
}; };
/** Visibility of the message channel */
export enum MessageChannelVisibility { export enum MessageChannelVisibility {
Metadata = 'METADATA', Metadata = 'METADATA',
ShareEverything = 'SHARE_EVERYTHING', ShareEverything = 'SHARE_EVERYTHING',

View File

@ -1,11 +1,39 @@
import { CalendarChannelVisibility } from '~/generated/graphql'; import { CalendarChannelVisibility } from '~/generated/graphql';
export enum CalendarChannelSyncStatus {
NOT_SYNCED = 'NOT_SYNCED',
ONGOING = 'ONGOING',
ACTIVE = 'ACTIVE',
FAILED_INSUFFICIENT_PERMISSIONS = 'FAILED_INSUFFICIENT_PERMISSIONS',
FAILED_UNKNOWN = 'FAILED_UNKNOWN',
}
export enum CalendarChannelSyncStage {
FULL_CALENDAR_EVENT_LIST_FETCH_PENDING = 'FULL_CALENDAR_EVENT_LIST_FETCH_PENDING',
PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING = 'PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING',
CALENDAR_EVENT_LIST_FETCH_ONGOING = 'CALENDAR_EVENT_LIST_FETCH_ONGOING',
CALENDAR_EVENTS_IMPORT_PENDING = 'CALENDAR_EVENTS_IMPORT_PENDING',
CALENDAR_EVENTS_IMPORT_ONGOING = 'CALENDAR_EVENTS_IMPORT_ONGOING',
FAILED = 'FAILED',
}
export enum CalendarChannelContactAutoCreationPolicy {
AS_PARTICIPANT_AND_ORGANIZER = 'AS_PARTICIPANT_AND_ORGANIZER',
AS_PARTICIPANT = 'AS_PARTICIPANT',
AS_ORGANIZER = 'AS_ORGANIZER',
NONE = 'NONE',
}
export type CalendarChannel = { export type CalendarChannel = {
id: string; id: string;
handle: string; handle: string;
isContactAutoCreationEnabled?: boolean; isContactAutoCreationEnabled: boolean;
isSyncEnabled?: boolean; contactAutoCreationPolicy: CalendarChannelContactAutoCreationPolicy;
isSyncEnabled: boolean;
visibility: CalendarChannelVisibility; visibility: CalendarChannelVisibility;
syncStatus: string; syncStatus: CalendarChannelSyncStatus;
syncStage: CalendarChannelSyncStage;
syncCursor: string;
syncStageStartedAt: Date;
throttleFailureCount: number;
__typename: 'CalendarChannel'; __typename: 'CalendarChannel';
}; };

View File

@ -6,14 +6,35 @@ export enum MessageChannelContactAutoCreationPolicy {
NONE = 'NONE', NONE = 'NONE',
} }
export enum MessageChannelSyncStatus {
NOT_SYNCED = 'NOT_SYNCED',
ONGOING = 'ONGOING',
ACTIVE = 'ACTIVE',
FAILED_INSUFFICIENT_PERMISSIONS = 'FAILED_INSUFFICIENT_PERMISSIONS',
FAILED_UNKNOWN = 'FAILED_UNKNOWN',
}
export enum MessageChannelSyncStage {
FULL_MESSAGE_LIST_FETCH_PENDING = 'FULL_MESSAGE_LIST_FETCH_PENDING',
PARTIAL_MESSAGE_LIST_FETCH_PENDING = 'PARTIAL_MESSAGE_LIST_FETCH_PENDING',
MESSAGE_LIST_FETCH_ONGOING = 'MESSAGE_LIST_FETCH_ONGOING',
MESSAGES_IMPORT_PENDING = 'MESSAGES_IMPORT_PENDING',
MESSAGES_IMPORT_ONGOING = 'MESSAGES_IMPORT_ONGOING',
FAILED = 'FAILED',
}
export type MessageChannel = { export type MessageChannel = {
id: string; id: string;
handle: string; handle: string;
contactAutoCreationPolicy?: MessageChannelContactAutoCreationPolicy; contactAutoCreationPolicy: MessageChannelContactAutoCreationPolicy;
excludeNonProfessionalEmails: boolean; excludeNonProfessionalEmails: boolean;
excludeGroupEmails: boolean; excludeGroupEmails: boolean;
isSyncEnabled: boolean; isSyncEnabled: boolean;
visibility: MessageChannelVisibility; visibility: MessageChannelVisibility;
syncStatus: string; syncStatus: MessageChannelSyncStatus;
syncStage: MessageChannelSyncStage;
syncCursor: string;
syncStageStartedAt: Date;
throttleFailureCount: number;
__typename: 'MessageChannel'; __typename: 'MessageChannel';
}; };

View File

@ -1,8 +1,9 @@
import { ConnectedAccount } from '@/accounts/types/ConnectedAccount'; import { ConnectedAccount } from '@/accounts/types/ConnectedAccount';
import { SettingsAccountsRowDropdownMenu } from '@/settings/accounts/components/SettingsAccountsRowDropdownMenu'; import { SettingsAccountsRowDropdownMenu } from '@/settings/accounts/components/SettingsAccountsRowDropdownMenu';
import { SyncStatus } from '@/settings/accounts/constants/SyncStatus';
import { computeSyncStatus } from '@/settings/accounts/utils/computeSyncStatus';
import { Status } from '@/ui/display/status/components/Status'; import { Status } from '@/ui/display/status/components/Status';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useMemo } from 'react';
const StyledRowRightContainer = styled.div` const StyledRowRightContainer = styled.div`
align-items: center; align-items: center;
@ -15,39 +16,26 @@ export const SettingsAccountsConnectedAccountsRowRightContainer = ({
}: { }: {
account: ConnectedAccount; account: ConnectedAccount;
}) => { }) => {
const mCSyncStatus = account.messageChannels[0]?.syncStatus; const messageChannelSyncStatus = account.messageChannels[0]?.syncStatus;
const cCSyncStatus = account.calendarChannels[0]?.syncStatus; const calendarChannelSyncStatus = account.calendarChannels[0]?.syncStatus;
const status = useMemo(() => { const status = computeSyncStatus(
if (mCSyncStatus === 'ACTIVE' && cCSyncStatus === 'ACTIVE') { messageChannelSyncStatus,
return 'Synced'; calendarChannelSyncStatus,
} else if (mCSyncStatus === 'NOT_SYNCED' && cCSyncStatus === 'NOT_SYNCED') { );
return 'Not synced';
} else if (mCSyncStatus === 'ONGOING' || cCSyncStatus === 'ONGOING') {
return 'Importing';
} else if (
mCSyncStatus === 'FAILED' ||
mCSyncStatus === 'FAILED_INSUFFICIENT_PERMISSIONS' ||
cCSyncStatus === 'FAILED' ||
cCSyncStatus === 'FAILED_INSUFFICIENT_PERMISSIONS'
) {
return 'Failed';
}
return '';
}, [mCSyncStatus, cCSyncStatus]);
return ( return (
<StyledRowRightContainer> <StyledRowRightContainer>
{status === 'Failed' && ( {status === SyncStatus.FAILED && (
<Status color="red" text="Sync failed" weight="medium" /> <Status color="red" text="Sync failed" weight="medium" />
)} )}
{status === 'Synced' && ( {status === SyncStatus.SYNCED && (
<Status color="green" text="Synced" weight="medium" /> <Status color="green" text="Synced" weight="medium" />
)} )}
{status === 'Not synced' && ( {status === SyncStatus.NOT_SYNCED && (
<Status color="orange" text="Not synced" weight="medium" /> <Status color="orange" text="Not synced" weight="medium" />
)} )}
{status === 'Importing' && ( {status === SyncStatus.IMPORTING && (
<Status <Status
color="turquoise" color="turquoise"
text="Importing" text="Importing"

View File

@ -0,0 +1,6 @@
export enum SyncStatus {
SYNCED = 'SYNCED',
FAILED = 'FAILED',
NOT_SYNCED = 'NOT_SYNCED',
IMPORTING = 'IMPORTING',
}

View File

@ -0,0 +1,87 @@
import { CalendarChannelSyncStatus } from '@/accounts/types/CalendarChannel';
import { MessageChannelSyncStatus } from '@/accounts/types/MessageChannel';
import { SyncStatus } from '@/settings/accounts/constants/SyncStatus';
import { computeSyncStatus } from '../computeSyncStatus';
describe('computeSyncStatus', () => {
test('should return FAILED when both sync statuses are FAILED', () => {
expect(
computeSyncStatus(
MessageChannelSyncStatus.FAILED_UNKNOWN,
CalendarChannelSyncStatus.FAILED_UNKNOWN,
),
).toEqual(SyncStatus.FAILED);
});
test('should return FAILED when message channel sync status is FAILED_UNKNOWN', () => {
expect(
computeSyncStatus(
MessageChannelSyncStatus.FAILED_UNKNOWN,
CalendarChannelSyncStatus.ACTIVE,
),
).toEqual(SyncStatus.FAILED);
});
test('should return FAILED when message channel sync status is FAILED_INSUFFICIENT_PERMISSIONS', () => {
expect(
computeSyncStatus(
MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS,
CalendarChannelSyncStatus.ACTIVE,
),
).toEqual(SyncStatus.FAILED);
});
test('should return FAILED when calendar channel sync status is FAILED_UNKNOWN', () => {
expect(
computeSyncStatus(
MessageChannelSyncStatus.ACTIVE,
CalendarChannelSyncStatus.FAILED_UNKNOWN,
),
).toEqual(SyncStatus.FAILED);
});
test('should return FAILED when calendar channel sync status is FAILED_INSUFFICIENT_PERMISSIONS', () => {
expect(
computeSyncStatus(
MessageChannelSyncStatus.ACTIVE,
CalendarChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS,
),
).toEqual(SyncStatus.FAILED);
});
test('should return IMPORTING when message channel sync status is ONGOING', () => {
expect(
computeSyncStatus(
MessageChannelSyncStatus.ONGOING,
CalendarChannelSyncStatus.ACTIVE,
),
).toEqual(SyncStatus.IMPORTING);
});
test('should return IMPORTING when calendar channel sync status is ONGOING', () => {
expect(
computeSyncStatus(
MessageChannelSyncStatus.ACTIVE,
CalendarChannelSyncStatus.ONGOING,
),
).toEqual(SyncStatus.IMPORTING);
});
test('should return SYNCED when one channel is ACTIVE and the other is NOT_SYNCED', () => {
expect(
computeSyncStatus(
MessageChannelSyncStatus.NOT_SYNCED,
CalendarChannelSyncStatus.ACTIVE,
),
).toEqual(SyncStatus.SYNCED);
});
test('should return SYNCED when one channel is ACTIVE and the other is NOT_SYNCED', () => {
expect(
computeSyncStatus(
MessageChannelSyncStatus.ACTIVE,
CalendarChannelSyncStatus.NOT_SYNCED,
),
).toEqual(SyncStatus.SYNCED);
});
});

View File

@ -0,0 +1,42 @@
import { CalendarChannelSyncStatus } from '@/accounts/types/CalendarChannel';
import { MessageChannelSyncStatus } from '@/accounts/types/MessageChannel';
import { SyncStatus } from '@/settings/accounts/constants/SyncStatus';
export const computeSyncStatus = (
messageChannelSyncStatus: MessageChannelSyncStatus,
calendarChannelSyncStatus: CalendarChannelSyncStatus,
) => {
if (
messageChannelSyncStatus === MessageChannelSyncStatus.FAILED_UNKNOWN ||
messageChannelSyncStatus ===
MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS ||
calendarChannelSyncStatus === CalendarChannelSyncStatus.FAILED_UNKNOWN ||
calendarChannelSyncStatus ===
CalendarChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS
) {
return SyncStatus.FAILED;
}
if (
messageChannelSyncStatus === MessageChannelSyncStatus.ONGOING ||
calendarChannelSyncStatus === CalendarChannelSyncStatus.ONGOING
) {
return SyncStatus.IMPORTING;
}
if (
messageChannelSyncStatus === MessageChannelSyncStatus.NOT_SYNCED &&
calendarChannelSyncStatus === CalendarChannelSyncStatus.NOT_SYNCED
) {
return SyncStatus.NOT_SYNCED;
}
if (
messageChannelSyncStatus === MessageChannelSyncStatus.ACTIVE ||
calendarChannelSyncStatus === CalendarChannelSyncStatus.ACTIVE
) {
return SyncStatus.SYNCED;
}
return SyncStatus.NOT_SYNCED;
};

View File

@ -1,14 +1,9 @@
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; import { Field, ObjectType } from '@nestjs/graphql';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { TimelineCalendarEventParticipant } from 'src/engine/core-modules/calendar/dtos/timeline-calendar-event-participant.dto'; import { TimelineCalendarEventParticipant } from 'src/engine/core-modules/calendar/dtos/timeline-calendar-event-participant.dto';
import { CalendarChannelVisibility } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; import { CalendarChannelVisibility } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
registerEnumType(CalendarChannelVisibility, {
name: 'CalendarChannelVisibility',
description: 'Visibility of the calendar channel',
});
@ObjectType('LinkMetadata') @ObjectType('LinkMetadata')
class LinkMetadata { class LinkMetadata {
@Field() @Field()

View File

@ -1,14 +1,9 @@
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; import { Field, ObjectType } from '@nestjs/graphql';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { TimelineThreadParticipant } from 'src/engine/core-modules/messaging/dtos/timeline-thread-participant.dto'; import { TimelineThreadParticipant } from 'src/engine/core-modules/messaging/dtos/timeline-thread-participant.dto';
import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
registerEnumType(MessageChannelVisibility, {
name: 'MessageChannelVisibility',
description: 'Visibility of the message channel',
});
@ObjectType('TimelineThread') @ObjectType('TimelineThread')
export class TimelineThread { export class TimelineThread {
@Field(() => UUIDScalarType) @Field(() => UUIDScalarType)

View File

@ -1,3 +1,5 @@
import { registerEnumType } from '@nestjs/graphql';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@ -47,6 +49,22 @@ export enum CalendarChannelContactAutoCreationPolicy {
NONE = 'NONE', NONE = 'NONE',
} }
registerEnumType(CalendarChannelVisibility, {
name: 'CalendarChannelVisibility',
});
registerEnumType(CalendarChannelSyncStatus, {
name: 'CalendarChannelSyncStatus',
});
registerEnumType(CalendarChannelSyncStage, {
name: 'CalendarChannelSyncStage',
});
registerEnumType(CalendarChannelContactAutoCreationPolicy, {
name: 'CalendarChannelContactAutoCreationPolicy',
});
@WorkspaceEntity({ @WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.calendarChannel, standardId: STANDARD_OBJECT_IDS.calendarChannel,
namePlural: 'calendarChannels', namePlural: 'calendarChannels',

View File

@ -1,3 +1,5 @@
import { registerEnumType } from '@nestjs/graphql';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@ -52,6 +54,26 @@ export enum MessageChannelContactAutoCreationPolicy {
NONE = 'NONE', NONE = 'NONE',
} }
registerEnumType(MessageChannelVisibility, {
name: 'MessageChannelVisibility',
});
registerEnumType(MessageChannelSyncStatus, {
name: 'MessageChannelSyncStatus',
});
registerEnumType(MessageChannelSyncStage, {
name: 'MessageChannelSyncStage',
});
registerEnumType(MessageChannelType, {
name: 'MessageChannelType',
});
registerEnumType(MessageChannelContactAutoCreationPolicy, {
name: 'MessageChannelContactAutoCreationPolicy',
});
@WorkspaceEntity({ @WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.messageChannel, standardId: STANDARD_OBJECT_IDS.messageChannel,
namePlural: 'messageChannels', namePlural: 'messageChannels',