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

Enable deletion of relation fields #5338

Merged
merged 10 commits into from
May 13, 2024
9 changes: 7 additions & 2 deletions packages/twenty-front/src/generated-metadata/gql.ts

Large diffs are not rendered by default.

29 changes: 13 additions & 16 deletions packages/twenty-front/src/generated-metadata/graphql.ts

Large diffs are not rendered by default.

35 changes: 23 additions & 12 deletions packages/twenty-front/src/generated/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,11 @@ export type MutationTrackArgs = {
};


export type MutationUpdateOneObjectArgs = {
input: UpdateOneObjectInput;
};


export type MutationUpdatePasswordViaResetTokenArgs = {
newPassword: Scalars['String'];
passwordResetToken: Scalars['String'];
Expand Down Expand Up @@ -548,18 +553,6 @@ export enum RelationDefinitionType {
OneToOne = 'ONE_TO_ONE'
}

export type RelationDeleteResponse = {
__typename?: 'RelationDeleteResponse';
createdAt?: Maybe<Scalars['DateTime']>;
fromFieldMetadataId?: Maybe<Scalars['String']>;
fromObjectMetadataId?: Maybe<Scalars['String']>;
id?: Maybe<Scalars['UUID']>;
relationType?: Maybe<RelationMetadataType>;
toFieldMetadataId?: Maybe<Scalars['String']>;
toObjectMetadataId?: Maybe<Scalars['String']>;
updatedAt?: Maybe<Scalars['DateTime']>;
};

/** Type of the relation */
export enum RelationMetadataType {
ManyToMany = 'MANY_TO_MANY',
Expand Down Expand Up @@ -728,6 +721,24 @@ export type UpdateBillingEntity = {
success: Scalars['Boolean'];
};

export type UpdateObjectPayload = {
description?: InputMaybe<Scalars['String']>;
icon?: InputMaybe<Scalars['String']>;
imageIdentifierFieldMetadataId?: InputMaybe<Scalars['String']>;
isActive?: InputMaybe<Scalars['Boolean']>;
labelIdentifierFieldMetadataId?: InputMaybe<Scalars['String']>;
labelPlural?: InputMaybe<Scalars['String']>;
labelSingular?: InputMaybe<Scalars['String']>;
namePlural?: InputMaybe<Scalars['String']>;
nameSingular?: InputMaybe<Scalars['String']>;
};

export type UpdateOneObjectInput = {
/** The id of the object to update */
id: Scalars['UUID'];
update: UpdateObjectPayload;
};

export type UpdateWorkspaceInput = {
allowImpersonation?: InputMaybe<Scalars['Boolean']>;
displayName?: InputMaybe<Scalars['String']>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,11 @@ export const DELETE_ONE_FIELD_METADATA_ITEM = gql`
}
}
`;

export const DELETE_ONE_RELATION_METADATA_ITEM = gql`
mutation DeleteOneRelationMetadataItem($idToDelete: UUID!) {
deleteOneRelation(input: { id: $idToDelete }) {
id
}
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export const FIND_MANY_OBJECT_METADATA_ITEMS = gql`
defaultValue
Weiko marked this conversation as resolved.
Show resolved Hide resolved
options
relationDefinition {
relationId
direction
sourceObjectMetadata {
id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { gql } from '@apollo/client';

export const query = gql`
mutation DeleteOneRelationMetadataItem($idToDelete: UUID!) {
deleteOneRelation(input: { id: $idToDelete }) {
id
}
}
`;

export const variables = { idToDelete: 'idToDelete' };

export const responseData = {
id: 'idToDelete'
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { gql } from '@apollo/client';
import { FieldMetadataType } from '~/generated/graphql';

export const FIELD_METADATA_ID = '2c43466a-fe9e-4005-8d08-c5836067aa6c';
export const FIELD_RELATION_METADATA_ID = '4da0302d-358a-45cd-9973-9f92723ed3c1';
export const RELATION_METADATA_ID = 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6';

const baseFields = `
id
Expand All @@ -15,13 +20,20 @@ const baseFields = `
`;

export const queries = {
eraseMetadataField: gql`
deleteMetadataField: gql`
mutation DeleteOneFieldMetadataItem($idToDelete: UUID!) {
deleteOneField(input: { id: $idToDelete }) {
${baseFields}
}
}
`,
deleteMetadataFieldRelation: gql`
mutation DeleteOneRelationMetadataItem($idToDelete: UUID!) {
deleteOneRelation(input: { id: $idToDelete }) {
id
}
}
`,
activateMetadataField: gql`
mutation UpdateOneFieldMetadataItem(
$idToUpdate: UUID!
Expand All @@ -43,13 +55,13 @@ export const queries = {
`,
};

const fieldId = '2c43466a-fe9e-4005-8d08-c5836067aa6c';
export const objectMetadataId = '25611fce-6637-4089-b0ca-91afeec95784';

export const variables = {
eraseMetadataField: { idToDelete: fieldId },
deleteMetadataField: { idToDelete: FIELD_METADATA_ID },
deleteMetadataFieldRelation: { idToDelete: RELATION_METADATA_ID },
activateMetadataField: {
idToUpdate: fieldId,
idToUpdate: FIELD_METADATA_ID,
updatePayload: { isActive: true, label: undefined },
},
createMetadataField: {
Expand All @@ -66,14 +78,14 @@ export const variables = {
},
},
},
disableMetadataField: {
idToUpdate: fieldId,
deactivateMetadataField: {
idToUpdate: FIELD_METADATA_ID,
updatePayload: { isActive: false, label: undefined },
}
};

const defaultResponseData = {
id: '2c43466a-fe9e-4005-8d08-c5836067aa6c',
id: FIELD_METADATA_ID,
type: 'type',
name: 'name',
label: 'label',
Expand All @@ -86,11 +98,19 @@ const defaultResponseData = {
updatedAt: '1996-10-10T08:27:57.117Z',
};

const fieldRelationResponseData = {
...defaultResponseData,
id: FIELD_RELATION_METADATA_ID,
type: FieldMetadataType.Relation,
};

export const responseData = {
default: defaultResponseData,
fieldRelation: fieldRelationResponseData,
createMetadataField: {
...defaultResponseData,
defaultValue: '',
options: [],
},
};

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ReactNode } from 'react';
import { MockedProvider } from '@apollo/client/testing';
import { act, renderHook } from '@testing-library/react';
import { RecoilRoot } from 'recoil';

import { useDeleteOneRelationMetadataItem } from '@/object-metadata/hooks/useDeleteOneRelationMetadataItem';

import {
query,
responseData,
variables,
} from '../__mocks__/useDeleteOneRelationMetadataItem';

const mocks = [
{
request: {
query,
variables,
},
result: jest.fn(() => ({
data: {
deleteOneRelation: responseData,
},
})),
},
];

const Wrapper = ({ children }: { children: ReactNode }) => (
<RecoilRoot>
<MockedProvider mocks={mocks} addTypename={false}>
{children}
</MockedProvider>
</RecoilRoot>
);

describe('useDeleteOneRelationMetadataItem', () => {
it('should work as expected', async () => {
const { result } = renderHook(() => useDeleteOneRelationMetadataItem(), {
wrapper: Wrapper,
});

await act(async () => {
const res =
await result.current.deleteOneRelationMetadataItem('idToDelete');

expect(res.data).toEqual({ deleteOneRelation: responseData });
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,81 @@ import { RecoilRoot } from 'recoil';

import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { FieldMetadataType } from '~/generated/graphql';
import { FieldMetadataType, RelationDefinitionType } from '~/generated/graphql';

import {
FIELD_METADATA_ID,
FIELD_RELATION_METADATA_ID,
objectMetadataId,
queries,
RELATION_METADATA_ID,
responseData,
variables,
} from '../__mocks__/useFieldMetadataItem';

const fieldMetadataItem: FieldMetadataItem = {
id: '2c43466a-fe9e-4005-8d08-c5836067aa6c',
id: FIELD_METADATA_ID,
createdAt: '',
label: 'label',
name: 'name',
type: FieldMetadataType.Text,
updatedAt: '',
};

const fieldRelationMetadataItem: FieldMetadataItem = {
id: FIELD_RELATION_METADATA_ID,
createdAt: '',
label: 'label',
name: 'name',
type: FieldMetadataType.Relation,
updatedAt: '',
relationDefinition: {
relationId: RELATION_METADATA_ID,
direction: RelationDefinitionType.OneToMany,
sourceFieldMetadata: {
id: 'e5903d91-9b10-4f3e-b761-35c36e93b7c1',
name: 'sourceField',
},
targetFieldMetadata: {
id: 'd23d82d4-690b-489f-a8e3-fc5ed01a91f6',
name: 'targetField',
},
sourceObjectMetadata: {
id: 'bf46be8a-7c47-45a7-b2f1-30f49e14fbd9',
nameSingular: 'sourceObject',
namePlural: 'sourceObjects',
},
targetObjectMetadata: {
id: '987c0489-2855-4a63-bb81-93692e51b2a9',
nameSingular: 'targetObject',
namePlural: 'targetObjects',
},
},
};

const mocks = [
{
request: {
query: queries.eraseMetadataField,
variables: variables.eraseMetadataField,
query: queries.deleteMetadataField,
variables: variables.deleteMetadataField,
},
result: jest.fn(() => ({
data: {
deleteOneField: responseData.default,
},
})),
},
{
request: {
query: queries.deleteMetadataFieldRelation,
variables: variables.deleteMetadataFieldRelation,
},
result: jest.fn(() => ({
data: {
deleteOneRelation: responseData.fieldRelation,
},
})),
},
{
request: {
query: queries.activateMetadataField,
Expand All @@ -60,7 +105,7 @@ const mocks = [
{
request: {
query: queries.activateMetadataField,
variables: variables.disableMetadataField,
variables: variables.deactivateMetadataField,
},
result: jest.fn(() => ({
data: {
Expand Down Expand Up @@ -111,31 +156,48 @@ describe('useFieldMetadataItem', () => {
});
});

it('should disableMetadataField', async () => {
it('should deactivateMetadataField', async () => {
const { result } = renderHook(() => useFieldMetadataItem(), {
wrapper: Wrapper,
});

await act(async () => {
const res = await result.current.disableMetadataField(fieldMetadataItem);
const res =
await result.current.deactivateMetadataField(fieldMetadataItem);

expect(res.data).toEqual({
updateOneField: responseData.default,
});
});
});

it('should eraseMetadataField', async () => {
it('should deleteOneFieldMetadataItem when calling deleteMetadataField for a non-relation field', async () => {
const { result } = renderHook(() => useFieldMetadataItem(), {
wrapper: Wrapper,
});

await act(async () => {
const res = await result.current.eraseMetadataField(fieldMetadataItem);
const res = await result.current.deleteMetadataField(fieldMetadataItem);

expect(res.data).toEqual({
deleteOneField: responseData.default,
});
});
});

it('should deleteOneFieldMetadataItem when calling deleteMetadataField for a relation field', async () => {
const { result } = renderHook(() => useFieldMetadataItem(), {
wrapper: Wrapper,
});

await act(async () => {
const res = await result.current.deleteMetadataField(
fieldRelationMetadataItem,
);

expect(res.data).toEqual({
deleteOneRelation: responseData.fieldRelation,
});
});
});
});
Loading
Loading