protected $uptodate = false;
protected $managed_groups = [];
protected $cron = false;
+ protected $compact_menu = false;
/**
* Logs in user.
return $this->managed_groups;
}
+ /**
+ * Get compact menu mode
+ *
+ * @return bool
+ */
+ public function getCompactMenu(): bool
+ {
+ return ($this->logged && isset($_COOKIE['galette_compact_menu']) && $_COOKIE['galette_compact_menu']) ? true : false;
+ }
+
/**
* Is user currently up to date?
* An up to date member is active and either due free, or with up to date
{% set component_classes = "ui text compact small fluid menu" %}
{% endif %}
{% endif %}
-
-{% if ui == 'item' %}
- <div class="{{ component_classes }}">
- <div class="ui basic center aligned fitted segment">
- <span class="ui tiny header">{{ login.loggedInAs()|raw }}</span>
- </div>
- <a
- class="ui fluid {% if login.isImpersonated() %}purple{% else %}red{% endif %} basic button"
- href="{% if login.isImpersonated() %}{{ url_for("unimpersonate") }}{% else %}{{ url_for("logout") }}{% endif %}"
- >
- <i class="icon {% if login.isImpersonated() %}user secret{% else %}sign out alt{% endif %}"></i>
- {% if login.isImpersonated() %}{{ _T("Unimpersonate") }}{% else %}{{ _T("Log off") }}{% endif %}
- </a>
- </div>
-{% else %}
- <div class="{{ component_classes }}">
- <div class="ui item">
- <i class="user circle big icon"></i>
- {{ login.loggedInAs()|raw }}
- </div>
- <div class="right menu">
- <div class="item">
- <a
- class="ui {% if login.isImpersonated() %}purple{% else %}red{% endif %} icon button"
- href="{% if login.isImpersonated() %}{{ url_for("unimpersonate") }}{% else %}{{ url_for("logout") }}{% endif %}"
- title="{% if login.isImpersonated() %}{{ _T("Unimpersonate") }}{% else %}{{ _T("Log off") }}{% endif %}"
- data-position="bottom right"
- >
- <i class="icon {% if login.isImpersonated() %}user secret{% else %}sign out alt{% endif %}"></i>
- <span class="displaynone">{% if login.isImpersonated() %}{{ _T("Unimpersonate") }}{% else %}{{ _T("Log off") }}{% endif %}</span>
- </a>
+{% if login.isLogged() %}
+ {% if ui == 'item' %}
+ <div class="{{ component_classes }}">
+ <div class="ui basic center aligned fitted segment">
+ <span class="ui tiny header">{{ login.loggedInAs()|raw }}</span>
</div>
+ <a
+ class="ui fluid {% if login.isImpersonated() %}purple{% else %}red{% endif %} basic button"
+ href="{% if login.isImpersonated() %}{{ url_for("unimpersonate") }}{% else %}{{ url_for("logout") }}{% endif %}"
+ >
+ <i class="icon {% if login.isImpersonated() %}user secret{% else %}sign out alt{% endif %}"></i>
+ {% if login.isImpersonated() %}{{ _T("Unimpersonate") }}{% else %}{{ _T("Log off") }}{% endif %}
+ </a>
</div>
- </div>
+ {% else %}
+ {% if not login.getCompactMenu() %}
+ <div class="{{ component_classes }}">
+ <div class="ui item">
+ <i class="user circle big icon"></i>
+ {{ login.loggedInAs()|raw }}
+ </div>
+ <div class="right menu">
+ <div class="item">
+ <a
+ class="ui {% if login.isImpersonated() %}purple{% else %}red{% endif %} icon button"
+ href="{% if login.isImpersonated() %}{{ url_for("unimpersonate") }}{% else %}{{ url_for("logout") }}{% endif %}"
+ title="{% if login.isImpersonated() %}{{ _T("Unimpersonate") }}{% else %}{{ _T("Log off") }}{% endif %}"
+ data-position="bottom right"
+ >
+ <i class="icon {% if login.isImpersonated() %}user secret{% else %}sign out alt{% endif %}"></i>
+ <span class="displaynone">{% if login.isImpersonated() %}{{ _T("Unimpersonate") }}{% else %}{{ _T("Log off") }}{% endif %}</span>
+ </a>
+ </div>
+ </div>
+ </div>
+ {% include "elements/modes.html.twig" %}
+ {% else %}
+ {% set component_classes = "ui vertical centered tiny fluid icon menu" %}
+ <div id="logoutmenu" class="{{ component_classes }}">
+ <div class="ui dropdown item no-touch tooltip" data-html="{{ login.loggedInAs()|raw }}" data-position="right center">
+ <i class="user circle icon"></i>
+ <span class="text displaynone">{{ login.loggedInAs()|raw }}</span>
+ <div class="menu">
+ <div class="item">
+ <div class="ui basic center aligned fitted segment">
+ <img src="{{ url_for('logo') }}" width="{{ logo.getOptimalWidth() }}" height="{{ logo.getOptimalHeight() }}" alt="{{ preferences.pref_nom }}" class="icon"/>
+ <div class="ui block huge brand header">
+ {{ preferences.pref_nom }}
+ {% if preferences.pref_slogan %}<div class="sub tiny header">{{ __(preferences.pref_slogan) }}</div>{% endif %}
+ </div>
+ </div>
+ {{ login.loggedInAs()|raw }}
+ <div class="ui basic fitted segment">
+ {% include "elements/modes.html.twig" %}
+ </div>
+ <a
+ class="ui {% if login.isImpersonated() %}purple{% else %}red{% endif %} icon button"
+ href="{% if login.isImpersonated() %}{{ url_for("unimpersonate") }}{% else %}{{ url_for("logout") }}{% endif %}"
+ >
+ <i class="icon {% if login.isImpersonated() %}user secret{% else %}sign out alt{% endif %}"></i>
+ {% if login.isImpersonated() %}{{ _T("Unimpersonate") }}{% else %}{{ _T("Log off") }}{% endif %}
+ </a>
+ </div>
+ </div>
+ </div>
+ </div>
+ {% endif %}
+ {% endif %}
{% endif %}
-<aside class="ui computer only toc">
-{% if login.isLogged() %}
+<aside id="sidemenu" class="ui computer only toc{% if login.getCompactMenu() %} compact_menu{% endif %}">
{% include "elements/logout.html.twig" with {
ui: "menu"
} %}
-{% endif %}
-
- {% include "elements/modes.html.twig" %}
+{% if not login.getCompactMenu() %}
<div class="ui basic center aligned fitted segment">
<img src="{{ url_for('logo') }}" width="{{ logo.getOptimalWidth() }}" height="{{ logo.getOptimalHeight() }}" alt="{{ preferences.pref_nom }}" class="icon"/>
<div class="ui block huge brand header">
{% if preferences.pref_slogan %}<div class="sub tiny header">{{ __(preferences.pref_slogan) }}</div>{% endif %}
</div>
</div>
+{% endif %}
+
+ <div class="ui vertical{% if not login.getCompactMenu() %} accordion compact{% else %} tiny icon{% endif %} fluid menu">
+ {% set mode = login.getCompactMenu() ? "compact" : "accordion" %}
+ {% include "elements/navigation/navigation_items.html.twig" with {
+ mode: mode
+ } %}
+ </div>
- <div class="ui vertical accordion compact fluid menu">
- {% include "elements/navigation/navigation_items.html.twig" %}
+ <div class="ui basic fitted segment">
+ <div class="ui toggle mini checkbox">
+ <input type="checkbox" name="compactmenu" id="compactmenu" class="hidden"{% if login.getCompactMenu() %} checked="checked"{% endif %}>
+ <label for="compactmenu"{% if login.getCompactMenu() %} class="no-touch tooltip" data-html="{{ _T("Compact menu") }}"{% endif %}>
+ {% if not login.getCompactMenu() %}{{ _T("Compact menu") }}{% endif %}
+ </label>
+ </div>
</div>
</aside>
{% import "macros.twig" as menus_macros %}
+{% set mode = (mode is defined) ? mode %}
+
{% if login.isLogged() %}
<a href="{{ url_for('dashboard') }}"
title="{{ _T("Go to Galette's dashboard") }}"
class="{% if cur_route == "dashboard" %}active {% endif %}item"
+ data-position="right center"
>
- <div class="image header title">
+ {% if mode != "compact" %}
+ <div class="image header title{% if mode == "compact" %} no-touch tooltip" data-html="{{ _T("Dashboard") }}"{% else %}"{% endif %}>
+ {% endif %}
<i class="compass icon" aria-hidden="true"></i>
+ {% if mode != "compact" %}
{{ _T("Dashboard") }}
</div>
+ {% endif %}
</a>
{% endif %}
{% set menus = callstatic('\\Galette\\Core\\Galette', 'getAllMenus') %}
{% for menu in menus %}
- {{ menus_macros.renderMenu(menu.title, menu.icon, menu.items) }}
+ {{ menus_macros.renderMenu(menu.title, menu.icon, menu.items, mode) }}
{% endfor %}
-<header id="top-navbar" class="ui large top fixed menu">
+<header id="top-navbar" class="ui top fixed menu">
<div class="ui fluid container">
<a class="toc item">
<i class="sidebar icon"></i>
}
});
+ {% if login.isLogged() %}
+ // Display user menu in compact mode
+ var _compactMenu = function() {
+ var _hidden = Cookies.get('galette_compact_menu');
+ var _menu = document.getElementById('sidemenu');
+ var _content = _menu.nextElementSibling;
+ var _trigger = document.getElementById('compactmenu');
+ if (_hidden & _hidden == 1) {
+ _trigger.checked = true;
+ _menu.classList.add('compact_menu');
+ _content.classList.add('extended');
+ }
+ _trigger.addEventListener('change', function() {
+ var _checked = $(this).is(':checked');
+ Cookies.set(
+ 'galette_compact_menu',
+ (_checked ? 1 : 0),
+ {
+ expires: 365,
+ path: '/'
+ }
+ );
+ window.location.reload();
+ });
+ }
+
+ _compactMenu();
+ {% endif %}
+
{% if autocomplete %}
$('#ville_adh_field, #lieu_naissance_field').search({
apiSettings: {
-{% macro renderMenu(title, icon, items) %}
+{% macro renderMenu(title, icon, items, mode) %}
{% set my_routes = [] %}
{% for item in items %}
{% set my_routes = my_routes|merge([item.route.name])|merge(item.route.aliases ?? []) %}
{% endfor %}
- <div class="item">
- <div class="image header title{% if cur_route in my_routes %} active{% endif %}">
+ {% if mode == "compact" %}
+ <div class="ui{% if cur_route in my_routes %} active-menu{% endif %} dropdown item no-touch tooltip" data-html="{{ title }}" data-position="right center">
<i class="{{ icon }} icon"></i>
- {{ title }}
- <i class="dropdown icon"></i>
+ <span class="displaynone">{{ title }}</span>
+ <div class="menu">
+ {% for item in items %}
+ {{ _self.renderMenuItem(item.label, item.title, item.route, item.icon ?? null, null, 'right center') }}
+ {% endfor %}
+ </div>
</div>
- <div class="content{% if cur_route in my_routes %} active{% endif %}">
- {% for item in items %}
- {{ _self.renderMenuItem(item.label, item.title, item.route, item.icon ?? null) }}
- {% endfor %}
+ {% else %}
+ <div class="item">
+ <div class="image header title{% if cur_route in my_routes %} active{% endif %}">
+ <i class="{{ icon }} icon"></i>
+ {{ title }}
+ <i class="dropdown icon"></i>
+ </div>
+ <div class="content{% if cur_route in my_routes %} active{% endif %}">
+ {% for item in items %}
+ {{ _self.renderMenuItem(item.label, item.title, item.route, item.icon ?? null) }}
+ {% endfor %}
+ </div>
</div>
- </div>
+ {% endif %}
{% endmacro %}
{% macro renderMenuItem(label, title, route, icon, class, tips_position) %}
{% if login.isLogged() %}
{% include 'elements/navigation/navigation_aside.html.twig' %}
{% endif %}
- <section class="content{% if contentcls is defined %} {{ contentcls }}{% endif %}">
+ <section class="content{% if contentcls is defined %} {{ contentcls }}{% endif %}{% if login.getCompactMenu() %} extended{% endif %}">
{% if not login.isLogged() %}
<div class="ui basic center aligned fitted segment">
<img src="{{ url_for("logo") }}" width="{{ logo.getOptimalWidth() }}" height="{{ logo.getOptimalHeight() }}" alt="{{ preferences.pref_nom }}" class="icon"/>
overflow-y: scroll;
width: 260px;
padding: 1.25rem;
+ &.compact_menu {
+ z-index: 1001;
+ width: 85px;
+ overflow-y: initial;
+ #logoutmenu {
+ .ui.dropdown .menu > .item:hover,
+ .ui.dropdown .menu > .active.item {
+ background: @white !important;
+ color: @textColor !important;
+ font-weight: 400 !important;
+ cursor: default;
+ }
+ .brand.header {
+ max-width: 500px;
+ white-space: normal;
+ }
+ }
+ .ui.menu .dropdown.item.active-menu {
+ background: @lightGaletteColor;
+ }
+ .ui.toggle.checkbox {
+ line-height: 1rem;
+ input {
+ width: 3rem;
+ height: 1rem;
+ &:checked ~ label::after {
+ left: 1.35rem;
+ }
+ }
+ label {
+ min-height: 1rem;
+ padding-left: 4rem;
+ &::before {
+ width: 2.4rem;
+ height: 1rem;
+ }
+ &::after {
+ width: 1rem;
+ height: 1rem;
+ }
+ }
+ }
+ }
}
body:not(.front-page) section.content {
margin-left: 260px;
flex: 1 1 auto;
+ &.extended {
+ margin-left: 85px;
+ }
}
section.desktop .container {