fix(custom-fields) : context fields display, batch save, hierarchy propagation and UniqueEntity fix

- ComponentItem/PieceItem: DaisyUI divider, emit context-field-update for batch save
- CustomFieldDisplay: support editable/emit-blur/title/show-header props
- MachineComponentsCard/MachinePiecesCard: propagate custom-field-update events
- useMachineDetailCustomFields: pendingContextFieldUpdates + saveAllContextCustomFields
- useMachineDetailData: wire context field save into submitEdition
- useMachineDetailUpdates: only PATCH changed machine fields
- useMachineHierarchy: propagate contextCustomFields/Values from link to nodes
- componentStructure: include machineContextOnly in normalizeStructureForEditor
- Machine entity: convert empty reference to null, ignoreNull on UniqueEntity

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-03 13:46:39 +02:00
parent c54e5c33f2
commit 0049638e3c
14 changed files with 217 additions and 91 deletions

View File

@@ -1,10 +1,10 @@
<template>
<div
v-if="fields.length"
class="mt-4 pt-4 border-t border-base-200"
:class="containerClass"
>
<h5 class="text-sm font-medium text-base-content/80 mb-3">
Champs personnalisés
<h5 v-if="showHeader" class="text-sm font-medium text-base-content/80 mb-3">
{{ title }}
</h5>
<div :class="layoutClass">
<div
@@ -23,7 +23,7 @@
</label>
<!-- Mode édition -->
<template v-if="isEditMode && !resolveFieldReadOnly(field)">
<template v-if="isFieldEditable(field)">
<!-- Champ de type TEXT -->
<input
v-if="resolveFieldType(field) === 'text'"
@@ -142,6 +142,11 @@ const props = defineProps<{
fields: any[]
isEditMode: boolean
columns?: 1 | 2
title?: string
showHeader?: boolean
withTopBorder?: boolean
editable?: boolean
emitBlur?: boolean
}>()
const emit = defineEmits<{
@@ -155,6 +160,20 @@ const layoutClass = computed(() =>
: 'space-y-3',
)
const title = computed(() => props.title ?? 'Champs personnalisés')
const showHeader = computed(() => props.showHeader ?? true)
const containerClass = computed(() =>
props.withTopBorder === false
? ''
: 'mt-4 pt-4 border-t border-base-200',
)
const editable = computed(() => props.editable ?? true)
const emitBlur = computed(() => props.emitBlur ?? true)
function isFieldEditable(field: any) {
return props.isEditMode && editable.value && !resolveFieldReadOnly(field)
}
function onInput(field: any, value: string) {
field.value = value
emit('field-input', field, value)
@@ -164,10 +183,14 @@ function onBooleanChange(field: any, checked: boolean) {
const value = checked ? 'true' : 'false'
field.value = value
emit('field-input', field, value)
emit('field-blur', field)
if (emitBlur.value) {
emit('field-blur', field)
}
}
function onBlur(field: any) {
emit('field-blur', field)
if (emitBlur.value) {
emit('field-blur', field)
}
}
</script>