diff --git a/mayan/apps/acls/views.py b/mayan/apps/acls/views.py
index 2d61c8d654..54c928b80c 100644
--- a/mayan/apps/acls/views.py
+++ b/mayan/apps/acls/views.py
@@ -10,7 +10,6 @@ from django.http import Http404
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext_lazy as _
-from common.utils import encapsulate
from common.views import (
AssignRemoveView, SingleObjectCreateView, SingleObjectDeleteView,
SingleObjectListView
diff --git a/mayan/apps/appearance/templates/appearance/generic_list_subtemplate.html b/mayan/apps/appearance/templates/appearance/generic_list_subtemplate.html
index 6c01f9fe11..cb1577b986 100644
--- a/mayan/apps/appearance/templates/appearance/generic_list_subtemplate.html
+++ b/mayan/apps/appearance/templates/appearance/generic_list_subtemplate.html
@@ -87,7 +87,7 @@
{% endif %}
{% if not hide_columns %}
{% for column in object|get_source_columns %}
-
{{ object|object_property:column.attribute }} |
+ {% source_column_resolve column=column %} |
{% endfor %}
{% endif %}
{% for column in extra_columns %}
diff --git a/mayan/apps/converter/apps.py b/mayan/apps/converter/apps.py
index 6ae2a5ebc9..66f776cd78 100644
--- a/mayan/apps/converter/apps.py
+++ b/mayan/apps/converter/apps.py
@@ -3,7 +3,6 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from common import MayanAppConfig, menu_object, menu_sidebar
-from common.utils import encapsulate
from navigation import SourceColumn
from .links import (
@@ -23,9 +22,7 @@ class ConverterApp(MayanAppConfig):
SourceColumn(source=Transformation, label=_('Order'), attribute='order')
SourceColumn(
source=Transformation, label=_('Transformation'),
- attribute=encapsulate(
- lambda transformation: unicode(transformation)
- )
+ func=lambda context: unicode(context['object'])
)
SourceColumn(
source=Transformation, label=_('Arguments'), attribute='arguments'
diff --git a/mayan/apps/django_gpg/apps.py b/mayan/apps/django_gpg/apps.py
index 7a228f47a0..b01645acb4 100644
--- a/mayan/apps/django_gpg/apps.py
+++ b/mayan/apps/django_gpg/apps.py
@@ -5,7 +5,6 @@ from datetime import datetime
from django.utils.translation import ugettext_lazy as _
from common import MayanAppConfig, menu_object, menu_setup, menu_sidebar
-from common.utils import encapsulate
from navigation import SourceColumn
from .api import Key, KeyStub
@@ -23,34 +22,31 @@ class DjangoGPGApp(MayanAppConfig):
def ready(self):
super(DjangoGPGApp, self).ready()
- SourceColumn(source=Key, label='ID', attribute='key_id')
+ SourceColumn(source=Key, label=_('ID'), attribute='key_id')
SourceColumn(
- source=Key, label='Owner', attribute=encapsulate(
- lambda key: ', '.join(key.uids)
- )
+ source=Key, label=_('Owner'),
+ func=lambda context: ', '.join(context['object'].uids)
)
SourceColumn(
- source=KeyStub, label='ID', attribute=encapsulate(
- lambda key: '...{0}'.format(key.key_id[-16:])
- )
+ source=KeyStub, label=_('ID'),
+ func=lambda context: '...{0}'.format(context['object'].key_id[-16:])
)
- SourceColumn(source=KeyStub, label='Type', attribute='key_type')
+ SourceColumn(source=KeyStub, label=_('Type'), attribute='key_type')
SourceColumn(
- source=KeyStub, label='Creation date', attribute=encapsulate(
- lambda key: datetime.fromtimestamp(int(key.date))
+ source=KeyStub, label=_('Creation date'),
+ func=lambda context: datetime.fromtimestamp(
+ int(context['object'].date)
)
)
SourceColumn(
- source=KeyStub, label='Expiration date', attribute=encapsulate(
- lambda key: datetime.fromtimestamp(int(key.expires)) if key.expires else _('No expiration')
- )
+ source=KeyStub, label=_('Expiration date'),
+ func=lambda context: datetime.fromtimestamp(int(context['object'].expires)) if context['object'].expires else _('No expiration')
)
- SourceColumn(source=KeyStub, label='Length', attribute='length')
+ SourceColumn(source=KeyStub, label=_('Length'), attribute='length')
SourceColumn(
- source=KeyStub, label='Identities', attribute=encapsulate(
- lambda key: ', '.join(key.uids)
- )
+ source=KeyStub, label=_('Identities'),
+ func=lambda context: ', '.join(context['object'].uids)
)
menu_object.bind_links(links=(link_key_delete,), sources=(Key,))
diff --git a/mayan/apps/django_gpg/views.py b/mayan/apps/django_gpg/views.py
index 4ecd1bb673..ce3ec951c3 100644
--- a/mayan/apps/django_gpg/views.py
+++ b/mayan/apps/django_gpg/views.py
@@ -12,7 +12,6 @@ from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _
from common.generics import SimpleView, SingleObjectListView
-from common.utils import encapsulate
from permissions import Permission
from .api import Key
diff --git a/mayan/apps/document_comments/apps.py b/mayan/apps/document_comments/apps.py
index 1c82786a64..378ed7f66e 100644
--- a/mayan/apps/document_comments/apps.py
+++ b/mayan/apps/document_comments/apps.py
@@ -4,7 +4,6 @@ from django.utils.translation import ugettext_lazy as _
from acls import ModelPermission
from common import MayanAppConfig, menu_facet, menu_object, menu_sidebar
-from common.utils import encapsulate
from documents.models import Document
from navigation import SourceColumn
@@ -37,9 +36,7 @@ class DocumentCommentsApp(MayanAppConfig):
SourceColumn(source=Comment, label=_('Date'), attribute='submit_date')
SourceColumn(
source=Comment, label=_('User'),
- attribute=encapsulate(
- lambda x: x.user.get_full_name() if x.user.get_full_name() else x.user
- )
+ func=lambda context: context['object'].user.get_full_name() if context['object'].user.get_full_name() else context['object'].user
)
SourceColumn(source=Comment, label=_('Comment'), attribute='comment')
diff --git a/mayan/apps/document_indexing/apps.py b/mayan/apps/document_indexing/apps.py
index 14d229629e..02a7ef4993 100644
--- a/mayan/apps/document_indexing/apps.py
+++ b/mayan/apps/document_indexing/apps.py
@@ -9,10 +9,12 @@ from common import (
MayanAppConfig, menu_facet, menu_main, menu_object, menu_secondary,
menu_setup, menu_tools
)
+from common.widgets import two_state_template
from documents.models import Document
from documents.signals import post_document_created
from mayan.celery import app
from metadata.models import DocumentMetadata
+from navigation import SourceColumn
from rest_api.classes import APIEndPoint
from .handlers import (
@@ -27,7 +29,11 @@ from .links import (
link_template_node_create, link_template_node_delete,
link_template_node_edit
)
-from .models import Index, IndexTemplateNode
+from .models import (
+ DocumentIndexInstanceNode, Index, IndexInstance, IndexInstanceNode,
+ IndexTemplateNode
+)
+from .widgets import get_breadcrumbs, index_instance_item_link, node_level
class DocumentIndexingApp(MayanAppConfig):
@@ -41,6 +47,60 @@ class DocumentIndexingApp(MayanAppConfig):
APIEndPoint(app=self, version_string='1')
+ SourceColumn(source=Index, label=_('Label'), attribute='label')
+ SourceColumn(source=Index, label=_('Slug'), attribute='slug')
+ SourceColumn(
+ source=Index, label=_('Enabled'),
+ func=lambda context: two_state_template(context['object'].enabled)
+ )
+
+ SourceColumn(
+ source=IndexInstance, label=_('Items'),
+ func=lambda context: context['object'].get_items_count(
+ user=context['request'].user
+ )
+ )
+ SourceColumn(
+ source=IndexInstance, label=_('Document types'), attribute='get_document_types_names'
+ )
+
+ SourceColumn(
+ source=IndexTemplateNode, label=_('Level'),
+ func=lambda context: node_level(context['object'])
+ )
+ SourceColumn(
+ source=IndexTemplateNode, label=_('Enabled'),
+ func=lambda context: two_state_template(context['object'].enabled)
+ )
+ SourceColumn(
+ source=IndexTemplateNode, label=_('Has document links?'),
+ func=lambda context: two_state_template(context['object'].link_documents)
+ )
+
+ SourceColumn(
+ source=IndexInstanceNode, label=_('Node'),
+ func=lambda context: index_instance_item_link(context['object'])
+ )
+ SourceColumn(
+ source=IndexInstanceNode, label=_('Items'),
+ func=lambda context: context['object'].get_item_count(
+ user=context['request'].user
+ )
+ )
+
+ SourceColumn(
+ source=DocumentIndexInstanceNode, label=_('Node'),
+ func=lambda context: get_breadcrumbs(
+ index_instance_node=context['object'], single_link=True,
+ )
+ )
+ SourceColumn(
+ source=DocumentIndexInstanceNode, label=_('Items'),
+ func=lambda context: context['object'].get_item_count(
+ user=context['request'].user
+ )
+ )
+
app.conf.CELERY_QUEUES.append(
Queue('indexing', Exchange('indexing'), routing_key='indexing'),
)
diff --git a/mayan/apps/document_indexing/models.py b/mayan/apps/document_indexing/models.py
index e9c3caa870..af276c14c4 100644
--- a/mayan/apps/document_indexing/models.py
+++ b/mayan/apps/document_indexing/models.py
@@ -1,5 +1,6 @@
-from __future__ import unicode_literals
+from __future__ import absolute_import, unicode_literals
+from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@@ -8,7 +9,10 @@ from django.utils.translation import ugettext, ugettext_lazy as _
from mptt.fields import TreeForeignKey
from mptt.models import MPTTModel
+from acls.models import AccessControlList
from documents.models import Document, DocumentType
+from documents.permissions import permission_document_view
+from permissions import Permission
from .managers import IndexManager, IndexInstanceNodeManager
@@ -58,7 +62,10 @@ class Index(models.Model):
return '#'
def save(self, *args, **kwargs):
- """Automatically create the root index template node"""
+ """
+ Automatically create the root index template node
+ """
+
super(Index, self).save(*args, **kwargs)
IndexTemplateNode.objects.get_or_create(parent=None, index=self)
@@ -67,15 +74,28 @@ class Index(models.Model):
[unicode(document_type) for document_type in self.document_types.all()] or ['None']
)
+ class Meta:
+ verbose_name = _('Index')
+ verbose_name_plural = _('Indexes')
+
+
+class IndexInstance(Index):
def get_instance_node_count(self):
try:
return self.instance_root.get_descendant_count()
except IndexInstanceNode.DoesNotExist:
return 0
+ def get_items_count(self, user):
+ try:
+ return self.instance_root.get_item_count(user=user)
+ except IndexInstanceNode.DoesNotExist:
+ return 0
+
class Meta:
- verbose_name = _('Index')
- verbose_name_plural = _('Indexes')
+ proxy = True
+ verbose_name = _('Index instance')
+ verbose_name_plural = _('Index instances')
@python_2_unicode_compatible
@@ -140,9 +160,6 @@ class IndexInstanceNode(MPTTModel):
def __str__(self):
return self.value
- def index(self):
- return self.index_template_node.index
-
def get_absolute_url(self):
return reverse('indexing:index_instance_node_view', args=[self.pk])
@@ -151,6 +168,38 @@ class IndexInstanceNode(MPTTModel):
# Convenience method for serializer
return self.get_children()
+ def index(self):
+ return self.index_template_node.index
+
+ def get_item_count(self, user):
+ if self.index_template_node.link_documents:
+ queryset = self.documents
+
+ try:
+ Permission.check_permissions(user, (permission_document_view,))
+ except PermissionDenied:
+ queryset = AccessControlList.objects.filter_by_access(
+ permission_document_view, user, queryset
+ )
+
+ return queryset.count()
+ else:
+ return self.get_children().count()
+
class Meta:
verbose_name = _('Index node instance')
verbose_name_plural = _('Indexes node instances')
+
+
+class DocumentIndexInstanceNodeManager(models.Manager):
+ def get_for(self, document):
+ return self.filter(documents=document)
+
+
+class DocumentIndexInstanceNode(IndexInstanceNode):
+ objects = DocumentIndexInstanceNodeManager()
+
+ class Meta:
+ proxy = True
+ verbose_name = _('Document index node instance')
+ verbose_name_plural = _('Document indexes node instances')
diff --git a/mayan/apps/document_indexing/views.py b/mayan/apps/document_indexing/views.py
index 5ee33dff18..e36cf9bf24 100644
--- a/mayan/apps/document_indexing/views.py
+++ b/mayan/apps/document_indexing/views.py
@@ -11,7 +11,6 @@ from django.utils.html import mark_safe
from django.utils.translation import ugettext_lazy as _
from acls.models import AccessControlList
-from common.utils import encapsulate
from common.views import (
AssignRemoveView, SingleObjectCreateView, SingleObjectDeleteView,
SingleObjectEditView, SingleObjectListView
@@ -23,7 +22,10 @@ from documents.views import DocumentListView
from permissions import Permission
from .forms import IndexTemplateNodeForm
-from .models import Index, IndexInstanceNode, IndexTemplateNode
+from .models import (
+ DocumentIndexInstanceNode, Index, IndexInstance, IndexInstanceNode,
+ IndexTemplateNode
+)
from .permissions import (
permission_document_indexing_create, permission_document_indexing_delete,
permission_document_indexing_edit,
@@ -49,17 +51,8 @@ class SetupIndexListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'title': _('Indexes'),
'hide_object': True,
- 'extra_columns': [
- {'name': _('Label'), 'attribute': 'label'},
- {'name': _('Slug'), 'attribute': 'slug'},
- {
- 'name': _('Enabled'), 'attribute': encapsulate(
- lambda x: two_state_template(x.enabled)
- )
- },
- ]
+ 'title': _('Indexes'),
}
@@ -71,8 +64,8 @@ class SetupIndexEditView(SingleObjectEditView):
def get_extra_context(self):
return {
- 'title': _('Edit index: %s') % self.get_object(),
'object': self.get_object(),
+ 'title': _('Edit index: %s') % self.get_object(),
}
@@ -83,8 +76,8 @@ class SetupIndexDeleteView(SingleObjectDeleteView):
def get_extra_context(self):
return {
- 'title': _('Delete the index: %s?') % self.get_object(),
'object': self.get_object(),
+ 'title': _('Delete the index: %s?') % self.get_object(),
}
@@ -99,23 +92,6 @@ class SetupIndexTreeTemplateListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'extra_columns': (
- {
- 'name': _('Level'), 'attribute': encapsulate(
- lambda node: node_level(node)
- )
- },
- {
- 'name': _('Enabled'), 'attribute': encapsulate(
- lambda node: two_state_template(node.enabled)
- )
- },
- {
- 'name': _('Has document links?'), 'attribute': encapsulate(
- lambda node: two_state_template(node.link_documents)
- )
- },
- ),
'hide_object': True,
'index': self.get_index(),
'navigation_object_list': ('index',),
@@ -276,54 +252,17 @@ def template_node_delete(request, node_pk):
class IndexListView(SingleObjectListView):
- @staticmethod
- def get_items_count(instance):
- try:
- if instance.template_root.link_documents:
- return instance.instance_root.documents.count()
- else:
- return instance.instance_root.get_children().count()
- except IndexInstanceNode.DoesNotExist:
- return 0
-
- queryset = Index.objects.filter(enabled=True)
object_permission = permission_document_indexing_view
+ queryset = IndexInstance.objects.filter(enabled=True)
def get_extra_context(self):
return {
- 'title': _('Indexes'),
'hide_links': True,
- 'extra_columns': [
- {
- 'name': _('Items'), 'attribute': encapsulate(
- lambda instance: IndexListView.get_items_count(instance)
- )
- },
- {
- 'name': _('Document types'),
- 'attribute': 'get_document_types_names'
- },
- ],
+ 'title': _('Indexes'),
}
class IndexInstanceNodeView(DocumentListView, SingleObjectListView):
- @staticmethod
- def get_item_count(instance, user):
- if instance.index_template_node.link_documents:
- queryset = instance.documents
-
- try:
- Permission.check_permissions(user, (permission_document_view,))
- except PermissionDenied:
- queryset = AccessControlList.objects.filter_by_access(
- permission_document_view, user, queryset
- )
-
- return queryset.count()
- else:
- return instance.get_children().count()
-
def dispatch(self, request, *args, **kwargs):
self.index_instance = get_object_or_404(
IndexInstanceNode, pk=self.kwargs['pk']
@@ -371,25 +310,7 @@ class IndexInstanceNodeView(DocumentListView, SingleObjectListView):
}
if self.index_instance and not self.index_instance.index_template_node.link_documents:
- context.update(
- {
- 'extra_columns': [
- {
- 'name': _('Node'),
- 'attribute': encapsulate(
- lambda x: index_instance_item_link(x)
- )
- },
- {
- 'name': _('Items'),
- 'attribute': encapsulate(
- lambda instance: IndexInstanceNodeView.get_item_count(instance=instance, user=self.request.user)
- )
- }
- ],
- 'hide_object': True,
- }
- )
+ context.update({'hide_object': True})
return context
@@ -446,16 +367,6 @@ class DocumentIndexNodeListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'extra_columns': (
- {
- 'name': _('Node'),
- 'attribute': encapsulate(
- lambda node: get_breadcrumbs(
- index_instance_node=node, single_link=True, include_count=True
- )
- )
- },
- ),
'hide_object': True,
'object': self.get_document(),
'title': _(
@@ -464,4 +375,4 @@ class DocumentIndexNodeListView(SingleObjectListView):
}
def get_queryset(self):
- return self.get_document().node_instances.all()
+ return DocumentIndexInstanceNode.objects.get_for(self.get_document())
diff --git a/mayan/apps/document_indexing/widgets.py b/mayan/apps/document_indexing/widgets.py
index 6629af0be6..aafaa2fc50 100644
--- a/mayan/apps/document_indexing/widgets.py
+++ b/mayan/apps/document_indexing/widgets.py
@@ -7,22 +7,6 @@ from django.utils.translation import ugettext
from .models import IndexInstanceNode
-def index_instance_item_link(index_instance_item):
- if isinstance(index_instance_item, IndexInstanceNode):
- if index_instance_item.index_template_node.link_documents:
- icon_template = ''
- else:
- icon_template = ''
- else:
- icon_template = ''
-
- return mark_safe('%(icon_template)s %(text)s' % {
- 'url': index_instance_item.get_absolute_url(),
- 'icon_template': icon_template,
- 'text': index_instance_item
- })
-
-
def get_instance_link(index_instance_node, text=None, simple=False):
"""
Return an HTML anchor to an index instance
@@ -75,6 +59,22 @@ def get_breadcrumbs(index_instance_node, simple=False, single_link=False, includ
return mark_safe(' '.join(output))
+def index_instance_item_link(index_instance_item):
+ if isinstance(index_instance_item, IndexInstanceNode):
+ if index_instance_item.index_template_node.link_documents:
+ icon_template = ''
+ else:
+ icon_template = ''
+ else:
+ icon_template = ''
+
+ return mark_safe('%(icon_template)s %(text)s' % {
+ 'url': index_instance_item.get_absolute_url(),
+ 'icon_template': icon_template,
+ 'text': index_instance_item
+ })
+
+
def node_level(node):
"""
Render an indented tree like output for a specific node
diff --git a/mayan/apps/document_states/apps.py b/mayan/apps/document_states/apps.py
index 4ec4b24a83..1daee7de10 100644
--- a/mayan/apps/document_states/apps.py
+++ b/mayan/apps/document_states/apps.py
@@ -7,7 +7,6 @@ from common import (
MayanAppConfig, menu_facet, menu_object, menu_secondary, menu_setup,
menu_sidebar
)
-from common.utils import encapsulate
from common.widgets import two_state_template
from documents.models import Document
from navigation import SourceColumn
@@ -39,9 +38,7 @@ class DocumentStatesApp(MayanAppConfig):
SourceColumn(
source=Workflow, label=_('Initial state'),
- attribute=encapsulate(
- lambda workflow: workflow.get_initial_state() or _('None')
- )
+ func=lambda context: context['object'].get_initial_state() or _('None')
)
SourceColumn(
@@ -50,10 +47,8 @@ class DocumentStatesApp(MayanAppConfig):
)
SourceColumn(
source=WorkflowInstance, label=_('User'),
- attribute=encapsulate(
- lambda workflow: getattr(
- workflow.get_last_log_entry(), 'user', _('None')
- )
+ func=lambda context: getattr(
+ context['object'].get_last_log_entry(), 'user', _('None')
)
)
SourceColumn(
@@ -62,16 +57,14 @@ class DocumentStatesApp(MayanAppConfig):
)
SourceColumn(
source=WorkflowInstance, label=_('Date and time'),
- attribute=encapsulate(
- lambda workflow: getattr(
- workflow.get_last_log_entry(), 'datetime', _('None')
- )
+ func=lambda context: getattr(
+ context['object'].get_last_log_entry(), 'datetime', _('None')
)
)
SourceColumn(
source=WorkflowInstance, label=_('Completion'),
- attribute=encapsulate(lambda workflow: getattr(
- workflow.get_current_state(), 'completion', _('None'))
+ func=lambda context: getattr(
+ context['object'].get_current_state(), 'completion', _('None')
)
)
@@ -93,9 +86,7 @@ class DocumentStatesApp(MayanAppConfig):
SourceColumn(
source=WorkflowState, label=_('Is initial state?'),
- attribute=encapsulate(
- lambda state: two_state_template(state.initial)
- )
+ func=lambda context: two_state_template(context['object'].initial)
)
SourceColumn(
source=WorkflowState, label=_('Completion'), attribute='completion'
diff --git a/mayan/apps/documents/apps.py b/mayan/apps/documents/apps.py
index e0e19146ea..e2d077bbbd 100644
--- a/mayan/apps/documents/apps.py
+++ b/mayan/apps/documents/apps.py
@@ -17,7 +17,7 @@ from common import (
)
from common.classes import ModelAttribute
from common.signals import post_initial_setup
-from common.utils import encapsulate
+from common.widgets import two_state_template
from converter.links import link_transformation_list
from converter.permissions import (
permission_transformation_create,
@@ -125,17 +125,27 @@ class DocumentsApp(MayanAppConfig):
SourceColumn(
source=Document, label=_('Thumbnail'),
- attribute=encapsulate(
- lambda document: document_thumbnail(
- document, gallery_name='documents:document_list',
- size=setting_thumbnail_size.value,
- title=getattr(document, 'label', None),
- )
+ func=lambda context: document_thumbnail(
+ context['object'], gallery_name='documents:document_list',
+ size=setting_thumbnail_size.value,
+ title=getattr(context['object'], 'label', None),
)
)
SourceColumn(
source=Document, label=_('Type'), attribute='document_type'
)
+
+ # TODO: make permission aware
+ SourceColumn(
+ source=DocumentType, label=_('Documents'),
+ func=lambda context: context['object'].documents.count()
+ )
+
+ SourceColumn(
+ source=DocumentTypeFilename, label=_('Enabled'),
+ func=lambda context: two_state_template(context['object'].enabled)
+ )
+
SourceColumn(
source=DeletedDocument, label=_('Type'), attribute='document_type'
)
@@ -144,6 +154,23 @@ class DocumentsApp(MayanAppConfig):
attribute='deleted_date_time'
)
+ SourceColumn(
+ source=DocumentVersion, label=_('Time and date'),
+ attribute='timestamp'
+ )
+ SourceColumn(
+ source=DocumentVersion, label=_('MIME type'),
+ attribute='mimetype'
+ )
+ SourceColumn(
+ source=DocumentVersion, label=_('Encoding'),
+ attribute='encoding'
+ )
+ SourceColumn(
+ source=DocumentVersion, label=_('Comment'),
+ attribute='comment'
+ )
+
app.conf.CELERYBEAT_SCHEDULE.update(
{
'task_check_delete_periods': {
diff --git a/mayan/apps/documents/views.py b/mayan/apps/documents/views.py
index 8b4daa76d7..5afa5777f9 100644
--- a/mayan/apps/documents/views.py
+++ b/mayan/apps/documents/views.py
@@ -954,9 +954,6 @@ class DocumentTypeListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'extra_columns': [
- {'name': _('Documents'), 'attribute': encapsulate(lambda document_type: document_type.documents.count())}
- ],
'hide_link': True,
'title': _('Document types'),
}
@@ -1010,12 +1007,6 @@ class DocumentTypeFilenameListView(SingleObjectListView):
def get_extra_context(self):
return {
'document_type': self.get_document_type(),
- 'extra_columns': (
- {
- 'name': _('Enabled'),
- 'attribute': encapsulate(lambda filename: two_state_template(filename.enabled)),
- },
- ),
'hide_link': True,
'navigation_object_list': ('document_type',),
'title': _('Filenames for document type: %s') % self.get_document_type(),
@@ -1148,12 +1139,7 @@ class DocumentVersionListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'extra_columns': (
- {'name': _('Time and date'), 'attribute': 'timestamp'},
- {'name': _('MIME type'), 'attribute': 'mimetype'},
- {'name': _('Encoding'), 'attribute': 'encoding'},
- {'name': _('Comment'), 'attribute': 'comment'},
- ), 'hide_object': True, 'object': self.get_document(),
+ 'hide_object': True, 'object': self.get_document(),
'title': _('Versions of document: %s') % self.get_document(),
}
diff --git a/mayan/apps/events/apps.py b/mayan/apps/events/apps.py
index b527aaf87b..28637755c0 100644
--- a/mayan/apps/events/apps.py
+++ b/mayan/apps/events/apps.py
@@ -5,7 +5,6 @@ from django.utils.translation import ugettext_lazy as _
from actstream.models import Action
from common import MayanAppConfig, menu_tools
-from common.utils import encapsulate
from navigation import SourceColumn
from .links import link_events_list
@@ -21,8 +20,8 @@ class EventsApp(MayanAppConfig):
SourceColumn(source=Action, label=_('Timestamp'), attribute='timestamp')
SourceColumn(source=Action, label=_('Actor'), attribute='actor')
- SourceColumn(source=Action, label=_('Verb'), attribute=encapsulate(
- lambda entry: event_type_link(entry))
+ SourceColumn(source=Action, label=_('Verb'),
+ func=lambda context: event_type_link(context['object'])
)
menu_tools.bind_links(links=[link_events_list])
diff --git a/mayan/apps/events/views.py b/mayan/apps/events/views.py
index 86574fa494..201e39e203 100644
--- a/mayan/apps/events/views.py
+++ b/mayan/apps/events/views.py
@@ -26,14 +26,14 @@ class EventListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'extra_columns': [
+ 'extra_columns': (
{
'name': _('Target'),
'attribute': encapsulate(
lambda entry: event_object_link(entry)
)
- }
- ],
+ },
+ ),
'hide_object': True,
'title': _('Events'),
}
@@ -85,14 +85,14 @@ class VerbEventListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'extra_columns': [
+ 'extra_columns': (
{
'name': _('Target'),
'attribute': encapsulate(
lambda entry: event_object_link(entry)
)
- }
- ],
+ },
+ ),
'hide_object': True,
'title': _(
'Events of type: %s'
diff --git a/mayan/apps/folders/apps.py b/mayan/apps/folders/apps.py
index 6c74bd2824..b21f32b534 100644
--- a/mayan/apps/folders/apps.py
+++ b/mayan/apps/folders/apps.py
@@ -56,6 +56,12 @@ class FoldersApp(MayanAppConfig):
source=Folder, label=_('Created'), attribute='datetime_created'
)
SourceColumn(source=Folder, label=_('User'), attribute='user')
+ SourceColumn(
+ source=Folder, label=_('Documents'),
+ func=lambda context: context['object'].get_document_count(
+ user=context['request'].user
+ )
+ )
menu_facet.bind_links(
links=(link_document_folder_list,), sources=(Document,)
diff --git a/mayan/apps/folders/models.py b/mayan/apps/folders/models.py
index a2127c573a..007313cfad 100644
--- a/mayan/apps/folders/models.py
+++ b/mayan/apps/folders/models.py
@@ -1,12 +1,16 @@
-from __future__ import unicode_literals
+from __future__ import absolute_import, unicode_literals
from django.contrib.auth.models import User
+from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
+from acls.models import AccessControlList
from documents.models import Document
+from documents.permissions import permission_document_view
+from permissions import Permission
@python_2_unicode_compatible
@@ -28,6 +32,18 @@ class Folder(models.Model):
def get_absolute_url(self):
return reverse('folders:folder_view', args=[self.pk])
+ def get_document_count(self, user):
+ queryset = self.documents
+
+ try:
+ Permission.check_permissions(user, (permission_document_view,))
+ except PermissionDenied:
+ queryset = AccessControlList.objects.filter_by_access(
+ permission_document_view, user, queryset
+ )
+
+ return queryset.count()
+
class Meta:
ordering = ('label',)
unique_together = ('label', 'user')
diff --git a/mayan/apps/folders/views.py b/mayan/apps/folders/views.py
index 248d75f9e7..956e38e84c 100644
--- a/mayan/apps/folders/views.py
+++ b/mayan/apps/folders/views.py
@@ -12,7 +12,6 @@ from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _, ungettext
from acls.models import AccessControlList
-from common.utils import encapsulate
from common.views import (
SingleObjectCreateView, SingleObjectEditView, SingleObjectListView
)
@@ -48,31 +47,8 @@ class FolderEditView(SingleObjectEditView):
class FolderListView(SingleObjectListView):
object_permission = permission_folder_view
- @staticmethod
- def get_document_count(instance, user):
- queryset = instance.documents
-
- try:
- Permission.check_permissions(user, (permission_document_view,))
- except PermissionDenied:
- queryset = AccessControlList.objects.filter_by_access(
- permission_document_view, user, queryset
- )
-
- return queryset.count()
-
def get_extra_context(self):
return {
- 'extra_columns': [
- {
- 'name': _('Documents'),
- 'attribute': encapsulate(
- lambda instance: FolderListView.get_document_count(
- instance=instance, user=self.request.user
- )
- )
- },
- ],
'hide_link': True,
'title': _('Folders'),
}
@@ -253,16 +229,6 @@ class DocumentFolderListView(FolderListView):
def get_extra_context(self):
return {
- 'extra_columns': [
- {
- 'name': _('Documents'),
- 'attribute': encapsulate(
- lambda instance: FolderListView.get_document_count(
- instance=instance, user=self.request.user
- )
- )
- },
- ],
'hide_link': True,
'object': self.document,
'title': _('Folders containing document: %s') % self.document,
diff --git a/mayan/apps/installation/apps.py b/mayan/apps/installation/apps.py
index 1082417e2a..a5ae30bf39 100644
--- a/mayan/apps/installation/apps.py
+++ b/mayan/apps/installation/apps.py
@@ -3,7 +3,6 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from common import MayanAppConfig, menu_tools, menu_object, menu_secondary
-from common.utils import encapsulate
from navigation import SourceColumn
from .classes import Property, PropertyNamespace, PIPNotFound, VirtualEnv
@@ -24,7 +23,7 @@ class InstallationApp(MayanAppConfig):
)
SourceColumn(
source=PropertyNamespace, label=_('Items'),
- attribute=encapsulate(lambda entry: len(entry.get_properties()))
+ func=lambda context: len(context['object'].get_properties())
)
SourceColumn(source=Property, label=_('Label'), attribute='label')
diff --git a/mayan/apps/linking/apps.py b/mayan/apps/linking/apps.py
index 4b4a8f3773..7643a1e52d 100644
--- a/mayan/apps/linking/apps.py
+++ b/mayan/apps/linking/apps.py
@@ -9,7 +9,9 @@ from common import (
MayanAppConfig, menu_facet, menu_object, menu_secondary, menu_setup,
menu_sidebar
)
+from common.widgets import two_state_template
from documents.models import Document
+from navigation import SourceColumn
from .links import (
link_smart_link_create, link_smart_link_condition_create,
@@ -41,6 +43,26 @@ class LinkingApp(MayanAppConfig):
)
)
+ SourceColumn(
+ source=ResolvedSmartLink, label=_('Label'),
+ func=lambda context: context['object'].get_dynamic_label(
+ context['resolved_object']
+ )
+ )
+
+ SourceColumn(
+ source=SmartLink, label=_('Dynamic label'), attribute='dynamic_label'
+ )
+ SourceColumn(
+ source=SmartLink, label=_('Enabled'),
+ func=lambda context: two_state_template(context['object'].enabled)
+ )
+
+ SourceColumn(
+ source=SmartLinkCondition, label=_('Enabled'),
+ func=lambda context: two_state_template(context['object'].enabled)
+ )
+
menu_facet.bind_links(
links=(link_smart_link_instances_for_document,),
sources=(Document,)
diff --git a/mayan/apps/linking/views.py b/mayan/apps/linking/views.py
index fb6f21773a..171961bd54 100644
--- a/mayan/apps/linking/views.py
+++ b/mayan/apps/linking/views.py
@@ -12,7 +12,6 @@ from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _
from acls.models import AccessControlList
-from common.utils import encapsulate
from common.generics import (
AssignRemoveView, SingleObjectCreateView, SingleObjectEditView,
SingleObjectListView
@@ -145,14 +144,6 @@ class SmartLinkListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'extra_columns': [
- {'name': _('Dynamic label'), 'attribute': 'dynamic_label'},
- {
- 'name': _('Enabled'), 'attribute': encapsulate(
- lambda instance: two_state_template(instance.enabled)
- )
- },
- ],
'hide_link': True,
'title': _('Smart links'),
}
@@ -183,15 +174,6 @@ class DocumentSmartLinkListView(SmartLinkListView):
def get_extra_context(self):
return {
'document': self.document,
- 'extra_columns': (
- {
- 'name': _('Label'), 'attribute': encapsulate(
- lambda smart_link: smart_link.get_dynamic_label(
- self.document
- )
- )
- },
- ),
'hide_object': True,
'hide_link': True,
'object': self.document,
@@ -272,17 +254,9 @@ class SmartLinkConditionListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'title': _('Conditions for smart link: %s') % self.get_smart_link(),
- 'extra_columns': (
- {
- 'name': _('Enabled'),
- 'attribute': encapsulate(
- lambda condition: two_state_template(condition.enabled)
- )
- },
- ),
'hide_link': True,
'object': self.get_smart_link(),
+ 'title': _('Conditions for smart link: %s') % self.get_smart_link(),
}
def get_smart_link(self):
diff --git a/mayan/apps/mailer/apps.py b/mayan/apps/mailer/apps.py
index 64575a074b..158788e176 100644
--- a/mayan/apps/mailer/apps.py
+++ b/mayan/apps/mailer/apps.py
@@ -28,15 +28,11 @@ class MailerApp(MayanAppConfig):
super(MailerApp, self).ready()
SourceColumn(
- source=LogEntry,
- label='Date and time',
- attribute='datetime'
+ source=LogEntry, label=_('Date and time'), attribute='datetime'
)
SourceColumn(
- source=LogEntry,
- label='Message',
- attribute='message'
+ source=LogEntry, label=_('Message'), attribute='message'
)
ModelPermission.register(
diff --git a/mayan/apps/metadata/apps.py b/mayan/apps/metadata/apps.py
index 76e60071bd..49b620f1b4 100644
--- a/mayan/apps/metadata/apps.py
+++ b/mayan/apps/metadata/apps.py
@@ -13,7 +13,7 @@ from common import (
menu_setup, menu_sidebar, menu_tools
)
from common.classes import ModelAttribute
-from common.utils import encapsulate
+from common.widgets import two_state_template
from documents.models import Document, DocumentType
from documents.search import document_search
from documents.signals import post_document_type_change
@@ -38,7 +38,7 @@ from .links import (
link_setup_metadata_type_edit, link_setup_metadata_type_list,
link_documents_missing_required_metadata
)
-from .models import DocumentTypeMetadataType, MetadataType
+from .models import DocumentMetadata, DocumentTypeMetadataType, MetadataType
from .permissions import (
permission_metadata_document_add, permission_metadata_document_edit,
permission_metadata_document_remove, permission_metadata_document_view
@@ -94,9 +94,16 @@ class MetadataApp(MayanAppConfig):
SourceColumn(
source=Document, label=_('Metadata'),
- attribute=encapsulate(
- lambda document: get_metadata_string(document)
- )
+ func=lambda context: get_metadata_string(context['object'])
+ )
+
+ SourceColumn(
+ source=DocumentMetadata, label=_('Value'),
+ attribute='value'
+ )
+ SourceColumn(
+ source=DocumentMetadata, label=_('Required'),
+ func=lambda context: two_state_template(context['object'].is_required)
)
app.conf.CELERY_QUEUES.append(
diff --git a/mayan/apps/metadata/models.py b/mayan/apps/metadata/models.py
index c4bb1b831b..75929a8552 100644
--- a/mayan/apps/metadata/models.py
+++ b/mayan/apps/metadata/models.py
@@ -103,6 +103,10 @@ class DocumentMetadata(models.Model):
return super(DocumentMetadata, self).delete(*args, **kwargs)
+ @property
+ def is_required(self):
+ return self.metadata_type in self.document.document_type.metadata.filter(required=True)
+
class Meta:
unique_together = ('document', 'metadata_type')
verbose_name = _('Document metadata')
diff --git a/mayan/apps/metadata/views.py b/mayan/apps/metadata/views.py
index 35cb5aabe5..66673da4c1 100644
--- a/mayan/apps/metadata/views.py
+++ b/mayan/apps/metadata/views.py
@@ -11,7 +11,6 @@ from django.utils.http import urlencode
from django.utils.translation import ugettext_lazy as _, ungettext
from acls.models import AccessControlList
-from common.utils import encapsulate
from common.generics import (
AssignRemoveView, SingleObjectCreateView, SingleObjectDeleteView,
SingleObjectEditView, SingleObjectListView
@@ -495,18 +494,9 @@ class DocumentMetadataListView(SingleObjectListView):
def get_extra_context(self):
document = self.get_document()
return {
- 'title': _('Metadata for document: %s') % document,
- 'extra_columns': (
- {'name': _('Value'), 'attribute': 'value'},
- {
- 'name': _('Required'),
- 'attribute': encapsulate(
- lambda metadata: metadata.metadata_type in document.document_type.metadata.filter(required=True)
- )
- }
- ),
'hide_link': True,
'object': document,
+ 'title': _('Metadata for document: %s') % document,
}
def get_queryset(self):
diff --git a/mayan/apps/navigation/classes.py b/mayan/apps/navigation/classes.py
index 0a580f53dc..9841c8b531 100644
--- a/mayan/apps/navigation/classes.py
+++ b/mayan/apps/navigation/classes.py
@@ -281,11 +281,13 @@ class SourceColumn(object):
# unhashable type: list
return ()
- def __init__(self, source, label, attribute):
+ def __init__(self, source, label, attribute=None, func=None):
+ self.source = source
+ self.label = label
+ self.attribute = attribute
+ self.func = func
self.__class__._registry.setdefault(source, [])
- self.__class__._registry[source].append(
- {'label': label, 'attribute': attribute}
- )
+ self.__class__._registry[source].append(self)
class CombinedSource(object):
diff --git a/mayan/apps/navigation/templatetags/navigation_tags.py b/mayan/apps/navigation/templatetags/navigation_tags.py
index dccb73187f..7b3c3b4a31 100644
--- a/mayan/apps/navigation/templatetags/navigation_tags.py
+++ b/mayan/apps/navigation/templatetags/navigation_tags.py
@@ -2,6 +2,8 @@ from __future__ import unicode_literals
from django.template import Library
+from common.utils import return_attrib
+
from ..classes import Menu, SourceColumn
from ..forms import MultiItemForm
@@ -58,3 +60,11 @@ def get_source_columns(source):
pass
return SourceColumn.get_for_source(source)
+
+
+@register.simple_tag(takes_context=True)
+def source_column_resolve(context, column):
+ if column.attribute:
+ return return_attrib(context['object'], column.attribute)
+ elif column.func:
+ return column.func(context=context)
diff --git a/mayan/apps/ocr/apps.py b/mayan/apps/ocr/apps.py
index e7013314b8..9d3cc2ffd7 100644
--- a/mayan/apps/ocr/apps.py
+++ b/mayan/apps/ocr/apps.py
@@ -13,7 +13,6 @@ from common import (
MayanAppConfig, menu_facet, menu_multi_item, menu_object, menu_secondary,
menu_tools
)
-from common.utils import encapsulate
from documents.models import Document, DocumentType, DocumentVersion
from documents.search import document_search
from documents.signals import post_version_upload
@@ -70,9 +69,7 @@ class OCRApp(MayanAppConfig):
SourceColumn(
source=DocumentVersionOCRError, label=_('Document'),
- attribute=encapsulate(
- lambda entry: document_link(entry.document_version.document)
- )
+ func=lambda context: document_link(context['object'].document_version.document)
)
SourceColumn(
source=DocumentVersionOCRError, label=_('Added'),
diff --git a/mayan/apps/smart_settings/apps.py b/mayan/apps/smart_settings/apps.py
index e16639d2db..cc347428dd 100644
--- a/mayan/apps/smart_settings/apps.py
+++ b/mayan/apps/smart_settings/apps.py
@@ -7,7 +7,6 @@ from django.apps import apps
from django.utils.translation import ugettext_lazy as _
from common import MayanAppConfig, menu_setup, menu_object
-from common.utils import encapsulate
from common.widgets import exists_widget
from navigation import SourceColumn
@@ -29,20 +28,20 @@ class SmartSettingsApp(MayanAppConfig):
SourceColumn(
source=Namespace, label=_('Setting count'),
- attribute=encapsulate(lambda instance: len(instance.settings))
+ func=lambda context: len(context['object'].settings)
)
SourceColumn(
source=Setting, label=_('Name'),
- attribute=encapsulate(lambda instance: setting_widget(instance))
+ func=lambda context: setting_widget(context['object'])
)
SourceColumn(
source=Setting, label=_('Value'), attribute='serialized_value'
)
SourceColumn(
source=Setting, label=_('Found in path'),
- attribute=encapsulate(
- lambda instance: exists_widget(instance.value) if instance.is_path else _('n/a')
- )
+ func=lambda context: exists_widget(
+ context['object'].value
+ ) if context['object'].is_path else _('n/a')
)
menu_object.bind_links(
diff --git a/mayan/apps/sources/apps.py b/mayan/apps/sources/apps.py
index e218560db0..96c879bbd0 100644
--- a/mayan/apps/sources/apps.py
+++ b/mayan/apps/sources/apps.py
@@ -9,7 +9,6 @@ from common import (
menu_sidebar, menu_setup
)
from common.signals import post_initial_setup, post_upgrade
-from common.utils import encapsulate
from converter.links import link_transformation_list
from documents.models import Document
from documents.signals import post_version_upload
@@ -32,8 +31,8 @@ from .links import (
link_upload_version
)
from .models import (
- POP3Email, IMAPEmail, Source, StagingFolderSource, WatchFolderSource,
- WebFormSource
+ POP3Email, IMAPEmail, Source, SourceLog, StagingFolderSource,
+ WatchFolderSource, WebFormSource
)
from .widgets import staging_file_thumbnail
@@ -61,15 +60,24 @@ class SourcesApp(MayanAppConfig):
SourceColumn(
source=StagingFile,
label=_('Thumbnail'),
- attribute=encapsulate(
- lambda staging_file: staging_file_thumbnail(
- staging_file,
- gallery_name='sources:staging_list',
- title=staging_file.filename, size='100'
- )
+ func=lambda context: staging_file_thumbnail(
+ context['object'],
+ gallery_name='sources:staging_list',
+ title=context['object'].filename, size='100'
)
)
+ SourceColumn(
+ source=SourceLog,
+ label=_('Date time'),
+ func=lambda context: context['object'].datetime
+ )
+ SourceColumn(
+ source=SourceLog,
+ label=_('Message'),
+ func=lambda context: context['object'].message
+ )
+
app.conf.CELERY_QUEUES.extend(
(
Queue(
diff --git a/mayan/apps/sources/views.py b/mayan/apps/sources/views.py
index 066f2a7aed..5daa981b8a 100644
--- a/mayan/apps/sources/views.py
+++ b/mayan/apps/sources/views.py
@@ -58,16 +58,6 @@ class SourceLogListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'extra_columns': (
- {
- 'name': _('Date time'),
- 'attribute': encapsulate(lambda entry: entry.datetime)
- },
- {
- 'name': _('Message'),
- 'attribute': encapsulate(lambda entry: entry.message)
- },
- ),
'hide_object': True,
'object': self.get_source(),
'title': _('Log entries for source: %s') % self.get_source(),
@@ -494,7 +484,7 @@ class SetupSourceListView(SingleObjectListView):
queryset = Source.objects.select_subclasses()
extra_context = {
- 'extra_columns': [
+ 'extra_columns': (
{
'name': _('Type'),
'attribute': encapsulate(lambda entry: entry.class_fullname())
@@ -505,7 +495,7 @@ class SetupSourceListView(SingleObjectListView):
lambda entry: two_state_template(entry.enabled)
)
},
- ],
+ ),
'hide_link': True,
'title': _('Sources'),
}
diff --git a/mayan/apps/tags/apps.py b/mayan/apps/tags/apps.py
index 4563497502..73dd50f04e 100644
--- a/mayan/apps/tags/apps.py
+++ b/mayan/apps/tags/apps.py
@@ -9,7 +9,6 @@ from common import (
MayanAppConfig, menu_facet, menu_secondary, menu_object, menu_main,
menu_multi_item, menu_sidebar
)
-from common.utils import encapsulate
from documents.models import Document
from documents.search import document_search
from navigation import CombinedSource, SourceColumn
@@ -55,14 +54,18 @@ class TagsApp(MayanAppConfig):
SourceColumn(
source=Document, label=_('Tags'),
- attribute=encapsulate(
- lambda document: widget_inline_tags(document)
- )
+ func=lambda context: widget_inline_tags(context['object'])
)
SourceColumn(
source=Tag, label=_('Preview'),
- attribute=encapsulate(lambda tag: widget_single_tag(tag))
+ func=lambda context: widget_single_tag(context['object'])
+ )
+ SourceColumn(
+ source=Tag, label=_('Documents'),
+ func=lambda context: context['object'].get_document_count(
+ user=context['request'].user
+ )
)
document_search.add_model_field(field='tags__label', label=_('Tags'))
diff --git a/mayan/apps/tags/models.py b/mayan/apps/tags/models.py
index 33bfc5996b..79f2f2b128 100644
--- a/mayan/apps/tags/models.py
+++ b/mayan/apps/tags/models.py
@@ -1,12 +1,16 @@
-from __future__ import unicode_literals
+from __future__ import absolute_import, unicode_literals
from django.db import models
+from django.core.exceptions import PermissionDenied
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from colorful.fields import RGBColorField
+from acls.models import AccessControlList
from documents.models import Document
+from documents.permissions import permission_document_view
+from permissions import Permission
@python_2_unicode_compatible
@@ -25,3 +29,15 @@ class Tag(models.Model):
def __str__(self):
return self.label
+
+ def get_document_count(self, user):
+ queryset = self.documents
+
+ try:
+ Permission.check_permissions(user, (permission_document_view,))
+ except PermissionDenied:
+ queryset = AccessControlList.objects.filter_by_access(
+ permission_document_view, user, queryset
+ )
+
+ return queryset.count()
diff --git a/mayan/apps/tags/views.py b/mayan/apps/tags/views.py
index 13af4e7766..16bef84245 100644
--- a/mayan/apps/tags/views.py
+++ b/mayan/apps/tags/views.py
@@ -12,7 +12,6 @@ from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _, ungettext
from acls.models import AccessControlList
-from common.utils import encapsulate
from common.views import (
SingleObjectCreateView, SingleObjectEditView, SingleObjectListView
)
@@ -126,33 +125,9 @@ def tag_multiple_attach(request):
class TagListView(SingleObjectListView):
object_permission = permission_tag_view
- @staticmethod
- def get_document_count(instance, user):
- queryset = instance.documents
-
- try:
- Permission.check_permissions(user, (permission_document_view,))
- except PermissionDenied:
- queryset = AccessControlList.objects.filter_by_access(
- permission_document_view, user, queryset
- )
-
- return queryset.count()
-
def get_extra_context(self):
return {
- 'extra_columns': (
- {
- 'name': _('Documents'),
- 'attribute': encapsulate(
- lambda instance: TagListView.get_document_count(
- instance=instance, user=self.request.user
- )
- )
- },
- ),
'hide_link': True,
-
'title': _('Tags'),
}
@@ -282,16 +257,6 @@ class DocumentTagListView(TagListView):
def get_extra_context(self):
return {
- 'extra_columns': [
- {
- 'name': _('Documents'),
- 'attribute': encapsulate(
- lambda instance: TagListView.get_document_count(
- instance=instance, user=self.request.user
- )
- )
- },
- ],
'hide_link': True,
'object': self.document,
'title': _('Tags for document: %s') % self.document,
diff --git a/mayan/apps/user_management/apps.py b/mayan/apps/user_management/apps.py
index e730fb773c..d5d09d7e91 100644
--- a/mayan/apps/user_management/apps.py
+++ b/mayan/apps/user_management/apps.py
@@ -8,7 +8,9 @@ from actstream import registry
from common import menu_multi_item, menu_object, menu_secondary, menu_setup
from common.apps import MayanAppConfig
+from common.widgets import two_state_template
from metadata import MetadataLookup
+from navigation import SourceColumn
from rest_api.classes import APIEndPoint
from .links import (
@@ -33,6 +35,25 @@ class UserManagementApp(MayanAppConfig):
MetadataLookup(description=_('All the groups.'), name='group', value=Group.objects.all())
MetadataLookup(description=_('All the users.'), name='users', value=get_user_model().objects.all())
+ SourceColumn(
+ source=Group, label=_('Members'), attribute='user_set.count'
+ )
+
+ SourceColumn(
+ source=User, label=_('Full name'), attribute='get_full_name'
+ )
+ SourceColumn(
+ source=User, label=_('Email'), attribute='email'
+ )
+ SourceColumn(
+ source=User, label=_('Active'),
+ func=lambda context: two_state_template(context['object'].is_active)
+ )
+ SourceColumn(
+ source=User, label=_('Has usable password?'),
+ func=lambda context: two_state_template(context['object'].has_usable_password())
+ )
+
menu_multi_item.bind_links(
links=(link_group_multiple_delete,),
sources=('user_management:group_list',)
diff --git a/mayan/apps/user_management/views.py b/mayan/apps/user_management/views.py
index 783d8090a9..1df5c113c2 100644
--- a/mayan/apps/user_management/views.py
+++ b/mayan/apps/user_management/views.py
@@ -10,7 +10,6 @@ from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _
-from common.utils import encapsulate
from common.views import (
AssignRemoveView, SingleObjectCreateView, SingleObjectEditView,
SingleObjectListView
@@ -31,30 +30,6 @@ class UserListView(SingleObjectListView):
def get_extra_context(self):
return {
- 'extra_columns': (
- {
- 'name': _('Full name'),
- 'attribute': 'get_full_name'
- },
- {
- 'name': _('Email'),
- 'attribute': 'email'
- },
- {
- 'name': _('Active'),
- 'attribute': encapsulate(
- lambda user: two_state_template(user.is_active)
- ),
- },
- {
- 'name': _('Has usable password?'),
- 'attribute': encapsulate(
- lambda user: two_state_template(
- user.has_usable_password()
- )
- ),
- },
- ),
'hide_link': True,
'title': _('Users'),
}
@@ -301,8 +276,8 @@ class GroupEditView(SingleObjectEditView):
class GroupListView(SingleObjectListView):
extra_context = {
- 'title': _('Groups'),
'hide_link': True,
+ 'title': _('Groups'),
'extra_columns': [
{
'name': _('Members'),