Fix tasks (#5199)
## Query depth deprecation I'm deprecating depth parameter in our graphql query / cache tooling. They were obsolete since we introduce the possibility to provide RecordGqlFields ## Refactor combinedFindManyRecordHook The hook can now take an array of operationSignatures ## Fix tasks issues Fix optimistic rendering issue. Note that we still haven't handle optimisticEffect on creation properly
This commit is contained in:
@ -79,7 +79,7 @@ const mocks: MockedResponse[] = [
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
filter: { activityTargetId: { eq: '123' } },
|
||||
filter: { companyId: { eq: '123' } },
|
||||
limit: undefined,
|
||||
orderBy: undefined,
|
||||
},
|
||||
@ -180,7 +180,6 @@ describe('useActivities', () => {
|
||||
activitiesFilters: {},
|
||||
activitiesOrderByVariables: {},
|
||||
skip: false,
|
||||
skipActivityTargets: false,
|
||||
}),
|
||||
{ wrapper: Wrapper },
|
||||
);
|
||||
@ -188,8 +187,6 @@ describe('useActivities', () => {
|
||||
expect(result.current).toEqual({
|
||||
activities: [],
|
||||
loading: false,
|
||||
initialized: true,
|
||||
noActivities: true,
|
||||
});
|
||||
});
|
||||
|
||||
@ -202,12 +199,11 @@ describe('useActivities', () => {
|
||||
|
||||
const activities = useActivities({
|
||||
targetableObjects: [
|
||||
{ targetObjectNameSingular: 'activityTarget', id: '123' },
|
||||
{ targetObjectNameSingular: 'company', id: '123' },
|
||||
],
|
||||
activitiesFilters: {},
|
||||
activitiesOrderByVariables: {},
|
||||
skip: false,
|
||||
skipActivityTargets: false,
|
||||
});
|
||||
return { activities, setCurrentWorkspaceMember };
|
||||
},
|
||||
@ -218,18 +214,9 @@ describe('useActivities', () => {
|
||||
result.current.setCurrentWorkspaceMember(mockWorkspaceMembers[0]);
|
||||
});
|
||||
|
||||
expect(result.current.activities.loading).toBe(true);
|
||||
|
||||
// Wait for activityTargets to complete fetching
|
||||
await waitFor(() => !result.current.activities.loading);
|
||||
|
||||
expect(result.current.activities.loading).toBe(false);
|
||||
|
||||
// Wait for request to fetch activities to be made
|
||||
await waitFor(() => result.current.activities.loading);
|
||||
|
||||
// Wait for activities to complete fetching
|
||||
await waitFor(() => !result.current.activities.loading);
|
||||
await waitFor(() => {
|
||||
expect(result.current.activities.loading).toBe(false);
|
||||
});
|
||||
|
||||
const { activities } = result.current;
|
||||
|
||||
|
||||
@ -10,8 +10,8 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat
|
||||
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
||||
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
|
||||
import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope';
|
||||
import { JestObjectMetadataItemSetter } from '~/testing/jest/JestObjectMetadataItemSetter';
|
||||
import { mockWorkspaceMembers } from '~/testing/mock-data/workspace-members';
|
||||
|
||||
const mockObjectMetadataItems = getObjectMetadataItemsMock();
|
||||
|
||||
const cache = new InMemoryCache();
|
||||
@ -85,7 +85,6 @@ cache.writeFragment({
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
targetObjectNameSingular
|
||||
personId
|
||||
companyId
|
||||
company {
|
||||
@ -114,9 +113,11 @@ cache.writeFragment({
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<RecoilRoot>
|
||||
<MockedProvider cache={cache}>
|
||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||
{children}
|
||||
</SnackBarProviderScope>
|
||||
<JestObjectMetadataItemSetter>
|
||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||
{children}
|
||||
</SnackBarProviderScope>
|
||||
</JestObjectMetadataItemSetter>
|
||||
</MockedProvider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
|
||||
@ -82,7 +82,10 @@ describe('useCreateActivityInDB', () => {
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.createActivityInDB(mockedActivity);
|
||||
await result.current.createActivityInDB({
|
||||
...mockedActivity,
|
||||
__typename: 'Activity',
|
||||
});
|
||||
});
|
||||
|
||||
expect(mocks[0].result).toHaveBeenCalled();
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { isNonEmptyArray, isNonEmptyString } from '@sniptt/guards';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { findActivitiesOperationSignatureFactory } from '@/activities/graphql/operation-signatures/factories/findActivitiesOperationSignatureFactory';
|
||||
import { useActivityTargetsForTargetableObjects } from '@/activities/hooks/useActivityTargetsForTargetableObjects';
|
||||
import { FIND_MANY_ACTIVITIES_QUERY_KEY } from '@/activities/query-keys/FindManyActivitiesQueryKey';
|
||||
import { Activity } from '@/activities/types/Activity';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { OrderByField } from '@/object-metadata/types/OrderByField';
|
||||
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { RecordGqlOperationOrderBy } from '@/object-record/graphql/types/RecordGqlOperationOrderBy';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { sortByAscString } from '~/utils/array/sortByAscString';
|
||||
|
||||
@ -18,26 +17,19 @@ export const useActivities = ({
|
||||
activitiesFilters,
|
||||
activitiesOrderByVariables,
|
||||
skip,
|
||||
skipActivityTargets,
|
||||
}: {
|
||||
targetableObjects: ActivityTargetableObject[];
|
||||
activitiesFilters: ObjectRecordQueryFilter;
|
||||
activitiesOrderByVariables: OrderByField;
|
||||
activitiesFilters: RecordGqlOperationFilter;
|
||||
activitiesOrderByVariables: RecordGqlOperationOrderBy;
|
||||
skip?: boolean;
|
||||
skipActivityTargets?: boolean;
|
||||
}) => {
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
const {
|
||||
activityTargets,
|
||||
loadingActivityTargets,
|
||||
initialized: initializedActivityTargets,
|
||||
} = useActivityTargetsForTargetableObjects({
|
||||
targetableObjects,
|
||||
skip: skipActivityTargets || skip,
|
||||
});
|
||||
const { activityTargets, loadingActivityTargets } =
|
||||
useActivityTargetsForTargetableObjects({
|
||||
targetableObjects,
|
||||
skip: skip,
|
||||
});
|
||||
|
||||
const activityIds = [
|
||||
...new Set(
|
||||
@ -51,70 +43,40 @@ export const useActivities = ({
|
||||
),
|
||||
];
|
||||
|
||||
const activityTargetsFound =
|
||||
initializedActivityTargets && isNonEmptyArray(activityTargets);
|
||||
|
||||
const filter: ObjectRecordQueryFilter = {
|
||||
id: activityTargetsFound
|
||||
? {
|
||||
in: activityIds,
|
||||
}
|
||||
: undefined,
|
||||
const filter: RecordGqlOperationFilter = {
|
||||
id:
|
||||
targetableObjects.length > 0
|
||||
? {
|
||||
in: activityIds,
|
||||
}
|
||||
: undefined,
|
||||
...activitiesFilters,
|
||||
};
|
||||
|
||||
const skipActivities =
|
||||
skip ||
|
||||
(!skipActivityTargets &&
|
||||
(!initializedActivityTargets || !activityTargetsFound));
|
||||
const FIND_ACTIVITIES_OPERATION_SIGNATURE =
|
||||
findActivitiesOperationSignatureFactory({ objectMetadataItems });
|
||||
|
||||
const { records: activities, loading: loadingActivities } =
|
||||
useFindManyRecords<Activity>({
|
||||
skip: skipActivities,
|
||||
objectNameSingular: FIND_MANY_ACTIVITIES_QUERY_KEY.objectNameSingular,
|
||||
depth: FIND_MANY_ACTIVITIES_QUERY_KEY.depth,
|
||||
queryFields:
|
||||
FIND_MANY_ACTIVITIES_QUERY_KEY.fieldsFactory?.(objectMetadataItems),
|
||||
skip: skip || loadingActivityTargets,
|
||||
objectNameSingular:
|
||||
FIND_ACTIVITIES_OPERATION_SIGNATURE.objectNameSingular,
|
||||
recordGqlFields: FIND_ACTIVITIES_OPERATION_SIGNATURE.fields,
|
||||
filter,
|
||||
orderBy: activitiesOrderByVariables,
|
||||
onCompleted: useRecoilCallback(
|
||||
({ set }) =>
|
||||
(activities) => {
|
||||
if (!initialized) {
|
||||
setInitialized(true);
|
||||
}
|
||||
|
||||
for (const activity of activities) {
|
||||
set(recordStoreFamilyState(activity.id), activity);
|
||||
}
|
||||
},
|
||||
[initialized],
|
||||
[],
|
||||
),
|
||||
});
|
||||
|
||||
const loading = loadingActivities || loadingActivityTargets;
|
||||
|
||||
const noActivities =
|
||||
(!activityTargetsFound && !skipActivityTargets && initialized) ||
|
||||
(initialized && !loading && !isNonEmptyArray(activities));
|
||||
|
||||
useEffect(() => {
|
||||
if (skipActivities || noActivities) {
|
||||
setInitialized(true);
|
||||
}
|
||||
}, [
|
||||
activities,
|
||||
initialized,
|
||||
loading,
|
||||
noActivities,
|
||||
skipActivities,
|
||||
skipActivityTargets,
|
||||
]);
|
||||
|
||||
return {
|
||||
activities,
|
||||
loading,
|
||||
initialized,
|
||||
noActivities,
|
||||
loading: loadingActivities || loadingActivityTargets,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { useState } from 'react';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
import { ActivityTarget } from '@/activities/types/ActivityTarget';
|
||||
@ -16,8 +15,6 @@ export const useActivityTargetsForTargetableObject = ({
|
||||
nameSingular: targetableObject.targetObjectNameSingular,
|
||||
});
|
||||
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
|
||||
const targetableObjectId = targetableObject.id;
|
||||
|
||||
const skipRequest = !isNonEmptyString(targetableObjectId);
|
||||
@ -34,16 +31,10 @@ export const useActivityTargetsForTargetableObject = ({
|
||||
eq: targetableObject.id,
|
||||
},
|
||||
},
|
||||
onCompleted: () => {
|
||||
if (!initialized) {
|
||||
setInitialized(true);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
activityTargets,
|
||||
loadingActivityTargets,
|
||||
initialized,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { FIND_MANY_ACTIVITY_TARGETS_QUERY_KEY } from '@/activities/query-keys/FindManyActivityTargetsQueryKey';
|
||||
import { findActivityTargetsOperationSignatureFactory } from '@/activities/graphql/operation-signatures/factories/findActivityTargetsOperationSignatureFactory';
|
||||
import { ActivityTarget } from '@/activities/types/ActivityTarget';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { getActivityTargetsFilter } from '@/activities/utils/getActivityTargetsFilter';
|
||||
@ -11,12 +10,14 @@ import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
export const useActivityTargetsForTargetableObjects = ({
|
||||
targetableObjects,
|
||||
skip,
|
||||
onCompleted,
|
||||
}: {
|
||||
targetableObjects: Pick<
|
||||
ActivityTargetableObject,
|
||||
'id' | 'targetObjectNameSingular'
|
||||
>[];
|
||||
skip?: boolean;
|
||||
onCompleted?: (activityTargets: ActivityTarget[]) => void;
|
||||
}) => {
|
||||
const activityTargetsFilter = getActivityTargetsFilter({
|
||||
targetableObjects: targetableObjects,
|
||||
@ -24,7 +25,8 @@ export const useActivityTargetsForTargetableObjects = ({
|
||||
|
||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
const FIND_ACTIVITY_TARGETS_OPERATION_SIGNATURE =
|
||||
findActivityTargetsOperationSignatureFactory({ objectMetadataItems });
|
||||
|
||||
// TODO: We want to optimistically remove from this request
|
||||
// If we are on a show page and we remove the current show page object corresponding activity target
|
||||
@ -33,22 +35,14 @@ export const useActivityTargetsForTargetableObjects = ({
|
||||
useFindManyRecords<ActivityTarget>({
|
||||
skip,
|
||||
objectNameSingular:
|
||||
FIND_MANY_ACTIVITY_TARGETS_QUERY_KEY.objectNameSingular,
|
||||
FIND_ACTIVITY_TARGETS_OPERATION_SIGNATURE.objectNameSingular,
|
||||
filter: activityTargetsFilter,
|
||||
queryFields:
|
||||
FIND_MANY_ACTIVITY_TARGETS_QUERY_KEY.fieldsFactory?.(
|
||||
objectMetadataItems,
|
||||
),
|
||||
onCompleted: () => {
|
||||
if (!initialized) {
|
||||
setInitialized(true);
|
||||
}
|
||||
},
|
||||
recordGqlFields: FIND_ACTIVITY_TARGETS_OPERATION_SIGNATURE.fields,
|
||||
onCompleted,
|
||||
});
|
||||
|
||||
return {
|
||||
activityTargets,
|
||||
loadingActivityTargets,
|
||||
initialized,
|
||||
};
|
||||
};
|
||||
|
||||
@ -34,7 +34,6 @@ export const useCreateActivityInCache = () => {
|
||||
const { record: currentWorkspaceMemberRecord } = useFindOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.WorkspaceMember,
|
||||
objectRecordId: currentWorkspaceMember?.id,
|
||||
depth: 0,
|
||||
});
|
||||
|
||||
const { objectMetadataItem: objectMetadataItemActivity } =
|
||||
@ -66,6 +65,7 @@ export const useCreateActivityInCache = () => {
|
||||
|
||||
const createdActivityInCache = createOneActivityInCache({
|
||||
id: activityId,
|
||||
__typename: 'Activity',
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
author: currentWorkspaceMemberRecord,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { isNonEmptyArray } from '@sniptt/guards';
|
||||
|
||||
import { CREATE_ONE_ACTIVITY_QUERY_KEY } from '@/activities/query-keys/CreateOneActivityQueryKey';
|
||||
import { CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE } from '@/activities/graphql/operation-signatures/CreateOneActivityOperationSignature';
|
||||
import { ActivityForEditor } from '@/activities/types/ActivityForEditor';
|
||||
import { ActivityTarget } from '@/activities/types/ActivityTarget';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
@ -9,9 +9,9 @@ import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
||||
|
||||
export const useCreateActivityInDB = () => {
|
||||
const { createOneRecord: createOneActivity } = useCreateOneRecord({
|
||||
objectNameSingular: CREATE_ONE_ACTIVITY_QUERY_KEY.objectNameSingular,
|
||||
queryFields: CREATE_ONE_ACTIVITY_QUERY_KEY.fields,
|
||||
depth: CREATE_ONE_ACTIVITY_QUERY_KEY.depth,
|
||||
objectNameSingular:
|
||||
CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE.objectNameSingular,
|
||||
recordGqlFields: CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE.fields,
|
||||
});
|
||||
|
||||
const { createManyRecords: createManyActivityTargets } =
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
|
||||
import { FIND_MANY_ACTIVITIES_QUERY_KEY } from '@/activities/query-keys/FindManyActivitiesQueryKey';
|
||||
import { findActivitiesOperationSignatureFactory } from '@/activities/graphql/operation-signatures/factories/findActivitiesOperationSignatureFactory';
|
||||
import { Activity } from '@/activities/types/Activity';
|
||||
import { ActivityTarget } from '@/activities/types/ActivityTarget';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
@ -104,15 +104,16 @@ export const usePrepareFindManyActivitiesQuery = () => {
|
||||
return a.createdAt > b.createdAt ? -1 : 1;
|
||||
});
|
||||
|
||||
const FIND_ACTIVITIES_OPERATION_SIGNATURE =
|
||||
findActivitiesOperationSignatureFactory({ objectMetadataItems });
|
||||
|
||||
upsertFindManyActivitiesInCache({
|
||||
objectRecordsToOverwrite: filteredActivities,
|
||||
queryVariables: {
|
||||
...nextFindManyActivitiesQueryFilter,
|
||||
orderBy: { createdAt: 'DescNullsFirst' },
|
||||
},
|
||||
depth: FIND_MANY_ACTIVITIES_QUERY_KEY.depth,
|
||||
queryFields:
|
||||
FIND_MANY_ACTIVITIES_QUERY_KEY.fieldsFactory?.(objectMetadataItems),
|
||||
recordGqlFields: FIND_ACTIVITIES_OPERATION_SIGNATURE.fields,
|
||||
computeReferences: true,
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user