306 implement multi relation picker for person and try to factorize relation picker (#319)

* Removed useless folder

* First working version

* Refactored MultipleEntitySelect and splitted into 2 components

* Added TODO

* Removed useless Query

* Fixed refetch

* Fixed naming

* Fix tests

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Lucas Bordeau
2023-06-17 10:13:30 +02:00
committed by GitHub
parent 7f25f16766
commit d13ceb98fa
26 changed files with 604 additions and 369 deletions

View File

@ -17,6 +17,4 @@ export const DropdownMenu = styled.div`
height: fit-content;
width: 200px;
z-index: ${(props) => props.theme.lastLayerZIndex};
`;

View File

@ -0,0 +1,145 @@
import * as Apollo from '@apollo/client';
import {
EntitiesForMultipleEntitySelect,
EntityForSelect,
} from '@/comments/components/MultipleEntitySelect';
import {
Exact,
InputMaybe,
QueryMode,
Scalars,
SortOrder,
} from '~/generated/graphql';
type SelectStringKeys<T> = NonNullable<
{
[K in keyof T]: T[K] extends string ? K : never;
}[keyof T]
>;
type ExtractEntityTypeFromQueryResponse<T> = T extends {
searchResults: Array<infer U>;
}
? U
: never;
const DEFAULT_SEARCH_REQUEST_LIMIT = 10;
export function useFilteredSearchEntityQuery<
EntityType extends ExtractEntityTypeFromQueryResponse<QueryResponseForExtract> & {
id: string;
},
EntityStringField extends SelectStringKeys<EntityType>,
OrderByField extends EntityStringField,
SearchOnField extends EntityStringField,
QueryResponseForExtract,
QueryResponse extends {
searchResults: EntityType[];
},
EntityWhereInput,
EntityOrderByWithRelationInput,
QueryVariables extends Exact<{
where?: InputMaybe<EntityWhereInput>;
limit?: InputMaybe<Scalars['Int']>;
orderBy?: InputMaybe<
Array<EntityOrderByWithRelationInput> | EntityOrderByWithRelationInput
>;
}>,
>({
queryHook,
searchOnFields,
orderByField,
sortOrder = SortOrder.Asc,
selectedIds,
mappingFunction,
limit,
searchFilter, // TODO: put in a scoped recoil state
}: {
queryHook: (
queryOptions?: Apollo.QueryHookOptions<
QueryResponseForExtract,
QueryVariables
>,
) => Apollo.QueryResult<QueryResponse, QueryVariables>;
searchOnFields: SearchOnField[];
orderByField: OrderByField;
sortOrder?: SortOrder;
selectedIds: string[];
mappingFunction: (entity: EntityType) => EntityForSelect;
limit?: number;
searchFilter: string;
}): EntitiesForMultipleEntitySelect {
const { data: selectedEntitiesData } = queryHook({
variables: {
where: {
id: {
in: selectedIds,
},
},
orderBy: {
[orderByField]: sortOrder,
},
} as QueryVariables,
});
const searchFilterByField = searchOnFields.map((field) => ({
[field]: {
contains: `%${searchFilter}%`,
mode: QueryMode.Insensitive,
},
}));
const { data: filteredSelectedEntitiesData } = queryHook({
variables: {
where: {
AND: [
{
OR: searchFilterByField,
},
{
id: {
in: selectedIds,
},
},
],
},
orderBy: {
[orderByField]: sortOrder,
},
} as QueryVariables,
});
const { data: entitiesToSelectData } = queryHook({
variables: {
where: {
AND: [
{
OR: searchFilterByField,
},
{
id: {
notIn: selectedIds,
},
},
],
},
limit: limit ?? DEFAULT_SEARCH_REQUEST_LIMIT,
orderBy: {
[orderByField]: sortOrder,
},
} as QueryVariables,
});
return {
selectedEntities: (selectedEntitiesData?.searchResults ?? []).map(
mappingFunction,
),
filteredSelectedEntities: (
filteredSelectedEntitiesData?.searchResults ?? []
).map(mappingFunction),
entitiesToSelect: (entitiesToSelectData?.searchResults ?? []).map(
mappingFunction,
),
};
}

View File

@ -1,7 +1,7 @@
import { useRecoilState } from 'recoil';
import { RightDrawerComments } from '@/comments/components/comments/RightDrawerComments';
import { RightDrawerCreateCommentThread } from '@/comments/components/comments/RightDrawerCreateCommentThread';
import { RightDrawerComments } from '@/comments/components/RightDrawerComments';
import { RightDrawerCreateCommentThread } from '@/comments/components/RightDrawerCreateCommentThread';
import { isDefined } from '@/utils/type-guards/isDefined';
import { rightDrawerPageState } from '../states/rightDrawerPageState';

View File

@ -0,0 +1,10 @@
import { EntityForSelect } from '@/comments/components/MultipleEntitySelect';
export function flatMapAndSortEntityForSelectArrayOfArrayByName(
entityForSelectArray: EntityForSelect[][],
) {
const sortByName = (a: EntityForSelect, b: EntityForSelect) =>
a.name.localeCompare(b.name);
return entityForSelectArray.flatMap((entity) => entity).sort(sortByName);
}