Backport new menu, new sidebar and CSS changes

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2019-04-21 23:50:35 -04:00
parent d410e1ef6c
commit 1e37ca8315
31 changed files with 550 additions and 165 deletions

View File

@@ -96,6 +96,9 @@
manager. manager.
* Remove the MIMETYPE_FILE_READ_SIZE setting. * Remove the MIMETYPE_FILE_READ_SIZE setting.
* Use copyfileobj in the document parsers. * Use copyfileobj in the document parsers.
* Backport list facet menu code.
* Backport sidebar code.
* CSS updates to maximize usable width.
3.1.11 (2019-04-XX) 3.1.11 (2019-04-XX)
=================== ===================

View File

@@ -128,6 +128,9 @@ Other changes
manager. manager.
* Remove the MIMETYPE_FILE_READ_SIZE setting. * Remove the MIMETYPE_FILE_READ_SIZE setting.
* Use copyfileobj in the document parsers. * Use copyfileobj in the document parsers.
* Backport list facet menu code.
* Backport sidebar code.
* CSS updates to maximize usable width.
Removals Removals
-------- --------

View File

@@ -334,3 +334,70 @@ a i {
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
/*
* Main content
*/
.main {
}
/* Remove scroll bar caused by bootstraps -15px on .row margins */
.no-gutters {
margin-right: 0;
margin-left: 0;
> .col,
> [class*="col-"] {
padding-right: 0;
padding-left: 0;
}
}
@media (min-width: 768px) {
.main {
padding-right: 0px;
padding-left: 0px;
/*margin-left: 210px;*/
}
}
/* Side bar */
#menu-actions {
position: fixed;
right: 5px;
top: 65px;
z-index: 1020;
}
#viewport {
width: 100%;
}
.has-sidebar {
padding-right: 0px;
}
#sidebar {
display: none;
}
@media (min-width: 768px) {
#sidebar {
bottom: 0;
display: block;
overflow-x: visible;
overflow-y: auto;
padding-top: 10px;
position: fixed;
right: 0;
top: 100px;
width: 150px;
z-index: 1000;
}
.has-sidebar {
padding-right: 130px;
}
}

View File

@@ -22,7 +22,7 @@
{% if appearance_type == 'plain' %} {% if appearance_type == 'plain' %}
{% block content_plain %}{% endblock %} {% block content_plain %}{% endblock %}
{% else %} {% else %}
<div class="container-fluid"> <div class="">
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
{% check_sqlite as check_sqlite %} {% check_sqlite as check_sqlite %}
@@ -37,6 +37,86 @@
</div> </div>
</div> </div>
{% navigation_resolve_menus names='facet,list facet' sort_results=True as facet_menus_link_results %}
<div class="row">
<div class="col-xs-12 {% if facet_menus_link_results %}has-sidebar{% endif %}" id="viewport">
{% include 'appearance/calculate_form_title.html' %}
{# action menu #}
{% navigation_resolve_menus names='object,secondary' sort_results=True as action_menus_link_results %}
{% if action_menus_link_results %}
<div class="pull-right btn-group" id="menu-actions">
<button aria-expanded="true" class="btn btn-danger btn-sm dropdown-toggle" data-toggle="dropdown" type="button">
{% trans 'Actions' %}
<span class="caret"></span>
<span class="sr-only">{% trans 'Toggle Dropdown' %}</span>
</button>
<ul class="dropdown-menu" role="menu">
{% for menus_link_result in action_menus_link_results %}
{% if action_menus_link_results|length > 1 %}
<li class="dropdown-header">{{ menus_link_result.menu.label }}</li>
{% endif %}
{% for link_group in menus_link_result.link_groups %}
{% if navigation_object_list %}
{% ifchanged link_group.object %}
<li class="dropdown-header">{% common_get_object_verbose_name obj=link_group.object %}</li>
{% endifchanged %}
{% endif %}
{% with link_group.links as object_navigation_links %}
{% with 'true' as as_li %}
{% with 'true' as hide_active_anchor %}
{% with 'btn-sm' as link_classes %}
{% include 'navigation/generic_navigation.html' %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endwith %}
{% if not forloop.last and link_group %}
<li class="divider"></li>
{% endif %}
{% endfor %}
{% if not forloop.last and menus_link_result %}
<li class="divider"></li>
{% endif %}
{% endfor %}
</ul>
</div>
<div class="clearfix"></div>
{% endif %}
{% block content %}{% endblock %}
{% block footer %}{% endblock %}
</div>
{% if facet_menus_link_results %}
<div id="sidebar">
<div class="pull-right list-group">
{% for menu_link_result in facet_menus_link_results %}
{% for link_group in menu_link_result.link_groups %}
{% with link_group.links as object_navigation_links %}
{% with 'true' as hide_active_anchor %}
{% with 'active' as link_class_active %}
{% with 'list-group-item btn-sm' as link_classes %}
{% include 'navigation/generic_navigation.html' %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endfor %}
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% comment %}
{% get_menus_links names='object,sidebar,secondary' sort_results=True as links %} {% get_menus_links names='object,sidebar,secondary' sort_results=True as links %}
{% get_menu_links name='facet' sort_results=True as form_navigation_links %} {% get_menu_links name='facet' sort_results=True as form_navigation_links %}
@@ -97,6 +177,8 @@
</div> </div>
{% endif %} {% endif %}
</div> </div>
{% endcomment %}
</div> </div>
{% endif %} {% endif %}

View File

@@ -11,10 +11,12 @@
<div class="well center-block"> <div class="well center-block">
<div class="row"> <div class="row">
{% with 'navigation/large_button_link.html' as link_template %} {% with 'navigation/large_button_link.html' as link_template %}
{% for object_navigation_links in resolved_links %} {% for menu_results in resolved_links %}
{% with menu_results.links as object_navigation_links %}
{% include 'navigation/generic_navigation.html' %} {% include 'navigation/generic_navigation.html' %}
{% endwith %}
{% empty %} {% empty %}
<p class="text-center" colspan=99> <p class="text-center">
{% include 'appearance/no_results.html' %} {% include 'appearance/no_results.html' %}
</p> </p>
{% endfor %} {% endfor %}

View File

