mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-01-14 06:09:33 +00:00
Merge ebb8a2b48b into 3f6a6cc767
This commit is contained in:
commit
30840ac8b2
136 changed files with 23994 additions and 112 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<form class="form-horizontal" method="post" action="{{ path }}" data-turbo="false" data-turbo-frame="_top">
|
||||
<form class="form-horizontal" method="post" action="{{ path }}" data-turbo="false" data-turbo-frame="_top" {{ stimulus_controller('elements/toggle_visibility', {classes: ['format', 'level', 'include_children']}) }}>
|
||||
|
||||
<div class="row">
|
||||
<div class="row format">
|
||||
<label class="col-form-label col-md-3">{% trans %}export.format{% endtrans %}</label>
|
||||
<div class="col-md-9">
|
||||
<select class="form-select" name="format">
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-2">
|
||||
<div class="row mt-2 level">
|
||||
<label class="col-form-label col-md-3">{% trans %}export.level{% endtrans %}</label>
|
||||
<div class="col-md-9">
|
||||
<select class="form-select" name="level">
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-2">
|
||||
<div class="row mt-2 include_children">
|
||||
<div class="offset-md-3 col-sm">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input form-check-input" name="include_children" id="include_children" type="checkbox" checked>
|
||||
|
|
@ -34,9 +34,32 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{% if path is defined and 'assembly' in path %}
|
||||
<div class="row mt-2">
|
||||
<label class="col-form-label col-md-3" for="readableSelect" >{% trans %}export.readable.label{% endtrans %}</label>
|
||||
<div class="col-md-9">
|
||||
<select id="display" name="readableSelect" class="form-select" data-action="change->action-handler#handleAction">
|
||||
<option value="" selected></option>
|
||||
<option value="readable">{% trans %}export.readable{% endtrans %}</option>
|
||||
<option value="readable_bom">{% trans %}export.readable_bom{% endtrans %}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="row mt-2 align-items-center">
|
||||
<label class="col-form-label col-md-3" for="readableSelect">{% trans %}export.readable.label{% endtrans %}</label>
|
||||
<div class="col-md-9 d-flex align-items-center">
|
||||
<input class="form-check-input me-2" name="readableSelect" value="readable" id="display" type="checkbox" data-action="change->action-handler#handleAction">
|
||||
<label class="form-check-label" for="display">
|
||||
{% trans %}export.readable{% endtrans %}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="row mt-2">
|
||||
<div class="offset-sm-3 col-sm">
|
||||
<button type="submit" class="btn btn-primary">{% trans %}export.btn{% endtrans %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
|
|
|
|||
48
templates/admin/assembly_admin.html.twig
Normal file
48
templates/admin/assembly_admin.html.twig
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{% extends "admin/base_admin.html.twig" %}
|
||||
|
||||
{# @var entity App\Entity\AssemblySystem\Assembly #}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-archive fa-fw"></i> {% trans %}assembly.caption{% endtrans %}
|
||||
{% endblock %}
|
||||
|
||||
{% block edit_title %}
|
||||
{% trans %}assembly.edit{% endtrans %}: {{ entity.name }}
|
||||
{% endblock %}
|
||||
|
||||
{% block new_title %}
|
||||
{% trans %}assembly.new{% endtrans %}
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_pills %}
|
||||
<li class="nav-item"><a data-bs-toggle="tab" class="nav-link link-anchor" href="#part">{% trans %}assembly_bom_entry.labelp{% endtrans %}</a></li>
|
||||
{% endblock %}
|
||||
|
||||
{% block quick_links %}
|
||||
<div class="btn-toolbar" style="display: inline-block;">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-outline-secondary" href="{{ entity_url(entity) }}"><i class="fas fa-eye fa-fw"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_controls %}
|
||||
{{ form_row(form.description) }}
|
||||
{{ form_row(form.status) }}
|
||||
{{ form_row(form.ipn) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_panes %}
|
||||
<div class="tab-pane" id="part">
|
||||
{% form_theme form.bom_entries with ['form/collection_types_layout_assembly.html.twig'] %}
|
||||
{{ form_errors(form.bom_entries) }}
|
||||
{{ form_widget(form.bom_entries) }}
|
||||
{% if entity.id %}
|
||||
<a href="{{ path('assembly_import_bom', {'id': entity.id}) }}" class="btn btn-secondary mb-2"
|
||||
{% if not is_granted('edit', entity) %}disabled="disabled"{% endif %}>
|
||||
<i class="fa-solid fa-file-import fa-fw"></i>
|
||||
{% trans %}assembly.edit.bom.import_bom{% endtrans %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
22
templates/assemblies/add_parts.html.twig
Normal file
22
templates/assemblies/add_parts.html.twig
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{% extends "main_card.html.twig" %}
|
||||
|
||||
{% block title %}{% trans %}assembly.add_parts_to_assembly{% endtrans %}{% endblock %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fa-solid fa-magnifying-glass-plus fa-fw"></i>
|
||||
{% trans %}assembly.add_parts_to_assembly{% endtrans %}{% if assembly %}: <i>{{ assembly.name }}</i>{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block card_content %}
|
||||
|
||||
{{ form_start(form) }}
|
||||
|
||||
{{ form_row(form.assembly) }}
|
||||
{% form_theme form.bom_entries with ['form/collection_types_layout_assembly.html.twig'] %}
|
||||
{{ form_widget(form.bom_entries) }}
|
||||
|
||||
{{ form_row(form.submit) }}
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
{% endblock %}
|
||||
103
templates/assemblies/export_bom_pdf.html.twig
Normal file
103
templates/assemblies/export_bom_pdf.html.twig
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Assembly Hierarchy</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 20px; }
|
||||
table { border-collapse: collapse; width: 100%; margin-top: 10px; font-size: 10px;}
|
||||
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
|
||||
th { background-color: #f2f2f2; }
|
||||
.assembly-header { font-size: 14px; font-weight: bold; margin-top: 10px; margin-bottom: 10px; }
|
||||
.toc-table { margin-bottom: 40px; width: auto; font-size: 12px; }
|
||||
.toc-table th, .toc-table td { border: none; padding: 5px; text-align: left; }
|
||||
.referenced-assembly-table { margin-left: 20px; margin-top: 10px; }
|
||||
.page-break { page-break-after: always; }
|
||||
#footer { position: fixed; right: 0px; bottom: 10px; text-align: center; font-size: 10px; }
|
||||
#footer .page:after { content: counter(page, decimal); }
|
||||
@page { margin: 20px 30px 40px 50px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Inhaltsverzeichnis -->
|
||||
<h1>Table of Contents</h1>
|
||||
<table class="toc-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Assembly Name</th>
|
||||
<th>IPN</th>
|
||||
<th>Section</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for assembly in assemblies %}
|
||||
<tr>
|
||||
<td>{{ loop.index }}</td>
|
||||
<td>Assembly: {{ assembly.name }}</td>
|
||||
<td>{% if assembly.ipn != '' %}{{ assembly.ipn }}{% else %}-{% endif %}</td>
|
||||
<td>{{ loop.index + 1 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="page-break"></div>
|
||||
|
||||
<!-- Assembly Details -->
|
||||
{% for assembly in assemblies %}
|
||||
<div class="assembly-header">Assembly: {{ assembly.name }}</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>IPN</th>
|
||||
<th>Quantity</th>
|
||||
<th>Multiplier</th>
|
||||
<th>Effective Quantity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for part in assembly.parts %}
|
||||
<tr>
|
||||
<td>{{ part.name }}</td>
|
||||
<td>{{ part.ipn }}</td>
|
||||
<td>{{ part.quantity }}</td>
|
||||
<td>{% if assembly.multiplier %}{{ assembly.multiplier }}{% else %}-{% endif %}</td>
|
||||
<td>{{ part.effectiveQuantity }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% for other in assembly.others %}
|
||||
<tr>
|
||||
<td>{{ other.name }}</td>
|
||||
<td>{{ other.ipn }}</td>
|
||||
<td>{{ other.quantity }}</td>
|
||||
<td>{{ other.multiplier }}</td>
|
||||
<td>{{ other.effectiveQuantity }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% for referencedAssembly in assembly.referencedAssemblies %}
|
||||
<tr>
|
||||
<td>{{ referencedAssembly.name }}</td>
|
||||
<td>{{ referencedAssembly.ipn }}</td>
|
||||
<td>{{ referencedAssembly.quantity }}</td>
|
||||
<td></td>
|
||||
<td>{{ referencedAssembly.quantity }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% for refAssembly in assembly.referencedAssemblies %}
|
||||
{% include 'assemblies/export_bom_referenced_assembly_pdf.html.twig' with {'assembly': refAssembly} only %}
|
||||
{% endfor %}
|
||||
|
||||
{% if not loop.last %}
|
||||
<div style="page-break-after: always;"></div>
|
||||
{% endif %}
|
||||
|
||||
<div id="footer">
|
||||
<p class="page">Section </p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<div class="referenced-assembly-table">
|
||||
<div class="assembly-header">Referenced Assembly: {{ assembly.name }} [IPN: {% if assembly.ipn != '' %}{{ assembly.ipn }}{% else %}-{% endif %}, quantity: {{ assembly.quantity }}]</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Name</th>
|
||||
<th>IPN</th>
|
||||
<th>Quantity</th>
|
||||
<th>Multiplier</th>
|
||||
<th>Effective Quantity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for part in assembly.parts %}
|
||||
<tr>
|
||||
<td>Part</td>
|
||||
<td>{{ part.name }}</td>
|
||||
<td>{{ part.ipn }}</td>
|
||||
<td>{{ part.quantity }}</td>
|
||||
<td>{% if assembly.multiplier %}{{ assembly.multiplier }}{% else %}-{% endif %}</td>
|
||||
<td>{{ part.effectiveQuantity }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
{% for other in assembly.others %}
|
||||
<tr>
|
||||
<td>Other</td>
|
||||
<td>{{ other.name }}</td>
|
||||
<td>-</td>
|
||||
<td>{{ other.quantity }}</td>
|
||||
<td>{{ other.multiplier }}</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
{% for referencedAssembly in assembly.referencedAssemblies %}
|
||||
<tr>
|
||||
<td>Referenced assembly</td>
|
||||
<td>{{ referencedAssembly.name }}</td>
|
||||
<td>-</td>
|
||||
<td>{{ referencedAssembly.quantity }}</td>
|
||||
<td></td>
|
||||
<td>{{ referencedAssembly.multiplier }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Rekursive Auflistung weiterer Assemblies -->
|
||||
{% for refAssembly in assembly.referencedAssemblies %}
|
||||
{% include 'assemblies/export_bom_referenced_assembly_pdf.html.twig' with {'assembly': refAssembly} only %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
114
templates/assemblies/import_bom.html.twig
Normal file
114
templates/assemblies/import_bom.html.twig
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
{% extends "main_card.html.twig" %}
|
||||
|
||||
{% block title %}{% trans %}assembly.import_bom{% endtrans %}{% endblock %}
|
||||
|
||||
{% block before_card %}
|
||||
{% if validationErrors or importerErrors %}
|
||||
<div class="alert alert-danger">
|
||||
<h4><i class="fa-solid fa-exclamation-triangle fa-fw"></i> {% trans %}parts.import.errors.title{% endtrans %}</h4>
|
||||
<ul>
|
||||
{% if validationErrors %}
|
||||
{% for violation in validationErrors %}
|
||||
<li>
|
||||
<b>{{ violation.propertyPath }}: </b>
|
||||
{{ violation.message|trans(violation.parameters, 'validators') }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if importerErrors %}
|
||||
{% for violation in importerErrors %}
|
||||
<li>
|
||||
<b>{{ violation.propertyPath }}: </b>
|
||||
{{ violation.message|trans(violation.parameters, 'validators')|raw }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fa-solid fa-file-import fa-fw"></i>
|
||||
{% trans %}assembly.import_bom{% endtrans %}{% if assembly %}: <i>{{ assembly.name }}</i>{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block card_content %}
|
||||
{{ form(form) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_content %}
|
||||
<div class="container-fluid row d-flex align-items-stretch pe-0 me-0">
|
||||
<div class="col-md-12 col-lg-6 ps-0 mt-3 d-flex">
|
||||
<div class="card border-secondary flex-grow-1 overflow-auto">
|
||||
<div class="card-header bg-secondary text-white">
|
||||
{% trans %}assembly.import_bom.template.header.json{% endtrans %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<pre>{{ jsonTemplate|json_encode(constant('JSON_PRETTY_PRINT') b-or constant('JSON_UNESCAPED_UNICODE')) }}</pre>
|
||||
|
||||
{{ 'assembly.bom_import.template.json.table'|trans|raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 col-lg-6 ps-0 mt-3 d-flex">
|
||||
<div class="card border-secondary flex-grow-1 overflow-auto">
|
||||
<div class="card-header bg-secondary text-white">
|
||||
{% trans %}assembly.import_bom.template.header.csv{% endtrans %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ 'assembly.bom_import.template.csv.exptected_columns'|trans }}
|
||||
|
||||
<pre>quantity;name;part_id;part_mpnr;part_ipn;part_name;part_description;part_manufacturer_id;part_manufacturer_name;part_category_id;part_category_name</pre>
|
||||
|
||||
<ul>
|
||||
<li>quantity</li>
|
||||
<li>name</li>
|
||||
<li>part_id</li>
|
||||
<li>part_mpnr</li>
|
||||
<li>part_ipn</li>
|
||||
<li>part_name</li>
|
||||
<li>part_description</li>
|
||||
<li>part_manufacturer_id</li>
|
||||
<li>part_manufacturer_name</li>
|
||||
<li>part_category_id</li>
|
||||
<li>part_category_name</li>
|
||||
</ul>
|
||||
|
||||
{{ 'assembly.bom_import.template.csv.table'|trans|raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 col-lg-6 ps-0 mt-3 d-flex overflow-auto">
|
||||
<div class="card border-secondary flex-grow-1 overflow-auto">
|
||||
<div class="card-header bg-secondary text-white">
|
||||
{% trans %}assembly.import_bom.template.header.kicad_pcbnew{% endtrans %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ 'assembly.bom_import.template.kicad_pcbnew.exptected_columns'|trans }}
|
||||
<pre>Id;Designator;Package;Quantity;Designation;Supplier and ref</pre>
|
||||
|
||||
<ul>
|
||||
<li>Id</li>
|
||||
<li>Designator</li>
|
||||
<li>Package</li>
|
||||
<li>Quantity</li>
|
||||
<li>Designation</li>
|
||||
<li>Supplier and ref</li>
|
||||
<li>Note</li>
|
||||
<li>Footprint</li>
|
||||
<li>Value</li>
|
||||
<li>Footprint</li>
|
||||
</ul>
|
||||
|
||||
{{ 'assembly.bom_import.template.kicad_pcbnew.exptected_columns.note'|trans|raw }}
|
||||
|
||||
{{ 'assembly.bom_import.template.kicad_pcbnew.table'|trans|raw }}
|
||||
|
||||
{{ 'assembly.bom_import.template.json.table'|trans|raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
91
templates/assemblies/info/_attachments_info.html.twig
Normal file
91
templates/assemblies/info/_attachments_info.html.twig
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
{% import "helper.twig" as helper %}
|
||||
|
||||
<table class="table table-striped table-sm table-hover table-responsive-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{% trans %}attachment.name{% endtrans %}</th>
|
||||
<th>{% trans %}attachment.attachment_type{% endtrans %}</th>
|
||||
<th>{% trans %}attachment.file_name{% endtrans %}</th>
|
||||
<th>{% trans %}attachment.file_size{% endtrans %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
{% for attachment in assembly.attachments %}
|
||||
<tr>
|
||||
<td>
|
||||
{% import "components/attachments.macro.html.twig" as attachments %}
|
||||
{{ attachments.attachment_icon(attachment, attachment_manager) }}
|
||||
</td>
|
||||
<td class="align-middle">{{ attachment.name }}</td>
|
||||
<td class="align-middle">{{ attachment.attachmentType.fullPath }}</td>
|
||||
<td class="align-middle">
|
||||
{% if attachment.hasInternal() %}
|
||||
{{ attachment.filename }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle h6">
|
||||
{% if not attachment.hasInternal() %}
|
||||
<span class="badge bg-primary">
|
||||
<i class="fas fa-fw fa-globe"></i> {% trans %}attachment.external_only{% endtrans %}
|
||||
</span>
|
||||
{% elseif attachment_manager.internalFileExisting(attachment) %}
|
||||
<span class="badge bg-secondary">
|
||||
<i class="fas fa-hdd fa-fw"></i> {{ attachment_manager.humanFileSize(attachment) }}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="badge bg-warning">
|
||||
<i class="fas fa-exclamation-circle fa-fw"></i> {% trans %}attachment.file_not_found{% endtrans %}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if attachment.secure %}
|
||||
<br><span class="badge bg-success">
|
||||
<i class="fas fa-fw fa-shield-alt"></i> {% trans %}attachment.secure{% endtrans %}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if attachment == assembly.masterPictureAttachment %}
|
||||
<br>
|
||||
<span class="badge bg-primary">
|
||||
<i class="fas fa-id-card"></i> {% trans %}attachment.preview{% endtrans %}
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td><div class="btn-group" role="group" aria-label="">
|
||||
<a {% if attachment.hasExternal() %}href="{{ attachment.externalPath }}"{% endif %} target="_blank"
|
||||
class="btn btn-secondary {% if not attachment.hasExternal() %}disabled{% endif %}"
|
||||
data-turbo="false" title="{% trans with {"%host%": attachment.host} %}attachment.view_external.view_at{% endtrans %}" rel="noopener">
|
||||
<i class="fas fa-globe fa-fw"></i>
|
||||
</a>
|
||||
<a {% if attachment_manager.isInternalFileExisting(attachment) %}href="{{ entity_url(attachment, 'file_view') }}"{% endif %} target="_blank"
|
||||
class="btn btn-secondary {% if not attachment_manager.isInternalFileExisting(attachment) or (attachment.secure and not is_granted("show_private", attachment)) %}disabled{% endif %}"
|
||||
data-turbo="false" title="{% trans %}attachment.view_local{% endtrans %}" rel="noopener">
|
||||
<i class="fas fa-eye fa-fw"></i>
|
||||
</a>
|
||||
<a {% if attachment_manager.isInternalFileExisting(attachment) %}href="{{ entity_url(attachment, 'file_download') }}"{% endif %} data-turbo="false"
|
||||
class="btn btn-secondary {% if not attachment_manager.isInternalFileExisting(attachment) or (attachment.secure and not is_granted("show_private", attachment)) %}disabled{% endif %}"
|
||||
title="{% trans %}attachment.download_local{% endtrans %}">
|
||||
<i class="fas fa-download fa-fw"></i>
|
||||
</a>
|
||||
|
||||
<div class="btn-group" role="group">
|
||||
<button id="btnGroupDrop1" type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-boundary="window">
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
|
||||
<span class="text-muted dropdown-item-text" ><i class="fas fa-lightbulb fa-fw"></i> <b>ID:</b> {{ attachment.iD }}</span>
|
||||
<span class="text-muted dropdown-item-text" ><i class="fas fa-history fa-fw"></i> <b>{% trans %}lastModified{% endtrans %}:</b> {{ helper.entity_last_modified(attachment) }}</span>
|
||||
<span class="text-muted dropdown-item-text" ><i class="fas fa-calendar-plus fa-fw"></i> <b>{% trans %}createdAt{% endtrans %}:</b> {{ helper.entity_created_at(attachment) }}</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
72
templates/assemblies/info/_info.html.twig
Normal file
72
templates/assemblies/info/_info.html.twig
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
{% import "helper.twig" as helper %}
|
||||
|
||||
<div class="row mt-2">
|
||||
<div class="col-md-8">
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-lg-4 col-4 mt-auto mb-auto">
|
||||
{% if assembly.masterPictureAttachment %}
|
||||
<a href="{{ entity_url(assembly.masterPictureAttachment, 'file_view') }}" data-turbo="false" target="_blank" rel="noopener">
|
||||
<img class="d-block w-100 img-fluid img-thumbnail bg-body-tertiary part-info-image" src="{{ entity_url(assembly.masterPictureAttachment, 'file_view') }}" alt="">
|
||||
</a>
|
||||
{% else %}
|
||||
<img src="{{ asset('img/part_placeholder.svg') }}" class="img-fluid img-thumbnail bg-body-tertiary mb-2 " alt="Part main image" height="300" width="300">
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-9 col-lg-8 col-7">
|
||||
<h3 class="w-fit" title="{% trans %}name.label{% endtrans %}">{{ assembly.name }}
|
||||
{# You need edit permission to use the edit button #}
|
||||
{% if is_granted('edit', assembly) %}
|
||||
<a href="{{ entity_url(assembly, 'edit') }}"><i class="fas fa-fw fa-sm fa-edit"></i></a>
|
||||
{% endif %}
|
||||
</h3>
|
||||
<h6 class="text-muted w-fit" title="{% trans %}description.label{% endtrans %}"><span>{{ assembly.description|format_markdown(true) }}</span></h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-4"> {# Sidebar panel with infos about last creation date, etc. #}
|
||||
<div class="mb-3">
|
||||
<span class="text-muted" title="{% trans %}lastModified{% endtrans %}">
|
||||
<i class="fas fa-history fa-fw"></i> {{ helper.date_user_combination(assembly, true) }}
|
||||
</span>
|
||||
<br>
|
||||
<span class="text-muted mt-1" title="{% trans %}createdAt{% endtrans %}">
|
||||
<i class="fas fa-calendar-plus fa-fw"></i> {{ helper.date_user_combination(assembly, false) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-1">
|
||||
<h6>
|
||||
{{ helper.assemblies_status_to_badge(assembly.status) }}
|
||||
</h6>
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
<h6>
|
||||
<span class="badge badge-primary bg-primary">
|
||||
<i class="fa-solid fa-list-check fa-fw"></i>
|
||||
{{ assembly.bomEntries | length }}
|
||||
{% trans %}assembly.info.bom_entries_count{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
</div>
|
||||
{% if assembly.children is not empty %}
|
||||
<div class="mt-1">
|
||||
<h6>
|
||||
<span class="badge badge-primary bg-secondary">
|
||||
<i class="fa-solid fa-folder-tree fa-fw"></i>
|
||||
{{ assembly.children | length }}
|
||||
{% trans %}assembly.info.sub_assemblies_count{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if assembly.comment is not empty %}
|
||||
<p>
|
||||
<h5>{% trans %}comment.label{% endtrans %}:</h5>
|
||||
{{ assembly.comment|format_markdown }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
118
templates/assemblies/info/_info_card.html.twig
Normal file
118
templates/assemblies/info/_info_card.html.twig
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
{% import "helper.twig" as helper %}
|
||||
{% import "label_system/dropdown_macro.html.twig" as dropdown %}
|
||||
|
||||
{{ helper.breadcrumb_entity_link(assembly) }}
|
||||
|
||||
<div class="accordion mb-4" id="listAccordion">
|
||||
<div class="accordion-item">
|
||||
<div class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2" data-bs-toggle="collapse" data-bs-target="#entityInfo" aria-expanded="true">
|
||||
{% if assembly.masterPictureAttachment is not null and attachment_manager.isFileExisting(assembly.masterPictureAttachment) %}
|
||||
<img class="hoverpic ms-0 me-1 d-inline" {{ stimulus_controller('elements/hoverpic') }} data-thumbnail="{{ entity_url(assembly.masterPictureAttachment, 'file_view') }}" src="{{ attachment_thumbnail(assembly.masterPictureAttachment, 'thumbnail_sm') }}">
|
||||
{% else %}
|
||||
{{ helper.entity_icon(assembly, "me-1") }}
|
||||
{% endif %}
|
||||
{% trans %}assembly.label{% endtrans %}: <b>{{ assembly.name }}</b>
|
||||
</button>
|
||||
</div>
|
||||
<div id="entityInfo" class="accordion-collapse collapse show" data-bs-parent="#listAccordion">
|
||||
<div class="accordion-body">
|
||||
{% if assembly.description is not empty %}
|
||||
{{ assembly.description|format_markdown }}
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
|
||||
<a class="nav-link active" id="v-pills-home-tab" data-bs-toggle="pill" href="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">
|
||||
<i class="fas fa-info-circle fa-fw"></i>
|
||||
{% trans %}entity.info.common.tab{% endtrans %}
|
||||
</a>
|
||||
<a class="nav-link" id="v-pills-statistics-tab" data-bs-toggle="pill" href="#v-pills-statistics" role="tab" aria-controls="v-pills-profile" aria-selected="false">
|
||||
<i class="fas fa-chart-pie fa-fw"></i>
|
||||
{% trans %}entity.info.statistics.tab{% endtrans %}
|
||||
</a>
|
||||
{% if assembly.attachments is not empty %}
|
||||
<a class="nav-link" id="v-pills-attachments-tab" data-bs-toggle="pill" href="#v-pills-attachments" role="tab" aria-controls="v-pills-attachments" aria-selected="false">
|
||||
<i class="fas fa-paperclip fa-fw"></i>
|
||||
{% trans %}entity.info.attachments.tab{% endtrans %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if assembly.comment is not empty %}
|
||||
<a class="nav-link" id="v-pills-comment-tab" data-bs-toggle="pill" href="#v-pills-comment" role="tab">
|
||||
<i class="fas fa-comment-alt fa-fw"></i>
|
||||
{% trans %}comment.label{% endtrans %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<div class="tab-content" id="v-pills-tabContent">
|
||||
<div class="tab-pane fade show active" id="v-pills-home" role="tabpanel" aria-labelledby="v-pills-home-tab">
|
||||
<div class="row">
|
||||
<div class="col-sm-9 form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4">{% trans %}entity.info.name{% endtrans %}:</label>
|
||||
<span class="col-sm form-control-static">{{ assembly.name }}</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4">{% trans %}entity.info.parent{% endtrans %}:</label>
|
||||
<span class="col-sm form-control-static">
|
||||
{% if assembly.parent %}
|
||||
{{ assembly.parent.fullPath }}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
{% block quick_links %}{% endblock %}
|
||||
|
||||
<a class="btn btn-secondary w-100 mb-2" href="{{ entity_url(assembly, 'edit') }}">
|
||||
<i class="fas fa-edit"></i> {% trans %}entity.edit.btn{% endtrans %}
|
||||
</a>
|
||||
<div class="">
|
||||
<span class="text-muted" title="{% trans %}lastModified{% endtrans %}">
|
||||
<i class="fas fa-history fa-fw"></i> {{ assembly.lastModified | format_datetime("short") }}
|
||||
</span>
|
||||
<br>
|
||||
<span class="text-muted mt-1" title="{% trans %}createdAt{% endtrans %}">
|
||||
<i class="fas fa-calendar-plus fa-fw"></i> {{ assembly.addedDate | format_datetime("short") }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="v-pills-statistics" role="tabpanel" aria-labelledby="v-pills-statistics-tab">
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4">{% trans %}entity.info.children_count{% endtrans %}:</label>
|
||||
<span class="col-sm form-control-static">{{ assembly.children | length }}</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4">{% trans %}entity.info.parts_count{% endtrans %}:</label>
|
||||
<span class="col-sm form-control-static">{{ assembly.bomEntries | length }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if assembly.attachments is not empty %}
|
||||
<div class="tab-pane fade" id="v-pills-attachments" role="tabpanel" aria-labelledby="v-pills-attachments-tab">
|
||||
{% include "parts/info/_attachments_info.html.twig" with {"part": assembly} %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if assembly.comment is not empty %}
|
||||
<div class="tab-pane fade" id="v-pills-comment" role="tabpanel" aria-labelledby="home-tab">
|
||||
<div class="container-fluid mt-2 latex" data-controller="common--latex">
|
||||
{{ assembly.comment|format_markdown }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
5
templates/assemblies/info/_part.html.twig
Normal file
5
templates/assemblies/info/_part.html.twig
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{% import "components/datatables.macro.html.twig" as datatables %}
|
||||
|
||||
<div class="mb-2 mt-2"></div>
|
||||
|
||||
{{ datatables.datatable(datatable, 'elements/datatables/datatables', 'assemblies') }}
|
||||
28
templates/assemblies/info/_subassemblies.html.twig
Normal file
28
templates/assemblies/info/_subassemblies.html.twig
Normal 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>
|
||||
135
templates/assemblies/info/info.html.twig
Normal file
135
templates/assemblies/info/info.html.twig
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
{% extends "main_card.html.twig" %}
|
||||
{% import "helper.twig" as helper %}
|
||||
|
||||
{% block title %}
|
||||
{% trans %}assembly.info.title{% endtrans %}: {{ assembly.name }}
|
||||
{% endblock %}
|
||||
|
||||
{% block before_card %}
|
||||
<div class="row mb-3">
|
||||
<div class="col d-flex align-items-center">
|
||||
<a href="{{ path('assembly_new') }}"
|
||||
class="btn btn-success me-2 {% if not is_granted('@assemblies.create') %}disabled{% endif %}">
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}assembly.new{% endtrans %}
|
||||
</a>
|
||||
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-success" {% if not is_granted('@assemblies.edit') %}disabled{% endif %}
|
||||
href="{{ path('assembly_add_parts', {"id": assembly.id, "_redirect": uri_without_host(app.request)}) }}">
|
||||
<i class="fa-solid fa-square-plus fa-fw"></i>
|
||||
{% trans %}assembly.info.bom_add_parts{% endtrans %}
|
||||
</a>
|
||||
<button type="button" class="btn btn-success dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<span class="visually-hidden">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ path('assembly_import_bom', {'id': assembly.id}) }}" {% if not is_granted('edit', assembly) %}disabled="disabled"{% endif %}>
|
||||
<i class="fa-solid fa-file-import fa-fw"></i>
|
||||
{% trans %}assembly.edit.bom.import_bom{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<a class="btn btn-secondary ms-2" {% if not is_granted('@assemblies.edit') %}disabled{% endif %}
|
||||
href="{{ path('assembly_edit', {"id": assembly.id}) }}#part">
|
||||
<i class="fa-solid fa-square-plus fa-cog"></i>
|
||||
{% trans %}assembly_bom_entry.labelp{% endtrans %}
|
||||
</a>
|
||||
|
||||
<a class="btn btn-secondary ms-2" {% if not is_granted('@assemblies.edit') %}disabled{% endif %}
|
||||
href="{{ path('assembly_edit', {"id": assembly.id}) }}">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ helper.breadcrumb_entity_link(assembly) }}
|
||||
{{ parent() }}
|
||||
{% endblock %}
|
||||
|
||||
{% block card_title %}
|
||||
{% if assembly.masterPictureAttachment is not null and attachment_manager.isFileExisting(assembly.masterPictureAttachment) %}
|
||||
<img class="hoverpic ms-0 me-1 d-inline" {{ stimulus_controller('elements/hoverpic') }} data-thumbnail="{{ entity_url(assembly.masterPictureAttachment, 'file_view') }}" src="{{ attachment_thumbnail(assembly.masterPictureAttachment, 'thumbnail_sm') }}">
|
||||
{% else %}
|
||||
{{ helper.entity_icon(assembly, "me-1") }}
|
||||
{% endif %}
|
||||
{% trans %}assembly.info.title{% endtrans %}: <b>{{ assembly.name }}</b>
|
||||
{% endblock %}
|
||||
|
||||
{% block card_content %}
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="info-tab" data-bs-toggle="tab" data-bs-target="#info-tab-pane"
|
||||
type="button" role="tab" aria-controls="info-tab-pane" aria-selected="true">
|
||||
<i class="fa-solid fa-circle-info fa-fw"></i>
|
||||
{% 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">
|
||||
<i class="fa-solid fa-list-check fa-fw"></i>
|
||||
{% trans %}assembly_bom_entry.labelp{% endtrans %}
|
||||
<span class="badge bg-secondary">{{ assembly.bomEntries | length }}</span>
|
||||
</button>
|
||||
</li>
|
||||
{% if assembly.attachments is not empty %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="attachments-tab" data-bs-toggle="tab"
|
||||
data-bs-target="#attachments-tab-pane" role="tab">
|
||||
<i class="fas fa-paperclip fa-fw"></i>
|
||||
{% trans %}attachment.labelp{% endtrans %}
|
||||
<span class="badge bg-secondary">{{ assembly.attachments | length }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if assembly.parameters is not empty %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="parameters-tab" data-bs-toggle="tab"
|
||||
data-bs-target="#parameters-tab-pane" role="tab">
|
||||
<i class="fas fa-atlas fa-fw"></i>
|
||||
{% trans %}entity.info.parameters.tab{% endtrans %}
|
||||
<span class="badge bg-secondary">{{ assembly.parameters | length }}</span>
|
||||
</a>
|
||||
</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>
|
||||
<div class="tab-pane fade" id="attachments-tab-pane" role="tabpanel" aria-labelledby="attachments-tab" tabindex="0">
|
||||
{% include "assemblies/info/_attachments_info.html.twig" with {"assembly": assembly} %}
|
||||
</div>
|
||||
<div class="tab-pane fade" id="parameters-tab-pane" role="tabpanel" aria-labelledby="parameters-tab">
|
||||
{% for name, parameters in assembly.groupedParameters %}
|
||||
{% if name is not empty %}<h5 class="mt-1">{{ name }}</h5>{% endif %}
|
||||
{{ helper.parameters_table(assembly.parameters) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
6
templates/assemblies/lists/_action_bar.html.twig
Normal file
6
templates/assemblies/lists/_action_bar.html.twig
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<a href="{{ path('assembly_new', url_options) }}" class="btn btn-success float-start {% if not is_granted("@assemblies.create") or (entity is defined and entity.notSelectable) %}disabled{% endif %}"><i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans%}assemblies.create.btn{% endtrans %}</a>
|
||||
</div>
|
||||
</div>
|
||||
62
templates/assemblies/lists/_filter.html.twig
Normal file
62
templates/assemblies/lists/_filter.html.twig
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<div class="accordion-item">
|
||||
<div class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#filterFormCollapse" aria-expanded="false" aria-controls="filterFormCollapse"><i class="fa-solid fa-filter fa-fw"></i> {% trans %}filter.title{% endtrans %}</button>
|
||||
</div>
|
||||
<div id="filterFormCollapse" class="accordion-collapse collapse" data-bs-parent="#listAccordion">
|
||||
<div class="accordion-body">
|
||||
<ul class="nav nav-tabs" id="filterTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="filter-common-tab" data-bs-toggle="tab" data-bs-target="#filter-common"><i class="fas fa-id-card fa-fw"></i> {% trans %}assembly.edit.tab.common{% endtrans %}</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="filter-advanced-tab" data-bs-toggle="tab" data-bs-target="#filter-advanced"><i class="fas fa-shapes fa-fw"></i> {% trans %}assembly.edit.tab.advanced{% endtrans %}</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="filter-attachments-tab" data-bs-toggle="tab" data-bs-target="#filter-attachments"><i class="fas fa-paperclip fa-fw"></i> {% trans %}assembly.edit.tab.attachments{% endtrans %}</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{{ form_start(filterForm, {"attr": {"data-controller": "helpers--form-cleanup", "data-action": "helpers--form-cleanup#submit"}}) }}
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active pt-3" id="filter-common" role="tabpanel" aria-labelledby="filter-common-tab" tabindex="0">
|
||||
{{ form_row(filterForm.name) }}
|
||||
{{ form_row(filterForm.description) }}
|
||||
{{ form_row(filterForm.comment) }}
|
||||
</div>
|
||||
|
||||
<div class="tab-pane pt-3" id="filter-advanced" role="tabpanel" aria-labelledby="filter-advanced-tab" tabindex="0">
|
||||
{{ form_row(filterForm.dbId) }}
|
||||
{{ form_row(filterForm.ipn) }}
|
||||
{{ form_row(filterForm.lastModified) }}
|
||||
{{ form_row(filterForm.addedDate) }}
|
||||
</div>
|
||||
|
||||
<div class="tab-pane pt-3" id="filter-attachments" role="tabpanel" aria-labelledby="filter-attachments-tab" tabindex="0">
|
||||
{{ form_row(filterForm.attachmentsCount) }}
|
||||
{{ form_row(filterForm.attachmentType) }}
|
||||
{{ form_row(filterForm.attachmentName) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ form_row(filterForm.submit) }}
|
||||
{{ form_row(filterForm.discard) }}
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-9 offset-sm-3">
|
||||
<button type="button" class="btn btn-danger" {{ stimulus_action('helpers/form_cleanup', 'clearAll') }}>{% trans %}filter.clear_filters{% endtrans %}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Retain the query parameters of the search form if it is existing #}
|
||||
{% if searchFilter is defined %}
|
||||
{% for property, value in searchFilter|to_array %}
|
||||
<input type="hidden" name="{{ property }}" data-no-clear="true" value="{{ value }}">
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{{ form_end(filterForm) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
30
templates/assemblies/lists/all_list.html.twig
Normal file
30
templates/assemblies/lists/all_list.html.twig
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{% extends "base.html.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{% trans %}assembly_list.all.title{% endtrans %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="accordion mb-3" id="listAccordion">
|
||||
<div class="accordion-item">
|
||||
<div class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2" data-bs-toggle="collapse" data-bs-target="#searchInfo" disabled>
|
||||
<i class="fa-solid fa-globe fa-fw"></i>
|
||||
{% trans %}assembly_list.all.title{% endtrans %}
|
||||
</button>
|
||||
</div>
|
||||
<div id="searchInfo" class="accordion-collapse collapse" data-bs-parent="#listAccordion">
|
||||
<div class="accordion-body">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "assemblies/lists/_filter.html.twig" %}
|
||||
</div>
|
||||
|
||||
{% include "assemblies/lists/_action_bar.html.twig" with {'url_options': {}} %}
|
||||
{% include "assemblies/lists/data.html.twig" %}
|
||||
|
||||
{% endblock %}
|
||||
3
templates/assemblies/lists/data.html.twig
Normal file
3
templates/assemblies/lists/data.html.twig
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{% import "components/datatables.macro.html.twig" as datatables %}
|
||||
|
||||
{{ datatables.partsDatatableWithForm(datatable) }}
|
||||
|
|
@ -65,6 +65,10 @@
|
|||
<label for="search_footprint" class="form-check-label justify-content-start">{% trans %}footprint.label{% endtrans %}</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="search_assembly" name="assembly" value="1" {{ stimulus_controller('elements/localStorage_checkbox') }}>
|
||||
<label for="search_assembly" class="form-check-label justify-content-start">{% trans %}assembly.label{% endtrans %}</label>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="regex" name="regex" value="1" {{ stimulus_controller('elements/localStorage_checkbox') }}>
|
||||
|
|
@ -106,4 +110,4 @@
|
|||
{{ _self.settings_drodown(is_navbar) }}
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endmacro %}
|
||||
{% endmacro %}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
['manufacturers', path('tree_manufacturer_root'), '@manufacturer@@', is_granted('@manufacturers.read') and is_granted('@parts.read'), 'manufacturer'],
|
||||
['suppliers', path('tree_supplier_root'), '@supplier@@', is_granted('@suppliers.read') and is_granted('@parts.read'), 'supplier'],
|
||||
['projects', path('tree_device_root'), '@project@@', is_granted('@projects.read'), 'project'],
|
||||
['assembly', path('tree_assembly_root'), 'assembly.labelp', is_granted('@assemblies.read'), 'assembly'],
|
||||
['tools', path('tree_tools'), 'tools.label', true, 'tool'],
|
||||
] %}
|
||||
|
||||
|
|
|
|||
74
templates/form/collection_types_layout_assembly.html.twig
Normal file
74
templates/form/collection_types_layout_assembly.html.twig
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
{% block assembly_bom_entry_collection_widget %}
|
||||
{% import 'components/collection_type.macro.html.twig' as collection %}
|
||||
<div {{ collection.controller(form, 'assembly.bom.delete.confirm', 3) }}>
|
||||
<table class="table table-striped table-bordered table-sm" {{ collection.target() }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th> {# expand button #}
|
||||
<th>{% trans %}assembly.bom.quantity{% endtrans %}</th>
|
||||
<th>{% trans %}assembly.bom.partOrAssembly{% endtrans %}</th>
|
||||
<th>{% trans %}assembly.bom.identifiers{% endtrans %}</th>
|
||||
<th></th> {# Remove button #}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for entry in form %}
|
||||
{{ form_widget(entry) }}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-success mb-2" {{ collection.create_btn() }}>
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}assembly.bom.add_entry{% endtrans %}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block assembly_bom_entry_widget %}
|
||||
{% set target_id = 'expand_row-' ~ form.vars.name %}
|
||||
|
||||
{% import 'components/collection_type.macro.html.twig' as collection %}
|
||||
<tr>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-outline-secondary" type="button" data-bs-toggle="collapse" data-bs-target="#{{ target_id }}">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
{{ form_widget(form.quantity) }}
|
||||
{{ form_errors(form.quantity) }}
|
||||
</td>
|
||||
<td style="min-width: 450px;">
|
||||
{{ form_row(form.part) }}
|
||||
{{ form_errors(form.part) }}
|
||||
<div class="text-center mb-2" style="line-height: 1">∨</div>
|
||||
{{ form_widget(form.referencedAssembly) }}
|
||||
{{ form_errors(form.referencedAssembly) }}
|
||||
</td>
|
||||
<td style="min-width: 450px;">
|
||||
{{ form_row(form.name) }}
|
||||
{{ form_errors(form.name) }}
|
||||
<div class="text-center mb-2" style="line-height: 1"></div>
|
||||
{{ form_row(form.designator) }}
|
||||
{{ form_errors(form.designator) }}
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-danger lot_btn_delete position-relative" {{ collection.delete_btn() }}>
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
{{ collection.new_element_indicator(value) }}
|
||||
</button>
|
||||
{{ form_errors(form) }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="p-0 d-none"></tr>
|
||||
<tr class="p-0">
|
||||
<td colspan="5" class="accordion-body collapse" id="{{ target_id }}">
|
||||
<div class="">
|
||||
{{ form_row(form.comment) }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endblock %}
|
||||
|
|
@ -76,6 +76,21 @@
|
|||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro assemblies_status_to_badge(status, class="badge") %}
|
||||
{% if status is not empty %}
|
||||
{% set color = " bg-secondary" %}
|
||||
|
||||
{% if status == "in_production" %}
|
||||
{% set color = " bg-success" %}
|
||||
{% endif %}
|
||||
|
||||
<span class="{{ class ~ color}}">
|
||||
<i class="fa-fw fas fa-info-circle"></i>
|
||||
{{ ("assembly.status." ~ status) | trans }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro structural_entity_link(entity, link_type = "list_parts") %}
|
||||
{# @var entity \App\Entity\Base\StructuralDBElement #}
|
||||
{% if entity %}
|
||||
|
|
@ -101,6 +116,7 @@
|
|||
"category": ["fa-solid fa-tags", "category.label"],
|
||||
"currency": ["fa-solid fa-coins", "currency.label"],
|
||||
"device": ["fa-solid fa-archive", "project.label"],
|
||||
"assembly": ["fa-solid fa-list", "assembly.label"],
|
||||
"footprint": ["fa-solid fa-microchip", "footprint.label"],
|
||||
"group": ["fa-solid fa-users", "group.label"],
|
||||
"label_profile": ["fa-solid fa-qrcode", "label_profile.label"],
|
||||
|
|
|
|||
31
templates/parts/info/_assemblies.html.twig
Normal file
31
templates/parts/info/_assemblies.html.twig
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{% import "components/attachments.macro.html.twig" as attachments %}
|
||||
{% import "helper.twig" as helper %}
|
||||
|
||||
<table class="table table-striped table-sm table-hover table-responsive-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{% trans %}entity.info.name{% endtrans %}</th>
|
||||
<th>{% trans %}description.label{% endtrans %}</th>
|
||||
<th>{% trans %}assembly.bom.quantity{% endtrans %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for bom_entry in part.assemblyBomEntries %}
|
||||
{# @var bom_entry App\Entity\Assembly\AssemblyBOMEntry #}
|
||||
<tr>
|
||||
<td>{% if bom_entry.assembly.masterPictureAttachment is not null %}{{ attachments.attachment_icon(bom_entry.assembly.masterPictureAttachment, attachment_manager) }}{% endif %}</td>
|
||||
<td><a href="{{ path('assembly_info', {'id': bom_entry.assembly.iD}) }}">{{ bom_entry.assembly.name }}</a></td> {# Name #}
|
||||
<td>{{ bom_entry.assembly.description|format_markdown }}</td> {# Description #}
|
||||
<td>{{ bom_entry.quantity | format_amount(part.partUnit) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a class="btn btn-success" {% if not is_granted('@assemblies.edit') %}disabled{% endif %}
|
||||
href="{{ path('assembly_add_parts_no_id', {"parts": part.id, "_redirect": uri_without_host(app.request)}) }}">
|
||||
<i class="fa-solid fa-magnifying-glass-plus fa-fw"></i>
|
||||
{% trans %}part.info.add_part_to_assembly{% endtrans %}
|
||||
</a>
|
||||
|
|
@ -109,15 +109,20 @@
|
|||
{% trans %}vendor.partinfo.history{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
{% if part.projectBomEntries is not empty %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="projects-tab" data-bs-toggle="tab" href="#projects" role="tab">
|
||||
<i class="fas fa-archive fa-fw"></i>
|
||||
{% trans %}project.labelp{% endtrans %}
|
||||
<span class="badge bg-secondary">{{ part.projectBomEntries | length }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="projects-tab" data-bs-toggle="tab" href="#projects" role="tab">
|
||||
<i class="fas fa-archive fa-fw"></i>
|
||||
{% trans %}project.labelp{% endtrans %}
|
||||
<span class="badge bg-secondary">{{ part.projectBomEntries | length }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="assemblies-tab" data-bs-toggle="tab" href="#assemblies" role="tab">
|
||||
<i class="fas fa-archive fa-fw"></i>
|
||||
{% trans %}assembly.labelp{% endtrans %}
|
||||
<span class="badge bg-secondary">{{ part.assemblyBomEntries | length }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="tools-tab" data-bs-toggle="tab" href="#tools" role="tab">
|
||||
<i class="fas fa-tools"></i>
|
||||
|
|
@ -167,6 +172,10 @@
|
|||
{% include "parts/info/_projects.html.twig" %}
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="assemblies" role="tabpanel" aria-labelledby="assemblies-tab">
|
||||
{% include "parts/info/_assemblies.html.twig" %}
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="history" role="tabpanel" aria-labelledby="history-tab">
|
||||
{% include "parts/info/_history.html.twig" %}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@
|
|||
<button class="nav-link" id="filter-projects-tab" data-bs-toggle="tab" data-bs-target="#filter-projects"><i class="fas fa-archive fa-fw"></i> {% trans %}project.labelp{% endtrans %}</button>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if filterForm.assembly is defined %}
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="filter-assemblies-tab" data-bs-toggle="tab" data-bs-target="#filter-assemblies"><i class="fas fa-archive fa-fw"></i> {% trans %}assembly.labelp{% endtrans %}</button>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if filterForm.inBulkImportJob is defined %}
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="filter-bulk-import-tab" data-bs-toggle="tab" data-bs-target="#filter-bulk-import"><i class="fas fa-download fa-fw"></i> {% trans %}part.edit.tab.bulk_import{% endtrans %}</button>
|
||||
|
|
@ -132,6 +137,13 @@
|
|||
{{ form_row(filterForm.bomComment) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if filterForm.assembly is defined %}
|
||||
<div class="tab-pane pt-3" id="filter-assemblies" role="tabpanel" aria-labelledby="filter-assemblies-tab" tabindex="0">
|
||||
{{ form_row(filterForm.assembly) }}
|
||||
{{ form_row(filterForm.assemblyBomQuantity) }}
|
||||
{{ form_row(filterForm.assemblyBomName) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if filterForm.inBulkImportJob is defined %}
|
||||
<div class="tab-pane pt-3" id="filter-bulk-import" role="tabpanel" aria-labelledby="filter-bulk-import-tab" tabindex="0">
|
||||
{{ form_row(filterForm.inBulkImportJob) }}
|
||||
|
|
@ -163,4 +175,4 @@
|
|||
{{ form_end(filterForm) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,29 +3,107 @@
|
|||
{% block title %}{% trans %}project.import_bom{% endtrans %}{% endblock %}
|
||||
|
||||
{% block before_card %}
|
||||
{% if errors %}
|
||||
{% if validationErrors or importerErrors %}
|
||||
<div class="alert alert-danger">
|
||||
<h4><i class="fa-solid fa-exclamation-triangle fa-fw"></i> {% trans %}parts.import.errors.title{% endtrans %}</h4>
|
||||
<ul>
|
||||
{% for violation in errors %}
|
||||
<li>
|
||||
<b>{{ violation.propertyPath }}: </b>
|
||||
{{ violation.message|trans(violation.parameters, 'validators') }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if validationErrors %}
|
||||
{% for violation in validationErrors %}
|
||||
<li>
|
||||
<b>{{ violation.propertyPath }}: </b>
|
||||
{{ violation.message|trans(violation.parameters, 'validators') }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if importerErrors %}
|
||||
{% for violation in importerErrors %}
|
||||
<li>
|
||||
<b>{{ violation.propertyPath }}: </b>
|
||||
{{ violation.message|trans(violation.parameters, 'validators')|raw }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fa-solid fa-file-import fa-fw"></i>
|
||||
{% trans %}project.import_bom{% endtrans %}{% if project %}: <i>{{ project.name }}</i>{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block card_content %}
|
||||
|
||||
{{ form(form) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_content %}
|
||||
<div class="container-fluid row d-flex align-items-stretch pe-0 me-0">
|
||||
<div class="col-md-12 col-lg-6 ps-0 mt-3 d-flex">
|
||||
<div class="card border-secondary flex-grow-1 overflow-auto">
|
||||
<div class="card-header bg-secondary text-white">
|
||||
{% trans %}project.import_bom.template.header.json{% endtrans %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<pre>{{ jsonTemplate|json_encode(constant('JSON_PRETTY_PRINT') b-or constant('JSON_UNESCAPED_UNICODE')) }}</pre>
|
||||
|
||||
{{ 'project.bom_import.template.json.table'|trans|raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 col-lg-6 ps-0 mt-3 d-flex">
|
||||
<div class="card border-secondary flex-grow-1 overflow-auto">
|
||||
<div class="card-header bg-secondary text-white">
|
||||
{% trans %}project.import_bom.template.header.csv{% endtrans %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ 'project.bom_import.template.csv.exptected_columns'|trans }}
|
||||
|
||||
<pre>quantity;name;part_id;part_mpnr;part_ipn;part_name;part_manufacturer_id;part_manufacturer_name</pre>
|
||||
|
||||
<ul>
|
||||
<li>quantity</li>
|
||||
<li>name</li>
|
||||
<li>part_id</li>
|
||||
<li>part_mpnr</li>
|
||||
<li>part_ipn</li>
|
||||
<li>part_name</li>
|
||||
<li>part_manufacturer_id</li>
|
||||
<li>part_manufacturer_name</li>
|
||||
</ul>
|
||||
|
||||
{{ 'project.bom_import.template.csv.table'|trans|raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 col-lg-6 ps-0 mt-3 d-flex overflow-auto">
|
||||
<div class="card border-secondary flex-grow-1 overflow-auto">
|
||||
<div class="card-header bg-secondary text-white">
|
||||
{% trans %}project.import_bom.template.header.kicad_pcbnew{% endtrans %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ 'project.bom_import.template.kicad_pcbnew.exptected_columns'|trans }}
|
||||
<pre>Id;Designator;Package;Quantity;Designation;Supplier and ref</pre>
|
||||
|
||||
<ul>
|
||||
<li>Id</li>
|
||||
<li>Designator</li>
|
||||
<li>Package</li>
|
||||
<li>Quantity</li>
|
||||
<li>Designation</li>
|
||||
<li>Supplier and ref</li>
|
||||
<li>Note</li>
|
||||
<li>Footprint</li>
|
||||
<li>Value</li>
|
||||
<li>Footprint</li>
|
||||
</ul>
|
||||
|
||||
{{ 'project.bom_import.template.kicad_pcbnew.exptected_columns.note'|trans|raw }}
|
||||
|
||||
{{ 'project.bom_import.template.kicad_pcbnew.table'|trans|raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Loading…
Add table
Add a link
Reference in a new issue