fix: many fields in an object (#10061)

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Jérémy M
2025-02-11 17:15:30 +01:00
committed by GitHub
parent 47f262c970
commit ed4a5b0c15
43 changed files with 22318 additions and 22058 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -488,6 +488,7 @@ export type Field = {
label: Scalars['String'];
name: Scalars['String'];
object?: Maybe<Object>;
objectMetadataId: Scalars['UUID'];
options?: Maybe<Scalars['JSON']>;
relation?: Maybe<Relation>;
relationDefinition?: Maybe<RelationDefinition>;
@ -519,6 +520,7 @@ export type FieldFilter = {
isActive?: InputMaybe<BooleanFieldComparison>;
isCustom?: InputMaybe<BooleanFieldComparison>;
isSystem?: InputMaybe<BooleanFieldComparison>;
objectMetadataId?: InputMaybe<StringFieldComparison>;
or?: InputMaybe<Array<FieldFilter>>;
};
@ -1569,6 +1571,23 @@ export type SignUpOutput = {
workspace: WorkspaceUrlsAndId;
};
export type StringFieldComparison = {
eq?: InputMaybe<Scalars['String']>;
gt?: InputMaybe<Scalars['String']>;
gte?: InputMaybe<Scalars['String']>;
iLike?: InputMaybe<Scalars['String']>;
in?: InputMaybe<Array<Scalars['String']>>;
is?: InputMaybe<Scalars['Boolean']>;
isNot?: InputMaybe<Scalars['Boolean']>;
like?: InputMaybe<Scalars['String']>;
lt?: InputMaybe<Scalars['String']>;
lte?: InputMaybe<Scalars['String']>;
neq?: InputMaybe<Scalars['String']>;
notILike?: InputMaybe<Scalars['String']>;
notIn?: InputMaybe<Array<Scalars['String']>>;
notLike?: InputMaybe<Scalars['String']>;
};
export enum SubscriptionInterval {
Day = 'Day',
Month = 'Month',
@ -1690,6 +1709,7 @@ export type UpdateFieldInput = {
isUnique?: InputMaybe<Scalars['Boolean']>;
label?: InputMaybe<Scalars['String']>;
name?: InputMaybe<Scalars['String']>;
objectMetadataId?: InputMaybe<Scalars['UUID']>;
options?: InputMaybe<Scalars['JSON']>;
settings?: InputMaybe<Scalars['JSON']>;
};

View File

@ -47,7 +47,8 @@ const mocks: MockedResponse[] = [
noteId
opportunityId
personId
rocketId
petId
surveyResultId
taskId
type
updatedAt

View File

@ -65,7 +65,8 @@ const mocks: MockedResponse[] = [
noteId
opportunityId
personId
rocketId
petId
surveyResultId
taskId
type
updatedAt
@ -94,8 +95,9 @@ const mocks: MockedResponse[] = [
noteId
opportunityId
personId
petId
position
rocketId
surveyResultId
taskId
updatedAt
viewId
@ -119,7 +121,8 @@ const mocks: MockedResponse[] = [
id
opportunityId
personId
rocketId
petId
surveyResultId
taskId
updatedAt
}
@ -141,8 +144,9 @@ const mocks: MockedResponse[] = [
noteId
opportunityId
personId
petId
properties
rocketId
surveyResultId
taskId
updatedAt
workflowId

View File

@ -269,9 +269,70 @@ mutation UpdateOneFavorite(
}
}
personId
position
rocket {
pet {
__typename
age
averageCostOfKibblePerMonth {
amountMicros
currencyCode
}
bio
birthday
comments
createdAt
createdBy {
source
workspaceMemberId
name
context
}
deletedAt
extraData
id
interestingFacts
isGoodWithKids
location {
addressStreet1
addressStreet2
addressCity
addressState
addressCountry
addressPostcode
addressLat
addressLng
}
makesOwnerThinkOf {
firstName
lastName
}
name
pictures {
primaryLinkUrl
primaryLinkLabel
secondaryLinks
}
position
soundSwag
species
traits
updatedAt
vetEmail {
primaryEmail
additionalEmails
}
vetPhone {
primaryPhoneNumber
primaryPhoneCountryCode
primaryPhoneCallingCode
additionalPhones
}
}
petId
position
surveyResult {
__typename
averageEstimatedNumberOfAtomsInTheUniverse
comments
createdAt
createdBy {
source
@ -282,10 +343,14 @@ mutation UpdateOneFavorite(
deletedAt
id
name
participants
percentageOfCompletion
position
score
shortNotes
updatedAt
}
rocketId
surveyResultId
task {
__typename
assigneeId
@ -314,6 +379,8 @@ mutation UpdateOneFavorite(
icon
id
isCompact
kanbanAggregateOperation
kanbanAggregateOperationFieldMetadataId
kanbanFieldMetadataId
key
name
@ -326,6 +393,12 @@ mutation UpdateOneFavorite(
workflow {
__typename
createdAt
createdBy {
source
workspaceMemberId
name
context
}
deletedAt
id
lastPublishedVersionId
@ -337,6 +410,7 @@ mutation UpdateOneFavorite(
workflowId
workflowRun {
__typename
context
createdAt
createdBy {
source
@ -564,9 +638,70 @@ export const mocks = [
}
}
personId
position
rocket {
pet {
__typename
age
averageCostOfKibblePerMonth {
amountMicros
currencyCode
}
bio
birthday
comments
createdAt
createdBy {
source
workspaceMemberId
name
context
}
deletedAt
extraData
id
interestingFacts
isGoodWithKids
location {
addressStreet1
addressStreet2
addressCity
addressState
addressCountry
addressPostcode
addressLat
addressLng
}
makesOwnerThinkOf {
firstName
lastName
}
name
pictures {
primaryLinkUrl
primaryLinkLabel
secondaryLinks
}
position
soundSwag
species
traits
updatedAt
vetEmail {
primaryEmail
additionalEmails
}
vetPhone {
primaryPhoneNumber
primaryPhoneCountryCode
primaryPhoneCallingCode
additionalPhones
}
}
petId
position
surveyResult {
__typename
averageEstimatedNumberOfAtomsInTheUniverse
comments
createdAt
createdBy {
source
@ -577,10 +712,14 @@ export const mocks = [
deletedAt
id
name
participants
percentageOfCompletion
position
score
shortNotes
updatedAt
}
rocketId
surveyResultId
task {
__typename
assigneeId
@ -609,6 +748,8 @@ export const mocks = [
icon
id
isCompact
kanbanAggregateOperation
kanbanAggregateOperationFieldMetadataId
kanbanFieldMetadataId
key
name
@ -621,6 +762,12 @@ export const mocks = [
workflow {
__typename
createdAt
createdBy {
source
workspaceMemberId
name
context
}
deletedAt
id
lastPublishedVersionId
@ -632,6 +779,7 @@ export const mocks = [
workflowId
workflowRun {
__typename
context
createdAt
createdBy {
source

View File

@ -1,11 +1,8 @@
import { gql } from '@apollo/client';
export const FIND_MANY_OBJECT_METADATA_ITEMS = gql`
query ObjectMetadataItems(
$objectFilter: ObjectFilter
$fieldFilter: FieldFilter
) {
objects(paging: { first: 1000 }, filter: $objectFilter) {
query ObjectMetadataItems {
objects(paging: { first: 1000 }) {
edges {
node {
id
@ -50,55 +47,45 @@ export const FIND_MANY_OBJECT_METADATA_ITEMS = gql`
}
}
}
fields(paging: { first: 1000 }, filter: $fieldFilter) {
edges {
node {
fieldsList {
id
type
name
label
description
icon
isCustom
isActive
isSystem
isNullable
isUnique
createdAt
updatedAt
defaultValue
options
settings
isLabelSyncedWithName
relationDefinition {
relationId
direction
sourceObjectMetadata {
id
type
name
label
description
icon
isCustom
isActive
isSystem
isNullable
isUnique
createdAt
updatedAt
defaultValue
options
settings
isLabelSyncedWithName
relationDefinition {
relationId
direction
sourceObjectMetadata {
id
nameSingular
namePlural
}
sourceFieldMetadata {
id
name
}
targetObjectMetadata {
id
nameSingular
namePlural
}
targetFieldMetadata {
id
name
}
}
nameSingular
namePlural
}
sourceFieldMetadata {
id
name
}
targetObjectMetadata {
id
nameSingular
namePlural
}
targetFieldMetadata {
id
name
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}

View File

@ -1,116 +1,6 @@
import { gql } from '@apollo/client';
import { FIND_MANY_OBJECT_METADATA_ITEMS } from '@/object-metadata/graphql/queries';
import { mockedStandardObjectMetadataQueryResult } from '~/testing/mock-data/generated/mock-metadata-query-result';
export const query = gql`
query ObjectMetadataItems($objectFilter: ObjectFilter, $fieldFilter: FieldFilter) {
objects(paging: {first: 1000}, filter: $objectFilter) {
edges {
node {
id
dataSourceId
nameSingular
namePlural
labelSingular
labelPlural
description
icon
isCustom
isRemote
isActive
isSystem
createdAt
updatedAt
labelIdentifierFieldMetadataId
imageIdentifierFieldMetadataId
shortcut
isLabelSyncedWithName
indexMetadatas(paging: {first: 100}) {
edges {
node {
id
createdAt
updatedAt
name
indexWhereClause
indexType
isUnique
indexFieldMetadatas(paging: {first: 100}) {
edges {
node {
id
createdAt
updatedAt
order
fieldMetadataId
}
}
}
}
}
}
fields(paging: {first: 1000}, filter: $fieldFilter) {
edges {
node {
id
type
name
label
description
icon
isCustom
isActive
isSystem
isNullable
isUnique
createdAt
updatedAt
defaultValue
options
settings
isLabelSyncedWithName
relationDefinition {
relationId
direction
sourceObjectMetadata {
id
nameSingular
namePlural
}
sourceFieldMetadata {
id
name
}
targetObjectMetadata {
id
nameSingular
namePlural
}
targetFieldMetadata {
id
name
}
}
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}
`;
export const variables = { objectFilter: undefined, fieldFilter: undefined };
export const query = FIND_MANY_OBJECT_METADATA_ITEMS;
export const responseData = mockedStandardObjectMetadataQueryResult;

View File

@ -1,6 +1,6 @@
import { ReactNode } from 'react';
import { MockedProvider } from '@apollo/client/testing';
import { renderHook } from '@testing-library/react';
import { ReactNode } from 'react';
import { RecoilRoot } from 'recoil';
import { useFindManyObjectMetadataItems } from '@/object-metadata/hooks/useFindManyObjectMetadataItems';
@ -9,14 +9,12 @@ import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/Sn
import {
query,
responseData,
variables,
} from '../__mocks__/useFindManyObjectMetadataItems';
const mocks = [
{
request: {
query,
variables,
},
result: jest.fn(() => ({
data: {

View File

@ -4,8 +4,6 @@ import { useMemo } from 'react';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import {
FieldFilter,
ObjectFilter,
ObjectMetadataItemsQuery,
ObjectMetadataItemsQueryVariables,
} from '~/generated-metadata/graphql';
@ -18,12 +16,8 @@ import { useApolloMetadataClient } from './useApolloMetadataClient';
export const useFindManyObjectMetadataItems = ({
skip,
objectFilter,
fieldFilter,
}: {
skip?: boolean;
objectFilter?: ObjectFilter;
fieldFilter?: FieldFilter;
} = {}) => {
const apolloMetadataClient = useApolloMetadataClient();
@ -33,10 +27,6 @@ export const useFindManyObjectMetadataItems = ({
ObjectMetadataItemsQuery,
ObjectMetadataItemsQueryVariables
>(FIND_MANY_OBJECT_METADATA_ITEMS, {
variables: {
objectFilter,
fieldFilter,
},
client: apolloMetadataClient ?? undefined,
skip: skip || !apolloMetadataClient,
onError: (error) => {

View File

@ -28,6 +28,8 @@ export const useRefreshObjectMetadataItems = (
});
replaceObjectMetadataItemIfDifferent(objectMetadataItems);
return objectMetadataItems;
};
const replaceObjectMetadataItemIfDifferent = useRecoilCallback(
@ -45,6 +47,7 @@ export const useRefreshObjectMetadataItems = (
},
[],
);
return {
refreshObjectMetadataItems,
};

View File

@ -10,6 +10,7 @@ export type ObjectMetadataItem = Omit<
| 'dataSourceId'
| 'indexMetadatas'
| 'labelIdentifierFieldMetadataId'
| 'fieldsList'
> & {
__typename?: string;
fields: FieldMetadataItem[];

View File

@ -14,9 +14,11 @@ export const mapPaginatedObjectMetadataItemsToObjectMetadataItems = ({
object.node.labelIdentifierFieldMetadataId,
);
const { fieldsList, ...objectWithoutFieldsList } = object.node;
return {
...object.node,
fields: object.node.fields.edges.map((field) => field.node),
...objectWithoutFieldsList,
fields: fieldsList,
labelIdentifierFieldMetadataId,
indexMetadatas: object.node.indexMetadatas?.edges.map((index) => ({
...index.node,

View File

@ -66,7 +66,8 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
noteId
opportunityId
personId
rocketId
petId
surveyResultId
taskId
type
updatedAt
@ -173,8 +174,9 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
noteId
opportunityId
personId
petId
position
rocketId
surveyResultId
taskId
updatedAt
viewId
@ -225,7 +227,8 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
noteId
opportunityId
personId
rocketId
petId
surveyResultId
updatedAt
}
}
@ -275,7 +278,8 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
id
opportunityId
personId
rocketId
petId
surveyResultId
taskId
updatedAt
}
@ -297,8 +301,9 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
noteId
opportunityId
personId
petId
properties
rocketId
surveyResultId
taskId
updatedAt
workflowId

View File

@ -201,7 +201,7 @@ const mocks: MockedResponse[] = [
}
}
personId
rocket {
pet {
__typename
createdAt
createdBy {
@ -216,7 +216,8 @@ const mocks: MockedResponse[] = [
position
updatedAt
}
rocketId
petId
surveyResultId
updatedAt
}
}
@ -361,7 +362,7 @@ const mocks: MockedResponse[] = [
}
}
personId
rocket {
pet {
__typename
createdAt
createdBy {
@ -376,7 +377,8 @@ const mocks: MockedResponse[] = [
position
updatedAt
}
rocketId
petId
surveyResultId
task {
__typename
assigneeId

View File

@ -75,7 +75,8 @@ const mocks: MockedResponse[] = [
noteId
opportunityId
personId
rocketId
petId
surveyResultId
taskId
type
updatedAt
@ -108,8 +109,9 @@ const mocks: MockedResponse[] = [
noteId
opportunityId
personId
petId
position
rocketId
surveyResultId
taskId
updatedAt
viewId
@ -144,7 +146,8 @@ const mocks: MockedResponse[] = [
noteId
opportunityId
personId
rocketId
petId
surveyResultId
updatedAt
}
}
@ -243,7 +246,8 @@ const mocks: MockedResponse[] = [
id
opportunityId
personId
rocketId
petId
surveyResultId
taskId
updatedAt
}
@ -265,8 +269,9 @@ const mocks: MockedResponse[] = [
noteId
opportunityId
personId
petId
properties
rocketId
surveyResultId
taskId
updatedAt
workflowId

View File

@ -74,7 +74,8 @@ const companyMocks = [
noteId
opportunityId
personId
rocketId
petId
surveyResultId
taskId
type
updatedAt
@ -107,8 +108,9 @@ const companyMocks = [
noteId
opportunityId
personId
petId
position
rocketId
surveyResultId
taskId
updatedAt
viewId
@ -143,7 +145,8 @@ const companyMocks = [
noteId
opportunityId
personId
rocketId
petId
surveyResultId
updatedAt
}
}
@ -242,7 +245,8 @@ const companyMocks = [
id
opportunityId
personId
rocketId
petId
surveyResultId
taskId
updatedAt
}
@ -264,8 +268,9 @@ const companyMocks = [
noteId
opportunityId
personId
petId
properties
rocketId
surveyResultId
taskId
updatedAt
workflowId

View File

@ -24,8 +24,10 @@ export const mockedFavoritesData = [
view: null,
taskId: null,
task: null,
rocketId: null,
rocket: null,
petId: null,
pet: null,
surveyResultId: null,
surveyResult: null,
personId: null,
person: null,
opportunityId: null,
@ -55,8 +57,10 @@ export const mockedFavoritesData = [
view: mockedViewsData[0],
taskId: null,
task: null,
rocketId: null,
rocket: null,
petId: null,
pet: null,
surveyResultId: null,
surveyResult: null,
personId: null,
person: null,
opportunityId: null,
@ -86,8 +90,10 @@ export const mockedFavoritesData = [
view: mockedViewsData[1],
taskId: null,
task: null,
rocketId: null,
rocket: null,
petId: null,
pet: null,
surveyResultId: null,
surveyResult: null,
personId: null,
person: null,
opportunityId: null,
@ -117,8 +123,10 @@ export const mockedFavoritesData = [
view: mockedViewsData[1],
taskId: null,
task: null,
rocketId: null,
rocket: null,
petId: null,
pet: null,
surveyResultId: null,
surveyResult: null,
personId: null,
person: null,
opportunityId: null,

View File

@ -1,5 +1,6 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { objectMetadataItemSchema } from '@/object-metadata/validation-schemas/objectMetadataItemSchema';
import { mockedStandardObjectMetadataQueryResult } from '~/testing/mock-data/generated/mock-metadata-query-result';
export const generatedMockObjectMetadataItems: ObjectMetadataItem[] =
@ -9,9 +10,11 @@ export const generatedMockObjectMetadataItems: ObjectMetadataItem[] =
edge.node.labelIdentifierFieldMetadataId,
);
const { fieldsList, ...objectWithoutFieldsList } = edge.node;
return {
...edge.node,
fields: edge.node.fields.edges.map((edge) => edge.node),
...objectWithoutFieldsList,
fields: fieldsList,
labelIdentifierFieldMetadataId,
indexMetadatas: edge.node.indexMetadatas.edges.map((index) => ({
...index.node,