Activity cache injection (#3791)

* WIP

* Minor fixes

* Added TODO

* Fix post merge

* Fix

* Fixed warnings

* Fixed comments

* Fixed comments

* Fixed naming

* Removed comment

* WIP

* WIP 2

* Finished working version

* Fixes

* Fixed typing

* Fixes

* Fixes

* Fixes

* Naming fixes

* WIP

* Fix import

* WIP

* Working version on title

* Fixed create record id overwrite

* Removed unecessary callback

* Masterpiece

* Fixed delete on click outside drawer or delete

* Cleaned

* Cleaned

* Cleaned

* Minor fixes

* Fixes

* Fixed naming

* WIP

* Fix

* Fixed create from target inline cell

* Removed console.log

* Fixed delete activity optimistic effect

* Fixed no title

* Fixed debounce and title body creation

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Lucas Bordeau
2024-02-09 14:51:30 +01:00
committed by GitHub
parent 9ceff84bbf
commit cca72da708
87 changed files with 2195 additions and 1058 deletions

View File

@ -0,0 +1 @@
export const MAX_QUERY_DEPTH_FOR_CACHE_INJECTION = 1;

View File

@ -4,7 +4,8 @@ import { useRecoilCallback } from 'recoil';
import { useMapFieldMetadataToGraphQLQuery } from '@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useGenerateFindOneRecordQuery } from '@/object-record/hooks/useGenerateFindOneRecordQuery';
import { MAX_QUERY_DEPTH_FOR_CACHE_INJECTION } from '@/object-record/cache/constants/MaxQueryDepthForCacheInjection';
import { useInjectIntoFindOneRecordQueryCache } from '@/object-record/cache/hooks/useInjectIntoFindOneRecordQueryCache';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { capitalize } from '~/utils/string/capitalize';
@ -17,47 +18,44 @@ export const useAddRecordInCache = ({
const mapFieldMetadataToGraphQLQuery = useMapFieldMetadataToGraphQLQuery();
const apolloClient = useApolloClient();
const generateFindOneRecordQuery = useGenerateFindOneRecordQuery();
const findOneRecordQuery = generateFindOneRecordQuery({
objectMetadataItem,
});
const { injectIntoFindOneRecordQueryCache } =
useInjectIntoFindOneRecordQueryCache({
objectMetadataItem,
});
return useRecoilCallback(
({ set }) =>
(record: ObjectRecord) => {
const fragment = gql`
fragment Create${capitalize(
objectMetadataItem.nameSingular,
)}InCache on ${capitalize(objectMetadataItem.nameSingular)} {
__typename
id
${objectMetadataItem.fields
.map((field) =>
mapFieldMetadataToGraphQLQuery({
field,
maxDepthForRelations: MAX_QUERY_DEPTH_FOR_CACHE_INJECTION,
}),
)
.join('\n')}
}
`;
const cachedObjectRecord = {
__typename: `${capitalize(objectMetadataItem.nameSingular)}`,
...record,
};
apolloClient.writeFragment({
id: `${capitalize(objectMetadataItem.nameSingular)}:${record.id}`,
fragment: gql`
fragment Create${capitalize(
objectMetadataItem.nameSingular,
)}InCache on ${capitalize(objectMetadataItem.nameSingular)} {
__typename
id
${objectMetadataItem.fields
.map((field) => mapFieldMetadataToGraphQLQuery(field))
.join('\n')}
}
`,
data: {
__typename: `${capitalize(objectMetadataItem.nameSingular)}`,
...record,
},
fragment,
data: cachedObjectRecord,
});
// TODO: Turn into injectIntoFindOneRecordQueryCache
apolloClient.writeQuery({
query: findOneRecordQuery,
variables: {
objectRecordId: record.id,
},
data: {
[objectMetadataItem.nameSingular]: {
__typename: `${capitalize(objectMetadataItem.nameSingular)}`,
...record,
},
},
});
// TODO: should we keep this here ? Or should the caller of createOneRecordInCache/createManyRecordsInCache be responsible for this ?
injectIntoFindOneRecordQueryCache(cachedObjectRecord);
// TODO: remove this once we get rid of entityFieldsFamilyState
set(recordStoreFamilyState(record.id), record);
@ -66,7 +64,7 @@ export const useAddRecordInCache = ({
objectMetadataItem,
apolloClient,
mapFieldMetadataToGraphQLQuery,
findOneRecordQuery,
injectIntoFindOneRecordQueryCache,
],
);
};

View File

@ -0,0 +1,50 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useReadFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useReadFindManyRecordsQueryInCache';
import { useUpsertFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useUpsertFindManyRecordsQueryInCache';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
export const useAppendToFindManyRecordsQueryInCache = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
const { readFindManyRecordsQueryInCache } =
useReadFindManyRecordsQueryInCache({
objectMetadataItem,
});
const {
upsertFindManyRecordsQueryInCache: overwriteFindManyRecordsQueryInCache,
} = useUpsertFindManyRecordsQueryInCache({
objectMetadataItem,
});
const appendToFindManyRecordsQueryInCache = <
T extends ObjectRecord = ObjectRecord,
>({
queryVariables,
objectRecordsToAppend,
}: {
queryVariables: ObjectRecordQueryVariables;
objectRecordsToAppend: T[];
}) => {
const existingObjectRecords = readFindManyRecordsQueryInCache({
queryVariables,
});
const newObjectRecordList = [
...existingObjectRecords,
...objectRecordsToAppend,
];
overwriteFindManyRecordsQueryInCache({
objectRecordsToOverwrite: newObjectRecordList,
queryVariables,
});
};
return {
appendToFindManyRecordsQueryInCache,
};
};

View File

@ -27,7 +27,7 @@ export const useGetRecordFromCache = ({
fragment ${capitalizedObjectName}Fragment on ${capitalizedObjectName} {
id
${objectMetadataItem.fields
.map((field) => mapFieldMetadataToGraphQLQuery(field))
.map((field) => mapFieldMetadataToGraphQLQuery({ field }))
.join('\n')}
}
`;

View File

@ -0,0 +1,44 @@
import { useApolloClient } from '@apollo/client';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useGenerateFindOneRecordQuery } from '@/object-record/hooks/useGenerateFindOneRecordQuery';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { capitalize } from '~/utils/string/capitalize';
export const useInjectIntoFindOneRecordQueryCache = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
const apolloClient = useApolloClient();
const generateFindOneRecordQuery = useGenerateFindOneRecordQuery();
const injectIntoFindOneRecordQueryCache = <
T extends ObjectRecord = ObjectRecord,
>(
record: T,
) => {
const findOneRecordQueryForCacheInjection = generateFindOneRecordQuery({
objectMetadataItem,
depth: 1,
});
apolloClient.writeQuery({
query: findOneRecordQueryForCacheInjection,
variables: {
objectRecordId: record.id,
},
data: {
[objectMetadataItem.nameSingular]: {
__typename: `${capitalize(objectMetadataItem.nameSingular)}`,
...record,
},
},
});
};
return {
injectIntoFindOneRecordQueryCache,
};
};

View File

@ -0,0 +1,53 @@
import { useApolloClient } from '@apollo/client';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
import { useGenerateFindManyRecordsQuery } from '@/object-record/hooks/useGenerateFindManyRecordsQuery';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { ObjectRecordQueryResult } from '@/object-record/types/ObjectRecordQueryResult';
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
import { isDefined } from '~/utils/isDefined';
export const useReadFindManyRecordsQueryInCache = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
const apolloClient = useApolloClient();
const generateFindManyRecordsQuery = useGenerateFindManyRecordsQuery();
const readFindManyRecordsQueryInCache = <
T extends ObjectRecord = ObjectRecord,
>({
queryVariables,
}: {
queryVariables: ObjectRecordQueryVariables;
}) => {
const findManyRecordsQueryForCacheRead = generateFindManyRecordsQuery({
objectMetadataItem,
});
const existingRecordsQueryResult = apolloClient.readQuery<
ObjectRecordQueryResult<T>
>({
query: findManyRecordsQueryForCacheRead,
variables: queryVariables,
});
const existingRecordConnection =
existingRecordsQueryResult?.[objectMetadataItem.namePlural];
const existingObjectRecords = isDefined(existingRecordConnection)
? getRecordsFromRecordConnection({
recordConnection: existingRecordConnection,
})
: [];
return existingObjectRecords;
};
return {
readFindManyRecordsQueryInCache,
};
};

View File

@ -0,0 +1,51 @@
import { useApolloClient } from '@apollo/client';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { MAX_QUERY_DEPTH_FOR_CACHE_INJECTION } from '@/object-record/cache/constants/MaxQueryDepthForCacheInjection';
import { getRecordConnectionFromRecords } from '@/object-record/cache/utils/getRecordConnectionFromRecords';
import { useGenerateFindManyRecordsQuery } from '@/object-record/hooks/useGenerateFindManyRecordsQuery';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
export const useUpsertFindManyRecordsQueryInCache = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
const apolloClient = useApolloClient();
const generateFindManyRecordsQuery = useGenerateFindManyRecordsQuery();
const upsertFindManyRecordsQueryInCache = <
T extends ObjectRecord = ObjectRecord,
>({
queryVariables,
objectRecordsToOverwrite,
}: {
queryVariables: ObjectRecordQueryVariables;
objectRecordsToOverwrite: T[];
}) => {
const findManyRecordsQueryForCacheOverwrite = generateFindManyRecordsQuery({
objectMetadataItem,
depth: MAX_QUERY_DEPTH_FOR_CACHE_INJECTION,
});
const newObjectRecordConnection = getRecordConnectionFromRecords({
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
records: objectRecordsToOverwrite,
});
apolloClient.writeQuery({
query: findManyRecordsQueryForCacheOverwrite,
variables: queryVariables,
data: {
[objectMetadataItem.namePlural]: newObjectRecordConnection,
},
});
};
return {
upsertFindManyRecordsQueryInCache,
};
};

View File

@ -2,14 +2,18 @@ import { useApolloClient } from '@apollo/client';
import { v4 } from 'uuid';
import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect';
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { useGenerateObjectRecordOptimisticResponse } from '@/object-record/cache/hooks/useGenerateObjectRecordOptimisticResponse';
import { getCreateManyRecordsMutationResponseField } from '@/object-record/hooks/useGenerateCreateManyRecordMutation';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { sanitizeRecordInput } from '@/object-record/utils/sanitizeRecordInput';
type CreateManyRecordsOptions = {
skipOptimisticEffect?: boolean;
};
export const useCreateManyRecords = <
CreatedObjectRecord extends ObjectRecord = ObjectRecord,
>({
@ -27,15 +31,22 @@ export const useCreateManyRecords = <
objectMetadataItem,
});
const getRelationMetadata = useGetRelationMetadata();
const { objectMetadataItems } = useObjectMetadataItems();
const createManyRecords = async (data: Partial<CreatedObjectRecord>[]) => {
const sanitizedCreateManyRecordsInput = data.map((input) =>
sanitizeRecordInput({
const createManyRecords = async (
data: Partial<CreatedObjectRecord>[],
options?: CreateManyRecordsOptions,
) => {
const sanitizedCreateManyRecordsInput = data.map((input) => {
const idForCreation = input.id ?? v4();
const sanitizedRecordInput = sanitizeRecordInput({
objectMetadataItem,
recordInput: { ...input, id: v4() },
}),
);
recordInput: { ...input, id: idForCreation },
});
return sanitizedRecordInput;
});
const optimisticallyCreatedRecords = sanitizedCreateManyRecordsInput.map(
(record) =>
@ -51,21 +62,25 @@ export const useCreateManyRecords = <
variables: {
data: sanitizedCreateManyRecordsInput,
},
optimisticResponse: {
[mutationResponseField]: optimisticallyCreatedRecords,
},
update: (cache, { data }) => {
const records = data?.[mutationResponseField];
optimisticResponse: options?.skipOptimisticEffect
? undefined
: {
[mutationResponseField]: optimisticallyCreatedRecords,
},
update: options?.skipOptimisticEffect
? undefined
: (cache, { data }) => {
const records = data?.[mutationResponseField];
if (!records?.length) return;
if (!records?.length) return;
triggerCreateRecordsOptimisticEffect({
cache,
objectMetadataItem,
records,
getRelationMetadata,
});
},
triggerCreateRecordsOptimisticEffect({
cache,
objectMetadataItem,
recordsToCreate: records,
objectMetadataItems,
});
},
});
return createdObjects.data?.[mutationResponseField] ?? [];

View File

@ -22,7 +22,7 @@ export const useCreateManyRecordsInCache = <T extends ObjectRecord>({
objectMetadataItem,
});
const createManyRecordsInCache = async (data: Partial<T>[]) => {
const createManyRecordsInCache = (data: Partial<T>[]) => {
const recordsWithId = data.map((record) => ({
...record,
id: (record.id as string) ?? v4(),

View File

@ -2,8 +2,8 @@ import { useApolloClient } from '@apollo/client';
import { v4 } from 'uuid';
import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect';
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { useGenerateObjectRecordOptimisticResponse } from '@/object-record/cache/hooks/useGenerateObjectRecordOptimisticResponse';
import { getCreateOneRecordMutationResponseField } from '@/object-record/hooks/useGenerateCreateOneRecordMutation';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
@ -13,6 +13,10 @@ type useCreateOneRecordProps = {
objectNameSingular: string;
};
type CreateOneRecordOptions = {
skipOptimisticEffect?: boolean;
};
export const useCreateOneRecord = <
CreatedObjectRecord extends ObjectRecord = ObjectRecord,
>({
@ -29,12 +33,17 @@ export const useCreateOneRecord = <
objectMetadataItem,
});
const getRelationMetadata = useGetRelationMetadata();
const { objectMetadataItems } = useObjectMetadataItems();
const createOneRecord = async (
input: Partial<CreatedObjectRecord>,
options?: CreateOneRecordOptions,
) => {
const idForCreation = input.id ?? v4();
const createOneRecord = async (input: Partial<CreatedObjectRecord>) => {
const sanitizedCreateOneRecordInput = sanitizeRecordInput({
objectMetadataItem,
recordInput: { ...input, id: v4() },
recordInput: { ...input, id: idForCreation },
});
const optimisticallyCreatedRecord =
@ -51,21 +60,25 @@ export const useCreateOneRecord = <
variables: {
input: sanitizedCreateOneRecordInput,
},
optimisticResponse: {
[mutationResponseField]: optimisticallyCreatedRecord,
},
update: (cache, { data }) => {
const record = data?.[mutationResponseField];
optimisticResponse: options?.skipOptimisticEffect
? undefined
: {
[mutationResponseField]: optimisticallyCreatedRecord,
},
update: options?.skipOptimisticEffect
? undefined
: (cache, { data }) => {
const record = data?.[mutationResponseField];
if (!record) return;
if (!record) return;
triggerCreateRecordsOptimisticEffect({
cache,
objectMetadataItem,
records: [record],
getRelationMetadata,
});
},
triggerCreateRecordsOptimisticEffect({
cache,
objectMetadataItem,
recordsToCreate: [record],
objectMetadataItems,
});
},
});
return createdObject.data?.[mutationResponseField] ?? null;

View File

@ -23,7 +23,7 @@ export const useCreateOneRecordInCache = <T>({
objectMetadataItem,
});
const createOneRecordInCache = async (input: ObjectRecord) => {
const createOneRecordInCache = (input: ObjectRecord) => {
const generatedCachedObjectRecord =
generateObjectRecordOptimisticResponse(input);

View File

@ -1,8 +1,8 @@
import { useApolloClient } from '@apollo/client';
import { triggerDeleteRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect';
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { getDeleteManyRecordsMutationResponseField } from '@/object-record/hooks/useGenerateDeleteManyRecordMutation';
import { isDefined } from '~/utils/isDefined';
import { capitalize } from '~/utils/string/capitalize';
@ -20,7 +20,7 @@ export const useDeleteManyRecords = ({
const { objectMetadataItem, deleteManyRecordsMutation, getRecordFromCache } =
useObjectMetadataItem({ objectNameSingular });
const getRelationMetadata = useGetRelationMetadata();
const { objectMetadataItems } = useObjectMetadataItems();
const mutationResponseField = getDeleteManyRecordsMutationResponseField(
objectMetadataItem.namePlural,
@ -50,8 +50,8 @@ export const useDeleteManyRecords = ({
triggerDeleteRecordsOptimisticEffect({
cache,
objectMetadataItem,
records: cachedRecords,
getRelationMetadata,
recordsToDelete: cachedRecords,
objectMetadataItems,
});
},
});

View File

@ -2,8 +2,8 @@ import { useCallback } from 'react';
import { useApolloClient } from '@apollo/client';
import { triggerDeleteRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect';
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { getDeleteOneRecordMutationResponseField } from '@/object-record/utils/generateDeleteOneRecordMutation';
import { capitalize } from '~/utils/string/capitalize';
@ -20,7 +20,7 @@ export const useDeleteOneRecord = ({
const { objectMetadataItem, deleteOneRecordMutation, getRecordFromCache } =
useObjectMetadataItem({ objectNameSingular });
const getRelationMetadata = useGetRelationMetadata();
const { objectMetadataItems } = useObjectMetadataItems();
const mutationResponseField =
getDeleteOneRecordMutationResponseField(objectNameSingular);
@ -48,8 +48,8 @@ export const useDeleteOneRecord = ({
triggerDeleteRecordsOptimisticEffect({
cache,
objectMetadataItem,
records: [cachedRecord],
getRelationMetadata,
recordsToDelete: [cachedRecord],
objectMetadataItems,
});
},
});
@ -60,10 +60,10 @@ export const useDeleteOneRecord = ({
apolloClient,
deleteOneRecordMutation,
getRecordFromCache,
getRelationMetadata,
mutationResponseField,
objectMetadataItem,
objectNameSingular,
objectMetadataItems,
],
);

View File

@ -17,6 +17,7 @@ export const useFieldContext = ({
isLabelIdentifier = false,
objectNameSingular,
objectRecordId,
customUseUpdateOneObjectHook,
}: {
clearable?: boolean;
fieldMetadataName: string;
@ -24,6 +25,7 @@ export const useFieldContext = ({
isLabelIdentifier?: boolean;
objectNameSingular: string;
objectRecordId: string;
customUseUpdateOneObjectHook?: RecordUpdateHook;
}) => {
const { basePathToShowPage, objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
@ -65,7 +67,8 @@ export const useFieldContext = ({
position: fieldPosition,
objectMetadataItem,
}),
useUpdateRecord: useUpdateOneObjectMutation,
useUpdateRecord:
customUseUpdateOneObjectHook ?? useUpdateOneObjectMutation,
hotkeyScope: InlineCellHotkeyScope.InlineCell,
clearable,
}}

View File

@ -2,10 +2,9 @@ import { useQuery } from '@apollo/client';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
export const useFindOneRecord = <
ObjectType extends { id: string } & Record<string, any>,
>({
export const useFindOneRecord = <T extends ObjectRecord = ObjectRecord>({
objectNameSingular,
objectRecordId = '',
onCompleted,
@ -13,7 +12,7 @@ export const useFindOneRecord = <
skip,
}: ObjectMetadataItemIdentifier & {
objectRecordId: string | undefined;
onCompleted?: (data: ObjectType) => void;
onCompleted?: (data: T) => void;
skip?: boolean;
depth?: number;
}) => {
@ -23,7 +22,7 @@ export const useFindOneRecord = <
);
const { data, loading, error } = useQuery<
{ [nameSingular: string]: ObjectType },
{ [nameSingular: string]: T },
{ objectRecordId: string }
>(findOneRecordQuery, {
skip: !objectMetadataItem || !objectRecordId || skip,

View File

@ -31,7 +31,11 @@ export const useGenerateCreateManyRecordMutation = ({
${mutationResponseField}(data: $data) {
id
${objectMetadataItem.fields
.map((field) => mapFieldMetadataToGraphQLQuery(field))
.map((field) =>
mapFieldMetadataToGraphQLQuery({
field,
}),
)
.join('\n')}
}
}`;

View File

@ -31,7 +31,11 @@ export const useGenerateCreateOneRecordMutation = ({
${mutationResponseField}(data: $input) {
id
${objectMetadataItem.fields
.map((field) => mapFieldMetadataToGraphQLQuery(field))
.map((field) =>
mapFieldMetadataToGraphQLQuery({
field,
}),
)
.join('\n')}
}
}

View File

@ -36,7 +36,11 @@ export const useGenerateExecuteQuickActionOnOneRecordMutation = ({
${graphQLFieldForExecuteQuickActionOnOneRecordMutation}(id: $idToExecuteQuickActionOn) {
id
${objectMetadataItem.fields
.map((field) => mapFieldMetadataToGraphQLQuery(field))
.map((field) =>
mapFieldMetadataToGraphQLQuery({
field,
}),
)
.join('\n')}
}
}

View File

@ -71,7 +71,12 @@ export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({
node {
id
${fields
.map((field) => mapFieldMetadataToGraphQLQuery(field, depth))
.map((field) =>
mapFieldMetadataToGraphQLQuery({
field,
maxDepthForRelations: depth,
}),
)
.join('\n')}
}
cursor

View File

@ -28,7 +28,12 @@ export const useGenerateFindManyRecordsQuery = () => {
node {
id
${objectMetadataItem.fields
.map((field) => mapFieldMetadataToGraphQLQuery(field, depth))
.map((field) =>
mapFieldMetadataToGraphQLQuery({
field,
maxDepthForRelations: depth,
}),
)
.join('\n')}
}
cursor

View File

@ -12,8 +12,8 @@ export const useGenerateFindOneRecordQuery = () => {
}: {
objectMetadataItem: Pick<ObjectMetadataItem, 'nameSingular' | 'fields'>;
depth?: number;
}) =>
gql`
}) => {
return gql`
query FindOne${objectMetadataItem.nameSingular}($objectRecordId: UUID!) {
${objectMetadataItem.nameSingular}(filter: {
id: {
@ -22,9 +22,15 @@ export const useGenerateFindOneRecordQuery = () => {
}){
id
${objectMetadataItem.fields
.map((field) => mapFieldMetadataToGraphQLQuery(field, depth))
.map((field) =>
mapFieldMetadataToGraphQLQuery({
field,
maxDepthForRelations: depth,
}),
)
.join('\n')}
}
}
`;
`;
};
};

View File

@ -31,7 +31,7 @@ export const useGenerateUpdateOneRecordMutation = ({
${mutationResponseField}(id: $idToUpdate, data: $input) {
id
${objectMetadataItem.fields
.map((field) => mapFieldMetadataToGraphQLQuery(field))
.map((field) => mapFieldMetadataToGraphQLQuery({ field }))
.join('\n')}
}
}

View File

@ -1,8 +1,8 @@
import { useApolloClient } from '@apollo/client';
import { triggerUpdateRecordOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect';
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { useGenerateObjectRecordOptimisticResponse } from '@/object-record/cache/hooks/useGenerateObjectRecordOptimisticResponse';
import { getUpdateOneRecordMutationResponseField } from '@/object-record/hooks/useGenerateUpdateOneRecordMutation';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
@ -27,7 +27,7 @@ export const useUpdateOneRecord = <
objectMetadataItem,
});
const getRelationMetadata = useGetRelationMetadata();
const { objectMetadataItems } = useObjectMetadataItems();
const updateOneRecord = async ({
idToUpdate,
@ -69,9 +69,9 @@ export const useUpdateOneRecord = <
triggerUpdateRecordOptimisticEffect({
cache,
objectMetadataItem,
previousRecord: cachedRecord,
nextRecord: record,
getRelationMetadata,
currentRecord: cachedRecord,
updatedRecord: record,
objectMetadataItems,
});
},
});

View File

@ -1,5 +1,6 @@
import { ChangeEvent, useCallback, useContext, useState } from 'react';
import styled from '@emotion/styled';
import debounce from 'lodash.debounce';
import { IconTrash } from '@/ui/display/icon';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
@ -8,7 +9,6 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { MenuItemSelectColor } from '@/ui/navigation/menu-item/components/MenuItemSelectColor';
import { mainColorNames, ThemeColor } from '@/ui/theme/constants/colors';
import { textInputStyle } from '@/ui/theme/constants/effects';
import { debounce } from '~/utils/debounce';
import { BoardColumnContext } from '../contexts/BoardColumnContext';
import { useRecordBoardDeprecated } from '../hooks/useRecordBoardDeprecated';

View File

@ -36,7 +36,7 @@ export const generateEmptyFieldValue = (
return null;
}
case FieldMetadataType.Uuid: {
return '';
return null;
}
case FieldMetadataType.Boolean: {
return true;

View File

@ -0,0 +1,8 @@
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
export const mapEdgeToObjectRecord = <T extends ObjectRecord>(
objectRecordEdge: ObjectRecordEdge<T>,
) => {
return objectRecordEdge.node as T;
};