dashboard: tighten the printer, warranty and notification cards
Some checks failed
CI / backend (push) Failing after 8s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 8s
CI / migrations-mysql (push) Failing after 7s

PRINTER CARD is now supplies at or below 5 percent, a new
printers_dashboardpercent setting. The report and the card want different
scopes: the report lists anything the thresholds call low, which is right for
planning an order, while the dashboard is asking what to walk out and change
today - and a cartridge at 18 percent is not that. Lowest first.

PRINTER LOCATION WAS ALWAYS EMPTY. The lookup went through db.session.get on
locationid and produced nothing even where a location is set; the printers list
has always read it through the asset relationship, so the card does too now.

WARRANTY ROWS are identified the way the floor identifies them: the PC's
hostname and the MACHINE it drives, reusing the same lookup behind the warranty
page's machine column so the board and the report cannot disagree about which
bay a PC belongs to. No dates - expired or expiring is the whole decision when
scanning a board, and the exact day belongs on the report you order from.

NOTIFICATIONS are stacked: the type in full on one line, the message beneath,
trimmed to 100 characters with the rest on hover. Inline, the type was
truncated to make room for prose that was then truncated anyway, and neither
read. A tooltip is omitted when the text was not trimmed, because one repeating
what is already on screen is noise.

Two general additions: layout: 'stacked' on a card, and map.detailtooltip.
This commit is contained in:
cproudlock
2026-08-11 15:57:14 -04:00
parent 8623db3ee2
commit 42c050a9f4
9 changed files with 134 additions and 38 deletions

View File

@@ -1020,12 +1020,11 @@ def _get_low_supplies_data():
if has_low:
# location name for the report row
location_name = None
if asset.locationid:
from shopdb.api import Location
loc = db.session.get(Location, asset.locationid)
if loc:
location_name = loc.locationname
# Via the relationship, the way the printers list does it. The
# previous lookup went through db.session.get on locationid, and
# every row came back with no location even where one is set.
location_name = (asset.location.locationname
if asset.location else None)
results.append({
'printerid': printer.printerid,
@@ -1441,27 +1440,37 @@ def dashboard_supplies():
"""
data = _get_low_supplies_data()
threshold = 5
setting = Setting.query.filter_by(key='printers_dashboardpercent').first()
if setting and (setting.value or '').strip():
try:
threshold = int(setting.value)
except (TypeError, ValueError):
pass
rows = []
for printer in data.get('printers', []):
criticals = [s for s in printer['supplies'] if s['status'] == 'critical']
lows = [s for s in printer['supplies'] if s['status'] == 'low']
if not criticals and not lows:
# The CARD is tighter than the report. The report lists anything the
# thresholds call low, which is the right scope for planning an order;
# the dashboard is asking what to walk out and change today, and a
# cartridge at 18% is not that. Anything at or below the threshold.
depleted = [supply for supply in printer['supplies']
if isinstance(supply.get('remaining'), (int, float))
and supply['remaining'] <= threshold]
if not depleted:
continue
# Criticals first. Every depleted supply is listed, not just the worst
# class - whoever walks out there wants to carry both cartridges.
depleted.sort(key=lambda supply: supply['remaining'])
rows.append({
'printerid': printer['printerid'],
'printername': printer['printername'] or printer['assetnumber'],
'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.
'iscritical': any(s['status'] == 'critical' for s in depleted),
'supplies': [{
'text': '{} {}%'.format(_shortsupplyname(supply.get('name')),
supply.get('remaining')),
'title': _reordertip(supply),
'level': supply.get('status'),
} for supply in criticals + lows],
} for supply in depleted],
})
rows.sort(key=lambda r: (not r['iscritical'], r['printername']))