feat: disallow removing all comment thread targets (#779)
* feat: disallow removing all comment thread targets Closes #431 * Rename variables * Fix console error --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -1915,24 +1915,21 @@ export type GetCommentThreadQueryVariables = Exact<{
|
||||
|
||||
export type GetCommentThreadQuery = { __typename?: 'Query', findManyCommentThreads: Array<{ __typename?: 'CommentThread', id: string, createdAt: string, body?: string | null, title?: string | null, type: ActivityType, author: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string }, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } }> | null, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', id: string, commentableId: string, commentableType: CommentableType }> | null }> };
|
||||
|
||||
export type AddCommentThreadTargetOnCommentThreadMutationVariables = Exact<{
|
||||
export type AddCommentThreadTargetsOnCommentThreadMutationVariables = Exact<{
|
||||
commentThreadId: Scalars['String'];
|
||||
commentThreadTargetCreationDate: Scalars['DateTime'];
|
||||
commentThreadTargetId: Scalars['String'];
|
||||
commentableEntityId: Scalars['String'];
|
||||
commentableEntityType: CommentableType;
|
||||
commentThreadTargetInputs: Array<CommentThreadTargetCreateManyCommentThreadInput> | CommentThreadTargetCreateManyCommentThreadInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type AddCommentThreadTargetOnCommentThreadMutation = { __typename?: 'Mutation', updateOneCommentThread: { __typename?: 'CommentThread', id: string, createdAt: string, updatedAt: string, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', id: string, createdAt: string, updatedAt: string, commentableType: CommentableType, commentableId: string }> | null } };
|
||||
export type AddCommentThreadTargetsOnCommentThreadMutation = { __typename?: 'Mutation', updateOneCommentThread: { __typename?: 'CommentThread', id: string, createdAt: string, updatedAt: string, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', id: string, createdAt: string, updatedAt: string, commentableType: CommentableType, commentableId: string }> | null } };
|
||||
|
||||
export type RemoveCommentThreadTargetOnCommentThreadMutationVariables = Exact<{
|
||||
export type RemoveCommentThreadTargetsOnCommentThreadMutationVariables = Exact<{
|
||||
commentThreadId: Scalars['String'];
|
||||
commentThreadTargetId: Scalars['String'];
|
||||
commentThreadTargetIds: Array<Scalars['String']> | Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type RemoveCommentThreadTargetOnCommentThreadMutation = { __typename?: 'Mutation', updateOneCommentThread: { __typename?: 'CommentThread', id: string, createdAt: string, updatedAt: string, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', id: string, createdAt: string, updatedAt: string, commentableType: CommentableType, commentableId: string }> | null } };
|
||||
export type RemoveCommentThreadTargetsOnCommentThreadMutation = { __typename?: 'Mutation', updateOneCommentThread: { __typename?: 'CommentThread', id: string, createdAt: string, updatedAt: string, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', id: string, createdAt: string, updatedAt: string, commentableType: CommentableType, commentableId: string }> | null } };
|
||||
|
||||
export type DeleteCommentThreadMutationVariables = Exact<{
|
||||
commentThreadId: Scalars['String'];
|
||||
@ -2531,11 +2528,11 @@ export function useGetCommentThreadLazyQuery(baseOptions?: Apollo.LazyQueryHookO
|
||||
export type GetCommentThreadQueryHookResult = ReturnType<typeof useGetCommentThreadQuery>;
|
||||
export type GetCommentThreadLazyQueryHookResult = ReturnType<typeof useGetCommentThreadLazyQuery>;
|
||||
export type GetCommentThreadQueryResult = Apollo.QueryResult<GetCommentThreadQuery, GetCommentThreadQueryVariables>;
|
||||
export const AddCommentThreadTargetOnCommentThreadDocument = gql`
|
||||
mutation AddCommentThreadTargetOnCommentThread($commentThreadId: String!, $commentThreadTargetCreationDate: DateTime!, $commentThreadTargetId: String!, $commentableEntityId: String!, $commentableEntityType: CommentableType!) {
|
||||
export const AddCommentThreadTargetsOnCommentThreadDocument = gql`
|
||||
mutation AddCommentThreadTargetsOnCommentThread($commentThreadId: String!, $commentThreadTargetInputs: [CommentThreadTargetCreateManyCommentThreadInput!]!) {
|
||||
updateOneCommentThread(
|
||||
where: {id: $commentThreadId}
|
||||
data: {commentThreadTargets: {connectOrCreate: {create: {id: $commentThreadTargetId, createdAt: $commentThreadTargetCreationDate, commentableType: $commentableEntityType, commentableId: $commentableEntityId}, where: {id: $commentThreadTargetId}}}}
|
||||
data: {commentThreadTargets: {createMany: {data: $commentThreadTargetInputs}}}
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
@ -2550,41 +2547,38 @@ export const AddCommentThreadTargetOnCommentThreadDocument = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type AddCommentThreadTargetOnCommentThreadMutationFn = Apollo.MutationFunction<AddCommentThreadTargetOnCommentThreadMutation, AddCommentThreadTargetOnCommentThreadMutationVariables>;
|
||||
export type AddCommentThreadTargetsOnCommentThreadMutationFn = Apollo.MutationFunction<AddCommentThreadTargetsOnCommentThreadMutation, AddCommentThreadTargetsOnCommentThreadMutationVariables>;
|
||||
|
||||
/**
|
||||
* __useAddCommentThreadTargetOnCommentThreadMutation__
|
||||
* __useAddCommentThreadTargetsOnCommentThreadMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useAddCommentThreadTargetOnCommentThreadMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useAddCommentThreadTargetOnCommentThreadMutation` returns a tuple that includes:
|
||||
* To run a mutation, you first call `useAddCommentThreadTargetsOnCommentThreadMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useAddCommentThreadTargetsOnCommentThreadMutation` returns a tuple that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - An object with fields that represent the current status of the mutation's execution
|
||||
*
|
||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||
*
|
||||
* @example
|
||||
* const [addCommentThreadTargetOnCommentThreadMutation, { data, loading, error }] = useAddCommentThreadTargetOnCommentThreadMutation({
|
||||
* const [addCommentThreadTargetsOnCommentThreadMutation, { data, loading, error }] = useAddCommentThreadTargetsOnCommentThreadMutation({
|
||||
* variables: {
|
||||
* commentThreadId: // value for 'commentThreadId'
|
||||
* commentThreadTargetCreationDate: // value for 'commentThreadTargetCreationDate'
|
||||
* commentThreadTargetId: // value for 'commentThreadTargetId'
|
||||
* commentableEntityId: // value for 'commentableEntityId'
|
||||
* commentableEntityType: // value for 'commentableEntityType'
|
||||
* commentThreadTargetInputs: // value for 'commentThreadTargetInputs'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useAddCommentThreadTargetOnCommentThreadMutation(baseOptions?: Apollo.MutationHookOptions<AddCommentThreadTargetOnCommentThreadMutation, AddCommentThreadTargetOnCommentThreadMutationVariables>) {
|
||||
export function useAddCommentThreadTargetsOnCommentThreadMutation(baseOptions?: Apollo.MutationHookOptions<AddCommentThreadTargetsOnCommentThreadMutation, AddCommentThreadTargetsOnCommentThreadMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<AddCommentThreadTargetOnCommentThreadMutation, AddCommentThreadTargetOnCommentThreadMutationVariables>(AddCommentThreadTargetOnCommentThreadDocument, options);
|
||||
return Apollo.useMutation<AddCommentThreadTargetsOnCommentThreadMutation, AddCommentThreadTargetsOnCommentThreadMutationVariables>(AddCommentThreadTargetsOnCommentThreadDocument, options);
|
||||
}
|
||||
export type AddCommentThreadTargetOnCommentThreadMutationHookResult = ReturnType<typeof useAddCommentThreadTargetOnCommentThreadMutation>;
|
||||
export type AddCommentThreadTargetOnCommentThreadMutationResult = Apollo.MutationResult<AddCommentThreadTargetOnCommentThreadMutation>;
|
||||
export type AddCommentThreadTargetOnCommentThreadMutationOptions = Apollo.BaseMutationOptions<AddCommentThreadTargetOnCommentThreadMutation, AddCommentThreadTargetOnCommentThreadMutationVariables>;
|
||||
export const RemoveCommentThreadTargetOnCommentThreadDocument = gql`
|
||||
mutation RemoveCommentThreadTargetOnCommentThread($commentThreadId: String!, $commentThreadTargetId: String!) {
|
||||
export type AddCommentThreadTargetsOnCommentThreadMutationHookResult = ReturnType<typeof useAddCommentThreadTargetsOnCommentThreadMutation>;
|
||||
export type AddCommentThreadTargetsOnCommentThreadMutationResult = Apollo.MutationResult<AddCommentThreadTargetsOnCommentThreadMutation>;
|
||||
export type AddCommentThreadTargetsOnCommentThreadMutationOptions = Apollo.BaseMutationOptions<AddCommentThreadTargetsOnCommentThreadMutation, AddCommentThreadTargetsOnCommentThreadMutationVariables>;
|
||||
export const RemoveCommentThreadTargetsOnCommentThreadDocument = gql`
|
||||
mutation RemoveCommentThreadTargetsOnCommentThread($commentThreadId: String!, $commentThreadTargetIds: [String!]!) {
|
||||
updateOneCommentThread(
|
||||
where: {id: $commentThreadId}
|
||||
data: {commentThreadTargets: {delete: {id: $commentThreadTargetId}}}
|
||||
data: {commentThreadTargets: {deleteMany: {id: {in: $commentThreadTargetIds}}}}
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
@ -2599,33 +2593,33 @@ export const RemoveCommentThreadTargetOnCommentThreadDocument = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type RemoveCommentThreadTargetOnCommentThreadMutationFn = Apollo.MutationFunction<RemoveCommentThreadTargetOnCommentThreadMutation, RemoveCommentThreadTargetOnCommentThreadMutationVariables>;
|
||||
export type RemoveCommentThreadTargetsOnCommentThreadMutationFn = Apollo.MutationFunction<RemoveCommentThreadTargetsOnCommentThreadMutation, RemoveCommentThreadTargetsOnCommentThreadMutationVariables>;
|
||||
|
||||
/**
|
||||
* __useRemoveCommentThreadTargetOnCommentThreadMutation__
|
||||
* __useRemoveCommentThreadTargetsOnCommentThreadMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useRemoveCommentThreadTargetOnCommentThreadMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useRemoveCommentThreadTargetOnCommentThreadMutation` returns a tuple that includes:
|
||||
* To run a mutation, you first call `useRemoveCommentThreadTargetsOnCommentThreadMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useRemoveCommentThreadTargetsOnCommentThreadMutation` returns a tuple that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - An object with fields that represent the current status of the mutation's execution
|
||||
*
|
||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||
*
|
||||
* @example
|
||||
* const [removeCommentThreadTargetOnCommentThreadMutation, { data, loading, error }] = useRemoveCommentThreadTargetOnCommentThreadMutation({
|
||||
* const [removeCommentThreadTargetsOnCommentThreadMutation, { data, loading, error }] = useRemoveCommentThreadTargetsOnCommentThreadMutation({
|
||||
* variables: {
|
||||
* commentThreadId: // value for 'commentThreadId'
|
||||
* commentThreadTargetId: // value for 'commentThreadTargetId'
|
||||
* commentThreadTargetIds: // value for 'commentThreadTargetIds'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useRemoveCommentThreadTargetOnCommentThreadMutation(baseOptions?: Apollo.MutationHookOptions<RemoveCommentThreadTargetOnCommentThreadMutation, RemoveCommentThreadTargetOnCommentThreadMutationVariables>) {
|
||||
export function useRemoveCommentThreadTargetsOnCommentThreadMutation(baseOptions?: Apollo.MutationHookOptions<RemoveCommentThreadTargetsOnCommentThreadMutation, RemoveCommentThreadTargetsOnCommentThreadMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<RemoveCommentThreadTargetOnCommentThreadMutation, RemoveCommentThreadTargetOnCommentThreadMutationVariables>(RemoveCommentThreadTargetOnCommentThreadDocument, options);
|
||||
return Apollo.useMutation<RemoveCommentThreadTargetsOnCommentThreadMutation, RemoveCommentThreadTargetsOnCommentThreadMutationVariables>(RemoveCommentThreadTargetsOnCommentThreadDocument, options);
|
||||
}
|
||||
export type RemoveCommentThreadTargetOnCommentThreadMutationHookResult = ReturnType<typeof useRemoveCommentThreadTargetOnCommentThreadMutation>;
|
||||
export type RemoveCommentThreadTargetOnCommentThreadMutationResult = Apollo.MutationResult<RemoveCommentThreadTargetOnCommentThreadMutation>;
|
||||
export type RemoveCommentThreadTargetOnCommentThreadMutationOptions = Apollo.BaseMutationOptions<RemoveCommentThreadTargetOnCommentThreadMutation, RemoveCommentThreadTargetOnCommentThreadMutationVariables>;
|
||||
export type RemoveCommentThreadTargetsOnCommentThreadMutationHookResult = ReturnType<typeof useRemoveCommentThreadTargetsOnCommentThreadMutation>;
|
||||
export type RemoveCommentThreadTargetsOnCommentThreadMutationResult = Apollo.MutationResult<RemoveCommentThreadTargetsOnCommentThreadMutation>;
|
||||
export type RemoveCommentThreadTargetsOnCommentThreadMutationOptions = Apollo.BaseMutationOptions<RemoveCommentThreadTargetsOnCommentThreadMutation, RemoveCommentThreadTargetsOnCommentThreadMutationVariables>;
|
||||
export const DeleteCommentThreadDocument = gql`
|
||||
mutation DeleteCommentThread($commentThreadId: String!) {
|
||||
deleteManyCommentThreads(where: {id: {equals: $commentThreadId}}) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import {
|
||||
autoUpdate,
|
||||
@ -78,56 +78,98 @@ const StyledMenuWrapper = styled.div`
|
||||
export function CommentThreadRelationPicker({ commentThread }: OwnProps) {
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
const [searchFilter, setSearchFilter] = useState('');
|
||||
|
||||
const peopleIds =
|
||||
commentThread?.commentThreadTargets
|
||||
?.filter((relation) => relation.commentableType === 'Person')
|
||||
.map((relation) => relation.commentableId) ?? [];
|
||||
const companyIds =
|
||||
commentThread?.commentThreadTargets
|
||||
?.filter((relation) => relation.commentableType === 'Company')
|
||||
.map((relation) => relation.commentableId) ?? [];
|
||||
|
||||
const personsForMultiSelect = useFilteredSearchPeopleQuery({
|
||||
searchFilter,
|
||||
selectedIds: peopleIds,
|
||||
});
|
||||
|
||||
const companiesForMultiSelect = useFilteredSearchCompanyQuery({
|
||||
searchFilter,
|
||||
selectedIds: companyIds,
|
||||
});
|
||||
|
||||
const [selectedEntityIds, setSelectedEntityIds] = useState<
|
||||
Record<string, boolean>
|
||||
>({});
|
||||
const {
|
||||
setHotkeyScopeAndMemorizePreviousScope,
|
||||
goBackToPreviousHotkeyScope,
|
||||
} = usePreviousHotkeyScope();
|
||||
|
||||
function handleRelationContainerClick() {
|
||||
const initialPeopleIds = useMemo(
|
||||
() =>
|
||||
commentThread?.commentThreadTargets
|
||||
?.filter((relation) => relation.commentableType === 'Person')
|
||||
.map((relation) => relation.commentableId) ?? [],
|
||||
[commentThread?.commentThreadTargets],
|
||||
);
|
||||
const initialCompanyIds = useMemo(
|
||||
() =>
|
||||
commentThread?.commentThreadTargets
|
||||
?.filter((relation) => relation.commentableType === 'Company')
|
||||
.map((relation) => relation.commentableId) ?? [],
|
||||
[commentThread?.commentThreadTargets],
|
||||
);
|
||||
|
||||
const initialSelectedEntityIds = useMemo(
|
||||
() =>
|
||||
[...initialPeopleIds, ...initialCompanyIds].reduce<
|
||||
Record<string, boolean>
|
||||
>((result, entityId) => ({ ...result, [entityId]: true }), {}),
|
||||
[initialPeopleIds, initialCompanyIds],
|
||||
);
|
||||
|
||||
const personsForMultiSelect = useFilteredSearchPeopleQuery({
|
||||
searchFilter,
|
||||
selectedIds: initialPeopleIds,
|
||||
});
|
||||
|
||||
const companiesForMultiSelect = useFilteredSearchCompanyQuery({
|
||||
searchFilter,
|
||||
selectedIds: initialCompanyIds,
|
||||
});
|
||||
|
||||
const selectedEntities = flatMapAndSortEntityForSelectArrayOfArrayByName([
|
||||
personsForMultiSelect.selectedEntities,
|
||||
companiesForMultiSelect.selectedEntities,
|
||||
]);
|
||||
|
||||
const filteredSelectedEntities =
|
||||
flatMapAndSortEntityForSelectArrayOfArrayByName([
|
||||
personsForMultiSelect.filteredSelectedEntities,
|
||||
companiesForMultiSelect.filteredSelectedEntities,
|
||||
]);
|
||||
|
||||
const entitiesToSelect = flatMapAndSortEntityForSelectArrayOfArrayByName([
|
||||
personsForMultiSelect.entitiesToSelect,
|
||||
companiesForMultiSelect.entitiesToSelect,
|
||||
]);
|
||||
|
||||
const handleCheckItemsChange = useHandleCheckableCommentThreadTargetChange({
|
||||
commentThread,
|
||||
});
|
||||
|
||||
const exitEditMode = useCallback(() => {
|
||||
goBackToPreviousHotkeyScope();
|
||||
setIsMenuOpen(false);
|
||||
setSearchFilter('');
|
||||
|
||||
if (Object.values(selectedEntityIds).some((value) => !!value)) {
|
||||
handleCheckItemsChange(selectedEntityIds, entitiesToSelect);
|
||||
}
|
||||
}, [
|
||||
entitiesToSelect,
|
||||
selectedEntityIds,
|
||||
goBackToPreviousHotkeyScope,
|
||||
handleCheckItemsChange,
|
||||
]);
|
||||
|
||||
const handleRelationContainerClick = useCallback(() => {
|
||||
if (isMenuOpen) {
|
||||
exitEditMode();
|
||||
} else {
|
||||
setIsMenuOpen(true);
|
||||
setSelectedEntityIds(initialSelectedEntityIds);
|
||||
setHotkeyScopeAndMemorizePreviousScope(
|
||||
RelationPickerHotkeyScope.RelationPicker,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Place in a scoped recoil atom family
|
||||
function handleFilterChange(newSearchFilter: string) {
|
||||
setSearchFilter(newSearchFilter);
|
||||
}
|
||||
|
||||
const handleCheckItemChange = useHandleCheckableCommentThreadTargetChange({
|
||||
commentThread,
|
||||
});
|
||||
|
||||
function exitEditMode() {
|
||||
goBackToPreviousHotkeyScope();
|
||||
setIsMenuOpen(false);
|
||||
setSearchFilter('');
|
||||
}
|
||||
}, [
|
||||
initialSelectedEntityIds,
|
||||
exitEditMode,
|
||||
isMenuOpen,
|
||||
setHotkeyScopeAndMemorizePreviousScope,
|
||||
]);
|
||||
|
||||
useScopedHotkeys(
|
||||
['esc', 'enter'],
|
||||
@ -159,22 +201,6 @@ export function CommentThreadRelationPicker({ commentThread }: OwnProps) {
|
||||
},
|
||||
});
|
||||
|
||||
const selectedEntities = flatMapAndSortEntityForSelectArrayOfArrayByName([
|
||||
personsForMultiSelect.selectedEntities,
|
||||
companiesForMultiSelect.selectedEntities,
|
||||
]);
|
||||
|
||||
const filteredSelectedEntities =
|
||||
flatMapAndSortEntityForSelectArrayOfArrayByName([
|
||||
personsForMultiSelect.filteredSelectedEntities,
|
||||
companiesForMultiSelect.filteredSelectedEntities,
|
||||
]);
|
||||
|
||||
const entitiesToSelect = flatMapAndSortEntityForSelectArrayOfArrayByName([
|
||||
personsForMultiSelect.entitiesToSelect,
|
||||
companiesForMultiSelect.entitiesToSelect,
|
||||
]);
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledRelationContainer
|
||||
@ -204,9 +230,10 @@ export function CommentThreadRelationPicker({ commentThread }: OwnProps) {
|
||||
selectedEntities,
|
||||
loading: false, // TODO implement skeleton loading
|
||||
}}
|
||||
onItemCheckChange={handleCheckItemChange}
|
||||
onSearchFilterChange={handleFilterChange}
|
||||
onChange={setSelectedEntityIds}
|
||||
onSearchFilterChange={setSearchFilter}
|
||||
searchFilter={searchFilter}
|
||||
value={selectedEntityIds}
|
||||
/>
|
||||
</StyledMenuWrapper>
|
||||
</RecoilScope>
|
||||
|
||||
@ -6,8 +6,8 @@ import { GET_PEOPLE } from '@/people/queries';
|
||||
import {
|
||||
CommentThread,
|
||||
CommentThreadTarget,
|
||||
useAddCommentThreadTargetOnCommentThreadMutation,
|
||||
useRemoveCommentThreadTargetOnCommentThreadMutation,
|
||||
useAddCommentThreadTargetsOnCommentThreadMutation,
|
||||
useRemoveCommentThreadTargetsOnCommentThreadMutation,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { GET_COMMENT_THREADS_BY_TARGETS } from '../queries';
|
||||
@ -22,8 +22,8 @@ export function useHandleCheckableCommentThreadTargetChange({
|
||||
>;
|
||||
};
|
||||
}) {
|
||||
const [addCommentThreadTargetOnCommentThread] =
|
||||
useAddCommentThreadTargetOnCommentThreadMutation({
|
||||
const [addCommentThreadTargetsOnCommentThread] =
|
||||
useAddCommentThreadTargetsOnCommentThreadMutation({
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMPANIES) ?? '',
|
||||
getOperationName(GET_PEOPLE) ?? '',
|
||||
@ -31,8 +31,8 @@ export function useHandleCheckableCommentThreadTargetChange({
|
||||
],
|
||||
});
|
||||
|
||||
const [removeCommentThreadTargetOnCommentThread] =
|
||||
useRemoveCommentThreadTargetOnCommentThreadMutation({
|
||||
const [removeCommentThreadTargetsOnCommentThread] =
|
||||
useRemoveCommentThreadTargetsOnCommentThreadMutation({
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMPANIES) ?? '',
|
||||
getOperationName(GET_PEOPLE) ?? '',
|
||||
@ -40,36 +40,45 @@ export function useHandleCheckableCommentThreadTargetChange({
|
||||
],
|
||||
});
|
||||
|
||||
return function handleCheckItemChange(
|
||||
newCheckedValue: boolean,
|
||||
entity: CommentableEntityForSelect,
|
||||
return async function handleCheckItemsChange(
|
||||
entityValues: Record<string, boolean>,
|
||||
entities: CommentableEntityForSelect[],
|
||||
) {
|
||||
if (!commentThread) {
|
||||
return;
|
||||
}
|
||||
if (newCheckedValue) {
|
||||
addCommentThreadTargetOnCommentThread({
|
||||
|
||||
const currentEntityIds = commentThread.commentThreadTargets.map(
|
||||
({ commentableId }) => commentableId,
|
||||
);
|
||||
|
||||
const entitiesToAdd = entities.filter(
|
||||
({ id }) => entityValues[id] && !currentEntityIds.includes(id),
|
||||
);
|
||||
|
||||
if (entitiesToAdd.length)
|
||||
await addCommentThreadTargetsOnCommentThread({
|
||||
variables: {
|
||||
commentableEntityId: entity.id,
|
||||
commentableEntityType: entity.entityType,
|
||||
commentThreadId: commentThread.id,
|
||||
commentThreadTargetCreationDate: new Date().toISOString(),
|
||||
commentThreadTargetId: v4(),
|
||||
commentThreadTargetInputs: entitiesToAdd.map((entity) => ({
|
||||
id: v4(),
|
||||
createdAt: new Date().toISOString(),
|
||||
commentableType: entity.entityType,
|
||||
commentableId: entity.id,
|
||||
})),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const foundCorrespondingTarget = commentThread.commentThreadTargets?.find(
|
||||
(target) => target.commentableId === entity.id,
|
||||
);
|
||||
|
||||
if (foundCorrespondingTarget) {
|
||||
removeCommentThreadTargetOnCommentThread({
|
||||
variables: {
|
||||
commentThreadId: commentThread.id,
|
||||
commentThreadTargetId: foundCorrespondingTarget.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
const commentThreadTargetIdsToDelete = commentThread.commentThreadTargets
|
||||
.filter(({ commentableId }) => !entityValues[commentableId])
|
||||
.map(({ id }) => id);
|
||||
|
||||
if (commentThreadTargetIdsToDelete.length)
|
||||
await removeCommentThreadTargetsOnCommentThread({
|
||||
variables: {
|
||||
commentThreadId: commentThread.id,
|
||||
commentThreadTargetIds: commentThreadTargetIdsToDelete,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,26 +1,15 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const ADD_COMMENT_THREAD_TARGET = gql`
|
||||
mutation AddCommentThreadTargetOnCommentThread(
|
||||
export const ADD_COMMENT_THREAD_TARGETS = gql`
|
||||
mutation AddCommentThreadTargetsOnCommentThread(
|
||||
$commentThreadId: String!
|
||||
$commentThreadTargetCreationDate: DateTime!
|
||||
$commentThreadTargetId: String!
|
||||
$commentableEntityId: String!
|
||||
$commentableEntityType: CommentableType!
|
||||
$commentThreadTargetInputs: [CommentThreadTargetCreateManyCommentThreadInput!]!
|
||||
) {
|
||||
updateOneCommentThread(
|
||||
where: { id: $commentThreadId }
|
||||
data: {
|
||||
commentThreadTargets: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: $commentThreadTargetId
|
||||
createdAt: $commentThreadTargetCreationDate
|
||||
commentableType: $commentableEntityType
|
||||
commentableId: $commentableEntityId
|
||||
}
|
||||
where: { id: $commentThreadTargetId }
|
||||
}
|
||||
createMany: { data: $commentThreadTargetInputs }
|
||||
}
|
||||
}
|
||||
) {
|
||||
@ -38,14 +27,18 @@ export const ADD_COMMENT_THREAD_TARGET = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const REMOVE_COMMENT_THREAD_TARGET = gql`
|
||||
mutation RemoveCommentThreadTargetOnCommentThread(
|
||||
export const REMOVE_COMMENT_THREAD_TARGETS = gql`
|
||||
mutation RemoveCommentThreadTargetsOnCommentThread(
|
||||
$commentThreadId: String!
|
||||
$commentThreadTargetId: String!
|
||||
$commentThreadTargetIds: [String!]!
|
||||
) {
|
||||
updateOneCommentThread(
|
||||
where: { id: $commentThreadId }
|
||||
data: { commentThreadTargets: { delete: { id: $commentThreadTargetId } } }
|
||||
data: {
|
||||
commentThreadTargets: {
|
||||
deleteMany: { id: { in: $commentThreadTargetIds } }
|
||||
}
|
||||
}
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
|
||||
@ -79,7 +79,8 @@ export function Checkbox({
|
||||
indeterminate,
|
||||
variant = CheckboxVariant.Primary,
|
||||
}: OwnProps) {
|
||||
const [isInternalChecked, setIsInternalChecked] = React.useState(false);
|
||||
const [isInternalChecked, setIsInternalChecked] =
|
||||
React.useState<boolean>(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
setIsInternalChecked(checked);
|
||||
|
||||
@ -23,17 +23,16 @@ export function MultipleEntitySelect<
|
||||
CustomEntityForSelect extends EntityForSelect,
|
||||
>({
|
||||
entities,
|
||||
onItemCheckChange,
|
||||
onChange,
|
||||
onSearchFilterChange,
|
||||
searchFilter,
|
||||
value,
|
||||
}: {
|
||||
entities: EntitiesForMultipleEntitySelect<CustomEntityForSelect>;
|
||||
searchFilter: string;
|
||||
onSearchFilterChange: (newSearchFilter: string) => void;
|
||||
onItemCheckChange: (
|
||||
newCheckedValue: boolean,
|
||||
entity: CustomEntityForSelect,
|
||||
) => void;
|
||||
onChange: (value: Record<string, boolean>) => void;
|
||||
value: Record<string, boolean>;
|
||||
}) {
|
||||
const debouncedSetSearchFilter = debounce(onSearchFilterChange, 100, {
|
||||
leading: true,
|
||||
@ -61,13 +60,9 @@ export function MultipleEntitySelect<
|
||||
{entitiesInDropdown?.map((entity) => (
|
||||
<DropdownMenuCheckableItem
|
||||
key={entity.id}
|
||||
checked={
|
||||
entities.selectedEntities
|
||||
?.map((selectedEntity) => selectedEntity.id)
|
||||
?.includes(entity.id) ?? false
|
||||
}
|
||||
checked={value[entity.id]}
|
||||
onChange={(newCheckedValue) =>
|
||||
onItemCheckChange(newCheckedValue, entity)
|
||||
onChange({ ...value, [entity.id]: newCheckedValue })
|
||||
}
|
||||
>
|
||||
<Avatar
|
||||
|
||||
Reference in New Issue
Block a user