Add bulk set field (Storage Location, Brand) to dashboard toolbar
Select batteries, choose field and value from toolbar, hit Apply. Storage Location dropdown populated from existing locations.
This commit is contained in:
@@ -28,7 +28,13 @@ def create_app(config_object="config"):
|
||||
@app.route("/")
|
||||
def dashboard():
|
||||
batteries = db.query(Battery).order_by(Battery.label).all()
|
||||
return render_template("dashboard.html", batteries=batteries)
|
||||
storage_locations = [
|
||||
r[0] for r in db.query(Battery.storage_location)
|
||||
.filter(Battery.storage_location.isnot(None))
|
||||
.distinct().order_by(Battery.storage_location).all()
|
||||
]
|
||||
return render_template("dashboard.html", batteries=batteries,
|
||||
storage_locations=storage_locations)
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Battery — add
|
||||
@@ -278,6 +284,21 @@ def create_app(config_object="config"):
|
||||
b.brand = new_brand
|
||||
db.commit()
|
||||
flash(f"Updated brand to '{new_brand}' for {n} batter{'y' if n == 1 else 'ies'}.", "success")
|
||||
elif action == "set_field":
|
||||
field_name = request.form.get("field_name", "").strip()
|
||||
field_value = request.form.get("field_value", "").strip() or None
|
||||
allowed = {"brand", "storage_location"}
|
||||
if field_name not in allowed:
|
||||
flash("Invalid field.", "error")
|
||||
return redirect(url_for("dashboard"))
|
||||
if field_name == "brand" and not field_value:
|
||||
flash("Brand name is required.", "error")
|
||||
return redirect(url_for("dashboard"))
|
||||
for b in batteries:
|
||||
setattr(b, field_name, field_value)
|
||||
db.commit()
|
||||
label = field_name.replace("_", " ").title()
|
||||
flash(f"Set {label} on {n} batter{'y' if n == 1 else 'ies'}.", "success")
|
||||
else:
|
||||
flash("Unknown action.", "error")
|
||||
|
||||
|
||||
@@ -37,10 +37,36 @@
|
||||
<button class="btn btn-sm btn-secondary" name="action" value="retire" type="submit">Retire</button>
|
||||
<button class="btn btn-sm btn-danger" name="action" value="delete" type="submit"
|
||||
onclick="return confirm('Permanently delete selected batteries?')">Delete</button>
|
||||
<span style="display:flex;gap:0.35rem;align-items:center;">
|
||||
<input type="text" name="new_brand" id="new-brand-input" placeholder="New brand name"
|
||||
style="padding:0.25rem 0.5rem;font-size:0.85rem;border:1px solid #cbd5e1;border-radius:4px;width:160px;">
|
||||
<button class="btn btn-sm btn-primary" name="action" value="set_brand" type="submit">Change Brand</button>
|
||||
<span style="display:flex;gap:0.35rem;align-items:center;flex-wrap:wrap;">
|
||||
<input type="hidden" name="field_name" id="bulk-field-name" value="storage_location">
|
||||
<select id="bulk-field-select" onchange="updateBulkField(this)"
|
||||
style="padding:0.25rem 0.5rem;font-size:0.85rem;border:1px solid #cbd5e1;border-radius:4px;">
|
||||
<option value="storage_location">Storage Location</option>
|
||||
<option value="brand">Brand</option>
|
||||
</select>
|
||||
<!-- Storage Location value -->
|
||||
<span id="bulk-val-storage_location" style="display:flex;gap:0.25rem;align-items:center;">
|
||||
<select id="bulk-storage-select" onchange="bulkStorageChanged(this)"
|
||||
style="padding:0.25rem 0.5rem;font-size:0.85rem;border:1px solid #cbd5e1;border-radius:4px;">
|
||||
<option value="">— select —</option>
|
||||
{% for loc in storage_locations|default([]) %}
|
||||
<option value="{{ loc }}">{{ loc }}</option>
|
||||
{% endfor %}
|
||||
<option value="__new__">➕ New location…</option>
|
||||
</select>
|
||||
<input type="text" id="bulk-storage-text"
|
||||
style="display:none;padding:0.25rem 0.5rem;font-size:0.85rem;border:1px solid #cbd5e1;border-radius:4px;width:140px;"
|
||||
placeholder="Type location">
|
||||
<input type="hidden" name="field_value" id="bulk-field-value-storage" value="">
|
||||
</span>
|
||||
<!-- Brand value -->
|
||||
<span id="bulk-val-brand" style="display:none;">
|
||||
<input type="text" id="bulk-brand-text" oninput="document.getElementById('bulk-field-value-brand').value=this.value"
|
||||
style="padding:0.25rem 0.5rem;font-size:0.85rem;border:1px solid #cbd5e1;border-radius:4px;width:160px;"
|
||||
placeholder="New brand name">
|
||||
<input type="hidden" name="field_value" id="bulk-field-value-brand" value="">
|
||||
</span>
|
||||
<button class="btn btn-sm btn-primary" name="action" value="set_field" type="submit">Apply</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -127,5 +153,31 @@
|
||||
updateToolbar();
|
||||
});
|
||||
}());
|
||||
|
||||
function updateBulkField(sel) {
|
||||
var field = sel.value;
|
||||
document.getElementById('bulk-field-name').value = field;
|
||||
document.getElementById('bulk-val-storage_location').style.display = field === 'storage_location' ? 'flex' : 'none';
|
||||
document.getElementById('bulk-val-brand').style.display = field === 'brand' ? 'flex' : 'none';
|
||||
document.getElementById('bulk-field-value-storage').disabled = (field !== 'storage_location');
|
||||
document.getElementById('bulk-field-value-brand').disabled = (field !== 'brand');
|
||||
}
|
||||
// initialise disabled state on page load
|
||||
document.getElementById('bulk-field-value-brand').disabled = true;
|
||||
|
||||
function bulkStorageChanged(sel) {
|
||||
var text = document.getElementById('bulk-storage-text');
|
||||
var hidden = document.getElementById('bulk-field-value-storage');
|
||||
if (sel.value === '__new__') {
|
||||
text.style.display = '';
|
||||
text.value = '';
|
||||
text.oninput = function() { hidden.value = text.value; };
|
||||
text.focus();
|
||||
hidden.value = '';
|
||||
} else {
|
||||
text.style.display = 'none';
|
||||
hidden.value = sel.value;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user