b470cb21a1
## Summary This PR upgrades Apollo Client from v3.10.0 to v4 and refactors error handling patterns across the codebase to use a new centralized `useSnackBarOnQueryError` hook. ## Key Changes - **Dependency Update**: Upgraded `@apollo/client` from `^3.10.0` to `^3.11.0` in root package.json - **New Hook**: Added `useSnackBarOnQueryError` hook for centralized Apollo query error handling with snack bar notifications - **Error Handling Refactor**: Updated 100+ files to use the new error handling pattern: - Removed direct `ApolloError` imports where no longer needed - Replaced manual error handling logic with `useSnackBarOnQueryError` hook - Simplified error handling in hooks and components across multiple modules - **GraphQL Codegen**: Updated codegen configuration files to work with Apollo Client v3.11.0 - **Type Definitions**: Added TypeScript declaration file for `apollo-upload-client` module - **Test Updates**: Updated test files to reflect new error handling patterns ## Notable Implementation Details - The new `useSnackBarOnQueryError` hook provides a consistent way to handle Apollo query errors with automatic snack bar notifications - Changes span across multiple feature areas: auth, object records, settings, workflows, billing, and more - All changes maintain backward compatibility while improving code maintainability and reducing duplication - Jest configuration updated to work with the new Apollo Client version https://claude.ai/code/session_019WGZ6Rd7sEHuBg9sTrXRqJ --------- Co-authored-by: Claude <noreply@anthropic.com>
91 lines
2.9 KiB
TypeScript
91 lines
2.9 KiB
TypeScript
import { isDefined } from 'twenty-shared/utils';
|
|
import { useMutation } from '@apollo/client/react';
|
|
import { CreateNavigationMenuItemDocument } from '~/generated-metadata/graphql';
|
|
|
|
import { usePrefetchedNavigationMenuItemsData } from '@/navigation-menu-item/hooks/usePrefetchedNavigationMenuItemsData';
|
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
|
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
|
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
|
|
|
export const useCreateNavigationMenuItem = () => {
|
|
const { navigationMenuItems, currentWorkspaceMemberId } =
|
|
usePrefetchedNavigationMenuItemsData();
|
|
const objectMetadataItems = useAtomStateValue(objectMetadataItemsState);
|
|
|
|
const [createNavigationMenuItemMutation] = useMutation(
|
|
CreateNavigationMenuItemDocument,
|
|
{
|
|
refetchQueries: ['FindManyNavigationMenuItems'],
|
|
},
|
|
);
|
|
|
|
const createNavigationMenuItem = async (
|
|
targetRecord: ObjectRecord,
|
|
targetObjectNameSingular: string,
|
|
folderId?: string,
|
|
) => {
|
|
const isView = targetObjectNameSingular === 'view';
|
|
|
|
if (isView) {
|
|
const relevantItems = folderId
|
|
? navigationMenuItems.filter((item) => item.folderId === folderId)
|
|
: navigationMenuItems.filter(
|
|
(item) =>
|
|
!isDefined(item.folderId) && isDefined(item.userWorkspaceId),
|
|
);
|
|
|
|
const maxPosition = Math.max(
|
|
...relevantItems.map((item) => item.position),
|
|
0,
|
|
);
|
|
|
|
await createNavigationMenuItemMutation({
|
|
variables: {
|
|
input: {
|
|
viewId: targetRecord.id,
|
|
userWorkspaceId: currentWorkspaceMemberId,
|
|
folderId,
|
|
position: maxPosition + 1,
|
|
},
|
|
},
|
|
});
|
|
} else {
|
|
const objectMetadataItem = objectMetadataItems.find(
|
|
(item) => item.nameSingular === targetObjectNameSingular,
|
|
);
|
|
|
|
if (!isDefined(objectMetadataItem)) {
|
|
throw new Error(
|
|
`Object metadata item not found for nameSingular: ${targetObjectNameSingular}`,
|
|
);
|
|
}
|
|
|
|
const relevantItems = folderId
|
|
? navigationMenuItems.filter((item) => item.folderId === folderId)
|
|
: navigationMenuItems.filter(
|
|
(item) =>
|
|
!isDefined(item.folderId) && isDefined(item.userWorkspaceId),
|
|
);
|
|
|
|
const maxPosition = Math.max(
|
|
...relevantItems.map((item) => item.position),
|
|
0,
|
|
);
|
|
|
|
await createNavigationMenuItemMutation({
|
|
variables: {
|
|
input: {
|
|
targetRecordId: targetRecord.id,
|
|
targetObjectMetadataId: objectMetadataItem.id,
|
|
userWorkspaceId: currentWorkspaceMemberId,
|
|
folderId,
|
|
position: maxPosition + 1,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
};
|
|
|
|
return { createNavigationMenuItem };
|
|
};
|