Renamed parts/ templates folder to recommended snake_case style

This commit is contained in:
Jan Böhmer 2023-02-04 23:05:39 +01:00
parent e8efe81f79
commit 9097220026
41 changed files with 63 additions and 63 deletions

View file

@ -0,0 +1,85 @@
<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 part.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.external %}
<a href="{{ attachment.uRL }}" rel="noopener" target="_blank" class="link-external">{{ attachment.host }}</a>
{% else %}
{{ attachment.filename }}
{% endif %}
</td>
<td class="align-middle h6">
{% if attachment.external %}
<span class="badge bg-primary">
<i class="fas fa-fw fa-globe"></i> {% trans %}attachment.external{% endtrans %}
</span>
{% elseif attachment_manager.fileExisting(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 == part.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_manager.fileExisting(attachment) %}href="{{ entity_url(attachment, 'file_view') }}"{% endif %} target="_blank"
class="btn btn-secondary {% if not attachment_manager.fileExisting(attachment) or (attachment.secure and not is_granted("show_secure", attachment)) %}disabled{% endif %}"
data-turbo="false" title="{% trans %}attachment.view{% endtrans %}" rel="noopener">
<i class="fas fa-eye fa-fw"></i>
</a>
<a {% if attachment_manager.fileExisting(attachment) %}href="{{ entity_url(attachment, 'file_download') }}"{% endif %} data-turbo="false"
class="btn btn-secondary {% if not attachment_manager.fileExisting(attachment) or (attachment.secure and not is_granted("show_secure", attachment)) %}disabled{% endif %}"
title="{% trans %}attachment.download{% 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-calendar fa-fw"></i> <b>{% trans %}createdAt{% endtrans %}:</b> {{ attachment.addedDate | format_datetime("short")}}</span>
<span class="text-muted dropdown-item-text" ><i class="fas fa-history fa-fw"></i> <b>{% trans %}createdAt{% endtrans %}:</b> {{ attachment.addedDate | format_datetime("short")}}</span>
</div>
</div>
</div></td>
</tr>
{% endfor %}
</tbody>
</table>

View file

@ -0,0 +1,66 @@
{% import "helper.twig" as helper %}
<table class="table table-striped table-hover table-sm w-100 table-responsive-sm">
<tbody>
<tr> {# Creation date #}
<td>{% trans %}createdAt{% endtrans %}</td>
<td>{{ part.addedDate | format_datetime("long")}}</td>
</tr>
<tr>
<td>{% trans %}user.creating_user{% endtrans %}</td>
<td>{% if is_granted('show_history', part) %}
{{ creating_user(part).fullName(true) ?? 'Unknown'|trans }}
{% else %}
{% trans %}accessDenied{% endtrans %}
{% endif %}
</td>
</tr>
<tr> {# Last modified date #}
<td>{% trans %}lastModified{% endtrans %}</td>
<td>{{ part.lastModified | format_datetime("long")}}</td>
</tr>
<tr>
<td>{% trans %}user.last_editing_user{% endtrans %}</td>
<td>{% if is_granted('show_history', part) %}
{{ last_editing_user(part).fullName(true) ?? 'Unknown'|trans }}
{% else %}
{% trans %}accessDenied{% endtrans %}
{% endif %}
</td>
</tr>
<tr> {# ID #}
<td>{% trans %}id.label{% endtrans %}</td>
<td>{{ part.iD }}</td>
</tr>
<tr> {# IPN #}
<td>{% trans %}part.edit.ipn{% endtrans %}</td>
<td>{{ part.ipn ?? 'part.ipn.not_defined'|trans }}</td>
</tr>
<tr> {# Favorite status #}
<td>{% trans %}part.isFavorite{% endtrans %}</td>
<td>{{ helper.boolean_badge(part.favorite) }}</td>
</tr>
<tr> {# Build status #}
<td>{% trans %}part.is_build_part{% endtrans %}</td>
<td>{{ helper.boolean_badge(part.projectBuildPart) }}
{% if part.projectBuildPart %}(<a href="{{ entity_url(part.builtProject, "edit") }}">{{ part.builtProject.name }}</a>){% endif %}</td>
</tr>
<tr>
<td>{% trans %}part.minOrderAmount{% endtrans %}</td>
<td>{% if pricedetail_helper.minOrderAmount(part) %}
{{ pricedetail_helper.minOrderAmount(part) | format_amount(part.partUnit) }}
{% else %}
{% trans %}Unknown{% endtrans %}
{% endif %}
</td>
</tr>
</tbody>
</table>

View file

@ -0,0 +1,6 @@
<div class="mt-2">
{% if datatable is not null %}
{% import "components/history_log_macros.html.twig" as log %}
{{ log.element_history_component(datatable) }}
{% endif %}
</div>

View file

@ -0,0 +1,74 @@
{% import "helper.twig" as helper %}
<div class="row">
<div class="col-md-3 col-lg-4 col-3 mt-auto mb-auto">
{% include "parts/info/_picture.html.twig" %}
</div>
<div class="col-md-9 col-lg-8 col-7">
<h5 class="text-muted pt-2" title="{% trans %}manufacturer.label{% endtrans %}">
{% if part.manufacturer %}
{% if part.manufacturer.id is not null %}
<a href="{{ entity_url(part.manufacturer, 'list_parts') }}">{{ part.manufacturer.name}}</a>
{% else %}
{{ part.manufacturer.name }}
{% endif %}
{% endif %}
{% if part.manufacturerProductUrl %}
<small>
<a class="link-external" href="{{ part.manufacturerProductUrl }}" rel="noopener" target="_blank">{{ part.manufacturerProductNumber }}</a>
</small>
{% else %}
<small>{{ part.manufacturerProductNumber }}</small>
{% endif %}
</h5>
<h3 class="w-fit" title="{% trans %}name.label{% endtrans %}">{{ part.name }}
{# You need edit permission to use the edit button #}
{% if timeTravel is not null %}
<a href="{{ entity_url(part, 'info') }}"><i title="{% trans %}part.back_to_info{% endtrans %}" class="fas fa-fw fa-arrow-circle-left"></i></a>
{% elseif is_granted('edit', part) %}
<a href="{{ entity_url(part, '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>{{ part.description|format_markdown(true) }}</span></h6>
<h6 class="">
<i class="fas fa-tag fa-fw" title="{% trans %}category.label{% endtrans %}"></i>
<span class="text-muted">{{ helper.structural_entity_link(part.category) }}</span>
</h6>
<h6><i class="fas fa-shapes fa-fw"></i>
<span class="text-muted">
<span title="{% trans %}instock.label{% endtrans %}">{{ part.amountSum | format_amount(part.partUnit) }}</span>
/
<span title="{% trans %}mininstock.label{% endtrans %}">{{ part.minAmount | format_amount(part.partUnit) }}</span>
</span>
</h6>
<h6 class="">
<i class="fas fa-microchip fa-fw" title="{% trans %}footprint.label{% endtrans %}"></i>
<span class="text-muted">{{ helper.structural_entity_link(part.footprint) }}</span>
</h6>
{% set min_order_amount = pricedetail_helper.minOrderAmount(part) %}
{% set max_order_amount = pricedetail_helper.maxDiscountAmount(part) %}
{% set max_order_price = pricedetail_helper.calculateAvgPrice(part, max_order_amount, app.user.currency ?? null) %}
{% if max_order_price is not null %}
<h6>
<i class="fas fa-money-bill-alt fa-fw"></i>
<span class="text-muted">
<span title="{% trans %}part.avg_price.label{% endtrans %} {{ max_order_amount | format_amount(part.partUnit) }}">{{ max_order_price | format_money(app.user.currency ?? null) }}</span>
{% if min_order_amount < max_order_amount %}
<span> - </span>
<span title="{% trans %}part.avg_price.label{% endtrans %} {{ min_order_amount | format_amount(part.partUnit) }}">{{pricedetail_helper.calculateAvgPrice(part, min_order_amount, app.user.currency ?? null ) | format_money(app.user.currency ?? null) }}</span>
{% endif %}
</span>
</h6>
{% endif %}
{#
{% if part.comment != "" %}
<h6 title="{% trans %}comment.label{% endtrans %}">
<i class="fas fa-comment-alt fa-fw"></i>
<div class="d-inline-flex">
<span class="text-muted">{{ part.comment|nl2br }}</span>
</div>
</h6>
{% endif %} #}
</div>
</div>

View file

@ -0,0 +1,83 @@
<div class="table-responsive">
<table class="table table-striped table-header table-hover">
<thead>
<tr>
<th>{% trans %}part.supplier.name{% endtrans %}</th>
<th>{% trans %}part.supplier.partnr{% endtrans %}</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{% for order in part.orderdetails %}
<tr class="{% if order.obsolete %}table-danger{% endif %}">
<td>
<a href="{{ entity_url(order.supplier, 'list_parts') }}">{{ order.supplier.name }}</a>
</td>
<td>{% if order.supplierProductUrl is not empty %}
<a href="{{ order.supplierProductUrl }}" rel="noopener" target="_blank" class="link-external">{{ order.supplierPartNr }}</a>
{% else %}
{{ order.supplierPartNr }}
{% endif %}
</td>
<td>
{% if order.pricedetails is not empty %}
<table class="table table-bordered table-sm table-striped table-hover">
<thead class="thead-dark">
<tr>
<th>{% trans %}part.order.minamount{% endtrans %}</th>
<th>{% trans %}part.order.price{% endtrans %}</th>
<th>
{% trans %}part.order.single_price{% endtrans %}
{% if part.partUnit %}
/ 1 {{ part.partUnit.unit }}
{% endif %}
</th>
</tr>
</thead>
<tbody>
{% for detail in order.pricedetails %}
<tr>
<td>
{{ detail.MinDiscountQuantity | format_amount(part.partUnit) }}
</td>
<td>
{{ detail.price | format_money(detail.currency) }} / {{ detail.PriceRelatedQuantity | format_amount(part.partUnit) }}
{% set tmp = pricedetail_helper.convertMoneyToCurrency(detail.price, detail.currency) %}
{% if detail.currency != (app.user.currency ?? null) and tmp is not null and tmp.GreaterThan(0) %}
<span class="text-muted">({{ pricedetail_helper.convertMoneyToCurrency(detail.price, detail.currency, app.user.currency ?? null) | format_money(app.user.currency ?? null) }})</span>
{% endif %}
</td>
<td>
{{ detail.PricePerUnit | format_money(detail.currency) }}
{% set tmp = pricedetail_helper.convertMoneyToCurrency(detail.PricePerUnit, detail.currency) %}
{% if detail.currency != (app.user.currency ?? null) and tmp is not null and tmp.GreaterThan(0) %}
<span class="text-muted">({{ pricedetail_helper.convertMoneyToCurrency(detail.PricePerUnit, detail.currency, app.user.currency ?? null) | format_money(app.user.currency ?? null) }})</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</td>
<td> {# Action for order information #}
<div class="btn-group">
<button type="button" class="btn btn-info btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Action
</button>
<div class="dropdown-menu">
<span class="text-muted dropdown-item-text" ><i class="fas fa-lightbulb fa-fw"></i> <b>ID:</b> {{ order.iD }}</span>
<span class="text-muted dropdown-item-text" ><i class="fas fa-history fa-fw"></i> <b>{% trans %}createdAt{% endtrans %}:</b> {{ order.addedDate | format_datetime("short")}}</span>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#"><i class="fas fa-edit fa-fw"></i> {% trans %}edit.caption_short{% endtrans %}</a>
<a class="dropdown-item" href="#"><i class="fas fa-trash fa-fw"></i> {% trans %}delete.caption{% endtrans %}</a>
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

View file

@ -0,0 +1,97 @@
{% import "helper.twig" as helper %}
{% import "LabelSystem/dropdown_macro.html.twig" as dropdown %}
{% include "parts/info/_withdraw_modal.html.twig" %}
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>{% trans %}part_lots.description{% endtrans %}</th>
<th>{% trans %}part_lots.storage_location{% endtrans %}</th>
<th>{% trans %}part_lots.amount{% endtrans %}</th>
<th></th> {# Tags row #}
<th></th>
<th></th> {# Button row #}
</tr>
</thead>
<tbody>
{% for lot in part.partLots %}
<tr>
<td>{{ lot.description }}</td>
<td>
{% if lot.storageLocation %}
{{ helper.structural_entity_link(lot.storageLocation) }}
{% else %}
<span class="badge rounded-pill bg-warning">
<i class="fas fa-question-circle fa-fw"></i> {% trans %}part_lots.location_unknown{% endtrans %}
</span>
{% endif %}
</td>
<td>
{% if lot.instockUnknown %}
<span class="badge rounded-pill bg-warning">
<i class="fas fa-question-circle fa-fw"></i> {% trans %}part_lots.instock_unknown{% endtrans %}
</span>
{% else %}
{{ lot.amount | format_amount(part.partUnit, {'decimals': 5}) }}
{% endif %}
</td>
<td>
<h6>
{% if lot.expirationDate %}
<span class="badge bg-info" title="{% trans %}part_lots.expiration_date{% endtrans %}">
<i class="fas fa-calendar-alt fa-fw"></i> {{ lot.expirationDate | format_date() }}
</span>
{% endif %}
{% if lot.expired %}
<br>
<span class="badge bg-warning">
<i class="fas fa-exclamation-circle fa-fw"></i>
{% trans %}part_lots.is_expired{% endtrans %}
</span>
{% endif %}
{% if lot.needsRefill %}
<br>
<span class="badge bg-warning">
<i class="fas fa-dolly fa-fw"></i>
{% trans %}part_lots.need_refill{% endtrans %}
</span>
{% endif %}
</h6>
</td>
<td>
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#withdraw-modal"
data-action="withdraw" data-lot-id="{{ lot.id }}" data-lot-amount="{{ lot.amount }}"
title="{% trans %}part.info.withdraw_modal.title.withdraw{% endtrans %}"
{% if not is_granted('withdraw', lot) or not withdraw_add_helper.canWithdraw(lot) %}disabled{% endif %}
>
<i class="fa-solid fa-minus fa-fw"></i>
</button>
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#withdraw-modal"
data-action="add" data-lot-id="{{ lot.id }}" data-lot-amount="{{ lot.amount }}"
title="{% trans %}part.info.withdraw_modal.title.add{% endtrans %}"
{% if not is_granted('add', lot) or not withdraw_add_helper.canAdd(lot) %}disabled{% endif %}
>
<i class="fa-solid fa-plus fa-fw"></i>
</button>
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#withdraw-modal"
data-action="move" data-lot-id="{{ lot.id }}" data-lot-amount="{{ lot.amount }}"
title="{% trans %}part.info.withdraw_modal.title.move{% endtrans %}"
{% if not is_granted('move', lot) or not withdraw_add_helper.canWithdraw(lot) or part.partLots.count == 1 %}disabled{% endif %}
>
<i class="fa-solid fa-right-left fa-fw"></i>
</button>
</div>
</td>
<td>
{{ dropdown.profile_dropdown('part_lot', lot.id, false) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

View file

@ -0,0 +1,42 @@
{% if not pictures is empty %}
{# <img src="{{ part.masterPictureAttachment | entityURL('file_view') }}" class="img-fluid img-thumbnail bg-light" alt="Part main image" height="300" width="300"> #}
<div id="pictureCarousel" class="carousel slide mb-2" data-bs-interval="false" data-bs-ride="false">
<div class="carousel-indicators">
{% for pic in pictures %}
<button type="button" data-bs-target="#pictureCarousel" data-bs-slide-to="{{ loop.index0 }}" {% if loop.first %}class="active" aria-current="true"{% endif %} aria-label="{{ pic.name }}"></button>
{% endfor %}
</div>
<div class="carousel-inner">
{% for pic in pictures %}
{# @var pic App\Entity\Attachments\Attachment #}
<div class="carousel-item {% if loop.first %}active{% endif %}">
<a href="{{ entity_url(pic, 'file_view') }}" data-turbo="false" target="_blank" rel="noopener">
<img class="d-block w-100 img-fluid img-thumbnail bg-light" src="{{ entity_url(pic, 'file_view') }}" alt="">
<div class="mask"></div>
<div class="carousel-caption-hover">
<div class="carousel-caption">
<div><b>{{ pic.name }}</b></div>
<div>{% if pic.filename %}({{ pic.filename }}) {% endif %}</div>
<div>{{ entity_type_label(pic.element) }}</div>
</div>
</div>
</a>
</div>
{% endfor %}
</div>
{% if pictures | length > 1 %}
<button type="button" class="carousel-control-prev" data-bs-target="#pictureCarousel" role="button" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">{% trans %}part.info.prev_picture{% endtrans %}</span>
</button>
<button type="button" class="carousel-control-next" data-bs-target="#pictureCarousel" role="button" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">{% trans %}part.info.next_picture{% endtrans %}</span>
</button>
{% endif %}
</div>
{% else %}
<img src="{{ asset('img/part_placeholder.svg') }}" class="img-fluid img-thumbnail bg-light mb-2" alt="Part main image" height="300" width="300">
{% endif %}

View file

@ -0,0 +1,35 @@
{% 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 %}project.bom.quantity{% endtrans %}</th>
<th>{% trans %}project.bom.mountnames{% endtrans %}</th>
</tr>
</thead>
<tbody>
{% for bom_entry in part.projectBomEntries %}
{# @var bom_entry App\Entity\Project\ProjectBOMEntry #}
<tr>
<td>{% if bom_entry.project.masterPictureAttachment is not null %}{{ attachments.attachment_icon(bom_entry.project.masterPictureAttachment, attachment_manager) }}{% endif %}</td>
<td><a href="{{ path('project_info', {'id': bom_entry.project.iD}) }}">{{ bom_entry.project.name }}</a></td> {# Name #}
<td>{{ bom_entry.project.description|format_markdown }}</td> {# Description #}
<td>{{ bom_entry.quantity | format_amount(part.partUnit) }}</td>
<td>{% for tag in bom_entry.mountnames|split(',') %}
<span class="badge bg-secondary badge-secondary" >{{ tag | trim }}</span>
{% endfor %}</td>
</tr>
{% endfor %}
</tbody>
</table>
<a class="btn btn-success" {% if not is_granted('@projects.edit') %}disabled{% endif %}
href="{{ path('project_add_parts_no_id', {"parts": part.id, "_redirect": app.request.requestUri}) }}">
<i class="fa-solid fa-magnifying-glass-plus fa-fw"></i>
{% trans %}part.info.add_part_to_project{% endtrans %}
</a>

View file

@ -0,0 +1,70 @@
{% import "helper.twig" as helper %}
{% if timeTravel is not null %}
<b class="mb-2">{% trans with {'%timestamp%': timeTravel|format_datetime('short')} %}part.info.timetravel_hint{% endtrans %}</b>
{% endif %}
{% if part.projectBuildPart %}
<b class="mb-2">{% trans %}part.info.projectBuildPart.hint{% endtrans %}: <a href="{{ entity_url(part.builtProject) }}">{{ part.builtProject.name }}</a></b>
{% endif %}
<div class="mb-3">
<span class="text-muted" title="{% trans %}lastModified{% endtrans %}">
<i class="fas fa-history fa-fw"></i> {{ helper.date_user_combination(part, 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(part, false) }}
</span>
</div>
{# Part mass #}
{% if part.mass %}
<div>
<h6>
<span class="badge bg-secondary" title="{% trans %}part.mass.tooltip{% endtrans %}"><i class="fas fa-weight-hanging fa-fw"></i> {{ part.mass | format_si("g") }}</span>
</h6>
</div>
{% endif %}
{# Needs Review tag #}
{% if part.needsReview %}
<div class="mt-1">
<h6>
<span class="badge bg-warning"><i class="fas fa-ambulance fa-fw"></i> {% trans %}part.needs_review.badge{% endtrans %}</span>
</h6>
</div>
{% endif %}
{# Favorite Status tag #}
{% if part.favorite %}
<div class="mt-1">
<h6>
<span class="badge bg-success"><i class="fas fa-award fa-fw"></i> {% trans %}part.favorite.badge{% endtrans %}</span>
</h6>
</div>
{% endif %}
{% if part.obsolete %}
<div class="mt-1">
<h6>
<span class="badge bg-danger"><i class="fas fa-ghost fa-fw"></i> {% trans %}part.obsolete.badge{% endtrans %}</span>
</h6>
</div>
{% endif %}
{# Manufacturing status tag #}
<div class="mt-1">
<h6>
{{ helper.m_status_to_badge(part.manufacturingStatus) }}
</h6>
</div>
{# Show tags #}
{% if part.tags is not empty %}
<div class="mt-1">
<h6 style="line-height: 1.5;">
{{ helper.string_to_tags(part.tags) }}
</h6>
</div>
{% endif %}

View file

@ -0,0 +1,17 @@
{# var \App\Entity\Parts\Part part #}
{% import "helper.twig" as helper %}
{% for name, parameters in part.groupedParameters %}
{% if name is not empty %}<h5 class="mt-1">{{ name }}</h5>{% endif %}
{{ helper.parameters_table(parameters) }}
{% endfor %}
{% if description_params is not empty %}
<h5 class="mt-1">{% trans %}parameters.extracted_from_description{% endtrans %}</h5>
{{ helper.parameters_table(description_params) }}
{% endif %}
{% if comment_params is not empty %}
<h5 class="mt-1">{% trans %}parameters.auto_extracted_from_comment{% endtrans %}</h5>
{{ helper.parameters_table(comment_params) }}
{% endif %}

View file

@ -0,0 +1,60 @@
{% import "LabelSystem/dropdown_macro.html.twig" as dropdown %}
{% if is_granted('edit', part) %}
<a href="{{ entity_url(part, 'edit') }}" class="btn btn-primary mt-3">
<i class="fas fa-fw fa-edit"></i>
{% trans %}part.edit.btn{% endtrans %}
</a>
{% endif %}
{% if is_granted('create', part) %}
<br>
<div class="btn-group mt-2">
<a class="btn btn-primary" href="{{ entity_url(part, 'clone') }}">
<i class="fas fa-clone"></i>
{% trans %}part.clone.btn{% endtrans %}
</a>
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown">
<span class="caret"></span>
</button>
<div class="dropdown-menu" role="menu">
<a class="dropdown-item" href="{{ entity_url(part, 'create') }}">
<i class="fas fa-plus-square"></i>
{% trans %}part.create.btn{% endtrans %}
</a>
</div>
</div>
{% endif %}
<form method="post" class="mt-2" action="{{ entity_url(part, 'delete') }}"
{{ stimulus_controller('elements/delete_btn') }} {{ stimulus_action('elements/delete_btn', "submit", "submit") }}
data-delete-title="{% trans with {'%name%': part.name }%}part.delete.confirm_title{% endtrans %}"
data-delete-message="{% trans %}part.delete.message{% endtrans %}">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ part.id) }}">
<div class="form-group">
<div class="btn-group">
<button class="btn btn-danger" {% if not is_granted("delete", part) %}disabled{% endif %}>
<i class="fa fa-trash fa-fw"></i>
{% trans %}part.delete{% endtrans %}
</button>
<button type="button" class="btn btn-danger dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<div class="dropdown-menu p-2">
<div class="form-group"><label for="delete_log_comment">{% trans %}edit.log_comment{% endtrans %}</label>
<input type="text" id="delete_log_comment" name="log_comment" class="form-control">
</div>
</div>
</div>
</div>
</form>
{{ dropdown.profile_dropdown('part', part.id) }}
<a class="btn btn-success mt-2" {% if not is_granted('@projects.edit') %}disabled{% endif %}
href="{{ path('project_add_parts_no_id', {"parts": part.id, "_redirect": app.request.requestUri}) }}">
<i class="fa-solid fa-magnifying-glass-plus fa-fw"></i>
{% trans %}part.info.add_part_to_project{% endtrans %}
</a>

View file

@ -0,0 +1,61 @@
<div class="modal fade" id="withdraw-modal" tabindex="-1" aria-labelledby="withdraw-modal-title" aria-hidden="true" {{ stimulus_controller('pages/part_withdraw_modal') }}>
<form method="post" action="{{ path('part_add_withdraw', {"id": part.id}) }}">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="withdraw-modal-title"
data-withdraw="{% trans %}part.info.withdraw_modal.title.withdraw{% endtrans %}"
data-add="{% trans %}part.info.withdraw_modal.title.add{% endtrans %}"
data-move="{% trans %}part.info.withdraw_modal.title.move{% endtrans %}"
>Filled by JS Controller</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
{# non visible form elements #}
<input type="hidden" name="lot_id" value="">
<input type="hidden" name="action" value="">
<input type="hidden" name="_csfr" value="{{ csrf_token('part_withraw' ~ part.iD) }}">
<input type="hidden" name="_redirect" value="{{ app.request.requestUri }}">
<div class="row mb-2">
<label class="col-form-label col-sm-3">
{% trans %}part.info.withdraw_modal.amount{% endtrans %}
</label>
<div class="col-sm-9">
<input type="number" required class="form-control" min="0" step="{{ (part.partUnit and not part.partUnit.integer) ? 'any' : '1' }}" name="amount" value="">
</div>
</div>
<div class="row mb-2 d-none" id="withdraw-modal-move-to">
<label class="col-form-label col-sm-3">{% trans %}part.info.withdraw_modal.move_to{% endtrans %}</label>
<div class="col-sm-9">
{% for lots in part.partLots|filter(l => l.instockUnknown == false) %}
<div class="form-check">
<input class="form-check-input" type="radio" name="target_id" value="{{ lots.iD }}" id="modal_target_radio_{{ lots.iD }}" {% if not withdraw_add_helper.canAdd(lots) %}disabled{% endif %} required {% if loop.first %}checked{% endif %}>
<label class="form-check-label" for="modal_target_radio_{{ lots.iD }}">
{{ (lots.storageLocation) ? lots.storageLocation.fullPath : ("Lot " ~ loop.index) }}{% if lots.name is not empty %} ({{ lots.name }}){% endif %}: <b>{{ lots.amount | format_amount(part.partUnit) }}</b>
</label>
</div>
{% endfor %}
</div>
</div>
<div class="row mb-2">
<label class="col-form-label col-sm-3">
{% trans %}part.info.withdraw_modal.comment{% endtrans %}
</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="comment" value="">
<div id="emailHelp" class="form-text">{% trans %}part.info.withdraw_modal.comment.hint{% endtrans %}</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans %}modal.close{% endtrans %}</button>
<button type="submit" class="btn btn-primary">{% trans %}modal.submit{% endtrans %}</button>
</div>
</div>
</div>
</form>
</div>

View file

@ -0,0 +1,171 @@
{% extends "main_card.html.twig" %}
{% block title %}
{% trans %}part.info.title{% endtrans %} {{ part.name }}
{% endblock %}
{% block card_type %}
{% if timeTravel == null %}
bg-primary text-white
{% else %}
bg-primary-striped text-white
{% endif %}
{% endblock %}
{% block card_title %}
<i class="fa {{ part.favorite ? 'fa-star' : 'fa-info-circle'}} fa-fw" aria-hidden="true"></i>
{% trans %}part.info.title{% endtrans %} <b>"{{ part.name }}"</b>
{% if timeTravel != null %}
<i>({{ timeTravel | format_datetime('short') }})</i>
{% endif %}
{% if part.projectBuildPart %}
(<i>{{ entity_type_label(part.builtProject) }}</i>: <a class="text-white" href="{{ entity_url(part.builtProject) }}">{{ part.builtProject.name }}</a>)
{% endif %}
<div class="float-end">
{% trans %}id.label{% endtrans %}: {{ part.id }} {% if part.ipn is not empty %}(<i>{{ part.ipn }}</i>){% endif %}
</div>
{% endblock %}
{% block card_content %}
<div class="row">
<div class="col-md-9">
{% include "parts/info/_main_infos.html.twig" %}
</div>
<div class="col-md-3 offset-md-0 col-9 offset-3">
{% include "parts/info/_sidebar.html.twig" %}
</div>
</div>
<div class="">
<div class="">
<ul class="nav nav-tabs" id="partTab" role="tablist">
<li class="nav-item">
<a class="nav-link {% if part.partLots %}active{% endif %}" id="part_lots-tab" data-bs-toggle="tab"
href="#part_lots" role="tab">
<i class="fas fa-box fa-fw"></i>
{% trans %}part.part_lots.label{% endtrans %}
<span class="badge bg-secondary">{{ part.partLots | length }}</span>
</a>
</li>
{% if part.comment is not empty %}
<li class="nav-item">
<a class="nav-link" id="comment-tab" data-bs-toggle="tab"
href="#comment" role="tab">
<i class="fas fa-comment-alt fa-fw"></i>
{% trans %}comment.label{% endtrans %}
</a>
</li>
{% endif %}
{% if part.parameters is not empty or description_params is not empty or comment_params is not empty %}
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" role="tab" href="#specifications">
<i class="fas fa-atlas fa-fw"></i>
{% trans %}part.info.specifications{% endtrans %}
<span class="badge bg-secondary">{{ part.parameters | length }}</span>
</a>
</li>
{% endif %}
{% if part.attachments is not empty %}
<li class="nav-item">
<a class="nav-link" id="attachment-tab" data-bs-toggle="tab"
href="#attachments" role="tab">
<i class="fas fa-paperclip fa-fw"></i>
{% trans %}attachment.labelp{% endtrans %}
<span class="badge bg-secondary">{{ part.attachments | length }}</span>
</a>
</li>
{% endif %}
{% if part.orderdetails is not empty %}
<li class="nav-item">
<a class="nav-link" id="supplier-tab" data-bs-toggle="tab" href="#suppliers" role="tab">
<i class="fas fa-shopping-cart fa-fw"></i>
{% trans %}vendor.partinfo.shopping_infos{% endtrans %}
<span class="badge bg-secondary">{{ part.orderdetails | length }}</span>
</a>
</li>
{% endif %}
<li class="nav-item {% if datatable is null %}not-allowed{% endif %}">
<a class="nav-link {% if datatable is null %}disabled{% endif %}" id="history-tab" data-bs-toggle="tab" href="#history" role="tab">
<i class="fas fa-history"></i>
{% 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="tools-tab" data-bs-toggle="tab" href="#tools" role="tab">
<i class="fas fa-tools"></i>
{% trans %}tools.label{% endtrans %}
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="extended_info-tab" data-bs-toggle="tab" href="#extended_info" role="tab">
<i class="fas fa-clipboard-list"></i>
{% trans %}extended_info.label{% endtrans %}
</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
{% if part.comment is not empty %}
<div class="tab-pane fade show" id="comment" role="tabpanel" aria-labelledby="home-tab">
<div class="container-fluid mt-2 latex" data-controller="common--latex">
{{ part.comment|format_markdown }}
</div>
</div>
{% endif %}
<div class="tab-pane fade show active" id="part_lots" role="tabpanel" aria-labelledby="part_lots-tab">
{% include "parts/info/_part_lots.html.twig" %}
</div>
{% if part.attachments is not empty %}
<div class="tab-pane fade" id="attachments" role="tabpanel" aria-labelledby="attachment-tab">
{% include "parts/info/_attachments_info.html.twig" %}
</div>
{% endif %}
{% if part.orderdetails is not empty %}
<div class="tab-pane fade" id="suppliers" role="tabpanel" aria-labelledby="supplier-tab">
{% include "parts/info/_order_infos.html.twig" %}
</div>
{% endif %}
<div class="tab-pane fade" id="projects" role="tabpanel" aria-labelledby="projects-tab">
{% include "parts/info/_projects.html.twig" %}
</div>
<div class="tab-pane fade" id="history" role="tabpanel" aria-labelledby="history-tab">
{% include "parts/info/_history.html.twig" %}
</div>
<div class="tab-pane fade" id="tools" role="tabpanel" aria-labelledby="tools-tab">
{% include "parts/info/_tools.html.twig" %}
</div>
{% if part.parameters is not empty or description_params is not empty or comment_params is not empty %}
<div class="tab-pane fade" id="specifications" role="tabpanel" aria-labelledby="tools-tab">
{% include "parts/info/_specifications.html.twig" %}
</div>
{% endif %}
<div class="tab-pane fade" id="extended_info" role="tabpanel" aria-labelledby="extended_info-tab">
{% include "parts/info/_extended_infos.html.twig" %}
</div>
</div>
</div>
</div>
{% endblock %}