Refactor Filters and Search (#119)

This commit is contained in:
Charles Bochet
2023-05-17 13:25:33 +02:00
committed by GitHub
parent 96e3f2c7ea
commit 499752ed6b
25 changed files with 466 additions and 804 deletions
@@ -2,8 +2,7 @@ import { ChangeEvent, ComponentType, useState } from 'react';
import EditableCellWrapper from './EditableCellWrapper';
import styled from '@emotion/styled';
import { useSearch } from '../../../services/search/search';
import { FilterType } from '../table-header/interface';
import { People_Bool_Exp } from '../../../generated/graphql';
import { SearchConfigType, SearchableType } from '../table-header/interface';
const StyledEditModeContainer = styled.div`
width: 200px;
@@ -48,10 +47,13 @@ const StyledEditModeResultItem = styled.div`
cursor: pointer;
`;
export type EditableRelationProps<RelationType, ChipComponentPropsType> = {
export type EditableRelationProps<
RelationType extends SearchableType,
ChipComponentPropsType,
> = {
relation?: RelationType | null;
searchPlaceholder: string;
searchFilter: FilterType<People_Bool_Exp>;
searchConfig: SearchConfigType<RelationType>;
changeHandler: (relation: RelationType) => void;
editModeHorizontalAlign?: 'left' | 'right';
ChipComponent: ComponentType<ChipComponentPropsType>;
@@ -60,10 +62,13 @@ export type EditableRelationProps<RelationType, ChipComponentPropsType> = {
) => ChipComponentPropsType & JSX.IntrinsicAttributes;
};
function EditableRelation<RelationType, ChipComponentPropsType>({
function EditableRelation<
RelationType extends SearchableType,
ChipComponentPropsType,
>({
relation,
searchPlaceholder,
searchFilter,
searchConfig,
changeHandler,
editModeHorizontalAlign,
ChipComponent,
@@ -72,7 +77,8 @@ function EditableRelation<RelationType, ChipComponentPropsType>({
const [selectedRelation, setSelectedRelation] = useState(relation);
const [isEditMode, setIsEditMode] = useState(false);
const [filterSearchResults, setSearchInput, setFilterSearch] = useSearch();
const [filterSearchResults, setSearchInput, setFilterSearch] =
useSearch<RelationType>();
return (
<EditableCellWrapper
@@ -97,16 +103,16 @@ function EditableRelation<RelationType, ChipComponentPropsType>({
<StyledEditModeSearchInput
placeholder={searchPlaceholder}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
setFilterSearch(searchFilter);
setFilterSearch(searchConfig);
setSearchInput(event.target.value);
}}
/>
</StyledEditModeSearchContainer>
<StyledEditModeResults>
{filterSearchResults.results &&
filterSearchResults.results.map((result) => (
filterSearchResults.results.map((result, index) => (
<StyledEditModeResultItem
key={result.value.id}
key={index}
onClick={() => {
setSelectedRelation(result.value);
changeHandler(result.value);
@@ -3,16 +3,11 @@ import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes';
import { StoryFn } from '@storybook/react';
import CompanyChip, { CompanyChipPropsType } from '../../../chips/CompanyChip';
import {
GraphqlQueryCompany,
PartialCompany,
} from '../../../../interfaces/company.interface';
import { Company, mapCompany } from '../../../../interfaces/company.interface';
import { MockedProvider } from '@apollo/client/testing';
import { SEARCH_COMPANY_QUERY } from '../../../../services/search/search';
import styled from '@emotion/styled';
import { People_Bool_Exp } from '../../../../generated/graphql';
import { FilterType } from '../../table-header/interface';
import { FaBuilding } from 'react-icons/fa';
import { SearchConfigType } from '../../table-header/interface';
const component = {
title: 'editable-cell/EditableRelation',
@@ -58,13 +53,13 @@ const mocks = [
];
const Template: StoryFn<
typeof EditableRelation<PartialCompany, CompanyChipPropsType>
> = (args: EditableRelationProps<PartialCompany, CompanyChipPropsType>) => {
typeof EditableRelation<Company, CompanyChipPropsType>
> = (args: EditableRelationProps<Company, CompanyChipPropsType>) => {
return (
<MockedProvider mocks={mocks}>
<ThemeProvider theme={lightTheme}>
<StyledParent data-testid="content-editable-parent">
<EditableRelation<PartialCompany, CompanyChipPropsType> {...args} />
<EditableRelation<Company, CompanyChipPropsType> {...args} />
</StyledParent>
</ThemeProvider>
</MockedProvider>
@@ -77,36 +72,25 @@ EditableRelationStory.args = {
id: '123',
name: 'Heroku',
domain_name: 'heroku.com',
} as PartialCompany,
} as Company,
ChipComponent: CompanyChip,
chipComponentPropsMapper: (company: PartialCompany): CompanyChipPropsType => {
chipComponentPropsMapper: (company: Company): CompanyChipPropsType => {
return {
name: company.name,
picture: `https://www.google.com/s2/favicons?domain=${company.domain_name}&sz=256`,
};
},
changeHandler: (relation: PartialCompany) => {
changeHandler: (relation: Company) => {
console.log('changed', relation);
},
searchFilter: {
key: 'company_name',
label: 'Company',
icon: <FaBuilding />,
whereTemplate: () => {
return {};
},
searchQuery: SEARCH_COMPANY_QUERY,
searchTemplate: (searchInput: string) => ({
searchConfig: {
query: SEARCH_COMPANY_QUERY,
template: (searchInput: string) => ({
name: { _ilike: `%${searchInput}%` },
}),
searchResultMapper: (company: GraphqlQueryCompany) => ({
displayValue: company.name,
value: {
id: company.id,
name: company.name,
domain_name: company.domain_name,
},
resultMapper: (company) => ({
render: (company) => company.name,
value: mapCompany(company),
}),
operands: [],
} satisfies FilterType<People_Bool_Exp>,
} satisfies SearchConfigType<Company>,
};
@@ -2,17 +2,17 @@ import { fireEvent, render, waitFor } from '@testing-library/react';
import { EditableRelationStory } from '../__stories__/EditableRelation.stories';
import { CompanyChipPropsType } from '../../../chips/CompanyChip';
import { PartialCompany } from '../../../../interfaces/company.interface';
import { EditableRelationProps } from '../EditableRelation';
import { act } from 'react-dom/test-utils';
import { Company } from '../../../../interfaces/company.interface';
it('Checks the EditableRelation editing event bubbles up', async () => {
const func = jest.fn(() => null);
const { getByTestId, getByText } = render(
<EditableRelationStory
{...(EditableRelationStory.args as EditableRelationProps<
PartialCompany,
Company,
CompanyChipPropsType
>)}
changeHandler={func}
@@ -49,10 +49,16 @@ it('Checks the EditableRelation editing event bubbles up', async () => {
});
await waitFor(() => {
expect(func).toBeCalledWith({
domain_name: 'abnb.com',
id: 'abnb',
name: 'Airbnb',
});
expect(func).toBeCalledWith(
expect.objectContaining({
accountOwner: null,
address: undefined,
domain_name: 'abnb.com',
employees: undefined,
id: 'abnb',
name: 'Airbnb',
opportunities: [],
}),
);
});
});