dashboard: printer rows are a name and its cartridges, with the answer on hover
Some checks failed
CI / backend (push) Failing after 8s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 9s
CI / migrations-mysql (push) Failing after 7s

The printer card was a name followed by a comma-joined string of cartridges and
a location - the widest row on the board, and the one running past the card
edge.

Now: the printer name links to its page and reveals its location on hover, and
each depleted cartridge is its own chip showing "Black 4%", revealing the part
number to order on hover. The percentage says something is wrong; the part
number says what to do about it, which today means opening the printer's page
to find out. Every capacity tier is listed, as the report has always done.

Two additions to the card contract, both general: 'chips' maps a row key to a
list of {text, title, level}, and 'titletooltip' puts context on the row title.
Nothing load-bearing goes in a tooltip - hover is not discoverable and does not
exist on touch - so a chip always states the fact and only explains it on hover.

Chips are bordered rather than filled: a row of solid red pills reads as an
emergency even when a cartridge is merely low.

Also repaired a self-inflicted mess. A string-slice edit used a marker that
appears EARLIER in the file, so the slice was empty and two helpers were
injected at line 1, above the module docstring. Removed; the file parses and
the helpers live beside the route they serve.
This commit is contained in:
cproudlock
2026-08-11 15:46:21 -04:00
parent c34815b87e
commit 8623db3ee2
5 changed files with 119 additions and 16 deletions

View File

@@ -1407,6 +1407,24 @@ def _shortsupplyname(name):
return text or 'supply'
def _reordertip(supply):
"""What to order, for the chip's tooltip.
A percentage says a cartridge is nearly out; the part number says what to
buy, which is the next thing someone needs and today means opening the
printer's page to find it. Every capacity tier is listed, because the
report has always shown all reorder options.
"""
parts = supply.get('partnumbers') or []
if not parts:
return 'No part number on file for this model'
return ', '.join(
'{}{}'.format(part['partnumber'],
' ({})'.format(part['capacitytier'])
if part.get('capacitytier') else '')
for part in parts)
@printers_asset_bp.route('/dashboard/supplies', methods=['GET'])
@jwt_required()
@require_permission('printers.view')
@@ -1429,22 +1447,21 @@ def dashboard_supplies():
lows = [s for s in printer['supplies'] if s['status'] == 'low']
if not criticals and not lows:
continue
# Every depleted supply, criticals first. Listing only the worst class
# would hide a low cartridge behind a critical one on the same printer,
# and whoever walks out there wants to carry both.
worst = criticals + lows
# Criticals first. Every depleted supply is listed, not just the worst
# class - whoever walks out there wants to carry both cartridges.
rows.append({
'printerid': printer['printerid'],
'printername': printer['printername'] or printer['assetnumber'],
'location': printer['location'],
'status': 'critical' if criticals else 'low',
# 'remaining' is the percent left. There is no 'percent' key -
# reading one rendered every cartridge as "None%" on the board.
'supplies': ', '.join(
'{} {}%'.format(_shortsupplyname(s.get('name')),
s.get('remaining'))
for s in worst),
'location': printer['location'] or 'No location set',
'iscritical': bool(criticals),
# One chip per depleted supply: what is low, and on hover what to
# order to fix it.
'supplies': [{
'text': '{} {}%'.format(_shortsupplyname(supply.get('name')),
supply.get('remaining')),
'title': _reordertip(supply),
'level': supply.get('status'),
} for supply in criticals + lows],
})
rows.sort(key=lambda r: (not r['iscritical'], r['printername']))

View File

@@ -306,8 +306,11 @@ class PrintersPlugin(BasePlugin):
'position': 40,
'map': {
'title': 'printername',
'detail': 'supplies',
'meta': [{'key': 'location'}, {'key': 'status'}],
# Location on hover rather than on the line: it is context
# for "where do I walk", not part of the finding, and it
# was the text pushing rows past the card edge.
'titletooltip': 'location',
'chips': 'supplies',
'link': '/printers/{printerid}',
},
},