Relation picker module (#335)

- Created a relation picker module
- Added a CustomeEntityForSelect type
This commit is contained in:
Lucas Bordeau 2023-06-20 11:06:53 +02:00 committed by GitHub
parent c120903a45
commit e2eb40c1ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 64 additions and 50 deletions

View File

@ -14,7 +14,7 @@ import { IconArrowUpRight } from '@tabler/icons-react';
import { CommentThreadForDrawer } from '@/comments/types/CommentThreadForDrawer';
import CompanyChip from '@/companies/components/CompanyChip';
import { PersonChip } from '@/people/components/PersonChip';
import { useFilteredSearchEntityQuery } from '@/ui/hooks/menu/useFilteredSearchEntityQuery';
import { useFilteredSearchEntityQuery } from '@/relation-picker/hooks/useFilteredSearchEntityQuery';
import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef';
import { flatMapAndSortEntityForSelectArrayOfArrayByName } from '@/ui/utils/flatMapAndSortEntityForSelectArrayByName';
import { getLogoUrlFromDomainName } from '@/utils/utils';
@ -24,9 +24,9 @@ import {
useSearchPeopleQuery,
} from '~/generated/graphql';
import { MultipleEntitySelect } from '../../relation-picker/components/MultipleEntitySelect';
import { useHandleCheckableCommentThreadTargetChange } from '../hooks/useHandleCheckableCommentThreadTargetChange';
import { MultipleEntitySelect } from './MultipleEntitySelect';
import { CommentableEntityForSelect } from '../types/CommentableEntityForSelect';
type OwnProps = {
commentThread: CommentThreadForDrawer;
@ -112,12 +112,13 @@ export function CommentThreadRelationPicker({ commentThread }: OwnProps) {
searchOnFields: ['firstname', 'lastname'],
orderByField: 'lastname',
selectedIds: peopleIds,
mappingFunction: (entity) => ({
id: entity.id,
entityType: CommentableType.Person,
name: `${entity.firstname} ${entity.lastname}`,
avatarType: 'rounded',
}),
mappingFunction: (entity) =>
({
id: entity.id,
entityType: CommentableType.Person,
name: `${entity.firstname} ${entity.lastname}`,
avatarType: 'rounded',
} as CommentableEntityForSelect),
searchFilter,
});
@ -126,13 +127,14 @@ export function CommentThreadRelationPicker({ commentThread }: OwnProps) {
searchOnFields: ['name'],
orderByField: 'name',
selectedIds: companyIds,
mappingFunction: (company) => ({
id: company.id,
entityType: CommentableType.Company,
name: company.name,
avatarUrl: getLogoUrlFromDomainName(company.domainName),
avatarType: 'squared',
}),
mappingFunction: (company) =>
({
id: company.id,
entityType: CommentableType.Company,
name: company.name,
avatarUrl: getLogoUrlFromDomainName(company.domainName),
avatarType: 'squared',
} as CommentableEntityForSelect),
searchFilter,
});

View File

