Fallback to field metadata (#19131)
Rely on the field metadata items to always display all object's fields in the fields widget configuration editor. If fields are missing in the returned view fields, we add the missing fields through object metadata. https://github.com/user-attachments/assets/3c4d45e8-05d0-4943-be4b-bcf1e310155c
This commit is contained in:
committed by
GitHub
parent
5bbfce7789
commit
c11e4ece39
@@ -73,19 +73,15 @@ export const useSaveFieldsWidgetGroups = () => {
|
||||
name: group.name,
|
||||
position: group.position,
|
||||
isVisible: group.isVisible,
|
||||
fields: group.fields.flatMap((field) => {
|
||||
if (!isDefined(field.viewFieldId)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
viewFieldId: field.viewFieldId,
|
||||
isVisible: field.isVisible,
|
||||
position: field.position,
|
||||
},
|
||||
];
|
||||
}),
|
||||
fields: group.fields.map((field) => ({
|
||||
...(isDefined(field.viewFieldId)
|
||||
? { viewFieldId: field.viewFieldId }
|
||||
: {
|
||||
fieldMetadataId: field.fieldMetadataItem.id,
|
||||
}),
|
||||
isVisible: field.isVisible,
|
||||
position: field.position,
|
||||
})),
|
||||
})),
|
||||
},
|
||||
},
|
||||
@@ -97,19 +93,15 @@ export const useSaveFieldsWidgetGroups = () => {
|
||||
variables: {
|
||||
input: {
|
||||
widgetId,
|
||||
fields: ungroupedFields.flatMap((field) => {
|
||||
if (!isDefined(field.viewFieldId)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
viewFieldId: field.viewFieldId,
|
||||
isVisible: field.isVisible,
|
||||
position: field.position,
|
||||
},
|
||||
];
|
||||
}),
|
||||
fields: ungroupedFields.map((field) => ({
|
||||
...(isDefined(field.viewFieldId)
|
||||
? { viewFieldId: field.viewFieldId }
|
||||
: {
|
||||
fieldMetadataId: field.fieldMetadataItem.id,
|
||||
}),
|
||||
isVisible: field.isVisible,
|
||||
position: field.position,
|
||||
})),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
+90
-5
@@ -1,3 +1,4 @@
|
||||
import { useLabelIdentifierFieldMetadataItem } from '@/object-metadata/hooks/useLabelIdentifierFieldMetadataItem';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { type FieldsWidgetEditorMode } from '@/page-layout/widgets/fields/types/FieldsWidgetEditorMode';
|
||||
import {
|
||||
@@ -6,7 +7,11 @@ import {
|
||||
} from '@/page-layout/widgets/fields/types/FieldsWidgetGroup';
|
||||
import { useViewById } from '@/views/hooks/useViewById';
|
||||
import { useMemo } from 'react';
|
||||
import { isDefined, isNonEmptyArray } from 'twenty-shared/utils';
|
||||
import {
|
||||
isDefined,
|
||||
isFieldMetadataEligibleForFieldsWidget,
|
||||
isNonEmptyArray,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
type UseFieldsWidgetEditorGroupsDataParams = {
|
||||
viewId: string | null;
|
||||
@@ -28,6 +33,10 @@ export const useFieldsWidgetEditorGroupsData = ({
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
const { labelIdentifierFieldMetadataItem } =
|
||||
useLabelIdentifierFieldMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const result = useMemo<
|
||||
Pick<
|
||||
@@ -39,6 +48,45 @@ export const useFieldsWidgetEditorGroupsData = ({
|
||||
return { groups: [], ungroupedFields: [], editorMode: 'ungrouped' };
|
||||
}
|
||||
|
||||
const eligibleFieldMetadataIds = new Set(
|
||||
objectMetadataItem.fields
|
||||
.filter((field) =>
|
||||
isFieldMetadataEligibleForFieldsWidget({
|
||||
fieldName: field.name,
|
||||
fieldType: field.type,
|
||||
isLabelIdentifierField:
|
||||
field.id === labelIdentifierFieldMetadataItem?.id,
|
||||
}),
|
||||
)
|
||||
.map((field) => field.id),
|
||||
);
|
||||
|
||||
const buildMissingFields = ({
|
||||
existingFieldMetadataIds,
|
||||
startGlobalIndex,
|
||||
startPosition,
|
||||
}: {
|
||||
existingFieldMetadataIds: Set<string>;
|
||||
startGlobalIndex: number;
|
||||
startPosition: number;
|
||||
}): FieldsWidgetGroupField[] => {
|
||||
let globalIndex = startGlobalIndex;
|
||||
let position = startPosition;
|
||||
|
||||
return objectMetadataItem.fields
|
||||
.filter(
|
||||
(field) =>
|
||||
!existingFieldMetadataIds.has(field.id) &&
|
||||
eligibleFieldMetadataIds.has(field.id),
|
||||
)
|
||||
.map((field) => ({
|
||||
fieldMetadataItem: field,
|
||||
position: position++,
|
||||
isVisible: false,
|
||||
globalIndex: globalIndex++,
|
||||
}));
|
||||
};
|
||||
|
||||
if (isDefined(view) && isNonEmptyArray(view.viewFieldGroups)) {
|
||||
const viewFieldGroups = view.viewFieldGroups;
|
||||
|
||||
@@ -47,13 +95,14 @@ export const useFieldsWidgetEditorGroupsData = ({
|
||||
);
|
||||
|
||||
let globalIndex = 0;
|
||||
const existingFieldMetadataIds = new Set<string>();
|
||||
|
||||
const groups = sortedGroups.map((group) => {
|
||||
const groupFields = [...(group.viewFields ?? [])].sort(
|
||||
(a, b) => a.position - b.position,
|
||||
);
|
||||
|
||||
const fields = groupFields
|
||||
const fields: FieldsWidgetGroupField[] = groupFields
|
||||
.map((viewField) => {
|
||||
const fieldMetadataItem = objectMetadataItem.fields.find(
|
||||
(f) => f.id === viewField.fieldMetadataId,
|
||||
@@ -63,6 +112,8 @@ export const useFieldsWidgetEditorGroupsData = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
existingFieldMetadataIds.add(viewField.fieldMetadataId);
|
||||
|
||||
return {
|
||||
fieldMetadataItem,
|
||||
position: viewField.position,
|
||||
@@ -82,11 +133,28 @@ export const useFieldsWidgetEditorGroupsData = ({
|
||||
};
|
||||
});
|
||||
|
||||
const lastGroup = groups[groups.length - 1];
|
||||
const lastFieldPosition =
|
||||
lastGroup.fields.length > 0
|
||||
? Math.max(...lastGroup.fields.map((f) => f.position)) + 1
|
||||
: 0;
|
||||
|
||||
const missingFields = buildMissingFields({
|
||||
existingFieldMetadataIds,
|
||||
startGlobalIndex: globalIndex,
|
||||
startPosition: lastFieldPosition,
|
||||
});
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
lastGroup.fields = [...lastGroup.fields, ...missingFields];
|
||||
}
|
||||
|
||||
return { groups, ungroupedFields: [], editorMode: 'grouped' };
|
||||
}
|
||||
|
||||
if (isDefined(view) && view.viewFields.length > 0) {
|
||||
let globalIndex = 0;
|
||||
const existingFieldMetadataIds = new Set<string>();
|
||||
|
||||
const fields = [...view.viewFields]
|
||||
.sort((a, b) => a.position - b.position)
|
||||
@@ -99,6 +167,8 @@ export const useFieldsWidgetEditorGroupsData = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
existingFieldMetadataIds.add(viewField.fieldMetadataId);
|
||||
|
||||
return {
|
||||
fieldMetadataItem,
|
||||
position: viewField.position,
|
||||
@@ -109,13 +179,28 @@ export const useFieldsWidgetEditorGroupsData = ({
|
||||
})
|
||||
.filter(isDefined);
|
||||
|
||||
if (fields.length > 0) {
|
||||
return { groups: [], ungroupedFields: fields, editorMode: 'ungrouped' };
|
||||
const lastFieldPosition =
|
||||
fields.length > 0 ? Math.max(...fields.map((f) => f.position)) + 1 : 0;
|
||||
|
||||
const missingFields = buildMissingFields({
|
||||
existingFieldMetadataIds,
|
||||
startGlobalIndex: globalIndex,
|
||||
startPosition: lastFieldPosition,
|
||||
});
|
||||
|
||||
const allFields = [...fields, ...missingFields];
|
||||
|
||||
if (allFields.length > 0) {
|
||||
return {
|
||||
groups: [],
|
||||
ungroupedFields: allFields,
|
||||
editorMode: 'ungrouped',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { groups: [], ungroupedFields: [], editorMode: 'ungrouped' };
|
||||
}, [objectMetadataItem, view]);
|
||||
}, [objectMetadataItem, view, labelIdentifierFieldMetadataItem]);
|
||||
|
||||
return {
|
||||
...result,
|
||||
|
||||
Reference in New Issue
Block a user