-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
[Issue-5772] Add sort feature on settings tables #5787
base: main
Are you sure you want to change the base?
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
- Introduced
useTableSort
custom hook for table sorting - Added test cases for
useTableSort
- Integrated sorting in
SettingsObjectFieldItemTableRow
andSettingsObjectItemTableRow
- Enabled clickable headers for sorting in
TableHeader
- Updated
SettingsObjectDetail
andSettingsObjects
pages to use sorting functionality
tableDataSortedByFieldsCountInDescendingOrder, | ||
tableDataSortedBylabelInAscendingOrder, | ||
tableDataSortedBylabelInDescendingOrder, | ||
} from '~/testing/mock-data/tableData'; |
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.
Use toEqual
instead of toBe
for comparing objects or arrays to avoid potential issues with reference equality.
type SortConfig<T> = { | ||
sortByColumnKey: keyof T; | ||
sortOrder: sortOrders; | ||
}; |
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.
Consider renaming sortOrders
to SortOrders
to follow TypeScript enum naming conventions.
return order === sortOrders.ascending | ||
? (a[columnKey] as string).localeCompare(b[columnKey] as string) | ||
: (b[columnKey] as string).localeCompare(a[columnKey] as string); | ||
} else if (typeof a[columnKey] === 'number') { |
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.
Handle cases where a[columnKey]
or b[columnKey]
might be undefined
to prevent runtime errors.
@@ -7,6 +7,7 @@ import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMe | |||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; | |||
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug'; |
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.
Ensure fieldType
is correctly populated in all instances of fieldMetadataItem
.
@@ -41,10 +43,8 @@ const StyledIconTableCell = styled(TableCell)` | |||
export const SettingsObjectFieldItemTableRow = ({ |
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.
Consider adding a default value or error handling for updateDataTypes
to avoid potential runtime errors.
import { useTheme } from '@emotion/react'; | ||
import styled from '@emotion/styled'; | ||
import { useIcons } from 'twenty-ui'; | ||
|
||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; | ||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; | ||
import { SettingsDataModelObjectTypeTag } from '@/settings/data-model/objects/SettingsDataModelObjectTypeTag'; | ||
import { getObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel'; | ||
import { | ||
getObjectTypeLabel, |
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.
Ensure useEffect
dependency array is correct to avoid unnecessary re-renders.
@@ -1,7 +1,13 @@ | |||
import { useEffect } from 'react'; | |||
import { useCallback, useEffect, useState } from 'react'; |
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.
Consider importing useCallback
and useState
from React in a single line for better readability.
@@ -38,13 +64,74 @@ const StyledH1Title = styled(H1Title)` | |||
margin-bottom: 0; |
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.
Ensure that instanceCountObj
is correctly populated before using it in getRowData
to avoid potential undefined values.
Hi Charles,
Thanks a lot for your feedback. I will look in this and update the PR. Some
immediate work has come up and I hope to fix this on the weekend.
…On Mon, 10 Jun 2024, 5:11 pm Charles Bochet, ***@***.***> wrote:
@Anand-Krishnan-M-J <https://github.com/Anand-Krishnan-M-J> Thanks for
your PR :) Honnestly, I think we should restrict the scope to supporting
Links filtering. Supporting sort in this PR (for Thursday) looks very
ambitious. Let's treat that in a separated PR and keep this one for Links
filtering
1. Please run npx nx run twenty-front:lint:ci, you should see some
errors. (I believe they are tied to the changes you have made for sorting)
2. The work on Links looks good but I cannot test it as the front does
not build at the moment
3. we'll have few lines to add in the backend to remove secondaryLinks
from the FilterInput
image.png (view on web)
<https://github.com/twentyhq/twenty/assets/12035771/9b6f0909-8d3a-42d9-8f5d-58d696180fa6>
—
Reply to this email directly, view it on GitHub
<#5787 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AU4NDQEI4NO5BFCQ5D2SX6LZGWGG3AVCNFSM6AAAAABJBAMXOSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJYGEYTKNRSGE>
.
You are receiving this because you were mentioned.Message 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.
Thank you for contributing.
It's conceptually ok but some patterns feels odd, due to props drilling.
We use Recoil extensively in Twenty codebase and this feature particularly fits Recoil.
Could you please rework on a solution where :
- Sorts are stored in a Recoil family state (you'll find many examples in our codebase) I suggest you make a family state with a key like { tableId: string, tableObjectName: string, tableFieldName: string } => value: OrderBy | null
- The logic around a column header cell is abstracted in that header cell component and just modifies the related sort in the recoil family state
- Then each list should just use a hook like useSortedArray that takes (arrayToSort: ObjectRecord[], tableId: string, tableObjectName: string and fieldName: string (or fieldName array string[]) and it applies the sort and just derives the state.
It will be much more simpler to read and maintain (and review ;) )
@@ -0,0 +1,62 @@ | |||
import { useState } from 'react'; | |||
|
|||
enum sortOrders { |
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.
We already have OrderBy
: sortOrders.ascending; | ||
}; | ||
|
||
const handleSortClick = (columnKey: keyof T) => { |
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.
Handlers should be the scope of a component, not of a hook
sortConfig.sortOrder, | ||
); | ||
|
||
const toggleSortOrder = (sortOrder: sortOrders) => { |
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.
This function isn't toggling, it's just returning the opposite of the passed sortOrder, so it should either be renamed or either really toggling the state
@@ -17,11 +18,12 @@ import { SettingsObjectFieldDataType } from './SettingsObjectFieldDataType'; | |||
|
|||
type SettingsObjectFieldItemTableRowProps = { | |||
ActionIcon: ReactNode; | |||
fieldMetadataItem: FieldMetadataItem; | |||
fieldMetadataItem: FieldMetadataItem & { fieldType: string | boolean }; |
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.
fieldType is redundant, we already have a type property on fieldMetadataItem which should be used.
@@ -60,6 +60,18 @@ export const SettingsObjectFieldItemTableRow = ({ | |||
|
|||
const fieldType = fieldMetadataItem.type; | |||
const isFieldTypeSupported = isFieldTypeSupportedInSettings(fieldType); | |||
useEffect(() => { |
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.
This logic is not necessary because we already have a fieldMetadataItem array higher up in the tree, the row shouldn't be related to this feature.
!!identifierType && | ||
(identifierType === 'label' ? 'Record text' : 'Record image')} | ||
</TableCell> | ||
<TableCell>{fieldMetadataItem.fieldType}</TableCell> |
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.
We should be keep the derived state here, not adding a new field on fieldMetadataItem, if you need to share it with another place just create a util like getFieldMetadataItemTypeLabel(fieldMetadataItem)
Proposed Changes
Related Issue
#5772
Evidence
2024-06-09.21-35-41.mp4
Further comments
Apologies for the large PR. Looking forward for the review