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:
@ -0,0 +1 @@
|
||||
export const MAX_QUERY_DEPTH_FOR_CACHE_INJECTION = 1;
|
||||
@ -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,
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
@ -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,
|
||||
};
|
||||
};
|
||||
@ -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')}
|
||||
}
|
||||
`;
|
||||
|
||||
@ -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,
|
||||
};
|
||||
};
|
||||
@ -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,
|
||||
};
|
||||
};
|
||||
@ -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,
|
||||
};
|
||||
};
|
||||
@ -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] ?? [];
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -23,7 +23,7 @@ export const useCreateOneRecordInCache = <T>({
|
||||
objectMetadataItem,
|
||||
});
|
||||
|
||||
const createOneRecordInCache = async (input: ObjectRecord) => {
|
||||
const createOneRecordInCache = (input: ObjectRecord) => {
|
||||
const generatedCachedObjectRecord =
|
||||
generateObjectRecordOptimisticResponse(input);
|
||||
|
||||
|
||||
@ -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,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -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,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@ -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,
|
||||
}}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -31,7 +31,11 @@ export const useGenerateCreateManyRecordMutation = ({
|
||||
${mutationResponseField}(data: $data) {
|
||||
id
|
||||
${objectMetadataItem.fields
|
||||
.map((field) => mapFieldMetadataToGraphQLQuery(field))
|
||||
.map((field) =>
|
||||
mapFieldMetadataToGraphQLQuery({
|
||||
field,
|
||||
}),
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
}`;
|
||||
|
||||
@ -31,7 +31,11 @@ export const useGenerateCreateOneRecordMutation = ({
|
||||
${mutationResponseField}(data: $input) {
|
||||
id
|
||||
${objectMetadataItem.fields
|
||||
.map((field) => mapFieldMetadataToGraphQLQuery(field))
|
||||
.map((field) =>
|
||||
mapFieldMetadataToGraphQLQuery({
|
||||
field,
|
||||
}),
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,7 +36,11 @@ export const useGenerateExecuteQuickActionOnOneRecordMutation = ({
|
||||
${graphQLFieldForExecuteQuickActionOnOneRecordMutation}(id: $idToExecuteQuickActionOn) {
|
||||
id
|
||||
${objectMetadataItem.fields
|
||||
.map((field) => mapFieldMetadataToGraphQLQuery(field))
|
||||
.map((field) =>
|
||||
mapFieldMetadataToGraphQLQuery({
|
||||
field,
|
||||
}),
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +71,12 @@ export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({
|
||||
node {
|
||||
id
|
||||
${fields
|
||||
.map((field) => mapFieldMetadataToGraphQLQuery(field, depth))
|
||||
.map((field) =>
|
||||
mapFieldMetadataToGraphQLQuery({
|
||||
field,
|
||||
maxDepthForRelations: depth,
|
||||
}),
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
cursor
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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')}
|
||||
}
|
||||
}
|
||||
`;
|
||||
`;
|
||||
};
|
||||
};
|
||||
|
||||
@ -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')}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -36,7 +36,7 @@ export const generateEmptyFieldValue = (
|
||||
return null;
|
||||
}
|
||||
case FieldMetadataType.Uuid: {
|
||||
return '';
|
||||
return null;
|
||||
}
|
||||
case FieldMetadataType.Boolean: {
|
||||
return true;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user