Improve SourceColumn workflow by allowing explicit functions as columns. Remove usage of encapsulate. Move instances of 'extra_columns' to SourceColumn.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
{% endif %}
|
||||
{% if not hide_columns %}
|
||||
{% for column in object|get_source_columns %}
|
||||
<td>{{ object|object_property:column.attribute }}</td>
|
||||
<td>{% source_column_resolve column=column %}</td>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% for column in extra_columns %}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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,))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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'),
|
||||
)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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 = '<i class="fa fa-folder"></i>'
|
||||
else:
|
||||
icon_template = '<i class="fa fa-level-up fa-rotate-90"></i>'
|
||||
else:
|
||||
icon_template = ''
|
||||
|
||||
return mark_safe('%(icon_template)s <a href="%(url)s">%(text)s</a>' % {
|
||||
'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 = '<i class="fa fa-folder"></i>'
|
||||
else:
|
||||
icon_template = '<i class="fa fa-level-up fa-rotate-90"></i>'
|
||||
else:
|
||||
icon_template = ''
|
||||
|
||||
return mark_safe('%(icon_template)s <a href="%(url)s">%(text)s</a>' % {
|
||||
'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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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',
|
||||
func=lambda context: document_thumbnail(
|
||||
context['object'], gallery_name='documents:document_list',
|
||||
size=setting_thumbnail_size.value,
|
||||
title=getattr(document, 'label', None),
|
||||
)
|
||||
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': {
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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,)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,13 +60,22 @@ class SourcesApp(MayanAppConfig):
|
||||
SourceColumn(
|
||||
source=StagingFile,
|
||||
label=_('Thumbnail'),
|
||||
attribute=encapsulate(
|
||||
lambda staging_file: staging_file_thumbnail(
|
||||
staging_file,
|
||||
func=lambda context: staging_file_thumbnail(
|
||||
context['object'],
|
||||
gallery_name='sources:staging_list',
|
||||
title=staging_file.filename, size='100'
|
||||
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(
|
||||
|
||||
@@ -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'),
|
||||
}
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',)
|
||||
|
||||
@@ -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'),
|
||||
|
||||
Reference in New Issue
Block a user