Activity as standard object (#6219)
In this PR I layout the first steps to migrate Activity to a traditional Standard objects Since this is a big transition, I'd rather split it into several deployments / PRs <img width="1512" alt="image" src="https://github.com/user-attachments/assets/012e2bbf-9d1b-4723-aaf6-269ef588b050"> --------- Co-authored-by: Charles Bochet <charles@twenty.com> Co-authored-by: bosiraphael <71827178+bosiraphael@users.noreply.github.com> Co-authored-by: Weiko <corentin@twenty.com> Co-authored-by: Faisal-imtiyaz123 <142205282+Faisal-imtiyaz123@users.noreply.github.com> Co-authored-by: Prateek Jain <prateekj1171998@gmail.com>
This commit is contained in:
@ -1,133 +0,0 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { isNonEmptyArray, isNonEmptyString } from '@sniptt/guards';
|
||||
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { IconTrash } from 'twenty-ui';
|
||||
|
||||
import { useRefreshShowPageFindManyActivitiesQueries } from '@/activities/hooks/useRefreshShowPageFindManyActivitiesQueries';
|
||||
import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState';
|
||||
import { isActivityInCreateModeState } from '@/activities/states/isActivityInCreateModeState';
|
||||
import { isUpsertingActivityInDBState } from '@/activities/states/isCreatingActivityInDBState';
|
||||
import { temporaryActivityForEditorState } from '@/activities/states/temporaryActivityForEditorState';
|
||||
import { Activity } from '@/activities/types/Activity';
|
||||
import { ActivityTarget } from '@/activities/types/ActivityTarget';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useDeleteRecordFromCache } from '@/object-record/cache/hooks/useDeleteRecordFromCache';
|
||||
import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords';
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { mapToRecordId } from '@/object-record/utils/mapToObjectId';
|
||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
display: inline-flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
export const ActivityActionBar = () => {
|
||||
const viewableRecordId = useRecoilValue(viewableRecordIdState);
|
||||
const activityIdInDrawer = useRecoilValue(activityIdInDrawerState);
|
||||
|
||||
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 = useDeleteRecordFromCache({
|
||||
objectNameSingular: CoreObjectNameSingular.Activity,
|
||||
});
|
||||
const deleteActivityTargetFromCache = useDeleteRecordFromCache({
|
||||
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
|
||||
});
|
||||
|
||||
const [isActivityInCreateMode] = useRecoilState(isActivityInCreateModeState);
|
||||
const [isUpsertingActivityInDB] = useRecoilState(
|
||||
isUpsertingActivityInDBState,
|
||||
);
|
||||
|
||||
const { refreshShowPageFindManyActivitiesQueries } =
|
||||
useRefreshShowPageFindManyActivitiesQueries();
|
||||
|
||||
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;
|
||||
|
||||
setIsRightDrawerOpen(false);
|
||||
|
||||
if (!isNonEmptyString(viewableRecordId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isActivityInCreateMode && isDefined(temporaryActivityForEditor)) {
|
||||
deleteActivityFromCache(temporaryActivityForEditor);
|
||||
setTemporaryActivityForEditor(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNonEmptyString(activityIdInDrawer)) {
|
||||
const activityTargetIdsToDelete: string[] =
|
||||
activity.activityTargets.map(mapToRecordId) ?? [];
|
||||
|
||||
deleteActivityFromCache(activity);
|
||||
activity.activityTargets.forEach((activityTarget: ActivityTarget) => {
|
||||
deleteActivityTargetFromCache(activityTarget);
|
||||
});
|
||||
|
||||
refreshShowPageFindManyActivitiesQueries();
|
||||
|
||||
if (isNonEmptyArray(activityTargetIdsToDelete)) {
|
||||
await deleteManyActivityTargets(activityTargetIdsToDelete);
|
||||
}
|
||||
|
||||
await deleteOneActivity?.(viewableRecordId);
|
||||
}
|
||||
},
|
||||
[
|
||||
activityIdInDrawer,
|
||||
setIsRightDrawerOpen,
|
||||
viewableRecordId,
|
||||
isActivityInCreateMode,
|
||||
temporaryActivityForEditor,
|
||||
deleteActivityFromCache,
|
||||
setTemporaryActivityForEditor,
|
||||
refreshShowPageFindManyActivitiesQueries,
|
||||
deleteOneActivity,
|
||||
deleteActivityTargetFromCache,
|
||||
deleteManyActivityTargets,
|
||||
],
|
||||
);
|
||||
|
||||
const actionsAreDisabled = isUpsertingActivityInDB;
|
||||
|
||||
return (
|
||||
<StyledButtonContainer>
|
||||
<IconButton
|
||||
Icon={IconTrash}
|
||||
onClick={deleteActivity}
|
||||
size="medium"
|
||||
variant="secondary"
|
||||
disabled={actionsAreDisabled}
|
||||
/>
|
||||
</StyledButtonContainer>
|
||||
);
|
||||
};
|
||||
@ -1,39 +0,0 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { ActivityEditor } from '@/activities/components/ActivityEditor';
|
||||
import { ActivityEditorEffect } from '@/activities/components/ActivityEditorEffect';
|
||||
import { RecordValueSetterEffect } from '@/object-record/record-store/components/RecordValueSetterEffect';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
justify-content: space-between;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
type RightDrawerActivityProps = {
|
||||
activityId: string;
|
||||
showComment?: boolean;
|
||||
fillTitleFromBody?: boolean;
|
||||
};
|
||||
|
||||
export const RightDrawerActivity = ({
|
||||
activityId,
|
||||
showComment = false,
|
||||
fillTitleFromBody = false,
|
||||
}: RightDrawerActivityProps) => {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<RecordValueSetterEffect recordId={activityId} />
|
||||
<ActivityEditorEffect activityId={activityId} />
|
||||
<ActivityEditor
|
||||
activityId={activityId}
|
||||
showComment={showComment}
|
||||
fillTitleFromBody={fillTitleFromBody}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
@ -1,21 +0,0 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
|
||||
|
||||
import { RightDrawerActivity } from '../RightDrawerActivity';
|
||||
|
||||
export const RightDrawerCreateActivity = () => {
|
||||
const viewableRecordId = useRecoilValue(viewableRecordIdState);
|
||||
|
||||
return (
|
||||
<>
|
||||
{viewableRecordId && (
|
||||
<RightDrawerActivity
|
||||
activityId={viewableRecordId}
|
||||
showComment={false}
|
||||
fillTitleFromBody={true}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -1,17 +0,0 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
|
||||
|
||||
import { RightDrawerActivity } from '../RightDrawerActivity';
|
||||
|
||||
export const RightDrawerEditActivity = () => {
|
||||
const viewableRecordId = useRecoilValue(viewableRecordIdState);
|
||||
|
||||
return (
|
||||
<>
|
||||
{viewableRecordId && (
|
||||
<RightDrawerActivity activityId={viewableRecordId} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user