Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Issue-5772] Add sort feature on settings tables #5787

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Anand-Krishnan-M-J
Copy link
Contributor

Proposed Changes

  • Introduce a new custom hook - useTableSort to sort table content
  • Add test cases for the new custom hook
  • Integrate useTableSort hook on to the table in settings object and settings object field pages

Related Issue

#5772

Evidence

2024-06-09.21-35-41.mp4

Further comments

Apologies for the large PR. Looking forward for the review

Copy link

@greptile-apps greptile-apps bot left a 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 and SettingsObjectItemTableRow
  • Enabled clickable headers for sorting in TableHeader
  • Updated SettingsObjectDetail and SettingsObjects pages to use sorting functionality

tableDataSortedByFieldsCountInDescendingOrder,
tableDataSortedBylabelInAscendingOrder,
tableDataSortedBylabelInDescendingOrder,
} from '~/testing/mock-data/tableData';
Copy link

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;
};
Copy link

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') {
Copy link

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';
Copy link

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 = ({
Copy link

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,
Copy link

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';
Copy link

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;
Copy link

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.

@Anand-Krishnan-M-J
Copy link
Contributor Author

Anand-Krishnan-M-J commented Jun 10, 2024 via email

Copy link
Contributor

@lucasbordeau lucasbordeau left a 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 {
Copy link
Contributor

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) => {
Copy link
Contributor

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) => {
Copy link
Contributor

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 };
Copy link
Contributor

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(() => {
Copy link
Contributor

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>
Copy link
Contributor

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants