set up new view for skeleton hiearchi

This commit is contained in:
Matthieu
2025-09-22 08:34:05 +02:00
parent e33e91ee26
commit 936a9d74ca
30 changed files with 4530 additions and 2288 deletions

View File

@@ -27,6 +27,18 @@
<span v-if="component.constructeur" class="badge badge-outline badge-sm">{{ component.constructeur?.name }}</span>
<span v-if="component.emplacement" class="badge badge-outline badge-sm">{{ component.emplacement }}</span>
<span v-if="component.prix" class="badge badge-primary badge-sm">{{ component.prix }}</span>
<span
v-if="component.typeMachineComponentRequirement"
class="badge badge-outline badge-sm"
>
Groupe : {{ component.typeMachineComponentRequirement.label || component.typeMachineComponentRequirement.typeComposant?.name || 'Non défini' }}
</span>
<span
v-if="component.composantModel"
class="badge badge-outline badge-sm badge-primary"
>
Modèle : {{ component.composantModel.name }}
</span>
</div>
</div>
</div>
@@ -99,6 +111,44 @@
</div>
</div>
</div>
<div
v-if="isEditMode && component.typeMachineComponentRequirement"
class="grid grid-cols-1 md:grid-cols-2 gap-4"
>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Modèle de composant</span>
<span class="label-text-alt text-xs">
{{ component.typeMachineComponentRequirement.label || component.typeMachineComponentRequirement.typeComposant?.name || 'Famille' }}
</span>
</label>
<div class="flex flex-col md:flex-row gap-2 items-start md:items-center">
<select
:value="selectedComponentModelId"
class="select select-bordered select-sm"
@change="assignComponentModel($event.target.value)"
>
<option value="">Définir manuellement</option>
<option
v-for="model in componentModelOptionsList"
:key="model.id"
:value="model.id"
>
{{ model.name }}
</option>
</select>
<button
v-if="isEditMode && component.typeMachineComponentRequirement?.typeComposantId"
type="button"
class="btn btn-ghost btn-xs"
@click="emit('create-model-from-component', component)"
>
Sauvegarder comme modèle
</button>
</div>
</div>
</div>
</div>
<!-- Custom Fields Display - Editable or Read-only -->
@@ -243,9 +293,11 @@
:key="piece.id"
:piece="piece"
:is-edit-mode="isEditMode"
:piece-model-options="pieceModelOptionsProvider(piece)"
@update="updatePiece"
@edit="editPiece"
@custom-field-update="updatePieceCustomField"
@assign-model="emitAssignPieceModel"
/>
</div>
</div>
@@ -261,8 +313,13 @@
:is-edit-mode="isEditMode"
:collapse-all="collapseAll"
:toggle-token="toggleToken"
:component-model-options="componentModelOptionsProvider(subComponent)"
:component-model-options-provider="componentModelOptionsProvider"
:piece-model-options-provider="pieceModelOptionsProvider"
@update="$emit('update', $event)"
@edit-piece="$emit('edit-piece', $event)"
@assign-model="$emit('assign-model', $event)"
@assign-piece-model="$emit('assign-piece-model', $event)"
/>
</div>
</div>
@@ -284,23 +341,42 @@ import IconLucideChevronRight from '~icons/lucide/chevron-right'
const props = defineProps({
component: {
type: Object,
required: true
required: true,
},
isEditMode: {
type: Boolean,
default: false
default: false,
},
collapseAll: {
type: Boolean,
default: true
default: true,
},
toggleToken: {
type: Number,
default: 0
}
default: 0,
},
componentModelOptions: {
type: Array,
default: () => [],
},
componentModelOptionsProvider: {
type: Function,
default: () => [],
},
pieceModelOptionsProvider: {
type: Function,
default: () => [],
},
})
const emit = defineEmits(['update', 'edit-piece'])
const emit = defineEmits([
'update',
'edit-piece',
'custom-field-update',
'assign-model',
'assign-piece-model',
'create-model-from-component',
])
const isCollapsed = ref(true)
const selectedFiles = ref([])
@@ -312,6 +388,13 @@ const documentIcon = (doc) => getFileIcon({ name: doc.filename || doc.name, mime
const previewDocument = ref(null)
const previewVisible = ref(false)
const selectedComponentModelId = computed(() => props.component.composantModelId || props.component.composantModel?.id || '')
const componentModelOptionsList = computed(() => {
const provided = props.componentModelOptionsProvider(props.component)
return Array.isArray(provided) && provided.length ? provided : props.componentModelOptions
})
const pieceModelOptionsList = computed(() => props.pieceModelOptionsProvider(props.component) || [])
const handleConstructeurChange = async (value) => {
props.component.constructeurId = value
await updateComponent()
@@ -327,15 +410,14 @@ watch(
ensureDocumentsLoaded()
}
},
{ immediate: true }
{ immediate: true },
)
watch(
() => props.component.documents,
(docs) => {
documentsLoaded.value = !!(docs && docs.length)
}
},
)
const toggleCollapse = () => {
@@ -345,13 +427,11 @@ const toggleCollapse = () => {
}
}
// Methods
const updateComponent = () => {
emit('update', props.component)
}
const updateComponentCustomField = (field) => {
// Mettre à jour le champ personnalisé du composant
const updateComponentCustomField = () => {
emit('update', props.component)
}
@@ -364,10 +444,29 @@ const editPiece = (piece) => {
}
const updatePieceCustomField = (fieldUpdate) => {
// Forward to parent
emit('custom-field-update', fieldUpdate)
emit('edit-piece', { ...fieldUpdate, type: 'custom-field-update' })
}
const assignComponentModel = (value) => {
const previousModelId = props.component.composantModelId || props.component.composantModel?.id || null
const previousModel = props.component.composantModel || null
props.component.composantModelId = value || null
if (!value) {
props.component.composantModel = null
}
emit('assign-model', {
componentId: props.component.id,
composantModelId: value || null,
previousModelId,
previousModel,
})
}
const emitAssignPieceModel = (payload) => {
emit('assign-piece-model', payload)
}
const ensureDocumentsLoaded = async () => {
if (documentsLoaded.value || !props.component?.id) return
await refreshDocuments()
@@ -393,9 +492,9 @@ const handleFilesAdded = async (files) => {
const result = await uploadDocuments(
{
files,
context: { composantId: props.component.id }
context: { composantId: props.component.id },
},
{ updateStore: false }
{ updateStore: false },
)
if (result.success) {
@@ -413,7 +512,7 @@ const removeDocument = async (documentId) => {
if (!documentId) return
const result = await deleteDocument(documentId, { updateStore: false })
if (result.success) {
props.component.documents = (props.component.documents || []).filter(doc => doc.id !== documentId)
props.component.documents = (props.component.documents || []).filter((doc) => doc.id !== documentId)
}
}
@@ -450,4 +549,4 @@ const formatSize = (size) => {
const formatted = size / Math.pow(1024, index)
return `${formatted.toFixed(1)} ${units[index]}`
}
</script>
</script>