Webinterface

This commit is contained in:
2025-09-26 15:22:31 +00:00
parent e99e17be3b
commit 70d30e95fb
9 changed files with 280 additions and 0 deletions

1
.gitignore vendored
View File

@@ -29,6 +29,7 @@ __pycache__/
!/srv/
!/srv/poe_manager/
!/srv/poe_manager/*
!/srv/poe_manager/*/*
# Optional: SQLite DB ignorieren (falls du nicht willst, dass Passwörter im Repo landen)
# /srv/poe_manager/sqlite.db

View File

@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html>
<head>
<title>Devices</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
</head>
<body class="p-5">
<h2>Devices</h2>
<a href="{{ url_for('index') }}" class="btn btn-secondary mb-3">Zurück zum Dashboard</a>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="mt-2 alert alert-info">
{% for message in messages %}{{ message }}<br>{% endfor %}
</div>
{% endif %}
{% endwith %}
<p>Prüfintervall: <strong>{{ interval }} Minuten</strong></p>
{% if current_user.is_admin %}
<!-- Inline-Add Form -->
<h4>Neues Gerät hinzufügen</h4>
<form method="post" class="row g-2 mb-4">
<input type="hidden" name="add_device" value="1">
<div class="col"><input type="text" name="mac" placeholder="MAC" class="form-control" required></div>
<div class="col"><input type="text" name="rpi_ip" placeholder="RPI IP" class="form-control" required></div>
<div class="col"><input type="text" name="port" placeholder="Port" class="form-control" required></div>
<div class="col"><input type="text" name="name" placeholder="Name" class="form-control" required></div>
<div class="col">
<select name="switch_hostname" class="form-control" required>
<option value="">Switch wählen</option>
{% for sw in switches %}
<option value="{{ sw['hostname'] }}">{{ sw['hostname'] }}</option>
{% endfor %}
</select>
</div>
<div class="col"><button class="btn btn-success w-100">Hinzufügen</button></div>
</form>
{% endif %}
<!-- Devices Table -->
<table class="table table-bordered">
<thead>
<tr>
<th>MAC</th>
<th>RPI IP</th>
<th>Port</th>
<th>Name</th>
<th>Switch</th>
{% if current_user.is_admin %}<th>Aktionen</th>{% endif %}
</tr>
</thead>
<tbody>
{% for d in devices %}
<tr>
{% if current_user.is_admin %}
<!-- Inline-Edit Form -->
<form method="post">
<input type="hidden" name="edit_device" value="1">
<input type="hidden" name="old_mac" value="{{ d['mac'] }}">
<td><input name="mac" value="{{ d['mac'] }}" class="form-control" required></td>
<td><input name="rpi_ip" value="{{ d['rpi_ip'] }}" class="form-control" required></td>
<td><input name="port" value="{{ d['port'] }}" class="form-control" required></td>
<td><input name="name" value="{{ d['name'] }}" class="form-control" required></td>
<td>
<select name="switch_hostname" class="form-control" required>
{% for sw in switches %}
<option value="{{ sw['hostname'] }}" {% if sw['hostname']==d['switch_hostname'] %}selected{% endif %}>
{{ sw['hostname'] }}
</option>
{% endfor %}
</select>
</td>
<td class="d-flex gap-1">
<button class="btn btn-primary btn-sm">Speichern</button>
<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>
</td>
</form>
{% else %}
<td>{{ d['mac'] }}</td>
<td>{{ d['rpi_ip'] }}</td>
<td>{{ d['port'] }}</td>
<td>{{ d['name'] }}</td>
<td>{{ d['switch_hostname'] }}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

View File

