180 lines
6.2 KiB
HTML
180 lines
6.2 KiB
HTML
{% extends 'base/skeleton.html' %}
|
|
|
|
{% load static %}
|
|
{% load i18n %}
|
|
|
|
{% block head %}
|
|
{{ block.super }}
|
|
<style>
|
|
.pb-loading,
|
|
.pf-c-login__main >iframe {
|
|
display: flex;
|
|
height: 100%;
|
|
width: 100%;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
.pb-hidden {
|
|
display: none
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block body %}
|
|
<div class="pf-c-background-image">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="pf-c-background-image__filter" width="0" height="0">
|
|
<filter id="image_overlay">
|
|
<feColorMatrix type="matrix" values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0"></feColorMatrix>
|
|
<feComponentTransfer color-interpolation-filters="sRGB" result="duotone">
|
|
<feFuncR type="table" tableValues="0.086274509803922 0.43921568627451"></feFuncR>
|
|
<feFuncG type="table" tableValues="0.086274509803922 0.43921568627451"></feFuncG>
|
|
<feFuncB type="table" tableValues="0.086274509803922 0.43921568627451"></feFuncB>
|
|
<feFuncA type="table" tableValues="0 1"></feFuncA>
|
|
</feComponentTransfer>
|
|
</filter>
|
|
</svg>
|
|
</div>
|
|
<ul class="pf-c-alert-group pf-m-toast">
|
|
</ul>
|
|
<div class="pf-c-login">
|
|
<div class="pf-c-login__container">
|
|
<header class="pf-c-login__header">
|
|
<img class="pf-c-brand" src="{% static 'passbook/logo.svg' %}" style="height: 60px;"
|
|
alt="passbook icon" />
|
|
<img class="pf-c-brand" src="{% static 'passbook/brand.svg' %}" style="height: 60px;"
|
|
alt="passbook branding" />
|
|
</header>
|
|
<main class="pf-c-login__main" id="flow-body">
|
|
<div class="pf-c-login__main-body pb-loading">
|
|
<span class="pf-c-spinner" role="progressbar" aria-valuetext="Loading...">
|
|
<span class="pf-c-spinner__clipper"></span>
|
|
<span class="pf-c-spinner__lead-ball"></span>
|
|
<span class="pf-c-spinner__tail-ball"></span>
|
|
</span>
|
|
</div>
|
|
</main>
|
|
<footer class="pf-c-login__footer">
|
|
<p></p>
|
|
<ul class="pf-c-list pf-m-inline">
|
|
<li>
|
|
<a href="https://beryju.github.io/passbook/">{% trans 'Documentation' %}</a>
|
|
</li>
|
|
<!-- todo: load config.passbook.footer.links -->
|
|
</ul>
|
|
</footer>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
const flowBodyUrl = "{{ exec_url }}";
|
|
const messagesUrl = "{{ msg_url }}";
|
|
const flowBody = document.querySelector("#flow-body");
|
|
const spinner = document.querySelector(".pb-loading");
|
|
|
|
const updateMessages = () => {
|
|
let messageContainer = document.querySelector(".pf-c-alert-group");
|
|
fetch(messagesUrl).then(response => {
|
|
messageContainer.innerHTML = "";
|
|
response.json().then(data => {
|
|
data.forEach(msg => {
|
|
let icon = "";
|
|
switch (msg.level_tag) {
|
|
case 'error':
|
|
icon = 'fas fa-exclamation-circle'
|
|
break;
|
|
case 'warning':
|
|
icon = 'fas fa-exclamation-triangle'
|
|
break;
|
|
case 'success':
|
|
icon = 'fas fa-check-circle'
|
|
break;
|
|
case 'info':
|
|
icon = 'fas fa-info'
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (msg.level_tag === "error") {
|
|
msg.extra_tags = "pf-m-danger";
|
|
}
|
|
let item = `<li class="pf-c-alert-group__item">
|
|
<div class="pf-c-alert pf-m-${msg.level_tag} ${msg.extra_tags}">
|
|
<div class="pf-c-alert__icon">
|
|
<i class="${icon}"></i>
|
|
</div>
|
|
<h4 class="pf-c-alert__title">
|
|
${msg.message}
|
|
</h4>
|
|
</div>
|
|
</li>`;
|
|
var template = document.createElement('template');
|
|
template.innerHTML = item;
|
|
messageContainer.appendChild(template.content.firstChild);
|
|
});
|
|
});
|
|
});
|
|
};
|
|
const updateCard = (data) => {
|
|
switch (data.type) {
|
|
case "redirect":
|
|
window.location = data.to
|
|
break;
|
|
case "template":
|
|
flowBody.innerHTML = data.body;
|
|
updateMessages();
|
|
loadFormCode();
|
|
setFormSubmitHandlers();
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
const showSpinner = () => {
|
|
flowBody.innerHTML = "";
|
|
flowBody.appendChild(spinner);
|
|
};
|
|
const loadFormCode = () => {
|
|
document.querySelectorAll("#flow-body script").forEach(script => {
|
|
let newScript = document.createElement("script");
|
|
newScript.src = script.src;
|
|
document.head.appendChild(newScript);
|
|
});
|
|
};
|
|
const updateFormAction = (form) => {
|
|
for (let index = 0; index < form.elements.length; index++) {
|
|
const element = form.elements[index];
|
|
if (element.value === form.action) {
|
|
console.log("Found Form action URL in form elements, not changing form action.");
|
|
return false;
|
|
}
|
|
}
|
|
form.action = flowBodyUrl;
|
|
return true;
|
|
};
|
|
const checkAutosubmit = (form) => {
|
|
if ("autosubmit" in form.attributes) {
|
|
return form.submit();
|
|
}
|
|
};
|
|
const setFormSubmitHandlers = () => {
|
|
document.querySelectorAll("#flow-body form").forEach(form => {
|
|
console.log(`Checking for autosubmit attribute ${form}`);
|
|
checkAutosubmit(form);
|
|
console.log(`Setting action for form ${form}`);
|
|
updateFormAction(form);
|
|
console.log(`Adding handler for form ${form}`);
|
|
form.addEventListener('submit', (e) => {
|
|
e.preventDefault();
|
|
let formData = new FormData(form);
|
|
fetch(flowBodyUrl, {
|
|
method: 'post',
|
|
body: formData,
|
|
}).then(response => response.json()).then(data => {
|
|
updateCard(data);
|
|
});
|
|
});
|
|
});
|
|
};
|
|
|
|
fetch(flowBodyUrl).then(response => response.json()).then(data => updateCard(data));
|
|
</script>
|
|
{% endblock %}
|