Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/ephios/extra/middleware.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.conf import settings
from django.http import HttpResponse

from ephios.core.services.notifications.types import NOTIFICATION_READ_PARAM_NAME

Expand Down Expand Up @@ -41,3 +42,15 @@ def __call__(self, request):
notification.read = True
notification.save(update_fields=["read"])
return response


class CacheControlMiddleware:
def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
response: HttpResponse = self.get_response(request)
# To prevent storing sensitive data in the cache as well as
# to prevent outdated data being shown to users
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
return response
1 change: 1 addition & 0 deletions src/ephios/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
"ephios.extra.middleware.EphiosLocaleMiddleware",
"ephios.extra.middleware.CacheControlMiddleware",
"ephios.extra.middleware.EphiosNotificationMiddleware",
"ephios.core.services.files.EphiosMediaFileMiddleware",
"django.middleware.common.CommonMiddleware",
Expand Down
44 changes: 25 additions & 19 deletions src/ephios/static/ephios/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ function handleForms(elem) {
});
}

function blurForUnload() {
$('.blur-on-unload').addClass("unloading");
$('#unloading-spinner').removeClass("d-none");
}

$(document).ready(function () {
// Configure all prerendered Forms
handleForms($(document));
Expand All @@ -116,15 +121,9 @@ $(document).ready(function () {
// https://stackoverflow.com/a/41749865
if (navigator.standalone || window.matchMedia('(display-mode: standalone)').matches) {
$(window).on('beforeunload', function () {
$('.blur-on-unload').addClass("unloading");
$('#unloading-spinner').removeClass("d-none");
blurForUnload();
});
}
// when hitting "back" button in browser, the page is not reloaded so we need to remove the blur manually
window.addEventListener('pageshow', function (event) {
$('.blur-on-unload').removeClass("unloading");
$('#unloading-spinner').addClass("d-none");
});

if ($("body").data("pwa-network") === "offline") {
// disable all forms and post buttons
Expand Down Expand Up @@ -181,21 +180,21 @@ $(document).ready(function () {
// We need to store the prompt to be able to show the install button later on.
// We show the prompt to the user if they did not decline in the last month and are logged in
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredInstallPrompt = e;
if (!getCookie("pwaPrompt") && document.body.dataset.userIsAuthenticated === "True") {
pwaAndroidBsOffcanvas.show();
}
e.preventDefault();
deferredInstallPrompt = e;
if (!getCookie("pwaPrompt") && document.body.dataset.userIsAuthenticated === "True") {
pwaAndroidBsOffcanvas.show();
}
});

// When the user clicks on the install button in our PWA install prompt, we can used the saved prompt
// from the browser event to actually trigger the installation
const buttonInstall = document.getElementById("pwaInstall");
buttonInstall.addEventListener('click', async () => {
deferredInstallPrompt.prompt();
await deferredInstallPrompt.userChoice;
pwaAndroidBsOffcanvas.hide();
deferredInstallPrompt = null;
deferredInstallPrompt.prompt();
await deferredInstallPrompt.userChoice;
pwaAndroidBsOffcanvas.hide();
deferredInstallPrompt = null;
});

// iOS does not support programmatic installation, so we show an offcanvas with instructions instead
Expand All @@ -204,16 +203,23 @@ $(document).ready(function () {
}

setTimeout(() => {
// Only show this prompt inside of the PWA (with display-mode: standalone) for logged in user that did not decline in the last month
// Only show this prompt inside the PWA (with display-mode: standalone) for logged in user that did not decline in the last month
// isPushEnabled is set by webpush.js from django-webpush
if ((window.matchMedia('(display-mode: standalone)').matches || navigator.standalone) && typeof isPushEnabled !== undefined && !isPushEnabled && !getCookie("notificationPrompt")) {
document.getElementById("webpush-subscribe-button")
.addEventListener("click", _ => notificationBsOffcanvas.hide())
.addEventListener("click", _ => notificationBsOffcanvas.hide())
notificationBsOffcanvas.show();
}
}, 2000); // isPushEnabled is only set to true after a request to the backend, so it takes some time
});

})
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
// Force a reload if the page is shown from the bfcache.
blurForUnload();
location.reload();
}
});

