Merge remote-tracking branch 'origin/feature/create-assemblies' into feature/all-features

# Conflicts:
#	src/Controller/AdminPages/BaseAdminController.php
This commit is contained in:
Marcel Diegelmann 2025-10-01 14:00:53 +02:00
commit e9ee80cd53
9 changed files with 61 additions and 22 deletions

View file

@ -14,8 +14,6 @@ parameters:
partdb.db.emulate_natural_sort: '%env(bool:DATABASE_EMULATE_NATURAL_SORT)%' # If this is set to true, natural sorting is emulated on platforms that do not support it natively. This can be slow on large datasets.
partdb.create_assembly_use_ipn_placeholder_in_name: '%env(bool:CREATE_ASSEMBLY_USE_IPN_PLACEHOLDER_IN_NAME)%' # Use an %%ipn%% placeholder in the name of an assembly. Placeholder is replaced with the ipn input while saving.
######################################################################################################################
# Users and Privacy
######################################################################################################################

View file

@ -243,7 +243,6 @@ abstract class BaseAdminController extends AbstractController
'timeTravel' => $timeTravel_timestamp,
'repo' => $repo,
'partsContainingElement' => $repo instanceof PartsContainingRepositoryInterface,
'showParameters' => !($this instanceof PartCustomStateController),
]);
}
@ -403,7 +402,6 @@ abstract class BaseAdminController extends AbstractController
'import_form' => $import_form,
'mass_creation_form' => $mass_creation_form,
'route_base' => $this->route_base,
'showParameters' => !($this instanceof PartCustomStateController),
]);
}

View file

