Skip to content

Commit

Permalink
- added storage management
Browse files Browse the repository at this point in the history
- added delete activity
- fixed broken tests
  • Loading branch information
temi committed Oct 12, 2023
1 parent eb90541 commit 98ae5b9
Show file tree
Hide file tree
Showing 13 changed files with 251 additions and 9 deletions.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ buildscript {
}
}

plugins {
id "com.gorylenko.gradle-git-properties" version "2.4.1"
}


version "$biocollectVersion"
group "au.org.ala"
Expand Down
26 changes: 24 additions & 2 deletions grails-app/assets/javascripts/offline-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ function ActivitiesViewModel (config) {
}
}

/**
* Soft delete an activity from list
* @param activity
*/
self.remove = function(activity) {
self.activities.remove(activity);
}
Expand Down Expand Up @@ -204,16 +208,34 @@ function ActivityViewModel (activity, parent) {
return deferred.promise();
}

/**
* Hard delete an activity from the database
*/
self.deleteActivity = function() {
bootbox.confirm("This operation cannot be reversed. Are you sure you want to delete this activity?", function (result) {
if (result) {
entities.deleteActivity().then(function () {
parent.refreshPage();
self.uploading(true);
images = images || [];
var documentIds = images.map(image => image.documentId);
self.deleteImages({data:documentIds}).then(self.deleteSite).then(self.deleteActivityById).then(function (){
parent.refreshPage(0);
}).then(function () {
self.uploading(false);
}, function () {
self.uploading(false);
});
}
})
}

self.deleteSite = function () {
return entities.deleteSites([activity.siteId]);
}

self.deleteActivityById = function () {
return self.deleteActivityFromDB({data: {oldActivityId: activity.activityId}});
}

self.removeMeFromList = function() {
parent.remove(self);
}
Expand Down
2 changes: 2 additions & 0 deletions grails-app/assets/javascripts/pwa-offline-list-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
//= require emitter/emitter.js
//= require moment/moment.min.js
//= require moment/moment-timezone-with-data.min.js
//= require bootstrap4/js/bootstrap.bundle.min.js
//= require bootbox/bootbox.min.js
//= require knockout-dates.js
//= require fieldcapture-application.js
//= require enterBioActivityData.js
Expand Down
8 changes: 8 additions & 0 deletions grails-app/assets/javascripts/pwa-settings-manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//= require jquery/3.4.1/jquery-3.4.1.min.js
//= require knockout/3.4.0/knockout-3.4.0.js
//= require utils.js
//= require dexiejs/dexie.js
//= require bootstrap4/js/bootstrap.bundle.min.js
//= require bootbox/bootbox.min.js
//= require entities.js
//= require pwa-settings.js
83 changes: 83 additions & 0 deletions grails-app/assets/javascripts/pwa-settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
function StorageViewModel() {
var self = this,
deleteSteps = ['cache', 'db'];
self.maximum = ko.observable();
self.used = ko.observable();
self.free = ko.observable();
self.percentage = ko.computed(function () {
return Math.round(self.used() / self.maximum() * 100);
});
self.isOffline = ko.observable(false);
self.deleteProgress = ko.observable(0);
self.deleteSteps = ko.observable(deleteSteps.length);
self.deletePercentage = ko.computed(function () {
return Math.round(self.deleteProgress() / self.deleteSteps() * 100);
});
self.supported = ko.observable(true);
self.refresh = function () {
if (navigator.storage && navigator.storage.estimate) {
navigator.storage.estimate().then(
({ usage, quota }) => {
var gbUnit = 1024 * 1024 * 1024;
self.maximum(quota / gbUnit);
self.used(usage / gbUnit);
self.free(self.maximum() - self.used());
},
error => console.warn(`error estimating quota: ${error.name}: ${error.message}`)
);
}
else {
self.supported(false);
}
}

self.clearAll = function () {
self.deleteProgress(0);
bootbox.confirm("This operation cannot be reversed. Are you sure you want to delete?", function (result) {
if (result) {
self.deleteCache().then(self.deleteDBEntries).then(function () {
self.deleteProgress(self.deleteSteps());
});
}
});
}

self.deleteCache = function () {
return caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.map(function (cacheName) {
return caches.delete(cacheName);
})
);
}).then(function () {
self.refresh();
self.deleteProgress(self.deleteProgress() + 1);
});
}

self.deleteDBEntries = function () {
return entities.deleteTable('offlineMap').then(function () {
return entities.deleteTable('taxon').then(function () {
self.deleteProgress(self.deleteProgress() + 1);
});
});
}

document.addEventListener('offline', function () {
self.isOffline(true);
});

document.addEventListener('online', function () {
self.isOffline(false);
});

