Verified Commit 56c0a750 authored by Štěpán Henek's avatar Štěpán Henek 🌩

second level menus implemented

parent 0dacd2df
......@@ -42,15 +42,63 @@ from foris.state import current_state
logger = logging.getLogger(__name__)
class ConfigPageMixin(object):
# page url part /config/<slug>
slug: typing.Optional[str] = None
class BaseConfigPage(object):
menu_order = 50
slug: typing.Optional[str] = None
page_name: typing.Optional[str] = None
subpages: typing.Iterable[typing.Type['ConfigPageMixin']] = []
@staticmethod
def get_menu_tag_static(cls):
if current_state.guide.enabled and current_state.guide.current == cls.slug:
return {
"show": True,
"hint": "",
"text": "<i class='fas fa-reply'></i>",
}
else:
return {
"show": False,
"hint": "",
"text": "",
}
@classmethod
def get_menu_tag(cls):
return ConfigPageMixin.get_menu_tag_static(cls)
@staticmethod
def is_visible_static(cls):
if current_state.guide.enabled:
return cls.slug in current_state.guide.steps
return True
@classmethod
def is_visible(cls):
return ConfigPageMixin.is_visible_static(cls)
@staticmethod
def is_enabled_static(cls):
if current_state.guide.enabled:
return cls.slug in current_state.guide.available_tabs
return True
@classmethod
def is_enabled(cls):
return ConfigPageMixin.is_enabled_static(cls)
@classmethod
def subpage_slugs(cls):
return [e.slug for e in cls.subpages]
class ConfigPageMixin(BaseConfigPage):
# page url part /config/<slug>
template = "config/main"
template_type = "simple"
subpages: typing.Iterable[typing.Type['ConfigPageMixin']] = []
def call_action(self, action):
"""Call config page action.
......@@ -115,46 +163,9 @@ class ConfigPageMixin(object):
messages.warning(_("There were some errors in your input."))
return result
@staticmethod
def get_menu_tag_static(cls):
if current_state.guide.enabled and current_state.guide.current == cls.slug:
return {
"show": True,
"hint": "",
"text": "<i class='fas fa-reply'></i>",
}
else:
return {
"show": False,
"hint": "",
"text": "",
}
@classmethod
def get_menu_tag(cls):
return ConfigPageMixin.get_menu_tag_static(cls)
@staticmethod
def is_visible_static(cls):
if current_state.guide.enabled:
return cls.slug in current_state.guide.steps
return True
@classmethod
def is_visible(cls):
return ConfigPageMixin.is_visible_static(cls)
@staticmethod
def is_enabled_static(cls):
if current_state.guide.enabled:
return cls.slug in current_state.guide.available_tabs
return True
@classmethod
def is_enabled(cls):
return ConfigPageMixin.is_enabled_static(cls)
class JoinedPages(BaseConfigPage):
userfriendly_title = None
class NotificationsConfigPage(ConfigPageMixin):
......@@ -433,24 +444,14 @@ class RemoteConfigPage(ConfigPageMixin, remote.RemoteHandler):
return ConfigPageMixin.is_enabled_static(cls)
class SubordinatesWifiConfigPage(ConfigPageMixin, subordinates.SubordinatesWifiHandler):
slug = "suboridnates-wifi"
menu_order = 1 # submenu
template = "config/subordinates"
class SubordinatesConfigPage(ConfigPageMixin, subordinates.SubordinatesConfigHandler):
slug = "subordinates"
menu_order = 12
menu_order = 1 # submenu
template = "config/subordinates"
userfriendly_title = gettext("Managed devices")
userfriendly_title = gettext("Set up")
template_type = "jinja2"
subpages = [
SubordinatesWifiConfigPage
]
def render(self, **kwargs):
data = current_state.backend.perform("subordinates", "list")
......@@ -652,6 +653,15 @@ class SubordinatesConfigPage(ConfigPageMixin, subordinates.SubordinatesConfigHan
raise bottle.HTTPError(404, "No form '%s' not found." % form_name)
class SubordinatesJoinedPage(JoinedPages):
userfriendly_title = gettext("Managed devices")
name = "subordinates-main"
subpages: typing.Iterable[typing.Type['ConfigPageMixin']] = [
SubordinatesConfigPage,
]
class ProfileConfigPage(ConfigPageMixin, profile.ProfileHandler):
slug = "profile"
menu_order = 13
......@@ -1077,7 +1087,7 @@ config_pages = {
e.slug: e for e in [
NotificationsConfigPage,
RemoteConfigPage,
SubordinatesConfigPage,
SubordinatesJoinedPage,
PasswordConfigPage,
ProfileConfigPage,
NetworksConfigPage,
......@@ -1113,18 +1123,30 @@ def add_config_page(page_class):
"""
if page_class.slug is None:
raise Exception("Page %s doesn't define a propper slug" % page_class)
if page_class.slug in config_pages:
page_map = {k: v for k, v in config_pages.items()}
for page in config_pages.values():
for subpage in page.subpages:
page_map[subpage.slug] = subpage
if page_class.slug in page_map:
raise Exception("Error when adding page %s slug '%s' is already used in %s" % (
page_class, page_class.slug, config_pages[page_class.slug]
page_class, page_class.slug, page_map[page_class.slug]
))
config_pages[page_class.slug] = page_class
def get_config_page(page_name):
ConfigPage = config_pages.get(page_name, None)
if ConfigPage is None:
raise bottle.HTTPError(404, "Unknown configuration page.")
return ConfigPage
if ConfigPage:
return ConfigPage
# Try to iterate through subpages
for page in config_pages.values():
for subpage in page.subpages:
if subpage.slug == page_name:
return subpage
raise bottle.HTTPError(404, "Unknown configuration page.")
def _redirect_to_default_location():
......
......@@ -60,6 +60,7 @@ Foris.initialize = function () {
Foris.initWsHandlers();
Foris.initWebsockets();
Foris.initRebootRequired();
Foris.initMenuExpand();
};
Foris.initParsley = function () {
......@@ -777,6 +778,25 @@ Foris.performBackendQuery = async (controller_id, module, action, data) => {
});
};
Foris.initMenuExpand = () => {
$("#menu nav li.nav-expandable").click((e) => {
e.preventDefault();
let current = $(e.currentTarget);
let self_slug = current.attr("data-self-name");
if (self_slug && !current.hasClass("subpage-active")) {
$(`.parent-name-${self_slug}`).toggle("slow");
let expand_tag = current.find(".expand-tag i");
if (expand_tag.hasClass("fa-caret-square-down")) {
expand_tag.removeClass();
expand_tag.addClass("fas fa-caret-square-up");
} else {
expand_tag.removeClass();
expand_tag.addClass("fas fa-caret-square-down");
}
}
});
}
$(document).ready(function () {
Foris.initialize();
......
......@@ -77,6 +77,9 @@ $nav-item-border: 2px solid #ddd
background-color: #000
font-weight: bold
span.expand-tag
float: right
#subnav
+pie-clearfix
font-weight: bold
......@@ -185,4 +188,4 @@ $nav-item-border: 2px solid #ddd
#menu .submenu-item
padding-left: 1.5em
background-color: lighten(desaturate($sidebar-background-color, 20), 5)
background-color: lighten($sidebar-background-color, 4)
{% extends '_layout.html.j2' %}
{% macro write_active(page) -%}
{% if active_config_page_key is defined and active_config_page_key == page.slug %} active{% endif %}
{% endmacro -%}
{% macro render_menu_item(page, parent, display) -%}
{% if page.is_visible() and page.is_enabled() %}
<li class="{{ write_active(page) }}{% if parent %} submenu-item parent-name-{{ parent.name }}{% endif %}{% if active_config_page_key in page.subpage_slugs() %} subpage-active{% endif %}{% if not page.slug %} nav-expandable{% endif %}" {% if not display %}style="display: none;"{% endif %} data-self-name="{{ page.name if page.name else "" }}">
<a href="{{ url("config_page", page_name=page.slug) if page.slug else "#" }}">{% if parent %}<i class="fas fa-level-up-alt rotate-90"></i> {% endif %}{{ page.userfriendly_title }}
{% if page.subpages and active_config_page_key not in page.subpage_slugs() %}
<span title="{% trans %}Expandable{% endtrans %}" id="{{ page.slug or page.name }}_expand" class="expand-tag"><i class='fas fa-caret-square-down'></i></span>
{% elif page.get_menu_tag()["show"] %}
<span title="{{ page.get_menu_tag()["hint"]}}" style="{{"" if page.get_menu_tag()["show"] else "display: none" }}" id="{{ page.slug or page.name }}_menu_tag" class="menu-tag">
{{ page.get_menu_tag()["text"]|safe }}
</span>
{% endif %}
</a>
</li>
{% elif page.is_visible() %}
<li><span class="link-disabled"{% if not display %}style="display: none;"{% endif %}>{{ page.userfriendly_title }}</span></li>
{% endif %}
{% endmacro -%}
{% block base %}
{% if is_xhr is not defined %}
......@@ -65,32 +87,10 @@
<ul>
{% for config_page in get_config_pages() %}
{% if config_page.is_visible() and config_page.is_enabled() %}
<li{{ ' class="active"' if active_config_page_key is defined and config_page.slug == active_config_page_key else "" }}>
<a href="{{ url("config_page", page_name=config_page.slug) }}">{{ config_page.userfriendly_title }}
{% if config_page.get_menu_tag()["show"] %}
<span title="{{ config_page.get_menu_tag()["hint"]}}" style="{{"" if config_page.get_menu_tag()["show"] else "display: none" }}" id="{{ config_page.slug }}_menu_tag" class="menu-tag">
{{ config_page.get_menu_tag()["text"]|safe }}
</span>
{% endif %}
</a>
</li>
{% for subpage in config_page.subpages %}
{% if subpage.is_visible() and subpage.is_enabled() %}
<li class="{{ "active" if active_config_page_key is defined and subpage.slug == active_config_page_key else "" }} submenu-item">
<a href="{{ url("config_page", page_name=subpage.slug) }}"><i class="fas fa-level-up-alt rotate-90"></i> {{ subpage.userfriendly_title }}
{% if subpage.get_menu_tag()["show"] %}
<span title="{{ subpage.get_menu_tag()["hint"]}}" style="{{"" if subpage.get_menu_tag()["show"] else "display: none" }}" id="{{ subpage.slug }}_menu_tag" class="menu-tag">
{{ subpage.get_menu_tag()["text"]|safe }}
</span>
{% endif %}
</a>
{% elif subpage.is_visible() %}
<li><span class="link-disabled">{{ subpage.userfriendly_title }}</span></li>
{% endif %}
</li>
{% endfor %}
{% elif config_page.is_visible() %}
<li><span class="link-disabled">{{ config_page.userfriendly_title }}</span></li>
{{ render_menu_item(config_page, None, True) }}
{% for subpage in config_page.subpages %}
{{ render_menu_item(subpage, config_page, config_page.slug == active_config_page_key or active_config_page_key in config_page.subpage_slugs()) }}
{% endfor %}
{% endif %}
{% endfor %}
</ul>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment