Bugfix: External spool
Improvement: Use fragments in templates Features: Manual fill of empty tray Bump version to 0.1.3
This commit is contained in:
parent
5dd026479f
commit
96a85271c0
@ -7,6 +7,9 @@ Similar functionality to https://github.com/spuder/OpenSpool using only your pho
|
|||||||
|
|
||||||
Everything works locally without cloud access, you can use scripts/init_bambulab.py script to access your PRINTER_ID and PRINTER_CODE if it is not available on your printer.
|
Everything works locally without cloud access, you can use scripts/init_bambulab.py script to access your PRINTER_ID and PRINTER_CODE if it is not available on your printer.
|
||||||
|
|
||||||
|
### News
|
||||||
|
0.1.3 - 22.12.2024 - Added manual assignment for empty slots
|
||||||
|
|
||||||
### Main features
|
### Main features
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
@ -113,7 +116,9 @@ This feature has currently following issues/drawbacks:
|
|||||||
- Logs
|
- Logs
|
||||||
- TODOs
|
- TODOs
|
||||||
- Click to resolve issue
|
- Click to resolve issue
|
||||||
- More template components / less copy&paste
|
|
||||||
- Better Tray naming
|
- Better Tray naming
|
||||||
- Reduce the amount of files in docker container
|
- Reduce the amount of files in docker container
|
||||||
- Cloud service for controlled redirect so you don't have to reconfigure NFC tags
|
- Cloud service for controlled redirect so you don't have to reconfigure NFC tags
|
||||||
|
- Handle printer offline
|
||||||
|
- QR codes
|
||||||
|
- Add search to list of spools
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = '0.1.2'
|
__version__ = '0.1.3'
|
||||||
|
103
app.py
103
app.py
@ -14,9 +14,32 @@ from spoolman_service import augmentTrayDataWithSpoolMan, trayUid
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
EXTERNAL_SPOOL_AMS_ID = 255
|
||||||
|
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
def fronted_utilities():
|
def fronted_utilities():
|
||||||
return dict(SPOOLMAN_BASE_URL=SPOOLMAN_BASE_URL, AUTO_SPEND=AUTO_SPEND, color_is_dark=color_is_dark, BASE_URL=BASE_URL)
|
return dict(SPOOLMAN_BASE_URL=SPOOLMAN_BASE_URL, AUTO_SPEND=AUTO_SPEND, color_is_dark=color_is_dark, BASE_URL=BASE_URL, EXTERNAL_SPOOL_AMS_ID=EXTERNAL_SPOOL_AMS_ID)
|
||||||
|
|
||||||
|
@app.route("/issue")
|
||||||
|
def issue():
|
||||||
|
return render_template('issue.html')
|
||||||
|
|
||||||
|
@app.route("/fill")
|
||||||
|
def fill():
|
||||||
|
ams_id = request.args.get("ams")
|
||||||
|
tray_id = request.args.get("tray")
|
||||||
|
if not all([ams_id, tray_id]):
|
||||||
|
return "Missing AMS ID, or Tray ID."
|
||||||
|
|
||||||
|
spool_id = request.args.get("spool_id")
|
||||||
|
if spool_id:
|
||||||
|
spool_data = getSpoolById(spool_id)
|
||||||
|
setActiveTray(spool_id, spool_data["extra"], ams_id, tray_id)
|
||||||
|
setActiveSpool(ams_id, tray_id, spool_data)
|
||||||
|
return redirect(url_for('home', success_message=f"Updated Spool ID {spool_id} to AMS {ams_id}, Tray {tray_id}."))
|
||||||
|
else:
|
||||||
|
spools = fetchSpools()
|
||||||
|
return render_template('fill.html', spools=spools, ams_id=ams_id, tray_id=tray_id)
|
||||||
|
|
||||||
@app.route("/spool_info")
|
@app.route("/spool_info")
|
||||||
def spool_info():
|
def spool_info():
|
||||||
@ -63,43 +86,43 @@ def tray_load():
|
|||||||
try:
|
try:
|
||||||
# Update Spoolman with the selected tray
|
# Update Spoolman with the selected tray
|
||||||
spool_data = getSpoolById(spool_id)
|
spool_data = getSpoolById(spool_id)
|
||||||
|
|
||||||
setActiveTray(spool_id, spool_data["extra"], ams_id, tray_id)
|
setActiveTray(spool_id, spool_data["extra"], ams_id, tray_id)
|
||||||
|
setActiveSpool(ams_id, tray_id, spool_data)
|
||||||
ams_message = AMS_FILAMENT_SETTING
|
|
||||||
ams_message["print"]["sequence_id"] = 0
|
|
||||||
ams_message["print"]["ams_id"] = int(ams_id)
|
|
||||||
ams_message["print"]["tray_id"] = int(tray_id)
|
|
||||||
ams_message["print"]["tray_color"] = spool_data["filament"]["color_hex"].upper() + "FF"
|
|
||||||
|
|
||||||
if "nozzle_temperature" in spool_data["filament"]["extra"]:
|
|
||||||
nozzle_temperature_range = spool_data["filament"]["extra"]["nozzle_temperature"].strip("[]").split(",")
|
|
||||||
ams_message["print"]["nozzle_temp_min"] = int(nozzle_temperature_range[0])
|
|
||||||
ams_message["print"]["nozzle_temp_max"] = int(nozzle_temperature_range[1])
|
|
||||||
else:
|
|
||||||
nozzle_temperature_range_obj = generate_filament_temperatures(spool_data["filament"]["material"],
|
|
||||||
spool_data["filament"]["vendor"]["name"])
|
|
||||||
ams_message["print"]["nozzle_temp_min"] = int(nozzle_temperature_range_obj["filament_min_temp"])
|
|
||||||
ams_message["print"]["nozzle_temp_max"] = int(nozzle_temperature_range_obj["filament_max_temp"])
|
|
||||||
|
|
||||||
ams_message["print"]["tray_type"] = spool_data["filament"]["material"]
|
|
||||||
filament_brand_code = generate_filament_brand_code(spool_data["filament"]["material"],
|
|
||||||
spool_data["filament"]["vendor"]["name"],
|
|
||||||
spool_data["filament"]["extra"].get("type", ""))
|
|
||||||
ams_message["print"]["tray_info_idx"] = filament_brand_code["brand_code"]
|
|
||||||
|
|
||||||
# TODO: test sub_brand_code
|
|
||||||
# ams_message["print"]["tray_sub_brands"] = filament_brand_code["sub_brand_code"]
|
|
||||||
ams_message["print"]["tray_sub_brands"] = ""
|
|
||||||
|
|
||||||
print(ams_message)
|
|
||||||
publish(getMqttClient(), ams_message)
|
|
||||||
|
|
||||||
return redirect(url_for('home', success_message=f"Updated Spool ID {spool_id} with TAG id {tag_id} to AMS {ams_id}, Tray {tray_id}."))
|
return redirect(url_for('home', success_message=f"Updated Spool ID {spool_id} with TAG id {tag_id} to AMS {ams_id}, Tray {tray_id}."))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return render_template('error.html', exception=str(e))
|
return render_template('error.html', exception=str(e))
|
||||||
|
|
||||||
|
def setActiveSpool(ams_id, tray_id, spool_data):
|
||||||
|
ams_message = AMS_FILAMENT_SETTING
|
||||||
|
ams_message["print"]["sequence_id"] = 0
|
||||||
|
ams_message["print"]["ams_id"] = int(ams_id)
|
||||||
|
ams_message["print"]["tray_id"] = int(tray_id)
|
||||||
|
ams_message["print"]["tray_color"] = spool_data["filament"]["color_hex"].upper() + "FF"
|
||||||
|
|
||||||
|
if "nozzle_temperature" in spool_data["filament"]["extra"]:
|
||||||
|
nozzle_temperature_range = spool_data["filament"]["extra"]["nozzle_temperature"].strip("[]").split(",")
|
||||||
|
ams_message["print"]["nozzle_temp_min"] = int(nozzle_temperature_range[0])
|
||||||
|
ams_message["print"]["nozzle_temp_max"] = int(nozzle_temperature_range[1])
|
||||||
|
else:
|
||||||
|
nozzle_temperature_range_obj = generate_filament_temperatures(spool_data["filament"]["material"],
|
||||||
|
spool_data["filament"]["vendor"]["name"])
|
||||||
|
ams_message["print"]["nozzle_temp_min"] = int(nozzle_temperature_range_obj["filament_min_temp"])
|
||||||
|
ams_message["print"]["nozzle_temp_max"] = int(nozzle_temperature_range_obj["filament_max_temp"])
|
||||||
|
|
||||||
|
ams_message["print"]["tray_type"] = spool_data["filament"]["material"]
|
||||||
|
filament_brand_code = generate_filament_brand_code(spool_data["filament"]["material"],
|
||||||
|
spool_data["filament"]["vendor"]["name"],
|
||||||
|
spool_data["filament"]["extra"].get("type", ""))
|
||||||
|
ams_message["print"]["tray_info_idx"] = filament_brand_code["brand_code"]
|
||||||
|
|
||||||
|
# TODO: test sub_brand_code
|
||||||
|
# ams_message["print"]["tray_sub_brands"] = filament_brand_code["sub_brand_code"]
|
||||||
|
ams_message["print"]["tray_sub_brands"] = ""
|
||||||
|
|
||||||
|
print(ams_message)
|
||||||
|
publish(getMqttClient(), ams_message)
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def home():
|
def home():
|
||||||
@ -111,8 +134,8 @@ def home():
|
|||||||
success_message = request.args.get("success_message")
|
success_message = request.args.get("success_message")
|
||||||
|
|
||||||
issue = False
|
issue = False
|
||||||
#TODO: recheck tray ID and external spool ID and extract it to constant
|
#TODO: Fix issue when external spool info is reset via bambulab interface
|
||||||
augmentTrayDataWithSpoolMan(spool_list, vt_tray_data, trayUid(vt_tray_data["id"], 255))
|
augmentTrayDataWithSpoolMan(spool_list, vt_tray_data, trayUid(EXTERNAL_SPOOL_AMS_ID, vt_tray_data["id"]))
|
||||||
issue |= vt_tray_data["issue"]
|
issue |= vt_tray_data["issue"]
|
||||||
|
|
||||||
for ams in ams_data:
|
for ams in ams_data:
|
||||||
@ -125,10 +148,22 @@ def home():
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return render_template('error.html', exception=str(e))
|
return render_template('error.html', exception=str(e))
|
||||||
|
|
||||||
|
def sort_spools(spools):
|
||||||
|
def condition(item):
|
||||||
|
# Ensure the item has an "extra" key and is a dictionary
|
||||||
|
if not isinstance(item, dict) or "extra" not in item or not isinstance(item["extra"], dict):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Check the specified condition
|
||||||
|
return item["extra"].get("tag") or item["extra"].get("tag") == ""
|
||||||
|
|
||||||
|
# Sort with the custom condition: False values come first
|
||||||
|
return sorted(spools, key=lambda spool: bool(condition(spool)))
|
||||||
|
|
||||||
@app.route("/assign_tag")
|
@app.route("/assign_tag")
|
||||||
def assign_tag():
|
def assign_tag():
|
||||||
try:
|
try:
|
||||||
spools = fetchSpools()
|
spools = sort_spools(fetchSpools())
|
||||||
|
|
||||||
return render_template('assign_tag.html', spools=spools)
|
return render_template('assign_tag.html', spools=spools)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -3,70 +3,5 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<!-- Page Title -->
|
<!-- Page Title -->
|
||||||
<h1 class="mb-4 text-center">Assign NFC Tag to Spool</h1>
|
<h1 class="mb-4 text-center">Assign NFC Tag to Spool</h1>
|
||||||
|
{% with action_assign=True %}{% include 'fragments/list_spools.html' %}{% endwith %}
|
||||||
<!-- Empty State -->
|
|
||||||
{% if spools|length == 0 or not spools %}
|
|
||||||
<div class="alert alert-info text-center" role="alert">
|
|
||||||
No spools available to tag at the moment.
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
<!-- Spool List -->
|
|
||||||
<div class="list-group">
|
|
||||||
{% for spool in spools %}
|
|
||||||
{% if not spool.extra.get("tag") or spool.extra.get("tag") == "\"\"" %}
|
|
||||||
<!-- Individual Spool Item -->
|
|
||||||
<a href="{{ url_for('write_tag', spool_id=spool.id) }}"
|
|
||||||
class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
|
|
||||||
|
|
||||||
<!-- Left: Filament Color Badge -->
|
|
||||||
<div class="me-3">
|
|
||||||
<span class="badge d-inline-block"
|
|
||||||
style="background-color: #{{ spool.filament.color_hex }}; width: 20px; height: 50px;">
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Middle: Filament Details -->
|
|
||||||
<div class="flex-grow-1">
|
|
||||||
<!-- Vendor Name and Material (Row 1) -->
|
|
||||||
<h6 class="mb-0">{{ spool.filament.vendor.name }} - {{ spool.filament.material }}</h6>
|
|
||||||
<!-- Filament Name (Row 2) -->
|
|
||||||
<small class="text-muted">{{ spool.filament.name }}</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Action Icon -->
|
|
||||||
<span class="badge bg-primary rounded-pill">
|
|
||||||
<i class="bi bi-plus-circle"></i> Assign
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% for spool in spools %}
|
|
||||||
{% if spool.extra.get("tag") and spool.extra.get("tag") != "\"\"" %}
|
|
||||||
<!-- Individual Spool Item -->
|
|
||||||
<a href="{{ url_for('write_tag', spool_id=spool.id) }}"
|
|
||||||
class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
|
|
||||||
<!-- Left: Filament Color Badge -->
|
|
||||||
<div class="me-3">
|
|
||||||
<span class="badge d-inline-block"
|
|
||||||
style="background-color: #{{ spool.filament.color_hex }}; width: 20px; height: 50px;">
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Middle: Filament Details -->
|
|
||||||
<div class="flex-grow-1">
|
|
||||||
<!-- Vendor Name and Material (Row 1) -->
|
|
||||||
<h6 class="mb-0">{{ spool.filament.vendor.name }} - {{ spool.filament.material }}</h6>
|
|
||||||
<!-- Filament Name (Row 2) -->
|
|
||||||
<small class="text-muted">{{ spool.filament.name }}</small>
|
|
||||||
</div>
|
|
||||||
<!-- Action Icon -->
|
|
||||||
<span class="badge bg-secondary rounded-pill">
|
|
||||||
<i class="bi bi-plus-circle"></i> Reassign
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
7
templates/fill.html
Normal file
7
templates/fill.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Fill slot</h1>
|
||||||
|
<h2>AMS: {{ ams_id }}, Tray: {{ tray_id }}</h2>
|
||||||
|
{% with action_fill=True %}{% include 'fragments/list_spools.html' %}{% endwith %}
|
||||||
|
{% endblock %}
|
51
templates/fragments/list_spools.html
Normal file
51
templates/fragments/list_spools.html
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<!-- Empty State -->
|
||||||
|
{% if spools|length == 0 or not spools %}
|
||||||
|
<div class="alert alert-info text-center" role="alert">
|
||||||
|
No spools available to tag at the moment.
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
<!-- Spool List -->
|
||||||
|
<div class="list-group">
|
||||||
|
{% for spool in spools %}
|
||||||
|
<!-- Individual Spool Item -->
|
||||||
|
{% if action_fill %}<a href="{{ url_for('fill', spool_id=spool.id, ams=ams_id, tray=tray_id) }}"
|
||||||
|
class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">{% endif %}
|
||||||
|
{% if action_assign %}<a href="{{ url_for('write_tag', spool_id=spool.id) }}"
|
||||||
|
class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">{% endif %}
|
||||||
|
<!-- Left: Filament Color Badge -->
|
||||||
|
<div class="me-3">
|
||||||
|
<span class="badge d-inline-block"
|
||||||
|
style="background-color: #{{ spool.filament.color_hex }}; width: 20px; height: 50px;">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Middle: Filament Details -->
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<!-- Vendor Name and Material (Row 1) -->
|
||||||
|
<h6 class="mb-0">{{ spool.filament.vendor.name }} - {{ spool.filament.material }}</h6>
|
||||||
|
<!-- Filament Name (Row 2) -->
|
||||||
|
<small class="text-muted">{{ spool.filament.name }}</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if action_fill %}
|
||||||
|
<span class="badge bg-primary rounded-pill">
|
||||||
|
<i class="bi bi-plus-circle"></i> Fill
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if action_assign %}
|
||||||
|
<!-- Action Icon -->
|
||||||
|
{% if spool.extra.get("tag") or spool.extra.get("tag") == "\"\"" %}
|
||||||
|
<span class="badge bg-secondary rounded-pill">
|
||||||
|
<i class="bi bi-plus-circle"></i> Reassign
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-primary rounded-pill">
|
||||||
|
<i class="bi bi-plus-circle"></i> Assign
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if action_fill or action_assign %}</a>{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
57
templates/fragments/tray.html
Normal file
57
templates/fragments/tray.html
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<div class="card">
|
||||||
|
<!-- Tray ID -->
|
||||||
|
<div class="card-header d-flex justify-content-between align-items-center">
|
||||||
|
{% if tray_data.issue %}
|
||||||
|
<i class="bi bi-exclamation-circle text-danger me-2"></i>
|
||||||
|
{% endif %}
|
||||||
|
{% if not tray_data.tray_type %}
|
||||||
|
Empty
|
||||||
|
{% endif %}
|
||||||
|
Tray {{ tray_data.id }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
<!-- Tray Sub-Brand and Type -->
|
||||||
|
<div class="small text-muted mb-2">
|
||||||
|
{{ tray_data.tray_type }}
|
||||||
|
{% if tray_data.tray_sub_brands %}
|
||||||
|
<br/>
|
||||||
|
{{ tray_data.tray_sub_brands }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Badge with Dynamic Colors -->
|
||||||
|
<span class="badge d-inline-block p-2"
|
||||||
|
style="background-color: #{{ tray_data.tray_color }};
|
||||||
|
color: {% if color_is_dark(tray_data.tray_color) %}#FFFFFF{% else %}#000000{% endif %}">
|
||||||
|
#{{ tray_data.tray_color | upper }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- Remaining Percentage -->
|
||||||
|
<div class="mt-2">
|
||||||
|
Remaining:
|
||||||
|
{% if AUTO_SPEND and tray_data.matched %}
|
||||||
|
<span class="fw-bold">{{ tray_data.remaining_weight|round }}g</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="fw-bold">{{ tray_data.remain }}%</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
{% if pick_tray %}
|
||||||
|
<a class="btn btn-primary"
|
||||||
|
href="{{ url_for('tray_load', spool_id=current_spool['id'], tag_id=tag_id, ams=ams_id, tray=tray_id) }}">Pick
|
||||||
|
this tray</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if tray_data.issue %}
|
||||||
|
<a class="btn btn-primary"
|
||||||
|
href="{{ url_for('issue', ams=ams_id, tray=tray_id) }}">Fix
|
||||||
|
this tray</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if not pick_tray and not tray_data.tray_type %}
|
||||||
|
<a class="btn btn-primary"
|
||||||
|
href="{{ url_for('fill', ams=ams_id, tray=tray_id) }}">Fill
|
||||||
|
this tray</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">There is a mismatch between printer and SpoolMan</h5>
|
<h5 class="card-title">There is a mismatch between printer and SpoolMan</h5>
|
||||||
<p class="card-text">TODO: To fix the issue click on the tray with the red exclamation mark <i class="bi bi-exclamation-circle text-danger me-2"></i></p>
|
<p class="card-text">Fix issue by clicking "Fix this tray" on tray with <i class="bi bi-exclamation-circle text-danger me-2"></i></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -22,42 +22,7 @@
|
|||||||
<h5 class="mb-0">External Spool</h5>
|
<h5 class="mb-0">External Spool</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<!-- Tray ID -->
|
{% with tray_data=vt_tray_data, ams_id=EXTERNAL_SPOOL_AMS_ID, pick_tray=False, tray_id=vt_tray_data.id %} {% include 'fragments/tray.html' %} {% endwith %}
|
||||||
<h6 class="text-uppercase mb-1">
|
|
||||||
{% if vt_tray_data.issue %}
|
|
||||||
<i class="bi bi-exclamation-circle text-danger me-2"></i>
|
|
||||||
{% endif %}
|
|
||||||
{% if not vt_tray_data.tray_type %}
|
|
||||||
Empty
|
|
||||||
{% endif %}
|
|
||||||
Tray {{ vt_tray_data.id }}
|
|
||||||
</h6>
|
|
||||||
|
|
||||||
<!-- Tray Sub-Brand and Type -->
|
|
||||||
<div class="small text-muted mb-2">
|
|
||||||
{{ vt_tray_data.tray_type }}
|
|
||||||
{% if vt_tray_data.tray_sub_brands %}
|
|
||||||
<br/>
|
|
||||||
{{ vt_tray_data.tray_sub_brands }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Badge with Dynamic Colors -->
|
|
||||||
<span class="badge d-inline-block p-2"
|
|
||||||
style="background-color: #{{ vt_tray_data.tray_color }};
|
|
||||||
color: {% if color_is_dark(vt_tray_data.tray_color) %}#FFFFFF{% else %}#000000{% endif %}">
|
|
||||||
#{{ vt_tray_data.tray_color | upper }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<!-- Remaining Percentage -->
|
|
||||||
<div class="mt-2">
|
|
||||||
Remaining:
|
|
||||||
{% if AUTO_SPEND and vt_tray_data.matched %}
|
|
||||||
<span class="fw-bold">{{ vt_tray_data.remaining_weight|round }}g</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="fw-bold">{{ vt_tray_data.remain }}%</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -72,46 +37,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
{% for tray in ams.tray %}
|
{% for tray in ams.tray %}
|
||||||
<div class="col-6 mb-3">
|
<div class="col-6 mb-3">
|
||||||
<div class="border rounded p-2 text-center">
|
{% with tray_data=tray, ams_id=ams.id, pick_tray=False, tray_id=tray.id %} {% include 'fragments/tray.html' %} {% endwith %}
|
||||||
<!-- Tray ID -->
|
|
||||||
<h6 class="text-uppercase mb-1">
|
|
||||||
{% if tray.issue %}
|
|
||||||
<i class="bi bi-exclamation-circle text-danger me-2"></i>
|
|
||||||
{% endif %}
|
|
||||||
{% if not tray.tray_type %}
|
|
||||||
Empty
|
|
||||||
{% endif %}
|
|
||||||
Tray {{ tray.id }}
|
|
||||||
</h6>
|
|
||||||
|
|
||||||
<!-- Tray Sub-Brand and Type -->
|
|
||||||
<div class="small text-muted mb-2">
|
|
||||||
{{ tray.tray_type }}
|
|
||||||
{% if tray.tray_sub_brands %}
|
|
||||||
<br/>
|
|
||||||
{{ tray.tray_sub_brands }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if tray.tray_color %}
|
|
||||||
<!-- Badge with Dynamic Colors -->
|
|
||||||
<span class="badge d-inline-block p-2"
|
|
||||||
style="background-color: #{{ tray.tray_color }};
|
|
||||||
color: {% if color_is_dark(tray.tray_color) %}#FFFFFF{% else %}#000000{% endif %}">
|
|
||||||
#{{ tray.tray_color | upper }}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<!-- Remaining Percentage -->
|
|
||||||
<div class="mt-2">
|
|
||||||
Remaining:
|
|
||||||
{% if AUTO_SPEND and tray.matched %}
|
|
||||||
<span class="fw-bold">{{ tray.remaining_weight|round }}g</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="fw-bold">{{ tray.remain }}%</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
6
templates/issue.html
Normal file
6
templates/issue.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Solve issue</h1>
|
||||||
|
<h2>TBD</h2>
|
||||||
|
{% endblock %}
|
@ -46,42 +46,7 @@
|
|||||||
<h5 class="mb-0">External Spool</h5>
|
<h5 class="mb-0">External Spool</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<div class="card">
|
{% with tray_data=vt_tray_data, ams_id=EXTERNAL_SPOOL_AMS_ID, pick_tray=True, tray_id=vt_tray_data.id %} {% include 'fragments/tray.html' %} {% endwith %}
|
||||||
<!-- Tray ID -->
|
|
||||||
<div class="card-header d-flex justify-content-between align-items-center">
|
|
||||||
{% if vt_tray_data.issue %}
|
|
||||||
<i class="bi bi-exclamation-circle text-danger me-2"></i>
|
|
||||||
{% endif %}
|
|
||||||
{% if not vt_tray_data.tray_type %}
|
|
||||||
Empty
|
|
||||||
{% endif %}
|
|
||||||
Tray {{ vt_tray_data.id }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<!-- Tray Sub-Brand and Type -->
|
|
||||||
<div class="small text-muted mb-2">
|
|
||||||
{{ vt_tray_data.tray_type }}
|
|
||||||
{% if vt_tray_data.tray_sub_brands %}
|
|
||||||
<br/>
|
|
||||||
{{ vt_tray_data.tray_sub_brands }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Badge with Dynamic Colors -->
|
|
||||||
<span class="badge d-inline-block p-2"
|
|
||||||
style="background-color: #{{ vt_tray_data.tray_color }};
|
|
||||||
color: {% if color_is_dark(vt_tray_data.tray_color) %}#FFFFFF{% else %}#000000{% endif %}">
|
|
||||||
#{{ vt_tray_data.tray_color | upper }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<a class="btn btn-primary"
|
|
||||||
href="{{ url_for('tray_load', spool_id=current_spool['id'], tag_id=tag_id,ams=vt_tray_data['id'], tray='255') }}">Pick
|
|
||||||
this tray</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -96,43 +61,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
{% for tray in ams.tray %}
|
{% for tray in ams.tray %}
|
||||||
<div class="col-6 mb-3">
|
<div class="col-6 mb-3">
|
||||||
<div class="card">
|
{% with tray_data=tray, ams_id=ams.id, pick_tray=True, tray_id=tray.id %} {% include 'fragments/tray.html' %} {% endwith %}
|
||||||
<!-- Tray ID -->
|
|
||||||
<div class="card-header d-flex justify-content-between align-items-center">
|
|
||||||
{% if tray.issue %}
|
|
||||||
<i class="bi bi-exclamation-circle text-danger me-2"></i>
|
|
||||||
{% endif %}
|
|
||||||
{% if not tray.tray_type %}
|
|
||||||
Empty
|
|
||||||
{% endif %}
|
|
||||||
Tray {{ tray.id }}
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<!-- Tray Sub-Brand and Type -->
|
|
||||||
<div class="small text-muted mb-2">
|
|
||||||
{{ tray.tray_type }}
|
|
||||||
{% if tray.tray_sub_brands %}
|
|
||||||
<br/>
|
|
||||||
{{ tray.tray_sub_brands }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if tray.tray_color %}
|
|
||||||
<!-- Badge with Dynamic Colors -->
|
|
||||||
<span class="badge d-inline-block p-2"
|
|
||||||
style="background-color: #{{ tray.tray_color }};
|
|
||||||
color: {% if color_is_dark(tray.tray_color) %}#FFFFFF{% else %}#000000{% endif %}">
|
|
||||||
#{{ tray.tray_color | upper }}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<a class="btn btn-primary"
|
|
||||||
href="{{ url_for('tray_load', spool_id=current_spool['id'], tag_id=tag_id,ams=ams['id'], tray=tray['id']) }}">Pick
|
|
||||||
this tray</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user