feat: improve machine component hierarchy handling

This commit is contained in:
Matthieu
2025-10-13 09:01:19 +02:00
parent 95c2a82689
commit 06ae0ca7aa
9 changed files with 1184 additions and 408 deletions

View File

@@ -25,6 +25,12 @@
{{ component.name }}
</h3>
<div class="flex flex-wrap gap-2 mt-2">
<span
v-if="component.skeletonOnly"
class="badge badge-warning badge-sm"
>
Défini dans le catalogue
</span>
<span v-if="component.reference" class="badge badge-outline badge-sm">{{ component.reference }}</span>
<span v-if="component.constructeur" class="badge badge-outline badge-sm">{{ component.constructeur?.name }}</span>
<span v-if="component.prix" class="badge badge-primary badge-sm">{{ component.prix }}</span>
@@ -264,8 +270,8 @@
v-for="piece in component.pieces"
:key="piece.id"
:piece="piece"
:is-edit-mode="isEditMode"
:piece-model-options="pieceModelOptionsProvider(piece)"
:is-edit-mode="isEditMode && !piece.skeletonOnly"
@update="updatePiece"
@edit="editPiece"
@custom-field-update="updatePieceCustomField"
@@ -283,7 +289,7 @@
v-for="subComponent in childComponents"
:key="subComponent.id"
:component="subComponent"
:is-edit-mode="isEditMode"
:is-edit-mode="isEditMode && !subComponent.skeletonOnly"
:collapse-all="collapseAll"
:toggle-token="toggleToken"
@update="$emit('update', $event)"
@@ -358,11 +364,41 @@ const extractStructureCustomFields = (structure) => {
}
function fieldKeyFromNameAndType(name, type) {
const normalizedName = typeof name === 'string' ? name : ''
const normalizedName = typeof name === 'string' ? name.trim() : ''
const normalizedType = typeof type === 'string' ? type : ''
return normalizedName ? `${normalizedName}::${normalizedType}` : null
}
function deduplicateFieldDefinitions(definitions) {
const result = []
const seen = new Set()
;(Array.isArray(definitions) ? definitions : []).forEach((field) => {
if (!field || typeof field !== 'object') {
return
}
const id =
field.id ??
field.customFieldId ??
field.customField?.id ??
null
const nameKey = fieldKeyFromNameAndType(field.name, field.type)
if (!id && !nameKey) {
return
}
const key = id || nameKey
if (key && seen.has(key)) {
return
}
if (key) {
seen.add(key)
}
result.push(field)
})
return result
}
function mergeFieldDefinitionsWithValues(definitions, values) {
const definitionList = Array.isArray(definitions) ? definitions : []
const valueList = Array.isArray(values) ? values : []
@@ -458,6 +494,62 @@ function mergeFieldDefinitionsWithValues(definitions, values) {
return merged
}
function dedupeMergedFields(fields) {
if (!Array.isArray(fields) || fields.length <= 1) {
return Array.isArray(fields) ? fields : []
}
const seen = new Map()
const result = []
fields.forEach((field) => {
if (!field || typeof field !== 'object') {
return
}
const rawName = resolveFieldName(field)
const normalizedName = typeof rawName === 'string' ? rawName.trim() : ''
if (!normalizedName) {
return
}
field.name = normalizedName
field.type = resolveFieldType(field)
const fieldId = ensureCustomFieldId(field)
const nameKey = fieldKeyFromNameAndType(normalizedName, field.type)
const key = fieldId || nameKey
if (!key) {
result.push(field)
return
}
const existing = seen.get(key)
if (!existing) {
seen.set(key, field)
result.push(field)
return
}
const existingHasValue =
existing.value !== undefined &&
existing.value !== null &&
String(existing.value).trim().length > 0
const incomingHasValue =
field.value !== undefined &&
field.value !== null &&
String(field.value).trim().length > 0
if (!existingHasValue && incomingHasValue) {
Object.assign(existing, field)
seen.set(key, existing)
}
})
return result
}
const componentDefinitionSources = computed(() => {
const requirement = props.component.typeMachineComponentRequirement || {}
const type = requirement.typeComposant || props.component.typeComposant || {}
@@ -488,13 +580,15 @@ const componentDefinitionSources = computed(() => {
}
})
return definitions
return deduplicateFieldDefinitions(definitions)
})
const displayedCustomFields = computed(() =>
mergeFieldDefinitionsWithValues(
componentDefinitionSources.value,
props.component.customFieldValues,
dedupeMergedFields(
mergeFieldDefinitionsWithValues(
componentDefinitionSources.value,
props.component.customFieldValues,
),
),
)