155 lines
5.9 KiB
Django/Jinja
155 lines
5.9 KiB
Django/Jinja
{% extends 'base.html.j2' %}
|
|
{% set active_page = "addressbook" %}
|
|
|
|
{% block content %}
|
|
<div class="flex-grow-1 overflow-hidden d-flex pt-3 pb-lg-3" style='flex-basis: 0;'>
|
|
<div class="overflow-auto col-12 col-lg-4 {% if profile%}d-none{% endif %} d-lg-block" id="contacts">
|
|
{% if contacts %}
|
|
<div class="list-group">
|
|
{% for user in contacts %}
|
|
<button type="button" onclick="handleButtonClick(this)" data-username='{{ user.username }}'
|
|
class="profile-button list-group-item list-group-item-action {% if profile.username == user.username %}active{% endif%}">{{
|
|
user.display_name }}</button>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="h-100 w-100 d-flex align-items-center">
|
|
<div class="w-100 text-center" style="color: lightgrey"><em>Geen contacten om te tonen</em></div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="col pt-lg-2 ps-lg-4 pe-lg-4">
|
|
<div class="container overflow-auto h-100 pb-3 pb-lg-0" id="profile-wrap">
|
|
{% if profile %}
|
|
{% include 'addressbook_card.html.j2' %}
|
|
{% elif contacts %}
|
|
<div class="h-100 w-100 d-flex align-items-center">
|
|
<div class="w-100 text-center">
|
|
<p class="fst-italic" style="color: lightgrey">Niemand geselecteerd</p>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
|
<div id="toast-loading" class="toast align-items-center text-bg-primary border-0" role="alert" aria-live="assertive"
|
|
data-bs-autohide="false" aria-atomic="true">
|
|
<div class="d-flex">
|
|
<div class="toast-body">
|
|
<div class="spinner-border spinner-border-sm me-2" role="status"></div>Het duurt wat langer om te
|
|
laden..
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
|
<div id="toast-error" class="toast align-items-center text-bg-danger border-0" role="alert" aria-live="assertive"
|
|
data-bs-autohide="false" aria-atomic="true">
|
|
<div class="d-flex">
|
|
<div class="toast-body">
|
|
<i class="bi bi-exclamation-circle-fill me-1"></i>
|
|
<strong>Laden mislukt!</strong><br>
|
|
Herlaad de pagina of probeer het later opnieuw.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
var addressbookURL = {{ url_for('addressbook') | tojson}}
|
|
var cardURL = {{ url_for('addressbook_card') | tojson}}
|
|
|
|
function showContacts() {
|
|
document.getElementById('contacts').classList.remove('d-none');
|
|
scrollToActive();
|
|
}
|
|
|
|
function handleButtonClick(element) {
|
|
var username = element.dataset.username;
|
|
history.pushState({ 'username': username }, '', addressbookURL + username);
|
|
selectProfile(username);
|
|
}
|
|
|
|
function renderMap() {
|
|
var element = document.getElementById('osm-map-small');
|
|
if (element) {
|
|
var data = element.dataset
|
|
var map = L.map(element);
|
|
L.tileLayer('https://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png').addTo(map);
|
|
|
|
var marker = L.marker(L.latLng(data['lat'], data['lon'])).addTo(map);
|
|
marker.bindTooltip(data['label'], { 'permanent': true })
|
|
|
|
var target = L.latLng(data['lat'], data['lon']);
|
|
map.setView(target, 15);
|
|
}
|
|
}
|
|
|
|
function selectProfile(username) {
|
|
Array.from(document.getElementsByClassName('profile-button')).forEach(
|
|
function (element, idx, array) {
|
|
element.classList.remove('active')
|
|
if (element.dataset.username == username) {
|
|
element.classList.add('active')
|
|
}
|
|
}
|
|
)
|
|
|
|
var timeoutLoading = setTimeout(() => {
|
|
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-loading')).show()
|
|
}, 1000);
|
|
var timeoutError = setTimeout(() => {
|
|
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-error')).show()
|
|
}, 10000);
|
|
fetch(cardURL + username)
|
|
.then(function (response) {
|
|
if (response.ok) {
|
|
return response.text();
|
|
}
|
|
return Promise.reject(response);
|
|
})
|
|
.then(
|
|
function (html) {
|
|
document.getElementById('profile-wrap').innerHTML = html
|
|
renderMap();
|
|
document.getElementById('contacts').classList.add('d-none');
|
|
clearTimeout(timeoutLoading);
|
|
clearTimeout(timeoutError);
|
|
},
|
|
function (html) {
|
|
clearTimeout(timeoutLoading);
|
|
clearTimeout(timeoutError);
|
|
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-error')).show()
|
|
}
|
|
)
|
|
}
|
|
|
|
function scrollToActive() {
|
|
var active = document.getElementsByClassName('profile-button active');
|
|
if (active.length > 0) {
|
|
var grandParent = active[0].parentNode.parentNode;
|
|
grandParent.scrollTop = active[0].offsetTop - grandParent.offsetTop - grandParent.clientHeight / 2 + active[0].clientHeight / 2
|
|
}
|
|
}
|
|
|
|
window.addEventListener('popstate', function () {
|
|
var url = window.location.href;
|
|
var username = url.split('/').filter((fragment) => fragment.length > 0).at(-1);
|
|
if (username == 'addressbook') {
|
|
return
|
|
}
|
|
selectProfile(username)
|
|
scrollToActive();
|
|
})
|
|
|
|
window.addEventListener('load', function () {
|
|
scrollToActive();
|
|
renderMap();
|
|
});
|
|
</script>
|
|
{% endblock %} |