Devices is_active + Table

This commit is contained in:
2025-09-29 17:54:03 +00:00
parent 4a093c1317
commit b465bd9c54
5 changed files with 119 additions and 41 deletions

View File

@@ -47,7 +47,7 @@ def get_devices():
Liefert eine Liste aller Devices aus der Datenbank als Dictionaries. Liefert eine Liste aller Devices aus der Datenbank als Dictionaries.
""" """
conn = get_db_connection() conn = get_db_connection()
devices = conn.execute("SELECT mac, rpi_ip, port, name, switch_hostname FROM devices").fetchall() devices = conn.execute("SELECT mac, rpi_ip, port, name, switch_hostname, is_active FROM devices").fetchall()
conn.close() conn.close()
return devices return devices
@@ -150,14 +150,19 @@ def devices():
if not current_user.is_admin: if not current_user.is_admin:
flash("Zugriff verweigert!") flash("Zugriff verweigert!")
return redirect(url_for('devices')) return redirect(url_for('devices'))
mac = request.form['mac'] mac = request.form['mac']
rpi_ip = request.form['rpi_ip'] rpi_ip = request.form['rpi_ip']
port = request.form['port'] port = request.form['port']
name = request.form['name'] name = request.form['name']
switch_hostname = request.form['switch_hostname'] switch_hostname = request.form['switch_hostname']
is_active = 1 if 'is_active' in request.form else 0
try: try:
conn.execute("INSERT INTO devices (mac, rpi_ip, port, name, switch_hostname) VALUES (?, ?, ?, ?, ?)", conn.execute("""
(mac, rpi_ip, port, name, switch_hostname)) INSERT INTO devices (mac, rpi_ip, port, name, switch_hostname, is_active)
VALUES (?, ?, ?, ?, ?, ?)
""", (mac, rpi_ip, port, name, switch_hostname, is_active))
conn.commit() conn.commit()
flash(f"Gerät {name} hinzugefügt.") flash(f"Gerät {name} hinzugefügt.")
except sqlite3.IntegrityError: except sqlite3.IntegrityError:
@@ -168,18 +173,21 @@ def devices():
if not current_user.is_admin: if not current_user.is_admin:
flash("Zugriff verweigert!") flash("Zugriff verweigert!")
return redirect(url_for('devices')) return redirect(url_for('devices'))
old_mac = request.form['old_mac'] old_mac = request.form['old_mac']
mac = request.form['mac'] mac = request.form['mac']
rpi_ip = request.form['rpi_ip'] rpi_ip = request.form['rpi_ip']
port = request.form['port'] port = request.form['port']
name = request.form['name'] name = request.form['name']
switch_hostname = request.form['switch_hostname'] switch_hostname = request.form['switch_hostname']
is_active = 1 if 'is_active' in request.form else 0
try: try:
conn.execute(""" conn.execute("""
UPDATE devices UPDATE devices
SET mac=?, rpi_ip=?, port=?, name=?, switch_hostname=? SET mac=?, rpi_ip=?, port=?, name=?, switch_hostname=?, is_active=?
WHERE mac=? WHERE mac=?
""", (mac, rpi_ip, port, name, switch_hostname, old_mac)) """, (mac, rpi_ip, port, name, switch_hostname, is_active, old_mac))
conn.commit() conn.commit()
flash(f"Gerät {name} aktualisiert.") flash(f"Gerät {name} aktualisiert.")
except sqlite3.IntegrityError: except sqlite3.IntegrityError:
@@ -196,10 +204,12 @@ def devices():
flash(f"Gerät {del_mac} gelöscht.") flash(f"Gerät {del_mac} gelöscht.")
devices = conn.execute(""" devices = conn.execute("""
SELECT devices.mac, devices.rpi_ip, devices.port, devices.name, switches.hostname AS switch_hostname SELECT devices.mac, devices.rpi_ip, devices.port, devices.name, devices.is_active,
switches.hostname AS switch_hostname
FROM devices FROM devices
JOIN switches ON devices.switch_hostname = switches.hostname JOIN switches ON devices.switch_hostname = switches.hostname
""").fetchall() """).fetchall()
conn.close() conn.close()
interval_min = get_interval_seconds() // 60 interval_min = get_interval_seconds() // 60
return render_template('devices.html', devices=devices, switches=switches) return render_template('devices.html', devices=devices, switches=switches)

View File

@@ -11,8 +11,16 @@ def generate_ips_list():
# Alle Switches laden # Alle Switches laden
switches = {row['hostname']: row for row in conn.execute("SELECT hostname, ip, username, password FROM switches")} switches = {row['hostname']: row for row in conn.execute("SELECT hostname, ip, username, password FROM switches")}
# Alle Geräte laden # # Alle Geräte laden
devices = conn.execute("SELECT mac, rpi_ip, port, name, switch_hostname FROM devices").fetchall() # devices = conn.execute("SELECT mac, rpi_ip, port, name, switch_hostname FROM devices").fetchall()
# conn.close()
# Nur aktive Geräte laden
devices = conn.execute("""
SELECT mac, rpi_ip, port, name, switch_hostname
FROM devices
WHERE is_active=1
""").fetchall()
conn.close() conn.close()
tmp = tempfile.NamedTemporaryFile(delete=False, mode='w', prefix='ips_', suffix='.list') tmp = tempfile.NamedTemporaryFile(delete=False, mode='w', prefix='ips_', suffix='.list')

Binary file not shown.

View File

@@ -53,7 +53,7 @@ pre {
} }
.content-wrapper { .content-wrapper {
max-width: 1024px; max-width: 1080px;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
} }
@@ -102,3 +102,50 @@ pre {
font-size: 0.9em; font-size: 0.9em;
color: gray; color: gray;
} }
/* Tabelle anpassen */
.custom-table input,
.custom-table select {
height: 28px;
padding: 0.25rem 0.5rem;
font-size: 0.9rem;
}
/* Spaltenbreiten */
.custom-table .col-small {
width: 100px; /* Hostname, Port */
}
.custom-table .col-ip {
width: 120px; /* IP-Adresse schmaler */
}
.custom-table .col-mac {
width: 120px; /* MAC-Adresse schmaler */
}
/* Checkbox sichtbar auch bei disabled */
.checkbox-visible:disabled {
opacity: 1; /* nicht ausgegraut */
cursor: not-allowed;
}
/* Aktiv-Label für Neues Gerät */
label.text-white {
color: white !important;
}
.checkbox-visible:not(:checked) {
accent-color: #dc3545; /* rot wenn unchecked */
}
.checkbox-visible:disabled {
cursor: not-allowed;
opacity: 1; /* verhindert Ausgrauen */
}
.custom-actions {
gap: 0.5rem; /* horizontaler Abstand zwischen Buttons */
margin: auto 0;
background: #fff;
}

