Feat/activity optimistic activities (#4009)
* Fix naming * Fixed cache.evict bug for relation target deletion * Fixed cascade delete activity targets * Working version * Fix * fix * WIP * Fixed optimistic effect target inline cell * Removed openCreateActivityDrawer v1 * Ok for timeline * Removed console.log * Fix update record optimistic effect * Refactored activity queries into useActivities for everything * Fixed bugs * Cleaned * Fix lint --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -1,17 +1,22 @@
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import styled from '@emotion/styled';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { isNonEmptyArray } from '@sniptt/guards';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
|
||||
import { useDeleteActivityFromCache } from '@/activities/hooks/useDeleteActivityFromCache';
|
||||
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
||||
import { activityInDrawerState } from '@/activities/states/activityInDrawerState';
|
||||
import { activityTargetableEntityArrayState } from '@/activities/states/activityTargetableEntityArrayState';
|
||||
import { isCreatingActivityState } from '@/activities/states/isCreatingActivityState';
|
||||
import { isActivityInCreateModeState } from '@/activities/states/isActivityInCreateModeState';
|
||||
import { isUpsertingActivityInDBState } from '@/activities/states/isCreatingActivityInDBState';
|
||||
import { temporaryActivityForEditorState } from '@/activities/states/temporaryActivityForEditorState';
|
||||
import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState';
|
||||
import { useRemoveFromTimelineActivitiesQueries } from '@/activities/timeline/hooks/useRemoveFromTimelineActivitiesQueries';
|
||||
import { timelineTargetableObjectState } from '@/activities/timeline/states/timelineTargetableObjectState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords';
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { mapToRecordId } from '@/object-record/utils/mapToObjectId';
|
||||
import { IconPlus, IconTrash } from '@/ui/display/icon';
|
||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';
|
||||
@ -24,6 +29,8 @@ const StyledButtonContainer = styled.div`
|
||||
|
||||
export const ActivityActionBar = () => {
|
||||
const viewableActivityId = useRecoilValue(viewableActivityIdState);
|
||||
const activityInDrawer = useRecoilValue(activityInDrawerState);
|
||||
|
||||
const activityTargetableEntityArray = useRecoilValue(
|
||||
activityTargetableEntityArrayState,
|
||||
);
|
||||
@ -33,27 +40,52 @@ export const ActivityActionBar = () => {
|
||||
refetchFindManyQuery: true,
|
||||
});
|
||||
|
||||
const { deleteManyRecords: deleteManyActivityTargets } = useDeleteManyRecords(
|
||||
{
|
||||
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
|
||||
refetchFindManyQuery: true,
|
||||
},
|
||||
);
|
||||
|
||||
const [temporaryActivityForEditor, setTemporaryActivityForEditor] =
|
||||
useRecoilState(temporaryActivityForEditorState);
|
||||
|
||||
const { deleteActivityFromCache } = useDeleteActivityFromCache();
|
||||
|
||||
const [isCreatingActivity] = useRecoilState(isCreatingActivityState);
|
||||
|
||||
const apolloClient = useApolloClient();
|
||||
const [isActivityInCreateMode] = useRecoilState(isActivityInCreateModeState);
|
||||
const [isUpsertingActivityInDB] = useRecoilState(
|
||||
isUpsertingActivityInDBState,
|
||||
);
|
||||
const timelineTargetableObject = useRecoilValue(
|
||||
timelineTargetableObjectState,
|
||||
);
|
||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||
|
||||
const { removeFromTimelineActivitiesQueries } =
|
||||
useRemoveFromTimelineActivitiesQueries();
|
||||
|
||||
const deleteActivity = () => {
|
||||
if (viewableActivityId) {
|
||||
if (isCreatingActivity && isDefined(temporaryActivityForEditor)) {
|
||||
if (isActivityInCreateMode && isDefined(temporaryActivityForEditor)) {
|
||||
deleteActivityFromCache(temporaryActivityForEditor);
|
||||
setTemporaryActivityForEditor(null);
|
||||
} else {
|
||||
deleteOneActivity?.(viewableActivityId);
|
||||
// TODO: find a better way to do this with custom optimistic rendering for activities
|
||||
apolloClient.refetchQueries({
|
||||
include: ['FindManyActivities'],
|
||||
});
|
||||
if (activityInDrawer) {
|
||||
const activityTargetIdsToDelete =
|
||||
activityInDrawer?.activityTargets.map(mapToRecordId) ?? [];
|
||||
|
||||
if (isDefined(timelineTargetableObject)) {
|
||||
removeFromTimelineActivitiesQueries({
|
||||
activityTargetsToRemove: activityInDrawer?.activityTargets ?? [],
|
||||
activityIdToRemove: viewableActivityId,
|
||||
});
|
||||
}
|
||||
|
||||
if (isNonEmptyArray(activityTargetIdsToDelete)) {
|
||||
deleteManyActivityTargets(activityTargetIdsToDelete);
|
||||
}
|
||||
deleteOneActivity?.(viewableActivityId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,17 +98,19 @@ export const ActivityActionBar = () => {
|
||||
|
||||
const addActivity = () => {
|
||||
setIsRightDrawerOpen(false);
|
||||
if (record) {
|
||||
if (record && timelineTargetableObject) {
|
||||
openCreateActivity({
|
||||
type: record.type,
|
||||
assigneeId: isNonEmptyString(record.assigneeId)
|
||||
? record.assigneeId
|
||||
: undefined,
|
||||
customAssignee: record.assignee,
|
||||
targetableObjects: activityTargetableEntityArray,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const actionsAreDisabled = isUpsertingActivityInDB;
|
||||
|
||||
const isCreateActionDisabled = isActivityInCreateMode;
|
||||
|
||||
return (
|
||||
<StyledButtonContainer>
|
||||
<IconButton
|
||||
@ -84,12 +118,14 @@ export const ActivityActionBar = () => {
|
||||
onClick={addActivity}
|
||||
size="medium"
|
||||
variant="secondary"
|
||||
disabled={actionsAreDisabled || isCreateActionDisabled}
|
||||
/>
|
||||
<IconButton
|
||||
Icon={IconTrash}
|
||||
onClick={deleteActivity}
|
||||
size="medium"
|
||||
variant="secondary"
|
||||
disabled={actionsAreDisabled}
|
||||
/>
|
||||
</StyledButtonContainer>
|
||||
);
|
||||
|
||||
@ -24,11 +24,11 @@ export const RightDrawerActivity = ({
|
||||
showComment = true,
|
||||
fillTitleFromBody = false,
|
||||
}: RightDrawerActivityProps) => {
|
||||
const { activity } = useActivityById({
|
||||
const { activity, loading } = useActivityById({
|
||||
activityId,
|
||||
});
|
||||
|
||||
if (!activity) {
|
||||
if (!activity || loading) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user