first commit
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{block "title" .}}Email Server Management{{end}}</title>
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
:root { --sidebar-width: 280px; }
|
||||
body { background-color: #1a1a1a; color: #e0e0e0; }
|
||||
.main-container { display: flex; min-height: 100vh; }
|
||||
.content-area { flex: 1; margin-left: var(--sidebar-width); padding: 20px; transition: margin-left 0.3s ease; }
|
||||
.navbar-brand { color: #fff !important; }
|
||||
.card { background-color: #2d2d2d; border: 1px solid #404040; }
|
||||
.table-dark { --bs-table-bg: #2d2d2d; --bs-table-border-color: #404040; }
|
||||
.btn-outline-light:hover { background-color: #495057; }
|
||||
.alert-success { background-color: #0f5132; border-color: #146c43; color: #75b798; }
|
||||
.alert-danger { background-color: #58151c; border-color: #842029; color: #ea868f; }
|
||||
.alert-warning { background-color: #664d03; border-color: #997404; color: #ffda6a; }
|
||||
.alert-info { background-color: #055160; border-color: #087990; color: #6edff6; }
|
||||
.form-control:focus { border-color: #0d6efd; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); }
|
||||
.form-select:focus { border-color: #0d6efd; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); }
|
||||
.text-muted { color: #adb5bd !important; }
|
||||
.border-success { border-color: #198754 !important; }
|
||||
.border-danger { border-color: #dc3545 !important; }
|
||||
.text-success { color: #75b798 !important; }
|
||||
.text-danger { color: #ea868f !important; }
|
||||
.text-warning { color: #ffda6a !important; }
|
||||
::-webkit-scrollbar { width: 8px; }
|
||||
::-webkit-scrollbar-track { background: #2d2d2d; }
|
||||
::-webkit-scrollbar-thumb { background: #495057; border-radius: 4px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: #6c757d; }
|
||||
</style>
|
||||
|
||||
<link href="/pymta-manager/static/css/smtp-management.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
.tooltip-inner { color: #fff !important; background-color: #222 !important; font-size: 1rem; text-align: left; }
|
||||
.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,
|
||||
.bs-tooltip-top .tooltip-arrow::before { border-top-color: #222 !important; }
|
||||
</style>
|
||||
|
||||
{{block "extra_css" .}}{{end}}
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-container">
|
||||
{{template "sidebar_email.html" .}}
|
||||
|
||||
<div class="content-area">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4">
|
||||
<div class="container-fluid">
|
||||
<span class="navbar-brand mb-0 h1">
|
||||
<i class="bi bi-envelope-fill me-2"></i>
|
||||
{{block "page_title" .}}Email Server Management{{end}}
|
||||
</span>
|
||||
<div class="navbar-nav ms-auto">
|
||||
<span class="navbar-text">
|
||||
<i class="bi bi-clock-fill me-1"></i>
|
||||
<span id="current-time"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 1090;">
|
||||
{{range .flashes}}
|
||||
<div class="toast align-items-center text-bg-{{if eq .Category "error"}}danger{{else}}{{.Category}}{{end}} border-0" role="alert" aria-live="assertive" aria-atomic="true" data-bs-autohide="false">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
<i class="bi bi-{{if eq .Category "error"}}exclamation-triangle{{else if eq .Category "success"}}check-circle{{else}}info-circle{{end}} me-2"></i>
|
||||
{{.Message}}
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<main>
|
||||
{{block "content" .}}{{end}}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="confirmationModal" tabindex="-1" aria-labelledby="confirmationModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="confirmationModalLabel">
|
||||
<i class="bi bi-question-circle me-2"></i>
|
||||
Confirm Action
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" id="confirmationModalBody">
|
||||
Are you sure you want to proceed?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" id="confirmationModalConfirm">Confirm</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script>
|
||||
function updateTime() {
|
||||
const now = new Date();
|
||||
const timeString = now.toLocaleTimeString();
|
||||
const dateString = now.toLocaleDateString();
|
||||
document.getElementById('current-time').textContent = `${dateString} ${timeString}`;
|
||||
}
|
||||
setInterval(updateTime, 1000);
|
||||
updateTime();
|
||||
|
||||
// Notifications auto-dismiss after 5s, but hovering (reading, or selecting
|
||||
// text to copy) pauses the timer — it only resumes once the mouse leaves.
|
||||
// Clicking inside never dismisses; only the X button or the timer does.
|
||||
const TOAST_AUTOHIDE_MS = 5000;
|
||||
function armToastAutoDismiss(toastEl, bsToast) {
|
||||
let timer = null;
|
||||
const start = () => { timer = setTimeout(() => bsToast.hide(), TOAST_AUTOHIDE_MS); };
|
||||
const stop = () => { if (timer) { clearTimeout(timer); timer = null; } };
|
||||
toastEl.addEventListener('mouseenter', stop);
|
||||
toastEl.addEventListener('mouseleave', start);
|
||||
start();
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const toastElements = document.querySelectorAll('.toast');
|
||||
toastElements.forEach(function(toastElement) {
|
||||
const toast = new bootstrap.Toast(toastElement);
|
||||
toast.show();
|
||||
armToastAutoDismiss(toastElement, toast);
|
||||
});
|
||||
});
|
||||
|
||||
function showToast(message, type = 'info') {
|
||||
const toastContainer = document.querySelector('.toast-container');
|
||||
const toastId = 'toast-' + Date.now();
|
||||
const iconMap = { 'danger': 'exclamation-triangle', 'success': 'check-circle', 'warning': 'exclamation-triangle', 'info': 'info-circle' };
|
||||
const toastHtml = `
|
||||
<div id="${toastId}" class="toast align-items-center text-bg-${type} border-0" role="alert" aria-live="assertive" aria-atomic="true" data-bs-autohide="false">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
<i class="bi bi-${iconMap[type] || 'info-circle'} me-2"></i>
|
||||
${message}
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
toastContainer.insertAdjacentHTML('beforeend', toastHtml);
|
||||
const toastEl = document.getElementById(toastId);
|
||||
const newToast = new bootstrap.Toast(toastEl);
|
||||
newToast.show();
|
||||
armToastAutoDismiss(toastEl, newToast);
|
||||
toastEl.addEventListener('hidden.bs.toast', function() { this.remove(); });
|
||||
}
|
||||
|
||||
function showConfirmation(message, title = 'Confirm Action', confirmButtonText = 'Confirm', confirmButtonClass = 'btn-primary') {
|
||||
return new Promise((resolve) => {
|
||||
const modal = document.getElementById('confirmationModal');
|
||||
const modalTitle = document.getElementById('confirmationModalLabel');
|
||||
const modalBody = document.getElementById('confirmationModalBody');
|
||||
const confirmButton = document.getElementById('confirmationModalConfirm');
|
||||
modalTitle.innerHTML = `<i class="bi bi-question-circle me-2"></i>${title}`;
|
||||
modalBody.textContent = message;
|
||||
confirmButton.textContent = confirmButtonText;
|
||||
confirmButton.className = `btn ${confirmButtonClass}`;
|
||||
const handleConfirm = () => { resolve(true); bootstrap.Modal.getInstance(modal).hide(); cleanup(); };
|
||||
const handleCancel = () => { resolve(false); cleanup(); };
|
||||
const cleanup = () => {
|
||||
confirmButton.removeEventListener('click', handleConfirm);
|
||||
modal.removeEventListener('hidden.bs.modal', handleCancel);
|
||||
};
|
||||
confirmButton.addEventListener('click', handleConfirm);
|
||||
modal.addEventListener('hidden.bs.modal', handleCancel, { once: true });
|
||||
new bootstrap.Modal(modal).show();
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const deleteButtons = document.querySelectorAll('[data-confirm]');
|
||||
deleteButtons.forEach(function(button) {
|
||||
button.addEventListener('click', async function(e) {
|
||||
e.preventDefault();
|
||||
const confirmMessage = this.getAttribute('data-confirm');
|
||||
const confirmed = await showConfirmation(confirmMessage, 'Confirm Action', 'Confirm', 'btn-danger');
|
||||
if (confirmed) {
|
||||
const form = this.closest('form');
|
||||
if (form) { form.submit(); } else if (this.href) { window.location.href = this.href; }
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="/pymta-manager/static/js/smtp-management.js"></script>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
tooltipTriggerList.forEach(function (tooltipTriggerEl) {
|
||||
new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{{block "extra_js" .}}{{end}}
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user