function rememberDismissed(key) {
const date = new Date();
Expand Down
30 changes: 21 additions & 9 deletions src/ephios/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -204,27 +204,33 @@ <h5 class="offcanvas-title" id="pwaOffcanvasLabel">
<p class="pb-2">{% blocktranslate trimmed with platform_name=platform_name %}
You can install {{ platform_name }} on your device and use it like any other app!
{% endblocktranslate %} {% translate "Simply click the button below to continue." %}</p>
<button id="pwaInstall" class="btn btn-primary">{% blocktranslate trimmed with platform_name=platform_name %}Install {{ platform_name }}{% endblocktranslate %}</button>
<button id="pwaInstall" class="btn btn-primary">
{% blocktranslate trimmed with platform_name=platform_name %}Install
{{ platform_name }}{% endblocktranslate %}</button>
</div>
</div>
<div id="pwaAppleOffcanvas" class="offcanvas offcanvas-bottom">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="pwaOffcanvasLabel">{% blocktranslate trimmed with platform_name=platform_name %}
Install {{ platform_name }} app
{% endblocktranslate %}</h5>
<h5 class="offcanvas-title" id="pwaOffcanvasLabel">
{% blocktranslate trimmed with platform_name=platform_name %}
Install {{ platform_name }} app
{% endblocktranslate %}</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<p class="pb-2">{% blocktranslate trimmed with platform_name=platform_name %}
You can install {{ platform_name }} on your device and use it like any other app!
{% endblocktranslate %} {%translate "Simply follow the steps below." %}</p>
{% endblocktranslate %} {% translate "Simply follow the steps below." %}</p>
<hr>
<div class="container">
<div class="row align-items-center">
<div class="col-2">
<div class="p-2">
<svg id="pwa-safari" viewBox="0 0 20.283 19.932" width="24" height="24">
<g fill="currentColor"><path d="M9.96 19.922c5.45 0 9.962-4.522 9.962-9.961C19.922 4.51 15.4 0 9.952 0 4.511 0 0 4.512 0 9.96c0 5.44 4.521 9.962 9.96 9.962Zm0-1.66A8.26 8.26 0 0 1 1.67 9.96c0-4.61 3.672-8.3 8.281-8.3 4.61 0 8.31 3.69 8.31 8.3 0 4.61-3.69 8.3-8.3 8.3Z"/><path d="m5.87 14.883 5.605-2.735a1.47 1.47 0 0 0 .683-.673l2.725-5.596c.312-.664-.166-1.182-.85-.84L8.447 7.764c-.302.136-.508.341-.674.673L5.03 14.043c-.312.645.196 1.152.84.84Zm4.09-3.72A1.19 1.19 0 0 1 8.77 9.97c0-.664.527-1.201 1.19-1.201a1.2 1.2 0 0 1 1.202 1.2c0 .655-.537 1.192-1.201 1.192Z"/></g>
<g fill="currentColor">
<path d="M9.96 19.922c5.45 0 9.962-4.522 9.962-9.961C19.922 4.51 15.4 0 9.952 0 4.511 0 0 4.512 0 9.96c0 5.44 4.521 9.962 9.96 9.962Zm0-1.66A8.26 8.26 0 0 1 1.67 9.96c0-4.61 3.672-8.3 8.281-8.3 4.61 0 8.31 3.69 8.31 8.3 0 4.61-3.69 8.3-8.3 8.3Z"/>
<path d="m5.87 14.883 5.605-2.735a1.47 1.47 0 0 0 .683-.673l2.725-5.596c.312-.664-.166-1.182-.85-.84L8.447 7.764c-.302.136-.508.341-.674.673L5.03 14.043c-.312.645.196 1.152.84.84Zm4.09-3.72A1.19 1.19 0 0 1 8.77 9.97c0-.664.527-1.201 1.19-1.201a1.2 1.2 0 0 1 1.202 1.2c0 .655-.537 1.192-1.201 1.192Z"/>
</g>
</svg>
</div>
</div>
Expand All @@ -246,7 +252,10 @@ <h5 class="offcanvas-title" id="pwaOffcanvasLabel">{% blocktranslate trimmed wit
<div class="col-2">
<div class="p-2">
<svg id="pwa-share" width="25" height="32" viewBox="0 0 17.695 26.475">
<g fill="currentColor"><path d="M17.334 10.762v9.746c0 2.012-1.025 3.027-3.066 3.027H3.066C1.026 23.535 0 22.52 0 20.508v-9.746C0 8.75 1.025 7.734 3.066 7.734h2.94v1.573h-2.92c-.977 0-1.514.527-1.514 1.543v9.57c0 1.015.537 1.543 1.514 1.543h11.152c.967 0 1.524-.527 1.524-1.543v-9.57c0-1.016-.557-1.543-1.524-1.543h-2.91V7.734h2.94c2.04 0 3.066 1.016 3.066 3.028Z"/><path d="M8.662 15.889c.42 0 .781-.352.781-.762V5.097l-.058-1.464.654.693 1.484 1.582a.698.698 0 0 0 .528.235c.4 0 .713-.293.713-.694 0-.205-.088-.361-.235-.508l-3.3-3.183c-.196-.196-.362-.264-.567-.264-.195 0-.361.069-.566.264L4.795 4.94a.681.681 0 0 0-.225.508c0 .4.293.694.703.694.186 0 .4-.079.538-.235l1.474-1.582.664-.693-.058 1.465v10.029c0 .41.351.762.771.762Z"/></g>
<g fill="currentColor">
<path d="M17.334 10.762v9.746c0 2.012-1.025 3.027-3.066 3.027H3.066C1.026 23.535 0 22.52 0 20.508v-9.746C0 8.75 1.025 7.734 3.066 7.734h2.94v1.573h-2.92c-.977 0-1.514.527-1.514 1.543v9.57c0 1.015.537 1.543 1.514 1.543h11.152c.967 0 1.524-.527 1.524-1.543v-9.57c0-1.016-.557-1.543-1.524-1.543h-2.91V7.734h2.94c2.04 0 3.066 1.016 3.066 3.028Z"/>
<path d="M8.662 15.889c.42 0 .781-.352.781-.762V5.097l-.058-1.464.654.693 1.484 1.582a.698.698 0 0 0 .528.235c.4 0 .713-.293.713-.694 0-.205-.088-.361-.235-.508l-3.3-3.183c-.196-.196-.362-.264-.567-.264-.195 0-.361.069-.566.264L4.795 4.94a.681.681 0 0 0-.225.508c0 .4.293.694.703.694.186 0 .4-.079.538-.235l1.474-1.582.664-.693-.058 1.465v10.029c0 .41.351.762.771.762Z"/>
</g>
</svg>
</div>
</div>
Expand All @@ -256,7 +265,9 @@ <h5 class="offcanvas-title" id="pwaOffcanvasLabel">{% blocktranslate trimmed wit
<div class="col-2">
<div class="m-2">
<svg id="pwa-add" width="25" height="25">
<g><path d="m23.40492,1.60784c-1.32504,-1.32504 -3.19052,-1.56912 -5.59644,-1.56912l-10.65243,0c-2.33622,0 -4.2017,0.24408 -5.5267,1.56912c-1.32504,1.34243 -1.56911,3.17306 -1.56911,5.50924l0,10.5827c0,2.40596 0.22665,4.254 1.55165,5.57902c1.34246,1.32501 3.19052,1.5691 5.59647,1.5691l10.60013,0c2.40592,0 4.2714,-0.24408 5.59644,-1.5691c1.325,-1.34245 1.55166,-3.17306 1.55166,-5.57902l0,-10.51293c0,-2.40596 -0.22666,-4.25401 -1.55166,-5.57901zm-0.38355,5.21289l0,11.24518c0,1.51681 -0.20924,2.94643 -1.02865,3.78327c-0.83683,0.83685 -2.30134,1.0635 -3.81815,1.0635l-11.33234,0c-1.51681,0 -2.96386,-0.22665 -3.80073,-1.0635c-0.83683,-0.83684 -1.04607,-2.26646 -1.04607,-3.78327l0,-11.19288c0,-1.5517 0.20924,-3.01617 1.02865,-3.85304c0.83687,-0.83683 2.31876,-1.04607 3.87042,-1.04607l11.28007,0c1.51681,0 2.98132,0.22666 3.81815,1.06353c0.81941,0.81941 1.02865,2.26645 1.02865,3.78327zm-10.53039,12.08205c0.64506,0 1.02861,-0.43586 1.02861,-1.13326l0,-4.34117l4.53294,0c0.66252,0 1.13326,-0.36613 1.13326,-0.99376c0,-0.64506 -0.43586,-1.02861 -1.13326,-1.02861l-4.53294,0l0,-4.53294c0,-0.6974 -0.38355,-1.13326 -1.02861,-1.13326c-0.62763,0 -0.99376,0.45332 -0.99376,1.13326l0,4.53294l-4.51552,0c-0.69737,0 -1.15069,0.38355 -1.15069,1.02861c0,0.62763 0.48817,0.99376 1.15069,0.99376l4.51552,0l0,4.34117c0,0.66252 0.36613,1.13326 0.99376,1.13326z" /></g>
<g>
<path d="m23.40492,1.60784c-1.32504,-1.32504 -3.19052,-1.56912 -5.59644,-1.56912l-10.65243,0c-2.33622,0 -4.2017,0.24408 -5.5267,1.56912c-1.32504,1.34243 -1.56911,3.17306 -1.56911,5.50924l0,10.5827c0,2.40596 0.22665,4.254 1.55165,5.57902c1.34246,1.32501 3.19052,1.5691 5.59647,1.5691l10.60013,0c2.40592,0 4.2714,-0.24408 5.59644,-1.5691c1.325,-1.34245 1.55166,-3.17306 1.55166,-5.57902l0,-10.51293c0,-2.40596 -0.22666,-4.25401 -1.55166,-5.57901zm-0.38355,5.21289l0,11.24518c0,1.51681 -0.20924,2.94643 -1.02865,3.78327c-0.83683,0.83685 -2.30134,1.0635 -3.81815,1.0635l-11.33234,0c-1.51681,0 -2.96386,-0.22665 -3.80073,-1.0635c-0.83683,-0.83684 -1.04607,-2.26646 -1.04607,-3.78327l0,-11.19288c0,-1.5517 0.20924,-3.01617 1.02865,-3.85304c0.83687,-0.83683 2.31876,-1.04607 3.87042,-1.04607l11.28007,0c1.51681,0 2.98132,0.22666 3.81815,1.06353c0.81941,0.81941 1.02865,2.26645 1.02865,3.78327zm-10.53039,12.08205c0.64506,0 1.02861,-0.43586 1.02861,-1.13326l0,-4.34117l4.53294,0c0.66252,0 1.13326,-0.36613 1.13326,-0.99376c0,-0.64506 -0.43586,-1.02861 -1.13326,-1.02861l-4.53294,0l0,-4.53294c0,-0.6974 -0.38355,-1.13326 -1.02861,-1.13326c-0.62763,0 -0.99376,0.45332 -0.99376,1.13326l0,4.53294l-4.51552,0c-0.69737,0 -1.15069,0.38355 -1.15069,1.02861c0,0.62763 0.48817,0.99376 1.15069,0.99376l4.51552,0l0,4.34117c0,0.66252 0.36613,1.13326 0.99376,1.13326z"/>
</g>
</svg>
</div>
</div>
Expand All @@ -271,7 +282,8 @@ <h5 class="offcanvas-title" id="notificationOffcanvasLabel">{% translate "Activa
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<p>{% blocktranslate trimmed with platform_name=platform_name %}{{ platform_name }} can send you push notifications so that you stay up to date. Do you want to activate them?" {% endblocktranslate %}</p>
<p>{% blocktranslate trimmed with platform_name=platform_name %}{{ platform_name }} can send you push
notifications so that you stay up to date. Do you want to activate them?" {% endblocktranslate %}</p>
<button id="webpush-subscribe-button" class="btn btn-sm btn-primary"
data-url="{% url "save_webpush_info" %}">
{% translate "Subscribe to Push Messaging" %}
Expand Down
Loading