Alice Gaudon
6aa37eb9e4
Reorganize views into new "assets" folder structure
Turn locals into a store so locals don't have to be passed through files that don't need them
Some fixes to previous commit (esm) 82ab0b963c
Remove afs in favor of fs.promises (renamed afs.exists to Utils.doesFileExist
Rename Utils.readdirRecursively to Utils.listFilesRecursively
58 lines
1.8 KiB
Plaintext
58 lines
1.8 KiB
Plaintext
{% extends 'layouts/base.njk' %}
|
|
|
|
{% set h1 = 'Authentication lobby' %}
|
|
{% set title = app.name + ' ' + h1 %}
|
|
|
|
{% block body %}
|
|
<div class="container">
|
|
<div class="panel">
|
|
{{ macros.message('success', 'We sent a link to ' + email + '. To authenticate, open it from any device.') }}
|
|
{{ macros.message('info', 'This link will be valid for <span id="countdown"></span> and can only be used once.', true, true) }}
|
|
|
|
<p class="center">Waiting for you to open the link...</p>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
const validUntil = {{ validUntil }}.0;
|
|
|
|
function isValid() {
|
|
return new Date().getTime() < validUntil;
|
|
}
|
|
|
|
function websocketListen(websocket, e) {
|
|
if (e.data === 'refresh') {
|
|
window.location.reload();
|
|
}
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const countdown = document.getElementById('countdown');
|
|
|
|
if (!isValid()) return;
|
|
|
|
function animateCountdown() {
|
|
requestAnimationFrame(() => {
|
|
let diff = Math.max(0, validUntil - new Date().getTime());
|
|
if (diff === 0) {
|
|
return;
|
|
}
|
|
|
|
diff /= 1000;
|
|
const seconds = Math.floor(diff % 60).toFixed(0);
|
|
const minutes = Math.floor((diff - seconds) / 60).toFixed(0);
|
|
|
|
countdown.innerText = `${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
|
|
animateCountdown();
|
|
});
|
|
}
|
|
|
|
animateCountdown();
|
|
});
|
|
</script>
|
|
|
|
{{ macros.websocket(websocketUrl, 'websocketListen', 1, 'isValid') }}
|
|
{% endblock %}
|