feat(11-01): UIE-02 — dedicated Add Printer page at GET /printers/new
- Create imptune/templates/printers_new.html: full page extending base.html
with plain <form action="/printers" method="post"> (no HTMX, browser follows 303)
and inline driver upload sub-form
- Update imptune/templates/printers.html: remove inline Add Printer form,
add <a href="/printers/new" role="button">Add Printer</a> link
- Add GET /printers/new route in imptune/api/pages.py (placed before /{printer_id})
- Change POST /printers to always return RedirectResponse(url='/printers', status_code=303)
- Update existing POST /printers tests to assert 303 + follow_redirects=False
- Update test_printer_form.py to check /printers/new instead of /printers (UIE-02 arch)
- UIE-02 tests GREEN; UIE-01/03 scaffolds remain RED (expected — not yet implemented)
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Add Printer</h1>
|
||||
|
||||
<p><a href="/printers">← Back to Printer Library</a></p>
|
||||
|
||||
<div x-data="{ ip: '', port: '', portEdited: false }">
|
||||
<form action="/printers" method="post">
|
||||
|
||||
<label>
|
||||
Printer Name
|
||||
<input type="text" name="name" placeholder="e.g. HP LaserJet 4050" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
IP Address
|
||||
<input type="text" name="ip_address"
|
||||
x-model="ip"
|
||||
@input="if (!portEdited) port = 'IP_' + ip.replaceAll('.', '_')"
|
||||
placeholder="e.g. 192.168.1.100"
|
||||
required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Port Name
|
||||
<input type="text" name="port_name"
|
||||
x-model="port"
|
||||
@change="portEdited = true"
|
||||
@keydown="portEdited = true"
|
||||
placeholder="e.g. IP_192_168_1_100">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Driver
|
||||
<select name="driver_id" id="printer-form-driver-select">
|
||||
<option value="">-- No driver --</option>
|
||||
{% for item in driver_data %}
|
||||
<option value="{{ item.driver.id }}">
|
||||
{{ item.driver.original_filename }} ({{ item.names | join(', ') }})
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Duplex Mode
|
||||
<select name="duplex_mode">
|
||||
<option value="OneSided" selected>One-Sided</option>
|
||||
<option value="LongEdge">Long Edge</option>
|
||||
<option value="ShortEdge">Short Edge</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input type="checkbox" name="color_mode" value="on" checked>
|
||||
Color Mode
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Paper Size
|
||||
<select name="paper_size">
|
||||
<option value="A4" selected>A4</option>
|
||||
<option value="Letter">Letter</option>
|
||||
<option value="Legal">Legal</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input type="checkbox" name="collate" value="on" checked>
|
||||
Collate
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Client
|
||||
<select name="client_id">
|
||||
<option value="">-- Unassigned --</option>
|
||||
{% for c in clients %}
|
||||
<option value="{{ c.id }}">{{ c.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<button type="submit">Save Printer</button>
|
||||
</form>
|
||||
|
||||
<form hx-post="/drivers/upload"
|
||||
hx-target="#driver-list"
|
||||
hx-encoding="multipart/form-data"
|
||||
hx-swap="outerHTML">
|
||||
<input type="hidden" name="caller" value="printer_form">
|
||||
<label>
|
||||
Upload New Driver
|
||||
<input type="file" name="file" accept=".zip" required>
|
||||
</label>
|
||||
<button type="submit" class="secondary">Upload Driver</button>
|
||||
</form>
|
||||
<div id="driver-list" style="display:none"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user