Minor fixes on context menu (#9340)

- Fixed click outside for kanban not working (changed strategy)
- Tried a different approach for setting the context menu position
- Fixes https://github.com/twentyhq/twenty/issues/9336
This commit is contained in:
Lucas Bordeau
2025-01-03 17:46:42 +01:00
committed by GitHub
parent e87b2c9e33
commit ae4615d140
4 changed files with 64 additions and 12 deletions

View File

@ -4,7 +4,9 @@ import { useContext, useRef } from 'react';
import { useRecoilCallback } from 'recoil';
import { Key } from 'ts-key-enum';
import { useActionMenu } from '@/action-menu/hooks/useActionMenu';
import { ActionBarHotkeyScope } from '@/action-menu/types/ActionBarHotKeyScope';
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
import { RecordBoardHeader } from '@/object-record/record-board/components/RecordBoardHeader';
import { RecordBoardStickyHeaderEffect } from '@/object-record/record-board/components/RecordBoardStickyHeaderEffect';
import { RECORD_BOARD_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-board/constants/RecordBoardClickOutsideListenerId';
@ -22,6 +24,7 @@ import { recordStoreFamilyState } from '@/object-record/record-store/states/reco
import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope';
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
@ -65,6 +68,23 @@ export const RecordBoard = () => {
useContext(RecordBoardContext);
const boardRef = useRef<HTMLDivElement>(null);
const { toggleClickOutsideListener } = useClickOutsideListener(
RECORD_BOARD_CLICK_OUTSIDE_LISTENER_ID,
);
const actionMenuId = getActionMenuIdFromRecordIndexId(recordBoardId);
const { closeActionMenuDropdown } = useActionMenu(actionMenuId);
const handleDragSelectionStart = () => {
closeActionMenuDropdown();
toggleClickOutsideListener(false);
};
const handleDragSelectionEnd = () => {
toggleClickOutsideListener(true);
};
const visibleRecordGroupIds = useRecoilComponentFamilyValueV2(
visibleRecordGroupIdsComponentFamilySelector,
ViewType.Kanban,
@ -89,10 +109,13 @@ export const RecordBoard = () => {
'command-menu',
'modal-backdrop',
'page-action-container',
'record-board-card',
],
listenerId: RECORD_BOARD_CLICK_OUTSIDE_LISTENER_ID,
refs: [boardRef],
callback: resetRecordSelection,
refs: [],
callback: () => {
resetRecordSelection();
},
});
const selectAll = useRecoilCallback(
@ -219,8 +242,9 @@ export const RecordBoard = () => {
<RecordBoardScrollRestoreEffect />
<DragSelect
dragSelectable={boardRef}
onDragSelectionStart={resetRecordSelection}
onDragSelectionEnd={handleDragSelectionEnd}
onDragSelectionChange={setRecordAsSelected}
onDragSelectionStart={handleDragSelectionStart}
/>
</StyledBoardContentContainer>
</StyledContainerContainer>

View File

@ -66,5 +66,23 @@ export const useRecordBoardSelection = (recordBoardId: string) => {
[isRecordBoardCardSelectedFamilyState],
);
return { resetRecordSelection, setRecordAsSelected };
const checkIfLastUnselectAndCloseDropdown = useRecoilCallback(
({ snapshot, set }) =>
() => {
const recordIds = getSnapshotValue(
snapshot,
recordBoardSelectedRecordIdsSelector,
);
if (recordIds.length === 0) {
set(isActionMenuDropdownOpenState, false);
}
},
[recordBoardSelectedRecordIdsSelector, isActionMenuDropdownOpenState],
);
return {
resetRecordSelection,
setRecordAsSelected,
checkIfLastUnselectAndCloseDropdown,
};
};

View File

@ -3,6 +3,7 @@ import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-me
import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
import { useRecordBoardSelection } from '@/object-record/record-board/hooks/useRecordBoardSelection';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext';
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
@ -191,6 +192,9 @@ export const RecordBoardCard = ({
RecordBoardScopeInternalContext,
);
const { checkIfLastUnselectAndCloseDropdown } =
useRecordBoardSelection(recordBoardId);
const actionMenuId = getActionMenuIdFromRecordIndexId(recordBoardId);
const actionMenuDropdownId =
@ -215,6 +219,13 @@ export const RecordBoardCard = ({
openActionMenuDropdown();
};
const handleCardClick = () => {
if (!isCreating) {
setIsCurrentCardSelected(!isCurrentCardSelected);
checkIfLastUnselectAndCloseDropdown();
}
};
const PreventSelectOnClickContainer = ({
children,
}: {
@ -262,18 +273,17 @@ export const RecordBoardCard = ({
);
return (
<StyledBoardCardWrapper onContextMenu={handleActionMenuDropdown}>
<StyledBoardCardWrapper
className="record-board-card"
onContextMenu={handleActionMenuDropdown}
>
{!isCreating && <RecordValueSetterEffect recordId={recordId} />}
<InView>
<StyledBoardCard
ref={cardRef}
selected={isCurrentCardSelected}
onMouseLeave={onMouseLeaveBoard}
onClick={() => {
if (!isCreating) {
setIsCurrentCardSelected(!isCurrentCardSelected);
}
}}
onClick={handleCardClick}
>
<StyledBoardCardHeader showCompactView={isCompactModeActive}>
{isCreating && position !== undefined ? (

View File

@ -50,8 +50,8 @@ export const useTriggerActionMenuDropdown = ({
event.preventDefault();
set(recordIndexActionMenuDropdownPositionState, {
x: event.clientX,
y: event.clientY,
x: event.pageX,
y: event.pageY,
});
const isRowSelected = getSnapshotValue(