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(
|
const handleClickOutside = useRecoilCallback(
|
||||||
({ snapshot }) =>
|
({ snapshot }) =>
|
||||||
() => {
|
(event: MouseEvent | TouchEvent) => {
|
||||||
const hotkeyScope = snapshot
|
const hotkeyScope = snapshot
|
||||||
.getLoadable(currentHotkeyScopeState)
|
.getLoadable(currentHotkeyScopeState)
|
||||||
.getValue();
|
.getValue();
|
||||||
|
|
||||||
if (hotkeyScope?.scope === CommandMenuHotkeyScope.CommandMenuFocused) {
|
if (hotkeyScope?.scope === CommandMenuHotkeyScope.CommandMenuFocused) {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
event.preventDefault();
|
||||||
closeCommandMenu();
|
closeCommandMenu();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -38,10 +38,12 @@ export const useOpenRecordInCommandMenu = () => {
|
|||||||
recordId,
|
recordId,
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
isNewRecord = false,
|
isNewRecord = false,
|
||||||
|
resetNavigationStack = false,
|
||||||
}: {
|
}: {
|
||||||
recordId: string;
|
recordId: string;
|
||||||
objectNameSingular: string;
|
objectNameSingular: string;
|
||||||
isNewRecord?: boolean;
|
isNewRecord?: boolean;
|
||||||
|
resetNavigationStack?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const navigationStack = getSnapshotValue(
|
const navigationStack = getSnapshotValue(
|
||||||
snapshot,
|
snapshot,
|
||||||
@ -171,7 +173,7 @@ export const useOpenRecordInCommandMenu = () => {
|
|||||||
pageIcon: Icon,
|
pageIcon: Icon,
|
||||||
pageIconColor: IconColor,
|
pageIconColor: IconColor,
|
||||||
pageId: pageComponentInstanceId,
|
pageId: pageComponentInstanceId,
|
||||||
resetNavigationStack: false,
|
resetNavigationStack,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (objectNameSingular === CoreObjectNameSingular.WorkflowRun) {
|
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 { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
|
||||||
|
|
||||||
import { ActionMenuDropdownHotkeyScope } from '@/action-menu/types/ActionMenuDropdownHotKeyScope';
|
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 { RecordBoardCardBody } from '@/object-record/record-board/record-board-card/components/RecordBoardCardBody';
|
||||||
import { RecordBoardCardHeader } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeader';
|
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';
|
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 { openDropdown } = useDropdownV2();
|
||||||
|
|
||||||
const { openRecordFromIndexView } = useOpenRecordFromIndexView();
|
const { openRecordFromIndexView } = useOpenRecordFromIndexView();
|
||||||
|
const { activateBoardCard } = useActiveRecordBoardCard(recordBoardId);
|
||||||
|
const { unfocusBoardCard } = useFocusedRecordBoardCard(recordBoardId);
|
||||||
|
|
||||||
const handleActionMenuDropdown = (event: React.MouseEvent) => {
|
const handleActionMenuDropdown = (event: React.MouseEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -156,6 +160,8 @@ export const RecordBoardCard = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleCardClick = () => {
|
const handleCardClick = () => {
|
||||||
|
activateBoardCard({ rowIndex, columnIndex });
|
||||||
|
unfocusBoardCard();
|
||||||
openRecordFromIndexView({ recordId });
|
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 { RecordBoardCardHeaderContainer } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeaderContainer';
|
||||||
import { StopPropagationContainer } from '@/object-record/record-board/record-board-card/components/StopPropagationContainer';
|
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 { 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 { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
|
||||||
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
|
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 { 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 { 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 { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
|
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { Dispatch, SetStateAction, useContext } from 'react';
|
import { Dispatch, SetStateAction, useContext } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
@ -45,11 +47,10 @@ export const RecordBoardCardHeader = ({
|
|||||||
|
|
||||||
const record = useRecoilValue(recordStoreFamilyState(recordId));
|
const record = useRecoilValue(recordStoreFamilyState(recordId));
|
||||||
|
|
||||||
const { objectMetadataItem } = useContext(RecordBoardContext);
|
const { objectMetadataItem, recordBoardId } = useContext(RecordBoardContext);
|
||||||
|
const { rowIndex, columnIndex } = useContext(RecordBoardCardContext);
|
||||||
const recordBoardId = useAvailableScopeIdOrThrow(
|
const { activateBoardCard } = useActiveRecordBoardCard(recordBoardId);
|
||||||
RecordBoardScopeInternalContext,
|
const { unfocusBoardCard } = useFocusedRecordBoardCard(recordBoardId);
|
||||||
);
|
|
||||||
|
|
||||||
const showCompactView = useRecoilComponentValueV2(
|
const showCompactView = useRecoilComponentValueV2(
|
||||||
isRecordBoardCompactModeActiveComponentState,
|
isRecordBoardCompactModeActiveComponentState,
|
||||||
@ -66,6 +67,12 @@ export const RecordBoardCardHeader = ({
|
|||||||
|
|
||||||
const { openRecordFromIndexView } = useOpenRecordFromIndexView();
|
const { openRecordFromIndexView } = useOpenRecordFromIndexView();
|
||||||
|
|
||||||
|
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
|
||||||
|
const triggerEvent =
|
||||||
|
recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL
|
||||||
|
? 'CLICK'
|
||||||
|
: 'MOUSE_DOWN';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RecordBoardCardHeaderContainer showCompactView={showCompactView}>
|
<RecordBoardCardHeaderContainer showCompactView={showCompactView}>
|
||||||
<StopPropagationContainer>
|
<StopPropagationContainer>
|
||||||
@ -76,9 +83,11 @@ export const RecordBoardCardHeader = ({
|
|||||||
variant={AvatarChipVariant.Transparent}
|
variant={AvatarChipVariant.Transparent}
|
||||||
maxWidth={150}
|
maxWidth={150}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
activateBoardCard({ rowIndex, columnIndex });
|
||||||
|
unfocusBoardCard();
|
||||||
openRecordFromIndexView({ recordId });
|
openRecordFromIndexView({ recordId });
|
||||||
}}
|
}}
|
||||||
triggerEvent="CLICK"
|
triggerEvent={triggerEvent}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</StopPropagationContainer>
|
</StopPropagationContainer>
|
||||||
|
|||||||
@ -71,6 +71,7 @@ export const useOpenRecordFromIndexView = () => {
|
|||||||
openRecordInCommandMenu({
|
openRecordInCommandMenu({
|
||||||
recordId,
|
recordId,
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
|
resetNavigationStack: true,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
navigate(AppPath.RecordShowPage, {
|
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 { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly';
|
||||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||||
import { useOpenRecordFromIndexView } from '@/object-record/record-index/hooks/useOpenRecordFromIndexView';
|
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 { RecordUpdateContext } from '@/object-record/record-table/contexts/EntityUpdateMutationHookContext';
|
||||||
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
|
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
|
||||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||||
import { useRecordTableRowContextOrThrow } from '@/object-record/record-table/contexts/RecordTableRowContext';
|
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 { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState';
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
|
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
|
||||||
import { ReactNode, useContext } from 'react';
|
import { ReactNode, useContext } from 'react';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
import { useIsMobile } from 'twenty-ui/utilities';
|
import { useIsMobile } from 'twenty-ui/utilities';
|
||||||
|
|
||||||
type RecordTableCellFieldContextLabelIdentifierProps = {
|
type RecordTableCellFieldContextLabelIdentifierProps = {
|
||||||
@ -25,7 +30,10 @@ export const RecordTableCellFieldContextLabelIdentifier = ({
|
|||||||
useRecordTableRowContextOrThrow();
|
useRecordTableRowContextOrThrow();
|
||||||
|
|
||||||
const { columnDefinition } = useContext(RecordTableCellContext);
|
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 isMobile = useIsMobile();
|
||||||
const isRecordTableScrolledLeftComponent = useRecoilComponentValueV2(
|
const isRecordTableScrolledLeftComponent = useRecoilComponentValueV2(
|
||||||
@ -51,6 +59,12 @@ export const RecordTableCellFieldContextLabelIdentifier = ({
|
|||||||
|
|
||||||
const { openRecordFromIndexView } = useOpenRecordFromIndexView();
|
const { openRecordFromIndexView } = useOpenRecordFromIndexView();
|
||||||
|
|
||||||
|
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
|
||||||
|
const triggerEvent =
|
||||||
|
recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL
|
||||||
|
? 'CLICK'
|
||||||
|
: 'MOUSE_DOWN';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FieldContext.Provider
|
<FieldContext.Provider
|
||||||
value={{
|
value={{
|
||||||
@ -64,9 +78,12 @@ export const RecordTableCellFieldContextLabelIdentifier = ({
|
|||||||
isReadOnly: isFieldReadOnly,
|
isReadOnly: isFieldReadOnly,
|
||||||
maxWidth: columnDefinition.size,
|
maxWidth: columnDefinition.size,
|
||||||
onRecordChipClick: () => {
|
onRecordChipClick: () => {
|
||||||
|
activateRecordTableRow(rowIndex);
|
||||||
|
unfocusRecordTableRow();
|
||||||
openRecordFromIndexView({ recordId });
|
openRecordFromIndexView({ recordId });
|
||||||
},
|
},
|
||||||
isForbidden: !hasObjectReadPermissions,
|
isForbidden: !hasObjectReadPermissions,
|
||||||
|
triggerEvent,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
Reference in New Issue
Block a user