mirror of
https://github.com/tmdinosaurcenter/kiosk-guestbook.git
synced 2026-06-04 05:47:43 -06:00
047f57513d
All pages: manifest link, apple-mobile-web-app meta tags, theme-color, viewport-fit=cover, overscroll-behavior:none, safe-area padding, 16px input font-size to prevent iOS zoom, SW registration. admin.html: card-per-entry layout on small screens (d-md-none) with name, location, timestamp, newsletter status, email, comment, and delete button. Desktop table unchanged (d-none d-md-block).
102 lines
4.3 KiB
HTML
102 lines
4.3 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
<title>Guestbook Admin — Users</title>
|
|
|
|
<!-- PWA -->
|
|
<link rel="manifest" href="/manifest.webmanifest" />
|
|
<link rel="apple-touch-icon" href="/static/images/logo.png" />
|
|
<meta name="theme-color" content="#3a9cb8" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" />
|
|
<style>
|
|
html, body { overscroll-behavior: none; }
|
|
body { padding-bottom: env(safe-area-inset-bottom); }
|
|
input.form-control, select.form-select { font-size: 16px !important; }
|
|
</style>
|
|
</head>
|
|
<body class="bg-light">
|
|
<div class="container py-4" style="max-width: 700px;">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h1 class="h3 mb-0">User Management</h1>
|
|
<div class="d-flex gap-2">
|
|
<a href="{{ url_for('admin') }}" class="btn btn-outline-secondary btn-sm">Back to Entries</a>
|
|
<a href="{{ url_for('admin_logout') }}" class="btn btn-outline-danger btn-sm">Logout</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card mb-4">
|
|
<div class="card-header">Add User</div>
|
|
<div class="card-body">
|
|
<form method="POST" action="{{ url_for('admin_users_add') }}">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
|
<div class="row g-2">
|
|
<div class="col-sm-4">
|
|
<input type="text" name="username" class="form-control" placeholder="Username" required />
|
|
</div>
|
|
<div class="col-sm-4">
|
|
<input type="password" name="password" class="form-control" placeholder="Password" required />
|
|
</div>
|
|
<div class="col-sm-2">
|
|
<select name="role" class="form-select">
|
|
<option value="viewer">Viewer</option>
|
|
<option value="admin">Admin</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-sm-2">
|
|
<button type="submit" class="btn btn-primary w-100">Add</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<table class="table table-bordered bg-white">
|
|
<thead class="table-dark">
|
|
<tr>
|
|
<th>Username</th>
|
|
<th>Role</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for u in users %}
|
|
<tr>
|
|
<td>{{ u[1] }}</td>
|
|
<td><span class="badge bg-{{ 'danger' if u[2] == 'admin' else 'secondary' }}">{{ u[2] }}</span></td>
|
|
<td>
|
|
<form method="POST" action="{{ url_for('admin_users_delete', user_id=u[0]) }}"
|
|
onsubmit="return confirm('Remove user {{ u[1] }}?')">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
|
<button type="submit" class="btn btn-danger btn-sm">Remove</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr>
|
|
<td colspan="3" class="text-center text-muted">No users added yet.</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
|
|
<p class="text-muted small">
|
|
These accounts are in addition to the bootstrap superadmin configured in <code>.env</code>.
|
|
Admins can view and delete entries. Viewers can only view.
|
|
</p>
|
|
</div>
|
|
|
|
<script>
|
|
if ('serviceWorker' in navigator) {
|
|
window.addEventListener('load', function () {
|
|
navigator.serviceWorker.register('/sw.js', { scope: '/' });
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|