Fix bug favorite optimistic rendering and opportunity prefill (#2633)

* Fix bug favorite optimistic rendering and opportunity prefill

* Fixes
This commit is contained in:
Charles Bochet
2023-11-22 11:43:40 +01:00
committed by GitHub
parent 10febd9aeb
commit 8f623ceb5c
6 changed files with 105 additions and 28 deletions

View File

@ -16,7 +16,6 @@ const StyledContainer = styled.div`
`;
export const Favorites = () => {
// This is only temporary and will be refactored once we have main identifiers
const { favorites, handleReorderFavorite } = useFavorites({
objectNamePlural: 'companies',
});

View File

@ -2,10 +2,13 @@ import { useApolloClient } from '@apollo/client';
import { OnDragEndResponder } from '@hello-pangea/dnd';
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
import { useOptimisticEvict } from '@/apollo/optimistic-effect/hooks/useOptimisticEvict';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { Favorite } from '@/favorites/types/Favorite';
import { mapFavorites } from '@/favorites/utils/mapFavorites';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { getRecordOptimisticEffectDefinition } from '@/object-record/graphql/optimistic-effect-definition/getRecordOptimisticEffectDefinition';
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
@ -21,10 +24,20 @@ export const useFavorites = ({
const [favorites, setFavorites] = useRecoilState(favoritesState);
const { updateOneMutation, createOneMutation, deleteOneMutation } =
useObjectMetadataItem({
objectNamePlural: 'favorites',
const {
updateOneMutation,
createOneMutation,
deleteOneMutation,
objectMetadataItem: favoriteObjectMetadataItem,
} = useObjectMetadataItem({
objectNamePlural: 'favorites',
});
const { registerOptimisticEffect, triggerOptimisticEffects } =
useOptimisticEffect({
objectNameSingular: 'favorite',
});
const { performOptimisticEvict } = useOptimisticEvict();
const { objectMetadataItem: favoriteTargetObjectMetadataItem } =
useObjectMetadataItem({
@ -47,8 +60,19 @@ export const useFavorites = ({
if (!isDeeplyEqual(favorites, queriedFavorites)) {
set(favoritesState, queriedFavorites);
}
if (!favoriteObjectMetadataItem) {
return;
}
registerOptimisticEffect({
variables: { filter: {}, orderBy: {} },
definition: getRecordOptimisticEffectDefinition({
objectMetadataItem: favoriteObjectMetadataItem,
}),
});
},
[],
[favoriteObjectMetadataItem, registerOptimisticEffect],
),
});
@ -57,8 +81,10 @@ export const useFavorites = ({
async (favoriteTargetObjectId: string, additionalData?: any) => {
const favorites = snapshot.getLoadable(favoritesState).getValue();
const targetObjectName =
favoriteTargetObjectMetadataItem?.nameSingular ?? '';
if (!favoriteTargetObjectMetadataItem) {
return;
}
const targetObjectName = favoriteTargetObjectMetadataItem.nameSingular;
const result = await apolloClient.mutate({
mutation: createOneMutation,
@ -71,6 +97,8 @@ export const useFavorites = ({
},
});
triggerOptimisticEffects(`FavoriteEdge`, result.data[`createFavorite`]);
const createdFavorite = result?.data?.createFavorite;
const newFavorite = {
@ -87,8 +115,9 @@ export const useFavorites = ({
[
apolloClient,
createOneMutation,
currentWorkspaceMember,
favoriteTargetObjectMetadataItem?.nameSingular,
currentWorkspaceMember?.id,
favoriteTargetObjectMetadataItem,
triggerOptimisticEffects,
],
);
@ -136,6 +165,8 @@ export const useFavorites = ({
},
});
performOptimisticEvict('Favorite', 'id', idToDelete ?? '');
set(
favoritesState,
favorites.filter((favorite: Favorite) => favorite.id !== idToDelete),

View File

@ -2,6 +2,8 @@ import { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import styled from '@emotion/styled';
import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus';
import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { IconBuildingSkyscraper } from '@/ui/display/icon';
@ -36,13 +38,18 @@ export const RecordTablePage = () => {
objectNamePlural,
});
const onboardingStatus = useOnboardingStatus();
const navigate = useNavigate();
useEffect(() => {
if (objectNotFoundInMetadata) {
if (
objectNotFoundInMetadata &&
onboardingStatus === OnboardingStatus.Completed
) {
navigate('/');
}
}, [objectNotFoundInMetadata, navigate]);
}, [objectNotFoundInMetadata, navigate, onboardingStatus]);
const { createOneObject } = useCreateOneObjectRecord({
objectNameSingular: objectMetadataItem?.nameSingular,

View File

@ -58,7 +58,10 @@ export const ViewBarEffect = () => {
data.edges
.map((view) => view.node)
.find((view) => view.id === currentViewIdFromUrl) ??
data.edges[0].node;
data.edges[0]?.node ??
null;
if (!currentView) return;
set(currentViewIdState, currentView.id);

View File

@ -14,21 +14,6 @@ export const viewPrefillData = async (
.into(`${schemaName}.view`, ['name', 'objectMetadataId', 'type'])
.orIgnore()
.values([
{
name: 'All companies',
objectMetadataId: 'company',
type: 'table',
},
{
name: 'All people',
objectMetadataId: 'person',
type: 'table',
},
{
name: 'All opportunities',
objectMetadataId: 'company',
type: 'kanban',
},
{
name: 'All Companies',
objectMetadataId: objectMetadataMap['company'].id,
@ -41,7 +26,7 @@ export const viewPrefillData = async (
},
{
name: 'All Opportunities',
objectMetadataId: objectMetadataMap['company'].id,
objectMetadataId: objectMetadataMap['opportunity'].id,
type: 'kanban',
},
])

View File

@ -104,6 +104,58 @@ const opportunityMetadata = {
icon: 'IconBuildingSkyscraper',
isNullable: true,
},
{
isCustom: false,
isActive: true,
type: FieldMetadataType.UUID,
name: 'companyId',
label: 'Company ID (foreign key)',
targetColumnMap: {},
description: 'Foreign key for company',
icon: undefined,
isNullable: true,
isSystem: true,
defaultValue: undefined,
},
{
isCustom: false,
isActive: true,
type: FieldMetadataType.UUID,
name: 'personId',
label: 'Person ID (foreign key)',
targetColumnMap: {},
description: 'Foreign key for person',
icon: undefined,
isNullable: true,
isSystem: true,
defaultValue: undefined,
},
{
isCustom: false,
isActive: true,
type: FieldMetadataType.UUID,
name: 'pointOfContactId',
label: 'Point of Contact ID (foreign key)',
targetColumnMap: {},
description: 'Foreign key for point of contact',
icon: undefined,
isNullable: true,
isSystem: true,
defaultValue: undefined,
},
{
isCustom: false,
isActive: true,
type: FieldMetadataType.UUID,
name: 'pipelineStepId',
label: 'Pipeline Step ID (foreign key)',
targetColumnMap: {},
description: 'Foreign key for pipeline step',
icon: undefined,
isNullable: true,
isSystem: true,
defaultValue: undefined,
},
],
};