@@ -87,14 +87,40 @@
{% endfor %} {% endfor %}
{% if not hide_links %} {% if not hide_links %}
<p class="text-center">
{% get_menu_links name='object' source=object as resolved_links %} {% navigation_resolve_menus names='list facet,object' source=object as facet_menus_link_results %}
{% for object_navigation_links in resolved_links %}
{% with 'true' as as_dropdown %} {% if facet_menus_link_results %}
<div class="dropdown text-center">
<button aria-expanded="false" aria-haspopup="true" class="btn btn-default btn-danger btn-sm dropdown-toggle" data-toggle="dropdown">
{% trans 'Actions' %}
<span class="caret"></span>
<span class="sr-only">{% trans 'Toggle Dropdown' %}</span>
</button>
<ul class="dropdown-menu" role="menu">
{% for facet_menu_link_result in facet_menus_link_results %}
{% for link_group in facet_menu_link_result.link_groups %}
{% with link_group.links as object_navigation_links %}
{% with 'true' as as_li %}
{% with 'true' as hide_active_anchor %}
{% with 'btn-sm' as link_classes %}
{% include 'navigation/generic_navigation.html' %} {% include 'navigation/generic_navigation.html' %}
{% endwith %} {% endwith %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endfor %} {% endfor %}
</p>
{% if not forloop.last and facet_menu_link_result %}
<li class="divider"></li>
{% endif %}
{% endfor %}
</ul>
</div>
{% endif %}
{% endif %} {% endif %}
</div> </div>

View File

@@ -96,13 +96,29 @@
{% endfor %} {% endfor %}
{% if not hide_links %} {% if not hide_links %}
<td class="last"> <td class="last">
{% get_menu_links 'object' source=object as resolved_links %} {% navigation_resolve_menu name='list facet' sort_results=True source=object as facet_menus_results %}
{% for object_navigation_links in resolved_links %} {% for facet_menu_results in facet_menus_results %}
{% for link_group in facet_menu_results.link_groups %}
{% with link_group.links as object_navigation_links %}
{% with 'true' as horizontal %} {% with 'true' as horizontal %}
{% with 'true' as hide_icon %} {% with 'true' as hide_icon %}
{% include 'navigation/generic_navigation.html' %} {% include 'navigation/generic_navigation.html' %}
{% endwith %} {% endwith %}
{% endwith %} {% endwith %}
{% endwith %}
{% endfor %}
{% endfor %}
{% navigation_resolve_menu name='object' source=object as object_menus_results %}
{% for object_menu_results in object_menus_results %}
{% for link_group in object_menu_results.link_groups %}
{% with link_group.links as object_navigation_links %}
{% with 'true' as horizontal %}
{% with 'true' as hide_icon %}
{% include 'navigation/generic_navigation.html' %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endfor %}
{% endfor %} {% endfor %}
</td> </td>
{% endif %} {% endif %}

View File

@@ -16,6 +16,25 @@
</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">
{% navigation_resolve_menu name='main' as topbar_menus_results %}
{% for tobpar_menu_result in topbar_menus_results %}
{% for link_group in tobpar_menu_result.link_groups %}
{% for link in link_group.links %}
{% 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 %}
{% include 'navigation/generic_subnavigation.html' %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endfor %}
{% endfor %}
{% endfor %}
{% get_menu_links name='main' as menu_links %} {% get_menu_links name='main' 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 %}

View File

@@ -36,8 +36,8 @@
<div id="menu-main"> <div id="menu-main">
{% include 'appearance/main_menu.html' %} {% include 'appearance/main_menu.html' %}
</div> </div>
<div class="container-fluid"> <div class="main">
<div class="row"> <div class="row no-gutters">
<div class="col-xs-12"> <div class="col-xs-12">
<div id="ajax-content"></div> <div id="ajax-content"></div>
</div> </div>

View File

