Fix hovered portal on table with groups (#14512)
This PR fixes https://github.com/twentyhq/twenty/issues/13022 It was due to a mouse leave event that worked for table without groups but not with table with groups, the fix is to handle this event higher up in the table. This PR also fixes a bug that happened when hiding a column, the page crashed because of an indexed array returning undefined that TS didn't catch, linked to https://github.com/twentyhq/core-team-issues/issues/1205.
This commit is contained in:
+19
@@ -9,9 +9,13 @@ import { RecordTableNoRecordGroupBody } from '@/object-record/record-table/recor
|
||||
import { RecordTableRecordGroupsBody } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody';
|
||||
import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader';
|
||||
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
|
||||
import { recordTableHoverPositionComponentState } from '@/object-record/record-table/states/recordTableHoverPositionComponentState';
|
||||
import { isSomeCellInEditModeComponentSelector } from '@/object-record/record-table/states/selectors/isSomeCellInEditModeComponentSelector';
|
||||
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
|
||||
import { RECORD_INDEX_DRAG_SELECT_BOUNDARY_CLASS } from '@/ui/utilities/drag-select/constants/RecordIndecDragSelectBoundaryClass';
|
||||
import { useRecoilComponentFamilyCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyCallbackState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRef, useState } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
@@ -68,6 +72,20 @@ export const RecordTableContent = ({
|
||||
|
||||
const { lastColumnWidth } = useRecordTableLastColumnWidthToFill();
|
||||
|
||||
const setRecordTableHoverPosition = useSetRecoilComponentState(
|
||||
recordTableHoverPositionComponentState,
|
||||
);
|
||||
|
||||
const isSomeCellInEditMode = useRecoilComponentValue(
|
||||
isSomeCellInEditModeComponentSelector,
|
||||
);
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
if (!isSomeCellInEditMode) {
|
||||
setRecordTableHoverPosition(null);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledTableContainer ref={containerRef}>
|
||||
<RecordTableStyleWrapper
|
||||
@@ -76,6 +94,7 @@ export const RecordTableContent = ({
|
||||
visibleRecordFields={visibleRecordFields}
|
||||
lastColumnWidth={lastColumnWidth}
|
||||
id={RECORD_TABLE_HTML_ID}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<RecordTableHeader />
|
||||
{hasRecordGroups ? (
|
||||
|
||||
-6
@@ -1,6 +1,5 @@
|
||||
import { RecordTableBodyContextProvider } from '@/object-record/record-table/contexts/RecordTableBodyContext';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { useHandleContainerMouseEnter } from '@/object-record/record-table/hooks/internal/useHandleContainerMouseEnter';
|
||||
import { useRecordTableMoveFocusedCell } from '@/object-record/record-table/hooks/useRecordTableMoveFocusedCell';
|
||||
import { useCloseRecordTableCellNoGroup } from '@/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellNoGroup';
|
||||
import { useMoveHoverToCurrentCell } from '@/object-record/record-table/record-table-cell/hooks/useMoveHoverToCurrentCell';
|
||||
@@ -57,10 +56,6 @@ export const RecordTableNoRecordGroupBodyContextProvider = ({
|
||||
triggerActionMenuDropdown(event, recordId);
|
||||
};
|
||||
|
||||
const { handleContainerMouseEnter } = useHandleContainerMouseEnter({
|
||||
recordTableId,
|
||||
});
|
||||
|
||||
return (
|
||||
<RecordTableBodyContextProvider
|
||||
value={{
|
||||
@@ -69,7 +64,6 @@ export const RecordTableNoRecordGroupBodyContextProvider = ({
|
||||
onCloseTableCell: handleCloseTableCell,
|
||||
onMoveHoverToCurrentCell: handleMoveHoverToCurrentCell,
|
||||
onActionMenuDropdownOpened: handleActionMenuDropdown,
|
||||
onCellMouseEnter: handleContainerMouseEnter,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
-6
@@ -1,6 +1,5 @@
|
||||
import { RecordTableBodyContextProvider } from '@/object-record/record-table/contexts/RecordTableBodyContext';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { useHandleContainerMouseEnter } from '@/object-record/record-table/hooks/internal/useHandleContainerMouseEnter';
|
||||
import { useRecordTableMoveFocusedCell } from '@/object-record/record-table/hooks/useRecordTableMoveFocusedCell';
|
||||
import { useCloseRecordTableCellInGroup } from '@/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellInGroup';
|
||||
import { useMoveHoverToCurrentCell } from '@/object-record/record-table/record-table-cell/hooks/useMoveHoverToCurrentCell';
|
||||
@@ -58,10 +57,6 @@ export const RecordTableRecordGroupBodyContextProvider = ({
|
||||
triggerActionMenuDropdown(event, recordId);
|
||||
};
|
||||
|
||||
const { handleContainerMouseEnter } = useHandleContainerMouseEnter({
|
||||
recordTableId,
|
||||
});
|
||||
|
||||
return (
|
||||
<RecordTableBodyContextProvider
|
||||
value={{
|
||||
@@ -70,7 +65,6 @@ export const RecordTableRecordGroupBodyContextProvider = ({
|
||||
onCloseTableCell: handlecloseTableCellInGroup,
|
||||
onMoveHoverToCurrentCell: handleMoveHoverToCurrentCell,
|
||||
onActionMenuDropdownOpened: handleActionMenuDropdown,
|
||||
onCellMouseEnter: handleContainerMouseEnter,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
-1
@@ -174,7 +174,6 @@ const meta: Meta = {
|
||||
onCloseTableCell: () => {},
|
||||
onMoveHoverToCurrentCell: () => {},
|
||||
onActionMenuDropdownOpened: () => {},
|
||||
onCellMouseEnter: () => {},
|
||||
}}
|
||||
>
|
||||
<RecordTableRowContextProvider
|
||||
|
||||
-2
@@ -1,6 +1,5 @@
|
||||
import type React from 'react';
|
||||
|
||||
import { type HandleContainerMouseEnterArgs } from '@/object-record/record-table/hooks/internal/useHandleContainerMouseEnter';
|
||||
import { type OpenTableCellArgs } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCell';
|
||||
import { type MoveFocusDirection } from '@/object-record/record-table/types/MoveFocusDirection';
|
||||
import { type TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
|
||||
@@ -16,7 +15,6 @@ export type RecordTableBodyContextProps = {
|
||||
event: React.MouseEvent,
|
||||
recordId: string,
|
||||
) => void;
|
||||
onCellMouseEnter: (args: HandleContainerMouseEnterArgs) => void;
|
||||
};
|
||||
|
||||
export const [
|
||||
|
||||
-19
@@ -1,9 +1,5 @@
|
||||
import { RecordTableBody } from '@/object-record/record-table/record-table-body/components/RecordTableBody';
|
||||
import { RecordTableBodyDroppableContextProvider } from '@/object-record/record-table/record-table-body/contexts/RecordTableBodyDroppableContext';
|
||||
import { recordTableHoverPositionComponentState } from '@/object-record/record-table/states/recordTableHoverPositionComponentState';
|
||||
import { isSomeCellInEditModeComponentSelector } from '@/object-record/record-table/states/selectors/isSomeCellInEditModeComponentSelector';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { Droppable } from '@hello-pangea/dnd';
|
||||
import { type ReactNode, useState } from 'react';
|
||||
import { v4 } from 'uuid';
|
||||
@@ -21,20 +17,6 @@ export const RecordTableBodyDroppable = ({
|
||||
}: RecordTableBodyDroppableProps) => {
|
||||
const [v4Persistable] = useState(v4());
|
||||
|
||||
const setRecordTableHoverPosition = useSetRecoilComponentState(
|
||||
recordTableHoverPositionComponentState,
|
||||
);
|
||||
|
||||
const isSomeCellInEditMode = useRecoilComponentValue(
|
||||
isSomeCellInEditModeComponentSelector,
|
||||
);
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
if (!isSomeCellInEditMode) {
|
||||
setRecordTableHoverPosition(null);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Droppable
|
||||
droppableId={recordGroupId ?? v4Persistable}
|
||||
@@ -46,7 +28,6 @@ export const RecordTableBodyDroppable = ({
|
||||
ref={provided.innerRef}
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...provided.droppableProps}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<RecordTableBodyDroppableContextProvider
|
||||
value={{ droppablePlaceholder: provided.placeholder }}
|
||||
|
||||
+2
-5
@@ -75,14 +75,11 @@ export const RecordTableCellBaseContainer = ({
|
||||
fieldDefinition,
|
||||
isLabelIdentifier,
|
||||
);
|
||||
const { onMoveHoverToCurrentCell, onCellMouseEnter } =
|
||||
useRecordTableBodyContextOrThrow();
|
||||
const { onMoveHoverToCurrentCell } = useRecordTableBodyContextOrThrow();
|
||||
|
||||
const handleContainerMouseMove = () => {
|
||||
setIsFocused(true);
|
||||
onCellMouseEnter({
|
||||
cellPosition,
|
||||
});
|
||||
onMoveHoverToCurrentCell(cellPosition);
|
||||
};
|
||||
|
||||
const handleContainerMouseLeave = () => {
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@ import { RecordTableCellHoveredPortalContent } from '@/object-record/record-tabl
|
||||
import { RecordTableCellPortalRootContainer } from '@/object-record/record-table/record-table-cell/components/RecordTableCellPortalRootContainer';
|
||||
import { isRecordTableScrolledHorizontallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledHorizontallyComponentState';
|
||||
import { isRecordTableScrolledVerticallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledVerticallyComponentState';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const RecordTableCellHoveredPortal = () => {
|
||||
const hoverPosition = useRecoilComponentValue(
|
||||
@@ -26,7 +27,7 @@ export const RecordTableCellHoveredPortal = () => {
|
||||
hasRecordGroupsComponentSelector,
|
||||
);
|
||||
|
||||
if (!hoverPosition) {
|
||||
if (!isDefined(hoverPosition)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+8
-4
@@ -42,6 +42,12 @@ export const RecordTableCellPortalContexts = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
const recordField = visibleRecordFields[hoverPosition.column];
|
||||
|
||||
if (!isDefined(recordField)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<RecordTableRowContextProvider
|
||||
value={{
|
||||
@@ -59,13 +65,11 @@ export const RecordTableCellPortalContexts = ({
|
||||
>
|
||||
<RecordTableCellContext.Provider
|
||||
value={{
|
||||
recordField: visibleRecordFields[hoverPosition.column],
|
||||
recordField,
|
||||
cellPosition: hoverPosition,
|
||||
}}
|
||||
>
|
||||
<RecordTableCellFieldContextWrapper
|
||||
recordField={visibleRecordFields[hoverPosition.column]}
|
||||
>
|
||||
<RecordTableCellFieldContextWrapper recordField={recordField}>
|
||||
{children}
|
||||
</RecordTableCellFieldContextWrapper>
|
||||
</RecordTableCellContext.Provider>
|
||||
|
||||
+8
-1
@@ -6,6 +6,7 @@ import { RecordTableCellFirstRowFirstColumn } from '@/object-record/record-table
|
||||
import { RecordTableCellStyleWrapper } from '@/object-record/record-table/record-table-cell/components/RecordTableCellStyleWrapper';
|
||||
import { RecordTableCellWrapper } from '@/object-record/record-table/record-table-cell/components/RecordTableCellWrapper';
|
||||
import { getRecordTableColumnFieldWidthClassName } from '@/object-record/record-table/utils/getRecordTableColumnFieldWidthClassName';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { isNonEmptyArray } from '~/utils/isNonEmptyArray';
|
||||
|
||||
export const RecordTableCellsVisible = () => {
|
||||
@@ -23,10 +24,16 @@ export const RecordTableCellsVisible = () => {
|
||||
|
||||
const isFirstRow = rowIndex === 0;
|
||||
|
||||
const firstRecordField = visibleRecordFields[0];
|
||||
|
||||
if (!isDefined(firstRecordField)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<RecordTableCellWrapper
|
||||
recordField={visibleRecordFields[0]}
|
||||
recordField={firstRecordField}
|
||||
recordFieldIndex={0}
|
||||
>
|
||||
{isFirstRow ? (
|
||||
|
||||
@@ -169,7 +169,6 @@ const InternalTableContextProviders = ({
|
||||
>
|
||||
<RecordTableBodyContextProvider
|
||||
value={{
|
||||
onCellMouseEnter: () => {},
|
||||
onCloseTableCell: () => {},
|
||||
onOpenTableCell: () => {},
|
||||
onActionMenuDropdownOpened: () => {},
|
||||
|
||||
Reference in New Issue
Block a user