aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--templates/web/base/common_scripts.html1
-rw-r--r--web/cobrands/fixmystreet/offline.js268
2 files changed, 144 insertions, 125 deletions
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/web/cobrands/fixmystreet/offline.js b/web/cobrands/fixmystreet/offline.js
index 76a6afc1f..1c5d36eda 100644
--- a/web/cobrands/fixmystreet/offline.js
+++ b/web/cobrands/fixmystreet/offline.js
@@ -8,8 +8,7 @@ fixmystreet.offlineBanner = (function() {
}
// Note this non-global way of handling plurals may need looking at in future
- function formText() {
- var num = fixmystreet.offlineData.getForms().length;
+ function formText(num) {
if ( num === 1 ) {
return num + ' ' + translation_strings.offline.update_single;
} else {
@@ -17,12 +16,12 @@ fixmystreet.offlineBanner = (function() {
}
}
- function onlineText() {
- return sprintf(translation_strings.offline.saved_to_submit, formText());
+ function onlineText(num) {
+ return sprintf(translation_strings.offline.saved_to_submit, formText(num));
}
- function offlineText() {
- return translation_strings.offline.you_are_offline + ' \u2013 ' + sprintf(translation_strings.offline.N_saved, formText());
+ function offlineText(num) {
+ return translation_strings.offline.you_are_offline + ' \u2013 ' + sprintf(translation_strings.offline.N_saved, formText(num));
}
function remove() {
@@ -31,24 +30,29 @@ fixmystreet.offlineBanner = (function() {
return {
make: function(offline) {
- var num = fixmystreet.offlineData.getForms().length;
- var banner = ['<div class="top_banner top_banner--offline"><p><span id="offline_saving"></span> <span id="offline_forms">'];
- if (offline || num > 0) {
- banner.push(offline ? offlineText() : onlineText());
- }
- banner.push('</span></p></div>');
- banner = $(banner.join(''));
- banner.prependTo('.content');
- if (num === 0) {
- banner.hide();
- }
+ fixmystreet.offlineData.getFormsLength().then(function(num) {
+ var banner = ['<div class="top_banner top_banner--offline"><p><span id="offline_saving"></span> <span id="offline_forms">'];
+ if (offline || num > 0) {
+ banner.push(offline ? offlineText(num) : onlineText(num));
+ }
+ banner.push('</span></p></div>');
+ banner = $(banner.join(''));
+ banner.prependTo('.content');
+ if (num === 0) {
+ banner.hide();
+ }
+ });
window.addEventListener("offline", function(e) {
- $('#offline_forms').html(offlineText());
+ fixmystreet.offlineData.getFormsLength().then(function(num) {
+ $('#offline_forms').html(offlineText(num));
+ });
});
window.addEventListener("online", function(e) {
- $('#offline_forms').html(onlineText());
+ fixmystreet.offlineData.getFormsLength().then(function(num) {
+ $('#offline_forms').html(onlineText(num));
+ });
});
function nextForm(DataOrJqXHR, textStatus, jqXHROrErrorThrown) {
@@ -62,37 +66,40 @@ fixmystreet.offlineBanner = (function() {
$(document).on('click', '#oFN', function(e) {
e.preventDefault();
- fixmystreet.offlineData.getForms().forEach(function(form) {
- $(document).queue('postForm', function() {
- postForm(form[0], form[1]).fail(function(jqXHR) {
- if (jqXHR.status !== 400) {
- return nextForm();
- }
- // In case the request failed due to out-of-date CSRF token,
- // try once more with a new token given in the error response.
- var m = jqXHR.responseText.match(/content="([^"]*)" name="csrf-token"/);
- if (!m) {
- return nextForm();
- }
- var token = m[1];
- if (!token) {
- return nextForm();
- }
- var param = form[1].replace(/&token=[^&]*/, '&token=' + token);
- return postForm(form[0], param).fail(nextForm);
+ fixmystreet.offlineData.getForms().then(function(forms) {
+ forms.forEach(function(form) {
+ $(document).queue('postForm', function() {
+ postForm(form[0], form[1]).fail(function(jqXHR) {
+ if (jqXHR.status !== 400) {
+ return nextForm();
+ }
+ // In case the request failed due to out-of-date CSRF token,
+ // try once more with a new token given in the error response.
+ var m = jqXHR.responseText.match(/content="([^"]*)" name="csrf-token"/);
+ if (!m) {
+ return nextForm();
+ }
+ var token = m[1];
+ if (!token) {
+ return nextForm();
+ }
+ var param = form[1].replace(/&token=[^&]*/, '&token=' + token);
+ return postForm(form[0], param).fail(nextForm);
+ });
});
});
+ $(document).dequeue('postForm');
});
- $(document).dequeue('postForm');
});
},
update: function() {
$('.top_banner--offline').slideDown();
- $('#offline_forms span').text(formText());
- var num = fixmystreet.offlineData.getForms().length;
- if (num === 0) {
- window.setTimeout(remove, 3000);
- }
+ fixmystreet.offlineData.getFormsLength().then(function(num) {
+ $('#offline_forms span').text(formText(num));
+ if (num === 0) {
+ window.setTimeout(remove, 3000);
+ }
+ });
},
startProgress: function(l) {
$('.top_banner--offline').slideDown();
@@ -115,61 +122,64 @@ fixmystreet.offlineData = (function() {
var data;
function getData() {
- if (data === undefined) {
- data = JSON.parse(localStorage.getItem('offlineData'));
- if (!data) {
- data = { cachedReports: {}, forms: [] };
- }
+ if (data !== undefined) {
+ return Promise.resolve(data);
}
- return data;
+ return idbKeyval.get('offlineData').then(function(d) {
+ data = d || { cachedReports: {}, forms: [] };
+ return data;
+ });
}
- function saveData() {
- localStorage.setItem('offlineData', JSON.stringify(getData()));
+ function updateData(cb) {
+ getData().then(function(data) {
+ cb(data);
+ idbKeyval.set('offlineData', data);
+ });
}
return {
+ getFormsLength: function() {
+ return getData().then(function(data) { return data.forms.length; });
+ },
getForms: function() {
- return getData().forms;
+ return getData().then(function(data) { return data.forms; });
},
addForm: function(action, formData) {
- var forms = getData().forms;
- if (!forms.length || formData != forms[forms.length - 1][1]) {
- forms.push([action, formData]);
- saveData();
- }
- fixmystreet.offlineBanner.update();
+ updateData(function(data) {
+ var forms = data.forms;
+ if (!forms.length || formData != forms[forms.length - 1][1]) {
+ forms.push([action, formData]);
+ }
+ fixmystreet.offlineBanner.update();
+ });
},
shiftForm: function(idx) {
- getData().forms.shift();
- saveData();
- fixmystreet.offlineBanner.update();
+ updateData(function(data) {
+ data.forms.shift();
+ fixmystreet.offlineBanner.update();
+ });
},
clearForms: function(idx) {
- getData().forms = [];
- saveData();
- fixmystreet.offlineBanner.update();
- },
- getCachedUrls: function() {
- return Object.keys(getData().cachedReports);
+ updateData(function(data) {
+ data.forms = [];
+ fixmystreet.offlineBanner.update();
+ });
},
- isIndexed: function(url, lastupdate) {
- if (lastupdate) {
- return getData().cachedReports[url] === lastupdate;
- }
- return !!getData().cachedReports[url];
+ getCachedReports: function() {
+ return getData().then(function(data) { return data.cachedReports; });
},
add: function(url, lastupdate) {
- var data = getData();
- data.cachedReports[url] = lastupdate || "-";
- saveData();
+ updateData(function(data) {
+ data.cachedReports[url] = lastupdate || "-";
+ });
},
remove: function(urls) {
- var data = getData();
- urls.forEach(function(url) {
- delete data.cachedReports[url];
+ updateData(function(data) {
+ urls.forEach(function(url) {
+ delete data.cachedReports[url];
+ });
});
- saveData();
}
};
})();
@@ -200,7 +210,7 @@ fixmystreet.cachet = (function(){
item.url + '/map' // Static map image
];
$reportPage.find('img').each(function(i, img) {
- if (img.src.indexOf('/photo/') === -1 || fixmystreet.offlineData.isIndexed(img.src) || urlsInProgress[img.src]) {
+ if (img.src.indexOf('/photo/') === -1 || urlsInProgress[img.src]) {
return;
}
imagesToGet.push(img.src);
@@ -247,27 +257,30 @@ fixmystreet.offline = (function() {
var toRemove = [];
var shouldBeCached = {};
- localStorage.setItem('/my/planned', $('.item-list').html());
+ idbKeyval.set('/my/planned', $('.item-list').html());
- getReportsFromList().forEach(function(item, i) {
- if (!fixmystreet.offlineData.isIndexed(item.url, item.lastupdate)) {
- toCache.push(item);
- }
- shouldBeCached[item.url] = 1;
- });
+ fixmystreet.offlineData.getCachedReports().then(function(reports) {
+ getReportsFromList().forEach(function(item, i) {
+ var t = reports[item.url];
+ if (t !== item.lastupdate) {
+ toCache.push(item);
+ }
+ shouldBeCached[item.url] = 1;
+ });
+
+ Object.keys(reports).forEach(function(url) {
+ if ( !shouldBeCached[url] ) {
+ toRemove.push(url);
+ }
+ });
- fixmystreet.offlineData.getCachedUrls().forEach(function(url) {
- if ( !shouldBeCached[url] ) {
- toRemove.push(url);
+ if (toRemove[0]) {
+ removeReports(toRemove);
+ }
+ if (toCache[0]) {
+ fixmystreet.cachet.cacheReports(toCache);
}
});
-
- if (toRemove[0]) {
- removeReports(toRemove);
- }
- if (toCache[0]) {
- fixmystreet.cachet.cacheReports(toCache);
- }
}
// Remove a list of reports from the offline cache
@@ -299,20 +312,22 @@ fixmystreet.offline = (function() {
$('.js-back-to-report-list').attr('href', '/my/planned');
// Refill form with saved data if there is any
- var savedForm;
- fixmystreet.offlineData.getForms().forEach(function(form) {
- if (form[0].endsWith(url)) {
- savedForm = form[1];
- }
- });
- if (savedForm) {
- savedForm.replace(/\+/g, '%20').split('&').forEach(function(kv) {
- kv = kv.split('=', 2);
- if (kv[0] != 'include_update' && kv[0] != 'public_update' && kv[0] != 'save') {
- $('[name=' + kv[0] + ']').val(decodeURIComponent(kv[1]));
+ fixmystreet.offlineData.getForms().then(function(forms) {
+ var savedForm;
+ forms.forEach(function(form) {
+ if (form[0].endsWith(url)) {
+ savedForm = form[1];
}
});
- }
+ if (savedForm) {
+ savedForm.replace(/\+/g, '%20').split('&').forEach(function(kv) {
+ kv = kv.split('=', 2);
+ if (kv[0] != 'include_update' && kv[0] != 'public_update' && kv[0] != 'save') {
+ $('[name=' + kv[0] + ']').val(decodeURIComponent(kv[1]));
+ }
+ });
+ }
+ });
// If we catch the form submit, e.g. Chrome still seems to
// try and submit and we get the Chrome offline error page
@@ -343,33 +358,36 @@ if (!navigator.onLine && location.pathname.indexOf('/report') === 0) {
if ($('#offline_list').length) {
// We are OFFLINE
- var html = localStorage.getItem('/my/planned');
- if (html) {
+ idbKeyval.get('/my/planned').then(function(html) {
+ if (!html) { return; }
$('#offline_list').before('<h2>'+translation_strings.offline.your_reports+'</h2>');
$('#offline_list').html(html);
if (location.search.indexOf('saved=1') > 0) {
$('#offline_list').before('<p class="form-success">'+translation_strings.offline.update_saved+'</p>');
}
- var offlineForms = fixmystreet.offlineData.getForms();
- var savedForms = {};
- offlineForms.forEach(function(form) {
- savedForms[form[0]] = 1;
- });
- $('#offline_list a').each(function(i, a) {
- if (savedForms[a.href]) {
- $(this).find('h3').prepend('<em>'+translation_strings.offline.update_data_saved+'</em> ');
- }
+ fixmystreet.offlineData.getForms().then(function(offlineForms) {
+ var savedForms = {};
+ offlineForms.forEach(function(form) {
+ savedForms[form[0]] = 1;
+ });
+ $('#offline_list a').each(function(i, a) {
+ if (savedForms[a.href]) {
+ $(this).find('h3').prepend('<em>'+translation_strings.offline.update_data_saved+'</em> ');
+ }
+ });
});
- $('#offline_clear').css('margin-top', '5em').html('<button id="js-clear-localStorage">'+translation_strings.offline.clear_data+'</button>');
- $('#js-clear-localStorage').click(function() {
+ $('#offline_clear').css('margin-top', '5em').html('<button id="js-clear-storage">'+translation_strings.offline.clear_data+'</button>');
+ $('#js-clear-storage').click(function() {
if (window.confirm(translation_strings.offline.are_you_sure)) {
- fixmystreet.offline.removeReports(fixmystreet.offlineData.getCachedUrls());
+ fixmystreet.offlineData.getCachedReports().then(function(reports) {
+ fixmystreet.offline.removeReports(Object.keys(reports));
+ });
fixmystreet.offlineData.clearForms();
- localStorage.removeItem('/my/planned');
+ idbKeyval.del('/my/planned');
alert(translation_strings.offline.data_cleared);
}
});
- }
+ });
fixmystreet.offlineBanner.make(true);
} else {
fixmystreet.offlineBanner.make(false);