@@ -7,7 +7,8 @@ from mayan.apps.acls.classes import ModelPermission
from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_facet, menu_main, menu_multi_item, menu_object, menu_sidebar menu_facet, menu_list_facet, menu_main, menu_multi_item, menu_object,
menu_sidebar
) )
from mayan.apps.documents.search import document_page_search, document_search from mayan.apps.documents.search import document_page_search, document_search
from mayan.apps.navigation import SourceColumn from mayan.apps.navigation import SourceColumn
@@ -99,6 +100,10 @@ class CabinetsApp(MayanAppConfig):
link_cabinet_list, link_cabinet_create link_cabinet_list, link_cabinet_create
) )
) )
menu_list_facet.bind_links(
links=(link_cabinet_view, link_custom_acl_list),
sources=(Cabinet,)
)
menu_main.bind_links(links=(menu_cabinets,), position=98) menu_main.bind_links(links=(menu_cabinets,), position=98)
@@ -115,9 +120,7 @@ class CabinetsApp(MayanAppConfig):
) )
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_cabinet_view, link_cabinet_edit, link_cabinet_delete, link_cabinet_edit, link_cabinet_child_add
link_custom_acl_list, link_cabinet_child_add,
link_cabinet_delete
), sources=(Cabinet,) ), sources=(Cabinet,)
) )
menu_sidebar.bind_links( menu_sidebar.bind_links(

View File

@@ -15,6 +15,7 @@ menu_about = Menu(
icon_class=icon_menu_about, label=_('System'), name='about' icon_class=icon_menu_about, label=_('System'), name='about'
) )
menu_facet = Menu(label=_('Facet'), name='facet') menu_facet = Menu(label=_('Facet'), name='facet')
menu_list_facet = Menu(label=_('Facet'), name='list facet')
menu_main = Menu(name='main') menu_main = Menu(name='main')
menu_multi_item = Menu(name='multi item') menu_multi_item = Menu(name='multi item')
menu_object = Menu(label=_('Actions'), name='object') menu_object = Menu(label=_('Actions'), name='object')

View File

@@ -21,6 +21,14 @@ def check_sqlite():
return MESSAGE_SQLITE_WARNING return MESSAGE_SQLITE_WARNING
@register.simple_tag
def common_get_object_verbose_name(obj):
try:
return obj._meta.verbose_name
except AttributeError:
return type(obj)
@register.simple_tag @register.simple_tag
def get_collections(): def get_collections():
return Collection.get_all() return Collection.get_all()

View File

@@ -11,7 +11,8 @@ from mayan.apps.acls.links import link_acl_list
from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_facet, menu_main, menu_object, menu_secondary, menu_setup, menu_tools menu_facet, menu_list_facet, menu_main, menu_object, menu_secondary,
menu_setup, menu_tools
) )
from mayan.apps.common.widgets import TwoStateWidget from mayan.apps.common.widgets import TwoStateWidget
from mayan.apps.documents.signals import post_document_created, post_initial_document_type from mayan.apps.documents.signals import post_document_created, post_initial_document_type
@@ -183,11 +184,15 @@ class DocumentIndexingApp(MayanAppConfig):
menu_facet.bind_links( menu_facet.bind_links(
links=(link_document_index_list,), sources=(Document,) links=(link_document_index_list,), sources=(Document,)
) )
menu_list_facet.bind_links(
links=(
link_acl_list, link_index_setup_document_types,
link_index_setup_view,
), sources=(Index,)
)
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_index_setup_edit, link_index_setup_view, link_index_setup_delete, link_index_setup_edit,
link_index_setup_document_types, link_acl_list,
link_index_setup_delete
), sources=(Index,) ), sources=(Index,)
) )
menu_object.bind_links( menu_object.bind_links(

View File

@@ -12,7 +12,8 @@ from mayan.apps.acls.classes import ModelPermission
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.classes import ModelField from mayan.apps.common.classes import ModelField
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_facet, menu_multi_item, menu_object, menu_secondary, menu_tools menu_facet, menu_list_facet, menu_multi_item, menu_object, menu_secondary,
menu_tools
) )
from mayan.apps.documents.search import document_search, document_page_search from mayan.apps.documents.search import document_search, document_page_search
from mayan.apps.documents.signals import post_version_upload from mayan.apps.documents.signals import post_version_upload
@@ -145,16 +146,16 @@ class DocumentParsingApp(MayanAppConfig):
menu_facet.bind_links( menu_facet.bind_links(
links=(link_document_page_content,), sources=(DocumentPage,) links=(link_document_page_content,), sources=(DocumentPage,)
) )
menu_list_facet.bind_links(
links=(link_document_type_parsing_settings,),
sources=(DocumentType,)
)
menu_multi_item.bind_links( menu_multi_item.bind_links(
links=(link_document_submit_multiple,), sources=(Document,) links=(link_document_submit_multiple,), sources=(Document,)
) )
menu_object.bind_links( menu_object.bind_links(
links=(link_document_submit,), sources=(Document,) links=(link_document_submit,), sources=(Document,)
) )
menu_object.bind_links(
links=(link_document_type_parsing_settings,), sources=(DocumentType,),
position=99
)
menu_secondary.bind_links( menu_secondary.bind_links(
links=( links=(
link_document_content, link_document_parsing_errors_list, link_document_content, link_document_parsing_errors_list,

View File

@@ -12,8 +12,8 @@ from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.classes import ModelAttribute from mayan.apps.common.classes import ModelAttribute
from mayan.apps.common.links import link_object_error_list from mayan.apps.common.links import link_object_error_list
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_facet, menu_main, menu_object, menu_secondary, menu_setup, menu_facet, menu_list_facet, menu_main, menu_object, menu_secondary,
menu_sidebar, menu_tools menu_setup, menu_sidebar, menu_tools
) )
from mayan.apps.common.permissions_runtime import permission_error_log_view from mayan.apps.common.permissions_runtime import permission_error_log_view
from mayan.apps.common.widgets import TwoStateWidget from mayan.apps.common.widgets import TwoStateWidget
@@ -262,13 +262,17 @@ class DocumentStatesApp(MayanAppConfig):
menu_facet.bind_links( menu_facet.bind_links(
links=(link_document_workflow_instance_list,), sources=(Document,) links=(link_document_workflow_instance_list,), sources=(Document,)
) )
menu_list_facet.bind_links(
links=(
link_setup_workflow_document_types,
link_setup_workflow_states, link_setup_workflow_transitions,
link_workflow_preview, link_acl_list
), sources=(Workflow,)
)
menu_main.bind_links(links=(link_workflow_list,), position=10) menu_main.bind_links(links=(link_workflow_list,), position=10)
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_setup_workflow_states, link_setup_workflow_transitions, link_setup_workflow_delete, link_setup_workflow_edit
link_setup_workflow_document_types, link_setup_workflow_edit,
link_acl_list, link_workflow_preview,
link_setup_workflow_delete
), sources=(Workflow,) ), sources=(Workflow,)
) )
menu_object.bind_links( menu_object.bind_links(
@@ -291,12 +295,14 @@ class DocumentStatesApp(MayanAppConfig):
link_workflow_instance_transition link_workflow_instance_transition
), sources=(WorkflowInstance,) ), sources=(WorkflowInstance,)
) )
menu_object.bind_links(
menu_list_facet.bind_links(
links=( links=(
link_workflow_document_list, link_workflow_state_list, link_workflow_document_list,
link_workflow_state_list,
), sources=(WorkflowRuntimeProxy,) ), sources=(WorkflowRuntimeProxy,)
) )
menu_object.bind_links( menu_list_facet.bind_links(
links=( links=(
link_workflow_state_document_list, link_workflow_state_document_list,
), sources=(WorkflowStateRuntimeProxy,) ), sources=(WorkflowStateRuntimeProxy,)

View File

@@ -13,8 +13,8 @@ from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.classes import MissingItem, ModelField, Template from mayan.apps.common.classes import MissingItem, ModelField, Template
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_facet, menu_main, menu_object, menu_secondary, menu_setup, menu_facet, menu_list_facet, menu_main, menu_object, menu_secondary,
menu_sidebar, menu_multi_item, menu_tools menu_setup, menu_sidebar, menu_multi_item, menu_tools
) )
from mayan.apps.common.signals import post_initial_setup from mayan.apps.common.signals import post_initial_setup
from mayan.apps.common.widgets import TwoStateWidget from mayan.apps.common.widgets import TwoStateWidget
@@ -459,12 +459,17 @@ class DocumentsApp(MayanAppConfig):
) )
# Document type links # Document type links
menu_list_facet.bind_links(
links=(
link_document_type_filename_list,
link_acl_list, link_object_event_types_user_subcriptions_list,
link_events_for_object,
), sources=(DocumentType,)
)
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_document_type_edit, link_document_type_filename_list, link_document_type_delete, link_document_type_edit
link_acl_list, link_object_event_types_user_subcriptions_list,
link_document_type_delete,
link_events_for_object,
), sources=(DocumentType,) ), sources=(DocumentType,)
) )
menu_object.bind_links( menu_object.bind_links(
@@ -572,10 +577,10 @@ class DocumentsApp(MayanAppConfig):
link_document_page_navigation_first, link_document_page_navigation_first,
link_document_page_navigation_previous, link_document_page_navigation_previous,
link_document_page_navigation_next, link_document_page_navigation_next,
link_document_page_navigation_last, link_transformation_list link_document_page_navigation_last
), sources=(DocumentPage,) ), sources=(DocumentPage,)
) )
menu_object.bind_links( menu_list_facet.bind_links(
links=(link_transformation_list,), sources=(DocumentPage,) links=(link_transformation_list,), sources=(DocumentPage,)
) )

