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:
@ -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,
|
||||
}}
|
||||
>
|
||||
|
||||
@ -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,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user