Refactor Views by cleaning the code, relying on apolloCache and improving performances (#4516)

* Wip refactoring view

* Post merge conflicts

* Fix review

* Add create view capability

* Fix create object missing view

* Fix tests
This commit is contained in:
Charles Bochet 2024-03-20 14:21:58 +01:00 committed by GitHub
parent 20e14cb455
commit cfb0cce9b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
392 changed files with 3474 additions and 4410 deletions

View File

@ -108,6 +108,7 @@
"libphonenumber-js": "^1.10.26", "libphonenumber-js": "^1.10.26",
"lodash.camelcase": "^4.3.0", "lodash.camelcase": "^4.3.0",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"lodash.groupby": "^4.6.0",
"lodash.isempty": "^4.4.0", "lodash.isempty": "^4.4.0",
"lodash.isequal": "^4.5.0", "lodash.isequal": "^4.5.0",
"lodash.isobject": "^3.0.2", "lodash.isobject": "^3.0.2",

View File

@ -47,7 +47,7 @@ import { SettingsWorkspaceMembers } from '~/pages/settings/SettingsWorkspaceMemb
import { Tasks } from '~/pages/tasks/Tasks'; import { Tasks } from '~/pages/tasks/Tasks';
export const App = () => { export const App = () => {
const billing = useRecoilValue(billingState()); const billing = useRecoilValue(billingState);
return ( return (
<> <>

View File

@ -5,7 +5,7 @@ import { COMMAND_MENU_COMMANDS } from '@/command-menu/constants/CommandMenuComma
import { commandMenuCommandsState } from '@/command-menu/states/commandMenuCommandsState'; import { commandMenuCommandsState } from '@/command-menu/states/commandMenuCommandsState';
export const CommandMenuEffect = () => { export const CommandMenuEffect = () => {
const setCommands = useSetRecoilState(commandMenuCommandsState()); const setCommands = useSetRecoilState(commandMenuCommandsState);
const commands = COMMAND_MENU_COMMANDS; const commands = COMMAND_MENU_COMMANDS;
useEffect(() => { useEffect(() => {

View File

@ -45,7 +45,7 @@ export const PageChangeEffect = () => {
const openCreateActivity = useOpenCreateActivityDrawer(); const openCreateActivity = useOpenCreateActivityDrawer();
const isSignUpDisabled = useRecoilValue(isSignUpDisabledState()); const isSignUpDisabled = useRecoilValue(isSignUpDisabledState);
useEffect(() => { useEffect(() => {
if (!previousLocation || previousLocation !== location.pathname) { if (!previousLocation || previousLocation !== location.pathname) {

View File

@ -13,7 +13,7 @@ export const useDefaultHomePagePath = () => {
const companyViewId = records.find( const companyViewId = records.find(
(view: any) => view?.objectMetadataId === companyObjectMetadataItem.id, (view: any) => view?.objectMetadataId === companyObjectMetadataItem.id,
)?.node.id; )?.id;
const defaultHomePagePath = const defaultHomePagePath =
'/objects/companies' + (companyViewId ? `?view=${companyViewId}` : ''); '/objects/companies' + (companyViewId ? `?view=${companyViewId}` : '');

View File

@ -2,6 +2,7 @@ import { StrictMode } from 'react';
import ReactDOM from 'react-dom/client'; import ReactDOM from 'react-dom/client';
import { HelmetProvider } from 'react-helmet-async'; import { HelmetProvider } from 'react-helmet-async';
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import { loadDevMessages, loadErrorMessages } from '@apollo/client/dev';
import { RecoilRoot } from 'recoil'; import { RecoilRoot } from 'recoil';
import { ApolloProvider } from '@/apollo/components/ApolloProvider'; import { ApolloProvider } from '@/apollo/components/ApolloProvider';
@ -33,6 +34,10 @@ import 'react-loading-skeleton/dist/skeleton.css';
const root = ReactDOM.createRoot(document.getElementById('root')!); const root = ReactDOM.createRoot(document.getElementById('root')!);
// Adds messages only in a dev environment
loadDevMessages();
loadErrorMessages();
root.render( root.render(
<RecoilRoot> <RecoilRoot>
<AppErrorBoundary> <AppErrorBoundary>

View File

@ -102,7 +102,7 @@ export const CalendarEventRow = ({
className, className,
}: CalendarEventRowProps) => { }: CalendarEventRowProps) => {
const theme = useTheme(); const theme = useTheme();
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { displayCurrentEventCursor = false } = useContext(CalendarContext); const { displayCurrentEventCursor = false } = useContext(CalendarContext);
const { openCalendarEventRightDrawer } = useOpenCalendarEventRightDrawer(); const { openCalendarEventRightDrawer } = useOpenCalendarEventRightDrawer();

View File

@ -9,10 +9,10 @@ import { useSetRecordInStore } from '@/object-record/record-store/hooks/useSetRe
export const RightDrawerCalendarEvent = () => { export const RightDrawerCalendarEvent = () => {
const { setRecords } = useSetRecordInStore(); const { setRecords } = useSetRecordInStore();
const calendarEventId = useRecoilValue(viewableCalendarEventIdState()); const viewableCalendarEventId = useRecoilValue(viewableCalendarEventIdState);
const { record: calendarEvent } = useFindOneRecord<CalendarEvent>({ const { record: calendarEvent } = useFindOneRecord<CalendarEvent>({
objectNameSingular: CoreObjectNameSingular.CalendarEvent, objectNameSingular: CoreObjectNameSingular.CalendarEvent,
objectRecordId: calendarEventId ?? '', objectRecordId: viewableCalendarEventId ?? '',
onCompleted: (record) => setRecords([record]), onCompleted: (record) => setRecords([record]),
}); });

View File

@ -9,9 +9,9 @@ describe('useOpenCalendarEventRightDrawer', () => {
it('opens the right drawer with the calendar event', () => { it('opens the right drawer with the calendar event', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState()); const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState);
const viewableCalendarEventId = useRecoilValue( const viewableCalendarEventId = useRecoilValue(
viewableCalendarEventIdState(), viewableCalendarEventIdState,
); );
return { return {
...useOpenCalendarEventRightDrawer(), ...useOpenCalendarEventRightDrawer(),

View File

@ -10,7 +10,7 @@ export const useOpenCalendarEventRightDrawer = () => {
const { openRightDrawer } = useRightDrawer(); const { openRightDrawer } = useRightDrawer();
const setHotkeyScope = useSetHotkeyScope(); const setHotkeyScope = useSetHotkeyScope();
const setViewableCalendarEventId = useSetRecoilState( const setViewableCalendarEventId = useSetRecoilState(
viewableCalendarEventIdState(), viewableCalendarEventIdState,
); );
const openCalendarEventRightDrawer = (calendarEventId: string) => { const openCalendarEventRightDrawer = (calendarEventId: string) => {

View File

@ -11,7 +11,7 @@ import { Comment } from '../Comment';
import { mockComment, mockCommentWithLongValues } from './mock-comment'; import { mockComment, mockCommentWithLongValues } from './mock-comment';
const CommentSetterEffect = () => { const CommentSetterEffect = () => {
const setViewableActivity = useSetRecoilState(viewableActivityIdState()); const setViewableActivity = useSetRecoilState(viewableActivityIdState);
useEffect(() => { useEffect(() => {
setViewableActivity('test-id'); setViewableActivity('test-id');

View File

@ -13,7 +13,7 @@ import { CommentHeader } from '../CommentHeader';
import { mockComment, mockCommentWithLongValues } from './mock-comment'; import { mockComment, mockCommentWithLongValues } from './mock-comment';
const CommentHeaderSetterEffect = () => { const CommentHeaderSetterEffect = () => {
const setViewableActivity = useSetRecoilState(viewableActivityIdState()); const setViewableActivity = useSetRecoilState(viewableActivityIdState);
useEffect(() => { useEffect(() => {
setViewableActivity('test-id'); setViewableActivity('test-id');

View File

@ -116,7 +116,7 @@ export const ActivityBodyEditor = ({
); );
const [canCreateActivity, setCanCreateActivity] = useRecoilState( const [canCreateActivity, setCanCreateActivity] = useRecoilState(
canCreateActivityState(), canCreateActivityState,
); );
const [uploadFile] = useUploadFileMutation(); const [uploadFile] = useUploadFileMutation();
@ -339,7 +339,7 @@ export const ActivityBodyEditor = ({
if ( if (
isDefined(currentBlockContent) && isDefined(currentBlockContent) &&
isArray(currentBlockContent) && isArray(currentBlockContent) &&
currentBlockContent[0] && isDefined(currentBlockContent[0]) &&
currentBlockContent[0].type === 'text' currentBlockContent[0].type === 'text'
) { ) {
// Text block case // Text block case

View File

@ -61,7 +61,7 @@ export const ActivityComments = ({
objectNameSingular: CoreObjectNameSingular.Comment, objectNameSingular: CoreObjectNameSingular.Comment,
}); });
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { records: comments } = useFindManyRecords({ const { records: comments } = useFindManyRecords({
objectNameSingular: CoreObjectNameSingular.Comment, objectNameSingular: CoreObjectNameSingular.Comment,

View File

@ -29,15 +29,15 @@ export const ActivityEditorEffect = ({
({ snapshot, set }) => ({ snapshot, set }) =>
() => { () => {
const isUpsertingActivityInDB = snapshot const isUpsertingActivityInDB = snapshot
.getLoadable(isUpsertingActivityInDBState()) .getLoadable(isUpsertingActivityInDBState)
.getValue(); .getValue();
const canCreateActivity = snapshot const canCreateActivity = snapshot
.getLoadable(canCreateActivityState()) .getLoadable(canCreateActivityState)
.getValue(); .getValue();
const isActivityInCreateMode = snapshot const isActivityInCreateMode = snapshot
.getLoadable(isActivityInCreateModeState()) .getLoadable(isActivityInCreateModeState)
.getValue(); .getValue();
const activityFromStore = snapshot const activityFromStore = snapshot
@ -71,7 +71,7 @@ export const ActivityEditorEffect = ({
deleteActivityFromCache(activity); deleteActivityFromCache(activity);
} }
set(isActivityInCreateModeState(), false); set(isActivityInCreateModeState, false);
} else if (isDefined(activity)) { } else if (isDefined(activity)) {
if ( if (
activity.title !== activityTitle || activity.title !== activityTitle ||

View File

@ -71,7 +71,7 @@ export const ActivityTitle = ({ activityId }: ActivityTitleProps) => {
const activity = activityInStore as Activity; const activity = activityInStore as Activity;
const [canCreateActivity, setCanCreateActivity] = useRecoilState( const [canCreateActivity, setCanCreateActivity] = useRecoilState(
canCreateActivityState(), canCreateActivityState,
); );
const { upsertActivity } = useUpsertActivity(); const { upsertActivity } = useUpsertActivity();

View File

@ -122,7 +122,7 @@ export const EmailThreadPreview = ({
isSameEventThanRightDrawerClose(event.nativeEvent); isSameEventThanRightDrawerClose(event.nativeEvent);
const emailThreadIdWhenEmailThreadWasClosed = snapshot const emailThreadIdWhenEmailThreadWasClosed = snapshot
.getLoadable(emailThreadIdWhenEmailThreadWasClosedState()) .getLoadable(emailThreadIdWhenEmailThreadWasClosedState)
.getValue(); .getValue();
const canOpen = const canOpen =

View File

@ -58,12 +58,12 @@ export const EmailThreads = ({
}) => { }) => {
const { enqueueSnackBar } = useSnackBar(); const { enqueueSnackBar } = useSnackBar();
const { getEmailThreadsPageState } = useEmailThreadStates({ const { emailThreadsPageState } = useEmailThreadStates({
emailThreadScopeId: getScopeIdFromComponentId(entity.id), emailThreadScopeId: getScopeIdFromComponentId(entity.id),
}); });
const [emailThreadsPage, setEmailThreadsPage] = useRecoilState( const [emailThreadsPage, setEmailThreadsPage] = useRecoilState(
getEmailThreadsPageState(), emailThreadsPageState,
); );
const [isFetchingMoreEmails, setIsFetchingMoreEmails] = useState(false); const [isFetchingMoreEmails, setIsFetchingMoreEmails] = useState(false);

View File

@ -12,9 +12,9 @@ describe('useEmailThread', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const emailThread = useEmailThread(); const emailThread = useEmailThread();
const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState()); const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState);
const viewableEmailThreadId = useRecoilValue( const viewableEmailThreadId = useRecoilValue(
viewableEmailThreadIdState(), viewableEmailThreadIdState,
); );
return { ...emailThread, isRightDrawerOpen, viewableEmailThreadId }; return { ...emailThread, isRightDrawerOpen, viewableEmailThreadId };
@ -38,10 +38,10 @@ describe('useEmailThread', () => {
() => { () => {
const emailThread = useEmailThread(); const emailThread = useEmailThread();
const [isRightDrawerOpen, setIsRightDrawerOpen] = useRecoilState( const [isRightDrawerOpen, setIsRightDrawerOpen] = useRecoilState(
isRightDrawerOpenState(), isRightDrawerOpenState,
); );
const [viewableEmailThreadId, setViewableEmailThreadId] = const [viewableEmailThreadId, setViewableEmailThreadId] =
useRecoilState(viewableEmailThreadIdState()); useRecoilState(viewableEmailThreadIdState);
return { return {
...emailThread, ...emailThread,

View File

@ -30,7 +30,7 @@ describe('useEmailThreadStates hook', () => {
); );
expect(result.current.scopeId).toBe(mockScopeId); expect(result.current.scopeId).toBe(mockScopeId);
expect(result.current.getEmailThreadsPageState).toBe( expect(result.current.emailThreadsPageState).toBe(
mockGetEmailThreadsPageState, mockGetEmailThreadsPageState,
); );
}); });

View File

@ -17,7 +17,7 @@ export const useEmailThreadStates = ({
return { return {
scopeId, scopeId,
getEmailThreadsPageState: extractComponentState( emailThreadsPageState: extractComponentState(
emailThreadsPageComponentState, emailThreadsPageComponentState,
scopeId, scopeId,
), ),

View File

@ -13,21 +13,21 @@ export const useEmailThread = () => {
({ snapshot, set }) => ({ snapshot, set }) =>
(threadId: string) => { (threadId: string) => {
const isRightDrawerOpen = snapshot const isRightDrawerOpen = snapshot
.getLoadable(isRightDrawerOpenState()) .getLoadable(isRightDrawerOpenState)
.getValue(); .getValue();
const viewableEmailThreadId = snapshot const viewableEmailThreadId = snapshot
.getLoadable(viewableEmailThreadIdState()) .getLoadable(viewableEmailThreadIdState)
.getValue(); .getValue();
if (isRightDrawerOpen && viewableEmailThreadId === threadId) { if (isRightDrawerOpen && viewableEmailThreadId === threadId) {
set(viewableEmailThreadIdState(), null); set(viewableEmailThreadIdState, null);
closeRightDrawer(); closeRightDrawer();
return; return;
} }
openEmailThredRightDrawer(); openEmailThredRightDrawer();
set(viewableEmailThreadIdState(), threadId); set(viewableEmailThreadIdState, threadId);
}, },
[closeRightDrawer, openEmailThredRightDrawer], [closeRightDrawer, openEmailThredRightDrawer],
); );

View File

@ -34,7 +34,7 @@ export const RightDrawerEmailThread = () => {
callbackFunction: useRecoilCallback( callbackFunction: useRecoilCallback(
({ set }) => ({ set }) =>
() => { () => {
set(emailThreadIdWhenEmailThreadWasClosedState(), thread.id); set(emailThreadIdWhenEmailThreadWasClosedState, thread.id);
}, },
[thread], [thread],
), ),

View File

@ -9,7 +9,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
export const useRightDrawerEmailThread = () => { export const useRightDrawerEmailThread = () => {
const viewableEmailThreadId = useRecoilValue(viewableEmailThreadIdState()); const viewableEmailThreadId = useRecoilValue(viewableEmailThreadIdState);
const apolloClient = useApolloClient(); const apolloClient = useApolloClient();
const thread = apolloClient.readFragment({ const thread = apolloClient.readFragment({

View File

@ -10,7 +10,7 @@ import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { FileFolder, useUploadFileMutation } from '~/generated/graphql'; import { FileFolder, useUploadFileMutation } from '~/generated/graphql';
export const useUploadAttachmentFile = () => { export const useUploadAttachmentFile = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const [uploadFile] = useUploadFileMutation(); const [uploadFile] = useUploadFileMutation();
const { createOneRecord: createOneAttachment } = const { createOneRecord: createOneAttachment } =

View File

@ -201,7 +201,7 @@ describe('useActivities', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
const activities = useActivities({ const activities = useActivities({

View File

@ -58,7 +58,7 @@ describe('useActivityConnectionUtils', () => {
<RecoilRoot <RecoilRoot
initializeState={(snapshot) => { initializeState={(snapshot) => {
snapshot.set( snapshot.set(
objectMetadataItemsState(), objectMetadataItemsState,
getObjectMetadataItemsMock(), getObjectMetadataItemsMock(),
); );
}} }}
@ -86,7 +86,7 @@ describe('useActivityConnectionUtils', () => {
<RecoilRoot <RecoilRoot
initializeState={(snapshot) => { initializeState={(snapshot) => {
snapshot.set( snapshot.set(
objectMetadataItemsState(), objectMetadataItemsState,
getObjectMetadataItemsMock(), getObjectMetadataItemsMock(),
); );
}} }}

View File

@ -186,10 +186,10 @@ describe('useActivityTargetObjectRecords', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
const setObjectMetadataItems = useSetRecoilState( const setObjectMetadataItems = useSetRecoilState(
objectMetadataItemsState(), objectMetadataItemsState,
); );
const { activityTargetObjectRecords, loadingActivityTargets } = const { activityTargetObjectRecords, loadingActivityTargets } =

View File

@ -102,7 +102,7 @@ describe('useActivityTargetsForTargetableObject', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
const res = useActivityTargetsForTargetableObject({ const res = useActivityTargetsForTargetableObject({

View File

@ -29,10 +29,10 @@ describe('useAttachRelationInBothDirections', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
const setObjectMetadataItems = useSetRecoilState( const setObjectMetadataItems = useSetRecoilState(
objectMetadataItemsState(), objectMetadataItemsState,
); );
const res = useAttachRelationInBothDirections(); const res = useAttachRelationInBothDirections();

View File

@ -59,10 +59,10 @@ describe('useCreateActivityInCache', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
const setObjectMetadataItems = useSetRecoilState( const setObjectMetadataItems = useSetRecoilState(
objectMetadataItemsState(), objectMetadataItemsState,
); );
const res = useCreateActivityInCache(); const res = useCreateActivityInCache();

View File

@ -18,8 +18,8 @@ describe('useOpenActivityRightDrawer', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const openActivityRightDrawer = useOpenActivityRightDrawer(); const openActivityRightDrawer = useOpenActivityRightDrawer();
const viewableActivityId = useRecoilValue(viewableActivityIdState()); const viewableActivityId = useRecoilValue(viewableActivityIdState);
const activityIdInDrawer = useRecoilValue(activityIdInDrawerState()); const activityIdInDrawer = useRecoilValue(activityIdInDrawerState);
return { return {
openActivityRightDrawer, openActivityRightDrawer,
activityIdInDrawer, activityIdInDrawer,

View File

@ -28,10 +28,10 @@ describe('useOpenCreateActivityDrawer', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const openActivityRightDrawer = useOpenCreateActivityDrawer(); const openActivityRightDrawer = useOpenCreateActivityDrawer();
const viewableActivityId = useRecoilValue(viewableActivityIdState()); const viewableActivityId = useRecoilValue(viewableActivityIdState);
const activityIdInDrawer = useRecoilValue(activityIdInDrawerState()); const activityIdInDrawer = useRecoilValue(activityIdInDrawerState);
const setObjectMetadataItems = useSetRecoilState( const setObjectMetadataItems = useSetRecoilState(
objectMetadataItemsState(), objectMetadataItemsState,
); );
return { return {
openActivityRightDrawer, openActivityRightDrawer,

View File

@ -41,10 +41,10 @@ describe('useOpenCreateActivityDrawerForSelectedRowIds', () => {
() => { () => {
const openCreateActivityDrawerForSelectedRowIds = const openCreateActivityDrawerForSelectedRowIds =
useOpenCreateActivityDrawerForSelectedRowIds(recordTableId); useOpenCreateActivityDrawerForSelectedRowIds(recordTableId);
const viewableActivityId = useRecoilValue(viewableActivityIdState()); const viewableActivityId = useRecoilValue(viewableActivityIdState);
const activityIdInDrawer = useRecoilValue(activityIdInDrawerState()); const activityIdInDrawer = useRecoilValue(activityIdInDrawerState);
const setObjectMetadataItems = useSetRecoilState( const setObjectMetadataItems = useSetRecoilState(
objectMetadataItemsState(), objectMetadataItemsState,
); );
const scopeId = `${recordTableId}-scope`; const scopeId = `${recordTableId}-scope`;
const setTableRowIds = useSetRecoilState( const setTableRowIds = useSetRecoilState(

View File

@ -105,7 +105,7 @@ describe('useUpsertActivity', () => {
() => { () => {
const res = useUpsertActivity(); const res = useUpsertActivity();
const setIsActivityInCreateMode = useSetRecoilState( const setIsActivityInCreateMode = useSetRecoilState(
isActivityInCreateModeState(), isActivityInCreateModeState,
); );
return { ...res, setIsActivityInCreateMode }; return { ...res, setIsActivityInCreateMode };
@ -134,7 +134,7 @@ describe('useUpsertActivity', () => {
() => { () => {
const res = useUpsertActivity(); const res = useUpsertActivity();
const setIsActivityInCreateMode = useSetRecoilState( const setIsActivityInCreateMode = useSetRecoilState(
isActivityInCreateModeState(), isActivityInCreateModeState,
); );
const setObjectShowPageTargetableObject = useSetRecoilState( const setObjectShowPageTargetableObject = useSetRecoilState(
objectShowPageTargetableObjectState, objectShowPageTargetableObjectState,

View File

@ -14,7 +14,7 @@ export const useActivityTargetObjectRecords = ({
}: { }: {
activityId: string; activityId: string;
}) => { }) => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const { records: activityTargets, loading: loadingActivityTargets } = const { records: activityTargets, loading: loadingActivityTargets } =
useFindManyRecords<ActivityTarget>({ useFindManyRecords<ActivityTarget>({

View File

@ -27,7 +27,7 @@ export const useCreateActivityInCache = () => {
objectNameSingular: CoreObjectNameSingular.Activity, objectNameSingular: CoreObjectNameSingular.Activity,
}); });
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { record: currentWorkspaceMemberRecord } = useFindOneRecord({ const { record: currentWorkspaceMemberRecord } = useFindOneRecord({
objectNameSingular: CoreObjectNameSingular.WorkspaceMember, objectNameSingular: CoreObjectNameSingular.WorkspaceMember,

View File

@ -12,9 +12,9 @@ export const useOpenActivityRightDrawer = () => {
const { openRightDrawer, isRightDrawerOpen, rightDrawerPage } = const { openRightDrawer, isRightDrawerOpen, rightDrawerPage } =
useRightDrawer(); useRightDrawer();
const [viewableActivityId, setViewableActivityId] = useRecoilState( const [viewableActivityId, setViewableActivityId] = useRecoilState(
viewableActivityIdState(), viewableActivityIdState,
); );
const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState()); const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState);
const setHotkeyScope = useSetHotkeyScope(); const setHotkeyScope = useSetHotkeyScope();
return (activityId: string) => { return (activityId: string) => {

View File

@ -24,22 +24,20 @@ export const useOpenCreateActivityDrawer = () => {
const { createActivityInCache } = useCreateActivityInCache(); const { createActivityInCache } = useCreateActivityInCache();
const setActivityTargetableEntityArray = useSetRecoilState( const setActivityTargetableEntityArray = useSetRecoilState(
activityTargetableEntityArrayState(), activityTargetableEntityArrayState,
); );
const setViewableActivityId = useSetRecoilState(viewableActivityIdState()); const setViewableActivityId = useSetRecoilState(viewableActivityIdState);
const setIsCreatingActivity = useSetRecoilState( const setIsCreatingActivity = useSetRecoilState(isActivityInCreateModeState);
isActivityInCreateModeState(),
);
const setTemporaryActivityForEditor = useSetRecoilState( const setTemporaryActivityForEditor = useSetRecoilState(
temporaryActivityForEditorState(), temporaryActivityForEditorState,
); );
const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState()); const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState);
const [, setIsUpsertingActivityInDB] = useRecoilState( const [, setIsUpsertingActivityInDB] = useRecoilState(
isUpsertingActivityInDBState(), isUpsertingActivityInDBState,
); );
const openCreateActivityDrawer = async ({ const openCreateActivityDrawer = async ({

View File

@ -14,7 +14,7 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = (
) => { ) => {
const openCreateActivityDrawer = useOpenCreateActivityDrawer(); const openCreateActivityDrawer = useOpenCreateActivityDrawer();
const { getSelectedRowIdsSelector } = useRecordTableStates(recordTableId); const { selectedRowIdsSelector } = useRecordTableStates(recordTableId);
return useRecoilCallback( return useRecoilCallback(
({ snapshot }) => ({ snapshot }) =>
@ -25,7 +25,7 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = (
) => { ) => {
const selectedRowIds = getSnapshotValue( const selectedRowIds = getSnapshotValue(
snapshot, snapshot,
getSelectedRowIdsSelector(), selectedRowIdsSelector(),
); );
let activityTargetableObjectArray: ActivityTargetableObject[] = let activityTargetableObjectArray: ActivityTargetableObject[] =
@ -59,6 +59,6 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = (
targetableObjects: activityTargetableObjectArray, targetableObjects: activityTargetableObjectArray,
}); });
}, },
[openCreateActivityDrawer, getSelectedRowIdsSelector], [selectedRowIdsSelector, openCreateActivityDrawer],
); );
}; };

View File

@ -21,7 +21,7 @@ import { isDefined } from '~/utils/isDefined';
// TODO: create a generic way to have records only in cache for create mode and delete them afterwards ? // TODO: create a generic way to have records only in cache for create mode and delete them afterwards ?
export const useUpsertActivity = () => { export const useUpsertActivity = () => {
const [isActivityInCreateMode, setIsActivityInCreateMode] = useRecoilState( const [isActivityInCreateMode, setIsActivityInCreateMode] = useRecoilState(
isActivityInCreateModeState(), isActivityInCreateModeState,
); );
const { updateOneRecord: updateOneActivity } = useUpdateOneRecord<Activity>({ const { updateOneRecord: updateOneActivity } = useUpdateOneRecord<Activity>({
@ -31,10 +31,10 @@ export const useUpsertActivity = () => {
const { createActivityInDB } = useCreateActivityInDB(); const { createActivityInDB } = useCreateActivityInDB();
const [, setIsUpsertingActivityInDB] = useRecoilState( const [, setIsUpsertingActivityInDB] = useRecoilState(
isUpsertingActivityInDBState(), isUpsertingActivityInDBState,
); );
const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState()); const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState);
const objectShowPageTargetableObject = useRecoilValue( const objectShowPageTargetableObject = useRecoilValue(
objectShowPageTargetableObjectState, objectShowPageTargetableObjectState,

View File

@ -34,9 +34,7 @@ export const ActivityTargetInlineCellEditMode = ({
activity, activity,
activityTargetWithTargetRecords, activityTargetWithTargetRecords,
}: ActivityTargetInlineCellEditModeProps) => { }: ActivityTargetInlineCellEditModeProps) => {
const [isActivityInCreateMode] = useRecoilState( const [isActivityInCreateMode] = useRecoilState(isActivityInCreateModeState);
isActivityInCreateModeState(),
);
const selectedTargetObjectIds = activityTargetWithTargetRecords.map( const selectedTargetObjectIds = activityTargetWithTargetRecords.map(
(activityTarget) => ({ (activityTarget) => ({

View File

@ -36,13 +36,13 @@ const StyledButtonContainer = styled.div`
`; `;
export const ActivityActionBar = () => { export const ActivityActionBar = () => {
const viewableActivityId = useRecoilValue(viewableActivityIdState()); const viewableActivityId = useRecoilValue(viewableActivityIdState);
const activityIdInDrawer = useRecoilValue(activityIdInDrawerState()); const activityIdInDrawer = useRecoilValue(activityIdInDrawerState);
const activityTargetableEntityArray = useRecoilValue( const activityTargetableEntityArray = useRecoilValue(
activityTargetableEntityArrayState(), activityTargetableEntityArrayState,
); );
const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState()); const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState);
const { deleteOneRecord: deleteOneActivity } = useDeleteOneRecord({ const { deleteOneRecord: deleteOneActivity } = useDeleteOneRecord({
objectNameSingular: CoreObjectNameSingular.Activity, objectNameSingular: CoreObjectNameSingular.Activity,
}); });
@ -54,15 +54,13 @@ export const ActivityActionBar = () => {
); );
const [temporaryActivityForEditor, setTemporaryActivityForEditor] = const [temporaryActivityForEditor, setTemporaryActivityForEditor] =
useRecoilState(temporaryActivityForEditorState()); useRecoilState(temporaryActivityForEditorState);
const { deleteActivityFromCache } = useDeleteActivityFromCache(); const { deleteActivityFromCache } = useDeleteActivityFromCache();
const [isActivityInCreateMode] = useRecoilState( const [isActivityInCreateMode] = useRecoilState(isActivityInCreateModeState);
isActivityInCreateModeState(),
);
const [isUpsertingActivityInDB] = useRecoilState( const [isUpsertingActivityInDB] = useRecoilState(
isUpsertingActivityInDBState(), isUpsertingActivityInDBState,
); );
const objectShowPageTargetableObject = useRecoilValue( const objectShowPageTargetableObject = useRecoilValue(

View File

@ -5,7 +5,7 @@ import { viewableActivityIdState } from '@/activities/states/viewableActivityIdS
import { RightDrawerActivity } from '../RightDrawerActivity'; import { RightDrawerActivity } from '../RightDrawerActivity';
export const RightDrawerCreateActivity = () => { export const RightDrawerCreateActivity = () => {
const viewableActivityId = useRecoilValue(viewableActivityIdState()); const viewableActivityId = useRecoilValue(viewableActivityIdState);
return ( return (
<> <>

View File

@ -5,7 +5,7 @@ import { viewableActivityIdState } from '@/activities/states/viewableActivityIdS
import { RightDrawerActivity } from '../RightDrawerActivity'; import { RightDrawerActivity } from '../RightDrawerActivity';
export const RightDrawerEditActivity = () => { export const RightDrawerEditActivity = () => {
const viewableActivityId = useRecoilValue(viewableActivityIdState()); const viewableActivityId = useRecoilValue(viewableActivityIdState);
return ( return (
<> <>

View File

@ -9,10 +9,10 @@ import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { parseDate } from '~/utils/date-utils'; import { parseDate } from '~/utils/date-utils';
export const CurrentUserDueTaskCountEffect = () => { export const CurrentUserDueTaskCountEffect = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const [currentUserDueTaskCount, setCurrentUserDueTaskCount] = useRecoilState( const [currentUserDueTaskCount, setCurrentUserDueTaskCount] = useRecoilState(
currentUserDueTaskCountState(), currentUserDueTaskCountState,
); );
const { records: tasks } = useFindManyRecords({ const { records: tasks } = useFindManyRecords({

View File

@ -48,8 +48,8 @@ export const TaskGroups = ({
const openCreateActivity = useOpenCreateActivityDrawer(); const openCreateActivity = useOpenCreateActivityDrawer();
const { getActiveTabIdState } = useTabList(TASKS_TAB_LIST_COMPONENT_ID); const { activeTabIdState } = useTabList(TASKS_TAB_LIST_COMPONENT_ID);
const activeTabId = useRecoilValue(getActiveTabIdState()); const activeTabId = useRecoilValue(activeTabIdState);
if (!initialized) { if (!initialized) {
return <></>; return <></>;

View File

@ -7,7 +7,7 @@ import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { parseDate } from '~/utils/date-utils'; import { parseDate } from '~/utils/date-utils';
export const useCurrentUserTaskCount = () => { export const useCurrentUserTaskCount = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { records: tasks } = useFindManyRecords({ const { records: tasks } = useFindManyRecords({
objectNameSingular: CoreObjectNameSingular.Activity, objectNameSingular: CoreObjectNameSingular.Activity,

View File

@ -1,7 +1,7 @@
import { useEffect, useMemo } from 'react'; import { useEffect, useMemo } from 'react';
import { isNonEmptyArray } from '@sniptt/guards'; import { isNonEmptyArray } from '@sniptt/guards';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { useRecoilState } from 'recoil'; import { useRecoilState, useRecoilValue } from 'recoil';
import { useActivities } from '@/activities/hooks/useActivities'; import { useActivities } from '@/activities/hooks/useActivities';
import { currentCompletedTaskQueryVariablesState } from '@/activities/tasks/states/currentCompletedTaskQueryVariablesState'; import { currentCompletedTaskQueryVariablesState } from '@/activities/tasks/states/currentCompletedTaskQueryVariablesState';
@ -23,10 +23,12 @@ export const useTasks = ({
targetableObjects, targetableObjects,
filterDropdownId, filterDropdownId,
}: UseTasksProps) => { }: UseTasksProps) => {
const { selectedFilter } = useFilterDropdown({ const { selectedFilterState } = useFilterDropdown({
filterDropdownId, filterDropdownId,
}); });
const selectedFilter = useRecoilValue(selectedFilterState);
const assigneeIdFilter = useMemo( const assigneeIdFilter = useMemo(
() => () =>
selectedFilter selectedFilter

View File

@ -33,7 +33,7 @@ export const Timeline = ({
targetableObject: ActivityTargetableObject; targetableObject: ActivityTargetableObject;
}) => { }) => {
const { initialized, noActivities } = useRecoilValue( const { initialized, noActivities } = useRecoilValue(
timelineActivitiesNetworkingState(), timelineActivitiesNetworkingState,
); );
const showEmptyState = noActivities; const showEmptyState = noActivities;

View File

@ -16,8 +16,8 @@ export const TimelineCreateButtonGroup = ({
}: { }: {
targetableObject: ActivityTargetableObject; targetableObject: ActivityTargetableObject;
}) => { }) => {
const { getActiveTabIdState } = useTabList(TAB_LIST_COMPONENT_ID); const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID);
const setActiveTabId = useSetRecoilState(getActiveTabIdState()); const setActiveTabId = useSetRecoilState(activeTabIdState);
const openCreateActivity = useOpenCreateActivityDrawer(); const openCreateActivity = useOpenCreateActivityDrawer();

View File

@ -26,7 +26,7 @@ const StyledScrollWrapper = styled(ScrollWrapper)``;
export const TimelineItemsContainer = () => { export const TimelineItemsContainer = () => {
const timelineActivitiesForGroup = useRecoilValue( const timelineActivitiesForGroup = useRecoilValue(
timelineActivitiesForGroupState(), timelineActivitiesForGroupState,
); );
const groupedActivities = groupActivitiesByMonth(timelineActivitiesForGroup); const groupedActivities = groupActivitiesByMonth(timelineActivitiesForGroup);

View File

@ -35,10 +35,10 @@ export const TimelineQueryEffect = ({
}); });
const [timelineActivitiesNetworking, setTimelineActivitiesNetworking] = const [timelineActivitiesNetworking, setTimelineActivitiesNetworking] =
useRecoilState(timelineActivitiesNetworkingState()); useRecoilState(timelineActivitiesNetworkingState);
const [timelineActivitiesForGroup, setTimelineActivitiesForGroup] = const [timelineActivitiesForGroup, setTimelineActivitiesForGroup] =
useRecoilState(timelineActivitiesForGroupState()); useRecoilState(timelineActivitiesForGroupState);
useEffect(() => { useEffect(() => {
if (!isDefined(targetableObject)) { if (!isDefined(targetableObject)) {

View File

@ -13,7 +13,7 @@ export interface EventData {
} }
export const useEventTracker = () => { export const useEventTracker = () => {
const telemetry = useRecoilValue(telemetryState()); const telemetry = useRecoilValue(telemetryState);
const [createEventMutation] = useTrackMutation(); const [createEventMutation] = useTrackMutation();
return useCallback( return useCallback(

View File

@ -16,11 +16,11 @@ import { ApolloFactory } from '../services/apollo.factory';
export const useApolloFactory = () => { export const useApolloFactory = () => {
// eslint-disable-next-line @nx/workspace-no-state-useref // eslint-disable-next-line @nx/workspace-no-state-useref
const apolloRef = useRef<ApolloFactory<NormalizedCacheObject> | null>(null); const apolloRef = useRef<ApolloFactory<NormalizedCacheObject> | null>(null);
const [isDebugMode] = useRecoilState(isDebugModeState()); const [isDebugMode] = useRecoilState(isDebugModeState);
const navigate = useNavigate(); const navigate = useNavigate();
const isMatchingLocation = useIsMatchingLocation(); const isMatchingLocation = useIsMatchingLocation();
const [tokenPair, setTokenPair] = useRecoilState(tokenPairState()); const [tokenPair, setTokenPair] = useRecoilState(tokenPairState);
const apolloClient = useMemo(() => { const apolloClient = useMemo(() => {
apolloRef.current = new ApolloFactory({ apolloRef.current = new ApolloFactory({

View File

@ -26,127 +26,129 @@ export const triggerUpdateRelationsOptimisticEffect = ({
currentSourceRecord: CachedObjectRecord | null; currentSourceRecord: CachedObjectRecord | null;
updatedSourceRecord: CachedObjectRecord | null; updatedSourceRecord: CachedObjectRecord | null;
objectMetadataItems: ObjectMetadataItem[]; objectMetadataItems: ObjectMetadataItem[];
}) => }) => {
sourceObjectMetadataItem.fields.forEach((fieldMetadataItemOnSourceRecord) => { return sourceObjectMetadataItem.fields.forEach(
const notARelationField = (fieldMetadataItemOnSourceRecord) => {
fieldMetadataItemOnSourceRecord.type !== FieldMetadataType.Relation; const notARelationField =
fieldMetadataItemOnSourceRecord.type !== FieldMetadataType.Relation;
if (notARelationField) { if (notARelationField) {
return; return;
} }
const fieldDoesNotExist = const fieldDoesNotExist =
isDefined(updatedSourceRecord) && isDefined(updatedSourceRecord) &&
!(fieldMetadataItemOnSourceRecord.name in updatedSourceRecord); !(fieldMetadataItemOnSourceRecord.name in updatedSourceRecord);
if (fieldDoesNotExist) { if (fieldDoesNotExist) {
return; return;
} }
const relationDefinition = getRelationDefinition({ const relationDefinition = getRelationDefinition({
fieldMetadataItemOnSourceRecord, fieldMetadataItemOnSourceRecord,
objectMetadataItems, objectMetadataItems,
}); });
if (!relationDefinition) {
return;
}
if (!relationDefinition) { const { targetObjectMetadataItem, fieldMetadataItemOnTargetRecord } =
return; relationDefinition;
}
const { targetObjectMetadataItem, fieldMetadataItemOnTargetRecord } = const currentFieldValueOnSourceRecord:
relationDefinition; | ObjectRecordConnection
| CachedObjectRecord
| null = currentSourceRecord?.[fieldMetadataItemOnSourceRecord.name];
const currentFieldValueOnSourceRecord: const updatedFieldValueOnSourceRecord:
| ObjectRecordConnection | ObjectRecordConnection
| CachedObjectRecord | CachedObjectRecord
| null = currentSourceRecord?.[fieldMetadataItemOnSourceRecord.name]; | null = updatedSourceRecord?.[fieldMetadataItemOnSourceRecord.name];
const updatedFieldValueOnSourceRecord: if (
| ObjectRecordConnection isDeeplyEqual(
| CachedObjectRecord currentFieldValueOnSourceRecord,
| null = updatedSourceRecord?.[fieldMetadataItemOnSourceRecord.name]; updatedFieldValueOnSourceRecord,
)
) {
return;
}
if ( // TODO: replace this by a relation type check, if it's one to many,
isDeeplyEqual( // it's an object record connection (we can still check it though as a safeguard)
currentFieldValueOnSourceRecord, const currentFieldValueOnSourceRecordIsARecordConnection =
updatedFieldValueOnSourceRecord, isObjectRecordConnection(
) targetObjectMetadataItem.nameSingular,
) { currentFieldValueOnSourceRecord,
return;
}
// TODO: replace this by a relation type check, if it's one to many,
// it's an object record connection (we can still check it though as a safeguard)
const currentFieldValueOnSourceRecordIsARecordConnection =
isObjectRecordConnection(
targetObjectMetadataItem.nameSingular,
currentFieldValueOnSourceRecord,
);
const targetRecordsToDetachFrom =
currentFieldValueOnSourceRecordIsARecordConnection
? currentFieldValueOnSourceRecord.edges.map(
({ node }) => node as CachedObjectRecord,
)
: [currentFieldValueOnSourceRecord].filter(isDefined);
const updatedFieldValueOnSourceRecordIsARecordConnection =
isObjectRecordConnection(
targetObjectMetadataItem.nameSingular,
updatedFieldValueOnSourceRecord,
);
const targetRecordsToAttachTo =
updatedFieldValueOnSourceRecordIsARecordConnection
? updatedFieldValueOnSourceRecord.edges.map(
({ node }) => node as CachedObjectRecord,
)
: [updatedFieldValueOnSourceRecord].filter(isDefined);
const shouldDetachSourceFromAllTargets =
isDefined(currentSourceRecord) && targetRecordsToDetachFrom.length > 0;
if (shouldDetachSourceFromAllTargets) {
// TODO: see if we can de-hardcode this, put cascade delete in relation metadata item
// Instead of hardcoding it here
const shouldCascadeDeleteTargetRecords =
CORE_OBJECT_NAMES_TO_DELETE_ON_TRIGGER_RELATION_DETACH.includes(
targetObjectMetadataItem.nameSingular as CoreObjectNameSingular,
); );
if (shouldCascadeDeleteTargetRecords) { const targetRecordsToDetachFrom =
triggerDeleteRecordsOptimisticEffect({ currentFieldValueOnSourceRecordIsARecordConnection
cache, ? currentFieldValueOnSourceRecord.edges.map(
objectMetadataItem: targetObjectMetadataItem, ({ node }) => node as CachedObjectRecord,
recordsToDelete: targetRecordsToDetachFrom, )
objectMetadataItems, : [currentFieldValueOnSourceRecord].filter(isDefined);
});
} else { const updatedFieldValueOnSourceRecordIsARecordConnection =
targetRecordsToDetachFrom.forEach((targetRecordToDetachFrom) => { isObjectRecordConnection(
triggerDetachRelationOptimisticEffect({ targetObjectMetadataItem.nameSingular,
updatedFieldValueOnSourceRecord,
);
const targetRecordsToAttachTo =
updatedFieldValueOnSourceRecordIsARecordConnection
? updatedFieldValueOnSourceRecord.edges.map(
({ node }) => node as CachedObjectRecord,
)
: [updatedFieldValueOnSourceRecord].filter(isDefined);
const shouldDetachSourceFromAllTargets =
isDefined(currentSourceRecord) && targetRecordsToDetachFrom.length > 0;
if (shouldDetachSourceFromAllTargets) {
// TODO: see if we can de-hardcode this, put cascade delete in relation metadata item
// Instead of hardcoding it here
const shouldCascadeDeleteTargetRecords =
CORE_OBJECT_NAMES_TO_DELETE_ON_TRIGGER_RELATION_DETACH.includes(
targetObjectMetadataItem.nameSingular as CoreObjectNameSingular,
);
if (shouldCascadeDeleteTargetRecords) {
triggerDeleteRecordsOptimisticEffect({
cache,
objectMetadataItem: targetObjectMetadataItem,
recordsToDelete: targetRecordsToDetachFrom,
objectMetadataItems,
});
} else {
targetRecordsToDetachFrom.forEach((targetRecordToDetachFrom) => {
triggerDetachRelationOptimisticEffect({
cache,
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
sourceRecordId: currentSourceRecord.id,
fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name,
targetObjectNameSingular: targetObjectMetadataItem.nameSingular,
targetRecordId: targetRecordToDetachFrom.id,
});
});
}
}
const shouldAttachSourceToAllTargets =
isDefined(updatedSourceRecord) && targetRecordsToAttachTo.length > 0;
if (shouldAttachSourceToAllTargets) {
targetRecordsToAttachTo.forEach((targetRecordToAttachTo) =>
triggerAttachRelationOptimisticEffect({
cache, cache,
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular, sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
sourceRecordId: currentSourceRecord.id, sourceRecordId: updatedSourceRecord.id,
fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name, fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name,
targetObjectNameSingular: targetObjectMetadataItem.nameSingular, targetObjectNameSingular: targetObjectMetadataItem.nameSingular,
targetRecordId: targetRecordToDetachFrom.id, targetRecordId: targetRecordToAttachTo.id,
}); }),
}); );
} }
} },
);
const shouldAttachSourceToAllTargets = };
isDefined(updatedSourceRecord) && targetRecordsToAttachTo.length > 0;
if (shouldAttachSourceToAllTargets) {
targetRecordsToAttachTo.forEach((targetRecordToAttachTo) =>
triggerAttachRelationOptimisticEffect({
cache,
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
sourceRecordId: updatedSourceRecord.id,
fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name,
targetObjectNameSingular: targetObjectMetadataItem.nameSingular,
targetRecordId: targetRecordToAttachTo.id,
}),
);
}
});

View File

@ -76,13 +76,13 @@ describe('useAuth', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const client = useApolloClient(); const client = useApolloClient();
const icons = useRecoilValue(iconsState()); const icons = useRecoilValue(iconsState);
const authProviders = useRecoilValue(authProvidersState()); const authProviders = useRecoilValue(authProvidersState);
const billing = useRecoilValue(billingState()); const billing = useRecoilValue(billingState);
const isSignInPrefilled = useRecoilValue(isSignInPrefilledState()); const isSignInPrefilled = useRecoilValue(isSignInPrefilledState);
const supportChat = useRecoilValue(supportChatState()); const supportChat = useRecoilValue(supportChatState);
const telemetry = useRecoilValue(telemetryState()); const telemetry = useRecoilValue(telemetryState);
const isDebugMode = useRecoilValue(isDebugModeState()); const isDebugMode = useRecoilValue(isDebugModeState);
return { return {
...useAuth(), ...useAuth(),
client, client,

View File

@ -9,7 +9,7 @@ const renderHooks = () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const isLogged = useIsLogged(); const isLogged = useIsLogged();
const setTokenPair = useSetRecoilState(tokenPairState()); const setTokenPair = useSetRecoilState(tokenPairState);
return { return {
isLogged, isLogged,

View File

@ -38,13 +38,13 @@ const renderHooks = () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const onboardingStatus = useOnboardingStatus(); const onboardingStatus = useOnboardingStatus();
const setBilling = useSetRecoilState(billingState()); const setBilling = useSetRecoilState(billingState);
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState()); const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
const setTokenPair = useSetRecoilState(tokenPairState()); const setTokenPair = useSetRecoilState(tokenPairState);
const setVerifyPending = useSetRecoilState(isVerifyPendingState()); const setVerifyPending = useSetRecoilState(isVerifyPendingState);
return { return {
onboardingStatus, onboardingStatus,

View File

@ -32,14 +32,14 @@ import { currentUserState } from '../states/currentUserState';
import { tokenPairState } from '../states/tokenPairState'; import { tokenPairState } from '../states/tokenPairState';
export const useAuth = () => { export const useAuth = () => {
const [, setTokenPair] = useRecoilState(tokenPairState()); const [, setTokenPair] = useRecoilState(tokenPairState);
const setCurrentUser = useSetRecoilState(currentUserState()); const setCurrentUser = useSetRecoilState(currentUserState);
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState()); const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
const setIsVerifyPendingState = useSetRecoilState(isVerifyPendingState()); const setIsVerifyPendingState = useSetRecoilState(isVerifyPendingState);
const [challenge] = useChallengeMutation(); const [challenge] = useChallengeMutation();
const [signUp] = useSignUpMutation(); const [signUp] = useSignUpMutation();
@ -141,26 +141,26 @@ export const useAuth = () => {
({ snapshot }) => ({ snapshot }) =>
async () => { async () => {
const emptySnapshot = snapshot_UNSTABLE(); const emptySnapshot = snapshot_UNSTABLE();
const iconsValue = snapshot.getLoadable(iconsState()).getValue(); const iconsValue = snapshot.getLoadable(iconsState).getValue();
const authProvidersValue = snapshot const authProvidersValue = snapshot
.getLoadable(authProvidersState()) .getLoadable(authProvidersState)
.getValue(); .getValue();
const billing = snapshot.getLoadable(billingState()).getValue(); const billing = snapshot.getLoadable(billingState).getValue();
const isSignInPrefilled = snapshot const isSignInPrefilled = snapshot
.getLoadable(isSignInPrefilledState()) .getLoadable(isSignInPrefilledState)
.getValue(); .getValue();
const supportChat = snapshot.getLoadable(supportChatState()).getValue(); const supportChat = snapshot.getLoadable(supportChatState).getValue();
const telemetry = snapshot.getLoadable(telemetryState()).getValue(); const telemetry = snapshot.getLoadable(telemetryState).getValue();
const isDebugMode = snapshot.getLoadable(isDebugModeState()).getValue(); const isDebugMode = snapshot.getLoadable(isDebugModeState).getValue();
const initialSnapshot = emptySnapshot.map(({ set }) => { const initialSnapshot = emptySnapshot.map(({ set }) => {
set(iconsState(), iconsValue); set(iconsState, iconsValue);
set(authProvidersState(), authProvidersValue); set(authProvidersState, authProvidersValue);
set(billingState(), billing); set(billingState, billing);
set(isSignInPrefilledState(), isSignInPrefilled); set(isSignInPrefilledState, isSignInPrefilled);
set(supportChatState(), supportChat); set(supportChatState, supportChat);
set(telemetryState(), telemetry); set(telemetryState, telemetry);
set(isDebugModeState(), isDebugMode); set(isDebugModeState, isDebugMode);
return undefined; return undefined;
}); });

View File

@ -5,8 +5,8 @@ import { isVerifyPendingState } from '@/auth/states/isVerifyPendingState';
import { tokenPairState } from '../states/tokenPairState'; import { tokenPairState } from '../states/tokenPairState';
export const useIsLogged = (): boolean => { export const useIsLogged = (): boolean => {
const [tokenPair] = useRecoilState(tokenPairState()); const [tokenPair] = useRecoilState(tokenPairState);
const isVerifyPending = useRecoilValue(isVerifyPendingState()); const isVerifyPending = useRecoilValue(isVerifyPendingState);
return !!tokenPair && !isVerifyPending; return !!tokenPair && !isVerifyPending;
}; };

View File

@ -11,9 +11,9 @@ import {
} from '../utils/getOnboardingStatus'; } from '../utils/getOnboardingStatus';
export const useOnboardingStatus = (): OnboardingStatus | undefined => { export const useOnboardingStatus = (): OnboardingStatus | undefined => {
const billing = useRecoilValue(billingState()); const billing = useRecoilValue(billingState);
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspace = useRecoilValue(currentWorkspaceState()); const currentWorkspace = useRecoilValue(currentWorkspaceState);
const isLoggedIn = useIsLogged(); const isLoggedIn = useIsLogged();
return getOnboardingStatus({ return getOnboardingStatus({

View File

@ -46,7 +46,7 @@ const StyledInputContainer = styled.div`
`; `;
export const SignInUpForm = () => { export const SignInUpForm = () => {
const [authProviders] = useRecoilState(authProvidersState()); const [authProviders] = useRecoilState(authProvidersState);
const [showErrors, setShowErrors] = useState(false); const [showErrors, setShowErrors] = useState(false);
const { handleResetPassword } = useHandleResetPassword(); const { handleResetPassword } = useHandleResetPassword();
const workspace = useWorkspaceFromInviteHash(); const workspace = useWorkspaceFromInviteHash();

View File

@ -9,7 +9,7 @@ import { WorkspaceMember } from '~/generated/graphql.tsx';
export const useNavigateAfterSignInUp = () => { export const useNavigateAfterSignInUp = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const billing = useRecoilValue(billingState()); const billing = useRecoilValue(billingState);
const navigateAfterSignInUp = useCallback( const navigateAfterSignInUp = useCallback(
( (
currentWorkspace: CurrentWorkspace, currentWorkspace: CurrentWorkspace,

View File

@ -19,7 +19,7 @@ const validationSchema = z
export type Form = z.infer<typeof validationSchema>; export type Form = z.infer<typeof validationSchema>;
export const useSignInUpForm = () => { export const useSignInUpForm = () => {
const isSignInPrefilled = useRecoilValue(isSignInPrefilledState()); const isSignInPrefilled = useRecoilValue(isSignInPrefilledState);
const form = useForm<Form>({ const form = useForm<Form>({
mode: 'onChange', mode: 'onChange',
defaultValues: { defaultValues: {

View File

@ -15,17 +15,17 @@ import { isDefined } from '~/utils/isDefined';
export const ClientConfigProvider: React.FC<React.PropsWithChildren> = ({ export const ClientConfigProvider: React.FC<React.PropsWithChildren> = ({
children, children,
}) => { }) => {
const setAuthProviders = useSetRecoilState(authProvidersState()); const setAuthProviders = useSetRecoilState(authProvidersState);
const setIsDebugMode = useSetRecoilState(isDebugModeState()); const setIsDebugMode = useSetRecoilState(isDebugModeState);
const setIsSignInPrefilled = useSetRecoilState(isSignInPrefilledState()); const setIsSignInPrefilled = useSetRecoilState(isSignInPrefilledState);
const setIsSignUpDisabled = useSetRecoilState(isSignUpDisabledState()); const setIsSignUpDisabled = useSetRecoilState(isSignUpDisabledState);
const setBilling = useSetRecoilState(billingState()); const setBilling = useSetRecoilState(billingState);
const setTelemetry = useSetRecoilState(telemetryState()); const setTelemetry = useSetRecoilState(telemetryState);
const setSupportChat = useSetRecoilState(supportChatState()); const setSupportChat = useSetRecoilState(supportChatState);
const setSentryConfig = useSetRecoilState(sentryConfigState()); const setSentryConfig = useSetRecoilState(sentryConfigState);
const { data, loading } = useGetClientConfigQuery(); const { data, loading } = useGetClientConfigQuery();

View File

@ -109,9 +109,9 @@ export const CommandMenu = () => {
const openActivityRightDrawer = useOpenActivityRightDrawer(); const openActivityRightDrawer = useOpenActivityRightDrawer();
const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState); const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState);
const [commandMenuSearch, setCommandMenuSearch] = useRecoilState( const [commandMenuSearch, setCommandMenuSearch] = useRecoilState(
commandMenuSearchState(), commandMenuSearchState,
); );
const commandMenuCommands = useRecoilValue(commandMenuCommandsState()); const commandMenuCommands = useRecoilValue(commandMenuCommandsState);
const { closeKeyboardShortcutMenu } = useKeyboardShortcutMenu(); const { closeKeyboardShortcutMenu } = useKeyboardShortcutMenu();
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => { const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {

View File

@ -27,9 +27,9 @@ const meta: Meta<typeof CommandMenu> = {
component: CommandMenu, component: CommandMenu,
decorators: [ decorators: [
(Story) => { (Story) => {
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState()); const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
const { addToCommandMenu, setToInitialCommandMenu, openCommandMenu } = const { addToCommandMenu, setToInitialCommandMenu, openCommandMenu } =
useCommandMenu(); useCommandMenu();

View File

@ -25,7 +25,7 @@ const renderHooks = () => {
const commandMenu = useCommandMenu(); const commandMenu = useCommandMenu();
const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState); const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState);
const [commandMenuCommands, setCommandMenuCommands] = useRecoilState( const [commandMenuCommands, setCommandMenuCommands] = useRecoilState(
commandMenuCommandsState(), commandMenuCommandsState,
); );
return { return {

View File

@ -17,7 +17,7 @@ import { Command } from '../types/Command';
export const useCommandMenu = () => { export const useCommandMenu = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const setIsCommandMenuOpened = useSetRecoilState(isCommandMenuOpenedState); const setIsCommandMenuOpened = useSetRecoilState(isCommandMenuOpenedState);
const setCommands = useSetRecoilState(commandMenuCommandsState()); const setCommands = useSetRecoilState(commandMenuCommandsState);
const { resetSelectedItem } = useSelectableList('command-menu-list'); const { resetSelectedItem } = useSelectableList('command-menu-list');
const { const {
setHotkeyScopeAndMemorizePreviousScope, setHotkeyScopeAndMemorizePreviousScope,
@ -52,7 +52,7 @@ export const useCommandMenu = () => {
.getLoadable(isCommandMenuOpenedState) .getLoadable(isCommandMenuOpenedState)
.getValue(); .getValue();
set(commandMenuSearchState(), ''); set(commandMenuSearchState, '');
if (isCommandMenuOpened) { if (isCommandMenuOpened) {
closeCommandMenu(); closeCommandMenu();

View File

@ -5,7 +5,7 @@ import { useRecoilValue } from 'recoil';
import { isDebugModeState } from '@/client-config/states/isDebugModeState'; import { isDebugModeState } from '@/client-config/states/isDebugModeState';
export const ApolloDevLogEffect = () => { export const ApolloDevLogEffect = () => {
const isDebugMode = useRecoilValue(isDebugModeState()); const isDebugMode = useRecoilValue(isDebugModeState);
useEffect(() => { useEffect(() => {
if (isDebugMode) { if (isDebugMode) {

View File

@ -15,7 +15,7 @@ const formatTitle = (stateName: string) => {
}; };
export const RecoilDebugObserverEffect = () => { export const RecoilDebugObserverEffect = () => {
const isDebugMode = useRecoilValue(isDebugModeState()); const isDebugMode = useRecoilValue(isDebugModeState);
useRecoilTransactionObserver_UNSTABLE(({ snapshot }) => { useRecoilTransactionObserver_UNSTABLE(({ snapshot }) => {
if (!isDebugMode) { if (!isDebugMode) {

View File

@ -11,11 +11,11 @@ import { REACT_APP_SERVER_BASE_URL } from '~/config';
import { isDefined } from '~/utils/isDefined'; import { isDefined } from '~/utils/isDefined';
export const SentryInitEffect = () => { export const SentryInitEffect = () => {
const sentryConfig = useRecoilValue(sentryConfigState()); const sentryConfig = useRecoilValue(sentryConfigState);
const currentUser = useRecoilValue(currentUserState()); const currentUser = useRecoilValue(currentUserState);
const currentWorkspace = useRecoilValue(currentWorkspaceState()); const currentWorkspace = useRecoilValue(currentWorkspaceState);
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const [isSentryInitialized, setIsSentryInitialized] = useState(false); const [isSentryInitialized, setIsSentryInitialized] = useState(false);

View File

@ -46,11 +46,11 @@ describe('useFavorites', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
setCurrentWorkspaceMember(mockWorkspaceMember); setCurrentWorkspaceMember(mockWorkspaceMember);
const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); const setMetadataItems = useSetRecoilState(objectMetadataItemsState);
setMetadataItems(mockObjectMetadataItems); setMetadataItems(mockObjectMetadataItems);
return useFavorites(); return useFavorites();
@ -67,11 +67,11 @@ describe('useFavorites', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
setCurrentWorkspaceMember(mockWorkspaceMember); setCurrentWorkspaceMember(mockWorkspaceMember);
const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); const setMetadataItems = useSetRecoilState(objectMetadataItemsState);
setMetadataItems(mockObjectMetadataItems); setMetadataItems(mockObjectMetadataItems);
return useFavorites(); return useFavorites();
@ -95,11 +95,11 @@ describe('useFavorites', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
setCurrentWorkspaceMember(mockWorkspaceMember); setCurrentWorkspaceMember(mockWorkspaceMember);
const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); const setMetadataItems = useSetRecoilState(objectMetadataItemsState);
setMetadataItems(mockObjectMetadataItems); setMetadataItems(mockObjectMetadataItems);
return useFavorites(); return useFavorites();
@ -120,11 +120,11 @@ describe('useFavorites', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setCurrentWorkspaceMember = useSetRecoilState( const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState(), currentWorkspaceMemberState,
); );
setCurrentWorkspaceMember(mockWorkspaceMember); setCurrentWorkspaceMember(mockWorkspaceMember);
const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); const setMetadataItems = useSetRecoilState(objectMetadataItemsState);
setMetadataItems(mockObjectMetadataItems); setMetadataItems(mockObjectMetadataItems);
return useFavorites(); return useFavorites();

View File

@ -16,7 +16,7 @@ import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined'; import { isDefined } from '~/utils/isDefined';
export const useFavorites = () => { export const useFavorites = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { objectMetadataItem: favoriteObjectMetadataItem } = const { objectMetadataItem: favoriteObjectMetadataItem } =
useObjectMetadataItem({ useObjectMetadataItem({

View File

@ -28,12 +28,12 @@ export const AppNavigationDrawer = ({
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const isSettingsPage = useIsSettingsPage(); const isSettingsPage = useIsSettingsPage();
const currentMobileNavigationDrawer = useRecoilValue( const currentMobileNavigationDrawer = useRecoilValue(
currentMobileNavigationDrawerState(), currentMobileNavigationDrawerState,
); );
const setIsNavigationDrawerOpen = useSetRecoilState( const setIsNavigationDrawerOpen = useSetRecoilState(
isNavigationDrawerOpenState, isNavigationDrawerOpenState,
); );
const currentWorkspace = useRecoilValue(currentWorkspaceState()); const currentWorkspace = useRecoilValue(currentWorkspaceState);
const isSettingsDrawer = isMobile const isSettingsDrawer = isMobile
? currentMobileNavigationDrawer === 'settings' ? currentMobileNavigationDrawer === 'settings'

View File

@ -24,13 +24,11 @@ export const MainNavigationDrawerItems = () => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const { toggleCommandMenu } = useCommandMenu(); const { toggleCommandMenu } = useCommandMenu();
const isTasksPage = useIsTasksPage(); const isTasksPage = useIsTasksPage();
const currentUserDueTaskCount = useRecoilValue( const currentUserDueTaskCount = useRecoilValue(currentUserDueTaskCountState);
currentUserDueTaskCountState(),
);
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const setNavigationMemorizedUrl = useSetRecoilState( const setNavigationMemorizedUrl = useSetRecoilState(
navigationMemorizedUrlState(), navigationMemorizedUrlState,
); );
return ( return (

View File

@ -30,7 +30,7 @@ export const MobileNavigationBar = () => {
isNavigationDrawerOpenState, isNavigationDrawerOpenState,
); );
const [currentMobileNavigationDrawer, setCurrentMobileNavigationDrawer] = const [currentMobileNavigationDrawer, setCurrentMobileNavigationDrawer] =
useRecoilState(currentMobileNavigationDrawerState()); useRecoilState(currentMobileNavigationDrawerState);
const activeItemName = isNavigationDrawerOpen const activeItemName = isNavigationDrawerOpen
? currentMobileNavigationDrawer ? currentMobileNavigationDrawer

View File

@ -24,7 +24,7 @@ const MobileNavigationDrawerStateSetterEffect = ({
isNavigationDrawerOpenState, isNavigationDrawerOpenState,
); );
const setCurrentMobileNavigationDrawer = useSetRecoilState( const setCurrentMobileNavigationDrawer = useSetRecoilState(
currentMobileNavigationDrawerState(), currentMobileNavigationDrawerState,
); );
useEffect(() => { useEffect(() => {

View File

@ -13,7 +13,7 @@ export const ApolloMetadataClientProvider = ({
}: { }: {
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
const [tokenPair] = useRecoilState(tokenPairState()); const [tokenPair] = useRecoilState(tokenPairState);
const apolloMetadataClient = useMemo(() => { const apolloMetadataClient = useMemo(() => {
if (isNonEmptyString(tokenPair?.accessToken.token)) { if (isNonEmptyString(tokenPair?.accessToken.token)) {
return new ApolloClient({ return new ApolloClient({

View File

@ -10,7 +10,7 @@ export const ObjectMetadataItemsLoadEffect = () => {
useFindManyObjectMetadataItems(); useFindManyObjectMetadataItems();
const [objectMetadataItems, setObjectMetadataItems] = useRecoilState( const [objectMetadataItems, setObjectMetadataItems] = useRecoilState(
objectMetadataItemsState(), objectMetadataItemsState,
); );
useEffect(() => { useEffect(() => {

View File

@ -9,8 +9,8 @@ import { RelationPickerScope } from '@/object-record/relation-picker/scopes/Rela
export const ObjectMetadataItemsProvider = ({ export const ObjectMetadataItemsProvider = ({
children, children,
}: React.PropsWithChildren) => { }: React.PropsWithChildren) => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const shouldDisplayChildren = const shouldDisplayChildren =
objectMetadataItems.length > 0 || !currentWorkspaceMember; objectMetadataItems.length > 0 || !currentWorkspaceMember;

View File

@ -12,7 +12,7 @@ describe('useFilterOutUnexistingObjectMetadataItems', () => {
it('should work as expected', async () => { it('should work as expected', async () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); const setMetadataItems = useSetRecoilState(objectMetadataItemsState);
setMetadataItems(mockObjectMetadataItems.slice(1)); setMetadataItems(mockObjectMetadataItems.slice(1));
return useFilterOutUnexistingObjectMetadataItems(); return useFilterOutUnexistingObjectMetadataItems();

View File

@ -17,7 +17,7 @@ describe('useGetObjectRecordIdentifierByNameSingular', () => {
record: any; record: any;
objectNameSingular: string; objectNameSingular: string;
}) => { }) => {
const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); const setMetadataItems = useSetRecoilState(objectMetadataItemsState);
setMetadataItems(mockObjectMetadataItems); setMetadataItems(mockObjectMetadataItems);

View File

@ -31,7 +31,7 @@ describe('useGetRelationMetadata', () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); const setMetadataItems = useSetRecoilState(objectMetadataItemsState);
useEffect(() => { useEffect(() => {
setMetadataItems(objectMetadataItems); setMetadataItems(objectMetadataItems);

View File

@ -44,7 +44,7 @@ describe('useObjectMetadataItemForSettings', () => {
it('should findActiveObjectMetadataItemBySlug', async () => { it('should findActiveObjectMetadataItemBySlug', async () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); const setMetadataItems = useSetRecoilState(objectMetadataItemsState);
setMetadataItems(mockObjectMetadataItems); setMetadataItems(mockObjectMetadataItems);
return useObjectMetadataItemForSettings(); return useObjectMetadataItemForSettings();
@ -64,7 +64,7 @@ describe('useObjectMetadataItemForSettings', () => {
it('should findObjectMetadataItemById', async () => { it('should findObjectMetadataItemById', async () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); const setMetadataItems = useSetRecoilState(objectMetadataItemsState);
setMetadataItems(mockObjectMetadataItems); setMetadataItems(mockObjectMetadataItems);
return useObjectMetadataItemForSettings(); return useObjectMetadataItemForSettings();
@ -86,7 +86,7 @@ describe('useObjectMetadataItemForSettings', () => {
it('should findObjectMetadataItemByNamePlural', async () => { it('should findObjectMetadataItemByNamePlural', async () => {
const { result } = renderHook( const { result } = renderHook(
() => { () => {
const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); const setMetadataItems = useSetRecoilState(objectMetadataItemsState);
setMetadataItems(mockObjectMetadataItems); setMetadataItems(mockObjectMetadataItems);
return useObjectMetadataItemForSettings(); return useObjectMetadataItemForSettings();

View File

@ -28,7 +28,10 @@ export const useCreateOneObjectMetadataItem = () => {
input: { object: input }, input: { object: input },
}, },
awaitRefetchQueries: true, awaitRefetchQueries: true,
refetchQueries: [getOperationName(FIND_MANY_OBJECT_METADATA_ITEMS) ?? ''], refetchQueries: [
getOperationName(FIND_MANY_OBJECT_METADATA_ITEMS) ?? '',
'FindManyRecordsMultipleMetadataItems',
],
}); });
}; };

View File

@ -5,7 +5,7 @@ import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectReco
import { ObjectRecordIdentifier } from '@/object-record/types/ObjectRecordIdentifier'; import { ObjectRecordIdentifier } from '@/object-record/types/ObjectRecordIdentifier';
export const useGetObjectRecordIdentifierByNameSingular = () => { export const useGetObjectRecordIdentifierByNameSingular = () => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
return (record: any, objectNameSingular: string): ObjectRecordIdentifier => { return (record: any, objectNameSingular: string): ObjectRecordIdentifier => {
const objectMetadataItem = objectMetadataItems.find( const objectMetadataItem = objectMetadataItems.find(

View File

@ -42,7 +42,7 @@ export const useObjectMetadataItem = (
depth?: number, depth?: number,
eagerLoadedRelations?: Record<string, any>, eagerLoadedRelations?: Record<string, any>,
) => { ) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState()); const currentWorkspace = useRecoilValue(currentWorkspaceState);
const mockObjectMetadataItems = getObjectMetadataItemsMock(); const mockObjectMetadataItems = getObjectMetadataItemsMock();
@ -53,7 +53,7 @@ export const useObjectMetadataItem = (
}), }),
); );
let objectMetadataItems = useRecoilValue(objectMetadataItemsState()); let objectMetadataItems = useRecoilValue(objectMetadataItemsState);
if (currentWorkspace?.activationStatus !== 'active') { if (currentWorkspace?.activationStatus !== 'active') {
objectMetadataItem = objectMetadataItem =

View File

@ -5,7 +5,7 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat
import { getObjectSlug } from '../utils/getObjectSlug'; import { getObjectSlug } from '../utils/getObjectSlug';
export const useObjectMetadataItemForSettings = () => { export const useObjectMetadataItemForSettings = () => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const activeObjectMetadataItems = objectMetadataItems.filter( const activeObjectMetadataItems = objectMetadataItems.filter(
({ isActive, isSystem }) => isActive && !isSystem, ({ isActive, isSystem }) => isActive && !isSystem,

View File

@ -12,7 +12,7 @@ import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentif
export const useObjectMetadataItemOnly = ({ export const useObjectMetadataItemOnly = ({
objectNameSingular, objectNameSingular,
}: ObjectMetadataItemIdentifier) => { }: ObjectMetadataItemIdentifier) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState()); const currentWorkspace = useRecoilValue(currentWorkspaceState);
const mockObjectMetadataItems = getObjectMetadataItemsMock(); const mockObjectMetadataItems = getObjectMetadataItemsMock();
@ -23,7 +23,7 @@ export const useObjectMetadataItemOnly = ({
}), }),
); );
let objectMetadataItems = useRecoilValue(objectMetadataItemsState()); let objectMetadataItems = useRecoilValue(objectMetadataItemsState);
if (currentWorkspace?.activationStatus !== 'active') { if (currentWorkspace?.activationStatus !== 'active') {
objectMetadataItem = objectMetadataItem =

View File

@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
export const useObjectMetadataItems = () => { export const useObjectMetadataItems = () => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
return { return {
objectMetadataItems, objectMetadataItems,

View File

@ -10,7 +10,7 @@ export const useObjectNamePluralFromSingular = ({
}: { }: {
objectNameSingular: string; objectNameSingular: string;
}) => { }) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState()); const currentWorkspace = useRecoilValue(currentWorkspaceState);
const mockObjectMetadataItems = getObjectMetadataItemsMock(); const mockObjectMetadataItems = getObjectMetadataItemsMock();
let objectMetadataItem = useRecoilValue( let objectMetadataItem = useRecoilValue(

View File

@ -10,7 +10,7 @@ export const useObjectNameSingularFromPlural = ({
}: { }: {
objectNamePlural: string; objectNamePlural: string;
}) => { }) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState()); const currentWorkspace = useRecoilValue(currentWorkspaceState);
const mockObjectMetadataItems = getObjectMetadataItemsMock(); const mockObjectMetadataItems = getObjectMetadataItemsMock();

View File

@ -16,7 +16,7 @@ export const objectMetadataItemFamilySelector = selectorFamily<
get: get:
({ objectNameType, objectName }: ObjectMetadataItemSelector) => ({ objectNameType, objectName }: ObjectMetadataItemSelector) =>
({ get }) => { ({ get }) => {
const objectMetadataItems = get(objectMetadataItemsState()); const objectMetadataItems = get(objectMetadataItemsState);
if (objectNameType === 'singular') { if (objectNameType === 'singular') {
return ( return (

View File

@ -8,7 +8,7 @@ export const objectMetadataItemsByNamePluralMapSelector = selector<
>({ >({
key: 'objectMetadataItemsByNamePluralMapSelector', key: 'objectMetadataItemsByNamePluralMapSelector',
get: ({ get }) => { get: ({ get }) => {
const objectMetadataItems = get(objectMetadataItemsState()); const objectMetadataItems = get(objectMetadataItemsState);
return new Map( return new Map(
objectMetadataItems.map((objectMetadataItem) => [ objectMetadataItems.map((objectMetadataItem) => [

View File

@ -8,7 +8,7 @@ export const objectMetadataItemsByNameSingularMapSelector = selector<
>({ >({
key: 'objectMetadataItemsByNameSingularMapSelector', key: 'objectMetadataItemsByNameSingularMapSelector',
get: ({ get }) => { get: ({ get }) => {
const objectMetadataItems = get(objectMetadataItemsState()); const objectMetadataItems = get(objectMetadataItemsState);
return new Map( return new Map(
objectMetadataItems.map((objectMetadataItem) => [ objectMetadataItems.map((objectMetadataItem) => [

View File

@ -15,7 +15,7 @@ export const useAddRecordInCache = ({
}: { }: {
objectMetadataItem: ObjectMetadataItem; objectMetadataItem: ObjectMetadataItem;
}) => { }) => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const apolloClient = useApolloClient(); const apolloClient = useApolloClient();
const { injectIntoFindOneRecordQueryCache } = const { injectIntoFindOneRecordQueryCache } =

View File

@ -1,3 +1,4 @@
import { useCallback } from 'react';
import { gql, useApolloClient } from '@apollo/client'; import { gql, useApolloClient } from '@apollo/client';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
@ -13,21 +14,22 @@ export const useGetRecordFromCache = ({
}: { }: {
objectMetadataItem: ObjectMetadataItem; objectMetadataItem: ObjectMetadataItem;
}) => { }) => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const apolloClient = useApolloClient(); const apolloClient = useApolloClient();
return <CachedObjectRecord extends ObjectRecord = ObjectRecord>( return useCallback(
recordId: string, <CachedObjectRecord extends ObjectRecord = ObjectRecord>(
cache = apolloClient.cache, recordId: string,
) => { cache = apolloClient.cache,
if (isUndefinedOrNull(objectMetadataItem)) { ) => {
return null; if (isUndefinedOrNull(objectMetadataItem)) {
} return null;
}
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular); const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
const cacheReadFragment = gql` const cacheReadFragment = gql`
fragment ${capitalizedObjectName}Fragment on ${capitalizedObjectName} ${mapObjectMetadataToGraphQLQuery( fragment ${capitalizedObjectName}Fragment on ${capitalizedObjectName} ${mapObjectMetadataToGraphQLQuery(
{ {
objectMetadataItems, objectMetadataItems,
@ -36,14 +38,16 @@ export const useGetRecordFromCache = ({
)} )}
`; `;
const cachedRecordId = cache.identify({ const cachedRecordId = cache.identify({
__typename: capitalize(objectMetadataItem.nameSingular), __typename: capitalize(objectMetadataItem.nameSingular),
id: recordId, id: recordId,
}); });
return cache.readFragment<CachedObjectRecord & { __typename: string }>({ return cache.readFragment<CachedObjectRecord & { __typename: string }>({
id: cachedRecordId, id: cachedRecordId,
fragment: cacheReadFragment, fragment: cacheReadFragment,
}); });
}; },
[objectMetadataItem, objectMetadataItems, apolloClient],
);
}; };

View File

@ -17,7 +17,8 @@ export const getRecordEdgeFromRecord = <T extends ObjectRecord>({
return [ return [
key, key,
getRecordConnectionFromRecords({ getRecordConnectionFromRecords({
objectNameSingular: key, // Todo: this is a ugly and broken hack to get the singular, we need to infer this from metadata
objectNameSingular: key.slice(0, -1),
records: value as ObjectRecord[], records: value as ObjectRecord[],
}), }),
]; ];

Some files were not shown because too many files have changed in this diff Show More