460 create restore one and restore many records action (#10647)
Closes https://github.com/twentyhq/core-team-issues/issues/460 https://github.com/user-attachments/assets/5271e56d-bf67-49cc-a8da-e25c12171e2e
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
import { useDeleteMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction';
|
||||
import { useExportMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction';
|
||||
import { useRestoreMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useRestoreMultipleRecordsAction';
|
||||
import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
|
||||
import { useImportRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useImportRecordsNoSelectionRecordAction';
|
||||
import { useSeeDeletedRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useSeeDeletedRecordsNoSelectionRecordAction';
|
||||
@ -7,6 +8,7 @@ import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-action
|
||||
import { useAddToFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useAddToFavoritesSingleRecordAction';
|
||||
import { useDeleteSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useDeleteSingleRecordAction';
|
||||
import { useRemoveFromFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useRemoveFromFavoritesSingleRecordAction';
|
||||
import { useRestoreSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useRestoreSingleRecordAction';
|
||||
import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
|
||||
import { ActionHook } from '@/action-menu/actions/types/ActionHook';
|
||||
import { ActionViewType } from '@/action-menu/actions/types/ActionViewType';
|
||||
@ -21,6 +23,7 @@ import {
|
||||
IconFileImport,
|
||||
IconHeart,
|
||||
IconHeartOff,
|
||||
IconRefresh,
|
||||
IconRotate2,
|
||||
IconTrash,
|
||||
} from 'twenty-ui';
|
||||
@ -127,13 +130,42 @@ export const DEFAULT_ACTIONS_CONFIG_V1: Record<
|
||||
availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
|
||||
useAction: useExportMultipleRecordsAction,
|
||||
},
|
||||
restoreSingleRecord: {
|
||||
type: ActionMenuEntryType.Standard,
|
||||
scope: ActionMenuEntryScope.RecordSelection,
|
||||
key: SingleRecordActionKeys.RESTORE,
|
||||
label: msg`Restore record`,
|
||||
shortLabel: msg`Restore`,
|
||||
position: 7,
|
||||
Icon: IconRefresh,
|
||||
accent: 'default',
|
||||
isPinned: true,
|
||||
availableOn: [
|
||||
ActionViewType.SHOW_PAGE,
|
||||
ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
|
||||
],
|
||||
useAction: useRestoreSingleRecordAction,
|
||||
},
|
||||
restoreMultipleRecords: {
|
||||
type: ActionMenuEntryType.Standard,
|
||||
scope: ActionMenuEntryScope.RecordSelection,
|
||||
key: MultipleRecordsActionKeys.RESTORE,
|
||||
label: msg`Restore records`,
|
||||
shortLabel: msg`Restore`,
|
||||
position: 8,
|
||||
Icon: IconRefresh,
|
||||
accent: 'default',
|
||||
isPinned: true,
|
||||
availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
|
||||
useAction: useRestoreMultipleRecordsAction,
|
||||
},
|
||||
seeDeletedRecords: {
|
||||
type: ActionMenuEntryType.Standard,
|
||||
scope: ActionMenuEntryScope.Object,
|
||||
key: NoSelectionRecordActionKeys.SEE_DELETED_RECORDS,
|
||||
label: msg`See deleted records`,
|
||||
shortLabel: msg`Deleted records`,
|
||||
position: 7,
|
||||
position: 9,
|
||||
Icon: IconRotate2,
|
||||
accent: 'default',
|
||||
isPinned: false,
|
||||
@ -146,7 +178,7 @@ export const DEFAULT_ACTIONS_CONFIG_V1: Record<
|
||||
key: NoSelectionRecordActionKeys.IMPORT_RECORDS,
|
||||
label: msg`Import records`,
|
||||
shortLabel: msg`Import`,
|
||||
position: 8,
|
||||
position: 10,
|
||||
Icon: IconFileImport,
|
||||
accent: 'default',
|
||||
isPinned: false,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { useDeleteMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction';
|
||||
import { useDestroyMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useDestroyMultipleRecordsAction';
|
||||
import { useExportMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction';
|
||||
import { useRestoreMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useRestoreMultipleRecordsAction';
|
||||
import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
|
||||
import { useCreateNewTableRecordNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useCreateNewTableRecordNoSelectionRecordAction';
|
||||
import { useImportRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useImportRecordsNoSelectionRecordAction';
|
||||
@ -13,6 +14,7 @@ import { useExportNoteAction } from '@/action-menu/actions/record-actions/single
|
||||
import { useNavigateToNextRecordSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useNavigateToNextRecordSingleRecordAction';
|
||||
import { useNavigateToPreviousRecordSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useNavigateToPreviousRecordSingleRecordAction';
|
||||
import { useRemoveFromFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useRemoveFromFavoritesSingleRecordAction';
|
||||
import { useRestoreSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useRestoreSingleRecordAction';
|
||||
import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
|
||||
import { ActionHook } from '@/action-menu/actions/types/ActionHook';
|
||||
import { ActionViewType } from '@/action-menu/actions/types/ActionViewType';
|
||||
@ -31,6 +33,7 @@ import {
|
||||
IconHeart,
|
||||
IconHeartOff,
|
||||
IconPlus,
|
||||
IconRefresh,
|
||||
IconRotate2,
|
||||
IconTrash,
|
||||
IconTrashX,
|
||||
@ -244,4 +247,33 @@ export const DEFAULT_ACTIONS_CONFIG_V2: Record<
|
||||
availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
|
||||
useAction: useDestroyMultipleRecordsAction,
|
||||
},
|
||||
restoreSingleRecord: {
|
||||
type: ActionMenuEntryType.Standard,
|
||||
scope: ActionMenuEntryScope.RecordSelection,
|
||||
key: SingleRecordActionKeys.RESTORE,
|
||||
label: msg`Restore record`,
|
||||
shortLabel: msg`Restore`,
|
||||
position: 15,
|
||||
Icon: IconRefresh,
|
||||
accent: 'default',
|
||||
isPinned: true,
|
||||
availableOn: [
|
||||
ActionViewType.SHOW_PAGE,
|
||||
ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
|
||||
],
|
||||
useAction: useRestoreSingleRecordAction,
|
||||
},
|
||||
restoreMultipleRecords: {
|
||||
type: ActionMenuEntryType.Standard,
|
||||
scope: ActionMenuEntryScope.RecordSelection,
|
||||
key: MultipleRecordsActionKeys.RESTORE,
|
||||
label: msg`Restore records`,
|
||||
shortLabel: msg`Restore`,
|
||||
position: 16,
|
||||
Icon: IconRefresh,
|
||||
accent: 'default',
|
||||
isPinned: true,
|
||||
availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
|
||||
useAction: useRestoreMultipleRecordsAction,
|
||||
},
|
||||
};
|
||||
|
||||
@ -347,4 +347,34 @@ export const WORKFLOW_ACTIONS_CONFIG: Record<
|
||||
availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
|
||||
useAction: useImportRecordsNoSelectionRecordAction,
|
||||
},
|
||||
// TODO: uncomment when restore is implemented for workflows
|
||||
// restoreSingleRecord: {
|
||||
// type: ActionMenuEntryType.Standard,
|
||||
// scope: ActionMenuEntryScope.RecordSelection,
|
||||
// key: SingleRecordActionKeys.RESTORE,
|
||||
// label: msg`Restore workflow`,
|
||||
// shortLabel: msg`Restore`,
|
||||
// position: 15,
|
||||
// Icon: IconRefresh,
|
||||
// accent: 'default',
|
||||
// isPinned: true,
|
||||
// availableOn: [
|
||||
// ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
|
||||
// ActionViewType.SHOW_PAGE,
|
||||
// ],
|
||||
// useAction: useRestoreSingleRecordAction,
|
||||
// },
|
||||
// restoreMultipleRecords: {
|
||||
// type: ActionMenuEntryType.Standard,
|
||||
// scope: ActionMenuEntryScope.RecordSelection,
|
||||
// key: MultipleRecordsActionKeys.RESTORE,
|
||||
// label: msg`Restore workflows`,
|
||||
// shortLabel: msg`Restore`,
|
||||
// position: 16,
|
||||
// Icon: IconRefresh,
|
||||
// accent: 'default',
|
||||
// isPinned: true,
|
||||
// availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
|
||||
// useAction: useRestoreMultipleRecordsAction,
|
||||
// },
|
||||
};
|
||||
|
||||
@ -115,7 +115,7 @@ export const useDeleteMultipleRecordsAction: ActionHookWithObjectMetadataItem =
|
||||
title={'Delete Records'}
|
||||
subtitle={`Are you sure you want to delete these records? They can be recovered from the Options menu.`}
|
||||
onConfirmClick={handleDeleteClick}
|
||||
deleteButtonText={'Delete Records'}
|
||||
confirmButtonText={'Delete Records'}
|
||||
/>
|
||||
);
|
||||
|
||||
|
||||
@ -126,7 +126,7 @@ export const useDestroyMultipleRecordsAction: ActionHookWithObjectMetadataItem =
|
||||
"Are you sure you want to destroy these records? They won't be recoverable anymore."
|
||||
}
|
||||
onConfirmClick={handleDestroyClick}
|
||||
deleteButtonText={'Destroy Records'}
|
||||
confirmButtonText={'Destroy Records'}
|
||||
/>
|
||||
);
|
||||
|
||||
|
||||
@ -0,0 +1,135 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook';
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
|
||||
import { BACKEND_BATCH_REQUEST_MAX_COUNT } from '@/object-record/constants/BackendBatchRequestMaxCount';
|
||||
import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize';
|
||||
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords';
|
||||
import { useRestoreManyRecords } from '@/object-record/hooks/useRestoreManyRecords';
|
||||
import { useCheckIsSoftDeleteFilter } from '@/object-record/record-filter/hooks/useCheckIsSoftDeleteFilter';
|
||||
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
||||
import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const useRestoreMultipleRecordsAction: ActionHookWithObjectMetadataItem =
|
||||
({ objectMetadataItem }) => {
|
||||
const [isRestoreRecordsModalOpen, setIsRestoreRecordsModalOpen] =
|
||||
useState(false);
|
||||
|
||||
const contextStoreCurrentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
if (!contextStoreCurrentViewId) {
|
||||
throw new Error('Current view ID is not defined');
|
||||
}
|
||||
|
||||
const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission();
|
||||
|
||||
const { resetTableRowSelection } = useRecordTable({
|
||||
recordTableId: getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
contextStoreCurrentViewId,
|
||||
),
|
||||
});
|
||||
|
||||
const { restoreManyRecords } = useRestoreManyRecords({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
);
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const contextStoreFilters = useRecoilComponentValueV2(
|
||||
contextStoreFiltersComponentState,
|
||||
);
|
||||
|
||||
const { filterValueDependencies } = useFilterValueDependencies();
|
||||
|
||||
const deletedAtFilter: RecordGqlOperationFilter = {
|
||||
deletedAt: { is: 'NOT_NULL' },
|
||||
};
|
||||
|
||||
const graphqlFilter = {
|
||||
...computeContextStoreFilters(
|
||||
contextStoreTargetedRecordsRule,
|
||||
contextStoreFilters,
|
||||
objectMetadataItem,
|
||||
filterValueDependencies,
|
||||
),
|
||||
...deletedAtFilter,
|
||||
};
|
||||
|
||||
const { checkIsSoftDeleteFilter } = useCheckIsSoftDeleteFilter();
|
||||
|
||||
const isDeletedFilterActive = contextStoreFilters.some(
|
||||
checkIsSoftDeleteFilter,
|
||||
);
|
||||
|
||||
const { fetchAllRecords: fetchAllRecordIds } = useLazyFetchAllRecords({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
filter: graphqlFilter,
|
||||
limit: DEFAULT_QUERY_PAGE_SIZE,
|
||||
recordGqlFields: { id: true },
|
||||
});
|
||||
|
||||
const handleRestoreClick = useCallback(async () => {
|
||||
const recordsToRestore = await fetchAllRecordIds();
|
||||
const recordIdsToRestore = recordsToRestore.map((record) => record.id);
|
||||
|
||||
resetTableRowSelection();
|
||||
|
||||
await restoreManyRecords({
|
||||
idsToRestore: recordIdsToRestore,
|
||||
});
|
||||
}, [restoreManyRecords, fetchAllRecordIds, resetTableRowSelection]);
|
||||
|
||||
const isRemoteObject = objectMetadataItem.isRemote;
|
||||
|
||||
const shouldBeRegistered =
|
||||
!hasObjectReadOnlyPermission &&
|
||||
!isRemoteObject &&
|
||||
isDeletedFilterActive &&
|
||||
isDefined(contextStoreNumberOfSelectedRecords) &&
|
||||
contextStoreNumberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT &&
|
||||
contextStoreNumberOfSelectedRecords > 0;
|
||||
|
||||
const onClick = () => {
|
||||
if (!shouldBeRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsRestoreRecordsModalOpen(true);
|
||||
};
|
||||
|
||||
const confirmationModal = (
|
||||
<ConfirmationModal
|
||||
isOpen={isRestoreRecordsModalOpen}
|
||||
setIsOpen={setIsRestoreRecordsModalOpen}
|
||||
title={'Restore Records'}
|
||||
subtitle={`Are you sure you want to restore these records?`}
|
||||
onConfirmClick={handleRestoreClick}
|
||||
confirmButtonText={'Restore Records'}
|
||||
/>
|
||||
);
|
||||
|
||||
return {
|
||||
shouldBeRegistered,
|
||||
onClick,
|
||||
ConfirmationModal: confirmationModal,
|
||||
};
|
||||
};
|
||||
@ -2,4 +2,5 @@ export enum MultipleRecordsActionKeys {
|
||||
DELETE = 'delete-multiple-records',
|
||||
EXPORT = 'export-multiple-records',
|
||||
DESTROY = 'destroy-multiple-records',
|
||||
RESTORE = 'restore-multiple-records',
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ export const useDeleteSingleRecordAction: ActionHookWithObjectMetadataItem = ({
|
||||
closeRightDrawer({ emitCloseEvent: false });
|
||||
}
|
||||
}}
|
||||
deleteButtonText={'Delete Record'}
|
||||
confirmButtonText={'Delete Record'}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
@ -86,7 +86,7 @@ export const useDestroySingleRecordAction: ActionHookWithObjectMetadataItem = ({
|
||||
closeRightDrawer();
|
||||
}
|
||||
}}
|
||||
deleteButtonText={'Permanently Destroy Record'}
|
||||
confirmButtonText={'Permanently Destroy Record'}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
|
||||
import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook';
|
||||
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
|
||||
import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
|
||||
import { useRestoreManyRecords } from '@/object-record/hooks/useRestoreManyRecords';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState';
|
||||
import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useCallback, useContext, useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const useRestoreSingleRecordAction: ActionHookWithObjectMetadataItem = ({
|
||||
objectMetadataItem,
|
||||
}) => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
|
||||
const [isRestoreRecordModalOpen, setIsRestoreRecordModalOpen] =
|
||||
useState(false);
|
||||
|
||||
const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission();
|
||||
|
||||
const { resetTableRowSelection } = useRecordTable({
|
||||
recordTableId: objectMetadataItem.namePlural,
|
||||
});
|
||||
|
||||
const { restoreManyRecords } = useRestoreManyRecords({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
|
||||
const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
|
||||
const { closeRightDrawer } = useRightDrawer();
|
||||
|
||||
const handleRestoreClick = useCallback(async () => {
|
||||
resetTableRowSelection();
|
||||
|
||||
await restoreManyRecords({
|
||||
idsToRestore: [recordId],
|
||||
});
|
||||
}, [restoreManyRecords, resetTableRowSelection, recordId]);
|
||||
|
||||
const isRemoteObject = objectMetadataItem.isRemote;
|
||||
|
||||
const isSoftDeleteFilterActive = useRecoilComponentValueV2(
|
||||
isSoftDeleteFilterActiveComponentState,
|
||||
);
|
||||
|
||||
const isShowPage =
|
||||
useRecoilComponentValueV2(contextStoreCurrentViewTypeComponentState) ===
|
||||
ContextStoreViewType.ShowPage;
|
||||
|
||||
const { isInRightDrawer } = useContext(ActionMenuContext);
|
||||
|
||||
const shouldBeRegistered =
|
||||
!isRemoteObject &&
|
||||
isDefined(selectedRecord?.deletedAt) &&
|
||||
!hasObjectReadOnlyPermission &&
|
||||
(isShowPage || isSoftDeleteFilterActive);
|
||||
|
||||
const onClick = () => {
|
||||
if (!shouldBeRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsRestoreRecordModalOpen(true);
|
||||
};
|
||||
|
||||
const handleConfirmClick = () => {
|
||||
handleRestoreClick();
|
||||
if (isInRightDrawer) {
|
||||
closeRightDrawer({ emitCloseEvent: false });
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
shouldBeRegistered,
|
||||
onClick,
|
||||
ConfirmationModal: (
|
||||
<ConfirmationModal
|
||||
isOpen={isRestoreRecordModalOpen}
|
||||
setIsOpen={setIsRestoreRecordModalOpen}
|
||||
title={'Restore Record'}
|
||||
subtitle={'Are you sure you want to restore this record?'}
|
||||
onConfirmClick={handleConfirmClick}
|
||||
confirmButtonText={'Restore Record'}
|
||||
/>
|
||||
),
|
||||
};
|
||||
};
|
||||
@ -7,4 +7,5 @@ export enum SingleRecordActionKeys {
|
||||
NAVIGATE_TO_PREVIOUS_RECORD = 'navigate-to-previous-record-single-record',
|
||||
EXPORT_NOTE_TO_PDF = 'export-note-to-pdf-single-record',
|
||||
EXPORT = 'export-single-record',
|
||||
RESTORE = 'restore-single-record',
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ export const CurrentWorkspaceMemberFavorites = ({
|
||||
title={`Remove ${folder.favorites.length} ${folder.favorites.length > 1 ? 'favorites' : 'favorite'}?`}
|
||||
subtitle={`This action will delete this favorite folder ${folder.favorites.length > 1 ? `and all ${folder.favorites.length} favorites` : 'and the favorite'} inside. Do you want to continue?`}
|
||||
onConfirmClick={handleConfirmDelete}
|
||||
deleteButtonText="Delete Folder"
|
||||
confirmButtonText="Delete Folder"
|
||||
/>,
|
||||
document.body,
|
||||
)}
|
||||
|
||||
@ -30,9 +30,9 @@ export const RecordGroupReorderConfirmationModal = ({
|
||||
isOpen={isRecordGroupReorderConfirmationModalVisible}
|
||||
setIsOpen={setIsRecordGroupReorderConfirmationModalVisible}
|
||||
title="Group sorting"
|
||||
subtitle={`Would you like to remove ${recordGroupSort} group sorting ?`}
|
||||
subtitle={`Would you like to remove ${recordGroupSort} group sorting?`}
|
||||
onConfirmClick={onConfirmClick}
|
||||
deleteButtonText="Remove"
|
||||
confirmButtonText="Remove"
|
||||
/>,
|
||||
document.body,
|
||||
);
|
||||
|
||||
@ -2,19 +2,21 @@ import { useEffect } from 'react';
|
||||
|
||||
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
|
||||
import { hasUserSelectedAllRowsComponentState } from '@/object-record/record-table/record-table-row/states/hasUserSelectedAllRowsFamilyState';
|
||||
import { selectedRowIdsComponentSelector } from '@/object-record/record-table/states/selectors/selectedRowIdsComponentSelector';
|
||||
import { unselectedRowIdsComponentSelector } from '@/object-record/record-table/states/selectors/unselectedRowIdsComponentSelector';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
export const RecordIndexFiltersToContextStoreEffect = () => {
|
||||
const { recordIndexId } = useRecordIndexContextOrThrow();
|
||||
|
||||
const recordIndexFilters = useRecoilValue(recordIndexFiltersState);
|
||||
const recordIndexFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const setContextStoreTargetedRecords = useSetRecoilComponentStateV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
|
||||
@ -31,9 +31,9 @@ export const RecordIndexRemoveSortingModal = () => {
|
||||
isOpen={isRemoveSortingModalOpen}
|
||||
setIsOpen={setIsRemoveSortingModalOpen}
|
||||
title={'Remove sorting?'}
|
||||
subtitle={<>This is required to enable manual row reordering.</>}
|
||||
onConfirmClick={() => handleRemoveClick()}
|
||||
deleteButtonText={'Remove Sorting'}
|
||||
subtitle={'This is required to enable manual row reordering.'}
|
||||
onConfirmClick={handleRemoveClick}
|
||||
confirmButtonText={'Remove Sorting'}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -300,7 +300,7 @@ export const RecordDetailRelationRecordsListItem = ({
|
||||
</>
|
||||
}
|
||||
onConfirmClick={handleConfirmDelete}
|
||||
deleteButtonText={`Delete ${relationObjectTypeName}`}
|
||||
confirmButtonText={`Delete ${relationObjectTypeName}`}
|
||||
/>,
|
||||
document.body,
|
||||
)}
|
||||
|
||||
@ -18,8 +18,8 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
|
||||
type SettingsAccountsRowDropdownMenuProps = {
|
||||
account: ConnectedAccount;
|
||||
@ -106,7 +106,7 @@ export const SettingsAccountsRowDropdownMenu = ({
|
||||
</Trans>
|
||||
}
|
||||
onConfirmClick={deleteAccount}
|
||||
deleteButtonText={t`Delete account`}
|
||||
confirmButtonText={t`Delete account`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -50,7 +50,7 @@ export const DeleteAccount = () => {
|
||||
</>
|
||||
}
|
||||
onConfirmClick={deleteAccount}
|
||||
deleteButtonText={t`Delete account`}
|
||||
confirmButtonText={t`Delete account`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -51,7 +51,7 @@ export const DeleteWorkspace = () => {
|
||||
</Trans>
|
||||
}
|
||||
onConfirmClick={deleteWorkspace}
|
||||
deleteButtonText={t`Delete workspace`}
|
||||
confirmButtonText={t`Delete workspace`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -34,7 +34,7 @@ export const RoleAssignmentConfirmationModal = ({
|
||||
/>
|
||||
}
|
||||
onConfirmClick={onConfirm}
|
||||
deleteButtonText={t`Confirm`}
|
||||
confirmButtonText={t`Confirm`}
|
||||
confirmButtonAccent="blue"
|
||||
/>
|
||||
);
|
||||
|
||||
@ -85,7 +85,7 @@ export const SettingsServerlessFunctionSettingsTab = ({
|
||||
</>
|
||||
}
|
||||
onConfirmClick={deleteFunction}
|
||||
deleteButtonText="Delete function"
|
||||
confirmButtonText="Delete function"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -24,7 +24,7 @@ export type ConfirmationModalProps = {
|
||||
subtitle: ReactNode;
|
||||
setIsOpen: (val: boolean) => void;
|
||||
onConfirmClick: () => void;
|
||||
deleteButtonText?: string;
|
||||
confirmButtonText?: string;
|
||||
confirmationPlaceholder?: string;
|
||||
confirmationValue?: string;
|
||||
confirmButtonAccent?: ButtonAccent;
|
||||
@ -70,7 +70,7 @@ export const ConfirmationModal = ({
|
||||
subtitle,
|
||||
setIsOpen,
|
||||
onConfirmClick,
|
||||
deleteButtonText = `Delete`,
|
||||
confirmButtonText = 'Confirm',
|
||||
confirmationValue,
|
||||
confirmationPlaceholder,
|
||||
confirmButtonAccent = 'danger',
|
||||
@ -159,7 +159,7 @@ export const ConfirmationModal = ({
|
||||
onClick={handleConfirmClick}
|
||||
variant="secondary"
|
||||
accent={confirmButtonAccent}
|
||||
title={deleteButtonText}
|
||||
title={confirmButtonText}
|
||||
disabled={!isValidValue || loading}
|
||||
fullWidth
|
||||
dataTestId="confirmation-modal-confirm-button"
|
||||
|
||||
@ -18,7 +18,7 @@ export const Default: Story = {
|
||||
isOpen: true,
|
||||
title: 'Pariatur labore.',
|
||||
subtitle: 'Velit dolore aliquip laborum occaecat fugiat.',
|
||||
deleteButtonText: 'Delete',
|
||||
confirmButtonText: 'Delete',
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
@ -47,7 +47,7 @@ export const OverrideWorkflowDraftConfirmationModal = ({
|
||||
title="A draft already exists"
|
||||
subtitle="A draft already exists for this workflow. Are you sure you want to erase it?"
|
||||
onConfirmClick={handleOverrideDraft}
|
||||
deleteButtonText={'Override Draft'}
|
||||
confirmButtonText={'Override Draft'}
|
||||
AdditionalButtons={
|
||||
<StyledCenteredButton
|
||||
to={getAppPath(AppPath.RecordShowPage, {
|
||||
|
||||
@ -190,7 +190,7 @@ export const SettingsBilling = () => {
|
||||
` ${impact}`
|
||||
}
|
||||
onConfirmClick={switchInterval}
|
||||
deleteButtonText={t`Change ${to}`}
|
||||
confirmButtonText={t`Change ${to}`}
|
||||
confirmButtonAccent={'blue'}
|
||||
/>
|
||||
</SubMenuTopBarContainer>
|
||||
|
||||
@ -329,7 +329,7 @@ export const SettingsWorkspaceMembers = () => {
|
||||
workspaceMemberToDelete &&
|
||||
handleRemoveWorkspaceMember(workspaceMemberToDelete)
|
||||
}
|
||||
deleteButtonText={t`Delete account`}
|
||||
confirmButtonText={t`Delete account`}
|
||||
/>
|
||||
</SubMenuTopBarContainer>
|
||||
);
|
||||
|
||||
@ -260,7 +260,7 @@ export const SettingsDevelopersApiKeyDetail = () => {
|
||||
</Trans>
|
||||
}
|
||||
onConfirmClick={deleteIntegration}
|
||||
deleteButtonText={t`Delete`}
|
||||
confirmButtonText={t`Delete`}
|
||||
loading={isLoading}
|
||||
/>
|
||||
<ConfirmationModal
|
||||
@ -277,7 +277,7 @@ export const SettingsDevelopersApiKeyDetail = () => {
|
||||
</Trans>
|
||||
}
|
||||
onConfirmClick={regenerateApiKey}
|
||||
deleteButtonText={t`Regenerate key`}
|
||||
confirmButtonText={t`Regenerate key`}
|
||||
loading={isLoading}
|
||||
/>
|
||||
</>
|
||||
|
||||
@ -266,7 +266,7 @@ export const SettingsDevelopersWebhooksDetail = () => {
|
||||
</Trans>
|
||||
}
|
||||
onConfirmClick={deleteWebhook}
|
||||
deleteButtonText={t`Delete webhook`}
|
||||
confirmButtonText={t`Delete webhook`}
|
||||
/>
|
||||
</Section>
|
||||
</SettingsPageContainer>
|
||||
|
||||
Reference in New Issue
Block a user