06/04 Optimize app
This commit is contained in:
@@ -49,7 +49,7 @@
|
|||||||
<td class="text-muted nowrap">{{ r.checked_at.strftime('%H:%M:%S') if r.checked_at else '' }}</td>
|
<td class="text-muted nowrap">{{ r.checked_at.strftime('%H:%M:%S') if r.checked_at else '' }}</td>
|
||||||
<td>{{ r.full_name }}</td>
|
<td>{{ r.full_name }}</td>
|
||||||
<td>{{ r.website_name }}</td>
|
<td>{{ r.website_name }}</td>
|
||||||
<td><a href="{{ r.url }}" target="_blank" rel="noopener">{{ r.url[:40] }}…</a></td>
|
<td><a href="{{ r.url }}" target="_blank" rel="noopener">{{ r.url[:40] }}{% if r.url|length > 40 %}…{% endif %}</a></td>
|
||||||
<td class="text-muted">{{ r.user_note }}</td>
|
<td class="text-muted">{{ r.user_note }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% else %}<tr><td colspan="6" class="text-center text-muted">No data.</td></tr>{% endfor %}
|
{% else %}<tr><td colspan="6" class="text-center text-muted">No data.</td></tr>{% endfor %}
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
<td>{{ r.check_date }}</td>
|
<td>{{ r.check_date }}</td>
|
||||||
<td>{{ r.full_name }}</td>
|
<td>{{ r.full_name }}</td>
|
||||||
<td>{{ r.website_name }}</td>
|
<td>{{ r.website_name }}</td>
|
||||||
<td><a href="{{ r.url }}" target="_blank" rel="noopener">{{ r.url[:40] }}…</a></td>
|
<td><a href="{{ r.url }}" target="_blank" rel="noopener">{{ r.url[:40] }}{% if r.url|length > 40 %}…{% endif %}</a></td>
|
||||||
<td><span class="badge badge-danger">Not Checked</span></td>
|
<td><span class="badge badge-danger">Not Checked</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% else %}<tr><td colspan="5" class="text-center text-muted">No data.</td></tr>{% endfor %}
|
{% else %}<tr><td colspan="5" class="text-center text-muted">No data.</td></tr>{% endfor %}
|
||||||
@@ -83,7 +83,8 @@
|
|||||||
<td>{{ r.checked_count }}</td>
|
<td>{{ r.checked_count }}</td>
|
||||||
<td>{{ r.total_sites }}</td>
|
<td>{{ r.total_sites }}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="progress"><div class="progress-bar" style="width:{{ r.pct_complete or 0 }}%"></div></div>
|
{% set pct = (r.pct_complete or 0)|int %}
|
||||||
|
<div class="progress"><div class="progress-bar" style="width:{{ pct }}%;background:{% if pct >= 100 %}var(--success){% elif pct >= 50 %}var(--warning){% else %}var(--danger){% endif %}"></div></div>
|
||||||
</td>
|
</td>
|
||||||
<td><strong>{{ r.pct_complete or 0 }}%</strong></td>
|
<td><strong>{{ r.pct_complete or 0 }}%</strong></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -3,7 +3,13 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1 class="page-title">User Management</h1>
|
<h1 class="page-title">User Management</h1>
|
||||||
|
<div class="flex gap-1 items-center">
|
||||||
|
<div class="search-wrap">
|
||||||
|
<input type="text" id="user-search" placeholder="Search users…" autocomplete="off">
|
||||||
|
<span class="search-icon">🔍</span>
|
||||||
|
</div>
|
||||||
<button class="btn btn-primary" onclick="openModal('modal-create-user')">+ Add User</button>
|
<button class="btn btn-primary" onclick="openModal('modal-create-user')">+ Add User</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@@ -33,9 +39,9 @@
|
|||||||
title="Send password reset link to {{ u.email }}">✉ Reset</button>
|
title="Send password reset link to {{ u.email }}">✉ Reset</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<form method="post" action="{{ url_for('admin_users.delete', user_id=u.id) }}"
|
<form method="post" action="{{ url_for('admin_users.delete', user_id=u.id) }}"
|
||||||
style="display:inline"
|
style="display:inline">
|
||||||
onsubmit="return confirm('Delete user {{ u.username }}?')">
|
<button class="btn btn-danger btn-sm js-delete-user" type="button"
|
||||||
<button class="btn btn-danger btn-sm" type="submit">✕</button>
|
data-username="{{ u.username }}">✕</button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -76,7 +82,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">Password *</label>
|
<label class="form-label">Password *</label>
|
||||||
<input class="form-control" type="password" name="password" required>
|
<input class="form-control" type="password" name="password" id="create-user-pw" required>
|
||||||
|
<div class="pw-strength-wrap">
|
||||||
|
<div class="pw-strength-bar"><div class="pw-strength-fill" id="create-user-pw-fill"></div></div>
|
||||||
|
<small class="pw-strength-label" id="create-user-pw-label"></small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
@@ -136,6 +146,30 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
/* User search */
|
||||||
|
(function() {
|
||||||
|
var timer = null;
|
||||||
|
document.getElementById('user-search').addEventListener('input', function() {
|
||||||
|
var val = this.value;
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = setTimeout(function() {
|
||||||
|
var q = val.trim().toLowerCase();
|
||||||
|
document.querySelectorAll('tbody tr').forEach(function(row) {
|
||||||
|
row.style.display = !q || row.textContent.toLowerCase().includes(q) ? '' : 'none';
|
||||||
|
});
|
||||||
|
}, 250);
|
||||||
|
});
|
||||||
|
}());
|
||||||
|
|
||||||
|
/* Delete user — safe confirm via data-attribute */
|
||||||
|
document.querySelectorAll('.js-delete-user').forEach(function(btn) {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
if (confirm('Delete user ' + btn.dataset.username + '?')) {
|
||||||
|
btn.closest('form').submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function openEditUser(u) {
|
function openEditUser(u) {
|
||||||
document.getElementById('edit-username').value = u.username;
|
document.getElementById('edit-username').value = u.username;
|
||||||
document.getElementById('edit-full-name').value = u.full_name || '';
|
document.getElementById('edit-full-name').value = u.full_name || '';
|
||||||
@@ -147,6 +181,8 @@ function openEditUser(u) {
|
|||||||
openModal('modal-edit-user');
|
openModal('modal-edit-user');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attachPasswordStrength('create-user-pw', 'create-user-pw-fill', 'create-user-pw-label');
|
||||||
|
|
||||||
document.querySelectorAll('.js-send-reset').forEach(function(btn) {
|
document.querySelectorAll('.js-send-reset').forEach(function(btn) {
|
||||||
btn.addEventListener('click', function() {
|
btn.addEventListener('click', function() {
|
||||||
var username = btn.dataset.username;
|
var username = btn.dataset.username;
|
||||||
|
|||||||
@@ -15,6 +15,10 @@
|
|||||||
<input class="form-control" value="{{ session['user']['username'] }}" disabled>
|
<input class="form-control" value="{{ session['user']['username'] }}" disabled>
|
||||||
<small class="text-muted">Username cannot be changed. Contact an admin if needed.</small>
|
<small class="text-muted">Username cannot be changed. Contact an admin if needed.</small>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label">Role</label>
|
||||||
|
<input class="form-control" value="{{ session['user']['role'] | capitalize }}" disabled>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">Full Name</label>
|
<label class="form-label">Full Name</label>
|
||||||
<input class="form-control" name="full_name"
|
<input class="form-control" name="full_name"
|
||||||
|
|||||||
Reference in New Issue
Block a user