diff --git a/bricktracker/views/add.py b/bricktracker/views/add.py index db4671e..369787c 100644 --- a/bricktracker/views/add.py +++ b/bricktracker/views/add.py @@ -1,4 +1,4 @@ -from flask import Blueprint, current_app, render_template +from flask import Blueprint, current_app, render_template, abort from flask_login import login_required from ..configuration_list import BrickConfigurationList @@ -40,3 +40,23 @@ def bulk() -> str: bulk=True, **set_metadata_lists() ) + + +# Add individual parts +@add_page.route('/parts', methods=['GET']) +@login_required +@exception_handler(__file__) +def parts() -> str: + # Block route if individual parts feature is disabled + if current_app.config.get('DISABLE_INDIVIDUAL_PARTS', False): + abort(404) + + BrickConfigurationList.error_unless_is_set('REBRICKABLE_API_KEY') + + return render_template( + 'add_parts.html', + path=current_app.config['SOCKET_PATH'], + namespace=current_app.config['SOCKET_NAMESPACE'], + messages=MESSAGES, + **set_metadata_lists() + ) diff --git a/bricktracker/views/minifigure.py b/bricktracker/views/minifigure.py index 7fbb833..f700c67 100644 --- a/bricktracker/views/minifigure.py +++ b/bricktracker/views/minifigure.py @@ -1,6 +1,7 @@ from flask import Blueprint, current_app, render_template, request from .exceptions import exception_handler +from ..individual_minifigure_list import IndividualMinifigureList from ..minifigure import BrickMinifigure from ..minifigure_list import BrickMinifigureList from ..pagination_helper import get_pagination_config, build_pagination_context, get_request_params @@ -19,6 +20,7 @@ def list() -> str: problems_filter = request.args.get('problems', 'all') theme_id = request.args.get('theme', 'all') year = request.args.get('year', 'all') + individuals_filter = request.args.get('individuals', 'all') search_query, sort_field, sort_order, page = get_request_params() # Get pagination configuration @@ -32,6 +34,7 @@ def list() -> str: problems_filter=problems_filter, theme_id=theme_id, year=year, + individuals_filter=individuals_filter, search_query=search_query, page=page, per_page=per_page, @@ -42,7 +45,7 @@ def list() -> str: pagination_context = build_pagination_context(page, per_page, total_count, is_mobile) else: # ORIGINAL MODE - Single page with all data for client-side search - minifigures = BrickMinifigureList().all_filtered(owner_id=owner_id, problems_filter=problems_filter, theme_id=theme_id, year=year) + minifigures = BrickMinifigureList().all_filtered(owner_id=owner_id, problems_filter=problems_filter, theme_id=theme_id, year=year, individuals_filter=individuals_filter) pagination_context = None @@ -79,6 +82,7 @@ def list() -> str: 'selected_theme': theme_id, 'years': years, 'selected_year': year, + 'selected_individuals': individuals_filter, 'search_query': search_query, 'use_pagination': use_pagination, 'current_sort': sort_field, @@ -101,5 +105,6 @@ def details(*, figure: str) -> str: using=BrickSetList().using_minifigure(figure), missing=BrickSetList().missing_minifigure(figure), damaged=BrickSetList().damaged_minifigure(figure), + individual_instances=IndividualMinifigureList().instances_by_figure(figure), **set_metadata_lists(as_class=True) ) diff --git a/bricktracker/views/part.py b/bricktracker/views/part.py index 7450f48..771934e 100644 --- a/bricktracker/views/part.py +++ b/bricktracker/views/part.py @@ -1,6 +1,8 @@ from flask import Blueprint, render_template, request from .exceptions import exception_handler +from ..individual_part_list import IndividualPartList +from ..individual_part_lot_list import IndividualPartLotList from ..minifigure_list import BrickMinifigureList from ..pagination_helper import get_pagination_config, build_pagination_context, get_request_params from ..part import BrickPart @@ -21,6 +23,7 @@ def list() -> str: color_id = request.args.get('color', 'all') theme_id = request.args.get('theme', 'all') year = request.args.get('year', 'all') + individuals_filter = request.args.get('individuals', 'all') search_query, sort_field, sort_order, page = get_request_params() # Get pagination configuration @@ -34,6 +37,7 @@ def list() -> str: color_id=color_id, theme_id=theme_id, year=year, + individuals_filter=individuals_filter, search_query=search_query, page=page, per_page=per_page, @@ -44,7 +48,7 @@ def list() -> str: pagination_context = build_pagination_context(page, per_page, total_count, is_mobile) else: # ORIGINAL MODE - Single page with all data for client-side search - parts = BrickPartList().all_filtered(owner_id, color_id, theme_id, year) + parts = BrickPartList().all_filtered(owner_id, color_id, theme_id, year, individuals_filter) pagination_context = None # Get list of owners for filter dropdown @@ -83,6 +87,7 @@ def list() -> str: 'selected_theme': theme_id, 'years': years, 'selected_year': year, + 'selected_individuals': individuals_filter, 'search_query': search_query, 'use_pagination': use_pagination, 'current_sort': sort_field, @@ -225,5 +230,7 @@ def details(*, part: str, color: int) -> str: ), different_color=BrickPartList().with_different_color(brickpart), similar_prints=BrickPartList().from_print(brickpart), + individual_parts=IndividualPartList().by_part_and_color(part, color), + individual_lots=IndividualPartLotList().by_part_and_color(part, color), **set_metadata_lists(as_class=True) ) diff --git a/bricktracker/views/storage.py b/bricktracker/views/storage.py index 7d5ba3f..ed4f4a0 100644 --- a/bricktracker/views/storage.py +++ b/bricktracker/views/storage.py @@ -4,6 +4,9 @@ from .exceptions import exception_handler from ..set_list import BrickSetList, set_metadata_lists from ..set_storage import BrickSetStorage from ..set_storage_list import BrickSetStorageList +from ..individual_minifigure_list import IndividualMinifigureList +from ..individual_part_list import IndividualPartList +from ..individual_part_lot_list import IndividualPartLotList storage_page = Blueprint('storage', __name__, url_prefix='/storages') @@ -28,5 +31,8 @@ def details(*, id: str) -> str: 'storage.html', item=storage, sets=BrickSetList().using_storage(storage), + individual_minifigures=IndividualMinifigureList().using_storage(storage), + individual_parts=IndividualPartList().using_storage(storage), + individual_part_lots=IndividualPartLotList().using_storage(storage), **set_metadata_lists(as_class=True) )