Close side panel after command menu actions (#22118)
## What changed - Close the command side panel after eligible headless command-menu actions complete or are confirmed. - Cover delete, restore, permanent destroy, create view, import, see deleted, and hide deleted record commands. - Keep create-record behavior unchanged so a newly created record can still open in the side panel. - Add focused Jest coverage for the affected command components and the create-record exception. # Before https://github.com/user-attachments/assets/36632578-3cab-47db-8f6d-350cd6fce683 # After https://github.com/user-attachments/assets/c9dba19b-7f4a-44aa-ae7f-57660c5a1e96 --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
committed by
GitHub
parent
ad61d6d8a3
commit
e22d31c553
+4
@@ -6,6 +6,7 @@ import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryP
|
||||
import { useIncrementalDeleteManyRecords } from '@/object-record/hooks/useIncrementalDeleteManyRecords';
|
||||
import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-board/hooks/useRemoveSelectedRecordsFromRecordBoard';
|
||||
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -41,9 +42,12 @@ export const DeleteRecordsCommand = () => {
|
||||
const { removeNavigationMenuItemsByTargetRecordIds } =
|
||||
useRemoveNavigationMenuItemByTargetRecordId();
|
||||
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
|
||||
const handleExecute = async () => {
|
||||
removeSelectedRecordsFromRecordBoard();
|
||||
resetTableRowSelection();
|
||||
closeSidePanelMenu();
|
||||
|
||||
if (isDefined(recordId)) {
|
||||
const foundNavigationMenuItem = [
|
||||
|
||||
+5
-6
@@ -60,14 +60,13 @@ export const DestroyRecordsCommand = () => {
|
||||
throw new Error('Cannot destroy records without a valid filter');
|
||||
}
|
||||
|
||||
await incrementalDestroyManyRecords();
|
||||
|
||||
if (!isSingleRecord) {
|
||||
return;
|
||||
if (!isSingleRecord || isInSidePanel) {
|
||||
closeSidePanelMenu();
|
||||
}
|
||||
|
||||
if (isInSidePanel) {
|
||||
closeSidePanelMenu();
|
||||
await incrementalDestroyManyRecords();
|
||||
|
||||
if (!isSingleRecord || isInSidePanel) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -5,6 +5,7 @@ import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRec
|
||||
import { useRestoreManyRecords } from '@/object-record/hooks/useRestoreManyRecords';
|
||||
import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-board/hooks/useRemoveSelectedRecordsFromRecordBoard';
|
||||
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -24,6 +25,7 @@ export const RestoreRecordsCommand = () => {
|
||||
const { resetTableRowSelection } = useResetTableRowSelection(recordIndexId);
|
||||
const { removeSelectedRecordsFromRecordBoard } =
|
||||
useRemoveSelectedRecordsFromRecordBoard(recordIndexId);
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
|
||||
const { restoreManyRecords } = useRestoreManyRecords({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
@@ -49,6 +51,7 @@ export const RestoreRecordsCommand = () => {
|
||||
|
||||
const handleExecute = async () => {
|
||||
removeSelectedRecordsFromRecordBoard();
|
||||
closeSidePanelMenu();
|
||||
|
||||
if (!isDefined(graphqlFilter)) {
|
||||
throw new Error('Cannot restore records without a valid filter');
|
||||
|
||||
+4
@@ -1,5 +1,6 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||
@@ -11,6 +12,7 @@ export const CreateNewViewNoSelectionRecordCommand = () => {
|
||||
const { currentViewId, recordIndexId } = useHeadlessCommandContextApi();
|
||||
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
|
||||
if (!isDefined(currentViewId) || !isDefined(recordIndexId)) {
|
||||
throw new Error(
|
||||
@@ -26,6 +28,8 @@ export const CreateNewViewNoSelectionRecordCommand = () => {
|
||||
const { setViewPickerMode } = useViewPickerMode(recordIndexId);
|
||||
|
||||
const handleExecute = () => {
|
||||
closeSidePanelMenu();
|
||||
|
||||
if (currentViewId) {
|
||||
setViewPickerReferenceViewId(currentViewId);
|
||||
}
|
||||
|
||||
+3
@@ -4,6 +4,7 @@ import { useCheckIsSoftDeleteFilter } from '@/object-record/record-filter/hooks/
|
||||
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -34,6 +35,7 @@ export const HideDeletedRecordsNoSelectionRecordCommand = () => {
|
||||
);
|
||||
|
||||
const { removeRecordFilter } = useRemoveRecordFilter(recordIndexId);
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
|
||||
const handleExecute = () => {
|
||||
if (!isDefined(deletedFilter)) {
|
||||
@@ -42,6 +44,7 @@ export const HideDeletedRecordsNoSelectionRecordCommand = () => {
|
||||
|
||||
removeRecordFilter({ recordFilterId: deletedFilter.id });
|
||||
toggleSoftDeleteFilterState(false);
|
||||
closeSidePanelMenu();
|
||||
};
|
||||
|
||||
return <HeadlessEngineCommandWrapperEffect execute={handleExecute} />;
|
||||
|
||||
+8
-5
@@ -1,6 +1,7 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useOpenObjectRecordsSpreadsheetImportDialog } from '@/object-record/spreadsheet-import/hooks/useOpenObjectRecordsSpreadsheetImportDialog';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const ImportRecordsNoSelectionRecordCommand = () => {
|
||||
@@ -14,10 +15,12 @@ export const ImportRecordsNoSelectionRecordCommand = () => {
|
||||
useOpenObjectRecordsSpreadsheetImportDialog(
|
||||
objectMetadataItem.nameSingular,
|
||||
);
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
|
||||
return (
|
||||
<HeadlessEngineCommandWrapperEffect
|
||||
execute={openObjectRecordsSpreadsheetImportDialog}
|
||||
/>
|
||||
);
|
||||
const handleExecute = () => {
|
||||
closeSidePanelMenu();
|
||||
openObjectRecordsSpreadsheetImportDialog();
|
||||
};
|
||||
|
||||
return <HeadlessEngineCommandWrapperEffect execute={handleExecute} />;
|
||||
};
|
||||
|
||||
+3
@@ -1,6 +1,7 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeDeletedRecordsNoSelectionRecordCommand = () => {
|
||||
@@ -18,12 +19,14 @@ export const SeeDeletedRecordsNoSelectionRecordCommand = () => {
|
||||
viewBarId: recordIndexId,
|
||||
recordFiltersInstanceId: recordIndexId,
|
||||
});
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
|
||||
return (
|
||||
<HeadlessEngineCommandWrapperEffect
|
||||
execute={() => {
|
||||
handleToggleTrashColumnFilter();
|
||||
toggleSoftDeleteFilterState(true);
|
||||
closeSidePanelMenu();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user