Add new sidebar main menu

Add a left side menu navigation style. The main app navigation links
will be displayed here. The notification, user and system tools are now
displayed at the top navigation bar.

Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
Roberto Rosario
2018-12-20 16:42:50 -04:00
parent f77f64cc71
commit 60ac63ead4
12 changed files with 276 additions and 40 deletions

View File

@@ -202,6 +202,11 @@
- Updated the source test behavior to allow testing a source - Updated the source test behavior to allow testing a source
even when the source is disabled and to not deleted downloaded even when the source is disabled and to not deleted downloaded
content during a test. content during a test.
- Update the user interface to add new sidebar main menu for a
more common left side menu navigation style. The main app
navigation links will be displayed here. The notification,
user and system tools are now displayed at the top navigation
bar.
3.1.9 (2018-11-01) 3.1.9 (2018-11-01)
================== ==================

View File

@@ -49,10 +49,6 @@
url('../fonts/Lato_400italic.ttf') format('truetype'); url('../fonts/Lato_400italic.ttf') format('truetype');
} }
body {
padding-top: 70px;
}
.navbar-brand { .navbar-brand {
font-family: "IM Fell English SC", serif; font-family: "IM Fell English SC", serif;
} }
@@ -142,11 +138,7 @@ hr {
} }
.radio ul li { .radio ul li {
list-style-type:none; list-style-type: none;
}
a i {
padding-right: 3px;
} }
.dashboard-widget { .dashboard-widget {
@@ -341,3 +333,148 @@ a i {
font-size: 110%; font-size: 110%;
font-weight: bold; font-weight: bold;
} }
body {
padding-top: 40px;
}
.sub-header {
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
/*
* Top navigation
* Hide default border to remove 1px line.
*/
.navbar-fixed-top {
border: 0;
}
/*
* Sidebar
*/
/* Hide for mobile, show later */
.sidebar {
display: none;
}
@media (min-width: 768px) {
.sidebar {
position: fixed;
top: 51px;
bottom: 0;
left: 0;
z-index: 1000;
display: block;
padding-top: 10px;
overflow-x: hidden;
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
background-color: #2c3e50;
border-right: 1px solid #18bc9c;
}
.navbar-brand {
text-align: center;
width: 210px;
}
}
/*
* Main content
*/
.main {
padding: 20px;
}
@media (min-width: 768px) {
.main {
padding-right: 0px;
padding-left: 0px;
margin-left: 210px;
}
}
.main .page-header {
margin-top: 0;
}
.sidebar {
width: 210px;
}
.navbar-brand {
}
.container-fluid {
margin-right: 0px;
margin-left: 0px;
width: 100%;
}
.navbar-form > .form-control {
padding: 0px;
height: 35px;
margin-top: 3px;
}
#accordion-sidebar a {
padding: 10px 15px;
}
#accordion-sidebar a[aria-expanded="true"] {
background: #1a242f;
}
#accordion-sidebar .panel {
border: 0px;
}
#accordion-sidebar a {
text-decoration: none;
outline: none;
position: relative;
display: block;
}
#accordion-sidebar .panel-heading {
background-color: #2c3e50;
color: white;
padding: 0px;
}
#accordion-sidebar .panel-heading:hover {
background-color: #517394;
}
#accordion-sidebar .panel-title {
font-size: 15px;
}
#accordion-sidebar .panel-body {
font-size: 13px;
border: 0px;
background-color: #2c3e50;
padding-top: 5px;
padding-left: 20px;
padding-right: 0px;
padding-bottom: 0px;
}
#accordion-sidebar .panel-body li {
padding: 0px;
}
#accordion-sidebar .panel-body li:hover {
background-color: #517394;
}
#accordion-sidebar .panel-body a {
color: white;
text-decoration: none;
padding: 9px;
}
.navbar-brand {
outline: none;
}

View File

