Update store on data model mutation (#18684)

- enrich SSE events with relations
- remove queries from sse metadata events
- on sse event, manage store
- on object/field metadata changes, manage store

TODO left:
- fix other metadata items

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Thomas Trompette
2026-03-17 19:32:19 +01:00
committed by GitHub
parent e62dfae741
commit 994215e0dc
35 changed files with 1399 additions and 925 deletions
@@ -1,22 +1,32 @@
import { useMutation } from '@apollo/client/react';
import { useApolloClient, useMutation } from '@apollo/client/react';
import {
type CreateObjectInput,
CreateOneObjectMetadataItemDocument,
FindManyNavigationMenuItemsDocument,
FindManyViewsDocument,
} from '~/generated-metadata/graphql';
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore';
import { type FlatFieldMetadataItem } from '@/metadata-store/types/FlatFieldMetadataItem';
import { type FlatObjectMetadataItem } from '@/metadata-store/types/FlatObjectMetadataItem';
import { splitViewWithRelated } from '@/metadata-store/utils/splitViewWithRelated';
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { CombinedGraphQLErrors } from '@apollo/client/errors';
import { t } from '@lingui/core/macro';
import { CrudOperationType } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
export const useCreateOneObjectMetadataItem = () => {
const [createOneObjectMetadataItemMutation] = useMutation(
CreateOneObjectMetadataItemDocument,
);
const client = useApolloClient();
const { handleMetadataError } = useMetadataErrorHandler();
const { enqueueErrorSnackBar } = useSnackBar();
const { addToDraft, replaceDraft, applyChanges } = useMetadataStore();
const createOneObjectMetadataItem = async (
input: CreateObjectInput,
@@ -32,6 +42,73 @@ export const useCreateOneObjectMetadataItem = () => {
},
});
const createdObject = createdObjectMetadata.data?.createOneObject;
if (isDefined(createdObject)) {
const {
__typename: _objectTypename,
fieldsList,
...objectData
} = createdObject;
addToDraft({
key: 'objectMetadataItems',
items: [objectData as FlatObjectMetadataItem],
});
const flatFields = fieldsList.map((field) => {
const { __typename: _fieldTypename, ...fieldData } = field;
return {
...fieldData,
objectMetadataId: createdObject.id,
} as FlatFieldMetadataItem;
});
addToDraft({ key: 'fieldMetadataItems', items: flatFields });
applyChanges();
const [viewsResult, navItemsResult] = await Promise.all([
client.query({
query: FindManyViewsDocument,
variables: { objectMetadataId: createdObject.id },
fetchPolicy: 'network-only',
}),
client.query({
query: FindManyNavigationMenuItemsDocument,
fetchPolicy: 'network-only',
}),
]);
const fetchedViews = viewsResult.data?.getViews ?? [];
const {
flatViews,
flatViewFields,
flatViewFilters,
flatViewSorts,
flatViewGroups,
flatViewFilterGroups,
flatViewFieldGroups,
} = splitViewWithRelated(fetchedViews);
addToDraft({ key: 'views', items: flatViews });
addToDraft({ key: 'viewFields', items: flatViewFields });
addToDraft({ key: 'viewFilters', items: flatViewFilters });
addToDraft({ key: 'viewSorts', items: flatViewSorts });
addToDraft({ key: 'viewGroups', items: flatViewGroups });
addToDraft({ key: 'viewFilterGroups', items: flatViewFilterGroups });
addToDraft({ key: 'viewFieldGroups', items: flatViewFieldGroups });
replaceDraft(
'navigationMenuItems',
navItemsResult.data?.navigationMenuItems ?? [],
);
applyChanges();
}
return {
status: 'successful',
response: createdObjectMetadata,