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:
Thaïs
2023-07-21 01:17:43 +02:00
committed by GitHub
parent 872ec9e6bb
commit a2087da624
6 changed files with 174 additions and 155 deletions

View File

@ -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>