Fixed create new optimistic (#16257)

This PR fixes create new optimistic on boards, which was broken due to a
recent refactor of the query system for boards in : #16063
This commit is contained in:
Lucas Bordeau
2025-12-02 16:37:53 +01:00
committed by GitHub
parent bf818b7d8d
commit 21c023c6d6
6 changed files with 85 additions and 67 deletions
@@ -26,6 +26,7 @@ import { getCreateOneRecordMutationResponseField } from '@/object-record/utils/g
import { sanitizeRecordInput } from '@/object-record/utils/sanitizeRecordInput';
import { useRecoilValue } from 'recoil';
import { CustomError, isDefined } from 'twenty-shared/utils';
type useCreateOneRecordProps = {
objectNameSingular: string;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
@@ -9,21 +9,14 @@ import { RecordBoardColumnHeaderAggregateDropdown } from '@/object-record/record
import { RECORD_BOARD_COLUMN_WIDTH } from '@/object-record/record-board/constants/RecordBoardColumnWidth';
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView';
import { recordGroupDefinitionsComponentSelector } from '@/object-record/record-group/states/selectors/recordGroupDefinitionsComponentSelector';
import { RecordGroupDefinitionType } from '@/object-record/record-group/types/RecordGroupDefinition';
import { recordIndexAggregateDisplayLabelComponentState } from '@/object-record/record-index/states/recordIndexAggregateDisplayLabelComponentState';
import { recordIndexAggregateDisplayValueForGroupValueComponentFamilyState } from '@/object-record/record-index/states/recordIndexAggregateDisplayValueForGroupValueComponentFamilyState';
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
import { useCreateNewIndexRecord } from '@/object-record/record-table/hooks/useCreateNewIndexRecord';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useToggleDropdown } from '@/ui/layout/dropdown/hooks/useToggleDropdown';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { useRecoilCallback } from 'recoil';
import { findByProperty, isDefined } from 'twenty-shared/utils';
import { Tag } from 'twenty-ui/components';
import { IconDotsVertical, IconPlus } from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
@@ -104,62 +97,21 @@ export const RecordBoardColumnHeader = () => {
recordIndexAggregateDisplayValueForGroupValueComponentFamilyState,
{ groupValue: columnDefinition?.value ?? '' },
);
const { upsertRecordsInStore } = useUpsertRecordsInStore();
const recordIndexRecordIdsByGroupCallbackState =
useRecoilComponentCallbackState(
recordIndexRecordIdsByGroupComponentFamilyState,
);
const recordIndexAggregateDisplayLabel = useRecoilComponentValue(
recordIndexAggregateDisplayLabelComponentState,
);
const recordGroupDefinitions = useRecoilComponentValue(
recordGroupDefinitionsComponentSelector,
);
const { toggleDropdown } = useToggleDropdown();
const dropdownId = `record-board-column-dropdown-${columnDefinition.id}`;
const handleCreateNewRecordClick = useRecoilCallback(
({ set, snapshot }) =>
async () => {
const createdRecord = await createNewIndexRecord({
position: 'first',
[selectFieldMetadataItem.name]: columnDefinition.value,
});
const recordGroup = recordGroupDefinitions.find(
findByProperty('value', createdRecord[selectFieldMetadataItem.name]),
);
if (isDefined(recordGroup)) {
const currentRecordIds = getSnapshotValue(
snapshot,
recordIndexRecordIdsByGroupCallbackState(recordGroup.id),
);
const newRecordIds = [createdRecord.id, ...currentRecordIds];
set(
recordIndexRecordIdsByGroupCallbackState(recordGroup.id),
newRecordIds,
);
}
upsertRecordsInStore([createdRecord]);
},
[
createNewIndexRecord,
columnDefinition,
recordGroupDefinitions,
recordIndexRecordIdsByGroupCallbackState,
upsertRecordsInStore,
selectFieldMetadataItem,
],
);
const handleCreateNewRecordClick = async () => {
await createNewIndexRecord({
position: 'first',
[selectFieldMetadataItem.name]: columnDefinition.value,
});
};
return (
<StyledColumn>
@@ -2,17 +2,24 @@ import { useOpenRecordInCommandMenu } from '@/command-menu/hooks/useOpenRecordIn
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { recordGroupDefinitionsComponentSelector } from '@/object-record/record-group/states/selectors/recordGroupDefinitionsComponentSelector';
import { recordIndexGroupFieldMetadataItemComponentState } from '@/object-record/record-index/states/recordIndexGroupFieldMetadataComponentState';
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
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 { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { useRecoilCallback } from 'recoil';
import { AppPath } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { findByProperty, isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { useNavigateApp } from '~/hooks/useNavigateApp';
@@ -23,6 +30,19 @@ type UseCreateNewIndexRecordProps = {
export const useCreateNewIndexRecord = ({
objectMetadataItem,
}: UseCreateNewIndexRecordProps) => {
const recordGroupDefinitions = useRecoilComponentValue(
recordGroupDefinitionsComponentSelector,
);
const recordIndexRecordIdsByGroupCallbackState =
useRecoilComponentCallbackState(
recordIndexRecordIdsByGroupComponentFamilyState,
);
const recordIndexGroupFieldMetadataItem = useRecoilComponentValue(
recordIndexGroupFieldMetadataItemComponentState,
);
const { openRecordInCommandMenu } = useOpenRecordInCommandMenu();
const { createOneRecord } = useCreateOneRecord({
@@ -30,6 +50,8 @@ export const useCreateNewIndexRecord = ({
shouldMatchRootQueryFilter: true,
});
const { upsertRecordsInStore } = useUpsertRecordsInStore();
const navigate = useNavigateApp();
const { openRecordTitleCell } = useRecordTitleCell();
@@ -39,7 +61,7 @@ export const useCreateNewIndexRecord = ({
});
const createNewIndexRecord = useRecoilCallback(
({ snapshot }) =>
({ snapshot, set }) =>
async (recordInput?: Partial<ObjectRecord>) => {
const recordId = v4();
const recordInputFromFilters = buildRecordInputFromFilters();
@@ -85,6 +107,40 @@ export const useCreateNewIndexRecord = ({
});
}
if (isDefined(recordIndexGroupFieldMetadataItem)) {
const recordGroup = recordGroupDefinitions.find(
findByProperty(
'value',
createdRecord[recordIndexGroupFieldMetadataItem.name],
),
);
if (isDefined(recordGroup)) {
const currentRecordIds = getSnapshotValue(
snapshot,
recordIndexRecordIdsByGroupCallbackState(recordGroup.id),
);
if (recordInput?.position === 'first') {
const newRecordIds = [createdRecord.id, ...currentRecordIds];
set(
recordIndexRecordIdsByGroupCallbackState(recordGroup.id),
newRecordIds,
);
} else {
const newRecordIds = [...currentRecordIds, createdRecord.id];
set(
recordIndexRecordIdsByGroupCallbackState(recordGroup.id),
newRecordIds,
);
}
}
}
upsertRecordsInStore([createdRecord]);
return createdRecord;
},
[
@@ -94,6 +150,10 @@ export const useCreateNewIndexRecord = ({
objectMetadataItem,
openRecordInCommandMenu,
openRecordTitleCell,
recordGroupDefinitions,
recordIndexGroupFieldMetadataItem,
recordIndexRecordIdsByGroupCallbackState,
upsertRecordsInStore,
],
);