feat(minifigures): individual minifigures can now be disabled using env var
This commit is contained in:
@@ -122,6 +122,13 @@
|
||||
# Default: false
|
||||
# BK_HIDE_ALL_MINIFIGURES=true
|
||||
|
||||
# Optional: Disable the individual/loose minifigures system. This hides all individual
|
||||
# minifigure UI elements and prevents adding new individual minifigures. The routes remain
|
||||
# accessible so existing individual minifigures can still be viewed. Users who only track
|
||||
# set-based minifigures can use this to simplify the interface. Does not disable the route.
|
||||
# Default: false
|
||||
# BK_DISABLE_INDIVIDUAL_MINIFIGURES=false
|
||||
|
||||
# Optional: Hide the 'Parts' entry from the menu. Does not disable the route.
|
||||
# Default: false
|
||||
# BK_HIDE_ALL_PARTS=true
|
||||
|
||||
@@ -18,6 +18,7 @@ CONFIG: Final[list[dict[str, Any]]] = [
|
||||
{'n': 'DEBUG', 'c': bool},
|
||||
{'n': 'DEFAULT_TABLE_PER_PAGE', 'd': 25, 'c': int},
|
||||
{'n': 'DESCRIPTION_BADGE_MAX_LENGTH', 'd': 15, 'c': int},
|
||||
{'n': 'DISABLE_INDIVIDUAL_MINIFIGURES', 'c': bool},
|
||||
{'n': 'DOMAIN_NAME', 'e': 'DOMAIN_NAME', 'd': ''},
|
||||
{'n': 'FILE_DATETIME_FORMAT', 'd': '%d/%m/%Y, %H:%M:%S'},
|
||||
{'n': 'HOST', 'd': '0.0.0.0'},
|
||||
|
||||
@@ -84,6 +84,7 @@ RESTART_REQUIRED_VARS: Final[List[str]] = [
|
||||
'BK_AUTHENTICATION_KEY',
|
||||
'BK_DATABASE_PATH',
|
||||
'BK_DEBUG',
|
||||
'BK_DISABLE_INDIVIDUAL_MINIFIGURES',
|
||||
'BK_DOMAIN_NAME',
|
||||
'BK_HOST',
|
||||
'BK_PORT',
|
||||
|
||||
@@ -309,6 +309,14 @@ class IndividualMinifigure(RebrickableMinifigure):
|
||||
socket.progress_total = 2
|
||||
|
||||
try:
|
||||
# Check if individual minifigures are disabled
|
||||
from flask import current_app
|
||||
if current_app.config.get('DISABLE_INDIVIDUAL_MINIFIGURES', False):
|
||||
raise ErrorException(
|
||||
'Individual minifigures system is disabled. '
|
||||
'Only set-based minifigures can be added.'
|
||||
)
|
||||
|
||||
socket.auto_progress(message='Parsing minifigure number')
|
||||
figure = parse_minifig(str(data['figure']))
|
||||
|
||||
@@ -402,12 +410,17 @@ class IndividualMinifigure(RebrickableMinifigure):
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
socket.fail(
|
||||
message='Could not load the minifigure from Rebrickable: {error}. Data: {data}'.format(
|
||||
error=str(e),
|
||||
data=data,
|
||||
# Check if this is the "disabled" error - if so, show cleaner message
|
||||
error_msg = str(e)
|
||||
if 'Individual minifigures system is disabled' in error_msg:
|
||||
socket.fail(message=error_msg)
|
||||
else:
|
||||
socket.fail(
|
||||
message='Could not load the minifigure from Rebrickable: {error}. Data: {data}'.format(
|
||||
error=error_msg,
|
||||
data=data,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if not isinstance(e, (NotFoundException, ErrorException)):
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
<div id="add-complete"></div>
|
||||
{% endif %}
|
||||
<div class="mb-3">
|
||||
<label for="add-set" class="form-label">{% if not bulk %}Set or Minifigure number (only one){% else %}List of sets (separated by a comma){% endif %}</label>
|
||||
<input type="text" class="form-control" id="add-set" placeholder="{% if not bulk %}107-1 or fig-001234 or ...{% else %}107-1, 1642-1, ...{% endif %}"
|
||||
<label for="add-set" class="form-label">{% if not bulk %}{% if not config['DISABLE_INDIVIDUAL_MINIFIGURES'] %}Set or Minifigure number (only one){% else %}Set number (only one){% endif %}{% else %}List of sets (separated by a comma){% endif %}</label>
|
||||
<input type="text" class="form-control" id="add-set" placeholder="{% if not bulk %}{% if not config['DISABLE_INDIVIDUAL_MINIFIGURES'] %}107-1 or fig-001234 or ...{% else %}107-1 or ...{% endif %}{% else %}107-1, 1642-1, ...{% endif %}"
|
||||
data-path="{{ path }}"
|
||||
data-namespace="{{ namespace }}"
|
||||
data-msg-complete="{{ messages['COMPLETE'] }}"
|
||||
@@ -39,7 +39,7 @@
|
||||
data-msg-import-minifigure="{{ messages['IMPORT_MINIFIGURE'] }}"
|
||||
data-msg-load-minifigure="{{ messages['LOAD_MINIFIGURE'] }}"
|
||||
data-msg-minifigure-loaded="{{ messages['MINIFIGURE_LOADED'] }}">
|
||||
<div class="form-text">Sets: use format like 107-1. Minifigures: use format like fig-001234</div>
|
||||
<div class="form-text">Sets: use format like 107-1{% if not config['DISABLE_INDIVIDUAL_MINIFIGURES'] %}. Minifigures: use format like fig-001234{% endif %}</div>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="add-no-confirm" {% if bulk %}checked disabled{% endif %}>
|
||||
|
||||
@@ -756,6 +756,15 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input config-static-toggle" type="checkbox" id="static-BK_DISABLE_INDIVIDUAL_MINIFIGURES" data-var="BK_DISABLE_INDIVIDUAL_MINIFIGURES">
|
||||
<label class="form-check-label" for="static-BK_DISABLE_INDIVIDUAL_MINIFIGURES">
|
||||
BK_DISABLE_INDIVIDUAL_MINIFIGURES {{ config_badges('BK_DISABLE_INDIVIDUAL_MINIFIGURES') }}
|
||||
<div class="text-muted small">Completely disable individual/loose minifigures system</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="static-BK_DOMAIN_NAME" class="form-label">
|
||||
BK_DOMAIN_NAME {{ config_badges('BK_DOMAIN_NAME') }}
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
<div class="accordion accordion-flush" id="minifigure-details">
|
||||
{{ 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') }}
|
||||
{% if individual_instances is defined and individual_instances | length > 0 %}
|
||||
{{ accordion.cards(individual_instances, 'Individual minifigure instances', 'individual-instances', 'minifigure-details', 'individual_minifigure/card.html', icon='package-line') }}
|
||||
{% if not config['DISABLE_INDIVIDUAL_MINIFIGURES'] %}
|
||||
{% if individual_instances is defined and individual_instances | length > 0 %}
|
||||
{{ accordion.cards(individual_instances, 'Individual minifigure instances', 'individual-instances', 'minifigure-details', 'individual_minifigure/card.html', icon='package-line') }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{{ 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') }}
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
{% endif %}
|
||||
<button id="sort-sets" type="button" class="btn btn-outline-primary mb-2"
|
||||
data-sort-attribute="sets" data-sort-desc="true"><i class="ri-hashtag"></i><span class="d-none d-xl-inline"> Sets</span></button>
|
||||
{% if not config['DISABLE_INDIVIDUAL_MINIFIGURES'] %}
|
||||
<button id="sort-individual" type="button" class="btn btn-outline-primary mb-2"
|
||||
data-sort-attribute="individual" data-sort-desc="true"><i class="ri-package-line"></i><span class="d-none d-xl-inline"> Individual</span></button>
|
||||
{% endif %}
|
||||
<button id="sort-clear" type="button" class="btn btn-outline-dark mb-2"
|
||||
data-sort-clear="true"><i class="ri-close-circle-line"></i><span class="d-none d-xl-inline"> Clear</span></button>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
<td data-sort="{{ minifigure.fields.total_damaged }}">{{ minifigure.fields.total_damaged }}</td>
|
||||
{% endif %}
|
||||
<td data-sort="{{ minifigure.fields.total_sets }}">{{ minifigure.fields.total_sets }}</td>
|
||||
{% if not config['DISABLE_INDIVIDUAL_MINIFIGURES'] %}
|
||||
<td data-sort="{{ minifigure.fields.total_individual }}">{{ minifigure.fields.total_individual }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@@ -33,7 +33,7 @@
|
||||
<!-- PAGINATION MODE -->
|
||||
<div class="table-responsive-sm">
|
||||
<table data-table="false" class="table table-striped align-middle mb-0" id="minifigures">
|
||||
{{ table.header(parts=true, quantity=true, missing=true, damaged=true, sets=true, individual=true, minifigures=false) }}
|
||||
{{ table.header(parts=true, quantity=true, missing=true, damaged=true, sets=true, individual=(not config['DISABLE_INDIVIDUAL_MINIFIGURES']), minifigures=false) }}
|
||||
{% include 'minifigure/table_body.html' %}
|
||||
</table>
|
||||
</div>
|
||||
@@ -148,7 +148,7 @@
|
||||
<!-- ORIGINAL MODE - Single page with client-side search -->
|
||||
<div class="table-responsive-sm">
|
||||
<table data-table="true" class="table table-striped align-middle {% if not all %}sortable mb-0{% endif %}" id="minifigures">
|
||||
{{ table.header(parts=true, quantity=true, missing=true, damaged=true, sets=true, individual=true, minifigures=false) }}
|
||||
{{ table.header(parts=true, quantity=true, missing=true, damaged=true, sets=true, individual=(not config['DISABLE_INDIVIDUAL_MINIFIGURES']), minifigures=false) }}
|
||||
<tbody>
|
||||
{% for minifigure in table_collection %}
|
||||
<tr>
|
||||
|
||||
@@ -5,13 +5,17 @@
|
||||
<div class="card mb-3 flex-fill {% if solo %}card-solo{% endif %}">
|
||||
{{ card.header(item, item.fields.name, solo=solo, icon='archive-2-line') }}
|
||||
<div class="card-body border-bottom-0 {% if not solo %}p-1{% endif %}">
|
||||
{{ badge.total_sets(sets | length, solo=solo, last=false) }}
|
||||
{{ badge.total_individual_minifigures(individual_minifigures | length, solo=solo, last=last) }}
|
||||
{{ badge.total_sets(sets | length, solo=solo, last=(config['DISABLE_INDIVIDUAL_MINIFIGURES'] or last)) }}
|
||||
{% if not config['DISABLE_INDIVIDUAL_MINIFIGURES'] %}
|
||||
{{ badge.total_individual_minifigures(individual_minifigures | length, solo=solo, last=last) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if solo %}
|
||||
<div class="accordion accordion-flush border-top" id="storage-details">
|
||||
{{ accordion.cards(sets, 'Sets', 'sets-stored', 'storage-details', 'set/card.html', expanded=true, icon='hashtag') }}
|
||||
{{ accordion.cards(individual_minifigures, 'Individual Minifigures', 'individual-minifigures-stored', 'storage-details', 'individual_minifigure/card.html', icon='user-line') }}
|
||||
{% if not config['DISABLE_INDIVIDUAL_MINIFIGURES'] %}
|
||||
{{ accordion.cards(individual_minifigures, 'Individual Minifigures', 'individual-minifigures-stored', 'storage-details', 'individual_minifigure/card.html', icon='user-line') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-footer"></div>
|
||||
{% endif %}
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table data-table="true" class="table table-striped align-middle" id="storage">
|
||||
{{ table.header(image=false, missing=false, damaged=false, sets=true, individual=true) }}
|
||||
{{ table.header(image=false, missing=false, damaged=false, sets=true, individual=(not config['DISABLE_INDIVIDUAL_MINIFIGURES'])) }}
|
||||
<tbody>
|
||||
{% for item in table_collection %}
|
||||
<tr>
|
||||
<td data-sort="{{ item.fields.name }}"><a class="text-reset" href="{{ item.url() }}">{{ item.fields.name }}</a></td>
|
||||
<td>{{ item.fields.total_sets }}</td>
|
||||
<td>{{ item.fields.total_individual_minifigures }}</td>
|
||||
{% if not config['DISABLE_INDIVIDUAL_MINIFIGURES'] %}
|
||||
<td>{{ item.fields.total_individual_minifigures }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if sets_no_storage is defined and minifigs_no_storage is defined %}
|
||||
@@ -17,7 +19,9 @@
|
||||
<tr class="table-warning">
|
||||
<td data-sort="zzz-not-in-storage"><a class="text-reset" href="{{ url_for('storage.no_storage_details') }}"><em>Not in a storage location</em></a></td>
|
||||
<td>{{ sets_no_storage }}</td>
|
||||
<td>{{ minifigs_no_storage }}</td>
|
||||
{% if not config['DISABLE_INDIVIDUAL_MINIFIGURES'] %}
|
||||
<td>{{ minifigs_no_storage }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user