Fix bug favorite optimistic rendering and opportunity prefill (#2633)
* Fix bug favorite optimistic rendering and opportunity prefill * Fixes
This commit is contained in:
@ -16,7 +16,6 @@ const StyledContainer = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const Favorites = () => {
|
export const Favorites = () => {
|
||||||
// This is only temporary and will be refactored once we have main identifiers
|
|
||||||
const { favorites, handleReorderFavorite } = useFavorites({
|
const { favorites, handleReorderFavorite } = useFavorites({
|
||||||
objectNamePlural: 'companies',
|
objectNamePlural: 'companies',
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,10 +2,13 @@ import { useApolloClient } from '@apollo/client';
|
|||||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||||
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
|
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 { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { Favorite } from '@/favorites/types/Favorite';
|
import { Favorite } from '@/favorites/types/Favorite';
|
||||||
import { mapFavorites } from '@/favorites/utils/mapFavorites';
|
import { mapFavorites } from '@/favorites/utils/mapFavorites';
|
||||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
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 { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
|
||||||
import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults';
|
import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults';
|
||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||||
@ -21,10 +24,20 @@ export const useFavorites = ({
|
|||||||
|
|
||||||
const [favorites, setFavorites] = useRecoilState(favoritesState);
|
const [favorites, setFavorites] = useRecoilState(favoritesState);
|
||||||
|
|
||||||
const { updateOneMutation, createOneMutation, deleteOneMutation } =
|
const {
|
||||||
useObjectMetadataItem({
|
updateOneMutation,
|
||||||
objectNamePlural: 'favorites',
|
createOneMutation,
|
||||||
|
deleteOneMutation,
|
||||||
|
objectMetadataItem: favoriteObjectMetadataItem,
|
||||||
|
} = useObjectMetadataItem({
|
||||||
|
objectNamePlural: 'favorites',
|
||||||
|
});
|
||||||
|
|
||||||
|
const { registerOptimisticEffect, triggerOptimisticEffects } =
|
||||||
|
useOptimisticEffect({
|
||||||
|
objectNameSingular: 'favorite',
|
||||||
});
|
});
|
||||||
|
const { performOptimisticEvict } = useOptimisticEvict();
|
||||||
|
|
||||||
const { objectMetadataItem: favoriteTargetObjectMetadataItem } =
|
const { objectMetadataItem: favoriteTargetObjectMetadataItem } =
|
||||||
useObjectMetadataItem({
|
useObjectMetadataItem({
|
||||||
@ -47,8 +60,19 @@ export const useFavorites = ({
|
|||||||
if (!isDeeplyEqual(favorites, queriedFavorites)) {
|
if (!isDeeplyEqual(favorites, queriedFavorites)) {
|
||||||
set(favoritesState, 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) => {
|
async (favoriteTargetObjectId: string, additionalData?: any) => {
|
||||||
const favorites = snapshot.getLoadable(favoritesState).getValue();
|
const favorites = snapshot.getLoadable(favoritesState).getValue();
|
||||||
|
|
||||||
const targetObjectName =
|
if (!favoriteTargetObjectMetadataItem) {
|
||||||
favoriteTargetObjectMetadataItem?.nameSingular ?? '';
|
return;
|
||||||
|
}
|
||||||
|
const targetObjectName = favoriteTargetObjectMetadataItem.nameSingular;
|
||||||
|
|
||||||
const result = await apolloClient.mutate({
|
const result = await apolloClient.mutate({
|
||||||
mutation: createOneMutation,
|
mutation: createOneMutation,
|
||||||
@ -71,6 +97,8 @@ export const useFavorites = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
triggerOptimisticEffects(`FavoriteEdge`, result.data[`createFavorite`]);
|
||||||
|
|
||||||
const createdFavorite = result?.data?.createFavorite;
|
const createdFavorite = result?.data?.createFavorite;
|
||||||
|
|
||||||
const newFavorite = {
|
const newFavorite = {
|
||||||
@ -87,8 +115,9 @@ export const useFavorites = ({
|
|||||||
[
|
[
|
||||||
apolloClient,
|
apolloClient,
|
||||||
createOneMutation,
|
createOneMutation,
|
||||||
currentWorkspaceMember,
|
currentWorkspaceMember?.id,
|
||||||
favoriteTargetObjectMetadataItem?.nameSingular,
|
favoriteTargetObjectMetadataItem,
|
||||||
|
triggerOptimisticEffects,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -136,6 +165,8 @@ export const useFavorites = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
performOptimisticEvict('Favorite', 'id', idToDelete ?? '');
|
||||||
|
|
||||||
set(
|
set(
|
||||||
favoritesState,
|
favoritesState,
|
||||||
favorites.filter((favorite: Favorite) => favorite.id !== idToDelete),
|
favorites.filter((favorite: Favorite) => favorite.id !== idToDelete),
|
||||||
|
|||||||
@ -2,6 +2,8 @@ import { useEffect } from 'react';
|
|||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import styled from '@emotion/styled';
|
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 { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||||
import { IconBuildingSkyscraper } from '@/ui/display/icon';
|
import { IconBuildingSkyscraper } from '@/ui/display/icon';
|
||||||
@ -36,13 +38,18 @@ export const RecordTablePage = () => {
|
|||||||
objectNamePlural,
|
objectNamePlural,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onboardingStatus = useOnboardingStatus();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (objectNotFoundInMetadata) {
|
if (
|
||||||
|
objectNotFoundInMetadata &&
|
||||||
|
onboardingStatus === OnboardingStatus.Completed
|
||||||
|
) {
|
||||||
navigate('/');
|
navigate('/');
|
||||||
}
|
}
|
||||||
}, [objectNotFoundInMetadata, navigate]);
|
}, [objectNotFoundInMetadata, navigate, onboardingStatus]);
|
||||||
|
|
||||||
const { createOneObject } = useCreateOneObjectRecord({
|
const { createOneObject } = useCreateOneObjectRecord({
|
||||||
objectNameSingular: objectMetadataItem?.nameSingular,
|
objectNameSingular: objectMetadataItem?.nameSingular,
|
||||||
|
|||||||
@ -58,7 +58,10 @@ export const ViewBarEffect = () => {
|
|||||||
data.edges
|
data.edges
|
||||||
.map((view) => view.node)
|
.map((view) => view.node)
|
||||||
.find((view) => view.id === currentViewIdFromUrl) ??
|
.find((view) => view.id === currentViewIdFromUrl) ??
|
||||||
data.edges[0].node;
|
data.edges[0]?.node ??
|
||||||
|
null;
|
||||||
|
|
||||||
|
if (!currentView) return;
|
||||||
|
|
||||||
set(currentViewIdState, currentView.id);
|
set(currentViewIdState, currentView.id);
|
||||||
|
|
||||||
|
|||||||
@ -14,21 +14,6 @@ export const viewPrefillData = async (
|
|||||||
.into(`${schemaName}.view`, ['name', 'objectMetadataId', 'type'])
|
.into(`${schemaName}.view`, ['name', 'objectMetadataId', 'type'])
|
||||||
.orIgnore()
|
.orIgnore()
|
||||||
.values([
|
.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',
|
name: 'All Companies',
|
||||||
objectMetadataId: objectMetadataMap['company'].id,
|
objectMetadataId: objectMetadataMap['company'].id,
|
||||||
@ -41,7 +26,7 @@ export const viewPrefillData = async (
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'All Opportunities',
|
name: 'All Opportunities',
|
||||||
objectMetadataId: objectMetadataMap['company'].id,
|
objectMetadataId: objectMetadataMap['opportunity'].id,
|
||||||
type: 'kanban',
|
type: 'kanban',
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|||||||
@ -104,6 +104,58 @@ const opportunityMetadata = {
|
|||||||
icon: 'IconBuildingSkyscraper',
|
icon: 'IconBuildingSkyscraper',
|
||||||
isNullable: true,
|
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,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user