feat: improve machine component hierarchy handling
This commit is contained in:
@@ -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,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user