@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>Device Dashboard</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<style>
.device-card {
width: 150px;
margin: 5px;
text-align: center;
}
.status-badge {
font-size: 0.9rem;
margin-top: 5px;
}
</style>
</head>
<body class="p-3">
<h2>Device Dashboard</h2>
<div class="mb-3">
<a href="{{ url_for('logs') }}" class="btn btn-primary">Live Log</a>
<a href="{{ url_for('devices') }}" class="btn btn-secondary">Devices verwalten</a>
<a href="{{ url_for('switches') }}" class="btn btn-secondary">Switches verwalten</a>
<a href="{{ url_for('settings') }}" class="btn btn-warning">Einstellungen</a>
</div>
<p>Prüfintervall: <strong>{{ interval }} Minuten</strong></p>
<div class="d-flex flex-wrap">
{% for d in devices %}
<div class="card device-card">
<div class="card-body">
<h6 class="card-title">{{ d['name'] }}</h6>
{% if status[d['name']] == 'online' %}
<span class="badge bg-success status-badge">Online</span>
{% else %}
<span class="badge bg-danger status-badge">Offline</span>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</body>
</html>

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
</head>
<body class="p-5">
<h2>Login</h2>
<form method="post">
<input class="form-control mb-2" name="username" placeholder="Benutzername" required>
<input type="password" class="form-control mb-2" name="password" placeholder="Passwort" required>
<button class="btn btn-primary">Login</button>
</form>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="mt-2 alert alert-danger">{{ messages[0] }}</div>
{% endif %}
{% endwith %}
</body>
</html>

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title>Live Log</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<meta http-equiv="refresh" content="5"> <!-- alle 5 Sekunden neu laden -->
</head>
<body class="p-3">
<h2>Live Log: {{ log_name }}</h2>
<a href="{{ url_for('index') }}" class="btn btn-secondary mb-3">Zurück zum Dashboard</a>
<pre style="height:80vh; overflow:auto; background:#f8f9fa; padding:10px;">{{ log_content }}</pre>
</body>
</html>

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>Einstellungen</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
</head>
<body class="p-5">
<h2>PoE-Check Intervall</h2>
<a href="{{ url_for('index') }}" class="btn btn-secondary mb-3">Zurück zum Dashboard</a>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="mt-2 alert alert-info">
{% for message in messages %}{{ message }}<br>{% endfor %}
</div>
{% endif %}
{% endwith %}
<form method="post" class="row g-2">
<div class="col-auto">
<label for="interval" class="form-label">Intervall (Minuten)</label>
<input type="number" name="interval" id="interval" class="form-control" value="{{ interval }}" min="1" required>
</div>
<div class="col-auto align-self-end">
<button class="btn btn-primary">Speichern</button>
</div>
</form>
</body>
</html>

View File

@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<head>
<title>Switches</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
</head>
<body class="p-5">
<h2>Switches</h2>
<a href="{{ url_for('index') }}" class="btn btn-secondary mb-3">Zurück zum Dashboard</a>
{% 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 %}
<!-- Inline-Add Form -->
<h4>Neuen Switch hinzufügen</h4>
<form method="post" class="row g-2 mb-4">
<input type="hidden" name="add_switch" value="1">
<div class="col"><input type="text" name="hostname" placeholder="Hostname" class="form-control" required></div>
<div class="col"><input type="text" name="ip" placeholder="IP" class="form-control" required></div>
<div class="col"><input type="text" name="username" placeholder="Username" class="form-control" required></div>
<div class="col"><input type="password" name="password" placeholder="Passwort" class="form-control" required></div>
<div class="col"><button class="btn btn-success w-100">Hinzufügen</button></div>
</form>
{% endif %}
<!-- Switches Table -->
<table class="table table-bordered">
<thead>
<tr>
<th>Hostname</th>
<th>IP</th>
<th>Username</th>
{% if current_user.is_admin %}<th>Aktionen</th>{% endif %}
</tr>
</thead>
<tbody>
{% for sw in switches %}
<tr>
{% if current_user.is_admin %}
<!-- Inline-Edit Form -->
<form method="post">
<input type="hidden" name="edit_switch" value="1">
<input type="hidden" name="old_hostname" value="{{ sw['hostname'] }}">
<td><input name="hostname" value="{{ sw['hostname'] }}" class="form-control" required></td>
<td><input name="ip" value="{{ sw['ip'] }}" class="form-control" required></td>
<td><input name="username" value="{{ sw['username'] }}" class="form-control" required></td>
<td class="d-flex gap-1">
<button class="btn btn-primary btn-sm">Speichern</button>
<button name="delete_switch" value="{{ sw['hostname'] }}" class="btn btn-danger btn-sm" onclick="return confirm('Willst du den Switch wirklich löschen?');"> Löschen </button>
</td>
</form>
{% else %}
<td>{{ sw['hostname'] }}</td>
<td>{{ sw['ip'] }}</td>
<td>{{ sw['username'] }}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

1
srv/poe_manager/venv/lib64 Symbolic link
View File

@@ -0,0 +1 @@
lib

View File

@@ -0,0 +1,5 @@
home = /usr/bin
include-system-site-packages = false
version = 3.12.3
executable = /usr/bin/python3.12
command = /usr/bin/python3 -m venv /srv/poe_manager/venv