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:
@ -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>
|
||||
|
||||
Reference in New Issue
Block a user