Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Right drawer to edit records #5551

Merged
merged 33 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
12cc126
Basic edit in right drawer implem
FelixMalfait May 23, 2024
bcd26ad
Remove viewableActivityIdState
FelixMalfait May 23, 2024
79d6732
Remove viewableEmailThreadIdState
FelixMalfait May 23, 2024
b2cf04b
Actually better if we close the sidepanel on click outside
FelixMalfait May 23, 2024
98ea5fa
Fix linter
FelixMalfait May 23, 2024
3f4ca28
Change first cell behavior
FelixMalfait May 23, 2024
ec11e45
Remove panel for creation from index, focus on creation from show ins…
FelixMalfait May 23, 2024
dc5df24
Remove viewableCalendarEventIdState
FelixMalfait May 23, 2024
c144747
Summary tab
FelixMalfait May 24, 2024
a8dac2b
Improve mobile display
FelixMalfait May 26, 2024
3ec0298
Merge main (with regressions...)
FelixMalfait May 29, 2024
f061741
Merge branch 'main' into poc-right-drawer
FelixMalfait May 29, 2024
ae5cf01
Bring back button
FelixMalfait May 29, 2024
3ea22e9
WIP
FelixMalfait May 30, 2024
33465fe
Add context
FelixMalfait May 30, 2024
a5016c9
Create relationship
FelixMalfait May 30, 2024
32cfd54
Fix tabs issue
FelixMalfait May 31, 2024
0289968
Smarter firstname/lastname split
FelixMalfait May 31, 2024
ccf60c0
Add ability to add relation from list view
FelixMalfait May 31, 2024
0efd78e
Fix scroll
FelixMalfait May 31, 2024
62d858a
Fix strange relation on picker (although fix isn't that great either)
FelixMalfait May 31, 2024
684334b
Disable right drawer access from list
FelixMalfait May 31, 2024
6b67ade
Improve relation creation
FelixMalfait May 31, 2024
8674e61
Rename panel to right drawer
FelixMalfait May 31, 2024
5059239
Always show add new
FelixMalfait Jun 3, 2024
89df595
Code style updates
FelixMalfait Jun 3, 2024
1941b50
Merge branch 'main' into poc-right-drawer
FelixMalfait Jun 3, 2024
51b5c92
Typo
FelixMalfait Jun 3, 2024
1b210a2
Fix drawer transition glitch
FelixMalfait Jun 3, 2024
0b7bd6c
Improve drawer top bar
FelixMalfait Jun 3, 2024
2aa2795
Design fix
FelixMalfait Jun 3, 2024
337a1fc
Quick fix
FelixMalfait Jun 3, 2024
09cd6ed
Fix a broken typescript validation (unrelated to this PR)
FelixMalfait Jun 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import { useRecoilValue } from 'recoil';

import { CalendarEventDetails } from '@/activities/calendar/components/CalendarEventDetails';
import { FIND_ONE_CALENDAR_EVENT_OPERATION_SIGNATURE } from '@/activities/calendar/graphql/operation-signatures/FindOneCalendarEventOperationSignature';
import { viewableCalendarEventIdState } from '@/activities/calendar/states/viewableCalendarEventIdState';
import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
import { useSetRecordInStore } from '@/object-record/record-store/hooks/useSetRecordInStore';

export const RightDrawerCalendarEvent = () => {
const { setRecords } = useSetRecordInStore();
const viewableCalendarEventId = useRecoilValue(viewableCalendarEventIdState);
const viewableRecordId = useRecoilValue(viewableRecordIdState);
const { record: calendarEvent } = useFindOneRecord<CalendarEvent>({
objectNameSingular:
FIND_ONE_CALENDAR_EVENT_OPERATION_SIGNATURE.objectNameSingular,
objectRecordId: viewableCalendarEventId ?? '',
objectRecordId: viewableRecordId ?? '',
recordGqlFields: FIND_ONE_CALENDAR_EVENT_OPERATION_SIGNATURE.fields,
onCompleted: (record) => setRecords([record]),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,32 @@ import { act, renderHook } from '@testing-library/react';
import { RecoilRoot, useRecoilValue } from 'recoil';

import { useOpenCalendarEventRightDrawer } from '@/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer';
import { viewableCalendarEventIdState } from '@/activities/calendar/states/viewableCalendarEventIdState';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';

describe('useOpenCalendarEventRightDrawer', () => {
it('opens the right drawer with the calendar event', () => {
const { result } = renderHook(
() => {
const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState);
const viewableCalendarEventId = useRecoilValue(
viewableCalendarEventIdState,
);
const viewableRecordId = useRecoilValue(viewableRecordIdState);
return {
...useOpenCalendarEventRightDrawer(),
isRightDrawerOpen,
viewableCalendarEventId,
viewableRecordId,
};
},
{ wrapper: RecoilRoot },
);

expect(result.current.isRightDrawerOpen).toBe(false);
expect(result.current.viewableCalendarEventId).toBeNull();
expect(result.current.viewableRecordId).toBeNull();

act(() => {
result.current.openCalendarEventRightDrawer('1234');
});

expect(result.current.isRightDrawerOpen).toBe(true);
expect(result.current.viewableCalendarEventId).toBe('1234');
expect(result.current.viewableRecordId).toBe('1234');
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useSetRecoilState } from 'recoil';

import { viewableCalendarEventIdState } from '@/activities/calendar/states/viewableCalendarEventIdState';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
Expand All @@ -9,9 +9,7 @@ import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope
export const useOpenCalendarEventRightDrawer = () => {
const { openRightDrawer } = useRightDrawer();
const setHotkeyScope = useSetHotkeyScope();
const setViewableCalendarEventId = useSetRecoilState(
viewableCalendarEventIdState,
);
const setViewableCalendarEventId = useSetRecoilState(viewableRecordIdState);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming setViewableCalendarEventId to setViewableRecordId for consistency.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes


const openCalendarEventRightDrawer = (calendarEventId: string) => {
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { Meta, StoryObj } from '@storybook/react';
import { useSetRecoilState } from 'recoil';
import { ComponentDecorator } from 'twenty-ui';

import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';

import { ActivityActionBar } from '../../right-drawer/components/ActivityActionBar';
import { Comment } from '../Comment';

import { mockComment, mockCommentWithLongValues } from './mock-comment';

const CommentSetterEffect = () => {
const setViewableActivity = useSetRecoilState(viewableActivityIdState);
const setViewableActivity = useSetRecoilState(viewableRecordIdState);
FelixMalfait marked this conversation as resolved.
Show resolved Hide resolved

useEffect(() => {
setViewableActivity('test-id');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { DateTime } from 'luxon';
import { useSetRecoilState } from 'recoil';

import { ActivityActionBar } from '@/activities/right-drawer/components/ActivityActionBar';
import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
import { avatarUrl } from '~/testing/mock-data/users';

Expand All @@ -13,7 +13,7 @@ import { CommentHeader } from '../CommentHeader';
import { mockComment, mockCommentWithLongValues } from './mock-comment';

const CommentHeaderSetterEffect = () => {
const setViewableActivity = useSetRecoilState(viewableActivityIdState);
const setViewableActivity = useSetRecoilState(viewableRecordIdState);
FelixMalfait marked this conversation as resolved.
Show resolved Hide resolved

useEffect(() => {
setViewableActivity('test-id');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { ActivityComments } from '@/activities/components/ActivityComments';
import { ActivityCreationDate } from '@/activities/components/ActivityCreationDate';
import { ActivityEditorFields } from '@/activities/components/ActivityEditorFields';
import { ActivityTitleEffect } from '@/activities/components/ActivityTitleEffect';
import { ActivityTypeDropdown } from '@/activities/components/ActivityTypeDropdown';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';

import { ActivityTitle } from './ActivityTitle';
Expand Down Expand Up @@ -68,7 +67,6 @@ export const ActivityEditor = ({
<StyledContainer ref={containerRef}>
<StyledUpperPartContainer>
<StyledTopContainer>
<ActivityTypeDropdown activityId={activityId} />
<ActivityTitleEffect activityId={activityId} />
<StyledTitleContainer>
<ActivityTitle activityId={activityId} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import styled from '@emotion/styled';
import { IconMail, Tag } from 'twenty-ui';

import { beautifyPastDateRelativeToNow } from '~/utils/date-utils';
Comment on lines 1 to 3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing unused imports to keep the code clean.


Expand Down Expand Up @@ -43,7 +42,6 @@ export const EmailThreadHeader = ({
}: EmailThreadHeaderProps) => {
return (
<StyledContainer>
<Tag Icon={IconMail} color="gray" text="Email" onClick={() => {}} />
<StyledHead>
<StyledHeading>{subject}</StyledHeading>
<StyledContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { act, renderHook } from '@testing-library/react';
import { RecoilRoot, useRecoilState, useRecoilValue } from 'recoil';

import { useEmailThread } from '@/activities/emails/hooks/useEmailThread';
import { viewableEmailThreadIdState } from '@/activities/emails/states/viewableEmailThreadIdState';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';

const viewableEmailThreadId = '1234';
Expand All @@ -13,24 +13,22 @@ describe('useEmailThread', () => {
() => {
const emailThread = useEmailThread();
const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState);
const viewableEmailThreadId = useRecoilValue(
viewableEmailThreadIdState,
);
const viewableRecordId = useRecoilValue(viewableRecordIdState);

return { ...emailThread, isRightDrawerOpen, viewableEmailThreadId };
return { ...emailThread, isRightDrawerOpen, viewableRecordId };
},
{ wrapper: RecoilRoot },
);

expect(result.current.isRightDrawerOpen).toBe(false);
expect(result.current.viewableEmailThreadId).toBeNull();
expect(result.current.viewableRecordId).toBeNull();

act(() => {
result.current.openEmailThread(viewableEmailThreadId);
});

expect(result.current.isRightDrawerOpen).toBe(true);
expect(result.current.viewableEmailThreadId).toBe(viewableEmailThreadId);
expect(result.current.viewableRecordId).toBe(viewableEmailThreadId);
});

it('should close email thread if trying to open the same thread id', () => {
Expand All @@ -40,30 +38,31 @@ describe('useEmailThread', () => {
const [isRightDrawerOpen, setIsRightDrawerOpen] = useRecoilState(
isRightDrawerOpenState,
);
const [viewableEmailThreadId, setViewableEmailThreadId] =
useRecoilState(viewableEmailThreadIdState);
const [viewableRecordId, setViewableRecordId] = useRecoilState(
viewableRecordIdState,
);

return {
...emailThread,
isRightDrawerOpen,
viewableEmailThreadId,
viewableRecordId,
setIsRightDrawerOpen,
setViewableEmailThreadId,
setViewableRecordId,
};
},
{ wrapper: RecoilRoot },
);

act(() => {
result.current.setIsRightDrawerOpen(true);
result.current.setViewableEmailThreadId(viewableEmailThreadId);
result.current.setViewableRecordId(viewableEmailThreadId);
});

act(() => {
result.current.openEmailThread(viewableEmailThreadId);
});

expect(result.current.isRightDrawerOpen).toBe(false);
expect(result.current.viewableEmailThreadId).toBeNull();
expect(result.current.viewableRecordId).toBeNull();
});
});
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useRecoilCallback } from 'recoil';

import { useOpenEmailThreadRightDrawer } from '@/activities/emails/right-drawer/hooks/useOpenEmailThreadRightDrawer';
import { viewableEmailThreadIdState } from '@/activities/emails/states/viewableEmailThreadIdState';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';

export const useEmailThread = () => {
const { closeRightDrawer } = useRightDrawer();
const openEmailThredRightDrawer = useOpenEmailThreadRightDrawer();
const openEmailThreadRightDrawer = useOpenEmailThreadRightDrawer();

const openEmailThread = useRecoilCallback(
({ snapshot, set }) =>
Expand All @@ -17,19 +17,19 @@ export const useEmailThread = () => {
.getValue();

const viewableEmailThreadId = snapshot
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

viewableRecordId

.getLoadable(viewableEmailThreadIdState)
.getLoadable(viewableRecordIdState)
.getValue();

if (isRightDrawerOpen && viewableEmailThreadId === threadId) {
set(viewableEmailThreadIdState, null);
set(viewableRecordIdState, null);
closeRightDrawer();
return;
}

openEmailThredRightDrawer();
set(viewableEmailThreadIdState, threadId);
openEmailThreadRightDrawer();
set(viewableRecordIdState, threadId);
},
[closeRightDrawer, openEmailThredRightDrawer],
[closeRightDrawer, openEmailThreadRightDrawer],
);

return { openEmailThread };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import gql from 'graphql-tag';
import { useRecoilValue } from 'recoil';

import { fetchAllThreadMessagesOperationSignatureFactory } from '@/activities/emails/graphql/operation-signatures/factories/fetchAllThreadMessagesOperationSignatureFactory';
import { viewableEmailThreadIdState } from '@/activities/emails/states/viewableEmailThreadIdState';
import { EmailThreadMessage as EmailThreadMessageType } from '@/activities/emails/types/EmailThreadMessage';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';

export const useRightDrawerEmailThread = () => {
const viewableEmailThreadId = useRecoilValue(viewableEmailThreadIdState);
const viewableRecordId = useRecoilValue(viewableRecordIdState);

const apolloClient = useApolloClient();
const thread = apolloClient.readFragment({
id: `TimelineThread:${viewableEmailThreadId}`,
id: `TimelineThread:${viewableRecordId}`,
fragment: gql`
fragment timelineThread on TimelineThread {
id
Expand All @@ -25,7 +25,7 @@ export const useRightDrawerEmailThread = () => {

const FETCH_ALL_MESSAGES_OPERATION_SIGNATURE =
fetchAllThreadMessagesOperationSignatureFactory({
messageThreadId: viewableEmailThreadId,
messageThreadId: viewableRecordId,
});

const {
Expand All @@ -39,7 +39,7 @@ export const useRightDrawerEmailThread = () => {
FETCH_ALL_MESSAGES_OPERATION_SIGNATURE.objectNameSingular,
orderBy: FETCH_ALL_MESSAGES_OPERATION_SIGNATURE.variables.orderBy,
recordGqlFields: FETCH_ALL_MESSAGES_OPERATION_SIGNATURE.fields,
skip: !viewableEmailThreadId,
skip: !viewableRecordId,
});

const fetchMoreMessages = useCallback(() => {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { RecoilRoot, useRecoilValue } from 'recoil';

import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer';
import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState';
import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';

const Wrapper = ({ children }: { children: ReactNode }) => (
<RecoilRoot>
Expand All @@ -18,12 +18,12 @@ describe('useOpenActivityRightDrawer', () => {
const { result } = renderHook(
() => {
const openActivityRightDrawer = useOpenActivityRightDrawer();
const viewableActivityId = useRecoilValue(viewableActivityIdState);
const viewableRecordId = useRecoilValue(viewableRecordIdState);
const activityIdInDrawer = useRecoilValue(activityIdInDrawerState);
return {
openActivityRightDrawer,
activityIdInDrawer,
viewableActivityId,
viewableRecordId,
};
},
{
Expand All @@ -32,11 +32,11 @@ describe('useOpenActivityRightDrawer', () => {
);

expect(result.current.activityIdInDrawer).toBeNull();
expect(result.current.viewableActivityId).toBeNull();
expect(result.current.viewableRecordId).toBeNull();
act(() => {
result.current.openActivityRightDrawer('123');
});
expect(result.current.activityIdInDrawer).toBe('123');
expect(result.current.viewableActivityId).toBe('123');
expect(result.current.viewableRecordId).toBe('123');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { RecoilRoot, useRecoilValue, useSetRecoilState } from 'recoil';

import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState';
import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';

const mockUUID = '37873e04-2f83-4468-9ab7-3f87da6cafad';

Expand All @@ -28,15 +28,15 @@ describe('useOpenCreateActivityDrawer', () => {
const { result } = renderHook(
() => {
const openActivityRightDrawer = useOpenCreateActivityDrawer();
const viewableActivityId = useRecoilValue(viewableActivityIdState);
const viewableRecordId = useRecoilValue(viewableRecordIdState);
const activityIdInDrawer = useRecoilValue(activityIdInDrawerState);
const setObjectMetadataItems = useSetRecoilState(
objectMetadataItemsState,
);
return {
openActivityRightDrawer,
activityIdInDrawer,
viewableActivityId,
viewableRecordId,
setObjectMetadataItems,
};
},
Expand All @@ -50,14 +50,14 @@ describe('useOpenCreateActivityDrawer', () => {
});

expect(result.current.activityIdInDrawer).toBeNull();
expect(result.current.viewableActivityId).toBeNull();
expect(result.current.viewableRecordId).toBeNull();
await act(async () => {
result.current.openActivityRightDrawer({
type: 'Note',
targetableObjects: [],
});
});
expect(result.current.activityIdInDrawer).toBe(mockUUID);
expect(result.current.viewableActivityId).toBe(mockUUID);
expect(result.current.viewableRecordId).toBe(mockUUID);
});
});
Loading
Loading