-
- {% if multi_item_actions %}
+
diff --git a/mayan/apps/common/generics.py b/mayan/apps/common/generics.py
index c9b57e4123..6112e89db8 100644
--- a/mayan/apps/common/generics.py
+++ b/mayan/apps/common/generics.py
@@ -22,10 +22,15 @@ from django_downloadview import (
from pure_pagination.mixins import PaginationMixin
from .forms import ChoiceForm
-from .icons import icon_assign_remove_add, icon_assign_remove_remove
+from .icons import (
+ icon_assign_remove_add, icon_assign_remove_remove, icon_sort_down,
+ icon_sort_up
+)
from .literals import (
- TEXT_CHOICE_ITEMS, TEXT_CHOICE_LIST, TEXT_LIST_AS_ITEMS,
- TEXT_LIST_AS_ITEMS_PARAMETER
+ TEXT_CHOICE_ITEMS, TEXT_CHOICE_LIST, TEXT_LIST_AS_ITEMS_VARIABLE_NAME,
+ TEXT_LIST_AS_ITEMS_PARAMETER, TEXT_SORT_FIELD_PARAMETER,
+ TEXT_SORT_FIELD_VARIABLE_NAME, TEXT_SORT_ORDER_CHOICE_ASCENDING,
+ TEXT_SORT_ORDER_PARAMETER, TEXT_SORT_ORDER_VARIABLE_NAME
)
from .mixins import (
DeleteExtraDataMixin, DynamicFormViewMixin, ExtraContextMixin,
@@ -505,7 +510,7 @@ class SingleObjectListView(PaginationMixin, ViewPermissionCheckMixin, ObjectList
def get_context_data(self, **kwargs):
context = super(SingleObjectListView, self).get_context_data(**kwargs)
- if context.get(TEXT_LIST_AS_ITEMS):
+ if context.get(TEXT_LIST_AS_ITEMS_VARIABLE_NAME):
default_mode = TEXT_CHOICE_ITEMS
else:
default_mode = TEXT_CHOICE_LIST
@@ -514,15 +519,52 @@ class SingleObjectListView(PaginationMixin, ViewPermissionCheckMixin, ObjectList
TEXT_LIST_AS_ITEMS_PARAMETER, default_mode
)
- context.update({TEXT_LIST_AS_ITEMS: list_mode == TEXT_CHOICE_ITEMS})
+ print '@@ list_mode', list_mode
+
+ context.update(
+ {
+ TEXT_LIST_AS_ITEMS_VARIABLE_NAME: list_mode == TEXT_CHOICE_ITEMS,
+ TEXT_SORT_FIELD_VARIABLE_NAME: self.get_sort_field(),
+ TEXT_SORT_ORDER_VARIABLE_NAME: self.get_sort_order(),
+ 'icon_sort': self.get_sort_icon(),
+ }
+ )
return context
+ def get_sort_field(self):
+ return self.request.GET.get(TEXT_SORT_FIELD_PARAMETER)
+
+ def get_sort_icon(self):
+ sort_order = self.get_sort_order()
+ if not sort_order:
+ return
+ elif sort_order == TEXT_SORT_ORDER_CHOICE_ASCENDING:
+ return icon_sort_down
+ else:
+ return icon_sort_up
+
+ def get_sort_order(self):
+ return self.request.GET.get(TEXT_SORT_ORDER_PARAMETER)
+
def get_paginate_by(self, queryset):
return setting_paginate_by.value
def get_queryset(self):
+ self.field_name = self.get_sort_field()
+ if self.get_sort_order() == TEXT_SORT_ORDER_CHOICE_ASCENDING:
+ sort_order = ''
+ else:
+ sort_order = '-'
+
try:
- return super(SingleObjectListView, self).get_queryset()
+ queryset = super(SingleObjectListView, self).get_queryset()
except ImproperlyConfigured:
self.queryset = self.get_object_list()
- return super(SingleObjectListView, self).get_queryset()
+ queryset = super(SingleObjectListView, self).get_queryset()
+
+ if self.field_name:
+ queryset = queryset.order_by(
+ '{}{}'.format(sort_order, self.field_name)
+ )
+
+ return queryset
diff --git a/mayan/apps/common/icons.py b/mayan/apps/common/icons.py
index cab1d89260..b681f884e6 100644
--- a/mayan/apps/common/icons.py
+++ b/mayan/apps/common/icons.py
@@ -24,6 +24,12 @@ icon_forum = Icon(
icon_license = Icon(
driver_name='fontawesome', symbol='certificate'
)
+icon_list_mode_list = Icon(
+ driver_name='fontawesome', symbol='list'
+)
+icon_list_mode_items = Icon(
+ driver_name='fontawesome', symbol='th-large'
+)
icon_menu_about = Icon(
driver_name='fontawesome', symbol='info'
)
@@ -54,6 +60,8 @@ icon_social_paypal = Icon(
icon_social_twitter = Icon(
driver_name='fontawesomecss', css_classes='fab fa-twitter'
)
+icon_sort_down = Icon(driver_name='fontawesome', symbol='sort-down')
+icon_sort_up = Icon(driver_name='fontawesome', symbol='sort-up')
icon_source_code = Icon(driver_name='fontawesome', symbol='code-branch')
icon_support = Icon(
driver_name='fontawesome', symbol='phone'
diff --git a/mayan/apps/common/literals.py b/mayan/apps/common/literals.py
index f2d9f2ecce..80b781da2c 100644
--- a/mayan/apps/common/literals.py
+++ b/mayan/apps/common/literals.py
@@ -13,9 +13,15 @@ MESSAGE_SQLITE_WARNING = _(
PYPI_URL = 'https://pypi.python.org/pypi'
TEXT_LIST_AS_ITEMS_PARAMETER = '_list_mode'
-TEXT_LIST_AS_ITEMS = 'list_as_items'
+TEXT_LIST_AS_ITEMS_VARIABLE_NAME = 'list_as_items'
TEXT_CHOICE_ITEMS = 'items'
TEXT_CHOICE_LIST = 'list'
+TEXT_SORT_FIELD_PARAMETER = '_sort_field'
+TEXT_SORT_FIELD_VARIABLE_NAME = 'sort_field'
+TEXT_SORT_ORDER_CHOICE_ASCENDING = 'asc'
+TEXT_SORT_ORDER_CHOICE_DESCENDING = 'desc'
+TEXT_SORT_ORDER_PARAMETER = '_sort_order'
+TEXT_SORT_ORDER_VARIABLE_NAME = 'sort_order'
TIME_DELTA_UNIT_DAYS = 'days'
TIME_DELTA_UNIT_HOURS = 'hours'
diff --git a/mayan/apps/common/templatetags/common_tags.py b/mayan/apps/common/templatetags/common_tags.py
index dede905f71..b251558cc2 100644
--- a/mayan/apps/common/templatetags/common_tags.py
+++ b/mayan/apps/common/templatetags/common_tags.py
@@ -12,6 +12,7 @@ import mayan
from mayan.apps.appearance.settings import setting_max_title_length
from ..classes import Collection
+from ..icons import icon_list_mode_items, icon_list_mode_list
from ..literals import MESSAGE_SQLITE_WARNING
from ..utils import check_for_sqlite, resolve_attribute
@@ -24,11 +25,59 @@ def check_sqlite():
return MESSAGE_SQLITE_WARNING
+@register.simple_tag(takes_context=True)
+def common_calculate_title(context):
+ if context.get('title'):
+ return truncatechars(
+ value=context.get('title'), arg=setting_max_title_length.value
+ )
+ else:
+ if context.get('delete_view'):
+ return _('Confirm delete')
+ else:
+ if context.get('form'):
+ if context.get('object'):
+ return _('Edit %s') % context.get('object')
+ else:
+ return _('Confirm')
+ else:
+ if context.get('read_only'):
+ return _('Details for: %s') % context.get('object')
+ else:
+ if context.get('object'):
+ return _('Edit: %s') % context.get('object')
+ else:
+ return _('Create')
+
+
@register.simple_tag
def get_collections():
return Collection.get_all()
+@register.simple_tag(takes_context=True)
+def get_list_mode_icon(context):
+ if context.get('list_as_items', False):
+ return icon_list_mode_list
+ else:
+ return icon_list_mode_items
+
+
+@register.simple_tag(takes_context=True)
+def get_list_mode_querystring(context):
+ # We do this to get an mutable copy we can modify
+ querystring = context.request.GET.copy()
+
+ list_as_items = context.get('list_as_items', False)
+
+ if list_as_items:
+ querystring['_list_mode'] = 'list'
+ else:
+ querystring['_list_mode'] = 'items'
+
+ return '?{}'.format(querystring.urlencode())
+
+
@register.filter
def get_type(value):
return force_text(type(value))
@@ -53,28 +102,3 @@ def render_subtemplate(context, template_name, template_context):
new_context = Context(context.flatten())
new_context.update(Context(template_context))
return get_template(template_name).render(new_context.flatten())
-
-
-@register.simple_tag(takes_context=True)
-def common_calculate_title(context):
- if context.get('title'):
- return truncatechars(
- value=context.get('title'), arg=setting_max_title_length.value
- )
- else:
- if context.get('delete_view'):
- return _('Confirm delete')
- else:
- if context.get('form'):
- if context.get('object'):
- return _('Edit %s') % context.get('object')
- else:
- return _('Confirm')
- else:
- if context.get('read_only'):
- return _('Details for: %s') % context.get('object')
- else:
- if context.get('object'):
- return _('Edit: %s') % context.get('object')
- else:
- return _('Create')
diff --git a/mayan/apps/documents/apps.py b/mayan/apps/documents/apps.py
index 5686d8d0f3..1f102f8ed7 100644
--- a/mayan/apps/documents/apps.py
+++ b/mayan/apps/documents/apps.py
@@ -233,15 +233,25 @@ class DocumentsApp(MayanAppConfig):
document_page_thumbnail_widget = DocumentPageThumbnailWidget()
# Document
+ SourceColumn(
+ attribute='label', is_absolute_url=True, is_identifier=True,
+ is_sortable=True, source=Document
+ )
SourceColumn(
func=lambda context: document_page_thumbnail_widget.render(
instance=context['object']
), label=_('Thumbnail'), source=Document
)
SourceColumn(
- attribute='document_type', label=_('Type'), source=Document
+ attribute='document_type', is_sortable=True, label=_('Type'),
+ source=Document
)
SourceColumn(attribute='get_page_count', source=Document)
+ SourceColumn(
+ attribute='date_added', is_sortable=True, source=Document, views=(
+ 'documents:document_list_recent_added',
+ )
+ )
# DocumentPage
SourceColumn(
@@ -262,6 +272,10 @@ class DocumentsApp(MayanAppConfig):
)
# DocumentType
+ SourceColumn(
+ attribute='label', is_identifier=True, is_sortable=True,
+ source=DocumentType
+ )
SourceColumn(
func=lambda context: context['object'].get_document_count(
user=context['request'].user
@@ -269,11 +283,19 @@ class DocumentsApp(MayanAppConfig):
)
SourceColumn(
- attribute='enabled', source=DocumentTypeFilename,
+ attribute='filename', is_identifier=True, is_sortable=True,
+ source=DocumentTypeFilename
+ )
+ SourceColumn(
+ attribute='enabled', is_sortable=True, source=DocumentTypeFilename,
widget=TwoStateWidget
)
# DeletedDocument
+ SourceColumn(
+ attribute='label', is_identifier=True, is_sortable=True,
+ source=DeletedDocument
+ )
SourceColumn(
func=lambda context: document_page_thumbnail_widget.render(
instance=context['object']
@@ -281,7 +303,7 @@ class DocumentsApp(MayanAppConfig):
)
SourceColumn(
- attribute='document_type', source=DeletedDocument
+ attribute='document_type', is_sortable=True, source=DeletedDocument
)
SourceColumn(
attribute='get_rendered_deleted_date_time', source=DeletedDocument
@@ -298,9 +320,15 @@ class DocumentsApp(MayanAppConfig):
), label=_('Thumbnail'), source=DocumentVersion
)
SourceColumn(attribute='get_page_count', source=DocumentVersion)
- SourceColumn(attribute='mimetype', source=DocumentVersion)
- SourceColumn(attribute='encoding', source=DocumentVersion)
- SourceColumn(attribute='comment', source=DocumentVersion)
+ SourceColumn(
+ attribute='mimetype', is_sortable=True, source=DocumentVersion
+ )
+ SourceColumn(
+ attribute='encoding', is_sortable=True, source=DocumentVersion
+ )
+ SourceColumn(
+ attribute='comment', is_sortable=True, source=DocumentVersion
+ )
# DuplicatedDocument
SourceColumn(
diff --git a/mayan/apps/documents/views/document_type_views.py b/mayan/apps/documents/views/document_type_views.py
index 3034093ce4..c3936cdadb 100644
--- a/mayan/apps/documents/views/document_type_views.py
+++ b/mayan/apps/documents/views/document_type_views.py
@@ -115,6 +115,7 @@ class DocumentTypeListView(SingleObjectListView):
def get_extra_context(self):
return {
'hide_link': True,
+ 'hide_object': True,
'no_results_icon': icon_document_type_setup,
'no_results_main_link': link_document_type_create.resolve(
context=RequestContext(request=self.request)
@@ -224,6 +225,7 @@ class DocumentTypeFilenameListView(SingleObjectListView):
return {
'document_type': self.get_document_type(),
'hide_link': True,
+ 'hide_object': True,
'navigation_object_list': ('document_type',),
'no_results_icon': icon_document_type_filename,
'no_results_main_link': link_document_type_filename_create.resolve(
diff --git a/mayan/apps/documents/views/document_views.py b/mayan/apps/documents/views/document_views.py
index c51a0038ff..dd82fed1fd 100644
--- a/mayan/apps/documents/views/document_views.py
+++ b/mayan/apps/documents/views/document_views.py
@@ -84,6 +84,7 @@ class DocumentListView(SingleObjectListView):
def get_extra_context(self):
return {
'hide_links': True,
+ 'hide_object': True,
'list_as_items': True,
'no_results_icon': icon_document_list,
'no_results_text': _(
@@ -963,9 +964,6 @@ class RecentAddedDocumentListView(DocumentListView):
context = super(RecentAddedDocumentListView, self).get_extra_context()
context.update(
{
- 'extra_columns': (
- {'name': _('Added'), 'attribute': 'date_added'},
- ),
'no_results_icon': icon_document_list_recent_added,
'no_results_text': _(
'This view will list the latest documents uploaded '
diff --git a/mayan/apps/events/apps.py b/mayan/apps/events/apps.py
index 0604a32413..990c7a9d8d 100644
--- a/mayan/apps/events/apps.py
+++ b/mayan/apps/events/apps.py
@@ -40,7 +40,7 @@ class EventsApp(MayanAppConfig):
SourceColumn(
attribute='timestamp', is_identifier=True,
- label=_('Date and time'), source=Action
+ is_sortable=True, label=_('Date and time'), source=Action
)
SourceColumn(
func=widget_event_user_link, label=_('Actor'), source=Action
@@ -65,9 +65,8 @@ class EventsApp(MayanAppConfig):
)
SourceColumn(
- attribute='action.timestamp', is_identifier=True,
- label=_('Date and time'), source=Notification
-
+ attribute='action__timestamp', is_identifier=True,
+ is_sortable=True, label=_('Date and time'), source=Notification
)
SourceColumn(
func=widget_event_user_link, kwargs={'attribute': 'action'},
@@ -77,15 +76,14 @@ class EventsApp(MayanAppConfig):
func=widget_event_type_link, kwargs={'attribute': 'action'},
label=_('Event'), source=Notification
)
-
SourceColumn(
func=widget_event_object_link, kwargs={
'attribute': 'action.target'
}, label=_('Target'), source=Notification
)
SourceColumn(
- attribute='read', label=_('Seen'), source=Notification,
- widget=TwoStateWidget
+ attribute='read', is_sortable=True, label=_('Seen'),
+ source=Notification, widget=TwoStateWidget
)
menu_list_facet.bind_links(
diff --git a/mayan/apps/metadata/apps.py b/mayan/apps/metadata/apps.py
index c6b60776ee..94b0650ee9 100644
--- a/mayan/apps/metadata/apps.py
+++ b/mayan/apps/metadata/apps.py
@@ -154,17 +154,20 @@ class MetadataApp(MayanAppConfig):
SourceColumn(
attribute='metadata_type', is_identifier=True,
- source=DocumentMetadata
+ is_sortable=True, source=DocumentMetadata
+ )
+ SourceColumn(
+ attribute='value', is_sortable=True, source=DocumentMetadata
)
- SourceColumn(attribute='value', source=DocumentMetadata)
SourceColumn(
attribute='is_required', source=DocumentMetadata,
widget=TwoStateWidget
)
SourceColumn(
- attribute='label', is_identifier=True, source=MetadataType
+ attribute='label', is_identifier=True, is_sortable=True,
+ source=MetadataType
)
- SourceColumn(attribute='name', source=MetadataType)
+ SourceColumn(attribute='name', is_sortable=True, source=MetadataType)
app.conf.task_queues.append(
Queue('metadata', Exchange('metadata'), routing_key='metadata'),
diff --git a/mayan/apps/navigation/classes.py b/mayan/apps/navigation/classes.py
index 6dd5cc8e72..8542049de9 100644
--- a/mayan/apps/navigation/classes.py
+++ b/mayan/apps/navigation/classes.py
@@ -17,17 +17,23 @@ from django.urls import Resolver404, resolve
from django.utils.encoding import force_str, force_text
from django.utils.translation import ugettext_lazy as _
+from mayan.apps.common.literals import (
+ TEXT_SORT_FIELD_PARAMETER, TEXT_SORT_FIELD_VARIABLE_NAME,
+ TEXT_SORT_ORDER_CHOICE_ASCENDING, TEXT_SORT_ORDER_CHOICE_DESCENDING,
+ TEXT_SORT_ORDER_PARAMETER, TEXT_SORT_ORDER_VARIABLE_NAME
+)
from mayan.apps.common.utils import resolve_attribute
from mayan.apps.permissions import Permission
from .exceptions import NavigationError
+from .utils import get_current_view_name
logger = logging.getLogger(__name__)
class ResolvedLink(object):
- def __init__(self, link, current_view):
- self.current_view = current_view
+ def __init__(self, link, current_view_name):
+ self.current_view_name = current_view_name
self.disabled = False
self.link = link
self.url = '#'
@@ -36,7 +42,7 @@ class ResolvedLink(object):
@property
def active(self):
- return self.link.view == self.current_view
+ return self.link.view == self.current_view_name
@property
def description(self):
@@ -177,15 +183,8 @@ class Menu(object):
logger.warning('No request variable, aborting menu resolution')
return ()
- current_path = request.META['PATH_INFO']
-
- # 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)
+ current_view_name = get_current_view_name(request=request)
+ if not current_view_name:
return ()
resolved_navigation_object_list = self.get_resolved_navigation_object_list(
@@ -230,10 +229,10 @@ class Menu(object):
resolved_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)
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)
if resolved_links:
@@ -349,7 +348,7 @@ class Link(object):
request = Variable('request').resolve(context)
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
if not resolved_object:
@@ -384,7 +383,9 @@ class Link(object):
if not self.condition(context):
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:
view_name = Variable('"{}"'.format(self.view))
@@ -465,7 +466,7 @@ class Separator(Link):
self.view = None
def resolve(self, *args, **kwargs):
- result = ResolvedLink(current_view=None, link=self)
+ result = ResolvedLink(current_view_name=None, link=self)
result.separator = True
return result
@@ -498,7 +499,7 @@ class SourceColumn(object):
return sorted(columns, key=lambda x: x.order)
@classmethod
- def get_for_source(cls, source, exclude_identifier=False, only_identifier=False):
+ def get_for_source(cls, context, source, exclude_identifier=False, only_identifier=False):
try:
result = SourceColumn.sort(columns=cls._registry[source])
except KeyError:
@@ -521,16 +522,26 @@ class SourceColumn(object):
result = ()
if exclude_identifier:
- return [item for item in result if not item.is_identifier]
+ result = [item for item in result if not item.is_identifier]
else:
if only_identifier:
for item in result:
if item.is_identifier:
return item
- else:
- return result
+ return None
- def __init__(self, source, attribute=None, empty_value=None, func=None, is_identifier=False, kwargs=None, label=None, order=None, widget=None):
+ final_result = []
+ current_view_name = get_current_view_name(request=context.request)
+ for item in result:
+ if item.views:
+ if current_view_name in item.views:
+ final_result.append(item)
+ else:
+ final_result.append(item)
+
+ return final_result
+
+ def __init__(self, source, attribute=None, empty_value=None, func=None, is_absolute_url=False, is_identifier=False, is_sortable=False, kwargs=None, label=None, order=None, views=None, widget=None):
self.source = source
self._label = label
self.attribute = attribute
@@ -538,10 +549,13 @@ class SourceColumn(object):
self.func = func
self.kwargs = kwargs or {}
self.order = order or 0
+ self.is_absolute_url = is_absolute_url
self.is_identifier = is_identifier
+ self.is_sortable = is_sortable
self.__class__._registry.setdefault(source, [])
self.__class__._registry[source].append(self)
self.label = None
+ self.views = views or []
self.widget = widget
if not attribute and not func:
raise NavigationError(
@@ -554,7 +568,9 @@ class SourceColumn(object):
if not self._label:
if self.attribute:
try:
- attribute = resolve_attribute(obj=self.source, attribute=self.attribute)
+ attribute = resolve_attribute(
+ obj=self.source, attribute=self.attribute
+ )
self._label = getattr(attribute, 'short_description')
except AttributeError:
name, model = SourceColumn.get_attribute_recursive(
@@ -564,11 +580,39 @@ class SourceColumn(object):
name=name, model=model
)
else:
- self._label = getattr(self.func, 'short_description', _('Unnamed function'))
+ self._label = getattr(
+ self.func, 'short_description', _('Unnamed function')
+ )
self.label = self._label
+ def get_sort_field_querystring(self, context):
+ # We do this to get an mutable copy we can modify
+ querystring = context.request.GET.copy()
+
+ previous_sort_field = context.get(TEXT_SORT_FIELD_VARIABLE_NAME, None)
+ previous_sort_order = context.get(
+ TEXT_SORT_ORDER_VARIABLE_NAME, TEXT_SORT_ORDER_CHOICE_DESCENDING
+ )
+
+ if previous_sort_field != self.attribute:
+ sort_order = TEXT_SORT_ORDER_CHOICE_ASCENDING
+ else:
+ if previous_sort_order == TEXT_SORT_ORDER_CHOICE_DESCENDING:
+ sort_order = TEXT_SORT_ORDER_CHOICE_ASCENDING
+ else:
+ sort_order = TEXT_SORT_ORDER_CHOICE_DESCENDING
+
+ querystring[TEXT_SORT_FIELD_PARAMETER] = self.attribute
+ querystring[TEXT_SORT_ORDER_PARAMETER] = sort_order
+
+ return '?{}'.format(querystring.urlencode())
+
def resolve(self, context):
+ if self.views:
+ if get_current_view_name(request=context.request) not in self.views:
+ return
+
if self.attribute:
result = resolve_attribute(
obj=context['object'], attribute=self.attribute,
@@ -579,7 +623,7 @@ class SourceColumn(object):
if self.widget:
widget_instance = self.widget()
- return widget_instance.render(name='asd', value=result)
+ return widget_instance.render(name=self.attribute, value=result)
if not result:
if self.empty_value:
@@ -600,7 +644,7 @@ class Text(Link):
self.view = None
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.text_span = True
return result
diff --git a/mayan/apps/navigation/literals.py b/mayan/apps/navigation/literals.py
deleted file mode 100644
index 6f40e48c7d..0000000000
--- a/mayan/apps/navigation/literals.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import unicode_literals
-
-TEXT_ONLY_IDENTIFIER = 'only_identifier'
-TEXT_EXCLUDE_IDENTIFIER = 'exclude_identifier'
diff --git a/mayan/apps/navigation/templatetags/navigation_tags.py b/mayan/apps/navigation/templatetags/navigation_tags.py
index 0f8ca917fe..786a82cdb1 100644
--- a/mayan/apps/navigation/templatetags/navigation_tags.py
+++ b/mayan/apps/navigation/templatetags/navigation_tags.py
@@ -4,7 +4,6 @@ from django.template import Library
from ..classes import Link, Menu, SourceColumn
from ..forms import MultiItemForm
-from ..literals import TEXT_EXCLUDE_IDENTIFIER, TEXT_ONLY_IDENTIFIER
register = Library()
@@ -48,16 +47,13 @@ def get_multi_item_links_form(context, object_list):
return ''
-@register.filter
-def get_source_columns(source, args=None):
- exclude_identifier = False
- only_identifier = False
+@register.simple_tag(takes_context=True)
+def get_sort_field_querystring(context, column):
+ return column.get_sort_field_querystring(context=context)
- if args == TEXT_EXCLUDE_IDENTIFIER:
- exclude_identifier = True
- elif args == TEXT_ONLY_IDENTIFIER:
- only_identifier = True
+@register.simple_tag(takes_context=True)
+def get_source_columns(context, source, exclude_identifier=False, only_identifier=False):
try:
# Is it a query set?
source = source.model
@@ -77,7 +73,7 @@ def get_source_columns(source, args=None):
pass
return SourceColumn.get_for_source(
- source=source, exclude_identifier=exclude_identifier,
+ context=context, source=source, exclude_identifier=exclude_identifier,
only_identifier=only_identifier
)
diff --git a/mayan/apps/navigation/utils.py b/mayan/apps/navigation/utils.py
index 0d67993041..9750ab9138 100644
--- a/mayan/apps/navigation/utils.py
+++ b/mayan/apps/navigation/utils.py
@@ -1,10 +1,15 @@
from __future__ import absolute_import, unicode_literals
+import logging
+
from django.apps import apps
from django.core.exceptions import PermissionDenied
+from django.urls import Resolver404, resolve
from mayan.apps.permissions import Permission
+logger = logging.getLogger(__name__)
+
def get_cascade_condition(app_label, model_name, object_permission, view_permission=None):
"""
@@ -38,3 +43,20 @@ def get_cascade_condition(app_label, model_name, object_permission, view_permiss
return queryset.count() > 0
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
diff --git a/mayan/apps/tags/apps.py b/mayan/apps/tags/apps.py
index 86adc17f17..ee9c6617af 100644
--- a/mayan/apps/tags/apps.py
+++ b/mayan/apps/tags/apps.py
@@ -43,7 +43,7 @@ from .widgets import widget_document_tags
class TagsApp(MayanAppConfig):
app_namespace = 'tags'
- app_urls = 'tags'
+ app_url = 'tags'
has_rest_api = True
has_tests = True
name = 'mayan.apps.tags'
@@ -101,7 +101,8 @@ class TagsApp(MayanAppConfig):
)
SourceColumn(
- attribute='label', is_identifier=True, source=DocumentTag,
+ attribute='label', is_identifier=True, is_sortable=True,
+ source=DocumentTag,
)
SourceColumn(
attribute='get_preview_widget', source=DocumentTag
@@ -121,7 +122,8 @@ class TagsApp(MayanAppConfig):
)
SourceColumn(
- attribute='label', is_identifier=True, source=Tag
+ attribute='label', is_identifier=True, is_sortable=True,
+ source=Tag
)
SourceColumn(
attribute='get_preview_widget', source=Tag