@ -8,8 +8,8 @@ import {
useRemoveCommentThreadTargetOnCommentThreadMutation,
} from '~/generated/graphql';
import { EntityForSelect } from '../components/MultipleEntitySelect';
import { GET_COMMENT_THREADS_BY_TARGETS } from '../services';
import { CommentableEntityForSelect } from '../types/CommentableEntityForSelect';
import { CommentThreadForDrawer } from '../types/CommentThreadForDrawer';
export function useHandleCheckableCommentThreadTargetChange({
@ -37,7 +37,7 @@ export function useHandleCheckableCommentThreadTargetChange({
return function handleCheckItemChange(
newCheckedValue: boolean,
entity: EntityForSelect,
entity: CommentableEntityForSelect,
) {
if (newCheckedValue) {
addCommentThreadTargetOnCommentThread({

View File

@ -1,6 +1,6 @@
import { CommentableType } from '~/generated/graphql';
export type CommentableEntity = {
type: CommentableType;
id: string;
type: CommentableType;
};

View File

@ -0,0 +1,6 @@
import { EntityForSelect } from '@/relation-picker/types/EntityForSelect';
import { CommentableType } from '~/generated/graphql';
export type CommentableEntityForSelect = EntityForSelect & {
entityType: CommentableType;
};

View File

@ -1,42 +1,36 @@
import { debounce } from 'lodash';
import { EntityForSelect } from '@/relation-picker/types/EntityForSelect';
import { DropdownMenu } from '@/ui/components/menu/DropdownMenu';
import { DropdownMenuCheckableItem } from '@/ui/components/menu/DropdownMenuCheckableItem';
import { DropdownMenuItem } from '@/ui/components/menu/DropdownMenuItem';
import { DropdownMenuItemContainer } from '@/ui/components/menu/DropdownMenuItemContainer';
import { DropdownMenuSearch } from '@/ui/components/menu/DropdownMenuSearch';
import { DropdownMenuSeparator } from '@/ui/components/menu/DropdownMenuSeparator';
import { Avatar, AvatarType } from '@/users/components/Avatar';
import { CommentableType } from '~/generated/graphql';
import { Avatar } from '@/users/components/Avatar';
export type EntitiesForMultipleEntitySelect = {
selectedEntities: EntityForSelect[];
filteredSelectedEntities: EntityForSelect[];
entitiesToSelect: EntityForSelect[];
export type EntitiesForMultipleEntitySelect<
CustomEntityForSelect extends EntityForSelect,
> = {
selectedEntities: CustomEntityForSelect[];
filteredSelectedEntities: CustomEntityForSelect[];
entitiesToSelect: CustomEntityForSelect[];
};
export type EntityTypeForSelect = CommentableType; // TODO: derivate from all usable entity types
export type EntityForSelect = {
id: string;
entityType: EntityTypeForSelect;
name: string;
avatarUrl?: string;
avatarType?: AvatarType;
};
export function MultipleEntitySelect({
export function MultipleEntitySelect<
CustomEntityForSelect extends EntityForSelect,
>({
entities,
onItemCheckChange,
onSearchFilterChange,
searchFilter,
}: {
entities: EntitiesForMultipleEntitySelect;
entities: EntitiesForMultipleEntitySelect<CustomEntityForSelect>;
searchFilter: string;
onSearchFilterChange: (newSearchFilter: string) => void;
onItemCheckChange: (
newCheckedValue: boolean,
entity: EntityForSelect,
entity: CustomEntityForSelect,
) => void;
}) {
const debouncedSetSearchFilter = debounce(onSearchFilterChange, 100, {

View File

@ -1,9 +1,7 @@
import * as Apollo from '@apollo/client';
import {
EntitiesForMultipleEntitySelect,
EntityForSelect,
} from '@/comments/components/MultipleEntitySelect';
import { EntitiesForMultipleEntitySelect } from '@/relation-picker/components/MultipleEntitySelect';
import { EntityForSelect } from '@/relation-picker/types/EntityForSelect';
import {
Exact,
InputMaybe,
@ -46,6 +44,7 @@ export function useFilteredSearchEntityQuery<
Array<EntityOrderByWithRelationInput> | EntityOrderByWithRelationInput
>;
}>,
CustomEntityForSelect extends EntityForSelect,
>({
queryHook,
searchOnFields,
@ -66,10 +65,10 @@ export function useFilteredSearchEntityQuery<
orderByField: OrderByField;
sortOrder?: SortOrder;
selectedIds: string[];
mappingFunction: (entity: EntityType) => EntityForSelect;
mappingFunction: (entity: EntityType) => CustomEntityForSelect;
limit?: number;
searchFilter: string;
}): EntitiesForMultipleEntitySelect {
}): EntitiesForMultipleEntitySelect<CustomEntityForSelect> {
const { data: selectedEntitiesData } = queryHook({
variables: {
where: {

View File

@ -0,0 +1,11 @@
import { AvatarType } from '@/users/components/Avatar';
import { EntityTypeForSelect } from './EntityTypeForSelect';
export type EntityForSelect = {
id: string;
entityType: EntityTypeForSelect;
name: string;
avatarUrl?: string;
avatarType?: AvatarType;
};

View File

@ -0,0 +1,3 @@
import { CommentableType, PipelineProgressableType } from '~/generated/graphql';
export type EntityTypeForSelect = CommentableType | PipelineProgressableType;

View File

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