diff --git a/plinth/modules/backups/api.py b/plinth/modules/backups/api.py
index 92851a661..f359c35ae 100644
--- a/plinth/modules/backups/api.py
+++ b/plinth/modules/backups/api.py
@@ -169,7 +169,7 @@ def backup_apps(backup_handler, path, app_names=None,
if not app_names:
apps = get_all_apps_for_backup()
else:
- apps = _get_apps_in_order(app_names)
+ apps = get_apps_in_order(app_names)
if _is_snapshot_available():
snapshot = _take_snapshot()
@@ -198,7 +198,7 @@ def restore_apps(restore_handler, app_names=None, create_subvolume=True,
if not app_names:
apps = get_all_apps_for_backup()
else:
- apps = _get_apps_in_order(app_names)
+ apps = get_apps_in_order(app_names)
_install_apps_before_restore(apps)
@@ -261,6 +261,13 @@ class BackupApp:
self.manifest == other_app.manifest and \
self.has_data == other_app.has_data
+ def is_installed(self):
+ """Return whether app is installed.
+
+ Return true even if the app needs update.
+ """
+ return self.app.setup_helper.get_state() != 'needs-setup'
+
def run_hook(self, hook, packet):
"""Run a hook inside an application."""
if not hasattr(self.app, hook):
@@ -280,14 +287,16 @@ def get_all_apps_for_backup():
apps = []
for module_name, module in module_loader.loaded_modules.items():
try:
- apps.append(BackupApp(module_name, module))
+ backup_app = BackupApp(module_name, module)
+ if backup_app.is_installed():
+ apps.append(backup_app)
except TypeError: # Application not available for backup/restore
pass
return apps
-def _get_apps_in_order(app_names):
+def get_apps_in_order(app_names):
"""Return a list of app modules in order of dependency."""
apps = []
for module_name, module in module_loader.loaded_modules.items():
diff --git a/plinth/modules/backups/static/loading_button.js b/plinth/modules/backups/static/loading_button.js
index bc87c4ca1..d5e90d24f 100644
--- a/plinth/modules/backups/static/loading_button.js
+++ b/plinth/modules/backups/static/loading_button.js
@@ -22,6 +22,8 @@
*/
+// XXX: This is misuse of sr-only class. This is problematic for people using
+// screen readers.
function swapWithLoadingButton() {
$("#restore_btn").addClass("sr-only");
$("#loading_btn").removeClass("sr-only");
diff --git a/plinth/modules/backups/templates/backups_restore.html b/plinth/modules/backups/templates/backups_restore.html
index e940b691d..4893911d7 100644
--- a/plinth/modules/backups/templates/backups_restore.html
+++ b/plinth/modules/backups/templates/backups_restore.html
@@ -59,6 +59,6 @@
{% endblock %}
{% block page_js %}
-
+
{% endblock %}
-
diff --git a/plinth/modules/backups/tests/test_api.py b/plinth/modules/backups/tests/test_api.py
index b1b31048c..8f256c8e0 100644
--- a/plinth/modules/backups/tests/test_api.py
+++ b/plinth/modules/backups/tests/test_api.py
@@ -140,7 +140,7 @@ class TestBackupProcesses(unittest.TestCase):
@staticmethod
@patch('plinth.module_loader.loaded_modules.items')
- def test__get_apps_in_order(modules):
+ def test_get_apps_in_order(modules):
"""Test that apps are listed in correct dependency order."""
apps = [
('names', MagicMock(backup=_get_test_manifest('names'))),
@@ -150,7 +150,7 @@ class TestBackupProcesses(unittest.TestCase):
module_loader.load_modules()
app_names = ['config', 'names']
- apps = api._get_apps_in_order(app_names)
+ apps = api.get_apps_in_order(app_names)
assert apps[0].name == 'names'
assert apps[1].name == 'config'
diff --git a/plinth/modules/backups/views.py b/plinth/modules/backups/views.py
index 03080d58d..f176d6627 100644
--- a/plinth/modules/backups/views.py
+++ b/plinth/modules/backups/views.py
@@ -179,10 +179,7 @@ class BaseRestoreView(SuccessMessageMixin, FormView):
"""Pass additional keyword args for instantiating the form."""
kwargs = super().get_form_kwargs()
included_apps = self._get_included_apps()
- installed_apps = api.get_all_apps_for_backup()
- kwargs['apps'] = [
- app for app in installed_apps if app.name in included_apps
- ]
+ kwargs['apps'] = api.get_apps_in_order(included_apps)
return kwargs
def get_context_data(self, **kwargs):
@@ -202,8 +199,8 @@ class RestoreFromUploadView(BaseRestoreView):
if not os.path.isfile(path):
messages.error(self.request, _('No backup file found.'))
return redirect(reverse_lazy('backups:index'))
- else:
- return super().get(*args, **kwargs)
+
+ return super().get(*args, **kwargs)
def get_context_data(self, **kwargs):
"""Return additional context for rendering the template."""