diff --git a/.env.sample b/.env.sample index d6141e6..fb52132 100644 --- a/.env.sample +++ b/.env.sample @@ -107,9 +107,10 @@ # Default: false # BK_HIDE_ALL_SETS=true -# Optional: Hide the 'Missing' entry from the menu. Does not disable the route. +# Optional: Hide the 'Problems' entry from the menu. Does not disable the route. # Default: false -# BK_HIDE_MISSING_PARTS=true +# Legacy name: BK_HIDE_MISSING_PARTS +# BK_HIDE_PROBLEMS_PARTS=true # Optional: Hide the 'Instructions' entry in a Set card # Default: false diff --git a/bricktracker/config.py b/bricktracker/config.py index cbb64a8..8ab193a 100644 --- a/bricktracker/config.py +++ b/bricktracker/config.py @@ -29,7 +29,7 @@ CONFIG: Final[list[dict[str, Any]]] = [ {'n': 'HIDE_ALL_MINIFIGURES', 'c': bool}, {'n': 'HIDE_ALL_PARTS', 'c': bool}, {'n': 'HIDE_ALL_SETS', 'c': bool}, - {'n': 'HIDE_MISSING_PARTS', 'c': bool}, + {'n': 'HIDE_PROBLEMS_PARTS', 'e': 'BK_HIDE_MISSING_PARTS', 'c': bool}, {'n': 'HIDE_SET_INSTRUCTIONS', 'c': bool}, {'n': 'HIDE_WISHES', 'c': bool}, {'n': 'MINIFIGURES_DEFAULT_ORDER', 'd': '"rebrickable_minifigures"."name" ASC'}, # noqa: E501 diff --git a/bricktracker/minifigure_list.py b/bricktracker/minifigure_list.py index 790018a..24a4d2e 100644 --- a/bricktracker/minifigure_list.py +++ b/bricktracker/minifigure_list.py @@ -21,10 +21,11 @@ class BrickMinifigureList(BrickRecordList[BrickMinifigure]): # Queries all_query: str = 'minifigure/list/all' + damaged_part_query: str = 'minifigure/list/damaged_part' last_query: str = 'minifigure/list/last' + missing_part_query: str = 'minifigure/list/missing_part' select_query: str = 'minifigure/list/from_set' using_part_query: str = 'minifigure/list/using_part' - missing_part_query: str = 'minifigure/list/missing_part' def __init__(self, /): super().__init__() @@ -47,6 +48,23 @@ class BrickMinifigureList(BrickRecordList[BrickMinifigure]): return self + # Minifigures with a part damaged part + def damaged_part(self, part: str, color: int, /) -> Self: + # Save the parameters to the fields + self.fields.part = part + self.fields.color = color + + # Load the minifigures from the database + for record in self.select( + override_query=self.damaged_part_query, + order=self.order + ): + minifigure = BrickMinifigure(record=record) + + self.records.append(minifigure) + + return self + # Last added minifigure def last(self, /, *, limit: int = 6) -> Self: # Randomize @@ -80,12 +98,7 @@ class BrickMinifigureList(BrickRecordList[BrickMinifigure]): return self # Minifigures missing a part - def missing_part( - self, - part: str, - color: int, - /, - ) -> Self: + def missing_part(self, part: str, color: int, /) -> Self: # Save the parameters to the fields self.fields.part = part self.fields.color = color @@ -102,12 +115,7 @@ class BrickMinifigureList(BrickRecordList[BrickMinifigure]): return self # Minifigure using a part - def using_part( - self, - part: str, - color: int, - /, - ) -> Self: + def using_part(self, part: str, color: int, /) -> Self: # Save the parameters to the fields self.fields.part = part self.fields.color = color diff --git a/bricktracker/navbar.py b/bricktracker/navbar.py index 17853eb..04b7053 100644 --- a/bricktracker/navbar.py +++ b/bricktracker/navbar.py @@ -11,7 +11,7 @@ NAVBAR: Final[list[dict[str, Any]]] = [ {'e': 'set.list', 't': 'Sets', 'i': 'grid-line', 'f': 'HIDE_ALL_SETS'}, # noqa: E501 {'e': 'add.add', 't': 'Add', 'i': 'add-circle-line', 'f': 'HIDE_ADD_SET'}, # noqa: E501 {'e': 'part.list', 't': 'Parts', 'i': 'shapes-line', 'f': 'HIDE_ALL_PARTS'}, # noqa: E501 - {'e': 'part.missing', 't': 'Missing', 'i': 'error-warning-line', 'f': 'HIDE_MISSING_PARTS'}, # noqa: E501 + {'e': 'part.problem', 't': 'Problems', 'i': 'error-warning-line', 'f': 'HIDE_PROBLEMS_PARTS'}, # noqa: E501 {'e': 'minifigure.list', 't': 'Minifigures', 'i': 'group-line', 'f': 'HIDE_ALL_MINIFIGURES'}, # noqa: E501 {'e': 'instructions.list', 't': 'Instructions', 'i': 'file-line', 'f': 'HIDE_ALL_INSTRUCTIONS'}, # noqa: E501 {'e': 'wish.list', 't': 'Wishlist', 'i': 'gift-line', 'f': 'HIDE_WISHES'}, diff --git a/bricktracker/part.py b/bricktracker/part.py index 64d71df..fa463be 100644 --- a/bricktracker/part.py +++ b/bricktracker/part.py @@ -74,9 +74,12 @@ class BrickPart(RebrickablePart): return True # A identifier for HTML component - def html_id(self, /) -> str: + def html_id(self, prefix: str | None = None, /) -> str: components: list[str] = ['part'] + if prefix is not None: + components.append(prefix) + if self.fields.figure is not None: components.append(self.fields.figure) @@ -144,36 +147,38 @@ class BrickPart(RebrickablePart): return self - # Update the missing part - def update_missing(self, json: Any | None, /) -> None: - missing: str | int = json.get('value', '') # type: ignore + # Update a problematic part + def update_problem(self, problem: str, json: Any | None, /) -> int: + amount: str | int = json.get('value', '') # type: ignore # We need a positive integer try: - if missing == '': - missing = 0 + if amount == '': + amount = 0 - missing = int(missing) + amount = int(amount) - if missing < 0: - missing = 0 + if amount < 0: + amount = 0 except Exception: - raise ErrorException('"{missing}" is not a valid integer'.format( - missing=missing + raise ErrorException('"{amount}" is not a valid integer'.format( + amount=amount )) - if missing < 0: - raise ErrorException('Cannot set a negative missing value') + if amount < 0: + raise ErrorException('Cannot set a negative amount') - self.fields.missing = missing + setattr(self.fields, problem, amount) BrickSQL().execute_and_commit( - 'part/update/missing', + 'part/update/{problem}'.format(problem=problem), parameters=self.sql_parameters() ) - # Compute the url for missing part - def url_for_missing(self, /) -> str: + return amount + + # Compute the url for problematic part + def url_for_problem(self, problem: str, /) -> str: # Different URL for a minifigure part if self.minifigure is not None: figure = self.minifigure.fields.figure @@ -181,10 +186,11 @@ class BrickPart(RebrickablePart): figure = None return url_for( - 'set.missing_part', + 'set.problem_part', id=self.fields.id, figure=figure, part=self.fields.part, color=self.fields.color, spare=self.fields.spare, + problem=problem, ) diff --git a/bricktracker/part_list.py b/bricktracker/part_list.py index 833ae61..86ca34a 100644 --- a/bricktracker/part_list.py +++ b/bricktracker/part_list.py @@ -25,7 +25,7 @@ class BrickPartList(BrickRecordList[BrickPart]): all_query: str = 'part/list/all' last_query: str = 'part/list/last' minifigure_query: str = 'part/list/from_minifigure' - missing_query: str = 'part/list/missing' + problem_query: str = 'part/list/problem' print_query: str = 'part/list/from_print' select_query: str = 'part/list/specific' @@ -138,10 +138,10 @@ class BrickPartList(BrickRecordList[BrickPart]): return self - # Load missing parts - def missing(self, /) -> Self: + # Load problematic parts + def problem(self, /) -> Self: for record in self.select( - override_query=self.missing_query, + override_query=self.problem_query, order=self.order ): part = BrickPart(record=record) diff --git a/bricktracker/set_list.py b/bricktracker/set_list.py index 54a3cb8..d538daa 100644 --- a/bricktracker/set_list.py +++ b/bricktracker/set_list.py @@ -18,6 +18,8 @@ class BrickSetList(BrickRecordList[BrickSet]): order: str # Queries + damaged_minifigure_query: str = 'set/list/damaged_minifigure' + damaged_part_query: str = 'set/list/damaged_part' generic_query: str = 'set/list/generic' light_query: str = 'set/list/light' missing_minifigure_query: str = 'set/list/missing_minifigure' @@ -57,6 +59,39 @@ class BrickSetList(BrickRecordList[BrickSet]): return self + # Sets with a minifigure part damaged + def damaged_minifigure(self, figure: str, /) -> Self: + # Save the parameters to the fields + self.fields.figure = figure + + # Load the sets from the database + for record in self.select( + override_query=self.damaged_minifigure_query, + order=self.order + ): + brickset = BrickSet(record=record) + + self.records.append(brickset) + + return self + + # Sets with a part damaged + def damaged_part(self, part: str, color: int, /) -> Self: + # Save the parameters to the fields + self.fields.part = part + self.fields.color = color + + # Load the sets from the database + for record in self.select( + override_query=self.damaged_part_query, + order=self.order + ): + brickset = BrickSet(record=record) + + self.records.append(brickset) + + return self + # A generic list of the different sets def generic(self, /) -> Self: for record in self.select( @@ -90,7 +125,7 @@ class BrickSetList(BrickRecordList[BrickSet]): return self - # Sets missing a minifigure + # Sets missing a minifigure part def missing_minifigure(self, figure: str, /) -> Self: # Save the parameters to the fields self.fields.figure = figure diff --git a/bricktracker/sql/minifigure/base/base.sql b/bricktracker/sql/minifigure/base/base.sql index dbfc428..d651bf0 100644 --- a/bricktracker/sql/minifigure/base/base.sql +++ b/bricktracker/sql/minifigure/base/base.sql @@ -7,6 +7,9 @@ SELECT {% block total_missing %} NULL AS "total_missing", -- dummy for order: total_missing {% endblock %} + {% block total_damaged %} + NULL AS "total_damaged", -- dummy for order: total_damaged + {% endblock %} {% block total_quantity %} NULL AS "total_quantity", -- dummy for order: total_quantity {% endblock %} diff --git a/bricktracker/sql/minifigure/list/all.sql b/bricktracker/sql/minifigure/list/all.sql index e3ce2bd..d0bb6eb 100644 --- a/bricktracker/sql/minifigure/list/all.sql +++ b/bricktracker/sql/minifigure/list/all.sql @@ -1,7 +1,11 @@ {% extends 'minifigure/base/base.sql' %} {% block total_missing %} -SUM(IFNULL("missing_join"."total", 0)) AS "total_missing", +SUM(IFNULL("problem_join"."total_missing", 0)) AS "total_missing", +{% endblock %} + +{% block total_damaged %} +SUM(IFNULL("problem_join"."total_damaged", 0)) AS "total_damaged", {% endblock %} {% block total_quantity %} @@ -18,15 +22,16 @@ LEFT JOIN ( SELECT "bricktracker_parts"."id", "bricktracker_parts"."figure", - SUM("bricktracker_parts"."missing") AS total + SUM("bricktracker_parts"."missing") AS "total_missing", + SUM("bricktracker_parts"."damaged") AS "total_damaged" FROM "bricktracker_parts" WHERE "bricktracker_parts"."figure" IS NOT NULL GROUP BY "bricktracker_parts"."id", "bricktracker_parts"."figure" -) "missing_join" -ON "bricktracker_minifigures"."id" IS NOT DISTINCT FROM "missing_join"."id" -AND "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM "missing_join"."figure" +) "problem_join" +ON "bricktracker_minifigures"."id" IS NOT DISTINCT FROM "problem_join"."id" +AND "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM "problem_join"."figure" {% endblock %} {% block group %} diff --git a/bricktracker/sql/minifigure/list/damaged_part.sql b/bricktracker/sql/minifigure/list/damaged_part.sql new file mode 100644 index 0000000..5cd18db --- /dev/null +++ b/bricktracker/sql/minifigure/list/damaged_part.sql @@ -0,0 +1,28 @@ +{% extends 'minifigure/base/base.sql' %} + +{% block total_damaged %} +SUM("bricktracker_parts"."damaged") AS "total_damaged", +{% endblock %} + +{% block join %} +LEFT JOIN "bricktracker_parts" +ON "bricktracker_minifigures"."id" IS NOT DISTINCT FROM "bricktracker_parts"."id" +AND "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM "bricktracker_parts"."figure" +{% endblock %} + +{% block where %} +WHERE "rebrickable_minifigures"."figure" IN ( + SELECT "bricktracker_parts"."figure" + FROM "bricktracker_parts" + WHERE "bricktracker_parts"."part" IS NOT DISTINCT FROM :part + AND "bricktracker_parts"."color" IS NOT DISTINCT FROM :color + AND "bricktracker_parts"."figure" IS NOT NULL + AND "bricktracker_parts"."damaged" > 0 + GROUP BY "bricktracker_parts"."figure" +) +{% endblock %} + +{% block group %} +GROUP BY + "rebrickable_minifigures"."figure" +{% endblock %} diff --git a/bricktracker/sql/minifigure/list/last.sql b/bricktracker/sql/minifigure/list/last.sql index 372610d..ddae212 100644 --- a/bricktracker/sql/minifigure/list/last.sql +++ b/bricktracker/sql/minifigure/list/last.sql @@ -4,6 +4,10 @@ SUM("bricktracker_parts"."missing") AS "total_missing", {% endblock %} +{% block total_damaged %} +SUM("bricktracker_parts"."damaged") AS "total_damaged", +{% endblock %} + {% block join %} LEFT JOIN "bricktracker_parts" ON "bricktracker_minifigures"."id" IS NOT DISTINCT FROM "bricktracker_parts"."id" diff --git a/bricktracker/sql/minifigure/select/generic.sql b/bricktracker/sql/minifigure/select/generic.sql index f5bacd7..b48bfb7 100644 --- a/bricktracker/sql/minifigure/select/generic.sql +++ b/bricktracker/sql/minifigure/select/generic.sql @@ -1,7 +1,11 @@ {% extends 'minifigure/base/base.sql' %} {% block total_missing %} -IFNULL("missing_join"."total", 0) AS "total_missing", +IFNULL("problem_join"."total_missing", 0) AS "total_missing", +{% endblock %} + +{% block total_damaged %} +IFNULL("problem_join"."total_damaged", 0) AS "total_damaged", {% endblock %} {% block total_quantity %} @@ -17,12 +21,13 @@ COUNT(DISTINCT "bricktracker_minifigures"."id") AS "total_sets" LEFT JOIN ( SELECT "bricktracker_parts"."figure", - SUM("bricktracker_parts"."missing") AS "total" + SUM("bricktracker_parts"."missing") AS "total_missing", + SUM("bricktracker_parts"."damaged") AS "total_damaged" FROM "bricktracker_parts" WHERE "bricktracker_parts"."figure" IS NOT DISTINCT FROM :figure GROUP BY "bricktracker_parts"."figure" -) "missing_join" -ON "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM "missing_join"."figure" +) "problem_join" +ON "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM "problem_join"."figure" {% endblock %} {% block where %} diff --git a/bricktracker/sql/part/base/base.sql b/bricktracker/sql/part/base/base.sql index 7849d4c..24c1c56 100644 --- a/bricktracker/sql/part/base/base.sql +++ b/bricktracker/sql/part/base/base.sql @@ -23,6 +23,9 @@ SELECT {% block total_missing %} NULL AS "total_missing", -- dummy for order: total_missing {% endblock %} + {% block total_damaged %} + NULL AS "total_damaged", -- dummy for order: total_damaged + {% endblock %} {% block total_quantity %} NULL AS "total_quantity", -- dummy for order: total_quantity {% endblock %} diff --git a/bricktracker/sql/part/list/all.sql b/bricktracker/sql/part/list/all.sql index c1d0ed1..77831a6 100644 --- a/bricktracker/sql/part/list/all.sql +++ b/bricktracker/sql/part/list/all.sql @@ -4,6 +4,10 @@ SUM("bricktracker_parts"."missing") AS "total_missing", {% endblock %} +{% block total_damaged %} +SUM("bricktracker_parts"."damaged") AS "total_damaged", +{% endblock %} + {% block total_quantity %} SUM("bricktracker_parts"."quantity" * IFNULL("bricktracker_minifigures"."quantity", 1)) AS "total_quantity", {% endblock %} diff --git a/bricktracker/sql/part/list/from_minifigure.sql b/bricktracker/sql/part/list/from_minifigure.sql index c840938..115b791 100644 --- a/bricktracker/sql/part/list/from_minifigure.sql +++ b/bricktracker/sql/part/list/from_minifigure.sql @@ -5,6 +5,10 @@ SUM("bricktracker_parts"."missing") AS "total_missing", {% endblock %} +{% block total_damaged %} +SUM("bricktracker_parts"."damaged") AS "total_damaged", +{% endblock %} + {% block where %} WHERE "bricktracker_parts"."figure" IS NOT DISTINCT FROM :figure {% endblock %} diff --git a/bricktracker/sql/part/list/from_print.sql b/bricktracker/sql/part/list/from_print.sql index f996864..fe1198c 100644 --- a/bricktracker/sql/part/list/from_print.sql +++ b/bricktracker/sql/part/list/from_print.sql @@ -1,8 +1,9 @@ {% extends 'part/base/base.sql' %} -{% block total_missing %} -{% endblock %} +{% block total_missing %}{% endblock %} + +{% block total_damaged %}{% endblock %} {% block where %} WHERE "rebrickable_parts"."print" IS NOT DISTINCT FROM :print diff --git a/bricktracker/sql/part/list/missing.sql b/bricktracker/sql/part/list/problem.sql similarity index 86% rename from bricktracker/sql/part/list/missing.sql rename to bricktracker/sql/part/list/problem.sql index 9d3446e..dbf411b 100644 --- a/bricktracker/sql/part/list/missing.sql +++ b/bricktracker/sql/part/list/problem.sql @@ -4,6 +4,10 @@ SUM("bricktracker_parts"."missing") AS "total_missing", {% endblock %} +{% block total_damaged %} +SUM("bricktracker_parts"."damaged") AS "total_damaged", +{% endblock %} + {% block total_sets %} COUNT("bricktracker_parts"."id") - COUNT("bricktracker_parts"."figure") AS "total_sets", {% endblock %} @@ -20,6 +24,7 @@ AND "bricktracker_parts"."figure" IS NOT DISTINCT FROM "bricktracker_minifigures {% block where %} WHERE "bricktracker_parts"."missing" > 0 +OR "bricktracker_parts"."damaged" > 0 {% endblock %} {% block group %} diff --git a/bricktracker/sql/part/list/specific.sql b/bricktracker/sql/part/list/specific.sql index d3e291a..7c62c68 100644 --- a/bricktracker/sql/part/list/specific.sql +++ b/bricktracker/sql/part/list/specific.sql @@ -5,6 +5,10 @@ IFNULL("bricktracker_parts"."missing", 0) AS "total_missing", {% endblock %} +{% block total_damaged %} +IFNULL("bricktracker_parts"."damaged", 0) AS "total_damaged", +{% endblock %} + {% block where %} WHERE "bricktracker_parts"."id" IS NOT DISTINCT FROM :id AND "bricktracker_parts"."figure" IS NOT DISTINCT FROM :figure diff --git a/bricktracker/sql/part/select/generic.sql b/bricktracker/sql/part/select/generic.sql index a1760d6..43a26da 100644 --- a/bricktracker/sql/part/select/generic.sql +++ b/bricktracker/sql/part/select/generic.sql @@ -4,6 +4,10 @@ SUM("bricktracker_parts"."missing") AS "total_missing", {% endblock %} +{% block total_damaged %} +SUM("bricktracker_parts"."damaged") AS "total_damaged", +{% endblock %} + {% block total_quantity %} SUM((NOT "bricktracker_parts"."spare") * "bricktracker_parts"."quantity" * IFNULL("bricktracker_minifigures"."quantity", 1)) AS "total_quantity", {% endblock %} diff --git a/bricktracker/sql/part/update/damaged.sql b/bricktracker/sql/part/update/damaged.sql new file mode 100644 index 0000000..d4bbabd --- /dev/null +++ b/bricktracker/sql/part/update/damaged.sql @@ -0,0 +1,7 @@ +UPDATE "bricktracker_parts" +SET "damaged" = :damaged +WHERE "bricktracker_parts"."id" IS NOT DISTINCT FROM :id +AND "bricktracker_parts"."figure" IS NOT DISTINCT FROM :figure +AND "bricktracker_parts"."part" IS NOT DISTINCT FROM :part +AND "bricktracker_parts"."color" IS NOT DISTINCT FROM :color +AND "bricktracker_parts"."spare" IS NOT DISTINCT FROM :spare diff --git a/bricktracker/sql/set/base/base.sql b/bricktracker/sql/set/base/base.sql index ffefe95..331b15e 100644 --- a/bricktracker/sql/set/base/base.sql +++ b/bricktracker/sql/set/base/base.sql @@ -21,6 +21,9 @@ SELECT {% block total_missing %} NULL AS "total_missing", -- dummy for order: total_missing {% endblock %} + {% block total_damaged %} + NULL AS "total_damaged", -- dummy for order: total_damaged + {% endblock %} {% block total_quantity %} NULL AS "total_quantity", -- dummy for order: total_quantity {% endblock %} diff --git a/bricktracker/sql/set/base/full.sql b/bricktracker/sql/set/base/full.sql index 271f890..92612df 100644 --- a/bricktracker/sql/set/base/full.sql +++ b/bricktracker/sql/set/base/full.sql @@ -5,7 +5,11 @@ {% endblock %} {% block total_missing %} -IFNULL("missing_join"."total", 0) AS "total_missing", +IFNULL("problem_join"."total_missing", 0) AS "total_missing", +{% endblock %} + +{% block total_damaged %} +IFNULL("problem_join"."total_damaged", 0) AS "total_damaged", {% endblock %} {% block total_quantity %} @@ -32,12 +36,13 @@ ON "bricktracker_sets"."id" IS NOT DISTINCT FROM "bricktracker_set_tags"."id" LEFT JOIN ( SELECT "bricktracker_parts"."id", - SUM("bricktracker_parts"."missing") AS "total" + SUM("bricktracker_parts"."missing") AS "total_missing", + SUM("bricktracker_parts"."damaged") AS "total_damaged" FROM "bricktracker_parts" {% block where_missing %}{% endblock %} GROUP BY "bricktracker_parts"."id" -) "missing_join" -ON "bricktracker_sets"."id" IS NOT DISTINCT FROM "missing_join"."id" +) "problem_join" +ON "bricktracker_sets"."id" IS NOT DISTINCT FROM "problem_join"."id" -- LEFT JOIN + SELECT to avoid messing the total LEFT JOIN ( diff --git a/bricktracker/sql/set/list/damaged_minifigure.sql b/bricktracker/sql/set/list/damaged_minifigure.sql new file mode 100644 index 0000000..51a615d --- /dev/null +++ b/bricktracker/sql/set/list/damaged_minifigure.sql @@ -0,0 +1,11 @@ +{% extends 'set/base/full.sql' %} + +{% block where %} +WHERE "bricktracker_sets"."id" IN ( + SELECT "bricktracker_parts"."id" + FROM "bricktracker_parts" + WHERE "bricktracker_parts"."figure" IS NOT DISTINCT FROM :figure + AND "bricktracker_parts"."missing" > 0 + GROUP BY "bricktracker_parts"."id" +) +{% endblock %} diff --git a/bricktracker/sql/set/list/damaged_part.sql b/bricktracker/sql/set/list/damaged_part.sql new file mode 100644 index 0000000..128931f --- /dev/null +++ b/bricktracker/sql/set/list/damaged_part.sql @@ -0,0 +1,12 @@ +{% extends 'set/base/full.sql' %} + +{% block where %} +WHERE "bricktracker_sets"."id" IN ( + SELECT "bricktracker_parts"."id" + FROM "bricktracker_parts" + WHERE "bricktracker_parts"."part" IS NOT DISTINCT FROM :part + AND "bricktracker_parts"."color" IS NOT DISTINCT FROM :color + AND "bricktracker_parts"."damaged" > 0 + GROUP BY "bricktracker_parts"."id" +) +{% endblock %} diff --git a/bricktracker/views/minifigure.py b/bricktracker/views/minifigure.py index 60647fa..5d9cc85 100644 --- a/bricktracker/views/minifigure.py +++ b/bricktracker/views/minifigure.py @@ -27,4 +27,5 @@ def details(*, figure: str) -> str: item=BrickMinifigure().select_generic(figure), using=BrickSetList().using_minifigure(figure), missing=BrickSetList().missing_minifigure(figure), + damaged=BrickSetList().damaged_minifigure(figure), ) diff --git a/bricktracker/views/part.py b/bricktracker/views/part.py index dbcfe0d..0bea4ab 100644 --- a/bricktracker/views/part.py +++ b/bricktracker/views/part.py @@ -19,13 +19,13 @@ def list() -> str: ) -# Missing -@part_page.route('/missing', methods=['GET']) +# Problem +@part_page.route('/problem', methods=['GET']) @exception_handler(__file__) -def missing() -> str: +def problem() -> str: return render_template( - 'missing.html', - table_collection=BrickPartList().missing() + 'problem.html', + table_collection=BrickPartList().problem() ) @@ -46,6 +46,10 @@ def details(*, part: str, color: int) -> str: part, color ), + sets_damaged=BrickSetList().damaged_part( + part, + color + ), minifigures_using=BrickMinifigureList().using_part( part, color @@ -54,5 +58,9 @@ def details(*, part: str, color: int) -> str: part, color ), + minifigures_damaged=BrickMinifigureList().damaged_part( + part, + color + ), similar_prints=BrickPartList().from_print(brickpart) ) diff --git a/bricktracker/views/set.py b/bricktracker/views/set.py index a6691e7..add66d2 100644 --- a/bricktracker/views/set.py +++ b/bricktracker/views/set.py @@ -136,18 +136,19 @@ def details(*, id: str) -> str: ) -# Update the missing pieces of a part -@set_page.route('//parts////missing', defaults={'figure': None}, methods=['POST']) # noqa: E501 -@set_page.route('//minifigures/
/parts////missing', methods=['POST']) # noqa: E501 +# Update problematic pieces of a set +@set_page.route('//parts////', defaults={'figure': None}, methods=['POST']) # noqa: E501 +@set_page.route('//minifigures/
/parts////', methods=['POST']) # noqa: E501 @login_required @exception_handler(__file__, json=True) -def missing_part( +def problem_part( *, id: str, figure: str | None, part: str, color: int, spare: int, + problem: str, ) -> Response: brickset = BrickSet().select_specific(id) @@ -164,20 +165,21 @@ def missing_part( minifigure=brickminifigure, ) - brickpart.update_missing(request.json) + amount = brickpart.update_problem(problem, request.json) # Info - logger.info('Set {set} ({id}): updated part ({part} color: {color}, spare: {spare}, minifigure: {figure}) missing count to {missing}'.format( # noqa: E501 + logger.info('Set {set} ({id}): updated part ({part} color: {color}, spare: {spare}, minifigure: {figure}) {problem} count to {amount}'.format( # noqa: E501 set=brickset.fields.set, id=brickset.fields.id, figure=figure, part=brickpart.fields.part, color=brickpart.fields.color, spare=brickpart.fields.spare, - missing=brickpart.fields.missing, + problem=problem, + amount=amount )) - return jsonify({'missing': brickpart.fields.missing}) + return jsonify({problem: amount}) # Refresh a set diff --git a/templates/macro/accordion.html b/templates/macro/accordion.html index 417ef47..8ae8a88 100644 --- a/templates/macro/accordion.html +++ b/templates/macro/accordion.html @@ -43,7 +43,7 @@ {% endif %} {% endmacro %} -{% macro table(table_collection, title, id, parent, target, quantity=none, icon=none, image=none, alt=none, details=none, no_missing=none, read_only=none) %} +{% macro table(table_collection, title, id, parent, target, quantity=none, icon=none, image=none, alt=none, details=none, read_only=none) %} {% set size=table_collection | length %} {% if size %} {{ header(title, id, parent, quantity=quantity, icon=icon, class='p-0', image=image, alt=alt) }} diff --git a/templates/macro/badge.html b/templates/macro/badge.html index ca57769..a3ea6d7 100644 --- a/templates/macro/badge.html +++ b/templates/macro/badge.html @@ -90,6 +90,10 @@ {{ badge(check=theme, solo=solo, last=last, color='primary', icon='price-tag-3-line', text=text, alt='Theme', tooltip=tooltip) }} {% endmacro %} +{% macro total_damaged(damaged, solo=false, last=false) %} + {{ badge(check=damaged, solo=solo, last=last, color='danger', icon='error-warning-line', collapsible='Damaged:', text=damaged, alt='Damaged') }} +{% endmacro %} + {% macro total_quantity(quantity, solo=false, last=false) %} {{ badge(check=quantity, solo=solo, last=last, color='success', icon='functions', collapsible='Quantity:', text=quantity, alt='Quantity') }} {% endmacro %} @@ -99,7 +103,7 @@ {% endmacro %} {% macro total_missing(missing, solo=false, last=false) %} - {{ badge(check=missing, solo=solo, last=last, color='danger', icon='error-warning-line', collapsible='Missing:', text=missing, alt='Missing') }} + {{ badge(check=missing, solo=solo, last=last, color='light text-danger-emphasis bg-danger-subtle border border-danger-subtle', icon='question-line', collapsible='Missing:', text=missing, alt='Missing') }} {% endmacro %} {% macro total_sets(sets, solo=false, last=false) %} diff --git a/templates/macro/table.html b/templates/macro/table.html index 91bb1c9..8db1dda 100644 --- a/templates/macro/table.html +++ b/templates/macro/table.html @@ -1,4 +1,4 @@ -{% macro header(color=false, quantity=false, missing=false, missing_parts=false, sets=false, minifigures=false) %} +{% macro header(color=false, quantity=false, missing_parts=false, damaged_parts=false, sets=false, minifigures=false) %} Image @@ -9,12 +9,8 @@ {% if quantity %} Quantity {% endif %} - {% if missing %} - Missing - {% endif %} - {% if missing_parts %} - Missing parts - {% endif %} + Missing{% if missing_parts %} parts{% endif %} + Damaged{% if damaged_parts %} parts{% endif %} {% if sets %} Sets {% endif %} diff --git a/templates/minifigure/card.html b/templates/minifigure/card.html index 446c164..80459e3 100644 --- a/templates/minifigure/card.html +++ b/templates/minifigure/card.html @@ -13,6 +13,7 @@ {{ badge.quantity(item.fields.total_quantity, solo=solo, last=last) }} {{ badge.total_sets(using | length, solo=solo, last=last) }} {{ badge.total_missing(item.fields.total_missing, solo=solo, last=last) }} + {{ badge.total_damaged(item.fields.total_damaged, solo=solo, last=last) }} {% if not last %} {{ badge.rebrickable(item, solo=solo, last=last) }} {% endif %} @@ -21,7 +22,8 @@
{{ accordion.table(item.generic_parts(), 'Parts', item.fields.figure, 'minifigure-details', 'part/table.html', icon='shapes-line', alt=item.fields.figure, read_only=read_only)}} {{ accordion.cards(using, 'Sets using this minifigure', 'using-inventory', 'minifigure-details', 'set/card.html', icon='hashtag') }} - {{ accordion.cards(missing, 'Sets missing parts of this minifigure', 'missing-inventory', 'minifigure-details', 'set/card.html', icon='error-warning-line') }} + {{ accordion.cards(missing, 'Sets missing parts for this minifigure', 'missing-inventory', 'minifigure-details', 'set/card.html', icon='question-line') }} + {{ accordion.cards(damaged, 'Sets with damaged parts for this minifigure', 'damaged-inventory', 'minifigure-details', 'set/card.html', icon='error-warning-line') }}
{% endif %} diff --git a/templates/minifigure/table.html b/templates/minifigure/table.html index 66ece79..aeb0bb7 100644 --- a/templates/minifigure/table.html +++ b/templates/minifigure/table.html @@ -2,7 +2,7 @@
- {{ table.header(quantity=true, missing_parts=true, sets=true) }} + {{ table.header(quantity=true, missing_parts=true, damaged_parts=true, sets=true) }} {% for item in table_collection %} @@ -15,6 +15,7 @@ + {% endfor %} diff --git a/templates/part/card.html b/templates/part/card.html index 4cb4031..8a0d7aa 100644 --- a/templates/part/card.html +++ b/templates/part/card.html @@ -15,6 +15,7 @@ {{ 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.total_damaged(item.fields.total_damaged, solo=solo, last=last) }} {% if not last %} {{ badge.rebrickable(item, solo=solo, last=last) }} {{ badge.bricklink(item, solo=solo, last=last) }} @@ -23,9 +24,11 @@ {% 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(sets_missing, 'Sets missing this part', 'sets-missing-inventory', 'part-details', 'set/card.html', icon='question-line') }} + {{ accordion.cards(sets_damaged, 'Sets with this part damaged', 'sets-damaged-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(minifigures_missing, 'Minifigures missing this part', 'minifigures-missing-inventory', 'part-details', 'minifigure/card.html', icon='question-line') }} + {{ accordion.cards(minifigures_damaged, 'Minifigures with this part damaged', 'minifigures-damaged-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='paint-brush-line') }}
diff --git a/templates/part/table.html b/templates/part/table.html index cd16f9b..ac96af5 100644 --- a/templates/part/table.html +++ b/templates/part/table.html @@ -3,7 +3,7 @@
{{ item.fields.total_quantity }} {{ item.fields.total_missing }}{{ item.fields.total_damaged }} {{ item.fields.total_sets }}
- {{ table.header(color=true, quantity=not no_quantity, missing=not no_missing, sets=all, minifigures=all) }} + {{ table.header(color=true, quantity=not no_quantity, sets=all, minifigures=all) }} {% for item in table_collection %} @@ -27,11 +27,12 @@ {% endif %} {% endif %} - {% if not no_missing %} - - {% endif %} + + {% if all %} diff --git a/templates/missing.html b/templates/problem.html similarity index 78% rename from templates/missing.html rename to templates/problem.html index d7c82a5..76f61f5 100644 --- a/templates/missing.html +++ b/templates/problem.html @@ -1,6 +1,6 @@ {% extends 'base.html' %} -{% block title %} - Missing parts{% endblock %} +{% block title %} - Problematic parts{% endblock %} {% block main %}
diff --git a/templates/set/card.html b/templates/set/card.html index eb48c18..262c640 100644 --- a/templates/set/card.html +++ b/templates/set/card.html @@ -6,8 +6,11 @@
Parts + data-sort-attribute="missing" data-sort-desc="true"> Missing +
@@ -53,6 +55,7 @@ + {% for status in brickset_statuses %}
{% if quantity %}{{ item.fields.quantity * quantity }}{% else %}{{ item.fields.quantity }}{% endif %} - {{ form.input('Missing', item.fields.id, item.html_id(), item.url_for_missing(), item.fields.total_missing, all=all, read_only=read_only) }} - + {{ form.input('Missing', item.fields.id, item.html_id('missing'), item.url_for_problem('missing'), item.fields.total_missing, all=all, read_only=read_only) }} + + {{ form.input('Damaged', item.fields.id, item.html_id('damaged'), item.url_for_problem('damaged'), item.fields.total_damaged, all=all, read_only=read_only) }} + {{ item.fields.total_sets }} {{ item.fields.total_minifigures }}