Fix sort with Email and FullName field types and add sort/filter to labelIdentifier column (#6132)

Fixes https://github.com/twentyhq/twenty/issues/5958

<img width="1088" alt="Screenshot 2024-07-04 at 16 23 25"
src="https://github.com/twentyhq/twenty/assets/1834158/746c45a4-7112-4322-8c26-04f3e98add06">

<img width="1280" alt="Screenshot 2024-07-04 at 16 15 39"
src="https://github.com/twentyhq/twenty/assets/1834158/9b9ecc60-9787-44a3-9ba7-0b33ec378e6f">
This commit is contained in:
Weiko
2024-07-05 17:01:47 +02:00
committed by GitHub
parent b33b468679
commit cc6ce142ce
4 changed files with 38 additions and 17 deletions

View File

@@ -18,6 +18,8 @@ export const formatFieldMetadataItemsAsSortDefinitions = ({
FieldMetadataType.Boolean, FieldMetadataType.Boolean,
FieldMetadataType.Select, FieldMetadataType.Select,
FieldMetadataType.Phone, FieldMetadataType.Phone,
FieldMetadataType.Email,
FieldMetadataType.FullName,
].includes(field.type) ].includes(field.type)
) { ) {
return acc; return acc;

View File

@@ -2,7 +2,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { OrderBy } from '@/object-metadata/types/OrderBy'; import { OrderBy } from '@/object-metadata/types/OrderBy';
import { hasPositionField } from '@/object-metadata/utils/hasPositionField'; import { hasPositionField } from '@/object-metadata/utils/hasPositionField';
import { RecordGqlOperationOrderBy } from '@/object-record/graphql/types/RecordGqlOperationOrderBy'; import { RecordGqlOperationOrderBy } from '@/object-record/graphql/types/RecordGqlOperationOrderBy';
import { Field } from '~/generated/graphql'; import { Field, FieldMetadataType } from '~/generated/graphql';
import { mapArrayToObject } from '~/utils/array/mapArrayToObject'; import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
import { isDefined } from '~/utils/isDefined'; import { isDefined } from '~/utils/isDefined';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
@@ -13,7 +13,8 @@ export const turnSortsIntoOrderBy = (
objectMetadataItem: ObjectMetadataItem, objectMetadataItem: ObjectMetadataItem,
sorts: Sort[], sorts: Sort[],
): RecordGqlOperationOrderBy => { ): RecordGqlOperationOrderBy => {
const fields: Pick<Field, 'id' | 'name'>[] = objectMetadataItem?.fields ?? []; const fields: Pick<Field, 'id' | 'name' | 'type'>[] =
objectMetadataItem?.fields ?? [];
const fieldsById = mapArrayToObject(fields, ({ id }) => id); const fieldsById = mapArrayToObject(fields, ({ id }) => id);
const sortsOrderBy = sorts const sortsOrderBy = sorts
.map((sort) => { .map((sort) => {
@@ -26,7 +27,7 @@ export const turnSortsIntoOrderBy = (
const direction: OrderBy = const direction: OrderBy =
sort.direction === 'asc' ? 'AscNullsFirst' : 'DescNullsLast'; sort.direction === 'asc' ? 'AscNullsFirst' : 'DescNullsLast';
return { [correspondingField.name]: direction }; return getOrderByForFieldMetadataType(correspondingField, direction);
}) })
.filter(isDefined); .filter(isDefined);
@@ -36,3 +37,21 @@ export const turnSortsIntoOrderBy = (
return sortsOrderBy; return sortsOrderBy;
}; };
const getOrderByForFieldMetadataType = (
field: Pick<Field, 'id' | 'name' | 'type'>,
direction: OrderBy,
) => {
switch (field.type) {
case FieldMetadataType.FullName:
return {
[field.name]: {
firstName: direction,
lastName: direction,
},
};
default:
return { [field.name]: direction };
}
};

View File

@@ -33,12 +33,13 @@ export const RecordTableColumnDropdownMenu = ({
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector()); const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector());
const secondVisibleColumn = visibleTableColumns[1]; const secondVisibleColumn = visibleTableColumns[1];
const canMove = column.isLabelIdentifier !== true;
const canMoveLeft = const canMoveLeft =
column.fieldMetadataId !== secondVisibleColumn?.fieldMetadataId; column.fieldMetadataId !== secondVisibleColumn?.fieldMetadataId && canMove;
const lastVisibleColumn = visibleTableColumns[visibleTableColumns.length - 1]; const lastVisibleColumn = visibleTableColumns[visibleTableColumns.length - 1];
const canMoveRight = const canMoveRight =
column.fieldMetadataId !== lastVisibleColumn?.fieldMetadataId; column.fieldMetadataId !== lastVisibleColumn?.fieldMetadataId && canMove;
const { handleColumnVisibilityChange, handleMoveTableColumn } = const { handleColumnVisibilityChange, handleMoveTableColumn } =
useTableColumns(); useTableColumns();
@@ -83,7 +84,9 @@ export const RecordTableColumnDropdownMenu = ({
const isSortable = column.isSortable === true; const isSortable = column.isSortable === true;
const isFilterable = column.isFilterable === true; const isFilterable = column.isFilterable === true;
const showSeparator = isFilterable || isSortable; const showSeparator =
(isFilterable || isSortable) && column.isLabelIdentifier !== true;
const canHide = column.isLabelIdentifier !== true;
return ( return (
<DropdownMenuItemsContainer> <DropdownMenuItemsContainer>
@@ -116,11 +119,13 @@ export const RecordTableColumnDropdownMenu = ({
text="Move right" text="Move right"
/> />
)} )}
<MenuItem {canHide && (
LeftIcon={IconEyeOff} <MenuItem
onClick={handleColumnVisibility} LeftIcon={IconEyeOff}
text="Hide" onClick={handleColumnVisibility}
/> text="Hide"
/>
)}
</DropdownMenuItemsContainer> </DropdownMenuItemsContainer>
); );
}; };

View File

@@ -4,7 +4,6 @@ import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { IconPlus } from 'twenty-ui'; import { IconPlus } from 'twenty-ui';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { ColumnHead } from '@/object-record/record-table/components/ColumnHead';
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
import { useTableColumns } from '@/object-record/record-table/hooks/useTableColumns'; import { useTableColumns } from '@/object-record/record-table/hooks/useTableColumns';
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
@@ -186,11 +185,7 @@ export const RecordTableHeaderCell = ({
onMouseLeave={() => setIconVisibility(false)} onMouseLeave={() => setIconVisibility(false)}
> >
<StyledColumnHeadContainer> <StyledColumnHeadContainer>
{column.isLabelIdentifier ? ( <ColumnHeadWithDropdown column={column} />
<ColumnHead column={column} />
) : (
<ColumnHeadWithDropdown column={column} />
)}
{(useIsMobile() || iconVisibility) && !!column.isLabelIdentifier && ( {(useIsMobile() || iconVisibility) && !!column.isLabelIdentifier && (
<StyledHeaderIcon> <StyledHeaderIcon>
<LightIconButton <LightIconButton