View File

@@ -3,22 +3,14 @@
<h2>Devices</h2> <h2>Devices</h2>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="mt-2 alert alert-info">
{% for message in messages %}{{ message }}<br>{% endfor %}
</div>
{% endif %}
{% endwith %}
{% if current_user.is_admin %} {% if current_user.is_admin %}
<h4>Neues Gerät hinzufügen</h4> <h4>Neues Gerät hinzufügen</h4>
<form method="post" class="row g-2 mb-4"> <form method="post" class="row g-2 mb-4">
<input type="hidden" name="add_device" value="1"> <input type="hidden" name="add_device" value="1">
<div class="col"><input type="text" name="name" placeholder="Hostname" class="form-control" required></div> <div class="col col-small"><input type="text" name="name" placeholder="Hostname" class="form-control" required></div>
<div class="col"><input type="text" name="rpi_ip" placeholder="IP-Adresse" class="form-control" required></div> <div class="col col-ip"><input type="text" name="rpi_ip" placeholder="IP-Adresse" class="form-control" required></div>
<div class="col"><input type="text" name="mac" placeholder="MAC-Adresse" class="form-control" required></div> <div class="col col-mac"><input type="text" name="mac" placeholder="MAC-Adresse" class="form-control" required></div>
<div class="col"><input type="text" name="port" placeholder="Port" class="form-control" required></div> <div class="col col-small"><input type="text" name="port" placeholder="Port" class="form-control" required></div>
<div class="col"> <div class="col">
<select name="switch_hostname" class="form-control" required> <select name="switch_hostname" class="form-control" required>
<option value="">Switch wählen</option> <option value="">Switch wählen</option>
@@ -27,33 +19,44 @@
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
<div class="col d-flex align-items-center">
<input type="checkbox" name="is_active" value="1" checked id="new_is_active">
<label for="new_is_active" class="ms-2 mb-0 text-white">Aktiv</label>
</div>
<div class="col"><button class="btn btn-success w-100">Hinzufügen</button></div> <div class="col"><button class="btn btn-success w-100">Hinzufügen</button></div>
</form> </form>
{% endif %} {% endif %}
<table class="table table-bordered"> <table class="table table-bordered custom-table">
<thead> <thead>
<tr> <tr>
<th>Hostname</th> <th class="col-small">Hostname</th>
<th>IP-Adresse</th> <th class="col-ip">IP-Adresse</th>
<th>MAC-Adresse</th> <th class="col-mac">MAC-Adresse</th>
<th>Switch</th> <th>Switch</th>
<th>Port</th> <th class="col-small">Port</th>
<th>Aktiv</th>
{% if current_user.is_admin %}<th>Aktionen</th>{% endif %} {% if current_user.is_admin %}<th>Aktionen</th>{% endif %}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for d in devices %} {% for d in devices %}
<tr> <tr>
{% if current_user.is_admin %}
<form method="post"> <form method="post">
<input type="hidden" name="edit_device" value="1"> <input type="hidden" name="edit_device" value="1">
<input type="hidden" name="old_mac" value="{{ d['mac'] }}"> <input type="hidden" name="old_mac" value="{{ d['mac'] }}">
<td><input name="name" value="{{ d['name'] }}" class="form-control" required></td>
<td><input name="rpi_ip" value="{{ d['rpi_ip'] }}" class="form-control" required></td> <td class="col-small">
<td><input name="mac" value="{{ d['mac'] }}" class="form-control" required></td> <input name="name" value="{{ d['name'] }}" class="form-control" required disabled>
</td>
<td class="col-ip">
<input name="rpi_ip" value="{{ d['rpi_ip'] }}" class="form-control" required disabled>
</td>
<td class="col-mac">
<input name="mac" value="{{ d['mac'] }}" class="form-control" required disabled>
</td>
<td> <td>
<select name="switch_hostname" class="form-control" required> <select name="switch_hostname" class="form-control" disabled required>
{% for sw in switches %} {% for sw in switches %}
<option value="{{ sw['hostname'] }}" {% if sw['hostname']==d['switch_hostname'] %}selected{% endif %}> <option value="{{ sw['hostname'] }}" {% if sw['hostname']==d['switch_hostname'] %}selected{% endif %}>
{{ sw['hostname'] }} {{ sw['hostname'] }}
@@ -61,23 +64,33 @@
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
<td><input name="port" value="{{ d['port'] }}" class="form-control" required></td> <td class="col-small">
<td class="d-flex gap-1"> <input name="port" value="{{ d['port'] }}" class="form-control" required disabled>
<button class="btn btn-primary btn-sm">Speichern</button> </td>
<td class="custom-checkbox">
<input type="checkbox" name="is_active" value="1" {% if d['is_active'] %}checked{% endif %} disabled class="checkbox-visible">
</td>
{% if current_user.is_admin %}
<td class="custom-actions">
<button type="button" class="btn btn-warning btn-sm" onclick="enableEdit(this)">Bearbeiten</button>
<button type="submit" class="btn btn-primary btn-sm d-none">Speichern</button>
<button name="delete_device" value="{{ d['mac'] }}" class="btn btn-danger btn-sm" <button name="delete_device" value="{{ d['mac'] }}" class="btn btn-danger btn-sm"
onclick="return confirm('Willst du das Gerät wirklich löschen?');">Löschen</button> onclick="return confirm('Willst du das Gerät wirklich löschen?');">Löschen</button>
</td> </td>
{% endif %}
</form> </form>
{% else %}
<td>{{ d['name'] }}</td>
<td>{{ d['rpi_ip'] }}</td>
<td>{{ d['mac'] }}</td>
<td>{{ d['switch_hostname'] }}</td>
<td>{{ d['port'] }}</td>
{% endif %}
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<script>
function enableEdit(btn) {
const row = btn.closest('tr');
row.querySelectorAll('input, select').forEach(el => el.disabled = false); // Inputs aktivieren
btn.classList.add('d-none'); // Bearbeiten ausblenden
row.querySelector('button.btn-primary').classList.remove('d-none'); // Speichern sichtbar
}
</script>
{% endblock %} {% endblock %}