Ensure record fields uniqueness across widgets (#16781)
This PR dissociates record inputs so that several inputs for the same record field can live on the same page. ## Simple values demo https://github.com/user-attachments/assets/a8c224d8-4cd6-4fe3-9cf8-01f6bdd2fca9 ## Relations demo https://github.com/user-attachments/assets/87267a8b-8ce5-41ce-8a78-cba2384828bb ## Doesn't break Record Table https://github.com/user-attachments/assets/bcdd2b05-7cb4-4ed2-9093-58be3e04e43e ## Doesn't break Show Page https://github.com/user-attachments/assets/f9ab9e14-012c-451e-a35f-01a165523f95
This commit is contained in:
committed by
GitHub
parent
6a4974e285
commit
06d0ac13c4
+88
-83
@@ -3,6 +3,7 @@ import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/uti
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useIsRecordReadOnly } from '@/object-record/read-only/hooks/useIsRecordReadOnly';
|
||||
import { isRecordFieldReadOnly } from '@/object-record/read-only/utils/isRecordFieldReadOnly';
|
||||
import { RecordFieldsScopeContextProvider } from '@/object-record/record-field-list/contexts/RecordFieldsScopeContext';
|
||||
import { RecordDetailSectionContainer } from '@/object-record/record-field-list/record-detail-section/components/RecordDetailSectionContainer';
|
||||
import { RecordFieldListComponentInstanceContext } from '@/object-record/record-field-list/states/contexts/RecordFieldListComponentInstanceContext';
|
||||
import { recordFieldListHoverPositionComponentState } from '@/object-record/record-field-list/states/recordFieldListHoverPositionComponentState';
|
||||
@@ -44,11 +45,11 @@ type FieldsWidgetProps = {
|
||||
widget: PageLayoutWidget;
|
||||
};
|
||||
|
||||
export const FieldsWidget = ({ widget: _widget }: FieldsWidgetProps) => {
|
||||
export const FieldsWidget = ({ widget }: FieldsWidgetProps) => {
|
||||
const targetRecord = useTargetRecord();
|
||||
const { isInRightDrawer } = useLayoutRenderingContext();
|
||||
|
||||
const instanceId = `fields-widget-${targetRecord.id}-${isInRightDrawer ? 'right-drawer' : ''}`;
|
||||
const instanceId = `fields-widget-${widget.id}-${targetRecord.id}${isInRightDrawer ? '-right-drawer' : ''}`;
|
||||
|
||||
const { recordLoading, isPrefetchLoading } = useRecordShowContainerData({
|
||||
objectRecordId: targetRecord.id,
|
||||
@@ -103,93 +104,97 @@ export const FieldsWidget = ({ widget: _widget }: FieldsWidgetProps) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<RecordFieldListComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId,
|
||||
}}
|
||||
>
|
||||
{sectionsWithFieldIndices.map((section) => (
|
||||
<RecordDetailSectionContainer key={section.id} title={section.title}>
|
||||
<PropertyBox>
|
||||
{isPrefetchLoading ? (
|
||||
<PropertyBoxSkeletonLoader />
|
||||
) : (
|
||||
<>
|
||||
{section.fields.map(
|
||||
({ field: fieldMetadataItem, globalIndex }) => {
|
||||
return (
|
||||
<FieldContext.Provider
|
||||
key={targetRecord.id + fieldMetadataItem.id}
|
||||
value={{
|
||||
recordId: targetRecord.id,
|
||||
maxWidth: 200,
|
||||
isLabelIdentifier: false,
|
||||
fieldDefinition:
|
||||
formatFieldMetadataItemAsColumnDefinition({
|
||||
field: fieldMetadataItem,
|
||||
position: globalIndex,
|
||||
objectMetadataItem,
|
||||
showLabel: true,
|
||||
labelWidth: 90,
|
||||
}),
|
||||
useUpdateRecord: useUpdateOneObjectRecordMutation,
|
||||
isDisplayModeFixHeight: true,
|
||||
isRecordFieldReadOnly: isRecordFieldReadOnly({
|
||||
isRecordReadOnly,
|
||||
objectPermissions:
|
||||
getObjectPermissionsFromMapByObjectMetadataId({
|
||||
objectPermissionsByObjectMetadataId,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
}),
|
||||
fieldMetadataItem: {
|
||||
id: fieldMetadataItem.id,
|
||||
isUIReadOnly:
|
||||
fieldMetadataItem.isUIReadOnly ?? false,
|
||||
},
|
||||
}),
|
||||
onMouseEnter: () =>
|
||||
setRecordFieldListHoverPosition(globalIndex),
|
||||
anchorId: `${getRecordFieldInputInstanceId({
|
||||
recordId: targetRecord.id,
|
||||
fieldName: fieldMetadataItem.name,
|
||||
prefix: instanceId,
|
||||
})}`,
|
||||
}}
|
||||
>
|
||||
<RecordFieldComponentInstanceContext.Provider
|
||||
<RecordFieldsScopeContextProvider value={{ scopeInstanceId: instanceId }}>
|
||||
<StyledContainer>
|
||||
<RecordFieldListComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId,
|
||||
}}
|
||||
>
|
||||
{sectionsWithFieldIndices.map((section) => (
|
||||
<RecordDetailSectionContainer
|
||||
key={section.id}
|
||||
title={section.title}
|
||||
>
|
||||
<PropertyBox>
|
||||
{isPrefetchLoading ? (
|
||||
<PropertyBoxSkeletonLoader />
|
||||
) : (
|
||||
<>
|
||||
{section.fields.map(
|
||||
({ field: fieldMetadataItem, globalIndex }) => {
|
||||
return (
|
||||
<FieldContext.Provider
|
||||
key={targetRecord.id + fieldMetadataItem.id}
|
||||
value={{
|
||||
instanceId: getRecordFieldInputInstanceId({
|
||||
recordId: targetRecord.id,
|
||||
maxWidth: 200,
|
||||
isLabelIdentifier: false,
|
||||
fieldDefinition:
|
||||
formatFieldMetadataItemAsColumnDefinition({
|
||||
field: fieldMetadataItem,
|
||||
position: globalIndex,
|
||||
objectMetadataItem,
|
||||
showLabel: true,
|
||||
labelWidth: 90,
|
||||
}),
|
||||
useUpdateRecord: useUpdateOneObjectRecordMutation,
|
||||
isDisplayModeFixHeight: true,
|
||||
isRecordFieldReadOnly: isRecordFieldReadOnly({
|
||||
isRecordReadOnly,
|
||||
objectPermissions:
|
||||
getObjectPermissionsFromMapByObjectMetadataId(
|
||||
{
|
||||
objectPermissionsByObjectMetadataId,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
},
|
||||
),
|
||||
fieldMetadataItem: {
|
||||
id: fieldMetadataItem.id,
|
||||
isUIReadOnly:
|
||||
fieldMetadataItem.isUIReadOnly ?? false,
|
||||
},
|
||||
}),
|
||||
onMouseEnter: () =>
|
||||
setRecordFieldListHoverPosition(globalIndex),
|
||||
anchorId: `${getRecordFieldInputInstanceId({
|
||||
recordId: targetRecord.id,
|
||||
fieldName: fieldMetadataItem.name,
|
||||
prefix: instanceId,
|
||||
}),
|
||||
})}`,
|
||||
}}
|
||||
>
|
||||
<RecordInlineCell
|
||||
loading={recordLoading}
|
||||
instanceIdPrefix={instanceId}
|
||||
/>
|
||||
</RecordFieldComponentInstanceContext.Provider>
|
||||
</FieldContext.Provider>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</PropertyBox>
|
||||
</RecordDetailSectionContainer>
|
||||
))}
|
||||
<RecordFieldComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: getRecordFieldInputInstanceId({
|
||||
recordId: targetRecord.id,
|
||||
fieldName: fieldMetadataItem.name,
|
||||
prefix: instanceId,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<RecordInlineCell loading={recordLoading} />
|
||||
</RecordFieldComponentInstanceContext.Provider>
|
||||
</FieldContext.Provider>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</PropertyBox>
|
||||
</RecordDetailSectionContainer>
|
||||
))}
|
||||
|
||||
<FieldsWidgetCellHoveredPortal
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
recordId={targetRecord.id}
|
||||
/>
|
||||
<FieldsWidgetCellEditModePortal
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
recordId={targetRecord.id}
|
||||
/>
|
||||
</RecordFieldListComponentInstanceContext.Provider>
|
||||
</StyledContainer>
|
||||
<FieldsWidgetCellHoveredPortal
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
recordId={targetRecord.id}
|
||||
/>
|
||||
<FieldsWidgetCellEditModePortal
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
recordId={targetRecord.id}
|
||||
/>
|
||||
</RecordFieldListComponentInstanceContext.Provider>
|
||||
</StyledContainer>
|
||||
</RecordFieldsScopeContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user