Modal API Refactoring (#12062)
# Modal API Refactoring This PR refactors the modal system to use an imperative approach for setting hotkey scopes, addressing race conditions that occurred with the previous effect-based implementation. Fixes #11986 Closes #12087 ## Key Changes: - **New Modal API**: Introduced a `useModal` hook with `openModal`, `closeModal`, and `toggleModal` functions, similar to the existing dropdown API - **Modal Identification**: Added a `modalId` prop to uniquely identify modals - **State Management**: Introduced `isModalOpenedComponentState` and removed individual boolean state atoms (like `isRemoveSortingModalOpenState`) - **Modal Constants**: Added consistent modal ID constants (e.g., `FavoriteFolderDeleteModalId`, `RecordIndexRemoveSortingModalId`) for better maintainability - **Mount Effects**: Created mount effect components (like `AuthModalMountEffect`) to handle initial modal opening where needed ## Implementation Details: - Modified `Modal` and `ConfirmationModal` components to accept the new `modalId` prop - Added a component-state-based approach using `ModalComponentInstanceContext` to track modal state - Introduced imperative modal handlers that properly manage hotkey scopes - Components like `ActionModal` and `AttachmentList` now use the new `useModal` hook for better control over modal state ## Benefits: - **Race Condition Prevention**: Hotkey scopes are now set imperatively, eliminating race conditions - **Consistent API**: Modal and dropdown now share similar patterns, improving developer experience ## Tests to do before merging: 1. Action Modals (Modal triggered by an action, for example the delete action) 2. Auth Modal (`AuthModal.tsx` and `AuthModalMountEffect.tsx`) - Test that auth modal opens automatically on mount - Verify authentication flow works properly 3. Email Verification Sent Modal (in `SignInUp.tsx`) - Verify this modal displays correctly 4. Attachment Preview Modal (in `AttachmentList.tsx`) - Test opening preview modal by clicking on attachments - Verify close, download functionality works - Test modal navigation and interactions 5. Favorite Folder Delete Modal (`CurrentWorkspaceMemberFavorites.tsx`) - Test deletion confirmation flow - Check that modal opens when attempting to delete folders with favorites 6. Record Board Remove Sorting Modal (`RecordBoard.tsx` using `RecordIndexRemoveSortingModalId`) - Test that modal appears when trying to drag records with sorting enabled - Verify sorting removal works correctly 7. Record Group Reorder Confirmation Modal (`RecordGroupReorderConfirmationModal.tsx`) - Test group reordering with sorting enabled - Verify confirmation modal properly handles sorting removal 8. Confirmation Modal (base component used by several modals) - Test all variants with different confirmation options For each modal, verify: - Opening/closing behavior - Hotkey support (Esc to close, Enter to confirm where applicable) - Click outside behavior - Proper z-index stacking - Any modal-specific functionality
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { DragDropContext, OnDragEndResponder } from '@hello-pangea/dnd'; // Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350
|
||||
import { useContext, useRef } from 'react';
|
||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
|
||||
import { RecordBoardHeader } from '@/object-record/record-board/components/RecordBoardHeader';
|
||||
@ -19,11 +19,12 @@ import { RecordBoardComponentInstanceContext } from '@/object-record/record-boar
|
||||
import { getDraggedRecordPosition } from '@/object-record/record-board/utils/getDraggedRecordPosition';
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { visibleRecordGroupIdsComponentFamilySelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentFamilySelector';
|
||||
import { RECORD_INDEX_REMOVE_SORTING_MODAL_ID } from '@/object-record/record-index/constants/RecordIndexRemoveSortingModalId';
|
||||
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
|
||||
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
@ -120,9 +121,7 @@ export const RecordBoard = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const setIsRemoveSortingModalOpen = useSetRecoilState(
|
||||
isRemoveSortingModalOpenState,
|
||||
);
|
||||
const { openModal } = useModal();
|
||||
|
||||
const handleDragEnd: OnDragEndResponder = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
@ -130,7 +129,7 @@ export const RecordBoard = () => {
|
||||
if (!result.destination) return;
|
||||
|
||||
if (currentRecordSorts.length > 0) {
|
||||
setIsRemoveSortingModalOpen(true);
|
||||
openModal(RECORD_INDEX_REMOVE_SORTING_MODAL_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -189,7 +188,7 @@ export const RecordBoard = () => {
|
||||
recordIndexRecordIdsByGroupFamilyState,
|
||||
selectFieldMetadataItem,
|
||||
updateOneRecord,
|
||||
setIsRemoveSortingModalOpen,
|
||||
openModal,
|
||||
currentRecordSorts,
|
||||
],
|
||||
);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { isRecordGroupReorderConfirmationModalVisibleState } from '@/object-record/record-group/states/isRecordGroupReorderConfirmationModalVisibleState';
|
||||
import { RECORD_GROUP_REORDER_CONFIRMATION_MODAL_ID } from '@/object-record/record-group/constants/RecordGroupReorderConfirmationModalId';
|
||||
import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
type RecordGroupReorderConfirmationModalProps = {
|
||||
onConfirmClick: () => void;
|
||||
@ -12,23 +11,13 @@ type RecordGroupReorderConfirmationModalProps = {
|
||||
export const RecordGroupReorderConfirmationModal = ({
|
||||
onConfirmClick,
|
||||
}: RecordGroupReorderConfirmationModalProps) => {
|
||||
const [
|
||||
isRecordGroupReorderConfirmationModalVisible,
|
||||
setIsRecordGroupReorderConfirmationModalVisible,
|
||||
] = useRecoilState(isRecordGroupReorderConfirmationModalVisibleState);
|
||||
|
||||
const recordGroupSort = useRecoilComponentValueV2(
|
||||
recordIndexRecordGroupSortComponentState,
|
||||
);
|
||||
|
||||
if (!isRecordGroupReorderConfirmationModalVisible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return createPortal(
|
||||
<ConfirmationModal
|
||||
isOpen={isRecordGroupReorderConfirmationModalVisible}
|
||||
setIsOpen={setIsRecordGroupReorderConfirmationModalVisible}
|
||||
modalId={RECORD_GROUP_REORDER_CONFIRMATION_MODAL_ID}
|
||||
title="Group sorting"
|
||||
subtitle={`Would you like to remove ${recordGroupSort} group sorting?`}
|
||||
onConfirmClick={onConfirmClick}
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
export const RECORD_GROUP_REORDER_CONFIRMATION_MODAL_ID =
|
||||
'record-group-reorder-confirmation-modal';
|
||||
@ -1,16 +1,16 @@
|
||||
import { RECORD_GROUP_REORDER_CONFIRMATION_MODAL_ID } from '@/object-record/record-group/constants/RecordGroupReorderConfirmationModalId';
|
||||
import { useReorderRecordGroups } from '@/object-record/record-group/hooks/useReorderRecordGroups';
|
||||
import { isRecordGroupReorderConfirmationModalVisibleState } from '@/object-record/record-group/states/isRecordGroupReorderConfirmationModalVisibleState';
|
||||
import { RecordGroupSort } from '@/object-record/record-group/types/RecordGroupSort';
|
||||
import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState';
|
||||
import { recordIndexRecordGroupIsDraggableSortComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexRecordGroupIsDraggableSortComponentSelector';
|
||||
import { useGoBackToPreviousDropdownFocusId } from '@/ui/layout/dropdown/hooks/useGoBackToPreviousDropdownFocusId';
|
||||
import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||
import { useState } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
type UseRecordGroupReorderConfirmationModalParams = {
|
||||
recordIndexId: string;
|
||||
@ -26,9 +26,7 @@ export const useRecordGroupReorderConfirmationModal = ({
|
||||
const { goBackToPreviousDropdownFocusId } =
|
||||
useGoBackToPreviousDropdownFocusId();
|
||||
|
||||
const setIsRecordGroupReorderConfirmationModalVisible = useSetRecoilState(
|
||||
isRecordGroupReorderConfirmationModalVisibleState,
|
||||
);
|
||||
const { openModal } = useModal();
|
||||
|
||||
const [pendingDragEndHandlerParams, setPendingDragEndHandlerParams] =
|
||||
useState<Parameters<OnDragEndResponder> | null>(null);
|
||||
@ -58,7 +56,7 @@ export const useRecordGroupReorderConfirmationModal = ({
|
||||
|
||||
const handleDragEndWithModal: OnDragEndResponder = (result, provided) => {
|
||||
if (!isDragableSortRecordGroup) {
|
||||
setIsRecordGroupReorderConfirmationModalVisible(true);
|
||||
openModal(RECORD_GROUP_REORDER_CONFIRMATION_MODAL_ID);
|
||||
setActiveDropdownFocusIdAndMemorizePrevious(null);
|
||||
setPendingDragEndHandlerParams([result, provided]);
|
||||
} else {
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
export const isRecordGroupReorderConfirmationModalVisibleState = atom<boolean>({
|
||||
key: 'isRecordGroupReorderConfirmationModalVisibleState',
|
||||
default: false,
|
||||
});
|
||||
@ -9,7 +9,10 @@ import { RecordBoardBodyEscapeHotkeyEffect } from '@/object-record/record-board/
|
||||
import { RecordBoardHotkeyEffect } from '@/object-record/record-board/components/RecordBoardHotkeyEffect';
|
||||
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
|
||||
import { RecordIndexRemoveSortingModal } from '@/object-record/record-index/components/RecordIndexRemoveSortingModal';
|
||||
import { RECORD_INDEX_REMOVE_SORTING_MODAL_ID } from '@/object-record/record-index/constants/RecordIndexRemoveSortingModalId';
|
||||
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
|
||||
import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
type RecordIndexBoardContainerProps = {
|
||||
recordBoardId: string;
|
||||
viewBarId: string;
|
||||
@ -39,6 +42,11 @@ export const RecordIndexBoardContainer = ({
|
||||
shouldMatchRootQueryFilter: true,
|
||||
});
|
||||
|
||||
const isRecordIndexRemoveSortingModalOpened = useRecoilComponentValueV2(
|
||||
isModalOpenedComponentState,
|
||||
RECORD_INDEX_REMOVE_SORTING_MODAL_ID,
|
||||
);
|
||||
|
||||
if (!selectFieldMetadataItem) {
|
||||
return;
|
||||
}
|
||||
@ -55,7 +63,9 @@ export const RecordIndexBoardContainer = ({
|
||||
}}
|
||||
>
|
||||
<RecordBoard />
|
||||
<RecordIndexRemoveSortingModal />
|
||||
{isRecordIndexRemoveSortingModalOpened && (
|
||||
<RecordIndexRemoveSortingModal />
|
||||
)}
|
||||
<RecordBoardHotkeyEffect />
|
||||
<RecordBoardBodyEscapeHotkeyEffect />
|
||||
</RecordBoardContext.Provider>
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { RECORD_INDEX_REMOVE_SORTING_MODAL_ID } from '@/object-record/record-index/constants/RecordIndexRemoveSortingModalId';
|
||||
import { useRemoveRecordSort } from '@/object-record/record-sort/hooks/useRemoveRecordSort';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
@ -14,8 +12,6 @@ export const RecordIndexRemoveSortingModal = () => {
|
||||
const fieldMetadataIds = currentRecordSorts.map(
|
||||
(viewSort) => viewSort.fieldMetadataId,
|
||||
);
|
||||
const [isRemoveSortingModalOpen, setIsRemoveSortingModalOpen] =
|
||||
useRecoilState(isRemoveSortingModalOpenState);
|
||||
|
||||
const { removeRecordSort } = useRemoveRecordSort();
|
||||
|
||||
@ -26,15 +22,12 @@ export const RecordIndexRemoveSortingModal = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConfirmationModal
|
||||
isOpen={isRemoveSortingModalOpen}
|
||||
setIsOpen={setIsRemoveSortingModalOpen}
|
||||
title={'Remove sorting?'}
|
||||
subtitle={'This is required to enable manual row reordering.'}
|
||||
onConfirmClick={handleRemoveClick}
|
||||
confirmButtonText={'Remove Sorting'}
|
||||
/>
|
||||
</>
|
||||
<ConfirmationModal
|
||||
modalId={RECORD_INDEX_REMOVE_SORTING_MODAL_ID}
|
||||
title={'Remove sorting?'}
|
||||
subtitle={'This is required to enable manual row reordering.'}
|
||||
onConfirmClick={handleRemoveClick}
|
||||
confirmButtonText={'Remove Sorting'}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { RecordUpdateHookParams } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { RecordIndexRemoveSortingModal } from '@/object-record/record-index/components/RecordIndexRemoveSortingModal';
|
||||
import { RECORD_INDEX_REMOVE_SORTING_MODAL_ID } from '@/object-record/record-index/constants/RecordIndexRemoveSortingModalId';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers';
|
||||
import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
type RecordIndexTableContainerProps = {
|
||||
recordTableId: string;
|
||||
@ -15,6 +18,11 @@ export const RecordIndexTableContainer = ({
|
||||
}: RecordIndexTableContainerProps) => {
|
||||
const { objectNameSingular } = useRecordIndexContextOrThrow();
|
||||
|
||||
const isRecordIndexRemoveSortingModalOpened = useRecoilComponentValueV2(
|
||||
isModalOpenedComponentState,
|
||||
RECORD_INDEX_REMOVE_SORTING_MODAL_ID,
|
||||
);
|
||||
|
||||
const { updateOneRecord } = useUpdateOneRecord({
|
||||
objectNameSingular,
|
||||
});
|
||||
@ -34,7 +42,9 @@ export const RecordIndexTableContainer = ({
|
||||
viewBarId={viewBarId}
|
||||
updateRecordMutation={updateEntity}
|
||||
/>
|
||||
<RecordIndexRemoveSortingModal />
|
||||
{isRecordIndexRemoveSortingModalOpened && (
|
||||
<RecordIndexRemoveSortingModal />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
export const RECORD_INDEX_REMOVE_SORTING_MODAL_ID =
|
||||
'record-index-remove-sorting-modal';
|
||||
@ -1,7 +1,7 @@
|
||||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useCallback, useContext, useState } from 'react';
|
||||
import { useCallback, useContext } from 'react';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
@ -34,6 +34,7 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { createPortal } from 'react-dom';
|
||||
import {
|
||||
IconChevronDown,
|
||||
@ -87,6 +88,8 @@ const StyledClickableZone = styled.div`
|
||||
|
||||
const MotionIconChevronDown = motion.create(IconChevronDown);
|
||||
|
||||
const DELETE_RELATION_MODAL_ID = 'delete-relation-modal';
|
||||
|
||||
type RecordDetailRelationRecordsListItemProps = {
|
||||
isExpanded: boolean;
|
||||
onClick: (relationRecordId: string) => void;
|
||||
@ -100,8 +103,7 @@ export const RecordDetailRelationRecordsListItem = ({
|
||||
}: RecordDetailRelationRecordsListItemProps) => {
|
||||
const { fieldDefinition } = useContext(FieldContext);
|
||||
|
||||
const [isDeleteRelationModalOpen, setIsDeleteRelationModalOpen] =
|
||||
useState(false);
|
||||
const { openModal } = useModal();
|
||||
|
||||
const {
|
||||
relationFieldMetadataId,
|
||||
@ -173,13 +175,12 @@ export const RecordDetailRelationRecordsListItem = ({
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
setIsDeleteRelationModalOpen(true);
|
||||
closeDropdown();
|
||||
openModal(DELETE_RELATION_MODAL_ID);
|
||||
};
|
||||
|
||||
const handleConfirmDelete = async () => {
|
||||
await deleteOneRelationRecord(relationRecord.id);
|
||||
setIsDeleteRelationModalOpen(false);
|
||||
};
|
||||
|
||||
const useUpdateOneObjectRecordMutation: RecordUpdateHook = () => {
|
||||
@ -306,8 +307,7 @@ export const RecordDetailRelationRecordsListItem = ({
|
||||
</AnimatedEaseInOut>
|
||||
{createPortal(
|
||||
<ConfirmationModal
|
||||
isOpen={isDeleteRelationModalOpen}
|
||||
setIsOpen={setIsDeleteRelationModalOpen}
|
||||
modalId={DELETE_RELATION_MODAL_ID}
|
||||
title={`Delete Related ${relationObjectTypeName}`}
|
||||
subtitle={
|
||||
<>
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
import { DragDropContext, DropResult } from '@hello-pangea/dnd';
|
||||
import { ReactNode } from 'react';
|
||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { getDraggedRecordPosition } from '@/object-record/record-board/utils/getDraggedRecordPosition';
|
||||
import { RECORD_INDEX_REMOVE_SORTING_MODAL_ID } from '@/object-record/record-index/constants/RecordIndexRemoveSortingModalId';
|
||||
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
@ -33,15 +34,13 @@ export const RecordTableBodyDragDropContextProvider = ({
|
||||
currentRecordSortsComponentState,
|
||||
);
|
||||
|
||||
const setIsRemoveSortingModalOpen = useSetRecoilState(
|
||||
isRemoveSortingModalOpenState,
|
||||
);
|
||||
const { openModal } = useModal();
|
||||
|
||||
const handleDragEnd = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(result: DropResult) => {
|
||||
if (currentRecordSorts.length > 0) {
|
||||
setIsRemoveSortingModalOpen(true);
|
||||
openModal(RECORD_INDEX_REMOVE_SORTING_MODAL_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -100,10 +99,10 @@ export const RecordTableBodyDragDropContextProvider = ({
|
||||
});
|
||||
},
|
||||
[
|
||||
currentRecordSorts.length,
|
||||
recordIndexAllRecordIdsSelector,
|
||||
setIsRemoveSortingModalOpen,
|
||||
updateOneRow,
|
||||
currentRecordSorts,
|
||||
openModal,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
import { DragDropContext, DropResult } from '@hello-pangea/dnd';
|
||||
import { ReactNode } from 'react';
|
||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { getDraggedRecordPosition } from '@/object-record/record-board/utils/getDraggedRecordPosition';
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { RECORD_INDEX_REMOVE_SORTING_MODAL_ID } from '@/object-record/record-index/constants/RecordIndexRemoveSortingModalId';
|
||||
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@ -26,9 +27,7 @@ export const RecordTableBodyRecordGroupDragDropContextProvider = ({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const setIsRemoveSortingModalOpen = useSetRecoilState(
|
||||
isRemoveSortingModalOpenState,
|
||||
);
|
||||
const { openModal } = useModal();
|
||||
|
||||
const recordIdsByGroupFamilyState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexRecordIdsByGroupComponentFamilyState,
|
||||
@ -73,7 +72,7 @@ export const RecordTableBodyRecordGroupDragDropContextProvider = ({
|
||||
}
|
||||
|
||||
if (currentRecordSorts.length > 0) {
|
||||
setIsRemoveSortingModalOpen(true);
|
||||
openModal(RECORD_INDEX_REMOVE_SORTING_MODAL_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -130,11 +129,11 @@ export const RecordTableBodyRecordGroupDragDropContextProvider = ({
|
||||
});
|
||||
},
|
||||
[
|
||||
currentRecordSortsCallbackState,
|
||||
objectMetadataItem.fields,
|
||||
recordIdsByGroupFamilyState,
|
||||
updateOneRow,
|
||||
setIsRemoveSortingModalOpen,
|
||||
currentRecordSortsCallbackState,
|
||||
openModal,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
export const isRemoveSortingModalOpenState = createState<boolean>({
|
||||
key: 'isRemoveSortingModalOpenState',
|
||||
defaultValue: false,
|
||||
});
|
||||
Reference in New Issue
Block a user