@@ -4,18 +4,13 @@ class MayanApp {
constructor (parameters) { constructor (parameters) {
var self = this; var self = this;
parameters = parameters || {} parameters = parameters || {
ajaxMenusOptions: []
}
this.ajaxSpinnerSeletor = '#ajax-spinner'; this.ajaxSpinnerSeletor = '#ajax-spinner';
this.ajaxExecuting = false; this.ajaxExecuting = false;
this.ajaxMenusOptions = [ this.ajaxMenusOptions = parameters.ajaxMenusOptions;
{
app: this,
interval: 5000,
menuSelector: '#main-menu',
url: apiTemplateMainMenuURL,
}
];
this.ajaxMenuHashes = {}; this.ajaxMenuHashes = {};
this.window = $(window); this.window = $(window);
} }
@@ -214,6 +209,8 @@ class MayanApp {
} }
initialize () { initialize () {
var self = this;
this.setupAJAXPeriodicWorkers(); this.setupAJAXPeriodicWorkers();
this.setupAJAXSpinner(); this.setupAJAXSpinner();
this.setupAutoSubmit(); this.setupAutoSubmit();
@@ -223,6 +220,7 @@ class MayanApp {
this.setupNavbarCollapse(); this.setupNavbarCollapse();
this.setupNewWindowAnchor(); this.setupNewWindowAnchor();
$.each(this.ajaxMenusOptions, function(index, value) { $.each(this.ajaxMenusOptions, function(index, value) {
value.app = self;
app.doRefreshAJAXMenu(value); app.doRefreshAJAXMenu(value);
}); });
partialNavigation.initialize(); partialNavigation.initialize();

View File

@@ -1 +1 @@
<i class="fa {{ css_classes }}"></i> <i class="fa {{ css_classes }}" style="padding-right: 5px; width: auto;"></i>

View File

@@ -1 +1 @@
<i class="fa fa-{{ symbol }}"></i> <i class="fa fa-{{ symbol }}" style="padding-right: 5px; width: auto;"></i>

View File

@@ -15,8 +15,8 @@
<a class="navbar-brand" href="{% url home_view %}">{% smart_setting 'COMMON_PROJECT_TITLE' %}</a> <a class="navbar-brand" href="{% url home_view %}">{% smart_setting 'COMMON_PROJECT_TITLE' %}</a>
</div> </div>
<div id="navbar" class="navbar-collapse collapse"> <div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav navbar-right">
{% get_menu_links 'main menu' as menu_links %} {% get_menu_links 'menu topbar' as menu_links %}
{% for link_set in menu_links %} {% for link_set in menu_links %}
{% for link in link_set %} {% for link in link_set %}
{% with 'true' as as_li %} {% with 'true' as as_li %}

View File

@@ -0,0 +1,70 @@
{% load i18n %}
{% load navigation_tags %}
{% load smart_settings_tags %}
{% load common_tags %}
{% load navigation_tags %}
<div class="panel-group" id="accordion-sidebar" role="tablist" aria-multiselectable="true">
{% get_menu_links 'main menu' as menu_links %}
{% for link_set in menu_links %}
{% for link in link_set %}
{% with 'true' as as_li %}
{% with 'true' as hide_active_anchor %}
{% with 'active' as li_class_active %}
{% with 'first' as li_class_first %}
{% with ' ' as link_classes %}
{% if link|get_type == "<class 'mayan.apps.navigation.classes.Menu'>" %}
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne">
<h4 class="panel-title">
<a class="non-ajax collapsed" role="button" data-toggle="collapse" data-parent="#accordion-sidebar" href="#accordion-body-{{ forloop.counter }}" aria-expanded="false" aria-controls="collapseOne">
<div class="pull-left">
{% if link.icon %}
<i class="hidden-xs hidden-sm hidden-md {{ link.icon }}"></i>
{% endif %}
{% if link.icon_class %}{{ link.icon_class.render }}{% endif %}
{{ link.label }}
</div>
<div class="accordion-indicator pull-right"><span class="caret"></span></div>
<div class="clearfix"></div>
</a>
</h4>
</div>
<div id="accordion-body-{{ forloop.counter }}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
<div class="panel-body">
<ul class="list-unstyled">
{% get_menu_links link.name as menu_links %}
{% for linkset in menu_links %}
{% with '' as li_class_active %}
{% with linkset as object_navigation_links %}
{% include 'navigation/generic_navigation.html' %}
{% endwith %}
{% endwith %}
{% endfor %}
</ul>
</div>
</div>
</div>
{% else %}
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne">
<h4 class="panel-title">
{% include 'navigation/generic_link_instance.html' %}
</h4>
</div>
</div>
{% endif %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endfor %}
{% endfor %}
</div>

View File

@@ -33,13 +33,18 @@
{% if appearance_type == 'plain' %} {% if appearance_type == 'plain' %}
{% block content_plain %}{% endblock %} {% block content_plain %}{% endblock %}
{% else %} {% else %}
<div id="main-menu"> <div id="menu-main">
{% include 'appearance/main_menu.html' %} {% include 'appearance/menu_main.html' %}
</div> </div>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="sidebar" id="menu-sidebar">
<div class="col-xs-12"> {% include 'appearance/menu_sidebar.html' %}
<div id="ajax-content"></div> </div>
<div class="main">
<div class="row">
<div class="col-xs-12">
<div id="ajax-content"></div>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -102,11 +107,26 @@
{# Transfer variable from Django to javascript #} {# Transfer variable from Django to javascript #}
var initialURL = '{% url home_view %}'; var initialURL = '{% url home_view %}';
var djangoDEBUG = {% if debug %}true{% else %}false{% endif %}; var djangoDEBUG = {% if debug %}true{% else %}false{% endif %};
var apiTemplateMainMenuURL = '{% url "rest_api:template-detail" "main_menu" %}'; var apiTemplateMainMenuURL = '{% url "rest_api:template-detail" "menu_main" %}';
</script> </script>
<script src="{% static 'appearance/js/base.js' %}" type="text/javascript"></script> <script src="{% static 'appearance/js/base.js' %}" type="text/javascript"></script>
<script> <script>
var app = new MayanApp(); var app = new MayanApp({
ajaxMenusOptions: [
{
interval: 5000,
menuSelector: '#menu-sidebar',
name: 'menu_main',
url: '{% url "rest_api:template-detail" "menu_sidebar" %}'
},
{
interval: 5000,
menuSelector: '#menu-main',
name: 'menu_sidebar',
url: '{% url "rest_api:template-detail" "menu_main" %}'
},
]
});
var afterBaseLoad = function () { var afterBaseLoad = function () {
MayanImage.intialize({ MayanImage.intialize({

View File

@@ -31,7 +31,9 @@ from .links import (
link_setup, link_tools, separator_user_label, text_user_label link_setup, link_tools, separator_user_label, text_user_label
) )
from .literals import DELETE_STALE_UPLOADS_INTERVAL, MESSAGE_SQLITE_WARNING from .literals import DELETE_STALE_UPLOADS_INTERVAL, MESSAGE_SQLITE_WARNING
from .menus import menu_about, menu_main, menu_secondary, menu_user from .menus import (
menu_about, menu_secondary, menu_topbar, menu_user
)
from .queues import * # NOQA - Force queues registration from .queues import * # NOQA - Force queues registration
from .settings import ( from .settings import (
setting_auto_logging, setting_production_error_log_path, setting_auto_logging, setting_production_error_log_path,
@@ -90,7 +92,10 @@ class CommonApp(MayanAppConfig):
warnings.warn(force_text(MESSAGE_SQLITE_WARNING)) warnings.warn(force_text(MESSAGE_SQLITE_WARNING))
Template( Template(
name='main_menu', template_name='appearance/main_menu.html' name='menu_main', template_name='appearance/menu_main.html'
)
Template(
name='menu_sidebar', template_name='appearance/menu_sidebar.html'
) )
app.conf.beat_schedule.update( app.conf.beat_schedule.update(
@@ -139,7 +144,7 @@ class CommonApp(MayanAppConfig):
) )
) )
menu_main.bind_links(links=(menu_about, menu_user,), position=99) menu_topbar.bind_links(links=(menu_about, menu_user,), position=99)
menu_secondary.bind_links( menu_secondary.bind_links(
links=(link_object_error_list_clear,), sources=( links=(link_object_error_list_clear,), sources=(
'common:object_error_list', 'common:object_error_list',

View File

@@ -9,7 +9,7 @@ from .icons import icon_menu_about, icon_menu_user
__all__ = ( __all__ = (
'menu_about', 'menu_facet', 'menu_list_facet', 'menu_main', 'menu_object', 'menu_about', 'menu_facet', 'menu_list_facet', 'menu_main', 'menu_object',
'menu_multi_item', 'menu_secondary', 'menu_setup', 'menu_sidebar', 'menu_multi_item', 'menu_secondary', 'menu_setup', 'menu_sidebar',
'menu_tools', 'menu_user' 'menu_tools', 'menu_topbar', 'menu_user'
) )
menu_about = Menu( menu_about = Menu(
@@ -24,6 +24,7 @@ menu_secondary = Menu(name='secondary menu')
menu_setup = Menu(name='setup menu') menu_setup = Menu(name='setup menu')
menu_sidebar = Menu(name='sidebar menu') menu_sidebar = Menu(name='sidebar menu')
menu_tools = Menu(name='tools menu') menu_tools = Menu(name='tools menu')
menu_topbar = Menu(name='menu topbar')
menu_user = Menu( menu_user = Menu(
icon_class=icon_menu_user, name='user menu', label=_('User') icon_class=icon_menu_user, name='user menu', label=_('User')
) )

View File

@@ -18,7 +18,7 @@ class CommonAPITestCase(BaseAPITestCase):
@override_settings(LANGUAGE_CODE='de') @override_settings(LANGUAGE_CODE='de')
def test_template_detail_view(self): def test_template_detail_view(self):
self.login_user() self.login_user()
template_main_menu = Template.get(name='main_menu') template_main_menu = Template.get(name='menu_main')
response = self.client.get(template_main_menu.get_absolute_url()) response = self.client.get(template_main_menu.get_absolute_url())
self.assertContains( self.assertContains(
@@ -26,7 +26,7 @@ class CommonAPITestCase(BaseAPITestCase):
) )
def test_template_detail_anonymous_view(self): def test_template_detail_anonymous_view(self):
template_main_menu = Template.get(name='main_menu') template_main_menu = Template.get(name='menu_main')
response = self.client.get(template_main_menu.get_absolute_url()) response = self.client.get(template_main_menu.get_absolute_url())
self.assertNotContains( self.assertNotContains(
response=response, text=TEST_TEMPLATE_RESULT, status_code=403 response=response, text=TEST_TEMPLATE_RESULT, status_code=403

View File

@@ -5,8 +5,8 @@ from django.contrib.auth import get_user_model
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from mayan.apps.common import ( from mayan.apps.common import (
MayanAppConfig, menu_list_facet, menu_main, menu_object, menu_secondary, MayanAppConfig, menu_list_facet, menu_object, menu_secondary,
menu_tools, menu_user menu_tools, menu_topbar, menu_user
) )
from mayan.apps.common.widgets import TwoStateWidget from mayan.apps.common.widgets import TwoStateWidget
from mayan.apps.navigation import SourceColumn from mayan.apps.navigation import SourceColumn
@@ -86,9 +86,6 @@ class EventsApp(MayanAppConfig):
menu_list_facet.bind_links( menu_list_facet.bind_links(
links=(link_user_events,), sources=(User,) links=(link_user_events,), sources=(User,)
) )
menu_main.bind_links(
links=(link_user_notifications_list,), position=99
)
menu_object.bind_links( menu_object.bind_links(
links=(link_notification_mark_read,), sources=(Notification,) links=(link_notification_mark_read,), sources=(Notification,)
) )
@@ -97,6 +94,9 @@ class EventsApp(MayanAppConfig):
sources=('events:user_notifications_list',) sources=('events:user_notifications_list',)
) )
menu_tools.bind_links(links=(link_events_list,)) menu_tools.bind_links(links=(link_events_list,))
menu_topbar.bind_links(
links=(link_user_notifications_list,), position=1
)
menu_user.bind_links( menu_user.bind_links(
links=( links=(
link_event_types_subscriptions_list, link_current_user_events link_event_types_subscriptions_list, link_current_user_events