aboutsummaryrefslogtreecommitdiffstats
path: root/templates
diff options
context:
space:
mode:
Diffstat (limited to 'templates')
-rw-r--r--templates/web/base/common_header_tags.html9
-rw-r--r--templates/web/base/common_scripts.html1
-rw-r--r--templates/web/base/header.html5
-rw-r--r--templates/web/base/offline/fallback.html (renamed from templates/web/base/offline/appcache.html)8
-rw-r--r--templates/web/base/offline/manifest.html16
-rw-r--r--templates/web/base/offline/service_worker.html104
-rw-r--r--templates/web/oxfordshire/header.html5
7 files changed, 119 insertions, 29 deletions
diff --git a/templates/web/base/common_header_tags.html b/templates/web/base/common_header_tags.html
index 728b81363..279f561df 100644
--- a/templates/web/base/common_header_tags.html
+++ b/templates/web/base/common_header_tags.html
@@ -1,6 +1,7 @@
[% SET start = c.config.ADMIN_BASE_URL IF admin %]
<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<link rel="manifest" href="/.well-known/manifest.webmanifest">
[% IF csrf_token %]
<meta content="[% csrf_token %]" name="csrf-token" />
@@ -15,6 +16,14 @@
(function(a){a=a.documentElement;a.className=a.className.replace(/\bno-js\b/,"js");var b=-1<a.className.indexOf("ie8");b=Modernizr.mq("(min-width: 48em)")||b?"desktop":"mobile";"IntersectionObserver"in window&&(a.className+=" lazyload");"mobile"==b&&(a.className+=' mobile[% " map-fullscreen only-map map-reporting" IF page == "around" %]')})(document);
</script>
+<script nonce="[% csp_nonce %]">
+if ('serviceWorker' in navigator) {
+ window.addEventListener('load', function() {
+ navigator.serviceWorker.register('/service-worker.js');
+ });
+}
+</script>
+
[% IF robots %]
<meta name="robots" content="[% robots %]">
[% ELSIF c.config.STAGING_SITE %]
diff --git a/templates/web/base/common_scripts.html b/templates/web/base/common_scripts.html
index 7df8feaa0..f94b3d464 100644
--- a/templates/web/base/common_scripts.html
+++ b/templates/web/base/common_scripts.html
@@ -46,6 +46,7 @@ IF c.user_exists AND (c.user.from_body OR c.user.is_superuser);
END;
IF c.user.has_body_permission_to('planned_reports');
scripts.push(
+ 'https://cdn.jsdelivr.net/npm/idb-keyval@3/dist/idb-keyval-iife.min.js',
version('/cobrands/fixmystreet/offline.js'),
);
END;
diff --git a/templates/web/base/header.html b/templates/web/base/header.html
index 74ec2d16a..b3d77b3a6 100644
--- a/templates/web/base/header.html
+++ b/templates/web/base/header.html
@@ -6,10 +6,7 @@
<!doctype html>
<!--[if IE 8]> <html class="no-js ie8"[% html_att | safe %]><![endif]-->
<!--[if IE 9]> <html class="no-js ie9"[% html_att | safe %]><![endif]-->
-<!--[if gt IE 9]><!--><html class="no-js"[% html_att | safe %]
-[% IF appcache ~%]
- manifest="/offline/appcache.manifest"
-[%~ END %]><!--<![endif]-->
+<!--[if gt IE 9]><!--><html class="no-js"[% html_att | safe %]><!--<![endif]-->
<head>
<meta name="viewport" content="initial-scale=1.0">
diff --git a/templates/web/base/offline/appcache.html b/templates/web/base/offline/fallback.html
index ed48b7a00..b8e1ee9b9 100644
--- a/templates/web/base/offline/appcache.html
+++ b/templates/web/base/offline/fallback.html
@@ -1,11 +1,9 @@
[% SET bodyclass = "fullwidthpage offlinepage" ~%]
-[% INCLUDE 'header.html' appcache = 1 %]
+[% INCLUDE 'header.html' %]
-<h1>[% loc('Internet glitch') %]</h1>
+<h1>[% loc('Offline') %]</h1>
-<p>[% loc('Sorry, we don’t have a good enough connection to fetch that page, or the
-page wasn’t found or there was a server error. Please try again later.') %]
-</p>
+<p>[% loc('Sorry, we don’t have a good enough connection to fetch that page.') %]</p>
<ul class="item-list item-list--reports" id="offline_list"></ul>
diff --git a/templates/web/base/offline/manifest.html b/templates/web/base/offline/manifest.html
deleted file mode 100644
index 93d26cb94..000000000
--- a/templates/web/base/offline/manifest.html
+++ /dev/null
@@ -1,16 +0,0 @@
-CACHE MANIFEST
-
-[% PROCESS 'common_scripts.html' ~%]
-
-CACHE:
-[% version('/cobrands/' _ c.cobrand.asset_moniker _ '/base.css') %]
-[% version('/cobrands/' _ c.cobrand.asset_moniker _ '/layout.css') %]
-[% FOR script IN scripts ~%]
- [%- script %]
-[% END %]
-
-NETWORK:
-*
-
-FALLBACK:
-/ [% version('../templates/web/base/offline/appcache.html', '/offline/appcache') %]
diff --git a/templates/web/base/offline/service_worker.html b/templates/web/base/offline/service_worker.html
new file mode 100644
index 000000000..0feb26ce6
--- /dev/null
+++ b/templates/web/base/offline/service_worker.html
@@ -0,0 +1,104 @@
+[%
+SET bodyclass = "offlinepage"; # For selection of scripts
+PROCESS 'common_scripts.html';
+SET offline_html = version('../templates/web/base/offline/fallback.html', '/offline/fallback');
+SET scripts_seen = {};
+
+~%]
+
+importScripts('https://cdn.jsdelivr.net/npm/idb-keyval@3/dist/idb-keyval-iife.min.js');
+
+const requiredOffline = [
+ "[% version('/cobrands/' _ c.cobrand.asset_moniker _ '/base.css') %]",
+ "[% version('/cobrands/' _ c.cobrand.asset_moniker _ '/layout.css') %]",
+ "[% version('/vendor/OpenLayers/theme/default/style.css') %]",
+ "[% version('/vendor/fancybox/jquery.fancybox-1.3.4.css') %]",
+ [%
+ FOR script IN scripts;
+ NEXT IF scripts_seen.${script};
+ scripts_seen.${script} = 1;
+ ~%]
+ "[%- script %]",
+ [% END %]
+ "[% offline_html %]"
+];
+
+const staticCache = 'static';
+// const pageCache = 'pages';
+
+addEventListener('install', function(evt) {
+ evt.waitUntil(precache());
+});
+
+async function precache() {
+ const cache = await caches.open(staticCache);
+ return cache.addAll(requiredOffline);
+}
+
+addEventListener('fetch', fetchEvent => {
+ const request = fetchEvent.request;
+ const url = new URL(request.url);
+
+ if (url.origin !== location.origin) {
+ return;
+ }
+
+ // Handle inspection form submission if offline...
+ if (request.method === 'POST' && RegExp('/report/\\d+$').test(url)) {
+ fetchEvent.respondWith(async function() {
+ const fetchPromise = fetch(request.clone());
+ try {
+ return await fetchPromise;
+ }
+ catch {
+ fetchEvent.waitUntil(async function() {
+ var text = await request.text();
+ let formData = new URLSearchParams(text);
+ formData.set('save', 2);
+ formData.set('saved_at', Math.floor(+new Date() / 1000));
+ formData = formData.toString();
+
+ var data = await idbKeyval.get('offlineData') || { cachedReports: {}, forms: [] };
+ var forms = data.forms;
+ if (!forms.length || formData != forms[forms.length - 1][1]) {
+ forms.push([request.url, formData]);
+ }
+ return idbKeyval.set('offlineData', data);
+ }());
+
+ return Response.redirect('/my/planned?saved=1');
+ };
+ }());
+ }
+
+ if (request.method !== "GET") {
+ return;
+ }
+
+ fetchEvent.respondWith(async function() {
+ if (request.mode === 'navigate') {
+ const fetchPromise = fetch(request);
+
+// For now, only save pages manually for inspectors
+// fetchEvent.waitUntil(async function() {
+// const responseCopy = (await fetchPromise).clone();
+// const cache = await caches.open(pageCache);
+// await responseCopy.ok ? cache.put(request, responseCopy) : cache.delete(request);
+// }());
+
+ try {
+ return await fetchPromise;
+ }
+ catch {
+ let cached = await caches.match(request) || await caches.match("[% offline_html %]");
+ return cached || offlineResponse();
+ }
+ } else {
+ const responseFromCache = await caches.match(request);
+ return responseFromCache || fetch(request);
+ }
+ }());
+});
+
+var offlineResponse = () =>
+ new Response('Service Unavailable', { status: 503, statusText: 'Service Unavailable', headers: { 'Content-Type': 'text/html' }});
diff --git a/templates/web/oxfordshire/header.html b/templates/web/oxfordshire/header.html
index 70d7e4b18..72cba2aec 100644
--- a/templates/web/oxfordshire/header.html
+++ b/templates/web/oxfordshire/header.html
@@ -1,10 +1,7 @@
<!doctype html>
<!--[if IE 8]> <html class="no-js ie8" lang="[% lang_code %]"><![endif]-->
<!--[if IE 9]> <html class="no-js ie9" lang="[% lang_code %]"><![endif]-->
-<!--[if gt IE 9]><!--><html class="no-js" lang="[% lang_code %]"
-[% IF appcache ~%]
- manifest="/offline/appcache.manifest"
-[%~ END %]><!--<![endif]-->
+<!--[if gt IE 9]><!--><html class="no-js" lang="[% lang_code %]"><!--<![endif]-->
<head>
<meta name="viewport" content="initial-scale=1.0">