diff options
author | Matthew Somerville <matthew@mysociety.org> | 2019-12-19 09:23:21 +0000 |
---|---|---|
committer | Matthew Somerville <matthew@mysociety.org> | 2020-02-14 10:38:49 +0000 |
commit | 0e80a90bebc12fe381892386f9ffd751edb38d7c (patch) | |
tree | 50f5ac13f745f6142c9b6cab726dacda2fb447fe /templates | |
parent | 43290e5f733b4e88c6b4e5467b7e446a416a4682 (diff) |
Initial service worker.
This basic service worker behaves identically to the existing appcache -
some static scripts and CSS are cached, any HTML offline instead returns
a static HTML page that knows how to show data on stored problems out of
localStorage (stored there when /my/planned was visited online). Inspect
form submissions will be captured and can be synced back when online.
Once feature parity is established, we will then remove appcache, switch
from using localStorage to the cache API, and hopefully move all offline
support into the service worker.
Diffstat (limited to 'templates')
-rw-r--r-- | templates/web/base/common_header_tags.html | 8 | ||||
-rw-r--r-- | templates/web/base/offline/fallback.html | 12 | ||||
-rw-r--r-- | templates/web/base/offline/service_worker.html | 62 |
3 files changed, 82 insertions, 0 deletions
diff --git a/templates/web/base/common_header_tags.html b/templates/web/base/common_header_tags.html index d54d97297..279f561df 100644 --- a/templates/web/base/common_header_tags.html +++ b/templates/web/base/common_header_tags.html @@ -16,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/offline/fallback.html b/templates/web/base/offline/fallback.html new file mode 100644 index 000000000..b8e1ee9b9 --- /dev/null +++ b/templates/web/base/offline/fallback.html @@ -0,0 +1,12 @@ +[% SET bodyclass = "fullwidthpage offlinepage" ~%] +[% INCLUDE 'header.html' %] + +<h1>[% loc('Offline') %]</h1> + +<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> + +<div id="offline_clear"></div> + +[% INCLUDE 'footer.html' %] diff --git a/templates/web/base/offline/service_worker.html b/templates/web/base/offline/service_worker.html new file mode 100644 index 000000000..1005e959b --- /dev/null +++ b/templates/web/base/offline/service_worker.html @@ -0,0 +1,62 @@ +[% +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 = {}; + +~%] + +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'; + +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 (request.method !== "GET" || url.origin !== location.origin) { + return; + } + + fetchEvent.respondWith(async function() { + if (request.mode === 'navigate') { + const fetchPromise = fetch(request); + + try { + return await fetchPromise; + } + catch { + let cached = 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' }});
\ No newline at end of file |