|
|
|
|
@ -105,6 +105,40 @@
|
|
|
|
|
.monoish { |
|
|
|
|
word-break: break-word; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.health-toast { |
|
|
|
|
position: fixed; |
|
|
|
|
right: 1.25rem; |
|
|
|
|
bottom: 1.25rem; |
|
|
|
|
z-index: 9999; |
|
|
|
|
min-width: 220px; |
|
|
|
|
max-width: 360px; |
|
|
|
|
padding: 0.8rem 1rem; |
|
|
|
|
border: 1px solid rgba(255,255,255,0.22); |
|
|
|
|
border-radius: 0.55rem; |
|
|
|
|
background: rgba(20, 24, 38, 0.96); |
|
|
|
|
color: inherit; |
|
|
|
|
box-shadow: 0 10px 28px rgba(0,0,0,0.35); |
|
|
|
|
opacity: 0; |
|
|
|
|
transform: translateY(12px); |
|
|
|
|
transition: opacity 180ms ease, transform 180ms ease; |
|
|
|
|
pointer-events: none; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.health-toast.show { |
|
|
|
|
opacity: 1; |
|
|
|
|
transform: translateY(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.health-toast.ok { |
|
|
|
|
border-color: rgba(105, 219, 124, 0.55); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.health-toast.bad { |
|
|
|
|
border-color: rgba(255, 135, 135, 0.55); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</style> |
|
|
|
|
<link rel="icon" type="image/png" href="/static/favicon.png"> |
|
|
|
|
</head> |
|
|
|
|
@ -243,14 +277,6 @@
|
|
|
|
|
<form method="post" action="/health/reconcile-now"> |
|
|
|
|
<button class="health-action-button" type="submit">Reconcile Now</button> |
|
|
|
|
</form> |
|
|
|
|
|
|
|
|
|
{% if request.args.get("reconcile") == "started" %} |
|
|
|
|
<p class="health-note ok">Manual reconcile started.</p> |
|
|
|
|
{% elif request.args.get("reconcile") == "failed" %} |
|
|
|
|
<p class="health-note bad">Manual reconcile failed to start.</p> |
|
|
|
|
{% elif request.args.get("reconcile") == "missing-worker" %} |
|
|
|
|
<p class="health-note bad">Worker script missing.</p> |
|
|
|
|
{% endif %} |
|
|
|
|
{% else %} |
|
|
|
|
<p>Not available</p> |
|
|
|
|
{% endif %} |
|
|
|
|
@ -260,5 +286,42 @@
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
{% include "footer.html" %} |
|
|
|
|
|
|
|
|
|
<div id="health-toast" class="health-toast" role="status" aria-live="polite"></div> |
|
|
|
|
|
|
|
|
|
<script> |
|
|
|
|
(function () { |
|
|
|
|
const params = new URLSearchParams(window.location.search); |
|
|
|
|
const result = params.get("reconcile"); |
|
|
|
|
if (!result) return; |
|
|
|
|
|
|
|
|
|
const messages = { |
|
|
|
|
"started": { text: "Manual reconcile started.", cls: "ok" }, |
|
|
|
|
"failed": { text: "Manual reconcile failed to start.", cls: "bad" }, |
|
|
|
|
"missing-worker": { text: "Worker script missing.", cls: "bad" } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const reconcileToastMessage = messages[result]; |
|
|
|
|
if (!reconcileToastMessage) return; |
|
|
|
|
|
|
|
|
|
const toast = document.getElementById("health-toast"); |
|
|
|
|
if (!toast) return; |
|
|
|
|
|
|
|
|
|
toast.textContent = reconcileToastMessage.text; |
|
|
|
|
toast.classList.add(reconcileToastMessage.cls); |
|
|
|
|
|
|
|
|
|
requestAnimationFrame(function () { |
|
|
|
|
toast.classList.add("show"); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
setTimeout(function () { |
|
|
|
|
toast.classList.remove("show"); |
|
|
|
|
|
|
|
|
|
const cleanUrl = window.location.pathname + window.location.hash; |
|
|
|
|
window.history.replaceState({}, document.title, cleanUrl); |
|
|
|
|
}, 3000); |
|
|
|
|
})(); |
|
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
</body> |
|
|
|
|
</html> |
|
|
|
|
|