diff --git a/plinth/menu.py b/plinth/menu.py
index 146073edc..fdeaa0ef1 100644
--- a/plinth/menu.py
+++ b/plinth/menu.py
@@ -27,7 +27,7 @@ class Menu(app.FollowerComponent):
def __init__(self, component_id, name=None, short_description=None,
icon=None, url_name=None, url_args=None, url_kwargs=None,
- parent_url_name=None, order=50):
+ parent_url_name=None, order=50, advanced=False):
"""Initialize a new menu item with basic properties.
name is the label of the menu item.
@@ -50,6 +50,8 @@ class Menu(app.FollowerComponent):
disregard that. If you need more granularity, don't bother renumbering
things. Feel free to use fractional orders.
+ advanced decides whether to show the menu item only in advanced mode.
+
"""
super().__init__(component_id)
if not url_name:
@@ -62,6 +64,7 @@ class Menu(app.FollowerComponent):
self.icon = icon
self.url = url
self.order = order
+ self.advanced = advanced
self.items = []
# Add self to parent menu item
diff --git a/plinth/modules/config/__init__.py b/plinth/modules/config/__init__.py
index 7db188e56..1e730f8a3 100644
--- a/plinth/modules/config/__init__.py
+++ b/plinth/modules/config/__init__.py
@@ -45,6 +45,7 @@ APACHE_HOMEPAGE_CONFIG = os.path.join(APACHE_CONF_ENABLED_DIR,
APACHE_HOMEPAGE_CONF_FILE_NAME)
FREEDOMBOX_APACHE_CONFIG = os.path.join(APACHE_CONF_ENABLED_DIR,
'freedombox.conf')
+ADVANCED_MODE_KEY = 'advanced_mode'
app = None
@@ -126,6 +127,18 @@ def change_home_page(shortcut_id):
actions.superuser_run('config', ['set-home-page', str(url)])
+def get_advanced_mode():
+ """Get whether option is enabled."""
+ from plinth import kvstore
+ return kvstore.get_default(ADVANCED_MODE_KEY, False)
+
+
+def set_advanced_mode(advanced_mode):
+ """Turn on/off advanced mode."""
+ from plinth import kvstore
+ kvstore.set(ADVANCED_MODE_KEY, advanced_mode)
+
+
def init():
"""Initialize the module"""
global app
diff --git a/plinth/modules/config/forms.py b/plinth/modules/config/forms.py
index eda39a29a..762dd91fa 100644
--- a/plinth/modules/config/forms.py
+++ b/plinth/modules/config/forms.py
@@ -100,3 +100,8 @@ class ConfigurationForm(forms.Form):
'/freedombox to reach {box_name} Service (Plinth).'),
box_name=ugettext_lazy(cfg.box_name)), required=False,
choices=get_homepage_choices)
+
+ advanced_mode = forms.BooleanField(
+ label=_('Show advanced apps and features'), required=False,
+ help_text=_('Show apps and features that require more technical '
+ 'knowledge.'))
diff --git a/plinth/modules/config/views.py b/plinth/modules/config/views.py
index 6bb9efd61..4c81a42e5 100644
--- a/plinth/modules/config/views.py
+++ b/plinth/modules/config/views.py
@@ -64,6 +64,7 @@ def get_status():
'hostname': config.get_hostname(),
'domainname': config.get_domainname(),
'homepage': config.get_home_page(),
+ 'advanced_mode': config.get_advanced_mode(),
}
@@ -102,6 +103,22 @@ def _apply_changes(request, old_status, new_status):
else:
messages.success(request, _('Webserver home page set'))
+ if old_status['advanced_mode'] != new_status['advanced_mode']:
+ try:
+ config.set_advanced_mode(new_status['advanced_mode'])
+ except Exception as exception:
+ messages.error(
+ request,
+ _('Error changing advanced mode: {exception}').format(
+ exception=exception))
+ else:
+ if new_status['advanced_mode']:
+ messages.success(request,
+ _('Showing advanced apps and features'))
+ else:
+ messages.success(request,
+ _('Hiding advanced apps and features'))
+
def set_hostname(hostname):
"""Sets machine hostname to hostname"""
diff --git a/plinth/templates/card.html b/plinth/templates/card.html
new file mode 100644
index 000000000..799002ba7
--- /dev/null
+++ b/plinth/templates/card.html
@@ -0,0 +1,34 @@
+{% comment %}
+#
+# This file is part of FreedomBox.
+#
+# 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