+ {% blocktrans trimmed %}
+ There are no more apps available to add.
+ {% endblocktrans %}
+
+{% endblock %}
diff --git a/plinth/templates/apps.html b/plinth/templates/apps.html
index 5b5112706..99a57b87b 100644
--- a/plinth/templates/apps.html
+++ b/plinth/templates/apps.html
@@ -5,9 +5,27 @@
{% load static %}
{% load i18n %}
+{% load extras %}
{% block page_js %}
{% endblock %}
{% block body_class %}apps-page{% endblock %}
+
+{% block toolbar-container %}
+
+ {% blocktrans trimmed %}
+ There are currently no apps added.
+ {% endblocktrans %}
+
+{% endblock %}
diff --git a/plinth/templates/cards.html b/plinth/templates/cards.html
index be49d25d6..6cfe29b6b 100644
--- a/plinth/templates/cards.html
+++ b/plinth/templates/cards.html
@@ -20,45 +20,28 @@
{% include "tags.html" %}
{% endblock %}
-
-
-
- {% for item in menu_items %}
- {% if not show_disabled or item.is_enabled %}
+ {% block header-container %}
+ {% endblock %}
+
+ {% block toolbar-container %}
+ {% endblock %}
+
+ {% if menu_items %}
+
+
+ {% for item in menu_items %}
{% if advanced_mode or not item.advanced %}
{% include "card.html" %}
{% endif %}
- {% endif %}
- {% endfor %}
-
-
-
-
- {% if show_disabled %}
-
-
{% trans "Available for install" %}
-
-
- {% for item in menu_items %}
- {% if not item.is_enabled %}
- {% if advanced_mode or not item.advanced %}
- {% include "card.html" %}
- {% endif %}
- {% endif %}
{% endfor %}
-
- {% endif %}
+ {% else %}
+ {% block cards-empty %}
+ {% endblock %}
+ {% endif %}
+
{% block content-container %}
{% endblock %}
diff --git a/plinth/urls.py b/plinth/urls.py
index 59bc844d8..6fec30dfe 100644
--- a/plinth/urls.py
+++ b/plinth/urls.py
@@ -23,7 +23,8 @@ urlpatterns = [
re_path(r'^language-selection/$',
public(views.LanguageSelectionView.as_view()),
name='language-selection'),
- re_path(r'^apps/$', views.AppsIndexView.as_view(), name='apps'),
+ re_path(r'^apps/$', views.AppsView.as_view(), name='apps'),
+ re_path(r'^apps/add/$', views.AppsAddView.as_view(), name='apps-add'),
re_path(r'^sys/$', views.system_index, name='system'),
re_path(r'', include((system_urlpatterns, 'system'))),
re_path(r'^uninstall/(?P
[1-9a-z\-_]+)/$',
diff --git a/plinth/views.py b/plinth/views.py
index 76d2c2c3f..7e1d20031 100644
--- a/plinth/views.py
+++ b/plinth/views.py
@@ -266,8 +266,8 @@ def _get_all_tags(menu_items: list[menu.Menu]) -> list[str]:
return sorted(get_tags(menu_items), key=_)
-class AppsIndexView(TemplateView):
- """View for apps index.
+class AppsView(TemplateView):
+ """View for showing installed apps.
This view supports filtering apps by one or more tags. If no tags are
provided, it will show all the apps. If one or more tags are provided,
@@ -277,11 +277,39 @@ class AppsIndexView(TemplateView):
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
- context['show_disabled'] = True
context['advanced_mode'] = get_advanced_mode()
tags = self.request.GET.getlist('tag', [])
- menu_items = menu.main_menu.active_item(self.request).items
+ menu_items = [
+ item for item in menu.main_menu.active_item(self.request).items
+ if item.is_enabled()
+ ]
+
+ context['tags'] = tags
+ context['all_tags'] = _get_all_tags(menu_items)
+ context['menu_items'] = _pick_menu_items(menu_items, tags)
+
+ return context
+
+
+class AppsAddView(TemplateView):
+ """View for showing apps that can be installed.
+
+ This view supports filtering apps by one or more tags. If no tags are
+ provided, it will show all the apps. If one or more tags are provided,
+ it will select apps matching any of the provided tags.
+ """
+ template_name = 'apps-add.html'
+
+ def get_context_data(self, *args, **kwargs):
+ context = super().get_context_data(*args, **kwargs)
+ context['advanced_mode'] = get_advanced_mode()
+
+ tags = self.request.GET.getlist('tag', [])
+ menu_items = [
+ item for item in menu.main_menu.active_item(self.request).items
+ if not item.is_enabled()
+ ]
context['tags'] = tags
context['all_tags'] = _get_all_tags(menu_items)