self.refresh();
}

function initialise() {
var storageViewModel = new StorageViewModel();
ko.applyBindings(storageViewModel, document.getElementById('storage-settings'));
checkOfflineForIntervalAndTriggerEvents(5000);
}

$(document).ready(initialise);
3 changes: 3 additions & 0 deletions grails-app/assets/stylesheets/pwa-settings-manifest.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/**
*= require base-bs4.css
*/
2 changes: 1 addition & 1 deletion grails-app/conf/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ grails:
---
#pwa
pwa:
appUrl: "http://localhost:8087"
appUrl: "http://localhost:5173"
cache:
ignore: ["/image/upload", "/ws/attachment/upload"]
baseMapUrl: "https://api.maptiler.com/maps/hybrid/{z}/{x}/{y}.jpg?key=WlLML7VfJfVwucTTgdcR"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,9 @@ class BioActivityController {
def pwaConfig () {
}

def pwaSettings () {
}

/**
* Preview activity survey form template
* @param formName Survey form name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class UrlMappings {
"/pwa/indexFragment/$projectActivityId" (controller: 'bioActivity', action: 'pwaIndexFragment')

"/pwa/offlineList" ( controller: 'bioActivity', action: 'pwaOfflineList' )
"/pwa/settings" (controller: 'bioActivity', action: 'pwaSettings')


"500"(controller:'error', action:'response500')
Expand Down
16 changes: 15 additions & 1 deletion grails-app/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1037,4 +1037,18 @@ pwa.offlinelist.species.heading=Species
pwa.offlinelist.record.image.alt=Image associated with record
pwa.offlinelist.record.noimage.alt=No image associated with record
label.upload=Upload
bioactivity.save=Save
bioactivity.save=Save
pwa.settings.heading=Settings
pwa.settings.storage.heading=Storage quota
pwa.settings.storage.total=Maximum storage (GB)
pwa.settings.storage.totalPercentage=Percentage used
pwa.settings.storage.used=Disk used (GB)
pwa.settings.storage.free=Free space (GB)
pwa.settings.storage.alert.heading=Unsupported
pwa.settings.storage.alert.message=Your browser does not support storage estimation. Some browsers that support this feature are - Safari (17), Chrome (61), Edge(79), Firefox(57) etc.
pwa.settings.storage.btn.refresh=Refresh
pwa.settings.manage.title=Manage storage
pwa.settings.manage.alert.heading=Delete items
pwa.settings.manage.alert.message=Delete items to make disk space. The following items will be deleted. <b>Unpublished records will not be deleted.</b> You will have to re-download surveys for them to wrok offline.
pwa.settings.manage.btn.clearAll=Delete
pwa.settings.manage.delete.progress=Deletion progress
12 changes: 7 additions & 5 deletions grails-app/views/bioActivity/pwaOfflineList.gsp
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,23 @@
<li data-bind="text: name"></li>
</ol>
</td>
<td>
<td class="btn-space">
<button class="btn btn-success btn-sm" data-bind="click: upload, enable: $parent.online, disable: disableUpload"><i class="fas fa-upload"></i> <g:message code="label.upload"/></button>
<a class="btn btn-primary btn-sm" data-bind="attr: {href: transients.viewActivityUrl()}, disable: uploading"><i class="far fa-eye"></i> <g:message code="label.view"/></a>
<a class="btn btn-dark btn-sm" data-bind="attr: {href: transients.editActivityUrl()}, disable: uploading"><i class="fas fa-pencil-alt"></i> <g:message code="label.edit"/></a>
<button class="btn btn-dark btn-sm" data-bind="click: upload, enable: $parent.online, disable: disableUpload"><i class="fas fa-upload"></i> <g:message code="label.upload"/></button>
<button class="btn btn-danger btn-sm" data-bind="click: upload, enable: $parent.online, disable: uploading"><i class="fas fa-upload"></i> <g:message code="label.delete"/></button>
<button class="btn btn-danger btn-sm" data-bind="click: deleteActivity, enable: $parent.online, disable: uploading"><i class="far fa-trash-alt"></i> <g:message code="label.delete"/></button>
</td>
</tr>
<!-- /ko -->
<tr data-bind="if : activities().length == 0">
<!-- ko if: activities().length == 0 -->
<tr>
<td colspan="4">
<div class="alert alert-info" role="alert">
<g:message code="pwa.activities.empty.msg"/>
</div>
</td>
</tr>
<!-- /ko -->
</tbody>
</table>
</div>
Expand All @@ -86,7 +88,7 @@
</div>
<script id="page-actions-buttons" type="text/html">
<div class="my-2 float-right">
<button type="button" class="btn btn-primary" data-bind="click: uploadAllHandler, disable: disableUpload()"><i class="fas fa-upload"></i> <g:message code="pwa.upload.all"/></button>
<button type="button" class="btn btn-success" data-bind="click: uploadAllHandler, disable: disableUpload()"><i class="fas fa-upload"></i> <g:message code="pwa.upload.all"/></button>
<!-- ko if: transients.isProjectActivity -->
<a class="btn btn-primary" id="create-activity" data-bind="attr: {href: transients.addActivityUrl()}"> <i class="fas fa-plus"></i> <g:message code="pwa.add.records"/></a>
<!-- /ko -->
Expand Down
99 changes: 99 additions & 0 deletions grails-app/views/bioActivity/pwaSettings.gsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta name="layout" content="pwa"/>
<title>PWA settings</title>
<asset:stylesheet src="pwa-settings-manifest.css"/>
<asset:javascript src="pwa-settings-manifest.js"/>
<asset:script>
var fcConfig = {
siteUrl: "/ws/site",
addActivityUrl: "/pwa/bioActivity/edit",
activityViewUrl: "/pwa/bioActivity/index",
activityEditUrl: "/pwa/bioActivity/edit",
imageUploadUrl: "/ws/attachment/upload",
bioActivityUpdate: "/ws/bioactivity/save",
updateSiteUrl: "/ws/bioactivity/site",
noImageUrl: "${asset.assetPath(src: "font-awesome/5.15.4/svgs/regular/image.svg")}",
pwaAppUrl: "${grailsApplication.config.getProperty('pwa.appUrl')}",
isCaching: ${params.getBoolean('cache', false)},
enableOffline: true
};
</asset:script>
</head>

<body>
<div class="container">
<h1><g:message code="pwa.settings.heading"/></h1>
<div id="storage-settings">
<bc:koLoading>
<h3><g:message code="pwa.settings.storage.heading"/></h3>
<!-- ko if: supported -->
<table class="table">
<tbody>
<tr>
<td colspan="2">
<div class="progress">
<div class="progress-bar bg-success" role="progressbar" data-bind="style: {width: percentage() + '%'}, text: percentage() + '%', attr: {'aria-valuenow': percentage}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</td>
</tr>
<tr>
<td><g:message code="pwa.settings.storage.total"/></td>
<td data-bind="text: maximum"></td>
</tr>
<tr>
<td><g:message code="pwa.settings.storage.free"/></td>
<td data-bind="text: free"></td>
</tr>
<tr>
<td><g:message code="pwa.settings.storage.used"/></td>
<td data-bind="text: used"></td>
</tr>
<tr>
<td><g:message code="pwa.settings.storage.totalPercentage"/></td>
<td data-bind="text: percentage() + ' %'"></td>
</tr>
<tr>
<td colspan="2">
<button class="btn btn-sm btn-success" data-bind="click: refresh">
<i class="fas fa-sync"></i>
<g:message code="pwa.settings.storage.btn.refresh"/>
</button>
</td>
</tr>
</tbody>
</table>
<!-- /ko -->
<!-- ko ifnot: supported -->
<div class="alert alert-info" role="alert">
<h4 class="alert-heading"><g:message code="pwa.settings.storage.alert.heading"/> </h4>
<p><g:message code="pwa.settings.storage.alert.message"/></p>
</div>
<!-- /ko -->
<h3><g:message code="pwa.settings.manage.title"/> </h3>
<div class="alert alert-danger" role="alert">
<h4 class="alert-heading"><g:message code="pwa.settings.manage.alert.heading"/> </h4>
<p><g:message code="pwa.settings.manage.alert.message"/></p>
</div>
<div class="row mb-2">
<div class="col-12">
<button class="btn btn-danger" data-bind="click: clearAll, disable: isOffline">
<i class="fas fa-trash"></i>
<g:message code="pwa.settings.manage.btn.clearAll"/>
</button>
</div>
</div>
<h6><g:message code="pwa.settings.manage.delete.progress"/> </h6>
<div class="row">
<div class="col-12">
<div class="progress">
<div class="progress-bar bg-success" role="progressbar" data-bind="style: {width: deletePercentage() + '%'}, text: deletePercentage() + '%', attr: {'aria-valuenow': deletePercentage}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
</bc:koLoading>
</div>
</div>
</body>
</html>
1 change: 1 addition & 0 deletions src/test/js/spec/PwaIndexSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ describe("PwaIndexSpec", function (){
beforeAll(function() {
window.maxArea = 25 * 1000 * 1000;
window.L.Google = function(){};
window.L.Google.isGoogleMapsReady = function () {return false};
window.ALA = {
MapConstants : {
/**
Expand Down

0 comments on commit 98ae5b9

Please sign in to comment.