Relation picker module (#335)
- Created a relation picker module - Added a CustomeEntityForSelect type
This commit is contained in:
@ -14,7 +14,7 @@ import { IconArrowUpRight } from '@tabler/icons-react';
|
|||||||
import { CommentThreadForDrawer } from '@/comments/types/CommentThreadForDrawer';
|
import { CommentThreadForDrawer } from '@/comments/types/CommentThreadForDrawer';
|
||||||
import CompanyChip from '@/companies/components/CompanyChip';
|
import CompanyChip from '@/companies/components/CompanyChip';
|
||||||
import { PersonChip } from '@/people/components/PersonChip';
|
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 { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef';
|
||||||
import { flatMapAndSortEntityForSelectArrayOfArrayByName } from '@/ui/utils/flatMapAndSortEntityForSelectArrayByName';
|
import { flatMapAndSortEntityForSelectArrayOfArrayByName } from '@/ui/utils/flatMapAndSortEntityForSelectArrayByName';
|
||||||
import { getLogoUrlFromDomainName } from '@/utils/utils';
|
import { getLogoUrlFromDomainName } from '@/utils/utils';
|
||||||
@ -24,9 +24,9 @@ import {
|
|||||||
useSearchPeopleQuery,
|
useSearchPeopleQuery,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
|
import { MultipleEntitySelect } from '../../relation-picker/components/MultipleEntitySelect';
|
||||||
import { useHandleCheckableCommentThreadTargetChange } from '../hooks/useHandleCheckableCommentThreadTargetChange';
|
import { useHandleCheckableCommentThreadTargetChange } from '../hooks/useHandleCheckableCommentThreadTargetChange';
|
||||||
|
import { CommentableEntityForSelect } from '../types/CommentableEntityForSelect';
|
||||||
import { MultipleEntitySelect } from './MultipleEntitySelect';
|
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
commentThread: CommentThreadForDrawer;
|
commentThread: CommentThreadForDrawer;
|
||||||
@ -112,12 +112,13 @@ export function CommentThreadRelationPicker({ commentThread }: OwnProps) {
|
|||||||
searchOnFields: ['firstname', 'lastname'],
|
searchOnFields: ['firstname', 'lastname'],
|
||||||
orderByField: 'lastname',
|
orderByField: 'lastname',
|
||||||
selectedIds: peopleIds,
|
selectedIds: peopleIds,
|
||||||
mappingFunction: (entity) => ({
|
mappingFunction: (entity) =>
|
||||||
id: entity.id,
|
({
|
||||||
entityType: CommentableType.Person,
|
id: entity.id,
|
||||||
name: `${entity.firstname} ${entity.lastname}`,
|
entityType: CommentableType.Person,
|
||||||
avatarType: 'rounded',
|
name: `${entity.firstname} ${entity.lastname}`,
|
||||||
}),
|
avatarType: 'rounded',
|
||||||
|
} as CommentableEntityForSelect),
|
||||||
searchFilter,
|
searchFilter,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -126,13 +127,14 @@ export function CommentThreadRelationPicker({ commentThread }: OwnProps) {
|
|||||||
searchOnFields: ['name'],
|
searchOnFields: ['name'],
|
||||||
orderByField: 'name',
|
orderByField: 'name',
|
||||||
selectedIds: companyIds,
|
selectedIds: companyIds,
|
||||||
mappingFunction: (company) => ({
|
mappingFunction: (company) =>
|
||||||
id: company.id,
|
({
|
||||||
entityType: CommentableType.Company,
|
id: company.id,
|
||||||
name: company.name,
|
entityType: CommentableType.Company,
|
||||||
avatarUrl: getLogoUrlFromDomainName(company.domainName),
|
name: company.name,
|
||||||
avatarType: 'squared',
|
avatarUrl: getLogoUrlFromDomainName(company.domainName),
|
||||||
}),
|
avatarType: 'squared',
|
||||||
|
} as CommentableEntityForSelect),
|
||||||
searchFilter,
|
searchFilter,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,8 @@ import {
|
|||||||
useRemoveCommentThreadTargetOnCommentThreadMutation,
|
useRemoveCommentThreadTargetOnCommentThreadMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
import { EntityForSelect } from '../components/MultipleEntitySelect';
|
|
||||||
import { GET_COMMENT_THREADS_BY_TARGETS } from '../services';
|
import { GET_COMMENT_THREADS_BY_TARGETS } from '../services';
|
||||||
|
import { CommentableEntityForSelect } from '../types/CommentableEntityForSelect';
|
||||||
import { CommentThreadForDrawer } from '../types/CommentThreadForDrawer';
|
import { CommentThreadForDrawer } from '../types/CommentThreadForDrawer';
|
||||||
|
|
||||||
export function useHandleCheckableCommentThreadTargetChange({
|
export function useHandleCheckableCommentThreadTargetChange({
|
||||||
@ -37,7 +37,7 @@ export function useHandleCheckableCommentThreadTargetChange({
|
|||||||
|
|
||||||
return function handleCheckItemChange(
|
return function handleCheckItemChange(
|
||||||
newCheckedValue: boolean,
|
newCheckedValue: boolean,
|
||||||
entity: EntityForSelect,
|
entity: CommentableEntityForSelect,
|
||||||
) {
|
) {
|
||||||
if (newCheckedValue) {
|
if (newCheckedValue) {
|
||||||
addCommentThreadTargetOnCommentThread({
|
addCommentThreadTargetOnCommentThread({
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { CommentableType } from '~/generated/graphql';
|
import { CommentableType } from '~/generated/graphql';
|
||||||
|
|
||||||
export type CommentableEntity = {
|
export type CommentableEntity = {
|
||||||
type: CommentableType;
|
|
||||||
id: string;
|
id: string;
|
||||||
|
type: CommentableType;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
import { EntityForSelect } from '@/relation-picker/types/EntityForSelect';
|
||||||
|
import { CommentableType } from '~/generated/graphql';
|
||||||
|
|
||||||
|
export type CommentableEntityForSelect = EntityForSelect & {
|
||||||
|
entityType: CommentableType;
|
||||||
|
};
|
||||||
@ -1,42 +1,36 @@
|
|||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
|
||||||
|
import { EntityForSelect } from '@/relation-picker/types/EntityForSelect';
|
||||||
import { DropdownMenu } from '@/ui/components/menu/DropdownMenu';
|
import { DropdownMenu } from '@/ui/components/menu/DropdownMenu';
|
||||||
import { DropdownMenuCheckableItem } from '@/ui/components/menu/DropdownMenuCheckableItem';
|
import { DropdownMenuCheckableItem } from '@/ui/components/menu/DropdownMenuCheckableItem';
|
||||||
import { DropdownMenuItem } from '@/ui/components/menu/DropdownMenuItem';
|
import { DropdownMenuItem } from '@/ui/components/menu/DropdownMenuItem';
|
||||||
import { DropdownMenuItemContainer } from '@/ui/components/menu/DropdownMenuItemContainer';
|
import { DropdownMenuItemContainer } from '@/ui/components/menu/DropdownMenuItemContainer';
|
||||||
import { DropdownMenuSearch } from '@/ui/components/menu/DropdownMenuSearch';
|
import { DropdownMenuSearch } from '@/ui/components/menu/DropdownMenuSearch';
|
||||||
import { DropdownMenuSeparator } from '@/ui/components/menu/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/components/menu/DropdownMenuSeparator';
|
||||||
import { Avatar, AvatarType } from '@/users/components/Avatar';
|
import { Avatar } from '@/users/components/Avatar';
|
||||||
import { CommentableType } from '~/generated/graphql';
|
|
||||||
|
|
||||||
export type EntitiesForMultipleEntitySelect = {
|
export type EntitiesForMultipleEntitySelect<
|
||||||
selectedEntities: EntityForSelect[];
|
CustomEntityForSelect extends EntityForSelect,
|
||||||
filteredSelectedEntities: EntityForSelect[];
|
> = {
|
||||||
entitiesToSelect: EntityForSelect[];
|
selectedEntities: CustomEntityForSelect[];
|
||||||
|
filteredSelectedEntities: CustomEntityForSelect[];
|
||||||
|
entitiesToSelect: CustomEntityForSelect[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EntityTypeForSelect = CommentableType; // TODO: derivate from all usable entity types
|
export function MultipleEntitySelect<
|
||||||
|
CustomEntityForSelect extends EntityForSelect,
|
||||||
export type EntityForSelect = {
|
>({
|
||||||
id: string;
|
|
||||||
entityType: EntityTypeForSelect;
|
|
||||||
name: string;
|
|
||||||
avatarUrl?: string;
|
|
||||||
avatarType?: AvatarType;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function MultipleEntitySelect({
|
|
||||||
entities,
|
entities,
|
||||||
onItemCheckChange,
|
onItemCheckChange,
|
||||||
onSearchFilterChange,
|
onSearchFilterChange,
|
||||||
searchFilter,
|
searchFilter,
|
||||||
}: {
|
}: {
|
||||||
entities: EntitiesForMultipleEntitySelect;
|
entities: EntitiesForMultipleEntitySelect<CustomEntityForSelect>;
|
||||||
searchFilter: string;
|
searchFilter: string;
|
||||||
onSearchFilterChange: (newSearchFilter: string) => void;
|
onSearchFilterChange: (newSearchFilter: string) => void;
|
||||||
onItemCheckChange: (
|
onItemCheckChange: (
|
||||||
newCheckedValue: boolean,
|
newCheckedValue: boolean,
|
||||||
entity: EntityForSelect,
|
entity: CustomEntityForSelect,
|
||||||
) => void;
|
) => void;
|
||||||
}) {
|
}) {
|
||||||
const debouncedSetSearchFilter = debounce(onSearchFilterChange, 100, {
|
const debouncedSetSearchFilter = debounce(onSearchFilterChange, 100, {
|
||||||
@ -1,9 +1,7 @@
|
|||||||
import * as Apollo from '@apollo/client';
|
import * as Apollo from '@apollo/client';
|
||||||
|
|
||||||
import {
|
import { EntitiesForMultipleEntitySelect } from '@/relation-picker/components/MultipleEntitySelect';
|
||||||
EntitiesForMultipleEntitySelect,
|
import { EntityForSelect } from '@/relation-picker/types/EntityForSelect';
|
||||||
EntityForSelect,
|
|
||||||
} from '@/comments/components/MultipleEntitySelect';
|
|
||||||
import {
|
import {
|
||||||
Exact,
|
Exact,
|
||||||
InputMaybe,
|
InputMaybe,
|
||||||
@ -46,6 +44,7 @@ export function useFilteredSearchEntityQuery<
|
|||||||
Array<EntityOrderByWithRelationInput> | EntityOrderByWithRelationInput
|
Array<EntityOrderByWithRelationInput> | EntityOrderByWithRelationInput
|
||||||
>;
|
>;
|
||||||
}>,
|
}>,
|
||||||
|
CustomEntityForSelect extends EntityForSelect,
|
||||||
>({
|
>({
|
||||||
queryHook,
|
queryHook,
|
||||||
searchOnFields,
|
searchOnFields,
|
||||||
@ -66,10 +65,10 @@ export function useFilteredSearchEntityQuery<
|
|||||||
orderByField: OrderByField;
|
orderByField: OrderByField;
|
||||||
sortOrder?: SortOrder;
|
sortOrder?: SortOrder;
|
||||||
selectedIds: string[];
|
selectedIds: string[];
|
||||||
mappingFunction: (entity: EntityType) => EntityForSelect;
|
mappingFunction: (entity: EntityType) => CustomEntityForSelect;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
searchFilter: string;
|
searchFilter: string;
|
||||||
}): EntitiesForMultipleEntitySelect {
|
}): EntitiesForMultipleEntitySelect<CustomEntityForSelect> {
|
||||||
const { data: selectedEntitiesData } = queryHook({
|
const { data: selectedEntitiesData } = queryHook({
|
||||||
variables: {
|
variables: {
|
||||||
where: {
|
where: {
|
||||||
11
front/src/modules/relation-picker/types/EntityForSelect.ts
Normal file
11
front/src/modules/relation-picker/types/EntityForSelect.ts
Normal 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;
|
||||||
|
};
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
import { CommentableType, PipelineProgressableType } from '~/generated/graphql';
|
||||||
|
|
||||||
|
export type EntityTypeForSelect = CommentableType | PipelineProgressableType;
|
||||||
@ -1,10 +1,9 @@
|
|||||||
import { EntityForSelect } from '@/comments/components/MultipleEntitySelect';
|
import { EntityForSelect } from '@/relation-picker/types/EntityForSelect';
|
||||||
|
|
||||||
export function flatMapAndSortEntityForSelectArrayOfArrayByName(
|
export function flatMapAndSortEntityForSelectArrayOfArrayByName<
|
||||||
entityForSelectArray: EntityForSelect[][],
|
T extends EntityForSelect,
|
||||||
) {
|
>(entityForSelectArray: T[][]) {
|
||||||
const sortByName = (a: EntityForSelect, b: EntityForSelect) =>
|
const sortByName = (a: T, b: T) => a.name.localeCompare(b.name);
|
||||||
a.name.localeCompare(b.name);
|
|
||||||
|
|
||||||
return entityForSelectArray.flatMap((entity) => entity).sort(sortByName);
|
return entityForSelectArray.flatMap((entity) => entity).sort(sortByName);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user