diff --git a/data/etc/plinth/modules-enabled/apps b/data/etc/plinth/modules-enabled/apps
deleted file mode 100644
index a58ec54d5..000000000
--- a/data/etc/plinth/modules-enabled/apps
+++ /dev/null
@@ -1 +0,0 @@
-plinth.modules.apps
diff --git a/data/etc/plinth/modules-enabled/system b/data/etc/plinth/modules-enabled/system
deleted file mode 100644
index de4c8dd50..000000000
--- a/data/etc/plinth/modules-enabled/system
+++ /dev/null
@@ -1 +0,0 @@
-plinth.modules.system
diff --git a/plinth/__main__.py b/plinth/__main__.py
index 6b22f42d1..886278a3c 100644
--- a/plinth/__main__.py
+++ b/plinth/__main__.py
@@ -30,6 +30,7 @@ import sys
import cherrypy
from plinth import cfg
+from plinth import menu
from plinth import module_loader
from plinth import service
from plinth import setup
@@ -330,6 +331,8 @@ def main():
module_loader.include_urls()
+ menu.init()
+
module_loader.load_modules()
if arguments.setup is not False:
run_setup_and_exit(arguments.setup)
diff --git a/plinth/cfg.py b/plinth/cfg.py
index 6cb10880d..a384fa0dc 100644
--- a/plinth/cfg.py
+++ b/plinth/cfg.py
@@ -19,8 +19,6 @@ import configparser
import logging
import os
-from plinth.menu import Menu
-
logger = logging.getLogger(__name__)
box_name = None
@@ -41,8 +39,6 @@ debug = False
server_dir = '/'
danube_edition = False
-main_menu = Menu()
-
config_file = None
DEFAULT_CONFIG_FILE = '/etc/plinth/plinth.config'
diff --git a/plinth/context_processors.py b/plinth/context_processors.py
index 91bcc2eb1..3496ce767 100644
--- a/plinth/context_processors.py
+++ b/plinth/context_processors.py
@@ -23,6 +23,7 @@ from django.utils.translation import ugettext as _, ugettext_noop
import re
from plinth import cfg
+from plinth.menu import main_menu
from plinth.utils import is_user_admin
@@ -40,7 +41,7 @@ def common(request):
active_menu_urls = [request.path[:index + 1] for index in slash_indices]
return {
'cfg': cfg,
- 'submenu': cfg.main_menu.active_item(request),
+ 'submenu': main_menu.active_item(request),
'active_menu_urls': active_menu_urls,
'box_name': _(cfg.box_name),
'user_is_admin': is_user_admin(request, True)
diff --git a/plinth/menu.py b/plinth/menu.py
index c5253156c..be4638b4e 100644
--- a/plinth/menu.py
+++ b/plinth/menu.py
@@ -84,3 +84,12 @@ class Menu(object):
for item in self.items:
if request.path.startswith(str(item.url)):
return item
+
+
+main_menu = Menu()
+
+
+def init():
+ """Create main menu and other essential menus."""
+ main_menu.add_urlname('', 'glyphicon-download-alt', 'apps')
+ main_menu.add_urlname('', 'glyphicon-cog', 'system')
diff --git a/plinth/modules/apps/__init__.py b/plinth/modules/apps/__init__.py
deleted file mode 100644
index a242582fb..000000000
--- a/plinth/modules/apps/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# This file is part of Plinth.
-#
-# 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 .
-#
-
-"""
-Plinth module for Apps section page
-"""
-
-from . import apps
-from .apps import init
-
-__all__ = ['apps', 'init']
-
-version = 1
-
-is_essential = True
diff --git a/plinth/modules/apps/apps.py b/plinth/modules/apps/apps.py
deleted file mode 100644
index 4450fb2be..000000000
--- a/plinth/modules/apps/apps.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# This file is part of Plinth.
-#
-# 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 .
-#
-
-from django.template.response import TemplateResponse
-from django.utils.translation import ugettext_lazy as _
-
-from plinth import cfg
-
-
-def init():
- """Initailize the apps module"""
- cfg.main_menu.add_urlname(_('Apps'), 'glyphicon-download-alt',
- 'apps:index')
-
-
-def index(request):
- """Serve the apps index page"""
- return TemplateResponse(request, 'apps.html', {'title': _('Applications')})
diff --git a/plinth/modules/apps/tests/__init__.py b/plinth/modules/apps/tests/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/plinth/modules/apps/urls.py b/plinth/modules/apps/urls.py
deleted file mode 100644
index 98bf022ed..000000000
--- a/plinth/modules/apps/urls.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# This file is part of Plinth.
-#
-# 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 .
-#
-
-"""
-URLs for the Apps module
-"""
-
-from django.conf.urls import url
-
-from . import apps as views
-
-
-urlpatterns = [
- url(r'^apps/$', views.index, name='index'),
-]
diff --git a/plinth/modules/avahi/__init__.py b/plinth/modules/avahi/__init__.py
index a074d77ea..27a4b52b0 100644
--- a/plinth/modules/avahi/__init__.py
+++ b/plinth/modules/avahi/__init__.py
@@ -23,6 +23,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import cfg
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.utils import format_lazy
from plinth.views import ServiceView
@@ -32,8 +33,6 @@ version = 1
is_essential = True
-depends = ['system']
-
managed_services = ['avahi-daemon']
managed_packages = ['avahi-daemon']
@@ -56,7 +55,7 @@ service = None
def init():
"""Intialize the service discovery module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-lamp', 'avahi:index')
global service # pylint: disable=W0603
diff --git a/plinth/modules/bind/__init__.py b/plinth/modules/bind/__init__.py
index 0c3089f9a..29ab61808 100644
--- a/plinth/modules/bind/__init__.py
+++ b/plinth/modules/bind/__init__.py
@@ -25,14 +25,12 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import service as service_module
+from plinth.menu import main_menu
version = 1
-depends = ['system']
-
title = _('Domain Name Server \n (BIND)')
service = None
@@ -57,7 +55,7 @@ CONFIG_FILE = '/etc/bind/named.conf.options'
def init():
"""Intialize the BIND module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-globe', 'bind:index')
global service
diff --git a/plinth/modules/config/__init__.py b/plinth/modules/config/__init__.py
index c1bf7de04..84b281557 100644
--- a/plinth/modules/config/__init__.py
+++ b/plinth/modules/config/__init__.py
@@ -28,4 +28,4 @@ version = 1
is_essential = True
-depends = ['system', 'firewall', 'names']
+depends = ['firewall', 'names']
diff --git a/plinth/modules/config/config.py b/plinth/modules/config/config.py
index be60cbf48..0bcb9d4ab 100644
--- a/plinth/modules/config/config.py
+++ b/plinth/modules/config/config.py
@@ -35,6 +35,7 @@ import socket
import plinth
from plinth import actions
from plinth import cfg
+from plinth.menu import main_menu
from plinth.modules import firewall
from plinth.modules.names import SERVICES
from plinth.signals import pre_hostname_change, post_hostname_change
@@ -146,7 +147,7 @@ class ConfigurationForm(forms.Form):
def init():
"""Initialize the module"""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(ugettext_lazy('Configure'), 'glyphicon-cog',
'config:index')
diff --git a/plinth/modules/datetime/__init__.py b/plinth/modules/datetime/__init__.py
index 0f0944cf4..92a750d4f 100644
--- a/plinth/modules/datetime/__init__.py
+++ b/plinth/modules/datetime/__init__.py
@@ -22,16 +22,14 @@ Plinth module to configure system date and time
from django.utils.translation import ugettext_lazy as _
import subprocess
-from plinth import cfg
from plinth import service as service_module
+from plinth.menu import main_menu
version = 1
is_essential = True
-depends = ['system']
-
managed_services = ['ntp']
managed_packages = ['ntp']
@@ -48,7 +46,7 @@ service = None
def init():
"""Intialize the date/time module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-time', 'datetime:index')
global service
diff --git a/plinth/modules/deluge/__init__.py b/plinth/modules/deluge/__init__.py
index 1b78b7435..0db2f2ee1 100644
--- a/plinth/modules/deluge/__init__.py
+++ b/plinth/modules/deluge/__init__.py
@@ -23,15 +23,13 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
version = 1
-depends = ['apps']
-
service = None
managed_services = ['deluge-web']
@@ -53,7 +51,7 @@ reserved_usernames = ['debian-deluged']
def init():
"""Initialize the Deluge module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-magnet', 'deluge:index')
global service
diff --git a/plinth/modules/diagnostics/__init__.py b/plinth/modules/diagnostics/__init__.py
index 7970b6218..fd0f1b514 100644
--- a/plinth/modules/diagnostics/__init__.py
+++ b/plinth/modules/diagnostics/__init__.py
@@ -22,7 +22,8 @@ Plinth module for system diagnostics
from django.utils.translation import ugettext_lazy as _
from plinth import action_utils
-from plinth import cfg
+from plinth.menu import main_menu
+
version = 1
@@ -36,12 +37,10 @@ description = [
'expected.')
]
-depends = ['system']
-
def init():
"""Initialize the module"""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-screenshot', 'diagnostics:index')
diff --git a/plinth/modules/disks/__init__.py b/plinth/modules/disks/__init__.py
index 22aa78a4d..e03282d99 100644
--- a/plinth/modules/disks/__init__.py
+++ b/plinth/modules/disks/__init__.py
@@ -20,18 +20,15 @@ Plinth module to manage disks.
"""
from django.utils.translation import ugettext_lazy as _
-import json
import logging
import subprocess
from plinth import actions
-from plinth import cfg
+from plinth.menu import main_menu
version = 1
-depends = ['system']
-
title = _('Disks')
description = []
@@ -43,7 +40,7 @@ logger = logging.getLogger(__name__)
def init():
"""Intialize the module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-hdd', 'disks:index')
diff --git a/plinth/modules/dynamicdns/__init__.py b/plinth/modules/dynamicdns/__init__.py
index 2108352fa..3eff8115a 100644
--- a/plinth/modules/dynamicdns/__init__.py
+++ b/plinth/modules/dynamicdns/__init__.py
@@ -22,11 +22,11 @@ Plinth module to configure ez-ipupdate client
from django.utils.translation import ugettext_lazy as _
from plinth import cfg
+from plinth.menu import main_menu
from plinth.utils import format_lazy
-version = 1
-depends = ['system']
+version = 1
managed_packages = ['ez-ipupdate']
@@ -54,7 +54,7 @@ reserved_usernames = ['ez-ipupd']
def init():
"""Initialize the module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-refresh', 'dynamicdns:index')
diff --git a/plinth/modules/ejabberd/__init__.py b/plinth/modules/ejabberd/__init__.py
index 9c75812b4..49c317179 100644
--- a/plinth/modules/ejabberd/__init__.py
+++ b/plinth/modules/ejabberd/__init__.py
@@ -26,17 +26,15 @@ import socket
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.signals import pre_hostname_change, post_hostname_change
from plinth.signals import domainname_change
version = 1
-depends = ['apps']
-
managed_services = ['ejabberd']
managed_packages = ['ejabberd']
@@ -61,7 +59,7 @@ logger = logging.getLogger(__name__)
def init():
"""Initialize the ejabberd module"""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-comment', 'ejabberd:index')
global service
diff --git a/plinth/modules/firewall/__init__.py b/plinth/modules/firewall/__init__.py
index 7ba78a480..b4340e836 100644
--- a/plinth/modules/firewall/__init__.py
+++ b/plinth/modules/firewall/__init__.py
@@ -24,16 +24,16 @@ import logging
from plinth import actions
from plinth import cfg
+from plinth.menu import main_menu
from plinth.signals import service_enabled
import plinth.service as service_module
from plinth.utils import format_lazy
+
version = 1
is_essential = True
-depends = ['system']
-
managed_packages = ['firewalld']
title = _('Firewall')
@@ -51,7 +51,7 @@ LOGGER = logging.getLogger(__name__)
def init():
"""Initailze firewall module"""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-fire', 'firewall:index')
service_enabled.connect(on_service_enabled)
diff --git a/plinth/modules/first_boot/templates/firstboot_complete.html b/plinth/modules/first_boot/templates/firstboot_complete.html
index 93fb7d5e2..9955af03b 100644
--- a/plinth/modules/first_boot/templates/firstboot_complete.html
+++ b/plinth/modules/first_boot/templates/firstboot_complete.html
@@ -37,7 +37,7 @@
diff --git a/plinth/modules/help/help.py b/plinth/modules/help/help.py
index 0c3c81d8d..222bce3c8 100644
--- a/plinth/modules/help/help.py
+++ b/plinth/modules/help/help.py
@@ -27,12 +27,13 @@ from django.utils.translation import ugettext as _, ugettext_lazy
from stronghold.decorators import public
from plinth import cfg, __version__
+from plinth.menu import main_menu
def init():
"""Initialize the Help module"""
- menu = cfg.main_menu.add_urlname(ugettext_lazy('Documentation'),
- 'glyphicon-book', 'help:index')
+ menu = main_menu.add_urlname(ugettext_lazy('Documentation'),
+ 'glyphicon-book', 'help:index')
menu.add_urlname(ugettext_lazy('Where to Get Help'), 'glyphicon-search',
'help:index_explicit', 5)
menu.add_urlname(ugettext_lazy('Manual'), 'glyphicon-info-sign',
diff --git a/plinth/modules/ikiwiki/__init__.py b/plinth/modules/ikiwiki/__init__.py
index 1f2f5981b..957ebaa25 100644
--- a/plinth/modules/ikiwiki/__init__.py
+++ b/plinth/modules/ikiwiki/__init__.py
@@ -23,15 +23,13 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
version = 1
-depends = ['apps']
-
managed_packages = ['ikiwiki', 'libdigest-sha-perl', 'libxml-writer-perl',
'xapian-omega', 'libsearch-xapian-perl',
'libimage-magick-perl']
@@ -51,7 +49,7 @@ description = [
def init():
"""Initialize the ikiwiki module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-edit', 'ikiwiki:index')
global service
diff --git a/plinth/modules/infinoted/__init__.py b/plinth/modules/infinoted/__init__.py
index 0ed0b254b..61588704c 100644
--- a/plinth/modules/infinoted/__init__.py
+++ b/plinth/modules/infinoted/__init__.py
@@ -27,14 +27,13 @@ from plinth import action_utils
from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.utils import format_lazy
from plinth.views import ServiceView
version = 1
-depends = ['apps']
-
service = None
managed_services = ['infinoted']
@@ -56,7 +55,7 @@ description = [
def init():
"""Initialize the infinoted module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-pencil', 'infinoted:index')
global service
diff --git a/plinth/modules/jsxc/__init__.py b/plinth/modules/jsxc/__init__.py
index a1e3065e0..c4e18685c 100644
--- a/plinth/modules/jsxc/__init__.py
+++ b/plinth/modules/jsxc/__init__.py
@@ -24,15 +24,13 @@ from django.utils.translation import ugettext_lazy as _
import logging
import socket
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
version = 1
-depends = ['apps']
-
managed_packages = ['libjs-jsxc']
title = _('Chat Client \n (JSXC)')
@@ -50,7 +48,7 @@ logger = logging.getLogger(__name__)
def init():
"""Initialize the JSXC module"""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-comment', 'jsxc:index')
global service
diff --git a/plinth/modules/letsencrypt/__init__.py b/plinth/modules/letsencrypt/__init__.py
index 97f8aba9f..daa7e5ba5 100644
--- a/plinth/modules/letsencrypt/__init__.py
+++ b/plinth/modules/letsencrypt/__init__.py
@@ -23,6 +23,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils
from plinth import cfg
+from plinth.menu import main_menu
from plinth.modules import names
from plinth.utils import format_lazy
@@ -31,7 +32,7 @@ version = 1
is_essential = False
-depends = ['apps', 'names']
+depends = ['names']
managed_packages = ['certbot']
@@ -59,7 +60,7 @@ service = None
def init():
"""Intialize the module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(_('Certificates (Let\'s Encrypt)'),
'glyphicon-lock', 'letsencrypt:index')
diff --git a/plinth/modules/matrixsynapse/__init__.py b/plinth/modules/matrixsynapse/__init__.py
index 21edc1936..af515b01b 100644
--- a/plinth/modules/matrixsynapse/__init__.py
+++ b/plinth/modules/matrixsynapse/__init__.py
@@ -28,14 +28,13 @@ from ruamel.yaml.util import load_yaml_guess_indent
from plinth import action_utils
from plinth import actions
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.modules import names
-version = 1
-depends = ['apps']
+version = 1
managed_services = ['matrix-synapse']
@@ -67,7 +66,7 @@ SERVER_NAME_PATH = "/etc/matrix-synapse/conf.d/server_name.yaml"
def init():
"""Initialize the matrix-synapse module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-comment', 'matrixsynapse:index')
global service
diff --git a/plinth/modules/minetest/__init__.py b/plinth/modules/minetest/__init__.py
index 9f2b6cd7f..d91dd02b4 100644
--- a/plinth/modules/minetest/__init__.py
+++ b/plinth/modules/minetest/__init__.py
@@ -29,13 +29,12 @@ from plinth import action_utils
from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.utils import format_lazy
version = 2
-depends = ['apps']
-
service = None
managed_services = ['minetest-server']
@@ -65,7 +64,7 @@ AUG_PATH = '/files' + CONFIG_FILE + '/.anon'
def init():
"""Initialize the module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-th-large', 'minetest:index')
global service
diff --git a/plinth/modules/monkeysphere/__init__.py b/plinth/modules/monkeysphere/__init__.py
index b0046eda7..726bffb61 100644
--- a/plinth/modules/monkeysphere/__init__.py
+++ b/plinth/modules/monkeysphere/__init__.py
@@ -21,12 +21,11 @@ Plinth module for monkeysphere.
from django.utils.translation import ugettext_lazy as _
-from plinth import cfg
+from plinth.menu import main_menu
+
version = 1
-depends = ['system']
-
managed_packages = ['monkeysphere']
title = _('Monkeysphere')
@@ -56,7 +55,7 @@ reserved_usernames = ['monkeysphere']
def init():
"""Initialize the monkeysphere module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(_('Monkeysphere'), 'glyphicon-certificate',
'monkeysphere:index')
diff --git a/plinth/modules/mumble/__init__.py b/plinth/modules/mumble/__init__.py
index c368e984d..aba1159ab 100644
--- a/plinth/modules/mumble/__init__.py
+++ b/plinth/modules/mumble/__init__.py
@@ -24,16 +24,14 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.views import ServiceView
version = 1
-depends = ['apps']
-
title = _('Voice Chat \n (Mumble)')
service = None
@@ -56,7 +54,7 @@ reserved_usernames = ['mumble-server']
def init():
"""Intialize the Mumble module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-headphones', 'mumble:index')
global service
diff --git a/plinth/modules/names/__init__.py b/plinth/modules/names/__init__.py
index e5f7d1f7d..83a48cd1d 100644
--- a/plinth/modules/names/__init__.py
+++ b/plinth/modules/names/__init__.py
@@ -22,9 +22,10 @@ Plinth module to configure name services
from django.utils.translation import ugettext_lazy as _
import logging
-from plinth import cfg
+from plinth.menu import main_menu
from plinth.signals import domain_added, domain_removed
+
SERVICES = (
('http', _('HTTP'), 80),
('https', _('HTTPS'), 443),
@@ -35,8 +36,6 @@ version = 1
is_essential = True
-depends = ['system']
-
title = _('Name Services')
domain_types = {}
@@ -47,7 +46,7 @@ logger = logging.getLogger(__name__)
def init():
"""Initialize the names module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-tag', 'names:index')
domain_added.connect(on_domain_added)
diff --git a/plinth/modules/networks/__init__.py b/plinth/modules/networks/__init__.py
index ef720b78a..39a673b76 100644
--- a/plinth/modules/networks/__init__.py
+++ b/plinth/modules/networks/__init__.py
@@ -24,16 +24,14 @@ from logging import Logger
import subprocess
from plinth import action_utils
-from plinth import cfg
from plinth import network
+from plinth.menu import main_menu
version = 1
is_essential = True
-depends = ['system']
-
managed_packages = ['network-manager', 'batctl']
title = _('Networks')
@@ -43,7 +41,7 @@ logger = Logger(__name__)
def init():
"""Initialize the Networks module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-signal', 'networks:index')
diff --git a/plinth/modules/openvpn/__init__.py b/plinth/modules/openvpn/__init__.py
index 095481101..000895d45 100644
--- a/plinth/modules/openvpn/__init__.py
+++ b/plinth/modules/openvpn/__init__.py
@@ -27,13 +27,12 @@ from plinth import action_utils
from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.utils import format_lazy
version = 1
-depends = ['apps']
-
service = None
managed_services = ['openvpn@freedombox']
@@ -56,8 +55,7 @@ description = [
def init():
"""Initialize the OpenVPN module."""
-
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-lock', 'openvpn:index')
global service
diff --git a/plinth/modules/pagekite/__init__.py b/plinth/modules/pagekite/__init__.py
index 719c00c5e..2deafd27c 100644
--- a/plinth/modules/pagekite/__init__.py
+++ b/plinth/modules/pagekite/__init__.py
@@ -23,11 +23,13 @@ from django.utils.translation import ugettext_lazy as _
from . import utils
from plinth import cfg
+from plinth.menu import main_menu
from plinth.utils import format_lazy
+
version = 1
-depends = ['system', 'names']
+depends = ['names']
managed_packages = ['pagekite']
@@ -77,7 +79,7 @@ description = [
def init():
"""Intialize the PageKite module"""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-flag', 'pagekite:index')
# Register kite name with Name Services module.
diff --git a/plinth/modules/power/__init__.py b/plinth/modules/power/__init__.py
index 82dd14937..c740ee2fa 100644
--- a/plinth/modules/power/__init__.py
+++ b/plinth/modules/power/__init__.py
@@ -21,14 +21,12 @@ Plinth module for power controls.
from django.utils.translation import ugettext_lazy as _
-from plinth import cfg
+from plinth.menu import main_menu
version = 1
is_essential = True
-depends = ['system']
-
title = _('Power')
description = [
@@ -38,5 +36,5 @@ description = [
def init():
"""Initialize the power module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-off', 'power:index')
diff --git a/plinth/modules/power/views.py b/plinth/modules/power/views.py
index 2c36fb506..7b1820084 100644
--- a/plinth/modules/power/views.py
+++ b/plinth/modules/power/views.py
@@ -42,7 +42,7 @@ def restart(request):
if request.method == 'POST':
actions.superuser_run('power', ['restart'], async=True)
- return redirect(reverse('apps:index'))
+ return redirect(reverse('apps'))
else:
form = Form(prefix='power')
@@ -57,7 +57,7 @@ def shutdown(request):
if request.method == 'POST':
actions.superuser_run('power', ['shutdown'], async=True)
- return redirect(reverse('apps:index'))
+ return redirect(reverse('apps'))
else:
form = Form(prefix='power')
diff --git a/plinth/modules/privoxy/__init__.py b/plinth/modules/privoxy/__init__.py
index aea63e38a..b84058d99 100644
--- a/plinth/modules/privoxy/__init__.py
+++ b/plinth/modules/privoxy/__init__.py
@@ -27,6 +27,7 @@ from plinth import action_utils
from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.utils import format_lazy
from plinth.views import ServiceView
@@ -35,8 +36,6 @@ version = 1
is_essential = False
-depends = ['apps']
-
managed_services = ['privoxy']
managed_packages = ['privoxy']
@@ -66,7 +65,7 @@ service = None
def init():
"""Intialize the module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-cloud-upload', 'privoxy:index')
global service
diff --git a/plinth/modules/quassel/__init__.py b/plinth/modules/quassel/__init__.py
index 1c1d82dbe..63b7e3f05 100644
--- a/plinth/modules/quassel/__init__.py
+++ b/plinth/modules/quassel/__init__.py
@@ -27,13 +27,12 @@ from plinth import action_utils
from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.utils import format_lazy
from plinth.views import ServiceView
version = 1
-depends = ['apps']
-
service = None
managed_services = ['quasselcore']
@@ -64,7 +63,7 @@ reserved_usernames = ['quasselcore']
def init():
"""Initialize the quassel module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-retweet', 'quassel:index')
global service
diff --git a/plinth/modules/radicale/__init__.py b/plinth/modules/radicale/__init__.py
index 1e0beccd7..ec40e77fb 100644
--- a/plinth/modules/radicale/__init__.py
+++ b/plinth/modules/radicale/__init__.py
@@ -28,11 +28,11 @@ from plinth import action_utils
from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.utils import format_lazy
-version = 1
-depends = ['apps']
+version = 1
service = None
@@ -59,7 +59,7 @@ CONFIG_FILE = '/etc/radicale/config'
def init():
"""Initialize the radicale module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-calendar', 'radicale:index')
global service
diff --git a/plinth/modules/repro/__init__.py b/plinth/modules/repro/__init__.py
index 916052469..5a454912f 100644
--- a/plinth/modules/repro/__init__.py
+++ b/plinth/modules/repro/__init__.py
@@ -24,15 +24,13 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.views import ServiceView
version = 2
-depends = ['apps']
-
managed_services = ['repro']
managed_packages = ['repro']
@@ -67,7 +65,7 @@ service = None
def init():
"""Initialize the repro module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-phone-alt', 'repro:index')
global service
diff --git a/plinth/modules/restore/__init__.py b/plinth/modules/restore/__init__.py
index 8369ecd25..dedbef702 100644
--- a/plinth/modules/restore/__init__.py
+++ b/plinth/modules/restore/__init__.py
@@ -23,13 +23,12 @@ from django.utils.translation import ugettext_lazy as _
from plinth import cfg
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.utils import format_lazy
version = 1
-depends = ['apps']
-
managed_services = ['node-restore']
managed_packages = ['node-restore']
@@ -56,7 +55,7 @@ service = None
def init():
"""Initialize the reStore module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-hdd', 'restore:index')
global service
diff --git a/plinth/modules/roundcube/__init__.py b/plinth/modules/roundcube/__init__.py
index f9f3421f7..501b0bdc6 100644
--- a/plinth/modules/roundcube/__init__.py
+++ b/plinth/modules/roundcube/__init__.py
@@ -23,15 +23,13 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
version = 1
-depends = ['apps']
-
managed_packages = ['sqlite3', 'roundcube', 'roundcube-sqlite3']
title = _('Email Client \n (Roundcube)')
@@ -63,7 +61,7 @@ service = None
def init():
"""Intialize the module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-envelope', 'roundcube:index')
global service
diff --git a/plinth/modules/security/__init__.py b/plinth/modules/security/__init__.py
index 4cf43de06..fd6f84eaa 100644
--- a/plinth/modules/security/__init__.py
+++ b/plinth/modules/security/__init__.py
@@ -21,16 +21,14 @@ Plinth module for security configuration
from django.utils.translation import ugettext_lazy as _
-from plinth import cfg
from plinth import actions
+from plinth.menu import main_menu
version = 1
is_essential = True
-depends = ['system']
-
title = _('Security')
@@ -40,7 +38,7 @@ ACCESS_CONF_SNIPPET = '-:ALL EXCEPT root fbx (admin) (sudo):ALL'
def init():
"""Initialize the module"""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-lock', 'security:index')
diff --git a/plinth/modules/shaarli/__init__.py b/plinth/modules/shaarli/__init__.py
index 28f2740cb..6773fb740 100644
--- a/plinth/modules/shaarli/__init__.py
+++ b/plinth/modules/shaarli/__init__.py
@@ -23,15 +23,13 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
version = 1
-depends = ['apps']
-
managed_packages = ['shaarli']
title = _('Bookmarks \n (Shaarli)')
@@ -50,7 +48,7 @@ service = None
def init():
"""Initialize the module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-bookmark', 'shaarli:index')
global service
diff --git a/plinth/modules/snapshot/__init__.py b/plinth/modules/snapshot/__init__.py
index 55e11ca40..caec951fd 100644
--- a/plinth/modules/snapshot/__init__.py
+++ b/plinth/modules/snapshot/__init__.py
@@ -22,13 +22,11 @@ Plinth module to manage filesystem snapshots.
from django.utils.translation import ugettext_lazy as _
from plinth import actions
-from plinth import cfg
+from plinth.menu import main_menu
version = 1
-depends = ['system']
-
managed_packages = ['snapper']
title = _('Snapshots')
@@ -52,7 +50,7 @@ service = None
def init():
"""Initialize the module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-film', 'snapshot:index')
diff --git a/plinth/modules/syncthing/__init__.py b/plinth/modules/syncthing/__init__.py
index 1ce2c4344..bf0b91d05 100644
--- a/plinth/modules/syncthing/__init__.py
+++ b/plinth/modules/syncthing/__init__.py
@@ -26,13 +26,12 @@ from plinth import action_utils
from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.utils import format_lazy
version = 1
-depends = ['apps']
-
managed_services = ['syncthing']
managed_packages = ['syncthing']
@@ -62,7 +61,7 @@ service = None
def init():
"""Intialize the module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-refresh', 'syncthing:index')
global service
diff --git a/plinth/modules/system/__init__.py b/plinth/modules/system/__init__.py
deleted file mode 100644
index 9a5d9479a..000000000
--- a/plinth/modules/system/__init__.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# This file is part of Plinth.
-#
-# 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 .
-#
-
-"""
-Plinth module for system section page
-"""
-
-from django.utils.translation import ugettext_lazy as _
-
-from plinth import cfg
-from plinth.utils import format_lazy
-
-
-version = 1
-
-is_essential = True
-
-title = _('System Configuration')
-
-description = [
- format_lazy(
- _('Here you can administrate the underlying system of your '
- '{box_name}.'), box_name=_(cfg.box_name)),
-
- format_lazy(
- _('The options affect the {box_name} at its most general level, '
- 'so be careful!'), box_name=_(cfg.box_name))
-]
-
-
-def init():
- """Initialize the system module"""
- cfg.main_menu.add_urlname(title, 'glyphicon-cog', 'system:index')
diff --git a/plinth/modules/system/tests/__init__.py b/plinth/modules/system/tests/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/plinth/modules/system/urls.py b/plinth/modules/system/urls.py
deleted file mode 100644
index 8e75a6af5..000000000
--- a/plinth/modules/system/urls.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# This file is part of Plinth.
-#
-# 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 .
-#
-
-"""
-URLs for the System module
-"""
-
-from django.conf.urls import url
-
-from . import views
-
-
-urlpatterns = [
- url(r'^sys/$', views.index, name='index'),
-]
diff --git a/plinth/modules/system/views.py b/plinth/modules/system/views.py
deleted file mode 100644
index bc4dd1953..000000000
--- a/plinth/modules/system/views.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# This file is part of Plinth.
-#
-# 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 .
-#
-
-from django.template.response import TemplateResponse
-
-from plinth.modules import system
-
-
-def index(request):
- """Serve the index page"""
- return TemplateResponse(request, 'system.html',
- {'title': system.title,
- 'description': system.description})
diff --git a/plinth/modules/tor/__init__.py b/plinth/modules/tor/__init__.py
index f009948dc..7e3499ed3 100644
--- a/plinth/modules/tor/__init__.py
+++ b/plinth/modules/tor/__init__.py
@@ -24,8 +24,8 @@ import json
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import service as service_module
+from plinth.menu import main_menu
from plinth.modules.names import SERVICES
from plinth.signals import domain_added, domain_removed
@@ -34,7 +34,7 @@ from . import utils
version = 2
-depends = ['apps', 'names']
+depends = ['names']
managed_packages = ['tor', 'tor-geoipdb', 'torsocks', 'obfs4proxy',
'apt-transport-tor']
@@ -58,7 +58,7 @@ bridge_service = None
def init():
"""Initialize the module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-eye-close', 'tor:index')
setup_helper = globals()['setup_helper']
diff --git a/plinth/modules/transmission/__init__.py b/plinth/modules/transmission/__init__.py
index 0d9ec85c9..2a7930a40 100644
--- a/plinth/modules/transmission/__init__.py
+++ b/plinth/modules/transmission/__init__.py
@@ -24,15 +24,13 @@ import json
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
version = 1
-depends = ['apps']
-
managed_services = ['transmission-daemon']
managed_packages = ['transmission-daemon']
@@ -53,7 +51,7 @@ service = None
def init():
"""Intialize the Transmission module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-save', 'transmission:index')
global service
diff --git a/plinth/modules/ttrss/__init__.py b/plinth/modules/ttrss/__init__.py
index a0d2fb5f8..6a0782933 100644
--- a/plinth/modules/ttrss/__init__.py
+++ b/plinth/modules/ttrss/__init__.py
@@ -23,15 +23,13 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth import action_utils
-from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
+from plinth.menu import main_menu
version = 1
-depends = ['apps']
-
managed_services = ['tt-rss']
managed_packages = ['tt-rss', 'postgresql', 'dbconfig-pgsql', 'php-pgsql']
@@ -52,7 +50,7 @@ service = None
def init():
"""Intialize the module."""
- menu = cfg.main_menu.get('apps:index')
+ menu = main_menu.get('apps')
menu.add_urlname(title, 'glyphicon-envelope', 'ttrss:index')
global service
diff --git a/plinth/modules/upgrades/__init__.py b/plinth/modules/upgrades/__init__.py
index bbbf63fde..a13199f4e 100644
--- a/plinth/modules/upgrades/__init__.py
+++ b/plinth/modules/upgrades/__init__.py
@@ -22,16 +22,14 @@ Plinth module for upgrades
from django.utils.translation import ugettext_lazy as _
from plinth import actions
-from plinth import cfg
from plinth import service as service_module
+from plinth.menu import main_menu
version = 1
is_essential = True
-depends = ['system']
-
managed_packages = ['unattended-upgrades']
title = _('Software Upgrades')
@@ -47,7 +45,7 @@ service = None
def init():
"""Initialize the module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-refresh', 'upgrades:index')
global service
service = service_module.Service(
diff --git a/plinth/modules/users/__init__.py b/plinth/modules/users/__init__.py
index bec3acd39..fc0f6861b 100644
--- a/plinth/modules/users/__init__.py
+++ b/plinth/modules/users/__init__.py
@@ -22,16 +22,15 @@ Plinth module to manage users
from django.utils.translation import ugettext_lazy as _
import subprocess
-from plinth import cfg
from plinth import action_utils
from plinth import actions
+from plinth.menu import main_menu
+
version = 1
is_essential = True
-depends = ['system']
-
managed_packages = ['ldapscripts', 'ldap-utils', 'libnss-ldapd',
'libpam-ldapd', 'nslcd', 'slapd']
@@ -48,7 +47,7 @@ title = _('Users and Groups')
def init():
"""Intialize the user module."""
- menu = cfg.main_menu.get('system:index')
+ menu = main_menu.get('system')
menu.add_urlname(title, 'glyphicon-user', 'users:index')
diff --git a/plinth/modules/apps/templates/apps.html b/plinth/templates/apps.html
similarity index 100%
rename from plinth/modules/apps/templates/apps.html
rename to plinth/templates/apps.html
diff --git a/plinth/templates/base.html b/plinth/templates/base.html
index c5570c240..cfb4234d9 100644
--- a/plinth/templates/base.html
+++ b/plinth/templates/base.html
@@ -103,13 +103,13 @@
-
+
{% trans "Apps" %}
-
+
{% trans "Configuration" %}
diff --git a/plinth/templates/index.html b/plinth/templates/index.html
index 2ccb01321..9fe5a4962 100644
--- a/plinth/templates/index.html
+++ b/plinth/templates/index.html
@@ -54,7 +54,7 @@
{% else %}
- {% url 'apps:index' as apps_url %}
+ {% url 'apps' as apps_url %}
{% blocktrans trimmed %}
Enable some applications to add
shortcuts to this page.
diff --git a/plinth/modules/system/templates/system.html b/plinth/templates/system.html
similarity index 62%
rename from plinth/modules/system/templates/system.html
rename to plinth/templates/system.html
index 18f3070e2..b35bfb5e9 100644
--- a/plinth/modules/system/templates/system.html
+++ b/plinth/templates/system.html
@@ -1,4 +1,4 @@
-{% extends 'simple_service.html' %}
+{% extends 'base.html' %}
{% comment %}
#
# This file is part of Plinth.
@@ -17,3 +17,23 @@
# along with this program. If not, see .
#
{% endcomment %}
+
+{% load i18n %}
+
+{% block content %}
+
+ {% trans "System Configuration" %}
+
+
+ {% blocktrans trimmed %}
+ Here you can administrate the underlying system of your {{ box_name }}.
+ {% endblocktrans %}
+
+
+
+ {% blocktrans trimmed %}
+ The options affect the {{ box_name }} at its most general level,
+ so be careful!
+ {% endblocktrans %}
+
+{% endblock %}
diff --git a/plinth/tests/test_cfg.py b/plinth/tests/test_cfg.py
index 35c94e857..c60f03c56 100644
--- a/plinth/tests/test_cfg.py
+++ b/plinth/tests/test_cfg.py
@@ -46,14 +46,6 @@ class TestCfg(unittest.TestCase):
"""Cleanup after all tests are completed."""
cfg.read()
- def test_read_main_menu(self):
- """Verify that the cfg.main_menu container is initially empty."""
- # Menu should be empty before...
- self.assertEqual(len(cfg.main_menu.items), 0)
- cfg.read(self.test_config_file, self.test_config_dir)
- # ...and after reading the config file
- self.assertEqual(len(cfg.main_menu.items), 0)
-
def test_read_default_config_file(self):
"""Verify that the default config file can be read correctly."""
# Read the plinth.config file directly
diff --git a/plinth/tests/test_context_processors.py b/plinth/tests/test_context_processors.py
index e8c4e737f..8f234b636 100644
--- a/plinth/tests/test_context_processors.py
+++ b/plinth/tests/test_context_processors.py
@@ -25,6 +25,12 @@ from django.test import TestCase
from plinth import cfg
from plinth import context_processors as cp
+from plinth import menu
+
+
+def setUpModule(): # noqa
+ """Setup all test cases by initializing menu module."""
+ menu.init()
class ContextProcessorsTestCase(TestCase):
diff --git a/plinth/tests/test_menu.py b/plinth/tests/test_menu.py
index d19d89b9e..aad4ed3be 100644
--- a/plinth/tests/test_menu.py
+++ b/plinth/tests/test_menu.py
@@ -24,6 +24,7 @@ from django.test import TestCase
from django.urls import reverse
import random
+from plinth import menu as menu_module
from plinth.menu import Menu
@@ -62,6 +63,22 @@ def dump_menu(menu):
class MenuTestCase(TestCase):
"""Verify the behavior of the Plinth Menu class."""
+ def test_init(self):
+ """Verify that main_menu and essential items are created."""
+ menu_module.init()
+ main_menu = menu_module.main_menu
+ self.assertIsInstance(main_menu, Menu)
+
+ apps_menu = main_menu.get('apps')
+ self.assertEqual(apps_menu.label, '')
+ self.assertEqual(apps_menu.icon, 'glyphicon-download-alt')
+ self.assertEqual(str(apps_menu.url), '/apps/')
+
+ system_menu = main_menu.get('system')
+ self.assertEqual(system_menu.label, '')
+ self.assertEqual(system_menu.icon, 'glyphicon-cog')
+ self.assertEqual(str(system_menu.url), '/sys/')
+
def test_menu_creation_without_arguments(self):
"""Verify the Menu state without initialization parameters."""
menu = Menu()
diff --git a/plinth/urls.py b/plinth/urls.py
index 44be0a509..f572d7d22 100644
--- a/plinth/urls.py
+++ b/plinth/urls.py
@@ -20,8 +20,15 @@ Django URLconf file containing all urls
"""
from django.conf.urls import url
+from django.views.generic import TemplateView
+
from . import views
+
urlpatterns = [
- url(r'^$', views.index, name='index')
+ url(r'^$', views.index, name='index'),
+ url(r'^apps/$', TemplateView.as_view(template_name='apps.html'),
+ name='apps'),
+ url(r'^sys/$', TemplateView.as_view(template_name='system.html'),
+ name='system'),
]