Display prints based on a part

This commit is contained in:
Gregoo 2025-01-29 14:03:48 +01:00
parent bb096f76d6
commit f32ea0b1b3
5 changed files with 84 additions and 22 deletions

View File

@ -26,6 +26,7 @@ class BrickPartList(BrickRecordList[BrickPart]):
last_query: str = 'part/list/last' last_query: str = 'part/list/last'
minifigure_query: str = 'part/list/from_minifigure' minifigure_query: str = 'part/list/from_minifigure'
missing_query: str = 'part/list/missing' missing_query: str = 'part/list/missing'
print_query: str = 'part/list/from_print'
select_query: str = 'part/list/specific' select_query: str = 'part/list/specific'
def __init__(self, /): def __init__(self, /):
@ -103,6 +104,40 @@ class BrickPartList(BrickRecordList[BrickPart]):
return self return self
# Load generic parts from a print
def from_print(
self,
brickpart: BrickPart,
/,
) -> Self:
# Save the part and print
if brickpart.fields.print is not None:
self.fields.print = brickpart.fields.print
else:
self.fields.print = brickpart.fields.part
self.fields.part = brickpart.fields.part
self.fields.color = brickpart.fields.color
# Load the parts from the database
for record in self.select(
override_query=self.print_query,
order=self.order
):
part = BrickPart(
record=record,
)
if (
current_app.config['SKIP_SPARE_PARTS'] and
part.fields.spare
):
continue
self.records.append(part)
return self
# Load missing parts # Load missing parts
def missing(self, /) -> Self: def missing(self, /) -> Self:
for record in self.select( for record in self.select(
@ -117,7 +152,7 @@ class BrickPartList(BrickRecordList[BrickPart]):
# Return a dict with common SQL parameters for a parts list # Return a dict with common SQL parameters for a parts list
def sql_parameters(self, /) -> dict[str, Any]: def sql_parameters(self, /) -> dict[str, Any]:
parameters: dict[str, Any] = {} parameters: dict[str, Any] = super().sql_parameters()
# Set id # Set id
if self.brickset is not None: if self.brickset is not None:

View File

@ -0,0 +1,17 @@
{% extends 'part/base/base.sql' %}
{% block total_missing %}
{% endblock %}
{% block where %}
WHERE "rebrickable_parts"."print" IS NOT DISTINCT FROM :print
AND "bricktracker_parts"."color" IS NOT DISTINCT FROM :color
AND "bricktracker_parts"."part" IS DISTINCT FROM :part
{% endblock %}
{% block group %}
GROUP BY
"bricktracker_parts"."part",
"bricktracker_parts"."color"
{% endblock %}

View File

@ -33,9 +33,11 @@ def missing() -> str:
@part_page.route('/<part>/<int:color>/details', methods=['GET']) # noqa: E501 @part_page.route('/<part>/<int:color>/details', methods=['GET']) # noqa: E501
@exception_handler(__file__) @exception_handler(__file__)
def details(*, part: str, color: int) -> str: def details(*, part: str, color: int) -> str:
brickpart = BrickPart().select_generic(part, color)
return render_template( return render_template(
'part.html', 'part.html',
item=BrickPart().select_generic(part, color), item=brickpart,
sets_using=BrickSetList().using_part( sets_using=BrickSetList().using_part(
part, part,
color color
@ -52,4 +54,5 @@ def details(*, part: str, color: int) -> str:
part, part,
color color
), ),
similar_prints=BrickPartList().from_print(brickpart)
) )

View File

@ -5,16 +5,18 @@
{% endif %} {% endif %}
<h5 class="mb-0 {% if not solo %}fs-6 text-nowrap overflow-x-hidden text-truncate{% endif %}"> <h5 class="mb-0 {% if not solo %}fs-6 text-nowrap overflow-x-hidden text-truncate{% endif %}">
{% if identifier %}<span class="badge text-bg-secondary fw-normal"><i class="ri-{{ icon }}"></i>{{ identifier }}</span>{% endif %} {% if identifier %}<span class="badge text-bg-secondary fw-normal"><i class="ri-{{ icon }}"></i>{{ identifier }}</span>{% endif %}
{% if item.fields.color_name %} {% if solo %}
<span class="badge bg-white text-black fw-normal border"><i class="ri-palette-line"></i> {% if item.fields.color_name %}
{% if item.fields.color_rgb %} <span class="badge bg-white text-black fw-normal border"><i class="ri-palette-line"></i>
<span class="color-rgb {% if item.fields.color == 9999 %}color-any{% endif %} align-bottom border border-black" {% if item.fields.color != 9999 %}style="background-color: #{{ item.fields.color_rgb }};"{% endif %}></span> {% if item.fields.color_rgb %}
{% endif %} <span class="color-rgb {% if item.fields.color == 9999 %}color-any{% endif %} align-bottom border border-black" {% if item.fields.color != 9999 %}style="background-color: #{{ item.fields.color_rgb }};"{% endif %}></span>
{{ item.fields.color_name }} {% endif %}
</span> {{ item.fields.color_name }}
</span>
{% endif %}
{% if item.fields.color_transparent %}<span class="badge text-bg-light fw-normal border"><i class="ri-blur-off-line"></i> Transparent</span>{% endif %}
{% if item.fields.print %}<span class="badge text-bg-light fw-normal border"><a class="text-reset" href="{{ item.url_for_print() }}"><i class="ri-paint-brush-line"></i> Print</a></span>{% endif %}
{% endif %} {% endif %}
{% if item.fields.color_transparent %}<span class="badge text-bg-light fw-normal border"><i class="ri-blur-off-line"></i> Transparent</span>{% endif %}
{% if item.fields.print %}<span class="badge text-bg-light fw-normal border"><a class="text-reset" href="{{ item.url_for_print() }}"><i class="ri-paint-brush-line"></i> Print</a></span>{% endif %}
{{ name }} {{ name }}
</h5> </h5>
{% if not solo %} {% if not solo %}

View File

@ -2,23 +2,28 @@
{% import 'macro/badge.html' as badge %} {% import 'macro/badge.html' as badge %}
{% import 'macro/card.html' as card %} {% import 'macro/card.html' as card %}
<div class="card mb-3 flex-fill card-solo"> <div class="card mb-3 flex-fill {% if solo %}card-solo{% endif %}">
{{ card.header(item, item.fields.name, solo=solo, identifier=item.fields.part, icon='shapes-line') }} {{ card.header(item, item.fields.name, solo=solo, identifier=item.fields.part, icon='shapes-line') }}
{{ card.image(item, solo=solo, last=last, caption=item.fields.name, alt=item.fields.image_id, medium=true) }} {{ card.image(item, solo=solo, last=last, caption=item.fields.name, alt=item.fields.image_id, medium=true) }}
<div class="card-body border-bottom {% if not solo %}p-1{% endif %}"> <div class="card-body border-bottom-0 {% if not solo %}p-1{% endif %}">
{{ badge.total_sets(sets_using | length, solo=solo, last=last) }} {{ badge.total_sets(sets_using | length, solo=solo, last=last) }}
{{ badge.total_minifigures(minifigures_using | length, solo=solo, last=last) }} {{ badge.total_minifigures(minifigures_using | length, solo=solo, last=last) }}
{{ badge.total_quantity(item.fields.total_quantity, solo=solo, last=last) }} {{ badge.total_quantity(item.fields.total_quantity, solo=solo, last=last) }}
{{ badge.total_spare(item.fields.total_spare, solo=solo, last=last) }} {{ badge.total_spare(item.fields.total_spare, solo=solo, last=last) }}
{{ badge.total_missing(item.fields.total_missing, solo=solo, last=last) }} {{ badge.total_missing(item.fields.total_missing, solo=solo, last=last) }}
{{ badge.rebrickable(item, solo=solo, last=last) }} {% if not last %}
{{ badge.bricklink(item, solo=solo, last=last) }} {{ badge.rebrickable(item, solo=solo, last=last) }}
{{ badge.bricklink(item, solo=solo, last=last) }}
{% endif %}
</div> </div>
<div class="accordion accordion-flush" id="part-details"> {% if solo %}
{{ accordion.cards(sets_using, 'Sets using this part', 'sets-using-inventory', 'part-details', 'set/card.html', icon='hashtag') }} <div class="accordion accordion-flush border-top" id="part-details">
{{ accordion.cards(sets_missing, 'Sets missing this part', 'sets-missing-inventory', 'part-details', 'set/card.html', icon='error-warning-line') }} {{ accordion.cards(sets_using, 'Sets using this part', 'sets-using-inventory', 'part-details', 'set/card.html', icon='hashtag') }}
{{ accordion.cards(minifigures_using, 'Minifigures using this part', 'minifigures-using-inventory', 'part-details', 'minifigure/card.html', icon='group-line') }} {{ accordion.cards(sets_missing, 'Sets missing this part', 'sets-missing-inventory', 'part-details', 'set/card.html', icon='error-warning-line') }}
{{ accordion.cards(minifigures_missing, 'Minifigures missing this part', 'minifigures-missing-inventory', 'part-details', 'minifigure/card.html', icon='error-warning-line') }} {{ accordion.cards(minifigures_using, 'Minifigures using this part', 'minifigures-using-inventory', 'part-details', 'minifigure/card.html', icon='group-line') }}
</div> {{ accordion.cards(minifigures_missing, 'Minifigures missing this part', 'minifigures-missing-inventory', 'part-details', 'minifigure/card.html', icon='error-warning-line') }}
<div class="card-footer"></div> {{ accordion.cards(similar_prints, 'Prints using the same base', 'similar-prints', 'part-details', 'part/card.html', icon='palette-line') }}
</div>
<div class="card-footer"></div>
{% endif %}
</div> </div>