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:
@ -10,7 +10,7 @@ import { sortDesc } from '~/utils/sort';
|
||||
|
||||
type CalendarEventGeneric = Omit<
|
||||
CalendarEvent,
|
||||
'participants' | 'externalCreatedAt'
|
||||
'participants' | 'externalCreatedAt' | '__typename'
|
||||
>;
|
||||
|
||||
export const useCalendarEvents = <T extends CalendarEventGeneric>(
|
||||
|
||||
@ -14,7 +14,6 @@ export const RightDrawerCalendarEvent = () => {
|
||||
objectNameSingular: CoreObjectNameSingular.CalendarEvent,
|
||||
objectRecordId: viewableCalendarEventId ?? '',
|
||||
onCompleted: (record) => setRecords([record]),
|
||||
depth: 2,
|
||||
});
|
||||
|
||||
if (!calendarEvent) return null;
|
||||
|
||||
@ -17,4 +17,5 @@ export type CalendarEvent = {
|
||||
title?: string;
|
||||
visibility: 'METADATA' | 'SHARE_EVERYTHING';
|
||||
calendarEventParticipants?: CalendarEventParticipant[];
|
||||
__typename: 'CalendarEvent';
|
||||
};
|
||||
|
||||
@ -161,6 +161,7 @@ export const ActivityBodyEditor = ({
|
||||
...oldActivity,
|
||||
id: activityId,
|
||||
body: newStringifiedBody,
|
||||
__typename: 'Activity',
|
||||
};
|
||||
});
|
||||
|
||||
@ -192,6 +193,7 @@ export const ActivityBodyEditor = ({
|
||||
...oldActivity,
|
||||
id: activityId,
|
||||
title: newTitleFromBody,
|
||||
__typename: 'Activity',
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@ -134,6 +134,7 @@ export const ActivityTitle = ({ activityId }: ActivityTitleProps) => {
|
||||
...currentActivity,
|
||||
id: activity.id,
|
||||
title: newTitle,
|
||||
__typename: activity.__typename,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@ -28,7 +28,6 @@ export const useRightDrawerEmailThread = () => {
|
||||
loading,
|
||||
fetchMoreRecords,
|
||||
} = useFindManyRecords<EmailThreadMessageType>({
|
||||
depth: 3,
|
||||
limit: 10,
|
||||
filter: {
|
||||
messageThreadId: {
|
||||
|
||||
@ -5,4 +5,5 @@ export type EmailThreadMessage = {
|
||||
text: string;
|
||||
receivedAt: string;
|
||||
messageParticipants: EmailThreadMessageParticipant[];
|
||||
__typename: 'EmailThreadMessage';
|
||||
};
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { Attachment } from '@/activities/files/types/Attachment';
|
||||
import { getFileType } from '@/activities/files/utils/getFileType';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getActivityTargetObjectFieldIdName';
|
||||
import { Attachment } from '@/attachments/types/Attachment';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
||||
|
||||
@ -8,7 +8,9 @@ export type Attachment = {
|
||||
activityId: string;
|
||||
authorId: string;
|
||||
createdAt: string;
|
||||
__typename: string;
|
||||
};
|
||||
|
||||
export type AttachmentType =
|
||||
| 'Archive'
|
||||
| 'Audio'
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { QueryKey } from '@/object-record/query-keys/types/QueryKey';
|
||||
import { RecordGqlOperationSignature } from '@/object-record/graphql/types/RecordGqlOperationSignature';
|
||||
|
||||
export const FIND_MANY_ACTIVITIES_QUERY_KEY: QueryKey = {
|
||||
objectNameSingular: CoreObjectNameSingular.Activity,
|
||||
variables: {},
|
||||
fieldsFactory: (_objectMetadataItems: ObjectMetadataItem[]) => {
|
||||
return {
|
||||
export const CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE: RecordGqlOperationSignature =
|
||||
{
|
||||
objectNameSingular: CoreObjectNameSingular.Activity,
|
||||
variables: {},
|
||||
fields: {
|
||||
id: true,
|
||||
__typename: true,
|
||||
createdAt: true,
|
||||
@ -31,8 +30,5 @@ export const FIND_MANY_ACTIVITIES_QUERY_KEY: QueryKey = {
|
||||
dueAt: true,
|
||||
reminderAt: true,
|
||||
type: true,
|
||||
activityTargets: true,
|
||||
};
|
||||
},
|
||||
depth: 2,
|
||||
};
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,45 @@
|
||||
import { generateActivityTargetMorphFieldKeys } from '@/activities/utils/generateActivityTargetMorphFieldKeys';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { RecordGqlOperationSignatureFactory } from '@/object-record/graphql/types/RecordGqlOperationSignatureFactory';
|
||||
|
||||
export const findActivitiesOperationSignatureFactory: RecordGqlOperationSignatureFactory =
|
||||
({ objectMetadataItems }: { objectMetadataItems: ObjectMetadataItem[] }) => ({
|
||||
objectNameSingular: CoreObjectNameSingular.Activity,
|
||||
variables: {},
|
||||
fields: {
|
||||
id: true,
|
||||
__typename: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
author: {
|
||||
id: true,
|
||||
name: true,
|
||||
__typename: true,
|
||||
},
|
||||
authorId: true,
|
||||
assigneeId: true,
|
||||
assignee: {
|
||||
id: true,
|
||||
name: true,
|
||||
__typename: true,
|
||||
},
|
||||
comments: true,
|
||||
attachments: true,
|
||||
body: true,
|
||||
title: true,
|
||||
completedAt: true,
|
||||
dueAt: true,
|
||||
reminderAt: true,
|
||||
type: true,
|
||||
activityTargets: {
|
||||
id: true,
|
||||
__typename: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
activity: true,
|
||||
activityId: true,
|
||||
...generateActivityTargetMorphFieldKeys(objectMetadataItems),
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -1,13 +1,13 @@
|
||||
import { generateActivityTargetMorphFieldKeys } from '@/activities/utils/generateActivityTargetMorphFieldKeys';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { QueryKey } from '@/object-record/query-keys/types/QueryKey';
|
||||
import { RecordGqlOperationSignatureFactory } from '@/object-record/graphql/types/RecordGqlOperationSignatureFactory';
|
||||
|
||||
export const FIND_MANY_ACTIVITY_TARGETS_QUERY_KEY: QueryKey = {
|
||||
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
|
||||
variables: {},
|
||||
fieldsFactory: (objectMetadataItems: ObjectMetadataItem[]) => {
|
||||
return {
|
||||
export const findActivityTargetsOperationSignatureFactory: RecordGqlOperationSignatureFactory =
|
||||
({ objectMetadataItems }: { objectMetadataItems: ObjectMetadataItem[] }) => ({
|
||||
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
|
||||
variables: {},
|
||||
fields: {
|
||||
id: true,
|
||||
__typename: true,
|
||||
createdAt: true,
|
||||
@ -15,7 +15,5 @@ export const FIND_MANY_ACTIVITY_TARGETS_QUERY_KEY: QueryKey = {
|
||||
activity: true,
|
||||
activityId: true,
|
||||
...generateActivityTargetMorphFieldKeys(objectMetadataItems),
|
||||
};
|
||||
},
|
||||
depth: 1,
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -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,
|
||||
});
|
||||
};
|
||||
|
||||
@ -27,14 +27,10 @@ export const Notes = ({
|
||||
}: {
|
||||
targetableObject: ActivityTargetableObject;
|
||||
}) => {
|
||||
const { notes, initialized } = useNotes(targetableObject);
|
||||
const { notes } = useNotes(targetableObject);
|
||||
|
||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||
|
||||
if (!initialized) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
if (notes?.length === 0) {
|
||||
return (
|
||||
<AnimatedPlaceholderEmptyContainer>
|
||||
|
||||
@ -6,7 +6,6 @@ import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableE
|
||||
jest.mock('@/activities/hooks/useActivities', () => ({
|
||||
useActivities: jest.fn(() => ({
|
||||
activities: [{ id: '1', content: 'Example Note' }],
|
||||
initialized: true,
|
||||
loading: false,
|
||||
})),
|
||||
}));
|
||||
@ -29,7 +28,7 @@ jest.mock('recoil', () => {
|
||||
});
|
||||
|
||||
describe('useNotes', () => {
|
||||
it('should return notes, initialized, and loading as expected', () => {
|
||||
it('should return notes, and loading as expected', () => {
|
||||
const mockTargetableObject: ActivityTargetableObject = {
|
||||
id: '1',
|
||||
targetObjectNameSingular: 'Example Target',
|
||||
@ -39,7 +38,6 @@ describe('useNotes', () => {
|
||||
expect(result.current.notes).toEqual([
|
||||
{ id: '1', content: 'Example Note' },
|
||||
]);
|
||||
expect(result.current.initialized).toBe(true);
|
||||
expect(result.current.loading).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -5,7 +5,7 @@ import { useActivities } from '@/activities/hooks/useActivities';
|
||||
import { currentNotesQueryVariablesState } from '@/activities/notes/states/currentNotesQueryVariablesState';
|
||||
import { FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY } from '@/activities/timeline/constants/FindManyTimelineActivitiesOrderBy';
|
||||
import { Note } from '@/activities/types/Note';
|
||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
import { ActivityTargetableObject } from '../../types/ActivityTargetableEntity';
|
||||
@ -18,11 +18,11 @@ export const useNotes = (targetableObject: ActivityTargetableObject) => {
|
||||
type: { eq: 'Note' },
|
||||
},
|
||||
orderBy: FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY,
|
||||
}) as ObjectRecordQueryVariables,
|
||||
}) as RecordGqlOperationVariables,
|
||||
[],
|
||||
);
|
||||
|
||||
const { activities, initialized, loading } = useActivities({
|
||||
const { activities, loading } = useActivities({
|
||||
activitiesFilters: notesQueryVariables.filter ?? {},
|
||||
activitiesOrderByVariables: notesQueryVariables.orderBy ?? {},
|
||||
targetableObjects: [targetableObject],
|
||||
@ -44,7 +44,6 @@ export const useNotes = (targetableObject: ActivityTargetableObject) => {
|
||||
|
||||
return {
|
||||
notes: activities as Note[],
|
||||
initialized,
|
||||
loading,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||
|
||||
export const currentNotesQueryVariablesState =
|
||||
atom<ObjectRecordQueryVariables | null>({
|
||||
atom<RecordGqlOperationVariables | null>({
|
||||
default: null,
|
||||
key: 'currentNotesQueryVariablesState',
|
||||
});
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { QueryKey } from '@/object-record/query-keys/types/QueryKey';
|
||||
|
||||
export const CREATE_ONE_ACTIVITY_QUERY_KEY: QueryKey = {
|
||||
objectNameSingular: CoreObjectNameSingular.Activity,
|
||||
variables: {},
|
||||
fields: {
|
||||
id: true,
|
||||
__typename: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
author: {
|
||||
id: true,
|
||||
name: true,
|
||||
__typename: true,
|
||||
},
|
||||
authorId: true,
|
||||
assigneeId: true,
|
||||
assignee: {
|
||||
id: true,
|
||||
name: true,
|
||||
__typename: true,
|
||||
},
|
||||
comments: true,
|
||||
attachments: true,
|
||||
body: true,
|
||||
title: true,
|
||||
completedAt: true,
|
||||
dueAt: true,
|
||||
reminderAt: true,
|
||||
type: true,
|
||||
},
|
||||
depth: 1,
|
||||
};
|
||||
@ -19,7 +19,6 @@ import { useDeleteRecordFromCache } from '@/object-record/cache/hooks/useDeleteR
|
||||
import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords';
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { getChildRelationArray } from '@/object-record/utils/getChildRelationArray';
|
||||
import { mapToRecordId } from '@/object-record/utils/mapToObjectId';
|
||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';
|
||||
@ -85,10 +84,6 @@ export const ActivityActionBar = () => {
|
||||
.getLoadable(recordStoreFamilyState(activityIdInDrawer))
|
||||
.getValue() as Activity;
|
||||
|
||||
const activityTargets = getChildRelationArray({
|
||||
childRelation: activity.activityTargets,
|
||||
});
|
||||
|
||||
setIsRightDrawerOpen(false);
|
||||
|
||||
if (!isNonEmptyString(viewableActivityId)) {
|
||||
@ -103,10 +98,10 @@ export const ActivityActionBar = () => {
|
||||
|
||||
if (isNonEmptyString(activityIdInDrawer)) {
|
||||
const activityTargetIdsToDelete: string[] =
|
||||
activityTargets.map(mapToRecordId) ?? [];
|
||||
activity.activityTargets.map(mapToRecordId) ?? [];
|
||||
|
||||
deleteActivityFromCache(activity);
|
||||
activityTargets.forEach((activityTarget: ActivityTarget) => {
|
||||
activity.activityTargets.forEach((activityTarget: ActivityTarget) => {
|
||||
deleteActivityTargetFromCache(activityTarget);
|
||||
});
|
||||
|
||||
|
||||
@ -18,7 +18,6 @@ export const CurrentUserDueTaskCountEffect = () => {
|
||||
|
||||
const { records: tasks } = useFindManyRecords<Activity>({
|
||||
objectNameSingular: CoreObjectNameSingular.Activity,
|
||||
depth: 0,
|
||||
filter: {
|
||||
type: { eq: 'Task' },
|
||||
completedAt: { is: 'NULL' },
|
||||
|
||||
@ -40,7 +40,6 @@ export const TaskGroups = ({
|
||||
upcomingTasks,
|
||||
unscheduledTasks,
|
||||
completedTasks,
|
||||
initialized,
|
||||
} = useTasks({
|
||||
filterDropdownId: filterDropdownId,
|
||||
targetableObjects: targetableObjects ?? [],
|
||||
@ -51,10 +50,6 @@ export const TaskGroups = ({
|
||||
const { activeTabIdState } = useTabList(TASKS_TAB_LIST_COMPONENT_ID);
|
||||
const activeTabId = useRecoilValue(activeTabIdState);
|
||||
|
||||
if (!initialized) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
if (
|
||||
(activeTabId !== 'done' &&
|
||||
todayOrPreviousTasks?.length === 0 &&
|
||||
|
||||
@ -49,7 +49,6 @@ const useActivitiesMock = jest.fn(
|
||||
activities: isCompletedFilter
|
||||
? completedTasks
|
||||
: [...todayOrPreviousTasks, ...unscheduledTasks],
|
||||
initialized: true,
|
||||
};
|
||||
},
|
||||
);
|
||||
@ -79,7 +78,6 @@ describe('useTasks', () => {
|
||||
upcomingTasks: [],
|
||||
unscheduledTasks,
|
||||
completedTasks,
|
||||
initialized: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { isNonEmptyArray } from '@sniptt/guards';
|
||||
import { DateTime } from 'luxon';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
|
||||
@ -9,8 +8,8 @@ import { currentIncompleteTaskQueryVariablesState } from '@/activities/tasks/sta
|
||||
import { FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY } from '@/activities/timeline/constants/FindManyTimelineActivitiesOrderBy';
|
||||
import { Activity } from '@/activities/types/Activity';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||
import { parseDate } from '~/utils/date-utils';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
@ -41,8 +40,6 @@ export const useTasks = ({
|
||||
[selectedFilter],
|
||||
);
|
||||
|
||||
const skipActivityTargets = !isNonEmptyArray(targetableObjects);
|
||||
|
||||
const completedQueryVariables = useMemo(
|
||||
() =>
|
||||
({
|
||||
@ -52,7 +49,7 @@ export const useTasks = ({
|
||||
...assigneeIdFilter,
|
||||
},
|
||||
orderBy: FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY,
|
||||
}) as ObjectRecordQueryVariables,
|
||||
}) as RecordGqlOperationVariables,
|
||||
[assigneeIdFilter],
|
||||
);
|
||||
|
||||
@ -65,7 +62,7 @@ export const useTasks = ({
|
||||
...assigneeIdFilter,
|
||||
},
|
||||
orderBy: FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY,
|
||||
}) as ObjectRecordQueryVariables,
|
||||
}) as RecordGqlOperationVariables,
|
||||
[assigneeIdFilter],
|
||||
);
|
||||
|
||||
@ -110,24 +107,16 @@ export const useTasks = ({
|
||||
setCurrentIncompleteTaskQueryVariables,
|
||||
]);
|
||||
|
||||
const {
|
||||
activities: completeTasksData,
|
||||
initialized: initializedCompleteTasks,
|
||||
} = useActivities({
|
||||
const { activities: completeTasksData } = useActivities({
|
||||
targetableObjects,
|
||||
activitiesFilters: completedQueryVariables.filter ?? {},
|
||||
activitiesOrderByVariables: completedQueryVariables.orderBy ?? {},
|
||||
skipActivityTargets,
|
||||
});
|
||||
|
||||
const {
|
||||
activities: incompleteTaskData,
|
||||
initialized: initializedIncompleteTasks,
|
||||
} = useActivities({
|
||||
const { activities: incompleteTaskData } = useActivities({
|
||||
targetableObjects,
|
||||
activitiesFilters: incompleteQueryVariables.filter ?? {},
|
||||
activitiesOrderByVariables: incompleteQueryVariables.orderBy ?? {},
|
||||
skipActivityTargets,
|
||||
});
|
||||
|
||||
const todayOrPreviousTasks = incompleteTaskData?.filter((task) => {
|
||||
@ -159,6 +148,5 @@ export const useTasks = ({
|
||||
upcomingTasks: (upcomingTasks ?? []) as Activity[],
|
||||
unscheduledTasks: (unscheduledTasks ?? []) as Activity[],
|
||||
completedTasks: (completedTasks ?? []) as Activity[],
|
||||
initialized: initializedCompleteTasks && initializedIncompleteTasks,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||
|
||||
export const currentCompletedTaskQueryVariablesState =
|
||||
atom<ObjectRecordQueryVariables | null>({
|
||||
atom<RecordGqlOperationVariables | null>({
|
||||
default: null,
|
||||
key: 'currentCompletedTaskQueryVariablesState',
|
||||
});
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||
|
||||
export const currentIncompleteTaskQueryVariablesState =
|
||||
atom<ObjectRecordQueryVariables | null>({
|
||||
atom<RecordGqlOperationVariables | null>({
|
||||
default: null,
|
||||
key: 'currentIncompleteTaskQueryVariablesState',
|
||||
});
|
||||
|
||||
@ -2,7 +2,7 @@ import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { TimelineCreateButtonGroup } from '@/activities/timeline/components/TimelineCreateButtonGroup';
|
||||
import { timelineActivitiesNetworkingState } from '@/activities/timeline/states/timelineActivitiesNetworkingState';
|
||||
import { timelineActivitiesForGroupState } from '@/activities/timeline/states/timelineActivitiesForGroupState';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import AnimatedPlaceholder from '@/ui/layout/animated-placeholder/components/AnimatedPlaceholder';
|
||||
import {
|
||||
@ -32,20 +32,11 @@ export const Timeline = ({
|
||||
}: {
|
||||
targetableObject: ActivityTargetableObject;
|
||||
}) => {
|
||||
const { initialized, noActivities } = useRecoilValue(
|
||||
timelineActivitiesNetworkingState,
|
||||
const timelineActivitiesForGroup = useRecoilValue(
|
||||
timelineActivitiesForGroupState,
|
||||
);
|
||||
|
||||
const showEmptyState = noActivities;
|
||||
|
||||
const showLoadingState = !initialized;
|
||||
|
||||
if (showLoadingState) {
|
||||
// TODO: Display a beautiful loading page
|
||||
return <></>;
|
||||
}
|
||||
|
||||
if (showEmptyState) {
|
||||
if (timelineActivitiesForGroup.length === 0) {
|
||||
return (
|
||||
<AnimatedPlaceholderEmptyContainer>
|
||||
<AnimatedPlaceholder type="emptyTimeline" />
|
||||
|
||||
@ -6,7 +6,6 @@ import { FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY } from '@/activities/timeline/co
|
||||
import { objectShowPageTargetableObjectState } from '@/activities/timeline/states/objectShowPageTargetableObjectIdState';
|
||||
import { timelineActivitiesFammilyState } from '@/activities/timeline/states/timelineActivitiesFamilyState';
|
||||
import { timelineActivitiesForGroupState } from '@/activities/timeline/states/timelineActivitiesForGroupState';
|
||||
import { timelineActivitiesNetworkingState } from '@/activities/timeline/states/timelineActivitiesNetworkingState';
|
||||
import { timelineActivityWithoutTargetsFamilyState } from '@/activities/timeline/states/timelineActivityWithoutTargetsFamilyState';
|
||||
import { Activity } from '@/activities/types/Activity';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
@ -27,16 +26,13 @@ export const TimelineQueryEffect = ({
|
||||
setTimelineTargetableObject(targetableObject);
|
||||
}, [targetableObject, setTimelineTargetableObject]);
|
||||
|
||||
const { activities, initialized, noActivities } = useActivities({
|
||||
const { activities } = useActivities({
|
||||
targetableObjects: [targetableObject],
|
||||
activitiesFilters: {},
|
||||
activitiesOrderByVariables: FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY,
|
||||
skip: !isDefined(targetableObject),
|
||||
});
|
||||
|
||||
const [timelineActivitiesNetworking, setTimelineActivitiesNetworking] =
|
||||
useRecoilState(timelineActivitiesNetworkingState);
|
||||
|
||||
const [timelineActivitiesForGroup, setTimelineActivitiesForGroup] =
|
||||
useRecoilState(timelineActivitiesForGroupState);
|
||||
|
||||
@ -49,6 +45,7 @@ export const TimelineQueryEffect = ({
|
||||
...activities.map((activity) => ({
|
||||
id: activity.id,
|
||||
createdAt: activity.createdAt,
|
||||
__typename: activity.__typename,
|
||||
})),
|
||||
].sort(sortObjectRecordByDateField('createdAt', 'DescNullsLast'));
|
||||
|
||||
@ -59,23 +56,9 @@ export const TimelineQueryEffect = ({
|
||||
if (!isDeeplyEqual(activitiesForGroup, timelineActivitiesForGroupSorted)) {
|
||||
setTimelineActivitiesForGroup(activitiesForGroup);
|
||||
}
|
||||
|
||||
if (
|
||||
!isDeeplyEqual(timelineActivitiesNetworking.initialized, initialized) ||
|
||||
!isDeeplyEqual(timelineActivitiesNetworking.noActivities, noActivities)
|
||||
) {
|
||||
setTimelineActivitiesNetworking({
|
||||
initialized,
|
||||
noActivities,
|
||||
});
|
||||
}
|
||||
}, [
|
||||
activities,
|
||||
initialized,
|
||||
noActivities,
|
||||
setTimelineActivitiesNetworking,
|
||||
targetableObject,
|
||||
timelineActivitiesNetworking,
|
||||
timelineActivitiesForGroup,
|
||||
setTimelineActivitiesForGroup,
|
||||
]);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { OrderByField } from '@/object-metadata/types/OrderByField';
|
||||
import { RecordGqlOperationOrderBy } from '@/object-record/graphql/types/RecordGqlOperationOrderBy';
|
||||
|
||||
export const FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY: OrderByField = {
|
||||
createdAt: 'DescNullsFirst',
|
||||
};
|
||||
export const FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY: RecordGqlOperationOrderBy =
|
||||
{
|
||||
createdAt: 'DescNullsFirst',
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { isNonEmptyArray, isNonEmptyString } from '@sniptt/guards';
|
||||
import { useRecoilCallback, useRecoilState } from 'recoil';
|
||||
|
||||
@ -28,15 +28,10 @@ export const useTimelineActivities = ({
|
||||
}
|
||||
}, [targetableObject, setObjectShowPageTargetableObject]);
|
||||
|
||||
const {
|
||||
activityTargets,
|
||||
loadingActivityTargets,
|
||||
initialized: initializedActivityTargets,
|
||||
} = useActivityTargetsForTargetableObject({
|
||||
targetableObject,
|
||||
});
|
||||
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
const { activityTargets, loadingActivityTargets } =
|
||||
useActivityTargetsForTargetableObject({
|
||||
targetableObject,
|
||||
});
|
||||
|
||||
const activityIds = Array.from(
|
||||
new Set(
|
||||
@ -65,33 +60,18 @@ export const useTimelineActivities = ({
|
||||
onCompleted: useRecoilCallback(
|
||||
({ set }) =>
|
||||
(activities) => {
|
||||
if (!initialized) {
|
||||
setInitialized(true);
|
||||
}
|
||||
|
||||
for (const activity of activities) {
|
||||
set(recordStoreFamilyState(activity.id), activity);
|
||||
}
|
||||
},
|
||||
[initialized],
|
||||
[],
|
||||
),
|
||||
depth: 3,
|
||||
});
|
||||
|
||||
const noActivityTargets =
|
||||
initializedActivityTargets && !isNonEmptyArray(activityTargets);
|
||||
|
||||
useEffect(() => {
|
||||
if (noActivityTargets) {
|
||||
setInitialized(true);
|
||||
}
|
||||
}, [noActivityTargets]);
|
||||
|
||||
const loading = loadingActivities || loadingActivityTargets;
|
||||
|
||||
return {
|
||||
activities,
|
||||
loading,
|
||||
initialized,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const timelineActivitiesNetworkingState = createState<{
|
||||
initialized: boolean;
|
||||
noActivities: boolean;
|
||||
}>({
|
||||
key: 'timelineActivitiesNetworkingState',
|
||||
defaultValue: {
|
||||
initialized: false,
|
||||
noActivities: false,
|
||||
},
|
||||
});
|
||||
@ -1,7 +1,10 @@
|
||||
import { Activity } from '@/activities/types/Activity';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export type ActivityForActivityGroup = Pick<Activity, 'id' | 'createdAt'>;
|
||||
export type ActivityForActivityGroup = Pick<
|
||||
Activity,
|
||||
'id' | 'createdAt' | '__typename'
|
||||
>;
|
||||
|
||||
export type ActivityGroup = {
|
||||
month: number;
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||
import { sortByAscString } from '~/utils/array/sortByAscString';
|
||||
|
||||
// Todo: this should be replace by the operationSignatureFactory pattern
|
||||
export const makeTimelineActivitiesQueryVariables = ({
|
||||
activityIds,
|
||||
}: {
|
||||
activityIds: string[];
|
||||
}): ObjectRecordQueryVariables => {
|
||||
}): RecordGqlOperationVariables => {
|
||||
return {
|
||||
filter: {
|
||||
id: {
|
||||
|
||||
@ -12,4 +12,5 @@ export type TimelineActivity = {
|
||||
linkedRecordCachedName: string;
|
||||
linkedRecordId: string;
|
||||
linkedObjectMetadataId: string;
|
||||
__typename: 'TimelineActivity';
|
||||
};
|
||||
|
||||
@ -5,7 +5,14 @@ import { WorkspaceMember } from '~/generated-metadata/graphql';
|
||||
|
||||
export type ActivityForEditor = Pick<
|
||||
Activity,
|
||||
'id' | 'title' | 'body' | 'type' | 'completedAt' | 'dueAt' | 'updatedAt'
|
||||
| 'id'
|
||||
| 'title'
|
||||
| 'body'
|
||||
| 'type'
|
||||
| 'completedAt'
|
||||
| 'dueAt'
|
||||
| 'updatedAt'
|
||||
| '__typename'
|
||||
> & {
|
||||
comments?: Comment[];
|
||||
} & {
|
||||
|
||||
@ -12,4 +12,5 @@ export type ActivityTarget = {
|
||||
person?: Pick<Person, 'id' | 'name' | 'avatarUrl'> | null;
|
||||
company?: Pick<Company, 'id' | 'name' | 'domainName'> | null;
|
||||
[key: string]: any;
|
||||
__typename: 'ActivityTarget';
|
||||
};
|
||||
|
||||
@ -7,4 +7,5 @@ export type Comment = {
|
||||
updatedAt: string;
|
||||
activityId: string;
|
||||
author: Pick<WorkspaceMember, 'id' | 'name' | 'avatarUrl'>;
|
||||
__typename: 'Comment';
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user