From 893bd2b4d68e38afff88b3b78ffdd5eceb7a3d90 Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Fri, 29 Mar 2019 07:54:28 -0400 Subject: [PATCH] apps: Separate enabled and disabled apps - Add 'secondary' flag to menu items. - Mark apps as 'secondary' when disabled. - Extend TemplateView for apps index. - Add card-container for disabled apps. Closes #1309 Signed-off-by: James Valleroy Reviewed-by: Sunil Mohan Adapa --- plinth/menu.py | 34 +++++++++++++- plinth/modules/deluge/__init__.py | 11 +++-- plinth/modules/ejabberd/__init__.py | 14 ++++-- plinth/modules/i2p/__init__.py | 7 +++ plinth/modules/ikiwiki/__init__.py | 11 +++-- plinth/modules/infinoted/__init__.py | 39 +++++++--------- plinth/modules/jsxc/__init__.py | 7 +++ plinth/modules/matrixsynapse/__init__.py | 8 +++- plinth/modules/mediawiki/__init__.py | 8 +++- plinth/modules/minetest/__init__.py | 12 +++-- plinth/modules/mldonkey/__init__.py | 7 +++ plinth/modules/mumble/__init__.py | 10 ++++- plinth/modules/openvpn/__init__.py | 7 +++ plinth/modules/privoxy/__init__.py | 10 ++++- plinth/modules/quassel/__init__.py | 10 ++++- plinth/modules/radicale/__init__.py | 8 +++- plinth/modules/roundcube/__init__.py | 10 ++++- plinth/modules/searx/__init__.py | 13 ++++-- plinth/modules/shadowsocks/__init__.py | 12 ++++- plinth/modules/syncthing/__init__.py | 17 ++++--- plinth/modules/tahoe/__init__.py | 7 +++ plinth/modules/tor/__init__.py | 15 ++++--- plinth/modules/transmission/__init__.py | 14 ++++-- plinth/modules/ttrss/__init__.py | 10 ++++- plinth/templates/cards.html | 57 +++++++++++++++++------- plinth/urls.py | 27 +++++------ plinth/views.py | 13 +++++- 27 files changed, 295 insertions(+), 103 deletions(-) diff --git a/plinth/menu.py b/plinth/menu.py index 2dbd79964..256c64323 100644 --- a/plinth/menu.py +++ b/plinth/menu.py @@ -23,7 +23,8 @@ from plinth.utils import format_lazy class Menu(object): """One menu item.""" - def __init__(self, name="",short_description="", label="", icon="", url="#", order=50): + def __init__(self, name="", short_description="", label="", icon="", + url="#", order=50): """label is the text that is displayed on the menu. icon is the icon to be displayed next to the label. @@ -47,6 +48,7 @@ class Menu(object): self.icon = icon self.url = url self.order = order + self.secondary = True # TODO: With an ordered dictionary for self.items we could access the # items by their URL directly instead of searching for them each time, # which we do currently with the 'get' method @@ -84,8 +86,10 @@ class Menu(object): return it. """ - item = Menu(name=name, short_description=short_description, label=label, icon=icon, url=url, order=order) + item = Menu(name=name, short_description=short_description, + label=label, icon=icon, url=url, order=order) self.items.append(item) + return item def active_item(self, request): @@ -94,6 +98,32 @@ class Menu(object): if request.path.startswith(str(item.url)): return item + def promote_item(self, urlname, url_args=None, url_kwargs=None): + """Promote a secondary item to an item.""" + found_item = None + url = reverse(urlname, args=url_args, kwargs=url_kwargs) + for item in self.items: + if str(item.url) == url: + found_item = item + + if found_item: + found_item.secondary = False + else: + raise KeyError('Menu item not found') + + def demote_item(self, urlname, url_args=None, url_kwargs=None): + """Demote an item to a secondary item.""" + found_item = None + url = reverse(urlname, args=url_args, kwargs=url_kwargs) + for item in self.items: + if str(item.url) == url: + found_item = item + + if found_item: + found_item.secondary = True + else: + raise KeyError('Menu item not found') + main_menu = Menu() diff --git a/plinth/modules/deluge/__init__.py b/plinth/modules/deluge/__init__.py index bc8c52a59..f9eee3c51 100644 --- a/plinth/modules/deluge/__init__.py +++ b/plinth/modules/deluge/__init__.py @@ -59,8 +59,7 @@ manual_page = 'Deluge' def init(): """Initialize the Deluge module.""" menu = main_menu.get('apps') - menu.add_urlname(name, 'deluge', 'deluge:index', - short_description) + menu.add_urlname(name, 'deluge', 'deluge:index', short_description) register_group(group) global service @@ -70,9 +69,9 @@ def init(): 'http', 'https' ], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable) - if is_enabled(): add_shortcut() + menu.promote_item('deluge:index') def setup(helper, old_version=None): @@ -87,6 +86,8 @@ def setup(helper, old_version=None): disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'deluge:index') def add_shortcut(): @@ -104,12 +105,16 @@ def enable(): """Enable the module.""" actions.superuser_run('deluge', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('deluge:index') def disable(): """Disable the module.""" actions.superuser_run('deluge', ['disable']) frontpage.remove_shortcut('deluge') + menu = main_menu.get('apps') + menu.demote_item('deluge:index') def diagnose(): diff --git a/plinth/modules/ejabberd/__init__.py b/plinth/modules/ejabberd/__init__.py index c4bbd99c0..6b7d40dab 100644 --- a/plinth/modules/ejabberd/__init__.py +++ b/plinth/modules/ejabberd/__init__.py @@ -50,9 +50,9 @@ description = [ _('To actually communicate, you can use the ' 'web client or any other XMPP client. ' - 'When enabled, ejabberd can be accessed by any ' - 'user with a {box_name} login.'), box_name=_(cfg.box_name), - users_url=reverse_lazy('users:index'), + 'When enabled, ejabberd can be accessed by any ' + ' user with a {box_name} login.'), + box_name=_(cfg.box_name), users_url=reverse_lazy('users:index'), jsxc_url=reverse_lazy('jsxc:index')) ] @@ -82,6 +82,8 @@ def init(): enable=enable, disable=disable) if is_enabled(): add_shortcut() + menu.promote_item('ejabberd:index') + pre_hostname_change.connect(on_pre_hostname_change) post_hostname_change.connect(on_post_hostname_change) domainname_change.connect(on_domainname_change) @@ -105,6 +107,8 @@ def setup(helper, old_version=None): enable=enable, disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'ejabberd:index') def add_shortcut(): @@ -123,12 +127,16 @@ def enable(): """Enable the module.""" actions.superuser_run('ejabberd', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('ejabberd:index') def disable(): """Enable the module.""" actions.superuser_run('ejabberd', ['disable']) frontpage.remove_shortcut('ejabberd') + menu = main_menu.get('apps') + menu.demote_item('ejabberd:index') def on_pre_hostname_change(sender, old_hostname, new_hostname, **kwargs): diff --git a/plinth/modules/i2p/__init__.py b/plinth/modules/i2p/__init__.py index a0334e14b..eb5f361fa 100644 --- a/plinth/modules/i2p/__init__.py +++ b/plinth/modules/i2p/__init__.py @@ -87,6 +87,7 @@ def init(): if is_enabled(): add_shortcut() + menu.promote_item('i2p:index') def setup(helper, old_version=None): @@ -133,6 +134,8 @@ def setup(helper, old_version=None): helper.call('post', service.notify_enabled, None, True) helper.call('post', proxies_service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'i2p:index') def add_shortcut(): @@ -157,12 +160,16 @@ def enable(): """Enable the module.""" actions.superuser_run('i2p', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('i2p:index') def disable(): """Enable the module.""" actions.superuser_run('i2p', ['disable']) frontpage.remove_shortcut('i2p') + menu = main_menu.get('apps') + menu.demote_item('i2p:index') def diagnose(): diff --git a/plinth/modules/ikiwiki/__init__.py b/plinth/modules/ikiwiki/__init__.py index af4e1dbcb..2187815d6 100644 --- a/plinth/modules/ikiwiki/__init__.py +++ b/plinth/modules/ikiwiki/__init__.py @@ -67,8 +67,7 @@ manual_page = 'Ikiwiki' def init(): """Initialize the ikiwiki module.""" menu = main_menu.get('apps') - menu.add_urlname(name, 'ikiwiki', 'ikiwiki:index', - short_description) + menu.add_urlname(name, 'ikiwiki', 'ikiwiki:index', short_description) register_group(group) global service @@ -77,9 +76,9 @@ def init(): service = service_module.Service( 'ikiwiki', name, ports=['http', 'https'], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable) - if is_enabled(): add_shortcuts() + menu.promote_item('ikiwiki:index') def setup(helper, old_version=None): @@ -93,6 +92,8 @@ def setup(helper, old_version=None): is_enabled=is_enabled, enable=enable, disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcuts) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'ikiwiki:index') def add_shortcuts(): @@ -113,12 +114,16 @@ def enable(): """Enable the module.""" actions.superuser_run('ikiwiki', ['enable']) add_shortcuts() + menu = main_menu.get('apps') + menu.promote_item('ikiwiki:index') def disable(): """Enable the module.""" actions.superuser_run('ikiwiki', ['disable']) frontpage.remove_shortcut('ikiwiki*') + menu = main_menu.get('apps') + menu.demote_item('ikiwiki:index') def diagnose(): diff --git a/plinth/modules/infinoted/__init__.py b/plinth/modules/infinoted/__init__.py index ffc4cfbe5..8a4998ee7 100644 --- a/plinth/modules/infinoted/__init__.py +++ b/plinth/modules/infinoted/__init__.py @@ -58,22 +58,17 @@ clients = clients def init(): """Initialize the infinoted module.""" menu = main_menu.get('apps') - menu.add_urlname(name, 'infinoted', 'infinoted:index', - short_description) + menu.add_urlname(name, 'infinoted', 'infinoted:index', short_description) global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service( - managed_services[0], - name, - ports=['infinoted-plinth'], - is_external=True, - enable=enable, - disable=disable) - + service = service_module.Service(managed_services[0], name, ports=[ + 'infinoted-plinth' + ], is_external=True, enable=enable, disable=disable) if service.is_enabled(): add_shortcut() + menu.promote_item('infinoted:index') class InfinotedServiceView(ServiceView): @@ -89,26 +84,20 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'infinoted', ['setup']) global service if service is None: - service = service_module.Service( - managed_services[0], - name, - ports=['infinoted-plinth'], - is_external=True, - enable=enable, - disable=disable) + service = service_module.Service(managed_services[0], name, ports=[ + 'infinoted-plinth' + ], is_external=True, enable=enable, disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'infinoted:index') def add_shortcut(): frontpage.add_shortcut( - 'infinoted', - name, - short_description=short_description, - url=None, - details=description, - configure_url=reverse_lazy('infinoted:index'), + 'infinoted', name, short_description=short_description, url=None, + details=description, configure_url=reverse_lazy('infinoted:index'), login_required=False) @@ -116,12 +105,16 @@ def enable(): """Enable the module.""" actions.superuser_run('service', ['enable', managed_services[0]]) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('infinoted:index') def disable(): """Disable the module.""" actions.superuser_run('service', ['disable', managed_services[0]]) frontpage.remove_shortcut('infinoted') + menu = main_menu.get('apps') + menu.demote_item('infinoted:index') def diagnose(): diff --git a/plinth/modules/jsxc/__init__.py b/plinth/modules/jsxc/__init__.py index 967a9ad15..e2b9c02b2 100644 --- a/plinth/modules/jsxc/__init__.py +++ b/plinth/modules/jsxc/__init__.py @@ -62,6 +62,7 @@ def init(): is_enabled=is_enabled, enable=enable, disable=disable) if is_enabled(): add_shortcut() + menu.promote_item('jsxc:index') def setup(helper, old_version=None): @@ -75,6 +76,8 @@ def setup(helper, old_version=None): is_enabled=is_enabled, enable=enable, disable=disable) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'jsxc:index') def add_shortcut(): @@ -91,7 +94,11 @@ def is_enabled(): def enable(): add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('jsxc:index') def disable(): frontpage.remove_shortcut('jsxc') + menu = main_menu.get('apps') + menu.demote_item('jsxc:index') diff --git a/plinth/modules/matrixsynapse/__init__.py b/plinth/modules/matrixsynapse/__init__.py index c6a56a466..c6fca7947 100644 --- a/plinth/modules/matrixsynapse/__init__.py +++ b/plinth/modules/matrixsynapse/__init__.py @@ -18,7 +18,6 @@ FreedomBox app to configure matrix-synapse server. """ -import json import logging import os @@ -83,6 +82,7 @@ def init(): disable=disable) if is_enabled(): add_shortcut() + menu.promote_item('matrixsynapse:index') def setup(helper, old_version=None): @@ -99,6 +99,8 @@ def setup(helper, old_version=None): ['post-install']) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'matrixsynapse:index') def add_shortcut(): @@ -123,12 +125,16 @@ def enable(): """Enable the module.""" actions.superuser_run('matrixsynapse', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('matrixsynapse:index') def disable(): """Enable the module.""" actions.superuser_run('matrixsynapse', ['disable']) frontpage.remove_shortcut('matrixsynapse') + menu = main_menu.get('apps') + menu.demote_item('matrixsynapse:index') def diagnose(): diff --git a/plinth/modules/mediawiki/__init__.py b/plinth/modules/mediawiki/__init__.py index b5b37d2f3..bb7884511 100644 --- a/plinth/modules/mediawiki/__init__.py +++ b/plinth/modules/mediawiki/__init__.py @@ -67,9 +67,9 @@ def init(): service = service_module.Service( 'mediawiki', name, ports=['http', 'https'], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable) - if is_enabled(): add_shortcut() + menu.promote_item('mediawiki:index') def setup(helper, old_version=None): @@ -91,6 +91,8 @@ def setup(helper, old_version=None): ) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'mediawiki:index') def add_shortcut(): @@ -109,12 +111,16 @@ def enable(): """Enable the module.""" actions.superuser_run('mediawiki', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('mediawiki:index') def disable(): """Enable the module.""" actions.superuser_run('mediawiki', ['disable']) frontpage.remove_shortcut('mediawiki') + menu = main_menu.get('apps') + menu.demote_item('mediawiki:index') def diagnose(): diff --git a/plinth/modules/minetest/__init__.py b/plinth/modules/minetest/__init__.py index 18c8a0eae..2bb24d718 100644 --- a/plinth/modules/minetest/__init__.py +++ b/plinth/modules/minetest/__init__.py @@ -83,9 +83,9 @@ def init(): service = service_module.Service(managed_services[0], name, ports=[ 'minetest-plinth' ], is_external=True, enable=enable, disable=disable) - if service.is_enabled(): add_shortcut() + menu.promote_item('minetest:index') def setup(helper, old_version=None): @@ -98,6 +98,8 @@ def setup(helper, old_version=None): ], is_external=True, enable=enable, disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'minetest:index') def add_shortcut(): @@ -111,12 +113,16 @@ def enable(): """Enable the module.""" actions.superuser_run('service', ['enable', managed_services[0]]) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('minetest:index') def disable(): """Disable the module.""" actions.superuser_run('service', ['disable', managed_services[0]]) frontpage.remove_shortcut('minetest') + menu = main_menu.get('apps') + menu.demote_item('minetest:index') def diagnose(): @@ -130,8 +136,8 @@ def diagnose(): def load_augeas(): """Initialize Augeas.""" - aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD + - augeas.Augeas.NO_MODL_AUTOLOAD) + aug = augeas.Augeas( + flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD) aug.set('/augeas/load/Php/lens', 'Php.lns') aug.set('/augeas/load/Php/incl[last() + 1]', CONFIG_FILE) aug.load() diff --git a/plinth/modules/mldonkey/__init__.py b/plinth/modules/mldonkey/__init__.py index 73d56334a..11b103429 100644 --- a/plinth/modules/mldonkey/__init__.py +++ b/plinth/modules/mldonkey/__init__.py @@ -79,6 +79,7 @@ def init(): if is_enabled(): add_shortcut() + menu.promote_item('mldonkey:index') def setup(helper, old_version=None): @@ -95,6 +96,8 @@ def setup(helper, old_version=None): is_running=is_running) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'mldonkey:index') def add_shortcut(): @@ -119,12 +122,16 @@ def enable(): """Enable the module.""" actions.superuser_run('mldonkey', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('mldonkey:index') def disable(): """Disable the module.""" actions.superuser_run('mldonkey', ['disable']) frontpage.remove_shortcut('mldonkey') + menu = main_menu.get('apps') + menu.demote_item('mldonkey:index') def diagnose(): diff --git a/plinth/modules/mumble/__init__.py b/plinth/modules/mumble/__init__.py index 32a390578..cd7e5c9a5 100644 --- a/plinth/modules/mumble/__init__.py +++ b/plinth/modules/mumble/__init__.py @@ -58,8 +58,7 @@ manual_page = 'Mumble' def init(): """Intialize the Mumble module.""" menu = main_menu.get('apps') - menu.add_urlname(name, 'mumble', 'mumble:index', - short_description) + menu.add_urlname(name, 'mumble', 'mumble:index', short_description) global service setup_helper = globals()['setup_helper'] @@ -70,6 +69,7 @@ def init(): if service.is_enabled(): add_shortcut() + menu.promote_item('mumble:index') class MumbleServiceView(ServiceView): @@ -90,6 +90,8 @@ def setup(helper, old_version=None): ], is_external=True, enable=enable, disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'mumble:index') def add_shortcut(): @@ -103,12 +105,16 @@ def enable(): """Enable the module.""" actions.superuser_run('service', ['enable', managed_services[0]]) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('mumble:index') def disable(): """Disable the module.""" actions.superuser_run('service', ['disable', managed_services[0]]) frontpage.remove_shortcut('mumble') + menu = main_menu.get('apps') + menu.demote_item('mumble:index') def diagnose(): diff --git a/plinth/modules/openvpn/__init__.py b/plinth/modules/openvpn/__init__.py index 8532e50a7..f9ebd8b36 100644 --- a/plinth/modules/openvpn/__init__.py +++ b/plinth/modules/openvpn/__init__.py @@ -67,6 +67,7 @@ def init(): if service.is_enabled() and is_setup(): add_shortcut() + menu.promote_item('openvpn:index') def setup(helper, old_version=None): @@ -81,6 +82,8 @@ def setup(helper, old_version=None): if service.is_enabled() and is_setup(): add_shortcut() + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'openvpn:index') def add_shortcut(): @@ -104,12 +107,16 @@ def enable(): """Enable the module.""" actions.superuser_run('service', ['enable', managed_services[0]]) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('openvpn:index') def disable(): """Enable the module.""" actions.superuser_run('service', ['disable', managed_services[0]]) frontpage.remove_shortcut('openvpn') + menu = main_menu.get('apps') + menu.demote_item('openvpn:index') def diagnose(): diff --git a/plinth/modules/privoxy/__init__.py b/plinth/modules/privoxy/__init__.py index e915d8ff8..7297c6c11 100644 --- a/plinth/modules/privoxy/__init__.py +++ b/plinth/modules/privoxy/__init__.py @@ -66,8 +66,7 @@ manual_page = 'Privoxy' def init(): """Intialize the module.""" menu = main_menu.get('apps') - menu.add_urlname(name, 'privoxy', 'privoxy:index', - short_description) + menu.add_urlname(name, 'privoxy', 'privoxy:index', short_description) global service setup_helper = globals()['setup_helper'] @@ -78,6 +77,7 @@ def init(): if service.is_enabled(): add_shortcut() + menu.promote_item('privoxy:index') def setup(helper, old_version=None): @@ -91,6 +91,8 @@ def setup(helper, old_version=None): enable=enable, disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'privoxy:index') def add_shortcut(): @@ -104,12 +106,16 @@ def enable(): """Enable the module.""" actions.superuser_run('service', ['enable', managed_services[0]]) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('privoxy:index') def disable(): """Disable the module.""" actions.superuser_run('service', ['disable', managed_services[0]]) frontpage.remove_shortcut('privoxy') + menu = main_menu.get('apps') + menu.demote_item('privoxy:index') class PrivoxyServiceView(ServiceView): diff --git a/plinth/modules/quassel/__init__.py b/plinth/modules/quassel/__init__.py index c7f05e332..2ca44ab1d 100644 --- a/plinth/modules/quassel/__init__.py +++ b/plinth/modules/quassel/__init__.py @@ -67,8 +67,7 @@ manual_page = 'Quassel' def init(): """Initialize the quassel module.""" menu = main_menu.get('apps') - menu.add_urlname(name, 'quassel', 'quassel:index', - short_description) + menu.add_urlname(name, 'quassel', 'quassel:index', short_description) global service setup_helper = globals()['setup_helper'] @@ -79,6 +78,7 @@ def init(): if service.is_enabled(): add_shortcut() + menu.promote_item('quassel:index') class QuasselServiceView(ServiceView): @@ -99,6 +99,8 @@ def setup(helper, old_version=None): ], is_external=True, enable=enable, disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'quassel:index') def add_shortcut(): @@ -112,12 +114,16 @@ def enable(): """Enable the module.""" actions.superuser_run('service', ['enable', managed_services[0]]) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('quassel:index') def disable(): """Disable the module.""" actions.superuser_run('service', ['disable', managed_services[0]]) frontpage.remove_shortcut('quassel') + menu = main_menu.get('apps') + menu.demote_item('quassel:index') def diagnose(): diff --git a/plinth/modules/radicale/__init__.py b/plinth/modules/radicale/__init__.py index d35a4498d..8f565650e 100644 --- a/plinth/modules/radicale/__init__.py +++ b/plinth/modules/radicale/__init__.py @@ -52,7 +52,6 @@ description = [ 'supported client ' 'application is needed. Radicale can be accessed by any user ' 'with a {box_name} login.'), box_name=_(cfg.box_name)), - _('Radicale provides a basic web interface, which only supports creating ' 'new calendars and addressbooks. It does not support adding events or ' 'contacts, which must be done using a separate client.'), @@ -87,6 +86,7 @@ def init(): if is_enabled(): add_shortcut() + menu.promote_item('radicale:index') def setup(helper, old_version=None): @@ -124,6 +124,8 @@ def setup(helper, old_version=None): is_running=is_running) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'radicale:index') def add_shortcut(): @@ -180,12 +182,16 @@ def enable(): """Enable the module.""" actions.superuser_run('radicale', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('radicale:index') def disable(): """Disable the module.""" actions.superuser_run('radicale', ['disable']) frontpage.remove_shortcut('radicale') + menu = main_menu.get('apps') + menu.demote_item('radicale:index') def load_augeas(): diff --git a/plinth/modules/roundcube/__init__.py b/plinth/modules/roundcube/__init__.py index 44fae5582..618ba9c18 100644 --- a/plinth/modules/roundcube/__init__.py +++ b/plinth/modules/roundcube/__init__.py @@ -64,8 +64,7 @@ manual_page = 'Roundcube' def init(): """Intialize the module.""" menu = main_menu.get('apps') - menu.add_urlname(name, 'roundcube', 'roundcube:index', - short_description) + menu.add_urlname(name, 'roundcube', 'roundcube:index', short_description) global service setup_helper = globals()['setup_helper'] @@ -76,6 +75,7 @@ def init(): if is_enabled(): add_shortcut() + menu.promote_item('roundcube:index') def setup(helper, old_version=None): @@ -89,6 +89,8 @@ def setup(helper, old_version=None): service = service_module.Service( 'roundcube', name, ports=['http', 'https'], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'roundcube:index') def add_shortcut(): @@ -106,12 +108,16 @@ def enable(): """Enable the module.""" actions.superuser_run('roundcube', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('roundcube:index') def disable(): """Enable the module.""" actions.superuser_run('roundcube', ['disable']) frontpage.remove_shortcut('roundcube') + menu = main_menu.get('apps') + menu.demote_item('roundcube:index') def diagnose(): diff --git a/plinth/modules/searx/__init__.py b/plinth/modules/searx/__init__.py index 53e64468e..b559b1e4b 100644 --- a/plinth/modules/searx/__init__.py +++ b/plinth/modules/searx/__init__.py @@ -56,8 +56,7 @@ manual_page = 'Searx' def init(): """Intialize the module.""" menu = main_menu.get('apps') - menu.add_urlname(name, 'searx', 'searx:index', - short_description) + menu.add_urlname(name, 'searx', 'searx:index', short_description) register_group(group) global service @@ -70,6 +69,7 @@ def init(): if is_enabled(): add_shortcut() + menu.promote_item('searx:index') def setup(helper, old_version=None): @@ -86,12 +86,15 @@ def setup(helper, old_version=None): ], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'searx:index') def add_shortcut(): """Helper method to add a shortcut to the frontpage.""" frontpage.add_shortcut('searx', name, short_description=short_description, - url='/searx/', login_required=True, allowed_groups=[group[0]]) + url='/searx/', login_required=True, + allowed_groups=[group[0]]) def get_safe_search_setting(): @@ -110,12 +113,16 @@ def enable(): """Enable the module.""" actions.superuser_run('searx', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('searx:index') def disable(): """Disable the module.""" actions.superuser_run('searx', ['disable']) frontpage.remove_shortcut('searx') + menu = main_menu.get('apps') + menu.demote_item('searx:index') def diagnose(): diff --git a/plinth/modules/shadowsocks/__init__.py b/plinth/modules/shadowsocks/__init__.py index 50ea3254e..9686c4e82 100644 --- a/plinth/modules/shadowsocks/__init__.py +++ b/plinth/modules/shadowsocks/__init__.py @@ -48,8 +48,8 @@ description = [ _('Your {box_name} can run a Shadowsocks client, that can connect to ' 'a Shadowsocks server. It will also run a SOCKS5 proxy. Local ' 'devices can connect to this proxy, and their data will be ' - 'encrypted and proxied through the Shadowsocks server.'), box_name=_( - cfg.box_name)), + 'encrypted and proxied through the Shadowsocks server.'), + box_name=_(cfg.box_name)), _('To use Shadowsocks after setup, set the SOCKS5 proxy URL in your ' 'device, browser or application to http://freedombox_address:1080/') ] @@ -73,6 +73,7 @@ def init(): if service.is_enabled(): add_shortcut() + menu.promote_item('shadowsocks:index') def setup(helper, old_version=None): @@ -86,6 +87,9 @@ def setup(helper, old_version=None): ], is_external=False, is_enabled=is_enabled, is_running=is_running, enable=enable, disable=disable) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'shadowsocks:index') + def add_shortcut(): """Helper method to add a shortcut to the frontpage.""" @@ -109,12 +113,16 @@ def enable(): """Enable service.""" actions.superuser_run('service', ['enable', managed_services[0]]) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('shadowsocks:index') def disable(): """Disable service.""" actions.superuser_run('service', ['disable', managed_services[0]]) frontpage.remove_shortcut('shadowsocks') + menu = main_menu.get('apps') + menu.demote_item('shadowsocks:index') def diagnose(): diff --git a/plinth/modules/syncthing/__init__.py b/plinth/modules/syncthing/__init__.py index 7a60fc169..8070b399f 100644 --- a/plinth/modules/syncthing/__init__.py +++ b/plinth/modules/syncthing/__init__.py @@ -68,8 +68,7 @@ manual_page = 'Syncthing' def init(): """Intialize the module.""" menu = main_menu.get('apps') - menu.add_urlname(name, 'syncthing', 'syncthing:index', - short_description) + menu.add_urlname(name, 'syncthing', 'syncthing:index', short_description) register_group(group) global service @@ -83,6 +82,7 @@ def init(): if is_enabled(): add_shortcut() + menu.promote_item('syncthing:index') def setup(helper, old_version=None): @@ -98,14 +98,15 @@ def setup(helper, old_version=None): is_running=is_running) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'syncthing:index') def add_shortcut(): """Helper method to add a shortcut to the frontpage.""" - frontpage.add_shortcut('syncthing', name, - short_description=short_description, - url='/syncthing/', login_required=True, - allowed_groups=[group[0]]) + frontpage.add_shortcut( + 'syncthing', name, short_description=short_description, + url='/syncthing/', login_required=True, allowed_groups=[group[0]]) def is_running(): @@ -123,12 +124,16 @@ def enable(): """Enable the module.""" actions.superuser_run('syncthing', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('syncthing:index') def disable(): """Enable the module.""" actions.superuser_run('syncthing', ['disable']) frontpage.remove_shortcut('syncthing') + menu = main_menu.get('apps') + menu.demote_item('syncthing:index') def diagnose(): diff --git a/plinth/modules/tahoe/__init__.py b/plinth/modules/tahoe/__init__.py index b59ec92e1..6c4c2b626 100644 --- a/plinth/modules/tahoe/__init__.py +++ b/plinth/modules/tahoe/__init__.py @@ -97,6 +97,7 @@ def init(): if is_enabled(): add_shortcut() + menu.promote_item('tahoe:index') def setup(helper, old_version=None): @@ -124,6 +125,8 @@ def post_setup(configured_domain_name): is_running=is_running) service.notify_enabled(None, True) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('tahoe:index') def add_shortcut(): @@ -150,12 +153,16 @@ def enable(): """Enable the module.""" actions.superuser_run('tahoe-lafs', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('tahoe:index') def disable(): """Enable the module.""" actions.superuser_run('tahoe-lafs', ['disable']) frontpage.remove_shortcut('tahoe-lafs') + menu = main_menu.get('apps') + menu.demote_item('tahoe:index') def diagnose(): diff --git a/plinth/modules/tor/__init__.py b/plinth/modules/tor/__init__.py index 60f628518..dece12353 100644 --- a/plinth/modules/tor/__init__.py +++ b/plinth/modules/tor/__init__.py @@ -71,6 +71,9 @@ def init(): needs_setup = setup_helper.get_state() == 'needs-setup' if not needs_setup: + if utils.is_enabled(): + menu.promote_item('tor:index') + global socks_service socks_service = service_module.Service( 'tor-socks', _('Tor Socks Proxy'), ports=['tor-socks'], @@ -167,8 +170,8 @@ def diagnose(): ports = json.loads(output)['ports'] results.append([ - _('Tor relay port available'), 'passed' - if 'orport' in ports else 'failed' + _('Tor relay port available'), + 'passed' if 'orport' in ports else 'failed' ]) if 'orport' in ports: results.append( @@ -177,16 +180,16 @@ def diagnose(): action_utils.diagnose_port_listening(ports['orport'], 'tcp6')) results.append([ - _('Obfs3 transport registered'), 'passed' - if 'obfs3' in ports else 'failed' + _('Obfs3 transport registered'), + 'passed' if 'obfs3' in ports else 'failed' ]) if 'obfs3' in ports: results.append( action_utils.diagnose_port_listening(ports['obfs3'], 'tcp4')) results.append([ - _('Obfs4 transport registered'), 'passed' - if 'obfs4' in ports else 'failed' + _('Obfs4 transport registered'), + 'passed' if 'obfs4' in ports else 'failed' ]) if 'obfs4' in ports: results.append( diff --git a/plinth/modules/transmission/__init__.py b/plinth/modules/transmission/__init__.py index 8e77bcf80..99f87c557 100644 --- a/plinth/modules/transmission/__init__.py +++ b/plinth/modules/transmission/__init__.py @@ -74,6 +74,7 @@ def init(): if is_enabled(): add_shortcut() + menu.promote('transmission:index') def setup(helper, old_version=None): @@ -97,13 +98,14 @@ def setup(helper, old_version=None): disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'transmission:index') def add_shortcut(): - frontpage.add_shortcut('transmission', name, - short_description=short_description, - url='/transmission', login_required=True, - allowed_groups=[group[0]]) + frontpage.add_shortcut( + 'transmission', name, short_description=short_description, + url='/transmission', login_required=True, allowed_groups=[group[0]]) def is_enabled(): @@ -116,12 +118,16 @@ def enable(): """Enable the module.""" actions.superuser_run('transmission', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('transmission:index') def disable(): """Enable the module.""" actions.superuser_run('transmission', ['disable']) frontpage.remove_shortcut('transmission') + menu = main_menu.get('apps') + menu.demote_item('transmission:index') def diagnose(): diff --git a/plinth/modules/ttrss/__init__.py b/plinth/modules/ttrss/__init__.py index d4581c8fa..8068fbdd0 100644 --- a/plinth/modules/ttrss/__init__.py +++ b/plinth/modules/ttrss/__init__.py @@ -67,8 +67,7 @@ manual_page = 'TinyTinyRSS' def init(): """Intialize the module.""" menu = main_menu.get('apps') - menu.add_urlname(name, 'ttrss', 'ttrss:index', - short_description) + menu.add_urlname(name, 'ttrss', 'ttrss:index', short_description) register_group(group) global service @@ -81,6 +80,7 @@ def init(): if is_enabled(): add_shortcut() + menu.promote_item('ttrss:index') def setup(helper, old_version=None): @@ -97,6 +97,8 @@ def setup(helper, old_version=None): disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) + menu = main_menu.get('apps') + helper.call('post', menu.promote_item, 'ttrss:index') def force_upgrade(helper, packages): @@ -131,12 +133,16 @@ def enable(): """Enable the module.""" actions.superuser_run('ttrss', ['enable']) add_shortcut() + menu = main_menu.get('apps') + menu.promote_item('ttrss:index') def disable(): """Enable the module.""" actions.superuser_run('ttrss', ['disable']) frontpage.remove_shortcut('ttrss') + menu = main_menu.get('apps') + menu.demote_item('ttrss:index') def diagnose(): diff --git a/plinth/templates/cards.html b/plinth/templates/cards.html index 4cbbb299f..14f93345e 100644 --- a/plinth/templates/cards.html +++ b/plinth/templates/cards.html @@ -33,27 +33,54 @@ + {% if show_secondary %} +
+
{% trans "Disabled" %}
+
+
+ {% for item in submenu.sorted_items %} + {% if item.secondary %} + + {% endif %} + {% endfor %} +
+
+
+ {% endif %} + {% block content-container %} {% endblock %} diff --git a/plinth/urls.py b/plinth/urls.py index 4404308c7..07be6c566 100644 --- a/plinth/urls.py +++ b/plinth/urls.py @@ -18,7 +18,6 @@ Django URLconf file containing all urls """ from django.conf.urls import url -from django.views.generic import TemplateView from captcha import views as cviews from plinth.modules.sso.views import CaptchaLoginView @@ -28,24 +27,20 @@ from . import views urlpatterns = [ url(r'^$', views.index, name='index'), - url(r'^language-selection/$', - public(views.LanguageSelectionView.as_view()), - name='language-selection'), - url(r'^apps/$', - TemplateView.as_view(template_name='apps.html'), name='apps'), + url(r'^language-selection/$', public( + views.LanguageSelectionView.as_view()), name='language-selection'), + url(r'^apps/$', views.AppsIndexView.as_view(), name='apps'), url(r'^sys/$', views.system_index, name='system'), # captcha urls are public - url(r'^captcha/image/(?P\w+)/$', - public(cviews.captcha_image), name='captcha-image', - kwargs={'scale': 1}), - url(r'^captcha/image/(?P\w+)@2/$', - public(cviews.captcha_image), name='captcha-image-2x', - kwargs={'scale': 2}), - url(r'^captcha/audio/(?P\w+)/$', - public(cviews.captcha_audio), name='captcha-audio'), - url(r'^captcha/refresh/$', - public(cviews.captcha_refresh), name='captcha-refresh'), + url(r'^captcha/image/(?P\w+)/$', public(cviews.captcha_image), + name='captcha-image', kwargs={'scale': 1}), + url(r'^captcha/image/(?P\w+)@2/$', public(cviews.captcha_image), + name='captcha-image-2x', kwargs={'scale': 2}), + url(r'^captcha/audio/(?P\w+)/$', public(cviews.captcha_audio), + name='captcha-audio'), + url(r'^captcha/refresh/$', public(cviews.captcha_refresh), + name='captcha-refresh'), # locked url from django-axes url(r'locked/$', public(CaptchaLoginView.as_view()), name='locked_out'), diff --git a/plinth/views.py b/plinth/views.py index e761158c2..df182cde0 100644 --- a/plinth/views.py +++ b/plinth/views.py @@ -66,6 +66,16 @@ def index(request): }) +class AppsIndexView(TemplateView): + """View for apps index""" + template_name = 'apps.html' + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + context['show_secondary'] = True + return context + + def system_index(request): """Serve the system index page.""" disk_views.warn_about_low_disk_space(request) @@ -186,7 +196,8 @@ class SetupView(TemplateView): # Perform expensive operation only if needed if not context['setup_current_operation']: - context['package_manager_is_busy'] = package.is_package_manager_busy() + context[ + 'package_manager_is_busy'] = package.is_package_manager_busy() return context