View File

@@ -8,7 +8,8 @@ from mayan.apps.acls.links import link_acl_list
from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_facet, menu_object, menu_secondary, menu_setup, menu_sidebar menu_facet, menu_list_facet, menu_object, menu_secondary, menu_setup,
menu_sidebar
) )
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
@@ -83,6 +84,12 @@ class LinkingApp(MayanAppConfig):
links=(link_smart_link_instances_for_document,), links=(link_smart_link_instances_for_document,),
sources=(Document,) sources=(Document,)
) )
menu_list_facet.bind_links(
links=(
link_acl_list, link_smart_link_document_types,
link_smart_link_condition_list,
), sources=(SmartLink,)
)
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_smart_link_condition_edit, link_smart_link_condition_edit,
@@ -91,9 +98,7 @@ class LinkingApp(MayanAppConfig):
) )
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_smart_link_edit, link_smart_link_document_types, link_smart_link_delete, link_smart_link_edit
link_smart_link_condition_list, link_acl_list,
link_smart_link_delete
), sources=(SmartLink,) ), sources=(SmartLink,)
) )
menu_object.bind_links( menu_object.bind_links(

View File

@@ -10,7 +10,8 @@ from mayan.apps.acls.links import link_acl_list
from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_object, menu_multi_item, menu_secondary, menu_setup, menu_tools menu_list_facet, menu_multi_item, menu_object, menu_secondary, menu_setup,
menu_tools
) )
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
@@ -102,6 +103,12 @@ class MailerApp(MayanAppConfig):
} }
) )
menu_list_facet.bind_links(
links=(
link_acl_list, link_user_mailer_log_list
), sources=(UserMailer,)
)
menu_multi_item.bind_links( menu_multi_item.bind_links(
links=( links=(
link_send_multiple_document, link_send_multiple_document_link link_send_multiple_document, link_send_multiple_document_link
@@ -116,8 +123,8 @@ class MailerApp(MayanAppConfig):
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_user_mailer_edit, link_user_mailer_log_list, link_user_mailer_delete, link_user_mailer_edit,
link_user_mailer_test, link_acl_list, link_user_mailer_delete, link_user_mailer_test
), sources=(UserMailer,) ), sources=(UserMailer,)
) )

View File

@@ -14,8 +14,8 @@ from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.classes import ModelAttribute, ModelField from mayan.apps.common.classes import ModelAttribute, ModelField
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_facet, menu_multi_item, menu_object, menu_secondary, menu_setup, menu_facet, menu_list_facet, menu_multi_item, menu_object, menu_secondary,
menu_sidebar menu_setup, menu_sidebar
) )
from mayan.apps.common.widgets import TwoStateWidget from mayan.apps.common.widgets import TwoStateWidget
from mayan.apps.documents.search import document_page_search, document_search from mayan.apps.documents.search import document_page_search, document_search
@@ -204,23 +204,27 @@ class MetadataApp(MayanAppConfig):
) )
menu_facet.bind_links(links=(link_metadata_view,), sources=(Document,)) menu_facet.bind_links(links=(link_metadata_view,), sources=(Document,))
menu_list_facet.bind_links(
links=(link_setup_document_type_metadata_types,), sources=(
DocumentType,
)
)
menu_multi_item.bind_links( menu_multi_item.bind_links(
links=( links=(
link_metadata_multiple_add, link_metadata_multiple_edit, link_metadata_multiple_add, link_metadata_multiple_edit,
link_metadata_multiple_remove link_metadata_multiple_remove
), sources=(Document,) ), sources=(Document,)
) )
menu_object.bind_links( menu_list_facet.bind_links(
links=( links=(
link_setup_document_type_metadata_types, link_acl_list, link_setup_metadata_type_document_types,
), sources=(DocumentType,) link_object_event_types_user_subcriptions_list,
link_events_for_object,
), sources=(MetadataType,)
) )
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_setup_metadata_type_edit, link_setup_metadata_type_delete, link_setup_metadata_type_edit
link_setup_metadata_type_document_types, link_acl_list,
link_object_event_types_user_subcriptions_list,
link_events_for_object, link_setup_metadata_type_delete,
), sources=(MetadataType,) ), sources=(MetadataType,)
) )
menu_secondary.bind_links( menu_secondary.bind_links(

View File

@@ -8,7 +8,9 @@ from mayan.apps.acls.classes import ModelPermission
from mayan.apps.acls.links import link_acl_list from mayan.apps.acls.links import link_acl_list
from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.menus import menu_object, menu_secondary, menu_setup from mayan.apps.common.menus import (
menu_list_facet, menu_object, menu_secondary, menu_setup
)
from mayan.apps.navigation import SourceColumn from mayan.apps.navigation import SourceColumn
from .links import ( from .links import (
@@ -54,9 +56,14 @@ class MOTDApp(MayanAppConfig):
func=lambda context: context['object'].end_datetime or _('None') func=lambda context: context['object'].end_datetime or _('None')
) )
menu_list_facet.bind_links(
links=(
link_acl_list,
), sources=(Message,)
)
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_message_edit, link_acl_list, link_message_delete link_message_delete, link_message_edit
), sources=(Message,) ), sources=(Message,)
) )
menu_secondary.bind_links( menu_secondary.bind_links(

View File

@@ -6,33 +6,37 @@ import logging
from furl import furl from furl import furl
from django.apps import apps from django.apps import apps
from django.conf import settings
from django.contrib.admin.utils import label_for_field from django.contrib.admin.utils import label_for_field
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.shortcuts import resolve_url
from django.template import VariableDoesNotExist, Variable from django.template import VariableDoesNotExist, Variable
from django.template.defaulttags import URLNode from django.template.defaulttags import URLNode
from django.urls import Resolver404, resolve from django.urls import resolve, reverse
from django.utils.encoding import force_str, force_text from django.utils.encoding import force_str, force_text
from mayan.apps.common.settings import setting_home_view
from mayan.apps.common.utils import return_attrib from mayan.apps.common.utils import return_attrib
from mayan.apps.permissions import Permission from mayan.apps.permissions import Permission
from .utils import get_current_view_name
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ResolvedLink(object): class ResolvedLink(object):
def __init__(self, link, current_view): def __init__(self, link, current_view_name):
self.current_view = current_view self.context = None
self.current_view_name = current_view_name
self.disabled = False self.disabled = False
self.link = link self.link = link
self.url = '#'
self.context = None
self.request = None self.request = None
self.url = '#'
def __repr__(self):
return '<ResolvedLink: {}>'.format(self.url)
@property @property
def active(self): def active(self):
return self.link.view == self.current_view return self.link.view == self.current_view_name
@property @property
def badge_text(self): def badge_text(self):
@@ -97,12 +101,15 @@ class Menu(object):
self.__class__._registry[name] = self self.__class__._registry[name] = self
self.non_sorted_sources = non_sorted_sources or [] self.non_sorted_sources = non_sorted_sources or []
def __repr__(self):
return '<Menu: {}>'.format(self.name)
def _map_links_to_source(self, links, source, map_variable='bound_links', position=None): def _map_links_to_source(self, links, source, map_variable='bound_links', position=None):
source_links = getattr(self, map_variable).setdefault(source, []) source_links = getattr(self, map_variable).setdefault(source, [])
for link in links: for link in links:
source_links.append(link) source_links.append(link)
self.link_positions[link] = position self.link_positions[link] = position or 0
def add_unsorted_source(self, source): def add_unsorted_source(self, source):
self.non_sorted_sources.append(source) self.non_sorted_sources.append(source)
@@ -159,6 +166,24 @@ class Menu(object):
) )
return resolved_navigation_object_list return resolved_navigation_object_list
def get_result_position(self, item):
"""
Method to help sort results by position.
"""
if isinstance(item, ResolvedLink):
return self.link_positions.get(item.link, 0)
else:
return self.link_positions.get(item, 0) or 0
def get_result_label(self, item):
"""
Method to help sort results by label.
"""
if isinstance(item, ResolvedLink):
return item.link.text
else:
return item.label
def resolve(self, context, source=None, sort_results=False): def resolve(self, context, source=None, sort_results=False):
if not self.check_condition(context=context): if not self.check_condition(context=context):
return [] return []
@@ -178,15 +203,8 @@ class Menu(object):
logger.warning('No request variable, aborting menu resolution') logger.warning('No request variable, aborting menu resolution')
return () return ()
current_path = request.META['PATH_INFO'] current_view_name = get_current_view_name(request=request)
if not current_view_name:
# Get sources: view name, view objects
try:
current_view = resolve(current_path).view_name
except Resolver404:
# Can't figure out which view corresponds to this URL.
# Most likely it is an invalid URL.
logger.warning('Can\'t figure out which view corresponds to this URL: %s; aborting menu resolution.', current_path)
return () return ()
resolved_navigation_object_list = self.get_resolved_navigation_object_list( resolved_navigation_object_list = self.get_resolved_navigation_object_list(
@@ -227,18 +245,28 @@ class Menu(object):
pass pass
if resolved_links: if resolved_links:
result.append(resolved_links) result.append(
{
'object': resolved_navigation_object,
'links': resolved_links
}
)
resolved_links = [] resolved_links = []
# View links # View links
for link in self.bound_links.get(current_view, []): for link in self.bound_links.get(current_view_name, []):
resolved_link = link.resolve(context=context) resolved_link = link.resolve(context=context)
if resolved_link: if resolved_link:
if resolved_link.link not in self.unbound_links.get(current_view, ()): if resolved_link.link not in self.unbound_links.get(current_view_name, ()):
resolved_links.append(resolved_link) resolved_links.append(resolved_link)
if resolved_links: if resolved_links:
result.append(resolved_links) result.append(
{
'object': current_view_name,
'links': resolved_links
}
)
resolved_links = [] resolved_links = []
@@ -256,7 +284,12 @@ class Menu(object):
resolved_links.append(resolved_link) resolved_links.append(resolved_link)
if resolved_links: if resolved_links:
result.append(resolved_links) result.append(
{
'object': None,
'links': resolved_links
}
)
if result: if result:
unsorted_source = False unsorted_source = False
@@ -267,15 +300,14 @@ class Menu(object):
break break
if sort_results and not unsorted_source: if sort_results and not unsorted_source:
result[0] = sorted( for link_group in result:
result[0], key=lambda item: ( link_group['links'] = sorted(
item.link.text if isinstance(item, ResolvedLink) else item.label link_group['links'], key=self.get_result_label
)
) )
else: else:
# Sort links by position value passed during bind for link_group in result:
result[0] = sorted( link_group['links'] = sorted(
result[0], key=lambda item: (self.link_positions.get(item.link) or 0) if isinstance(item, ResolvedLink) else (self.link_positions.get(item) or 0) link_group['links'], key=self.get_result_position
) )
return result return result
@@ -308,7 +340,7 @@ class Link(object):
def remove(cls, name): def remove(cls, name):
del cls._registry[name] del cls._registry[name]
def __init__(self, badge_text=None, text=None, view=None, args=None, condition=None, def __init__(self, text=None, view=None, args=None, badge_text=None, condition=None,
conditional_disable=None, description=None, html_data=None, conditional_disable=None, description=None, html_data=None,
html_extra_classes=None, icon=None, icon_class=None, html_extra_classes=None, icon=None, icon_class=None,
keep_query=False, kwargs=None, name=None, permissions=None, keep_query=False, kwargs=None, name=None, permissions=None,
@@ -351,7 +383,7 @@ class Link(object):
request = Variable('request').resolve(context) request = Variable('request').resolve(context)
current_path = request.META['PATH_INFO'] current_path = request.META['PATH_INFO']
current_view = resolve(current_path).view_name current_view_name = resolve(current_path).view_name
# ACL is tested agains the resolved_object or just {{ object }} if not # ACL is tested agains the resolved_object or just {{ object }} if not
if not resolved_object: if not resolved_object:
@@ -386,7 +418,9 @@ class Link(object):
if not self.condition(context): if not self.condition(context):
return None return None
resolved_link = ResolvedLink(current_view=current_view, link=self) resolved_link = ResolvedLink(
current_view_name=current_view_name, link=self
)
if self.view: if self.view:
view_name = Variable('"{}"'.format(self.view)) view_name = Variable('"{}"'.format(self.view))
@@ -419,7 +453,7 @@ class Link(object):
try: try:
resolved_link.url = node.render(context) resolved_link.url = node.render(context)
except Exception as exception: except Exception as exception:
logger.debug( logger.error(
'Error resolving link "%s" URL; %s', self.text, exception 'Error resolving link "%s" URL; %s', self.text, exception
) )
elif self.url: elif self.url:
@@ -437,7 +471,7 @@ class Link(object):
parsed_url = furl( parsed_url = furl(
force_str( force_str(
request.get_full_path() or request.META.get( request.get_full_path() or request.META.get(
'HTTP_REFERER', resolve_url(settings.LOGIN_REDIRECT_URL) 'HTTP_REFERER', reverse(setting_home_view.value)
) )
) )
) )
@@ -467,7 +501,7 @@ class Separator(Link):
self.view = None self.view = None
def resolve(self, *args, **kwargs): def resolve(self, *args, **kwargs):
result = ResolvedLink(current_view=None, link=self) result = ResolvedLink(current_view_name=None, link=self)
result.separator = True result.separator = True
return result return result
@@ -543,7 +577,7 @@ class Text(Link):
self.view = None self.view = None
def resolve(self, *args, **kwargs): def resolve(self, *args, **kwargs):
result = ResolvedLink(current_view=None, link=self) result = ResolvedLink(current_view_name=None, link=self)
result.context = kwargs.get('context') result.context = kwargs.get('context')
result.text_span = True result.text_span = True
return result return result

View File

@@ -1,5 +1,6 @@
{% load i18n %} {% load i18n %}
{% spaceless %}
{% if as_dropdown %} {% if as_dropdown %}
<div class="dropdown text-center"> <div class="dropdown text-center">
<button class="btn btn-default dropdown-toggle btn-danger btn-sm" type="button" id="dropdownMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <button class="btn btn-default dropdown-toggle btn-danger btn-sm" type="button" id="dropdownMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@@ -23,3 +24,4 @@
{% include 'navigation/generic_subnavigation.html' %} {% include 'navigation/generic_subnavigation.html' %}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% endspaceless %}

View File

@@ -12,14 +12,16 @@
<span class="caret"></span> <span class="caret"></span>
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{% get_menu_links link.name as menu_links %} {% navigation_resolve_menu name=link.name as sub_menus_results %}
{% for linkset in menu_links %} {% for sub_menu_results in sub_menus_results %}
{% for link_group in sub_menu_results.link_groups %}
{% with '' as li_class_active %} {% with '' as li_class_active %}
{% with linkset as object_navigation_links %} {% with link_group.links as object_navigation_links %}
{% include 'navigation/generic_navigation.html' %} {% include 'navigation/generic_navigation.html' %}
{% endwith %} {% endwith %}
{% endwith %} {% endwith %}
{% endfor %} {% endfor %}
{% endfor %}
</ul> </ul>
</li> </li>
{% else %} {% else %}

View File

@@ -39,7 +39,8 @@ def get_menus_links(context, names, source=None, sort_results=None):
def get_multi_item_links_form(context, object_list): def get_multi_item_links_form(context, object_list):
actions = [] actions = []
for link_set in Menu.get('multi item').resolve(context=context, source=object_list[0], sort_results=True): for link_set in Menu.get('multi item').resolve(context=context, source=object_list[0], sort_results=True):
for link in link_set: for link in link_set['links']:
if hasattr(link, 'url'):
actions.append((link.url, link.text)) actions.append((link.url, link.text))
form = MultiItemForm(actions=actions) form = MultiItemForm(actions=actions)
@@ -70,6 +71,35 @@ def get_source_columns(source):
return SourceColumn.get_for_source(source) return SourceColumn.get_for_source(source)
@register.simple_tag(takes_context=True)
def navigation_resolve_menu(context, name, source=None, sort_results=None):
result = []
menu = Menu.get(name)
link_groups = menu.resolve(
context=context, source=source, sort_results=sort_results
)
if link_groups:
result.append({'link_groups': link_groups, 'menu': menu})
return result
@register.simple_tag(takes_context=True)
def navigation_resolve_menus(context, names, source=None, sort_results=None):
result = []
for name in names.split(','):
menu = Menu.get(name=name)
link_groups = menu.resolve(context=context, sort_results=sort_results)
if link_groups:
result.append({'link_groups': link_groups, 'menu': menu})
return result
@register.simple_tag(takes_context=True) @register.simple_tag(takes_context=True)
def resolve_link(context, link): def resolve_link(context, link):
# This can be used to resolve links or menus too # This can be used to resolve links or menus too

View File

@@ -29,7 +29,8 @@ class LinkClassTestCase(GenericViewTestCase):
self.add_test_view(test_object=self.test_object) self.add_test_view(test_object=self.test_object)
self.namespace = PermissionNamespace( self.namespace = PermissionNamespace(
TEST_PERMISSION_NAMESPACE_NAME, TEST_PERMISSION_NAMESPACE_TEXT label=TEST_PERMISSION_NAMESPACE_TEXT,
name=TEST_PERMISSION_NAMESPACE_NAME
) )
self.test_permission = self.namespace.add_permission( self.test_permission = self.namespace.add_permission(
@@ -45,32 +46,30 @@ class LinkClassTestCase(GenericViewTestCase):
Permission.invalidate_cache() Permission.invalidate_cache()
def test_link_resolve(self): def test_link_resolve(self):
response = self.get(TEST_VIEW_NAME) response = self.get(viewname=TEST_VIEW_NAME)
context = Context({'request': response.wsgi_request}) context = Context({'request': response.wsgi_request})
resolved_link = self.link.resolve(context=context) resolved_link = self.link.resolve(context=context)
self.assertEqual(
self.assertEqual(resolved_link.url, reverse(TEST_VIEW_NAME)) resolved_link.url, reverse(viewname=TEST_VIEW_NAME)
)
def test_link_permission_resolve_no_permission(self): def test_link_permission_resolve_no_permission(self):
self.login_user()
link = Link( link = Link(
permissions=(self.test_permission,), text=TEST_LINK_TEXT, permissions=(self.test_permission,), text=TEST_LINK_TEXT,
view=TEST_VIEW_NAME view=TEST_VIEW_NAME
) )
response = self.get(TEST_VIEW_NAME) response = self.get(viewname=TEST_VIEW_NAME)
response.context.update({'request': response.wsgi_request}) response.context.update({'request': response.wsgi_request})
context = Context(response.context) context = Context(response.context)
resolved_link = link.resolve(context=context) resolved_link = link.resolve(context=context)
self.assertEqual(resolved_link, None) self.assertEqual(resolved_link, None)
def test_link_permission_resolve_with_permission(self): def test_link_permission_resolve_with_permission(self):
self.login_user()
link = Link( link = Link(
permissions=(self.test_permission,), text=TEST_LINK_TEXT, permissions=(self.test_permission,), text=TEST_LINK_TEXT,
view=TEST_VIEW_NAME view=TEST_VIEW_NAME
@@ -78,17 +77,16 @@ class LinkClassTestCase(GenericViewTestCase):
self.grant_access(obj=self.test_object, permission=self.test_permission) self.grant_access(obj=self.test_object, permission=self.test_permission)
response = self.get(TEST_VIEW_NAME) response = self.get(viewname=TEST_VIEW_NAME)
response.context.update({'request': response.wsgi_request}) response.context.update({'request': response.wsgi_request})
context = Context(response.context) context = Context(response.context)
resolved_link = link.resolve(context=context) resolved_link = link.resolve(context=context)
self.assertEqual(resolved_link.url, reverse(viewname=TEST_VIEW_NAME))
self.assertEqual(resolved_link.url, reverse(TEST_VIEW_NAME))
def test_link_permission_resolve_with_acl(self): def test_link_permission_resolve_with_acl(self):
# ACL is tested agains the resolved_object or just {{ object }} if not # ACL is tested agains the resolved_object or just {{ object }} if not
link = Link( link = Link(
permissions=(self.test_permission,), text=TEST_LINK_TEXT, permissions=(self.test_permission,), text=TEST_LINK_TEXT,
view=TEST_VIEW_NAME view=TEST_VIEW_NAME
@@ -96,14 +94,14 @@ class LinkClassTestCase(GenericViewTestCase):
self.grant_access(obj=self.test_object, permission=self.test_permission) self.grant_access(obj=self.test_object, permission=self.test_permission)
response = self.get(TEST_VIEW_NAME) response = self.get(viewname=TEST_VIEW_NAME)
response.context.update({'request': response.wsgi_request}) response.context.update({'request': response.wsgi_request})
context = Context(response.context) context = Context(response.context)
resolved_link = link.resolve(context=context) resolved_link = link.resolve(context=context)
self.assertNotEqual(resolved_link, None) self.assertNotEqual(resolved_link, None)
self.assertEqual(resolved_link.url, reverse(TEST_VIEW_NAME)) self.assertEqual(resolved_link.url, reverse(viewname=TEST_VIEW_NAME))
def test_link_with_unicode_querystring_request(self): def test_link_with_unicode_querystring_request(self):
url = furl(reverse(TEST_VIEW_NAME)) url = furl(reverse(TEST_VIEW_NAME))
@@ -130,7 +128,6 @@ class LinkClassTestCase(GenericViewTestCase):
context = Context({'request': response.wsgi_request}) context = Context({'request': response.wsgi_request})
resolved_link = self.link.resolve(context=context) resolved_link = self.link.resolve(context=context)
self.assertEqual( self.assertEqual(
resolved_link.url, resolved_link.url,
'{}?{}'.format(TEST_URL, TEST_QUERYSTRING_TWO_KEYS) '{}?{}'.format(TEST_URL, TEST_QUERYSTRING_TWO_KEYS)
@@ -184,10 +181,10 @@ class MenuClassTestCase(GenericViewTestCase):
def test_null_source_link_unbinding(self): def test_null_source_link_unbinding(self):
self.menu.bind_links(links=(self.link,)) self.menu.bind_links(links=(self.link,))
response = self.get(TEST_VIEW_NAME) response = self.get(viewname=TEST_VIEW_NAME)
context = Context({'request': response.wsgi_request}) context = Context({'request': response.wsgi_request})
self.assertEqual( self.assertEqual(
self.menu.resolve(context=context)[0][0].link, self.link self.menu.resolve(context=context)[0]['links'][0].link, self.link
) )
self.menu.unbind_links(links=(self.link,)) self.menu.unbind_links(links=(self.link,))
@@ -197,10 +194,12 @@ class MenuClassTestCase(GenericViewTestCase):
def test_null_source_submenu_unbinding(self): def test_null_source_submenu_unbinding(self):
self.menu.bind_links(links=(self.sub_menu,)) self.menu.bind_links(links=(self.sub_menu,))
response = self.get(TEST_VIEW_NAME) response = self.get(viewname=TEST_VIEW_NAME)
context = Context({'request': response.wsgi_request}) context = Context({'request': response.wsgi_request})
self.assertEqual(self.menu.resolve(context=context), [[self.sub_menu]]) self.assertEqual(
self.menu.resolve(context=context)[0]['links'], [self.sub_menu]
)
self.menu.unbind_links(links=(self.sub_menu,)) self.menu.unbind_links(links=(self.sub_menu,))

View File

@@ -1,10 +1,15 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
import logging
from django.apps import apps from django.apps import apps
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.urls import Resolver404, resolve
from mayan.apps.permissions import Permission from mayan.apps.permissions import Permission
logger = logging.getLogger(__name__)
def get_cascade_condition(app_label, model_name, object_permission, view_permission=None): def get_cascade_condition(app_label, model_name, object_permission, view_permission=None):
""" """
@@ -37,3 +42,20 @@ def get_cascade_condition(app_label, model_name, object_permission, view_permiss
return queryset.count() > 0 return queryset.count() > 0
return condition return condition
def get_current_view_name(request):
current_path = request.META['PATH_INFO']
# Get sources: view name, view objects
try:
current_view_name = resolve(current_path).view_name
except Resolver404:
# Can't figure out which view corresponds to this URL.
# Most likely it is an invalid URL.
logger.warning(
'Can\'t figure out which view corresponds to this '
'URL: %s; aborting menu resolution.', current_path
)
else:
return current_view_name

View File

@@ -12,7 +12,8 @@ from mayan.apps.acls.classes import ModelPermission
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.classes import ModelField from mayan.apps.common.classes import ModelField
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_facet, menu_multi_item, menu_object, menu_secondary, menu_tools menu_facet, menu_list_facet, menu_multi_item, menu_object, menu_secondary,
menu_tools
) )
from mayan.apps.documents.search import document_search, document_page_search from mayan.apps.documents.search import document_search, document_page_search
from mayan.apps.documents.signals import post_version_upload from mayan.apps.documents.signals import post_version_upload
@@ -138,21 +139,18 @@ class OCRApp(MayanAppConfig):
menu_facet.bind_links( menu_facet.bind_links(
links=(link_document_ocr_content,), sources=(Document,) links=(link_document_ocr_content,), sources=(Document,)
) )
menu_facet.bind_links( menu_list_facet.bind_links(
links=(link_document_page_ocr_content,), sources=(DocumentPage,) links=(link_document_page_ocr_content,), sources=(DocumentPage,)
) )
menu_list_facet.bind_links(
links=(link_document_type_ocr_settings,), sources=(DocumentType,)
)
menu_multi_item.bind_links( menu_multi_item.bind_links(
links=(link_document_submit_multiple,), sources=(Document,) links=(link_document_submit_multiple,), sources=(Document,)
) )
menu_object.bind_links( menu_object.bind_links(
links=(link_document_submit,), sources=(Document,) links=(link_document_submit,), sources=(Document,)
) )
menu_object.bind_links(
links=(link_document_page_ocr_content,), sources=(DocumentPage,)
)
menu_object.bind_links(
links=(link_document_type_ocr_settings,), sources=(DocumentType,)
)
menu_secondary.bind_links( menu_secondary.bind_links(
links=( links=(
link_document_ocr_content, link_document_ocr_errors_list, link_document_ocr_content, link_document_ocr_errors_list,

View File

@@ -9,7 +9,7 @@ from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_multi_item, menu_object, menu_secondary, menu_setup menu_list_facet, menu_multi_item, menu_object, menu_secondary, menu_setup
) )
from mayan.apps.common.signals import perform_upgrade from mayan.apps.common.signals import perform_upgrade
@@ -47,13 +47,17 @@ class PermissionsApp(MayanAppConfig):
) )
) )
menu_object.bind_links( menu_list_facet.bind_links(
links=(link_group_roles,), position=98, sources=(Group,) links=(
link_acl_list, link_role_groups, link_role_permissions,
), sources=(Role,)
)
menu_list_facet.bind_links(
links=(link_group_roles,), sources=(Group,)
) )
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_role_edit, link_role_groups, link_role_permissions, link_role_delete, link_role_edit
link_acl_list, link_role_delete
), sources=(Role,) ), sources=(Role,)
) )
menu_multi_item.bind_links( menu_multi_item.bind_links(

View File

@@ -7,7 +7,7 @@ from kombu import Exchange, Queue
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.classes import MissingItem from mayan.apps.common.classes import MissingItem
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_object, menu_secondary, menu_sidebar, menu_setup menu_list_facet, menu_object, menu_secondary, menu_sidebar, menu_setup
) )
from mayan.apps.common.signals import post_initial_setup, post_upgrade from mayan.apps.common.signals import post_initial_setup, post_upgrade
from mayan.apps.converter.links import link_transformation_list from mayan.apps.converter.links import link_transformation_list
@@ -125,10 +125,18 @@ class SourcesApp(MayanAppConfig):
) )
menu_documents.bind_links(links=(link_document_create_multiple,)) menu_documents.bind_links(links=(link_document_create_multiple,))
menu_list_facet.bind_links(
links=(
link_setup_source_logs, link_transformation_list,
), sources=(
POP3Email, IMAPEmail, SaneScanner, StagingFolderSource,
WatchFolderSource, WebFormSource
)
)
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_setup_source_edit, link_setup_source_delete, link_setup_source_delete, link_setup_source_edit
link_transformation_list, link_setup_source_logs
), sources=( ), sources=(
POP3Email, IMAPEmail, SaneScanner, StagingFolderSource, POP3Email, IMAPEmail, SaneScanner, StagingFolderSource,
WatchFolderSource, WebFormSource WatchFolderSource, WebFormSource

View File

@@ -10,7 +10,8 @@ from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.classes import ModelField from mayan.apps.common.classes import ModelField
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_facet, menu_object, menu_main, menu_multi_item, menu_sidebar menu_facet, menu_list_facet, menu_main, menu_multi_item, menu_object,
menu_sidebar
) )
from mayan.apps.documents.search import document_page_search, document_search from mayan.apps.documents.search import document_page_search, document_search
from mayan.apps.events import ModelEventType from mayan.apps.events import ModelEventType
@@ -42,7 +43,7 @@ from .search import tag_search # NOQA
class TagsApp(MayanAppConfig): class TagsApp(MayanAppConfig):
app_namespace = 'tags' app_namespace = 'tags'
app_urls = 'tags' app_url = 'tags'
has_rest_api = True has_rest_api = True
has_tests = True has_tests = True
name = 'mayan.apps.tags' name = 'mayan.apps.tags'
@@ -143,6 +144,14 @@ class TagsApp(MayanAppConfig):
links=(link_tag_document_list,), sources=(Document,) links=(link_tag_document_list,), sources=(Document,)
) )
menu_list_facet.bind_links(
links=(
link_acl_list, link_events_for_object,
link_object_event_types_user_subcriptions_list,
link_tag_tagged_item_list,
), sources=(Tag,)
)
menu_tags.bind_links( menu_tags.bind_links(
links=( links=(
link_tag_list, link_tag_create link_tag_list, link_tag_create
@@ -163,10 +172,7 @@ class TagsApp(MayanAppConfig):
) )
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_tag_tagged_item_list, link_tag_edit, link_acl_list, link_tag_edit, link_tag_delete
link_events_for_object,
link_object_event_types_user_subcriptions_list,
link_tag_delete
), ),
sources=(Tag,) sources=(Tag,)
) )

