Updated functionalities 2
This commit is contained in:
@@ -43,6 +43,19 @@
|
||||
.notif-body { font-size: 0.78rem; color: #555; white-space: normal; }
|
||||
.notif-time { font-size: 0.7rem; color: #999; }
|
||||
.notif-empty { padding: 24px; text-align: center; color: #aaa; font-size: 0.85rem; }
|
||||
|
||||
/* ── Active nav tab ── */
|
||||
.navbar-dark .navbar-nav .nav-link.active {
|
||||
background-color: rgba(255, 255, 255, 0.18);
|
||||
color: #ffffff !important;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
box-shadow: inset 0 -2px 0 rgba(255,255,255,0.6);
|
||||
}
|
||||
.navbar-dark .navbar-nav .nav-link:not(.active):hover {
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
border-radius: 6px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -18,6 +18,35 @@
|
||||
</div>
|
||||
|
||||
{% if customers %}
|
||||
|
||||
{% if expired_invitations %}
|
||||
<div class="alert alert-warning d-flex align-items-start gap-3 mb-3" role="alert">
|
||||
<i class="bi bi-exclamation-triangle-fill fs-5 mt-1 flex-shrink-0"></i>
|
||||
<div>
|
||||
<strong>{{ expired_invitations|length }} invitation{{ 's' if expired_invitations|length != 1 else '' }} expired</strong>
|
||||
— the following customer{{ 's' if expired_invitations|length != 1 else '' }} never completed account setup
|
||||
and {{ 'their' if expired_invitations|length != 1 else 'their' }} link has expired:
|
||||
<ul class="mb-2 mt-1">
|
||||
{% for c in expired_invitations %}
|
||||
<li>
|
||||
<strong>{{ c.display_name }}</strong> ({{ c.email }}) —
|
||||
expired {{ c.set_password_token_expires.strftime('%Y-%m-%d %H:%M') }}
|
||||
|
||||
<form method="POST" action="{{ url_for('customers.resend_invite', customer_id=c.id) }}"
|
||||
class="d-inline">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<button type="submit" class="btn btn-sm btn-warning py-0 px-2"
|
||||
style="font-size:.75rem;">
|
||||
<i class="bi bi-send me-1"></i>Resend
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<span class="text-muted small">Resend a fresh 72-hour invitation link or delete the account if it is no longer needed.</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
|
||||
@@ -21,6 +21,20 @@
|
||||
<form method="post">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
|
||||
{# ── Pause all emails banner ── #}
|
||||
{% set any_email_on = prefs_map.values() | selectattr('email_enabled') | list | length > 0
|
||||
or prefs_map | length == 0 %}
|
||||
<div class="alert alert-light border d-flex align-items-center justify-content-between py-2 mb-3">
|
||||
<div>
|
||||
<i class="bi bi-pause-circle me-2 text-secondary"></i>
|
||||
<strong>Pause all email notifications</strong>
|
||||
<span class="text-muted ms-2" style="font-size:.85rem;">— in-app notifications are unaffected</span>
|
||||
</div>
|
||||
<button type="button" id="pauseAllBtn" class="btn btn-sm btn-outline-secondary">
|
||||
<i class="bi bi-pause-fill me-1"></i>Pause All Emails
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-light">
|
||||
<div class="row fw-semibold text-muted" style="font-size:.8rem;">
|
||||
@@ -292,6 +306,42 @@
|
||||
badge.textContent = 'Live';
|
||||
}
|
||||
}
|
||||
|
||||
// ── Pause all emails button ──────────────────────────────────────────────
|
||||
var pauseBtn = document.getElementById('pauseAllBtn');
|
||||
if (pauseBtn) {
|
||||
pauseBtn.addEventListener('click', function () {
|
||||
var allEmailToggles = document.querySelectorAll('.email-toggle');
|
||||
var anyOn = Array.from(allEmailToggles).some(function (c) { return c.checked; });
|
||||
|
||||
allEmailToggles.forEach(function (emailChk) {
|
||||
var event = emailChk.dataset.event;
|
||||
var digestChk = document.getElementById('digest_' + event);
|
||||
var freqSelect = document.getElementById('freq_' + event);
|
||||
var badge = document.getElementById('badge-' + event);
|
||||
|
||||
if (anyOn) {
|
||||
// Pause: turn everything off
|
||||
emailChk.checked = false;
|
||||
digestChk.checked = false;
|
||||
digestChk.disabled = true;
|
||||
freqSelect.disabled = true;
|
||||
updateBadge(badge, false, false);
|
||||
} else {
|
||||
// Resume: re-enable email (digest stays off until user opts back in)
|
||||
emailChk.checked = true;
|
||||
digestChk.disabled = false;
|
||||
updateBadge(badge, true, false);
|
||||
}
|
||||
});
|
||||
|
||||
// Update button label to reflect new state
|
||||
var nowPaused = !anyOn ? false : true;
|
||||
pauseBtn.innerHTML = nowPaused
|
||||
? '<i class="bi bi-play-fill me-1"></i>Resume All Emails'
|
||||
: '<i class="bi bi-pause-fill me-1"></i>Pause All Emails';
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user