Files
twenty/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx
Charles Bochet 86c0f311f5 Introduce ComponentState (#4386)
* Proof of concept ComponentState

* Migrate to createState and createFamilyState

* Refactor

* Fix

* Fix tests

* Fix lint

* Fix tests

* Re-enable coverage
2024-03-09 11:31:00 +01:00

259 lines
10 KiB
TypeScript

import { useLocation } from 'react-router-dom';
import styled from '@emotion/styled';
import { isNonEmptyArray, isNonEmptyString } from '@sniptt/guards';
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { useDeleteActivityFromCache } from '@/activities/hooks/useDeleteActivityFromCache';
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
import { useRemoveFromActivitiesQueries } from '@/activities/hooks/useRemoveFromActivitiesQueries';
import { useRemoveFromActivityTargetsQueries } from '@/activities/hooks/useRemoveFromActivityTargetsQueries';
import { currentNotesQueryVariablesState } from '@/activities/notes/states/currentNotesQueryVariablesState';
import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState';
import { activityTargetableEntityArrayState } from '@/activities/states/activityTargetableEntityArrayState';
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 { currentCompletedTaskQueryVariablesState } from '@/activities/tasks/states/currentCompletedTaskQueryVariablesState';
import { currentIncompleteTaskQueryVariablesState } from '@/activities/tasks/states/currentIncompleteTaskQueryVariablesState';
import { FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY } from '@/activities/timeline/constants/FindManyTimelineActivitiesOrderBy';
import { objectShowPageTargetableObjectState } from '@/activities/timeline/states/objectShowPageTargetableObjectIdState';
import { Activity } from '@/activities/types/Activity';
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 { getChildRelationArray } from '@/object-record/utils/getChildRelationArray';
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';
import { isNonNullable } from '~/utils/isNonNullable';
const StyledButtonContainer = styled.div`
display: inline-flex;
gap: ${({ theme }) => theme.spacing(2)};
`;
export const ActivityActionBar = () => {
const viewableActivityId = useRecoilValue(viewableActivityIdState());
const activityIdInDrawer = useRecoilValue(activityIdInDrawerState());
const activityTargetableEntityArray = useRecoilValue(
activityTargetableEntityArrayState(),
);
const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState());
const { deleteOneRecord: deleteOneActivity } = useDeleteOneRecord({
objectNameSingular: CoreObjectNameSingular.Activity,
});
const { deleteManyRecords: deleteManyActivityTargets } = useDeleteManyRecords(
{
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
},
);
const [temporaryActivityForEditor, setTemporaryActivityForEditor] =
useRecoilState(temporaryActivityForEditorState());
const { deleteActivityFromCache } = useDeleteActivityFromCache();
const [isActivityInCreateMode] = useRecoilState(
isActivityInCreateModeState(),
);
const [isUpsertingActivityInDB] = useRecoilState(
isUpsertingActivityInDBState(),
);
const objectShowPageTargetableObject = useRecoilValue(
objectShowPageTargetableObjectState,
);
const openCreateActivity = useOpenCreateActivityDrawer();
const currentCompletedTaskQueryVariables = useRecoilValue(
currentCompletedTaskQueryVariablesState,
);
const currentIncompleteTaskQueryVariables = useRecoilValue(
currentIncompleteTaskQueryVariablesState,
);
const currentNotesQueryVariables = useRecoilValue(
currentNotesQueryVariablesState,
);
const { pathname } = useLocation();
const { removeFromActivitiesQueries } = useRemoveFromActivitiesQueries();
const { removeFromActivityTargetsQueries } =
useRemoveFromActivityTargetsQueries();
const weAreOnObjectShowPage = pathname.startsWith('/object');
const weAreOnTaskPage = pathname.startsWith('/tasks');
const deleteActivity = useRecoilCallback(
({ snapshot }) =>
async () => {
if (!activityIdInDrawer) {
throw new Error(
'activityIdInDrawer is not defined, this should not happen',
);
}
const activity = snapshot
.getLoadable(recordStoreFamilyState(activityIdInDrawer))
.getValue() as Activity;
const activityTargets = getChildRelationArray({
childRelation: activity.activityTargets,
});
setIsRightDrawerOpen(false);
if (isNonEmptyString(viewableActivityId)) {
if (
isActivityInCreateMode &&
isNonNullable(temporaryActivityForEditor)
) {
deleteActivityFromCache(temporaryActivityForEditor);
setTemporaryActivityForEditor(null);
} else if (isNonEmptyString(activityIdInDrawer)) {
const activityTargetIdsToDelete: string[] =
activityTargets.map(mapToRecordId) ?? [];
if (weAreOnTaskPage) {
removeFromActivitiesQueries({
activityIdToRemove: viewableActivityId,
targetableObjects: [],
activitiesFilters: currentCompletedTaskQueryVariables?.filter,
activitiesOrderByVariables:
currentCompletedTaskQueryVariables?.orderBy,
});
removeFromActivitiesQueries({
activityIdToRemove: viewableActivityId,
targetableObjects: [],
activitiesFilters: currentIncompleteTaskQueryVariables?.filter,
activitiesOrderByVariables:
currentIncompleteTaskQueryVariables?.orderBy,
});
} else if (
weAreOnObjectShowPage &&
isNonNullable(objectShowPageTargetableObject)
) {
removeFromActivitiesQueries({
activityIdToRemove: viewableActivityId,
targetableObjects: [objectShowPageTargetableObject],
activitiesFilters: {},
activitiesOrderByVariables:
FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY,
});
if (isNonNullable(currentCompletedTaskQueryVariables)) {
removeFromActivitiesQueries({
activityIdToRemove: viewableActivityId,
targetableObjects: [objectShowPageTargetableObject],
activitiesFilters: currentCompletedTaskQueryVariables?.filter,
activitiesOrderByVariables:
currentCompletedTaskQueryVariables?.orderBy,
});
}
if (isNonNullable(currentIncompleteTaskQueryVariables)) {
removeFromActivitiesQueries({
activityIdToRemove: viewableActivityId,
targetableObjects: [objectShowPageTargetableObject],
activitiesFilters:
currentIncompleteTaskQueryVariables?.filter,
activitiesOrderByVariables:
currentIncompleteTaskQueryVariables?.orderBy,
});
}
if (isNonNullable(currentNotesQueryVariables)) {
removeFromActivitiesQueries({
activityIdToRemove: viewableActivityId,
targetableObjects: [objectShowPageTargetableObject],
activitiesFilters: currentNotesQueryVariables?.filter,
activitiesOrderByVariables:
currentNotesQueryVariables?.orderBy,
});
}
removeFromActivityTargetsQueries({
activityTargetsToRemove: activity?.activityTargets ?? [],
targetableObjects: [objectShowPageTargetableObject],
});
}
if (isNonEmptyArray(activityTargetIdsToDelete)) {
await deleteManyActivityTargets(activityTargetIdsToDelete);
}
await deleteOneActivity?.(viewableActivityId);
}
}
},
[
activityIdInDrawer,
currentCompletedTaskQueryVariables,
currentIncompleteTaskQueryVariables,
currentNotesQueryVariables,
deleteActivityFromCache,
deleteManyActivityTargets,
deleteOneActivity,
isActivityInCreateMode,
objectShowPageTargetableObject,
removeFromActivitiesQueries,
removeFromActivityTargetsQueries,
setTemporaryActivityForEditor,
temporaryActivityForEditor,
viewableActivityId,
weAreOnObjectShowPage,
weAreOnTaskPage,
setIsRightDrawerOpen,
],
);
const record = useRecoilValue(
recordStoreFamilyState(viewableActivityId ?? ''),
);
const addActivity = () => {
setIsRightDrawerOpen(false);
if (
isNonNullable(record) &&
isNonNullable(objectShowPageTargetableObject)
) {
openCreateActivity({
type: record?.type,
customAssignee: record?.assignee,
targetableObjects: activityTargetableEntityArray,
});
}
};
const actionsAreDisabled = isUpsertingActivityInDB;
const isCreateActionDisabled = isActivityInCreateMode;
return (
<StyledButtonContainer>
<IconButton
Icon={IconPlus}
onClick={addActivity}
size="medium"
variant="secondary"
disabled={actionsAreDisabled || isCreateActionDisabled}
/>
<IconButton
Icon={IconTrash}
onClick={deleteActivity}
size="medium"
variant="secondary"
disabled={actionsAreDisabled}
/>
</StyledButtonContainer>
);
};