diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx index fffa5f2763a0..5830df05c91b 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx @@ -4,16 +4,18 @@ import { StyledObjectFieldTableRow, } from '@/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow'; import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-details/states/settingsObjectFieldsFamilyState'; +import { TextInput } from '@/ui/input/components/TextInput'; import { SortableTableHeader } from '@/ui/layout/table/components/SortableTableHeader'; import { Table } from '@/ui/layout/table/components/Table'; import { TableHeader } from '@/ui/layout/table/components/TableHeader'; import { TableSection } from '@/ui/layout/table/components/TableSection'; import { useSortedArray } from '@/ui/layout/table/hooks/useSortedArray'; import { TableMetadata } from '@/ui/layout/table/types/TableMetadata'; +import styled from '@emotion/styled'; import { isNonEmptyArray } from '@sniptt/guards'; - -import { useEffect, useMemo } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { useRecoilState } from 'recoil'; +import { IconSearch } from 'twenty-ui'; import { useMapFieldMetadataItemToSettingsObjectDetailTableItem } from '~/pages/settings/data-model/hooks/useMapFieldMetadataItemToSettingsObjectDetailTableItem'; import { SettingsObjectDetailTableItem } from '~/pages/settings/data-model/types/SettingsObjectDetailTableItem'; @@ -75,6 +77,9 @@ const SETTINGS_OBJECT_DETAIL_TABLE_METADATA_CUSTOM: TableMetadata { + const [searchTerm, setSearchTerm] = useState(''); + const tableMetadata = objectMetadataItem.isCustom ? SETTINGS_OBJECT_DETAIL_TABLE_METADATA_CUSTOM : SETTINGS_OBJECT_DETAIL_TABLE_METADATA_STANDARD; @@ -144,51 +151,75 @@ export const SettingsObjectFieldTable = ({ tableMetadata, ); + const filteredActiveItems = useMemo( + () => + sortedActiveObjectSettingsDetailItems.filter( + (item) => + item.label.toLowerCase().includes(searchTerm.toLowerCase()) || + item.dataType.toLowerCase().includes(searchTerm.toLowerCase()), + ), + [sortedActiveObjectSettingsDetailItems, searchTerm], + ); + + const filteredDisabledItems = useMemo( + () => + sortedDisabledObjectSettingsDetailItems.filter( + (item) => + item.label.toLowerCase().includes(searchTerm.toLowerCase()) || + item.dataType.toLowerCase().includes(searchTerm.toLowerCase()), + ), + [sortedDisabledObjectSettingsDetailItems, searchTerm], + ); + return ( - - - {tableMetadata.fields.map((item) => ( - - ))} - - - {isNonEmptyArray(sortedActiveObjectSettingsDetailItems) && ( - - {sortedActiveObjectSettingsDetailItems.map( - (objectSettingsDetailItem) => ( + <> + +
+ + {tableMetadata.fields.map((item) => ( + + ))} + + + {isNonEmptyArray(filteredActiveItems) && ( + + {filteredActiveItems.map((objectSettingsDetailItem) => ( - ), - )} - - )} - {isNonEmptyArray(sortedDisabledObjectSettingsDetailItems) && ( - - {sortedDisabledObjectSettingsDetailItems.map( - (objectSettingsDetailItem) => ( + ))} + + )} + {isNonEmptyArray(filteredDisabledItems) && ( + + {filteredDisabledItems.map((objectSettingsDetailItem) => ( - ), - )} - - )} -
+ ))} + + )} + + ); }; diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx index 567364f892de..3c13d55167db 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx @@ -1,6 +1,12 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; -import { H2Title, IconChevronRight, IconHierarchy2, IconPlus } from 'twenty-ui'; +import { + H2Title, + IconChevronRight, + IconHierarchy2, + IconPlus, + IconSearch, +} from 'twenty-ui'; import { useDeleteOneObjectMetadataItem } from '@/object-metadata/hooks/useDeleteOneObjectMetadataItem'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; @@ -18,6 +24,7 @@ import { getObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLab import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { SettingsPath } from '@/types/SettingsPath'; import { Button } from '@/ui/input/button/components/Button'; +import { TextInput } from '@/ui/input/components/TextInput'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; import { SortableTableHeader } from '@/ui/layout/table/components/SortableTableHeader'; @@ -27,17 +34,19 @@ import { TableSection } from '@/ui/layout/table/components/TableSection'; import { useSortedArray } from '@/ui/layout/table/hooks/useSortedArray'; import { UndecoratedLink } from '@/ui/navigation/link/components/UndecoratedLink'; import { isNonEmptyArray } from '@sniptt/guards'; -import { useMemo } from 'react'; +import { useMemo, useState } from 'react'; import { SETTINGS_OBJECT_TABLE_METADATA } from '~/pages/settings/data-model/constants/SettingsObjectTableMetadata'; import { SettingsObjectTableItem } from '~/pages/settings/data-model/types/SettingsObjectTableItem'; const StyledIconChevronRight = styled(IconChevronRight)` color: ${({ theme }) => theme.font.color.tertiary}; `; - +const StyledSearchInput = styled(TextInput)` + width: 100%; +`; export const SettingsObjects = () => { const theme = useTheme(); - + const [searchTerm, setSearchTerm] = useState(''); const { deleteOneObjectMetadataItem } = useDeleteOneObjectMetadataItem(); const { updateOneObjectMetadataItem } = useUpdateOneObjectMetadataItem(); @@ -102,7 +111,25 @@ export const SettingsObjects = () => { inactiveObjectSettingsArray, SETTINGS_OBJECT_TABLE_METADATA, ); + const filteredActiveObjectSettingsItems = useMemo( + () => + sortedActiveObjectSettingsItems.filter( + (item) => + item.labelPlural.toLowerCase().includes(searchTerm.toLowerCase()) || + item.objectTypeLabel.toLowerCase().includes(searchTerm.toLowerCase()), + ), + [sortedActiveObjectSettingsItems, searchTerm], + ); + const filteredInactiveObjectSettingsItems = useMemo( + () => + sortedInactiveObjectSettingsItems.filter( + (item) => + item.labelPlural.toLowerCase().includes(searchTerm.toLowerCase()) || + item.objectTypeLabel.toLowerCase().includes(searchTerm.toLowerCase()), + ), + [sortedInactiveObjectSettingsItems, searchTerm], + ); return ( {
+ + + {SETTINGS_OBJECT_TABLE_METADATA.fields.map( @@ -141,27 +176,31 @@ export const SettingsObjects = () => { {isNonEmptyArray(sortedActiveObjectSettingsItems) && ( - {sortedActiveObjectSettingsItems.map((objectSettingsItem) => ( - - } - link={`/settings/objects/${getObjectSlug( - objectSettingsItem.objectMetadataItem, - )}`} - /> - ))} + {filteredActiveObjectSettingsItems.map( + (objectSettingsItem) => ( + + } + link={`/settings/objects/${getObjectSlug( + objectSettingsItem.objectMetadataItem, + )}`} + /> + ), + )} )} {isNonEmptyArray(inactiveObjectMetadataItems) && ( - {sortedInactiveObjectSettingsItems.map( + {filteredInactiveObjectSettingsItems.map( (objectSettingsItem) => (