diff --git a/bricktracker/part_list.py b/bricktracker/part_list.py index 667c26e..833ae61 100644 --- a/bricktracker/part_list.py +++ b/bricktracker/part_list.py @@ -26,6 +26,7 @@ class BrickPartList(BrickRecordList[BrickPart]): last_query: str = 'part/list/last' minifigure_query: str = 'part/list/from_minifigure' missing_query: str = 'part/list/missing' + print_query: str = 'part/list/from_print' select_query: str = 'part/list/specific' def __init__(self, /): @@ -103,6 +104,40 @@ class BrickPartList(BrickRecordList[BrickPart]): 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 def missing(self, /) -> Self: for record in self.select( @@ -117,7 +152,7 @@ class BrickPartList(BrickRecordList[BrickPart]): # Return a dict with common SQL parameters for a parts list def sql_parameters(self, /) -> dict[str, Any]: - parameters: dict[str, Any] = {} + parameters: dict[str, Any] = super().sql_parameters() # Set id if self.brickset is not None: diff --git a/bricktracker/sql/part/list/from_print.sql b/bricktracker/sql/part/list/from_print.sql new file mode 100644 index 0000000..f996864 --- /dev/null +++ b/bricktracker/sql/part/list/from_print.sql @@ -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 %} diff --git a/bricktracker/views/part.py b/bricktracker/views/part.py index 5f20997..dbcfe0d 100644 --- a/bricktracker/views/part.py +++ b/bricktracker/views/part.py @@ -33,9 +33,11 @@ def missing() -> str: @part_page.route('///details', methods=['GET']) # noqa: E501 @exception_handler(__file__) def details(*, part: str, color: int) -> str: + brickpart = BrickPart().select_generic(part, color) + return render_template( 'part.html', - item=BrickPart().select_generic(part, color), + item=brickpart, sets_using=BrickSetList().using_part( part, color @@ -52,4 +54,5 @@ def details(*, part: str, color: int) -> str: part, color ), + similar_prints=BrickPartList().from_print(brickpart) ) diff --git a/templates/macro/card.html b/templates/macro/card.html index 3c26de7..ae8bce0 100644 --- a/templates/macro/card.html +++ b/templates/macro/card.html @@ -5,16 +5,18 @@ {% endif %}
{% if identifier %}{{ identifier }}{% endif %} - {% if item.fields.color_name %} - - {% if item.fields.color_rgb %} - - {% endif %} - {{ item.fields.color_name }} - + {% if solo %} + {% if item.fields.color_name %} + + {% if item.fields.color_rgb %} + + {% endif %} + {{ item.fields.color_name }} + + {% endif %} + {% if item.fields.color_transparent %} Transparent{% endif %} + {% if item.fields.print %} Print{% endif %} {% endif %} - {% if item.fields.color_transparent %} Transparent{% endif %} - {% if item.fields.print %} Print{% endif %} {{ name }}
{% if not solo %} diff --git a/templates/part/card.html b/templates/part/card.html index 9a14f4a..43dfcdc 100644 --- a/templates/part/card.html +++ b/templates/part/card.html @@ -2,23 +2,28 @@ {% import 'macro/badge.html' as badge %} {% import 'macro/card.html' as card %} -
+
{{ 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) }} -
+
{{ badge.total_sets(sets_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_spare(item.fields.total_spare, solo=solo, last=last) }} {{ badge.total_missing(item.fields.total_missing, solo=solo, last=last) }} - {{ badge.rebrickable(item, solo=solo, last=last) }} - {{ badge.bricklink(item, solo=solo, last=last) }} + {% if not last %} + {{ badge.rebrickable(item, solo=solo, last=last) }} + {{ badge.bricklink(item, solo=solo, last=last) }} + {% endif %}
-
- {{ accordion.cards(sets_using, 'Sets using this part', 'sets-using-inventory', 'part-details', 'set/card.html', icon='hashtag') }} - {{ accordion.cards(sets_missing, 'Sets missing this part', 'sets-missing-inventory', 'part-details', 'set/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') }} - {{ accordion.cards(minifigures_missing, 'Minifigures missing this part', 'minifigures-missing-inventory', 'part-details', 'minifigure/card.html', icon='error-warning-line') }} -
- + {% if solo %} +
+ {{ accordion.cards(sets_using, 'Sets using this part', 'sets-using-inventory', 'part-details', 'set/card.html', icon='hashtag') }} + {{ accordion.cards(sets_missing, 'Sets missing this part', 'sets-missing-inventory', 'part-details', 'set/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') }} + {{ accordion.cards(minifigures_missing, 'Minifigures missing this part', 'minifigures-missing-inventory', 'part-details', 'minifigure/card.html', icon='error-warning-line') }} + {{ accordion.cards(similar_prints, 'Prints using the same base', 'similar-prints', 'part-details', 'part/card.html', icon='palette-line') }} +
+ + {% endif %}