Fixes on side panel closing and table rows and board cards activation (#12609)
Fixes https://github.com/twentyhq/core-team-issues/issues/1096 This PR: - Prevents interaction with elements inside the index page when the side panel is opened, except for switching between records - Prevents stacking multiple records in the side panel navigation stack when navigating from the index - Adds activation and unfocus logic for board cards when clicked - Fixes table row activation after clicking on a record chip Before: https://github.com/user-attachments/assets/dcfec9fb-392b-4760-9b11-b0f077087b82 After: https://github.com/user-attachments/assets/93e0dc6a-c693-4484-b23e-f5ae291eb472
This commit is contained in:
@ -51,12 +51,14 @@ export const CommandMenuOpenContainer = ({
|
||||
|
||||
const handleClickOutside = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
() => {
|
||||
(event: MouseEvent | TouchEvent) => {
|
||||
const hotkeyScope = snapshot
|
||||
.getLoadable(currentHotkeyScopeState)
|
||||
.getValue();
|
||||
|
||||
if (hotkeyScope?.scope === CommandMenuHotkeyScope.CommandMenuFocused) {
|
||||
event.stopImmediatePropagation();
|
||||
event.preventDefault();
|
||||
closeCommandMenu();
|
||||
}
|
||||
},
|
||||
|
||||
@ -38,10 +38,12 @@ export const useOpenRecordInCommandMenu = () => {
|
||||
recordId,
|
||||
objectNameSingular,
|
||||
isNewRecord = false,
|
||||
resetNavigationStack = false,
|
||||
}: {
|
||||
recordId: string;
|
||||
objectNameSingular: string;
|
||||
isNewRecord?: boolean;
|
||||
resetNavigationStack?: boolean;
|
||||
}) => {
|
||||
const navigationStack = getSnapshotValue(
|
||||
snapshot,
|
||||
@ -171,7 +173,7 @@ export const useOpenRecordInCommandMenu = () => {
|
||||
pageIcon: Icon,
|
||||
pageIconColor: IconColor,
|
||||
pageId: pageComponentInstanceId,
|
||||
resetNavigationStack: false,
|
||||
resetNavigationStack,
|
||||
});
|
||||
|
||||
if (objectNameSingular === CoreObjectNameSingular.WorkflowRun) {
|
||||
|
||||
@ -10,6 +10,8 @@ import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/re
|
||||
import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
|
||||
|
||||
import { ActionMenuDropdownHotkeyScope } from '@/action-menu/types/ActionMenuDropdownHotKeyScope';
|
||||
import { useActiveRecordBoardCard } from '@/object-record/record-board/hooks/useActiveRecordBoardCard';
|
||||
import { useFocusedRecordBoardCard } from '@/object-record/record-board/hooks/useFocusedRecordBoardCard';
|
||||
import { RecordBoardCardBody } from '@/object-record/record-board/record-board-card/components/RecordBoardCardBody';
|
||||
import { RecordBoardCardHeader } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeader';
|
||||
import { RECORD_BOARD_CARD_CLICK_OUTSIDE_ID } from '@/object-record/record-board/record-board-card/constants/RecordBoardCardClickOutsideId';
|
||||
@ -142,6 +144,8 @@ export const RecordBoardCard = () => {
|
||||
const { openDropdown } = useDropdownV2();
|
||||
|
||||
const { openRecordFromIndexView } = useOpenRecordFromIndexView();
|
||||
const { activateBoardCard } = useActiveRecordBoardCard(recordBoardId);
|
||||
const { unfocusBoardCard } = useFocusedRecordBoardCard(recordBoardId);
|
||||
|
||||
const handleActionMenuDropdown = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
@ -156,6 +160,8 @@ export const RecordBoardCard = () => {
|
||||
};
|
||||
|
||||
const handleCardClick = () => {
|
||||
activateBoardCard({ rowIndex, columnIndex });
|
||||
unfocusBoardCard();
|
||||
openRecordFromIndexView({ recordId });
|
||||
};
|
||||
|
||||
|
||||
@ -4,15 +4,17 @@ import { useRecordBoardSelection } from '@/object-record/record-board/hooks/useR
|
||||
import { RecordBoardCardHeaderContainer } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeaderContainer';
|
||||
import { StopPropagationContainer } from '@/object-record/record-board/record-board-card/components/StopPropagationContainer';
|
||||
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';
|
||||
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
|
||||
|
||||
import { useActiveRecordBoardCard } from '@/object-record/record-board/hooks/useActiveRecordBoardCard';
|
||||
import { useFocusedRecordBoardCard } from '@/object-record/record-board/hooks/useFocusedRecordBoardCard';
|
||||
import { useOpenRecordFromIndexView } from '@/object-record/record-index/hooks/useOpenRecordFromIndexView';
|
||||
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
|
||||
import styled from '@emotion/styled';
|
||||
import { Dispatch, SetStateAction, useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
@ -45,11 +47,10 @@ export const RecordBoardCardHeader = ({
|
||||
|
||||
const record = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
|
||||
const { objectMetadataItem } = useContext(RecordBoardContext);
|
||||
|
||||
const recordBoardId = useAvailableScopeIdOrThrow(
|
||||
RecordBoardScopeInternalContext,
|
||||
);
|
||||
const { objectMetadataItem, recordBoardId } = useContext(RecordBoardContext);
|
||||
const { rowIndex, columnIndex } = useContext(RecordBoardCardContext);
|
||||
const { activateBoardCard } = useActiveRecordBoardCard(recordBoardId);
|
||||
const { unfocusBoardCard } = useFocusedRecordBoardCard(recordBoardId);
|
||||
|
||||
const showCompactView = useRecoilComponentValueV2(
|
||||
isRecordBoardCompactModeActiveComponentState,
|
||||
@ -66,6 +67,12 @@ export const RecordBoardCardHeader = ({
|
||||
|
||||
const { openRecordFromIndexView } = useOpenRecordFromIndexView();
|
||||
|
||||
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
|
||||
const triggerEvent =
|
||||
recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL
|
||||
? 'CLICK'
|
||||
: 'MOUSE_DOWN';
|
||||
|
||||
return (
|
||||
<RecordBoardCardHeaderContainer showCompactView={showCompactView}>
|
||||
<StopPropagationContainer>
|
||||
@ -76,9 +83,11 @@ export const RecordBoardCardHeader = ({
|
||||
variant={AvatarChipVariant.Transparent}
|
||||
maxWidth={150}
|
||||
onClick={() => {
|
||||
activateBoardCard({ rowIndex, columnIndex });
|
||||
unfocusBoardCard();
|
||||
openRecordFromIndexView({ recordId });
|
||||
}}
|
||||
triggerEvent="CLICK"
|
||||
triggerEvent={triggerEvent}
|
||||
/>
|
||||
)}
|
||||
</StopPropagationContainer>
|
||||
|
||||
@ -71,6 +71,7 @@ export const useOpenRecordFromIndexView = () => {
|
||||
openRecordInCommandMenu({
|
||||
recordId,
|
||||
objectNameSingular,
|
||||
resetNavigationStack: true,
|
||||
});
|
||||
} else {
|
||||
navigate(AppPath.RecordShowPage, {
|
||||
|
||||
@ -3,13 +3,18 @@ import { FieldContext } from '@/object-record/record-field/contexts/FieldContext
|
||||
import { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { useOpenRecordFromIndexView } from '@/object-record/record-index/hooks/useOpenRecordFromIndexView';
|
||||
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
|
||||
import { RecordUpdateContext } from '@/object-record/record-table/contexts/EntityUpdateMutationHookContext';
|
||||
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { useRecordTableRowContextOrThrow } from '@/object-record/record-table/contexts/RecordTableRowContext';
|
||||
import { useActiveRecordTableRow } from '@/object-record/record-table/hooks/useActiveRecordTableRow';
|
||||
import { useFocusedRecordTableRow } from '@/object-record/record-table/hooks/useFocusedRecordTableRow';
|
||||
import { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
|
||||
import { ReactNode, useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
type RecordTableCellFieldContextLabelIdentifierProps = {
|
||||
@ -25,7 +30,10 @@ export const RecordTableCellFieldContextLabelIdentifier = ({
|
||||
useRecordTableRowContextOrThrow();
|
||||
|
||||
const { columnDefinition } = useContext(RecordTableCellContext);
|
||||
const { objectMetadataItem } = useRecordTableContextOrThrow();
|
||||
const { objectMetadataItem, recordTableId } = useRecordTableContextOrThrow();
|
||||
const { rowIndex } = useRecordTableRowContextOrThrow();
|
||||
const { activateRecordTableRow } = useActiveRecordTableRow(recordTableId);
|
||||
const { unfocusRecordTableRow } = useFocusedRecordTableRow(recordTableId);
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
const isRecordTableScrolledLeftComponent = useRecoilComponentValueV2(
|
||||
@ -51,6 +59,12 @@ export const RecordTableCellFieldContextLabelIdentifier = ({
|
||||
|
||||
const { openRecordFromIndexView } = useOpenRecordFromIndexView();
|
||||
|
||||
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
|
||||
const triggerEvent =
|
||||
recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL
|
||||
? 'CLICK'
|
||||
: 'MOUSE_DOWN';
|
||||
|
||||
return (
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
@ -64,9 +78,12 @@ export const RecordTableCellFieldContextLabelIdentifier = ({
|
||||
isReadOnly: isFieldReadOnly,
|
||||
maxWidth: columnDefinition.size,
|
||||
onRecordChipClick: () => {
|
||||
activateRecordTableRow(rowIndex);
|
||||
unfocusRecordTableRow();
|
||||
openRecordFromIndexView({ recordId });
|
||||
},
|
||||
isForbidden: !hasObjectReadPermissions,
|
||||
triggerEvent,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user