Typed updateRecord hook in generic field logic (#3102)

* Typed updateRecord hook in generic field logic

* Use sanitize instead of additional optimisticInput
This commit is contained in:
Lucas Bordeau
2023-12-21 16:27:26 +01:00
committed by GitHub
parent 0d00e3d62d
commit 180aec5ad8
26 changed files with 124 additions and 150 deletions

View File

@ -2,7 +2,11 @@ import { ReactNode } from 'react';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
import {
FieldContext,
RecordUpdateHook,
RecordUpdateHookParams,
} from '@/object-record/field/contexts/FieldContext';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope';
@ -11,13 +15,11 @@ export const useFieldContext = ({
fieldMetadataName,
objectRecordId,
fieldPosition,
forceRefetch,
}: {
objectNameSingular: string;
objectRecordId: string;
fieldMetadataName: string;
fieldPosition: number;
forceRefetch?: boolean;
}) => {
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
@ -27,25 +29,15 @@ export const useFieldContext = ({
(field) => field.name === fieldMetadataName,
);
const useUpdateOneObjectMutation: () => [(params: any) => any, any] = () => {
const useUpdateOneObjectMutation: RecordUpdateHook = () => {
const { updateOneRecord } = useUpdateOneRecord({
objectNameSingular,
});
const updateEntity = ({
variables,
}: {
variables: {
where: { id: string };
data: {
[fieldName: string]: any;
};
};
}) => {
const updateEntity = ({ variables }: RecordUpdateHookParams) => {
updateOneRecord?.({
idToUpdate: variables.where.id,
input: variables.data,
forceRefetch,
idToUpdate: variables.where.id as string,
updateOneRecordInput: variables.updateOneRecordInput,
});
};
@ -66,7 +58,7 @@ export const useFieldContext = ({
position: fieldPosition,
objectMetadataItem,
}),
useUpdateEntityMutation: useUpdateOneObjectMutation,
useUpdateRecord: useUpdateOneObjectMutation,
hotkeyScope: InlineCellHotkeyScope.InlineCell,
}}
>

View File

@ -2,6 +2,7 @@ import { useApolloClient } from '@apollo/client';
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { capitalize } from '~/utils/string/capitalize';
type useUpdateOneRecordProps = {
@ -25,37 +26,46 @@ export const useUpdateOneRecord = <T>({
const updateOneRecord = async ({
idToUpdate,
input,
updateOneRecordInput,
}: {
idToUpdate: string;
input: Record<string, any>;
forceRefetch?: boolean;
updateOneRecordInput: Record<string, unknown>;
}) => {
const cachedRecord = getRecordFromCache(idToUpdate);
const optimisticallyUpdatedRecord: Record<string, any> = {
...(cachedRecord ?? {}),
...updateOneRecordInput,
};
const sanitizedUpdateOneRecordInput = Object.fromEntries(
Object.keys(updateOneRecordInput)
.filter((fieldName) => {
const fieldDefinition = objectMetadataItem.fields.find(
(field) => field.name === fieldName,
);
return fieldDefinition?.type !== FieldMetadataType.Relation;
})
.map((fieldName) => [fieldName, updateOneRecordInput[fieldName]]),
);
triggerOptimisticEffects({
typename: `${capitalize(objectMetadataItem.nameSingular)}Edge`,
updatedRecords: [
{
...(cachedRecord ?? {}),
...input,
},
],
updatedRecords: [optimisticallyUpdatedRecord],
});
const updatedRecord = await apolloClient.mutate({
mutation: updateOneRecordMutation,
variables: {
idToUpdate: idToUpdate,
idToUpdate,
input: {
...input,
...sanitizedUpdateOneRecordInput,
},
},
optimisticResponse: {
[`update${capitalize(objectMetadataItem.nameSingular)}`]: {
...(cachedRecord ?? {}),
...input,
},
[`update${capitalize(objectMetadataItem.nameSingular)}`]:
optimisticallyUpdatedRecord,
},
});