Removed sort definitions (#10368)

This PR focuses on complete removal of sort definitions.
This commit is contained in:
Lucas Bordeau
2025-02-21 16:59:38 +01:00
committed by GitHub
parent d747366bf3
commit 22203bfd3c
31 changed files with 93 additions and 324 deletions

View File

@ -1,6 +1,8 @@
import styled from '@emotion/styled';
import { IconChevronDown, MenuItem, useIcons } from 'twenty-ui';
import { availableFieldMetadataItemsForSortFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForSortFamilySelector';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId';
import { useCloseSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useCloseSortDropdown';
import { useResetRecordSortDropdownSearchInput } from '@/object-record/object-sort-dropdown/hooks/useResetRecordSortDropdownSearchInput';
@ -10,7 +12,6 @@ import { isRecordSortDirectionDropdownMenuUnfoldedComponentState } from '@/objec
import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState';
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
import { selectedRecordSortDirectionComponentState } from '@/object-record/object-sort-dropdown/states/selectedRecordSortDirectionComponentState';
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import {
RECORD_SORT_DIRECTIONS,
@ -28,8 +29,8 @@ import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
import { Trans, useLingui } from '@lingui/react/macro';
import { useRecoilValue } from 'recoil';
import { v4 } from 'uuid';
export const StyledInput = styled.input`
@ -89,14 +90,16 @@ export const ObjectSortDropdownButton = ({
const { resetSortDropdown } = useResetSortDropdown();
const { recordIndexId } = useRecordIndexContextOrThrow();
const { recordIndexId, objectMetadataItem } = useRecordIndexContextOrThrow();
const objectSortDropdownSearchInput = useRecoilComponentValueV2(
objectSortDropdownSearchInputComponentState,
);
const availableSortDefinitions = useRecoilComponentValueV2(
availableSortDefinitionsComponentState,
const sortableFieldMetadataItems = useRecoilValue(
availableFieldMetadataItemsForSortFamilySelector({
objectMetadataItemId: objectMetadataItem.id,
}),
);
const { getIcon } = useIcons();
@ -105,40 +108,45 @@ export const ObjectSortDropdownButton = ({
visibleTableColumnsComponentSelector,
recordIndexId,
);
const visibleColumnsIds = visibleTableColumns.map(
const visibleColumnsFieldMetadataIds = visibleTableColumns.map(
(column) => column.fieldMetadataId,
);
const hiddenTableColumns = useRecoilComponentValueV2(
hiddenTableColumnsComponentSelector,
recordIndexId,
);
const hiddenColumnIds = hiddenTableColumns.map(
const hiddenColumnFieldMetadataIds = hiddenTableColumns.map(
(column) => column.fieldMetadataId,
);
const filteredSearchInputSortDefinitions = availableSortDefinitions.filter(
(item) =>
const filteredSearchInputFieldMetadataItems =
sortableFieldMetadataItems.filter((item) =>
item.label
.toLocaleLowerCase()
.includes(objectSortDropdownSearchInput.toLocaleLowerCase()),
);
);
const visibleColumnsSortDefinitions = filteredSearchInputSortDefinitions
.sort((a, b) => {
const visibleFieldMetadataItems = filteredSearchInputFieldMetadataItems
.sort((fieldMetadataItemA, fieldMetadataItemB) => {
return (
visibleColumnsIds.indexOf(a.fieldMetadataId) -
visibleColumnsIds.indexOf(b.fieldMetadataId)
visibleColumnsFieldMetadataIds.indexOf(fieldMetadataItemA.id) -
visibleColumnsFieldMetadataIds.indexOf(fieldMetadataItemB.id)
);
})
.filter((item) => visibleColumnsIds.includes(item.fieldMetadataId));
.filter((fieldMetadataItem) =>
visibleColumnsFieldMetadataIds.includes(fieldMetadataItem.id),
);
const hiddenColumnsSortDefinitions = filteredSearchInputSortDefinitions
.sort((a, b) => a.label.localeCompare(b.label))
.filter((item) => hiddenColumnIds.includes(item.fieldMetadataId));
const hiddenFieldMetadataItems = filteredSearchInputFieldMetadataItems
.sort((fieldMetadataItemA, fieldMetadataItemB) =>
fieldMetadataItemA.label.localeCompare(fieldMetadataItemB.label),
)
.filter((fieldMetadataItem) =>
hiddenColumnFieldMetadataIds.includes(fieldMetadataItem.id),
);
const shoudShowSeparator =
visibleColumnsSortDefinitions.length > 0 &&
hiddenColumnsSortDefinitions.length > 0;
const shouldShowSeparator =
visibleFieldMetadataItems.length > 0 && hiddenFieldMetadataItems.length > 0;
const handleButtonClick = () => {
toggleSortDropdown();
@ -153,14 +161,13 @@ export const ObjectSortDropdownButton = ({
const onSortSelect = useRecoilComponentValueV2(onSortSelectComponentState);
const handleAddSort = (sortDefinition: SortDefinition) => {
const handleAddSort = (fieldMetadataItem: FieldMetadataItem) => {
setObjectSortDropdownSearchInput('');
closeSortDropdown();
onSortSelect?.({
id: v4(),
fieldMetadataId: sortDefinition.fieldMetadataId,
fieldMetadataId: fieldMetadataItem.id,
direction: selectedRecordSortDirection,
definition: sortDefinition,
});
};
@ -231,25 +238,25 @@ export const ObjectSortDropdownButton = ({
}
/>
<DropdownMenuItemsContainer>
{visibleColumnsSortDefinitions.map(
(visibleSortDefinition, index) => (
{visibleFieldMetadataItems.map(
(visibleFieldMetadataItem, index) => (
<MenuItem
testId={`visible-select-sort-${index}`}
key={index}
onClick={() => handleAddSort(visibleSortDefinition)}
LeftIcon={getIcon(visibleSortDefinition.iconName)}
text={visibleSortDefinition.label}
onClick={() => handleAddSort(visibleFieldMetadataItem)}
LeftIcon={getIcon(visibleFieldMetadataItem.icon)}
text={visibleFieldMetadataItem.label}
/>
),
)}
{shoudShowSeparator && <DropdownMenuSeparator />}
{hiddenColumnsSortDefinitions.map((hiddenSortDefinition, index) => (
{shouldShowSeparator && <DropdownMenuSeparator />}
{hiddenFieldMetadataItems.map((hiddenFieldMetadataItem, index) => (
<MenuItem
testId={`hidden-select-sort-${index}`}
key={index}
onClick={() => handleAddSort(hiddenSortDefinition)}
LeftIcon={getIcon(hiddenSortDefinition.iconName)}
text={hiddenSortDefinition.label}
onClick={() => handleAddSort(hiddenFieldMetadataItem)}
LeftIcon={getIcon(hiddenFieldMetadataItem.icon)}
text={hiddenFieldMetadataItem.label}
/>
))}
</DropdownMenuItemsContainer>

View File

@ -1,11 +0,0 @@
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
import { SortDefinition } from '../types/SortDefinition';
export const availableSortDefinitionsComponentState = createComponentStateV2<
SortDefinition[]
>({
key: 'availableSortDefinitionsComponentState',
defaultValue: [],
componentInstanceContext: ObjectSortDropdownComponentInstanceContext,
});

View File

@ -1,5 +0,0 @@
export type SortDefinition = {
fieldMetadataId: string;
label: string;
iconName: string;
};

View File

@ -1,15 +1,8 @@
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy';
import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
const sortDefinition: SortDefinition = {
fieldMetadataId: 'id',
label: 'definition label',
iconName: 'icon',
};
const objectMetadataItem: ObjectMetadataItem = {
id: 'object1',
fields: [],
@ -47,7 +40,6 @@ describe('turnSortsIntoOrderBy', () => {
id: 'id',
fieldMetadataId: 'field1',
direction: 'asc',
definition: sortDefinition,
},
];
const fields = [{ id: 'field1', name: 'field1' }] as FieldMetadataItem[];
@ -62,13 +54,11 @@ describe('turnSortsIntoOrderBy', () => {
id: 'id',
fieldMetadataId: 'field1',
direction: 'asc',
definition: sortDefinition,
},
{
id: 'id',
fieldMetadataId: 'field2',
direction: 'desc',
definition: sortDefinition,
},
];
const fields = [
@ -90,7 +80,6 @@ describe('turnSortsIntoOrderBy', () => {
id: 'id',
fieldMetadataId: 'invalidField',
direction: 'asc',
definition: sortDefinition,
},
];
expect(turnSortsIntoOrderBy(objectMetadataItem, sorts)).toEqual([
@ -104,7 +93,6 @@ describe('turnSortsIntoOrderBy', () => {
id: 'id',
fieldMetadataId: 'invalidField',
direction: 'asc',
definition: sortDefinition,
},
];
expect(

View File

@ -4,7 +4,6 @@ import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/s
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { sortRecordsByPosition } from '@/object-record/utils/sortRecordsByPosition';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { isDefined } from 'twenty-shared';
@ -49,7 +48,6 @@ export const useSetRecordIdsForColumn = (recordBoardId?: string) => {
(record) =>
record[recordGroupFieldMetadata.name] === recordGroup?.value,
)
.sort(sortRecordsByPosition)
.map((record) => record.id);
if (!isDeeplyEqual(existingRecordGroupRowIds, recordGroupRowIds)) {

View File

@ -23,27 +23,21 @@ export const RecordIndexViewBarEffect = ({
objectNameSingular,
});
const { columnDefinitions, sortDefinitions } =
const { columnDefinitions } =
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
const {
setViewObjectMetadataId,
setAvailableSortDefinitions,
setAvailableFieldDefinitions,
} = useInitViewBar(viewBarId);
const { setViewObjectMetadataId, setAvailableFieldDefinitions } =
useInitViewBar(viewBarId);
useEffect(() => {
if (isUndefinedOrNull(objectMetadataItem)) {
return;
}
setViewObjectMetadataId?.(objectMetadataItem.id);
setAvailableSortDefinitions?.(sortDefinitions);
setAvailableFieldDefinitions?.(columnDefinitions);
}, [
setViewObjectMetadataId,
objectMetadataItem,
setAvailableSortDefinitions,
sortDefinitions,
setAvailableFieldDefinitions,
columnDefinitions,
]);

View File

@ -8,7 +8,6 @@ import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useReco
import { tableViewFilterGroupsComponentState } from '@/object-record/record-table/states/tableViewFilterGroupsComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
export const useFindManyRecordIndexTableParams = (
@ -33,14 +32,9 @@ export const useFindManyRecordIndexTableParams = (
const { currentViewWithCombinedFiltersAndSorts } =
useGetCurrentView(recordTableId);
const availableSortDefinitions = useRecoilComponentValueV2(
availableSortDefinitionsComponentState,
recordTableId,
);
const viewSorts = currentViewWithCombinedFiltersAndSorts?.viewSorts ?? [];
const sorts = mapViewSortsToSorts(viewSorts, availableSortDefinitions);
const sorts = mapViewSortsToSorts(viewSorts);
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,

View File

@ -40,11 +40,6 @@ export const useHandleToggleColumnSort = ({
const newSort: RecordSort = {
id: v4(),
fieldMetadataId,
definition: {
fieldMetadataId,
label: correspondingColumnDefinition.label,
iconName: correspondingColumnDefinition.iconName,
},
direction: 'asc',
};

View File

@ -14,7 +14,6 @@ import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/s
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
import { isDefined } from 'twenty-shared';
@ -52,11 +51,7 @@ export const useLoadRecordIndexBoardColumn = ({
const viewsorts = currentViewWithCombinedFiltersAndSorts?.viewSorts ?? [];
const sortDefinitions = useRecoilComponentValueV2(
availableSortDefinitionsComponentState,
);
const sorts = mapViewSortsToSorts(viewsorts, sortDefinitions);
const sorts = mapViewSortsToSorts(viewsorts);
const { filterValueDependencies } = useFilterValueDependencies();

View File

@ -1,8 +1,8 @@
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector';
import { availableFieldMetadataItemsForSortFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForSortFamilySelector';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
import { formatFieldMetadataItemsAsSortDefinitions } from '@/object-metadata/utils/formatFieldMetadataItemsAsSortDefinitions';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { useSetRecordGroup } from '@/object-record/record-group/hooks/useSetRecordGroup';
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
@ -81,9 +81,13 @@ export const useLoadRecordIndexStates = () => {
)
.getValue();
const sortDefinitions = formatFieldMetadataItemsAsSortDefinitions({
fields: activeFieldMetadataItems,
});
const sortableFieldMetadataItems = snapshot
.getLoadable(
availableFieldMetadataItemsForSortFamilySelector({
objectMetadataItemId: objectMetadataItem.id,
}),
)
.getValue();
const columnDefinitions: ColumnDefinition<FieldMetadata>[] =
activeFieldMetadataItems
@ -101,9 +105,12 @@ export const useLoadRecordIndexStates = () => {
(fieldMetadataItem) =>
fieldMetadataItem.id === column.fieldMetadataId,
);
const existsInSortDefinitions = sortDefinitions.some(
(sort) => sort.fieldMetadataId === column.fieldMetadataId,
const existsInSortDefinitions = sortableFieldMetadataItems.some(
(fieldMetadataItem) =>
fieldMetadataItem.id === column.fieldMetadataId,
);
return {
...column,
isFilterable: existsInFilterDefinitions,
@ -228,23 +235,13 @@ export const useLoadRecordIndexStates = () => {
),
}));
const activeFieldMetadataItems = objectMetadataItem.fields.filter(
({ isActive, isSystem }) => isActive && !isSystem,
);
const sortDefinitions = formatFieldMetadataItemsAsSortDefinitions({
fields: activeFieldMetadataItems,
});
set(
tableSortsComponentState.atomFamily({
instanceId: recordIndexId,
}),
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
);
setRecordIndexSorts(
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
mapViewSortsToSorts(view.viewSorts),
);
setRecordIndexSorts(mapViewSortsToSorts(view.viewSorts));
setRecordIndexViewType(view.type);
setRecordIndexOpenRecordIn(view.openRecordIn);
setRecordIndexViewKanbanFieldMetadataIdState(

View File

@ -1,15 +0,0 @@
import { availableFieldMetadataItemsForSortFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForSortFamilySelector';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { useRecoilValue } from 'recoil';
export const useSortableFieldMetadataItemsInRecordIndexContext = () => {
const { objectMetadataItem } = useRecordIndexContextOrThrow();
const sortableFieldMetadataItems = useRecoilValue(
availableFieldMetadataItemsForSortFamilySelector({
objectMetadataItemId: objectMetadataItem.id,
}),
);
return { sortableFieldMetadataItems };
};

View File

@ -1,9 +1,7 @@
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
import { RecordSortDirection } from '@/object-record/record-sort/types/RecordSortDirection';
export type RecordSort = {
id: string;
fieldMetadataId: string;
direction: RecordSortDirection;
definition: SortDefinition;
};