View File

@@ -10,7 +10,8 @@ from mayan.apps.acls.links import link_acl_list
from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.apps import MayanAppConfig
from mayan.apps.common.menus import ( from mayan.apps.common.menus import (
menu_multi_item, menu_object, menu_secondary, menu_setup, menu_user menu_list_facet, menu_multi_item, menu_object, menu_secondary, menu_setup,
menu_user
) )
from mayan.apps.common.widgets import TwoStateWidget from mayan.apps.common.widgets import TwoStateWidget
from mayan.apps.metadata import MetadataLookup from mayan.apps.metadata import MetadataLookup
@@ -114,22 +115,31 @@ class UserManagementApp(MayanAppConfig):
).render() ).render()
) )
menu_list_facet.bind_links(
links=(
link_acl_list, link_group_members
), sources=(Group,)
)
menu_list_facet.bind_links(
links=(
link_acl_list, link_user_groups, link_user_set_options
), sources=(User,)
)
menu_multi_item.bind_links( menu_multi_item.bind_links(
links=(link_user_multiple_set_password, link_user_multiple_delete), links=(link_user_multiple_set_password, link_user_multiple_delete),
sources=('user_management:user_list',) sources=('user_management:user_list',)
) )
menu_object.bind_links( menu_object.bind_links(
links=(link_group_edit, link_group_members,), links=(link_group_edit,),
sources=(Group,) sources=(Group,)
) )
menu_object.bind_links( menu_object.bind_links(
links=(link_acl_list, link_group_delete,), position=99, links=(link_group_delete,), position=99,
sources=(Group,) sources=(Group,)
) )
menu_object.bind_links( menu_object.bind_links(
links=( links=(
link_user_edit, link_user_set_password, link_user_groups, link_user_delete, link_user_edit, link_user_set_password
link_user_set_options, link_acl_list, link_user_delete
), sources=(User,) ), sources=(User,)
) )
menu_secondary.bind_links( menu_secondary.bind_links(