Fix From Many relation for deleted notes crashing (#11117)
In this PR, I'm: - fixing the root cause (we should not try to render a RecordChip if the record is not defined in RelationFromMany Display) - fixing related typing issues - we won't be able to catch the issue from TS perspective as ObjectRecord is a Record of string, any
This commit is contained in:
@ -1,5 +1,4 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { Nullable } from 'twenty-ui';
|
||||
|
||||
import { ActivityTargetWithTargetRecord } from '@/activities/types/ActivityTargetObject';
|
||||
import { Note } from '@/activities/types/Note';
|
||||
@ -9,6 +8,7 @@ import { TaskTarget } from '@/activities/types/TaskTarget';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useActivityTargetObjectRecords = (
|
||||
@ -34,7 +34,7 @@ export const useActivityTargetObjectRecords = (
|
||||
: [];
|
||||
|
||||
const activityTargetObjectRecords = targets
|
||||
.map<Nullable<ActivityTargetWithTargetRecord>>((activityTarget) => {
|
||||
.map<ActivityTargetWithTargetRecord | undefined>((activityTarget) => {
|
||||
if (!isDefined(activityTarget)) {
|
||||
throw new Error(`Cannot find activity target`);
|
||||
}
|
||||
@ -51,10 +51,11 @@ export const useActivityTargetObjectRecords = (
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const targetObjectRecord =
|
||||
activityTarget[correspondingObjectMetadataItem.nameSingular];
|
||||
const targetObjectRecord = activityTarget[
|
||||
correspondingObjectMetadataItem.nameSingular
|
||||
] as ObjectRecord | undefined;
|
||||
|
||||
if (!targetObjectRecord) {
|
||||
if (!isDefined(targetObjectRecord)) {
|
||||
throw new Error(
|
||||
`Cannot find target object record of type ${correspondingObjectMetadataItem.nameSingular}, make sure the request for activities eagerly loads for the target objects on activity target relation.`,
|
||||
);
|
||||
@ -62,7 +63,7 @@ export const useActivityTargetObjectRecords = (
|
||||
|
||||
return {
|
||||
activityTarget,
|
||||
targetObject: targetObjectRecord ?? undefined,
|
||||
targetObject: targetObjectRecord,
|
||||
targetObjectMetadataItem: correspondingObjectMetadataItem,
|
||||
};
|
||||
})
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const getLabelIdentifierFieldValue = (
|
||||
record: ObjectRecord,
|
||||
|
||||
@ -22,6 +22,7 @@ export const useRecordChipData = ({
|
||||
|
||||
const identifierChipGenerator =
|
||||
identifierChipGeneratorPerObject[objectNameSingular];
|
||||
|
||||
if (isDefined(identifierChipGenerator)) {
|
||||
return {
|
||||
recordChipData: identifierChipGenerator(record),
|
||||
|
||||
@ -48,13 +48,17 @@ export const RelationFromManyFieldDisplay = () => {
|
||||
|
||||
return (
|
||||
<ExpandableList isChipCountDisplayed={isFocused}>
|
||||
{fieldValue.filter(isDefined).map((record) => (
|
||||
<RecordChip
|
||||
key={record.id}
|
||||
objectNameSingular={objectNameSingular}
|
||||
record={record[relationFieldName]}
|
||||
/>
|
||||
))}
|
||||
{fieldValue
|
||||
.map((record) =>
|
||||
isDefined(record) && isDefined(record[relationFieldName]) ? (
|
||||
<RecordChip
|
||||
key={record.id}
|
||||
objectNameSingular={objectNameSingular}
|
||||
record={record[relationFieldName]}
|
||||
/>
|
||||
) : undefined,
|
||||
)
|
||||
.filter(isDefined)}
|
||||
</ExpandableList>
|
||||
);
|
||||
} else if (isRelationFromActivityTargets) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
@ -10,14 +10,20 @@ export const DropdownOnToggleEffect = ({
|
||||
onDropdownOpen?: () => void;
|
||||
}) => {
|
||||
const { isDropdownOpen } = useDropdown();
|
||||
const [currentIsDropdownOpen, setCurrentIsDropdownOpen] =
|
||||
useState(isDropdownOpen);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDropdownOpen) {
|
||||
if (isDropdownOpen && !currentIsDropdownOpen) {
|
||||
setCurrentIsDropdownOpen(isDropdownOpen);
|
||||
onDropdownOpen?.();
|
||||
} else {
|
||||
}
|
||||
|
||||
if (!isDropdownOpen && currentIsDropdownOpen) {
|
||||
setCurrentIsDropdownOpen(isDropdownOpen);
|
||||
onDropdownClose?.();
|
||||
}
|
||||
}, [isDropdownOpen, onDropdownClose, onDropdownOpen]);
|
||||
}, [currentIsDropdownOpen, isDropdownOpen, onDropdownClose, onDropdownOpen]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user