diff --git a/plinth/modules/backups/forms.py b/plinth/modules/backups/forms.py
index b331f0334..3883a80d3 100644
--- a/plinth/modules/backups/forms.py
+++ b/plinth/modules/backups/forms.py
@@ -40,7 +40,7 @@ logger = logging.getLogger(__name__)
def _get_app_choices(apps):
"""Return a list of check box multiple choices from list of apps."""
- choices = []
+ choices = [('select_all', _("Include all apps"))]
for app in apps:
name = app.app.name
if not app.has_data:
diff --git a/plinth/modules/backups/static/select_all.js b/plinth/modules/backups/static/select_all.js
new file mode 100644
index 000000000..416ed64fc
--- /dev/null
+++ b/plinth/modules/backups/static/select_all.js
@@ -0,0 +1,50 @@
+/*
+ This file is part of FreedomBox.
+
+ @licstart The following is the entire license notice for the
+ JavaScript code in this page.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+ @licend The above is the entire license notice
+ for the JavaScript code in this page.
+*/
+
+
+// jQuery selector for the "select all" checkbox
+var select_all = "#id_backups-selected_apps_0";
+
+// Initialize the "select all" checkbox to checked
+$(select_all).prop('checked', true);
+
+/*
+ * When there is a change on the "select all" checkbox,set the
+ * checked property of all the checkboxes to the value of the
+ * "select all" checkbox
+ */
+$(select_all).change(function() {
+ $(":checkbox").prop('checked', $(this).prop("checked"));
+});
+
+
+$(':checkbox').change(function() {
+ // If the rest of the checkbox items are checked check the "select all" checkbox as well
+ if ($(':checkbox:checked').length == ($(':checkbox').length-1)) {
+ $(select_all).prop('checked', true);
+ }
+ // Uncheck "select all" if one of the listed checkbox item is unchecked
+ if (false == $(this).prop("checked")) {
+ $(select_all).prop('checked', false);
+ }
+});
diff --git a/plinth/modules/backups/templates/backups_form.html b/plinth/modules/backups/templates/backups_form.html
index 9d466d606..0d7999d3a 100644
--- a/plinth/modules/backups/templates/backups_form.html
+++ b/plinth/modules/backups/templates/backups_form.html
@@ -20,16 +20,21 @@
{% load bootstrap %}
{% load i18n %}
+{% load static %}
{% block configuration %}
{% endblock %}
+
+{% block page_js %}
+
+{% endblock %}
diff --git a/plinth/modules/backups/templates/backups_restore.html b/plinth/modules/backups/templates/backups_restore.html
index 116068267..6b58ccf16 100644
--- a/plinth/modules/backups/templates/backups_restore.html
+++ b/plinth/modules/backups/templates/backups_restore.html
@@ -59,4 +59,5 @@
{% block page_js %}
+
{% endblock %}
diff --git a/plinth/modules/backups/views.py b/plinth/modules/backups/views.py
index d917079d5..230508abc 100644
--- a/plinth/modules/backups/views.py
+++ b/plinth/modules/backups/views.py
@@ -103,7 +103,8 @@ class CreateArchiveView(SuccessMessageMixin, FormView):
repository.mount()
name = datetime.now().strftime('%Y-%m-%d:%H:%M')
- repository.create_archive(name, form.cleaned_data['selected_apps'])
+ selected_apps = form.cleaned_data['selected_apps'][1:]
+ repository.create_archive(name, selected_apps)
return super().form_valid(form)
@@ -224,7 +225,8 @@ class RestoreFromUploadView(BaseRestoreView):
def form_valid(self, form):
"""Restore files from the archive on valid form submission."""
path = self.request.session.get(SESSION_PATH_VARIABLE)
- backups.restore_from_upload(path, form.cleaned_data['selected_apps'])
+ selected_apps = form.cleaned_data['selected_apps'][1:]
+ backups.restore_from_upload(path, selected_apps)
return super().form_valid(form)
@@ -241,8 +243,8 @@ class RestoreArchiveView(BaseRestoreView):
def form_valid(self, form):
"""Restore files from the archive on valid form submission."""
repository = get_repository(self.kwargs['uuid'])
- repository.restore_archive(self.kwargs['name'],
- form.cleaned_data['selected_apps'])
+ selected_apps = form.cleaned_data['selected_apps'][1:]
+ repository.restore_archive(self.kwargs['name'], selected_apps)
return super().form_valid(form)