@ -202,9 +202,10 @@ class AssemblyBOMEntry extends AbstractDBElement implements UniqueValidatableInt
return $this->designator;
}
public function setDesignator(string $designator): void
public function setDesignator(string $designator): AssemblyBOMEntry
{
$this->designator = $designator;
return $this;
}
/**

View file

@ -51,15 +51,17 @@ class AssemblyBOMEntryType extends AbstractType
->add('designator', TextType::class, [
'label' => 'assembly.bom.designator',
'help' => 'assembly.bom.designator.help',
'required' => false
'empty_data' => '',
'required' => false,
])
->add('mountnames', TextType::class, [
'required' => false,
'label' => 'assembly.bom.mountnames',
'empty_data' => '',
'attr' => [
'class' => 'tagsinput',
'data-controller' => 'elements--tagsinput',
]
],
])
->add('comment', RichTextEditorType::class, [
'required' => false,

View file

@ -857,7 +857,7 @@ class BOMImporter
if (isset($entry['name'])) {
$givenName = trim($entry['name']) === '' ? null : trim ($entry['name']);
if ($givenName !== null && $bomEntry->getPart() !== null && $bomEntry->getPart()->getName() !== $givenName) {
if ($givenName !== null && $part !== null && $part->getName() !== $givenName) {
//Apply different names for parts list entry
$bomEntry->setName(trim($entry['name']) === '' ? null : trim ($entry['name']));
}

View file

@ -383,8 +383,8 @@ class EntityExporter
'Id', 'ParentId', 'Type', 'ProjectNameHierarchical', 'ProjectName', 'ProjectFullName',
//BOM relevant attributes
'Quantity', 'PartId', 'PartName', 'Ipn', 'Manufacturer', 'Mpn', 'Name', 'Designator',
'Description', 'MountNames'
'Quantity', 'PartId', 'PartName', 'Ipn', 'Manufacturer', 'Mpn', 'Name', 'Mountnames',
'Description',
],
'processEntity' => fn($entity, $depth) => [
'Id' => $entity->getId(),
@ -402,9 +402,8 @@ class EntityExporter
'Manufacturer' => '-',
'Mpn' => '-',
'Name' => '-',
'Designator' => '-',
'Mountnames' => '-',
'Description' => '-',
'MountNames' => '-',
],
'processBomEntries' => fn($entity, $depth) => array_map(fn(ProjectBOMEntry $bomEntry) => [
'Id' => $entity->getId(),
@ -422,9 +421,8 @@ class EntityExporter
'Manufacturer' => $bomEntry->getPart()?->getManufacturer()?->getName() ?? '',
'Mpn' => $bomEntry->getPart()?->getManufacturerProductNumber() ?? '',
'Name' => $bomEntry->getPart()?->getName() ?? '',
'Designator' => $bomEntry->getMountnames() ?? '',
'Mountnames' => $bomEntry->getMountnames(),
'Description' => $bomEntry->getPart()?->getDescription() ?? '',
'MountNames' => $bomEntry->getMountNames(),
], $entity->getBomEntries()->toArray()),
],
Assembly::class => [
@ -434,8 +432,8 @@ class EntityExporter
//BOM relevant attributes
'Quantity', 'PartId', 'PartName', 'Ipn', 'Manufacturer', 'Mpn', 'Name', 'Designator',
'Description', 'MountNames', 'ReferencedAssemblyId', 'ReferencedAssemblyIpn',
'ReferencedAssemblyFullName'
'Mountnames', 'Description', 'ReferencedAssemblyId', 'ReferencedAssemblyIpn',
'ReferencedAssemblyFullName',
],
'processEntity' => fn($entity, $depth) => [
'Id' => $entity->getId(),
@ -455,8 +453,8 @@ class EntityExporter
'Mpn' => '-',
'Name' => '-',
'Designator' => '-',
'Mountnames' => '-',
'Description' => '-',
'MountNames' => '-',
'ReferencedAssemblyId' => '-',
'ReferencedAssemblyIpn' => '-',
'ReferencedAssemblyFullName' => '-',
@ -593,7 +591,7 @@ class EntityExporter
'Mpn' => $bomEntry->getPart()?->getManufacturerProductNumber() ?? '-',
'Name' => $bomEntry->getName() ?? '-',
'Designator' => $bomEntry->getDesignator(),
'MountNames' => $bomEntry->getMountNames(),
'Mountnames' => $bomEntry->getMountnames(),
'Description' => $bomEntry->getPart()?->getDescription() ?? '-',
'ReferencedAssemblyId' => $bomEntry->getReferencedAssembly()?->getId() ?? '-',
'ReferencedAssemblyIpn' => $bomEntry->getReferencedAssembly()?->getIpn() ?? '-',
@ -628,8 +626,8 @@ class EntityExporter
'Mpn' => $partData['part']?->getManufacturerProductNumber(),
'Name' => $partData['name'] ?? '',
'Designator' => $partData['designator'],
'Mountnames' => '-',
'Description' => $partData['part']?->getDescription(),
'MountNames' => '-',
'ReferencedAssemblyId' => '-',
'ReferencedAssemblyIpn' => '-',
'ReferencedAssemblyFullName' => '-',

View file

@ -86,7 +86,7 @@
<li class="nav-item">
<a data-bs-toggle="tab" class="nav-link link-anchor" href="#attachments">{% trans %}admin.attachments{% endtrans %}</a>
</li>
{% if entity.parameters is defined and showParameters == true %}
{% if entity.parameters is defined %}
<li class="nav-item">
<a data-bs-toggle="tab" class="nav-link link-anchor" href="#parameters">{% trans %}admin.parameters{% endtrans %}</a>
</li>
@ -201,4 +201,4 @@
</turbo-frame>
</div>
</div>
{% endblock %}
{% endblock %}

View file

@ -0,0 +1,28 @@
<table class="table table-striped table-hover">
<thead>
<tr>
<th>{% trans %}name.label{% endtrans %}</th>
<th>{% trans %}description.label{% endtrans %}</th>
<th># {% trans %}assembly.info.bom_entries_count{% endtrans %}</th>
<th># {% trans %}assembly.info.sub_assemblies_count{% endtrans %}</th>
</tr>
</thead>
<tbody>
{% for assembly in assembly.children %}
<tr>
<td> {# Name #}
<a href="{{ entity_url(assembly, 'info') }}">{{ assembly.name }}</a>
</td>
<td> {# Description #}
{{ assembly.description | format_markdown }}
</td>
<td>
{{ assembly.bomEntries | length }}
</td>
<td>
{{ assembly.children | length }}
</td>
</tr>
{% endfor %}
</tbody>
</table>

View file

@ -70,6 +70,16 @@
{% trans %}assembly.info.info.label{% endtrans %}
</button>
</li>
{% if assembly.children is not empty %}
<li class="nav-item" role="presentation">
<button class="nav-link" id="subassemblies-tab" data-bs-toggle="tab" data-bs-target="#subassemblies-tab-pane"
type="button" role="tab" aria-controls="subassemblies-tab-pane" aria-selected="false">
<i class="fa-solid fa-folder-tree fa-fw"></i>
{% trans %}assembly.info.sub_assemblies.label{% endtrans %}
<span class="badge bg-secondary">{{ assembly.children | length }}</span>
</button>
</li>
{% endif %}
<li class="nav-item" role="presentation">
<button class="nav-link" id="part-tab" data-bs-toggle="tab" data-bs-target="#part-tab-pane"
type="button" role="tab" aria-controls="part-tab-pane" aria-selected="false">
@ -99,11 +109,15 @@
</li>
{% endif %}
</ul>
<div class="tab-content">
<div class="tab-pane fade show active" id="info-tab-pane" role="tabpanel" aria-labelledby="info-tab" tabindex="0">
{% include "assemblies/info/_info.html.twig" %}
</div>
{% if assembly.children is not empty %}
<div class="tab-pane fade" id="subassemblies-tab-pane" role="tabpanel" aria-labelledby="bom-tab" tabindex="0">
{% include "assemblies/info/_subassemblies.html.twig" %}
</div>
{% endif %}
<div class="tab-pane fade" id="part-tab-pane" role="tabpanel" aria-labelledby="part-tab" tabindex="0">
{% include "assemblies/info/_part.html.twig" %}
</div>