Fixes #13838 When creating a note from the command menu side panel (e.g. clicking "Add Note" in a related notes section on an Opportunity/company/people page), the title field was not auto-focused — focus point went to body instead. ## Root Cause When a record opens in the side panel, there is no page navigation, so `PageChangeEffect` (which handles title auto-focus for full-page views) never runs. `openNewRecordTitleCell()` was simply never called for the side-panel path. ## Fix `openRecordInCommandMenu` is the single entry point for all side-panel record opens, so title auto-focus is handled there once for all callers. Previously, `useCreateNewIndexRecord` called `openRecordInCommandMenu` and then called `openNewRecordTitleCell` separately, which would have caused a double invocation after this fix. The redundant call has been removed. ## Before https://github.com/user-attachments/assets/df0d9e4f-dc25-4a0d-a49e-898a14f9c0a0 ## After https://github.com/user-attachments/assets/1a5044f7-6bb7-4333-8934-c1081b935e97 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
-22
@@ -4,14 +4,9 @@ import { useOpenRecordInCommandMenu } from '@/command-menu/hooks/useOpenRecordIn
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { type FieldMetadataItemRelation } from '@/object-metadata/types/FieldMetadataItemRelation';
|
||||
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
|
||||
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
||||
import { useRecordTitleCell } from '@/object-record/record-title-cell/hooks/useRecordTitleCell';
|
||||
import { RecordTitleCellContainerType } from '@/object-record/record-title-cell/types/RecordTitleCellContainerType';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getForeignKeyNameFromRelationFieldName } from '@/object-record/utils/getForeignKeyNameFromRelationFieldName';
|
||||
import { getRecordFieldInputInstanceId } from '@/object-record/utils/getRecordFieldInputId';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
interface CreateRelatedRecordActionProps {
|
||||
targetFieldMetadataItemRelation: FieldMetadataItemRelation;
|
||||
@@ -46,8 +41,6 @@ export const CreateRelatedRecordAction = ({
|
||||
objectNameSingular: CoreObjectNameSingular.NoteTarget,
|
||||
});
|
||||
|
||||
const { openRecordTitleCell } = useRecordTitleCell();
|
||||
|
||||
const targetObject =
|
||||
targetObjectMetadataItem.nameSingular === CoreObjectNameSingular.TaskTarget
|
||||
? taskObjectMetadataItem
|
||||
@@ -99,21 +92,6 @@ export const CreateRelatedRecordAction = ({
|
||||
objectNameSingular: targetObject.nameSingular,
|
||||
isNewRecord: true,
|
||||
});
|
||||
|
||||
const labelIdentifierFieldMetadataItem =
|
||||
getLabelIdentifierFieldMetadataItem(targetObject);
|
||||
|
||||
if (isDefined(labelIdentifierFieldMetadataItem)) {
|
||||
openRecordTitleCell({
|
||||
recordId: createdRecord.id,
|
||||
fieldMetadataItemId: labelIdentifierFieldMetadataItem.id,
|
||||
instanceId: getRecordFieldInputInstanceId({
|
||||
recordId: createdRecord.id,
|
||||
fieldName: labelIdentifierFieldMetadataItem.name,
|
||||
prefix: RecordTitleCellContainerType.ShowPage,
|
||||
}),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
+43
@@ -12,6 +12,7 @@ import { contextStoreCurrentViewTypeComponentState } from '@/context-store/state
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
|
||||
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { CommandMenuPages } from 'twenty-shared/types';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
@@ -29,6 +30,16 @@ jest.mock('@/command-menu/hooks/useNavigateCommandMenu', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const mockOpenNewRecordTitleCell = jest.fn();
|
||||
jest.mock(
|
||||
'@/object-record/record-title-cell/hooks/useOpenNewRecordTitleCell',
|
||||
() => ({
|
||||
useOpenNewRecordTitleCell: () => ({
|
||||
openNewRecordTitleCell: mockOpenNewRecordTitleCell,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
const personMockObjectMetadataItem = generatedMockObjectMetadataItems.find(
|
||||
(item) => item.nameSingular === 'person',
|
||||
)!;
|
||||
@@ -173,4 +184,36 @@ describe('useOpenRecordInCommandMenu', () => {
|
||||
resetNavigationStack: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should open title cell in edit mode when isNewRecord is true', () => {
|
||||
const { result } = renderHooks();
|
||||
|
||||
act(() => {
|
||||
result.current.openRecordInCommandMenu({
|
||||
recordId: 'new-record-123',
|
||||
objectNameSingular: 'person',
|
||||
isNewRecord: true,
|
||||
});
|
||||
});
|
||||
|
||||
expect(mockOpenNewRecordTitleCell).toHaveBeenCalledWith({
|
||||
recordId: 'new-record-123',
|
||||
fieldName: getLabelIdentifierFieldMetadataItem(
|
||||
personMockObjectMetadataItem,
|
||||
)?.name,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not open title cell when isNewRecord is false', () => {
|
||||
const { result } = renderHooks();
|
||||
|
||||
act(() => {
|
||||
result.current.openRecordInCommandMenu({
|
||||
recordId: 'record-123',
|
||||
objectNameSingular: 'person',
|
||||
});
|
||||
});
|
||||
|
||||
expect(mockOpenNewRecordTitleCell).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,17 +14,19 @@ import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType
|
||||
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { getIconColorForObjectType } from '@/object-metadata/utils/getIconColorForObjectType';
|
||||
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
|
||||
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
|
||||
import { useOpenNewRecordTitleCell } from '@/object-record/record-title-cell/hooks/useOpenNewRecordTitleCell';
|
||||
import { CommandMenuPages } from 'twenty-shared/types';
|
||||
|
||||
import { useRunWorkflowRunOpeningInCommandMenuSideEffects } from '@/workflow/hooks/useRunWorkflowRunOpeningInCommandMenuSideEffects';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
import { v4 } from 'uuid';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
export const useOpenRecordInCommandMenu = () => {
|
||||
const store = useStore();
|
||||
@@ -34,6 +36,7 @@ export const useOpenRecordInCommandMenu = () => {
|
||||
const { navigateCommandMenu } = useCommandMenu();
|
||||
const { runWorkflowRunOpeningInCommandMenuSideEffects } =
|
||||
useRunWorkflowRunOpeningInCommandMenuSideEffects();
|
||||
const { openNewRecordTitleCell } = useOpenNewRecordTitleCell();
|
||||
|
||||
const openRecordInCommandMenu = useCallback(
|
||||
({
|
||||
@@ -190,10 +193,23 @@ export const useOpenRecordInCommandMenu = () => {
|
||||
recordId,
|
||||
});
|
||||
}
|
||||
|
||||
if (isNewRecord) {
|
||||
const labelIdentifierField =
|
||||
getLabelIdentifierFieldMetadataItem(objectMetadataItem);
|
||||
|
||||
if (isDefined(labelIdentifierField)) {
|
||||
openNewRecordTitleCell({
|
||||
recordId,
|
||||
fieldName: labelIdentifierField.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
[
|
||||
getIcon,
|
||||
navigateCommandMenu,
|
||||
openNewRecordTitleCell,
|
||||
runWorkflowRunOpeningInCommandMenuSideEffects,
|
||||
theme,
|
||||
store,
|
||||
|
||||
+1
-22
@@ -10,16 +10,13 @@ import { recordIndexOpenRecordInState } from '@/object-record/record-index/state
|
||||
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { useBuildRecordInputFromFilters } from '@/object-record/record-table/hooks/useBuildRecordInputFromFilters';
|
||||
import { useRecordTitleCell } from '@/object-record/record-title-cell/hooks/useRecordTitleCell';
|
||||
import { RecordTitleCellContainerType } from '@/object-record/record-title-cell/types/RecordTitleCellContainerType';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { canOpenObjectInSidePanel } from '@/object-record/utils/canOpenObjectInSidePanel';
|
||||
import { getRecordFieldInputInstanceId } from '@/object-record/utils/getRecordFieldInputId';
|
||||
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { useStore } from 'jotai';
|
||||
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { AppPath } from 'twenty-shared/types';
|
||||
import { findByProperty, isDefined } from 'twenty-shared/utils';
|
||||
@@ -60,8 +57,6 @@ export const useCreateNewIndexRecord = ({
|
||||
|
||||
const navigate = useNavigateApp();
|
||||
|
||||
const { openRecordTitleCell } = useRecordTitleCell();
|
||||
|
||||
const { buildRecordInputFromFilters } = useBuildRecordInputFromFilters({
|
||||
objectMetadataItem,
|
||||
});
|
||||
@@ -101,21 +96,6 @@ export const useCreateNewIndexRecord = ({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
isNewRecord: true,
|
||||
});
|
||||
|
||||
const labelIdentifierFieldMetadataItem =
|
||||
getLabelIdentifierFieldMetadataItem(objectMetadataItem);
|
||||
|
||||
if (isDefined(labelIdentifierFieldMetadataItem)) {
|
||||
openRecordTitleCell({
|
||||
recordId,
|
||||
fieldMetadataItemId: labelIdentifierFieldMetadataItem.id,
|
||||
instanceId: getRecordFieldInputInstanceId({
|
||||
recordId,
|
||||
fieldName: labelIdentifierFieldMetadataItem.name,
|
||||
prefix: RecordTitleCellContainerType.PageHeader,
|
||||
}),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const labelIdentifierFieldMetadataItem =
|
||||
getLabelIdentifierFieldMetadataItem(objectMetadataItem);
|
||||
@@ -181,7 +161,6 @@ export const useCreateNewIndexRecord = ({
|
||||
navigate,
|
||||
objectMetadataItem,
|
||||
openRecordInCommandMenu,
|
||||
openRecordTitleCell,
|
||||
recordGroupDefinitions,
|
||||
recordIndexGroupFieldMetadataItem,
|
||||
recordIndexRecordIdsByGroupCallbackState,
|
||||
|
||||
Reference in New Issue
Block a user