Add device_type field, mobile-friendly improvements, and device filtering
- Device model: add device_type column (String 50, nullable) - Device add/edit: type select with presets + custom entry - Device detail: show type in info card; new Edit Device form - Device list: Type column + client-side filter bar (type + text search) - Mobile: card-style responsive tables on dashboard and device list, form-grid-2col collapse, larger tap targets, stacked form-actions, column picker viewport fix, filter bar full-width controls - Assign page: larger radio touch targets (min-height 44px) - 3 new acceptance tests for device_type (45 total)
This commit is contained in:
@@ -379,7 +379,8 @@ def create_app(config_object="config"):
|
||||
@app.route("/device/")
|
||||
def device_list():
|
||||
devices = db.query(Device).order_by(Device.name).all()
|
||||
return render_template("device_list.html", devices=devices)
|
||||
device_types = sorted({d.device_type for d in devices if d.device_type})
|
||||
return render_template("device_list.html", devices=devices, device_types=device_types)
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Devices — add
|
||||
@@ -387,14 +388,19 @@ def create_app(config_object="config"):
|
||||
|
||||
@app.route("/device/add", methods=["GET", "POST"])
|
||||
def device_add():
|
||||
all_devices = db.query(Device).all()
|
||||
device_types = sorted({d.device_type for d in all_devices if d.device_type})
|
||||
|
||||
if request.method == "POST":
|
||||
name = request.form.get("name", "").strip()
|
||||
slots_raw = request.form.get("battery_slots", "1").strip()
|
||||
notes = request.form.get("notes", "").strip() or None
|
||||
device_type = request.form.get("device_type", "").strip() or None
|
||||
|
||||
if not name:
|
||||
flash("Device name is required.", "error")
|
||||
return render_template("device_add.html"), 400
|
||||
return render_template("device_add.html",
|
||||
device_types=device_types), 400
|
||||
|
||||
try:
|
||||
slots = int(slots_raw)
|
||||
@@ -403,21 +409,25 @@ def create_app(config_object="config"):
|
||||
except ValueError:
|
||||
flash("Battery slots must be a positive integer.", "error")
|
||||
return render_template("device_add.html",
|
||||
form_name=name, form_notes=notes or ""), 400
|
||||
device_types=device_types,
|
||||
form_name=name, form_notes=notes or "",
|
||||
form_device_type=request.form.get("device_type", "")), 400
|
||||
|
||||
if db.query(Device).filter_by(name=name).first():
|
||||
flash(f"A device named '{name}' already exists.", "error")
|
||||
return render_template("device_add.html",
|
||||
device_types=device_types,
|
||||
form_name=name, form_slots=slots,
|
||||
form_notes=notes or ""), 400
|
||||
form_notes=notes or "",
|
||||
form_device_type=request.form.get("device_type", "")), 400
|
||||
|
||||
device = Device(name=name, battery_slots=slots, notes=notes)
|
||||
device = Device(name=name, battery_slots=slots, notes=notes, device_type=device_type)
|
||||
db.add(device)
|
||||
db.commit()
|
||||
flash(f"Device '{name}' added.", "success")
|
||||
return redirect(url_for("device_list"))
|
||||
|
||||
return render_template("device_add.html")
|
||||
return render_template("device_add.html", device_types=device_types)
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Devices — detail
|
||||
@@ -432,8 +442,47 @@ def create_app(config_object="config"):
|
||||
available_batteries = (db.query(Battery)
|
||||
.filter_by(status="available")
|
||||
.order_by(Battery.label).all())
|
||||
device_types = sorted({d.device_type for d in db.query(Device).all() if d.device_type})
|
||||
return render_template("device_detail.html", device=device, brands=brands,
|
||||
available_batteries=available_batteries)
|
||||
available_batteries=available_batteries,
|
||||
device_types=device_types)
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Devices — edit
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
@app.route("/device/<int:device_id>/edit", methods=["POST"])
|
||||
def device_edit(device_id):
|
||||
device = db.get(Device, device_id)
|
||||
if device is None:
|
||||
abort(404)
|
||||
name = request.form.get("name", "").strip()
|
||||
slots_raw = request.form.get("battery_slots", "1").strip()
|
||||
notes = request.form.get("notes", "").strip() or None
|
||||
device_type = request.form.get("device_type", "").strip() or None
|
||||
|
||||
if not name:
|
||||
flash("Device name is required.", "error")
|
||||
return redirect(url_for("device_detail", device_id=device_id))
|
||||
try:
|
||||
slots = int(slots_raw)
|
||||
if slots < 1:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
flash("Battery slots must be a positive integer.", "error")
|
||||
return redirect(url_for("device_detail", device_id=device_id))
|
||||
existing = db.query(Device).filter_by(name=name).first()
|
||||
if existing and existing.id != device_id:
|
||||
flash(f"A device named '{name}' already exists.", "error")
|
||||
return redirect(url_for("device_detail", device_id=device_id))
|
||||
|
||||
device.name = name
|
||||
device.battery_slots = slots
|
||||
device.notes = notes
|
||||
device.device_type = device_type
|
||||
db.commit()
|
||||
flash("Device updated.", "success")
|
||||
return redirect(url_for("device_detail", device_id=device_id))
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Devices — install batteries
|
||||
|
||||
Reference in New Issue
Block a user