Skip to content

Commit

Permalink
Added ability to search objects and fields (#6775)
Browse files Browse the repository at this point in the history
  • Loading branch information
ehconitin authored Aug 29, 2024
1 parent 9fafb2c commit ebfdc6c
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -75,6 +77,9 @@ const SETTINGS_OBJECT_DETAIL_TABLE_METADATA_CUSTOM: TableMetadata<SettingsObject
},
};

const StyledSearchInput = styled(TextInput)`
width: 100%;
`;
export type SettingsObjectFieldTableProps = {
objectMetadataItem: ObjectMetadataItem;
mode: 'view' | 'new-field';
Expand All @@ -85,6 +90,8 @@ export const SettingsObjectFieldTable = ({
objectMetadataItem,
mode,
}: SettingsObjectFieldTableProps) => {
const [searchTerm, setSearchTerm] = useState('');

const tableMetadata = objectMetadataItem.isCustom
? SETTINGS_OBJECT_DETAIL_TABLE_METADATA_CUSTOM
: SETTINGS_OBJECT_DETAIL_TABLE_METADATA_STANDARD;
Expand Down Expand Up @@ -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 (
<Table>
<StyledObjectFieldTableRow>
{tableMetadata.fields.map((item) => (
<SortableTableHeader
key={item.fieldName}
fieldName={item.fieldName}
label={item.fieldLabel}
tableId={tableMetadata.tableId}
initialSort={tableMetadata.initialSort}
/>
))}
<TableHeader></TableHeader>
</StyledObjectFieldTableRow>
{isNonEmptyArray(sortedActiveObjectSettingsDetailItems) && (
<TableSection title="Active">
{sortedActiveObjectSettingsDetailItems.map(
(objectSettingsDetailItem) => (
<>
<StyledSearchInput
LeftIcon={IconSearch}
placeholder="Search a field..."
value={searchTerm}
onChange={setSearchTerm}
/>
<Table>
<StyledObjectFieldTableRow>
{tableMetadata.fields.map((item) => (
<SortableTableHeader
key={item.fieldName}
fieldName={item.fieldName}
label={item.fieldLabel}
tableId={tableMetadata.tableId}
initialSort={tableMetadata.initialSort}
/>
))}
<TableHeader></TableHeader>
</StyledObjectFieldTableRow>
{isNonEmptyArray(filteredActiveItems) && (
<TableSection title="Active">
{filteredActiveItems.map((objectSettingsDetailItem) => (
<SettingsObjectFieldItemTableRow
key={objectSettingsDetailItem.fieldMetadataItem.id}
settingsObjectDetailTableItem={objectSettingsDetailItem}
status="active"
mode={mode}
/>
),
)}
</TableSection>
)}
{isNonEmptyArray(sortedDisabledObjectSettingsDetailItems) && (
<TableSection
isInitiallyExpanded={mode === 'new-field' ? true : false}
title="Inactive"
>
{sortedDisabledObjectSettingsDetailItems.map(
(objectSettingsDetailItem) => (
))}
</TableSection>
)}
{isNonEmptyArray(filteredDisabledItems) && (
<TableSection
isInitiallyExpanded={mode === 'new-field' ? true : false}
title="Inactive"
>
{filteredDisabledItems.map((objectSettingsDetailItem) => (
<SettingsObjectFieldItemTableRow
key={objectSettingsDetailItem.fieldMetadataItem.id}
settingsObjectDetailTableItem={objectSettingsDetailItem}
status="disabled"
mode={mode}
/>
),
)}
</TableSection>
)}
</Table>
))}
</TableSection>
)}
</Table>
</>
);
};
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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';
Expand All @@ -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();

Expand Down Expand Up @@ -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 (
<SubMenuTopBarContainer
Icon={IconHierarchy2}
Expand All @@ -123,6 +150,14 @@ export const SettingsObjects = () => {
<SettingsObjectCoverImage />
<Section>
<H2Title title="Existing objects" />

<StyledSearchInput
LeftIcon={IconSearch}
placeholder="Search an object..."
value={searchTerm}
onChange={setSearchTerm}
/>

<Table>
<StyledObjectTableRow>
{SETTINGS_OBJECT_TABLE_METADATA.fields.map(
Expand All @@ -141,27 +176,31 @@ export const SettingsObjects = () => {
</StyledObjectTableRow>
{isNonEmptyArray(sortedActiveObjectSettingsItems) && (
<TableSection title="Active">
{sortedActiveObjectSettingsItems.map((objectSettingsItem) => (
<SettingsObjectMetadataItemTableRow
key={objectSettingsItem.objectMetadataItem.namePlural}
objectMetadataItem={objectSettingsItem.objectMetadataItem}
totalObjectCount={objectSettingsItem.totalObjectCount}
action={
<StyledIconChevronRight
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
/>
}
link={`/settings/objects/${getObjectSlug(
objectSettingsItem.objectMetadataItem,
)}`}
/>
))}
{filteredActiveObjectSettingsItems.map(
(objectSettingsItem) => (
<SettingsObjectMetadataItemTableRow
key={objectSettingsItem.objectMetadataItem.namePlural}
objectMetadataItem={
objectSettingsItem.objectMetadataItem
}
totalObjectCount={objectSettingsItem.totalObjectCount}
action={
<StyledIconChevronRight
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
/>
}
link={`/settings/objects/${getObjectSlug(
objectSettingsItem.objectMetadataItem,
)}`}
/>
),
)}
</TableSection>
)}
{isNonEmptyArray(inactiveObjectMetadataItems) && (
<TableSection title="Inactive">
{sortedInactiveObjectSettingsItems.map(
{filteredInactiveObjectSettingsItems.map(
(objectSettingsItem) => (
<SettingsObjectMetadataItemTableRow
key={objectSettingsItem.objectMetadataItem.namePlural}
Expand Down

0 comments on commit ebfdc6c

Please sign in to comment.