fix: display current object name in morph relation picker after rename (#17209)
**Summary** Issue #16963: When an object is renamed, the morph relation picker still shows the old name. **Root cause** The picker used searchRecord.objectNameSingular from the GraphQL search response, which can be stale after a rename. The search record stores the object name at query time, not the current metadata. **Solution** - Updated SingleRecordPickerMenuItem: - Added useObjectMetadataItems to access current object metadata. - Look up the current object metadata by morphItem.objectMetadataId. - Use labelSingular (or nameSingular as fallback) instead of searchRecord.objectNameSingular for display. - Updated MultipleRecordPickerMenuItemContent: - Use objectMetadataItem.labelSingular (already available as a prop) instead of searchRecord.objectNameSingular. --------- Co-authored-by: Marie Stoppa <marie.stoppa@essec.edu>
This commit is contained in:
+18
-2
@@ -62,17 +62,27 @@ export type SettingsDataModelFieldMorphRelationFormValues = z.infer<
|
||||
>;
|
||||
|
||||
type SettingsDataModelFieldRelationFormProps = {
|
||||
sourceObjectMetadataId: string;
|
||||
existingFieldMetadataId: string;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export const SettingsDataModelFieldRelationForm = ({
|
||||
existingFieldMetadataId,
|
||||
sourceObjectMetadataId,
|
||||
disabled = false,
|
||||
}: SettingsDataModelFieldRelationFormProps) => {
|
||||
const { t } = useLingui();
|
||||
const { control } =
|
||||
useFormContext<SettingsDataModelFieldMorphRelationFormValues>();
|
||||
const { control, watch } = useFormContext();
|
||||
|
||||
const currentIds = watch('morphRelationObjectMetadataIds') as
|
||||
| string[]
|
||||
| undefined;
|
||||
|
||||
const isSelfInDestinationForMorphRelation =
|
||||
isDefined(currentIds) &&
|
||||
currentIds.length > 1 &&
|
||||
currentIds.includes(sourceObjectMetadataId);
|
||||
|
||||
const { fieldMetadataItem: existingFieldMetadataItem } =
|
||||
useFieldMetadataItemById(existingFieldMetadataId);
|
||||
@@ -85,6 +95,7 @@ export const SettingsDataModelFieldRelationForm = ({
|
||||
const initialRelationObjectMetadataItems =
|
||||
useRelationSettingsFormInitialTargetObjectMetadatas({
|
||||
fieldMetadataItem: existingFieldMetadataItem,
|
||||
sourceObjectMetadataId,
|
||||
});
|
||||
|
||||
const initialRelationType =
|
||||
@@ -136,6 +147,11 @@ export const SettingsDataModelFieldRelationForm = ({
|
||||
selectedObjectMetadataIds={value}
|
||||
withSearchInput={true}
|
||||
onChange={onChange}
|
||||
error={
|
||||
isSelfInDestinationForMorphRelation
|
||||
? t`Relations cannot include the source object when multiple destinations are selected.`
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
+9
@@ -40,6 +40,14 @@ export const SettingsDataModelFieldRelationFormCard = ({
|
||||
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
const sourceObjectMetadataItem = objectMetadataItems.find(
|
||||
(item) => item.nameSingular === objectNameSingular,
|
||||
);
|
||||
|
||||
if (!sourceObjectMetadataItem) {
|
||||
throw new Error('Object not found.');
|
||||
}
|
||||
|
||||
const relationObjectMetadataIds: string[] = watch(
|
||||
'morphRelationObjectMetadataIds',
|
||||
[],
|
||||
@@ -116,6 +124,7 @@ export const SettingsDataModelFieldRelationFormCard = ({
|
||||
<>
|
||||
<SettingsDataModelFieldRelationForm
|
||||
existingFieldMetadataId={existingFieldMetadataId}
|
||||
sourceObjectMetadataId={sourceObjectMetadataItem?.id}
|
||||
disabled={disabled}
|
||||
/>
|
||||
{isJunctionRelationsEnabled && (
|
||||
|
||||
+10
-1
@@ -5,8 +5,10 @@ import { fieldMetadataItemHasMorphRelations } from '@/settings/data-model/fields
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useRelationSettingsFormInitialTargetObjectMetadatas = ({
|
||||
sourceObjectMetadataId,
|
||||
fieldMetadataItem,
|
||||
}: {
|
||||
sourceObjectMetadataId: string;
|
||||
fieldMetadataItem?: Pick<
|
||||
FieldMetadataItem,
|
||||
'type' | 'morphRelations' | 'relation'
|
||||
@@ -36,7 +38,14 @@ export const useRelationSettingsFormInitialTargetObjectMetadatas = ({
|
||||
|
||||
const availableItems = activeObjectMetadataItems
|
||||
.filter(isObjectMetadataAvailableForRelation)
|
||||
.sort((a, b) => a.labelSingular.localeCompare(b.labelSingular));
|
||||
.filter((item) => item.id !== sourceObjectMetadataId)
|
||||
.sort((a, b) => {
|
||||
if (a.isCustom === b.isCustom) {
|
||||
return 0;
|
||||
}
|
||||
return a.isCustom ? -1 : 1;
|
||||
});
|
||||
|
||||
const firstInitialObjectCandidate = availableItems[0];
|
||||
if (!isDefined(firstInitialObjectCandidate)) {
|
||||
throw new Error(
|
||||
|
||||
+34
-3
@@ -1,16 +1,47 @@
|
||||
import { settingsDataModelFieldDescriptionFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldDescriptionForm';
|
||||
import { settingsDataModelFieldIconLabelFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldIconLabelForm';
|
||||
import { settingsDataModelFieldSettingsFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { z } from 'zod';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { settingsDataModelFieldTypeFormSchema } from '~/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect';
|
||||
|
||||
export const settingsFieldFormSchema = (existingOtherLabels?: string[]) => {
|
||||
return z
|
||||
type SettingsFieldFormSchemaOptions = {
|
||||
existingOtherLabels?: string[];
|
||||
sourceObjectMetadataId?: string;
|
||||
};
|
||||
|
||||
export const settingsFieldFormSchema = (
|
||||
options: SettingsFieldFormSchemaOptions = {},
|
||||
) => {
|
||||
const { existingOtherLabels, sourceObjectMetadataId } = options;
|
||||
|
||||
const baseSchema = z
|
||||
.object({})
|
||||
.extend(
|
||||
settingsDataModelFieldIconLabelFormSchema(existingOtherLabels).shape,
|
||||
)
|
||||
.extend(settingsDataModelFieldDescriptionFormSchema().shape)
|
||||
.extend(settingsDataModelFieldTypeFormSchema.shape)
|
||||
.and(settingsDataModelFieldSettingsFormSchema);
|
||||
.and(settingsDataModelFieldSettingsFormSchema)
|
||||
.refine((data) => {
|
||||
const formData = data as {
|
||||
type?: FieldMetadataType;
|
||||
morphRelationObjectMetadataIds?: string[];
|
||||
};
|
||||
if (formData.type !== FieldMetadataType.MORPH_RELATION) return true;
|
||||
if (!isDefined(sourceObjectMetadataId)) return true;
|
||||
if (
|
||||
!isDefined(formData.morphRelationObjectMetadataIds) ||
|
||||
formData.morphRelationObjectMetadataIds.length <= 1
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
formData.morphRelationObjectMetadataIds.includes(sourceObjectMetadataId)
|
||||
)
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
return baseSchema;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user