-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Simplify last visited #10259
Simplify last visited #10259
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR Summary
This PR significantly simplifies the navigation state management system by removing and consolidating last visited functionality.
- Removes
useLastVisitedObjectMetadataItem
hook and related selectors, replacing with simpleruseSetLastVisitedObjectMetadataId
hook - Simplifies
useLastVisitedView
to only provide getter functionality, removing workspace-specific state management - Changes state management from
createComponentState
tocreateState
inlastVisitedObjectMetadataItemIdState.ts
, modifying type fromRecord<string, string>
tostring | null
- Introduces potential issue in
useSetLastVisitedViewForObjectMetadataNamePlural
using incorrect state for view tracking - Removes accidental debug
console.log
inRecordIndexContainer.tsx
16 file(s) reviewed, 5 comment(s)
Edit PR Review Bot Settings | Greptile
console.log( | ||
'mainContextStoreComponentInstanceIdToSet', | ||
mainContextStoreComponentInstanceIdToSet, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: console.log statement should be removed before merging to production
console.log( | |
'mainContextStoreComponentInstanceIdToSet', | |
mainContextStoreComponentInstanceIdToSet, | |
); |
const lastVisitedViewPerObjectMetadataItem = snapshot | ||
.getLoadable(lastVisitedObjectMetadataItemIdState) | ||
.getValue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: incorrect state usage - lastVisitedObjectMetadataItemIdState
should contain IDs, not views. Should use lastVisitedViewPerObjectMetadataItemState
instead to get the last visited view
const lastVisitedViewPerObjectMetadataItem = snapshot | |
.getLoadable(lastVisitedObjectMetadataItemIdState) | |
.getValue(); | |
const lastVisitedViewPerObjectMetadataItem = snapshot | |
.getLoadable(lastVisitedViewPerObjectMetadataItemState) | |
.getValue(); |
set(lastVisitedViewPerObjectMetadataItemState, { | ||
[objectMetadataItem.id]: viewId, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: this overwrites the entire state object instead of merging with existing entries. Should spread existing state: set(lastVisitedViewPerObjectMetadataItemState, (prev) => ({ ...prev, [objectMetadataItem.id]: viewId }))
set(lastVisitedViewPerObjectMetadataItemState, { | |
[objectMetadataItem.id]: viewId, | |
}); | |
set(lastVisitedViewPerObjectMetadataItemState, (prev) => ({ | |
...prev, | |
[objectMetadataItem.id]: viewId, | |
})); |
@@ -187,6 +187,8 @@ export const RecordIndexContainer = () => { | |||
FeatureFlagKey.IsCommandMenuV2Enabled, | |||
); | |||
|
|||
console.log(columnDefinitions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Remove debug console.log statement before merging to production
console.log(columnDefinitions); |
@@ -143,19 +131,6 @@ export const ObjectSettings = ({ objectMetadataItem }: ObjectSettingsProps) => { | |||
|
|||
formConfig.reset(undefined, { keepValues: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: reset is called before navigation, could lead to state inconsistency if navigation fails
import { isDefined } from 'twenty-shared'; | ||
|
||
export const useSetLastVisitedViewForObjectMetadataNamePlural = () => { | ||
const { records: views, findManyRecords } = useLazyPrefetchedData<View>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
introducing this hook but I think we should use a state and stop reading from apollo cache here
@greptileai trigger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR Summary
(updates since last review)
This PR continues to refine the navigation state management system with additional changes focused on view handling and prefetching. Here are the key new changes:
- Added new
useLazyPrefetchedData
hook inprefetch/hooks/useLazyPrefetchData.ts
for optimized data loading with operation signature factory support - Modified
MainContextStoreProvider
to include robust view fallback logic usingindexView
when no view ID is available - Removed redundant state checks and optional chaining in
useSetLastVisitedViewForObjectMetadataNamePlural
hook - Simplified
SettingsObjectSummaryCard
by removinguseLastVisitedView
hook and its fallback logic - Fixed state update in
useSetLastVisitedViewForObjectMetadataNamePlural
where it overwrites entire state instead of merging entries
7 file(s) reviewed, 4 comment(s)
Edit PR Review Bot Settings | Greptile
const navigationPath = getAppPath( | ||
AppPath.RecordIndexPage, | ||
{ objectNamePlural: objectMetadataItem.namePlural }, | ||
viewId ? { viewId } : undefined, | ||
lastVisitedViewId ? { viewId: lastVisitedViewId } : undefined, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: navigationPath now uses lastVisitedViewId while active states use contextStoreCurrentViewId, which could cause inconsistent UI state
setLastVisitedViewForObjectMetadataNamePlural({ | ||
objectNamePlural: objectMetadataItem.namePlural, | ||
viewId: viewId, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: setLastVisitedViewForObjectMetadataNamePlural is called unconditionally on every effect run. Consider adding a condition to only update when values change.
setLastVisitedObjectMetadataId({ | ||
objectMetadataItemId: objectMetadataItem.id, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: setLastVisitedObjectMetadataId is called unconditionally on every effect run. Consider adding a condition to only update when the ID changes.
const recordGqlFields = | ||
operationSignatureFactory({ objectMetadataItem }).fields ?? filter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: The nullish coalescing operator here could be problematic if operationSignatureFactory().fields is an empty object - it would not fall back to the filter. Consider checking for empty object as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice refactor ! Only nitpicks
isNavigationDrawerExpandedState, | ||
); | ||
const [, setCurrentMobileNavigationDrawer] = useRecoilState( | ||
const setCurrentMobileNavigationDrawer = useSetRecoilState( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Praise: Nice
}) => { | ||
await findManyRecords(); | ||
|
||
const view = views.find((view: View) => view.id === viewId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Redundant arg typing
lastVisitedViewPerObjectMetadataItem?.[objectMetadataItem?.id]; | ||
|
||
if (isDefined(objectMetadataItem) && lastVisitedViewId !== viewId) { | ||
set(lastVisitedViewPerObjectMetadataItemState, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Could avoid making findManyRecords
each run
const mainContextStoreComponentInstanceId = useRecoilValue( | ||
mainContextStoreComponentInstanceIdState, | ||
); | ||
|
||
const lastVisitedViewId = getLastVisitedViewIdFromObjectMetadataItemId( | ||
objectMetadataItem.id, | ||
const contextStoreCurrentViewId = useRecoilComponentValueV2( | ||
contextStoreCurrentViewIdComponentState, | ||
mainContextStoreComponentInstanceId, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Could be unused ?
const { filterableFieldMetadataItems } = | ||
useFilterableFieldMetadataItemsInRecordIndexContext(); | ||
const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems( | ||
objectMetadataItem?.id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remark: We should not use any on the following fields
export type Scalars = {
ID: { input: string; output: string; }
String: { input: string; output: string; }
Boolean: { input: boolean; output: boolean; }
Int: { input: number; output: number; }
Float: { input: number; output: number; }
/** Cursor for paging through collections */
ConnectionCursor: { input: any; output: any; }
/** A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. */
DateTime: { input: any; output: any; }
/** The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */
JSON: { input: any; output: any; }
/** The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */
JSONObject: { input: any; output: any; }
/** A UUID scalar type */
UUID: { input: unknown; output: unknown; }
/** The `Upload` scalar type represents a file upload. */
Upload: { input: any; output: any; }
};
Using unknown on UUID shows possible runtime error here 431 tsc-errors
About to create an issue to address this
In this PR, I'm simplifying the lastVisitedView / Object logic: