Refactor the tags app
Remove the widget from the model. Add keyword arguments. Separate form widgets from html widgets. HTML widgets now go in the html_widgets module. Update the TagMultipleSelectionForm class to be a subclass of FilteredSelectionForm. Move Select2 specific JavaScript from the appearence app to the tags app. Update tag attachment and removal view names. Modernize tests. Add more tests. Consolidate repeated test code into test mixins. Update views to comply with MERCs 5 and 6. Use uniform nomeclature for URLs. Update URLs parameters to use the '_id' form. Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
@@ -8,10 +8,10 @@ class MayanApp {
|
|||||||
ajaxMenusOptions: []
|
ajaxMenusOptions: []
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ajaxSpinnerSeletor = '#ajax-spinner';
|
|
||||||
this.ajaxExecuting = false;
|
this.ajaxExecuting = false;
|
||||||
this.ajaxMenusOptions = options.ajaxMenusOptions;
|
this.ajaxMenusOptions = options.ajaxMenusOptions;
|
||||||
this.ajaxMenuHashes = {};
|
this.ajaxMenuHashes = {};
|
||||||
|
this.ajaxSpinnerSeletor = '#ajax-spinner';
|
||||||
this.window = $(window);
|
this.window = $(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,22 +81,6 @@ class MayanApp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static tagSelectionTemplate (tag, container) {
|
|
||||||
var $tag = $(
|
|
||||||
'<span class="label label-tag" style="background: ' + tag.element.dataset.color + ';"> ' + tag.text + '</span>'
|
|
||||||
);
|
|
||||||
container[0].style.background = tag.element.dataset.color;
|
|
||||||
return $tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
static tagResultTemplate (tag) {
|
|
||||||
if (!tag.element) { return ''; }
|
|
||||||
var $tag = $(
|
|
||||||
'<span class="label label-tag" style="background: ' + tag.element.dataset.color + ';"> ' + tag.text + '</span>'
|
|
||||||
);
|
|
||||||
return $tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
static updateNavbarState () {
|
static updateNavbarState () {
|
||||||
var uri = new URI(window.location.hash);
|
var uri = new URI(window.location.hash);
|
||||||
var uriFragment = uri.fragment();
|
var uriFragment = uri.fragment();
|
||||||
@@ -445,12 +429,6 @@ class MayanApp {
|
|||||||
dropdownAutoWidth: true,
|
dropdownAutoWidth: true,
|
||||||
width: '100%'
|
width: '100%'
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.select2-tags').select2({
|
|
||||||
templateSelection: MayanApp.tagSelectionTemplate,
|
|
||||||
templateResult: MayanApp.tagResultTemplate,
|
|
||||||
width: '100%'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resizeFullHeight () {
|
resizeFullHeight () {
|
||||||
|
|||||||
@@ -8,4 +8,4 @@ from .models import Tag
|
|||||||
@admin.register(Tag)
|
@admin.register(Tag)
|
||||||
class TagAdmin(admin.ModelAdmin):
|
class TagAdmin(admin.ModelAdmin):
|
||||||
filter_horizontal = ('documents',)
|
filter_horizontal = ('documents',)
|
||||||
list_display = ('label', 'color', 'get_preview_widget')
|
list_display = ('label', 'color')
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
from rest_framework import generics
|
from rest_framework import generics, status
|
||||||
|
from rest_framework.decorators import action
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from mayan.apps.common.mixins import ExternalObjectViewMixin
|
from mayan.apps.common.mixins import ExternalObjectMixin
|
||||||
|
from mayan.apps.documents.api_views import DocumentViewSet
|
||||||
from mayan.apps.documents.models import Document
|
from mayan.apps.documents.models import Document
|
||||||
from mayan.apps.documents.permissions import permission_document_view
|
from mayan.apps.documents.permissions import permission_document_view
|
||||||
from mayan.apps.documents.serializers import DocumentSerializer
|
from mayan.apps.documents.serializers import DocumentSerializer
|
||||||
from mayan.apps.rest_api.filters import MayanObjectPermissionsFilter
|
from mayan.apps.rest_api.filters import MayanObjectPermissionsFilter
|
||||||
|
from mayan.apps.rest_api.generics import (
|
||||||
|
ListAPIView, ListCreateAPIView, RetrieveDestroyAPIView,
|
||||||
|
RetrieveUpdateDestroyAPIView
|
||||||
|
)
|
||||||
from mayan.apps.rest_api.permissions import MayanPermission
|
from mayan.apps.rest_api.permissions import MayanPermission
|
||||||
|
|
||||||
from .models import Tag
|
from .models import Tag
|
||||||
@@ -17,116 +23,295 @@ from .permissions import (
|
|||||||
permission_tag_edit, permission_tag_remove, permission_tag_view
|
permission_tag_edit, permission_tag_remove, permission_tag_view
|
||||||
)
|
)
|
||||||
from .serializers import (
|
from .serializers import (
|
||||||
DocumentTagSerializer, TagSerializer, WritableTagSerializer
|
DocumentTagAttachSerializer, DocumentTagSerializer, TagAttachSerializer,
|
||||||
|
TagRemoveSerializer, TagSerializer,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class APITagListView(generics.ListCreateAPIView):
|
|
||||||
|
from django.conf.urls import url, include
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
from rest_framework import routers, serializers, viewsets
|
||||||
|
from rest_framework.decorators import detail_route
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from drf_yasg.utils import swagger_auto_schema
|
||||||
|
|
||||||
|
|
||||||
|
class TagViewSet(viewsets.ModelViewSet):
|
||||||
|
filter_backends = (MayanObjectPermissionsFilter,)
|
||||||
|
lookup_field = 'pk'
|
||||||
|
lookup_url_kwarg='tag_id'
|
||||||
|
permission_classes = (MayanPermission,)
|
||||||
|
queryset = Tag.objects.all()
|
||||||
|
serializer_class = TagSerializer
|
||||||
|
|
||||||
|
|
||||||
|
#@swagger_auto_schema(operation_description='GET /articles/today/')
|
||||||
|
@swagger_auto_schema(
|
||||||
|
operation_description="partial_update description override", responses={200: TagAttachSerializer}
|
||||||
|
)
|
||||||
|
@action(
|
||||||
|
detail=True, lookup_field='pk', lookup_url_kwarg='tag_id',
|
||||||
|
methods=('post',), serializer_class=TagAttachSerializer,
|
||||||
|
url_name='document-attach', url_path='attach'
|
||||||
|
)
|
||||||
|
def attach(self, request, *args, **kwargs):
|
||||||
|
#print '!!! attach', args, kwargs#, self.context
|
||||||
|
#return Response({})
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
#print '((((((((', serializer.validated_data
|
||||||
|
#self.perform_attach(serializer=serializer)
|
||||||
|
serializer.attach(instance=self.get_object())
|
||||||
|
headers = self.get_success_headers(data=serializer.data)
|
||||||
|
return Response(
|
||||||
|
serializer.data, status=status.HTTP_200_OK, headers=headers
|
||||||
|
)
|
||||||
|
|
||||||
|
#def perform_attach(self, serializer):
|
||||||
|
# #print '!!!!', serializer
|
||||||
|
# serializer.attach(instance=self.get_object())
|
||||||
|
|
||||||
|
#def get_success_headers(self, data):
|
||||||
|
# try:
|
||||||
|
# return {'Location': str(data[api_settings.URL_FIELD_NAME])}
|
||||||
|
# except (TypeError, KeyError):
|
||||||
|
# return {}
|
||||||
|
|
||||||
|
@action(
|
||||||
|
detail=True, lookup_field='pk', lookup_url_kwarg='tag_id',
|
||||||
|
url_name='document-list', url_path='documents'
|
||||||
|
)
|
||||||
|
def document_list(self, request, *args, **kwargs):
|
||||||
|
queryset = self.get_object().documents.all()
|
||||||
|
|
||||||
|
#TODO:Filter queryset
|
||||||
|
#queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
|
||||||
|
page = self.paginate_queryset(queryset)
|
||||||
|
if page is not None:
|
||||||
|
#serializer = self.get_serializer(page, many=True)
|
||||||
|
serializer = DocumentSerializer(page, many=True, context={'request': request})
|
||||||
|
return self.get_paginated_response(serializer.data)
|
||||||
|
|
||||||
|
#serializer = self.get_serializer(queryset, many=True)
|
||||||
|
serializer = DocumentSerializer(queryset, many=True, context={'request': request})
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
|
#serializer = DocumentSerializer(
|
||||||
|
# instance=, many=True,
|
||||||
|
# context={'request': request}
|
||||||
|
#)
|
||||||
|
#return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
|
@action(
|
||||||
|
detail=True, lookup_field='pk', lookup_url_kwarg='tag_id',
|
||||||
|
methods=('post',), serializer_class=TagRemoveSerializer,
|
||||||
|
url_name='document-remove', url_path='remove'
|
||||||
|
)
|
||||||
|
def remove(self, request, *args, **kwargs):
|
||||||
|
#print '!!! attach', args, kwargs#, self.context
|
||||||
|
#return Response({})
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
#print '((((((((', serializer.validated_data
|
||||||
|
#self.perform_attach(serializer=serializer)
|
||||||
|
serializer.remove(instance=self.get_object())
|
||||||
|
headers = self.get_success_headers(data=serializer.data)
|
||||||
|
return Response(
|
||||||
|
serializer.data, status=status.HTTP_200_OK, headers=headers
|
||||||
|
)
|
||||||
|
|
||||||
|
#def get_serializer_class(self, *args, **kwargs):
|
||||||
|
# #if self.action == 'attach':
|
||||||
|
# print '!!!!get_serializer_class', args, kwargs
|
||||||
|
# return TagAttachSerializer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DocumentTagViewSet(ExternalObjectMixin, viewsets.ReadOnlyModelViewSet):
|
||||||
|
external_object_class = Document
|
||||||
|
external_object_pk_url_kwarg = 'document_id'
|
||||||
|
external_object_permission = permission_tag_view
|
||||||
|
lookup_field = 'pk'
|
||||||
|
object_permission = {
|
||||||
|
'list': permission_document_view,
|
||||||
|
'retrieve': permission_document_view
|
||||||
|
}
|
||||||
|
serializer_class = DocumentTagSerializer
|
||||||
|
|
||||||
|
@action(
|
||||||
|
detail=True, lookup_field='pk', lookup_url_kwarg='document_id',
|
||||||
|
methods=('post',), serializer_class=DocumentTagAttachSerializer,
|
||||||
|
url_name='tag-attach', url_path='attach'
|
||||||
|
)
|
||||||
|
def attach(self, request, *args, **kwargs):
|
||||||
|
return Response({})
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
serializer = DocumentSerializer(
|
||||||
|
instance=self.get_object().documents.all(), many=True,
|
||||||
|
context={'request': request}
|
||||||
|
)
|
||||||
|
return Response(serializer.data)
|
||||||
|
'''
|
||||||
|
|
||||||
|
def get_document(self):
|
||||||
|
return self.get_external_object()
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
#return self.get_document().get_tags(user=self.request.user).all()
|
||||||
|
return self.get_document().tags.all()
|
||||||
|
|
||||||
|
#@detail_route(lookup_url_kwarg='tag_id')
|
||||||
|
#def document_list(self, request, *args, **kwargs):
|
||||||
|
# serializer = DocumentSerializer(
|
||||||
|
## instance=self.get_object().documents.all(), many=True,
|
||||||
|
# context={'request': request}
|
||||||
|
# )
|
||||||
|
# return Response(serializer.data)
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
class APITagListView(ListCreateAPIView):
|
||||||
"""
|
"""
|
||||||
get: Returns a list of all the tags.
|
get: Returns a list of all the tags.
|
||||||
post: Create a new tag.
|
post: Create a new tag.
|
||||||
"""
|
"""
|
||||||
filter_backends = (MayanObjectPermissionsFilter,)
|
object_permission = {'GET': permission_tag_view}
|
||||||
mayan_object_permissions = {'GET': (permission_tag_view,)}
|
|
||||||
mayan_view_permissions = {'POST': (permission_tag_create,)}
|
|
||||||
permission_classes = (MayanPermission,)
|
|
||||||
queryset = Tag.objects.all()
|
queryset = Tag.objects.all()
|
||||||
|
serializer_class = TagSerializer
|
||||||
def get_serializer(self, *args, **kwargs):
|
view_permission = {'POST': permission_tag_create}
|
||||||
if not self.request:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return super(APITagListView, self).get_serializer(*args, **kwargs)
|
|
||||||
|
|
||||||
def get_serializer_class(self):
|
|
||||||
if self.request.method == 'GET':
|
|
||||||
return TagSerializer
|
|
||||||
elif self.request.method == 'POST':
|
|
||||||
return WritableTagSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class APITagView(generics.RetrieveUpdateDestroyAPIView):
|
class APITagView(RetrieveUpdateDestroyAPIView):
|
||||||
"""
|
"""
|
||||||
delete: Delete the selected tag.
|
delete: Delete the selected tag.
|
||||||
get: Return the details of the selected tag.
|
get: Return the details of the selected tag.
|
||||||
patch: Edit the selected tag.
|
patch: Edit the selected tag.
|
||||||
put: Edit the selected tag.
|
put: Edit the selected tag.
|
||||||
"""
|
"""
|
||||||
filter_backends = (MayanObjectPermissionsFilter,)
|
|
||||||
lookup_url_kwarg = 'tag_pk'
|
lookup_url_kwarg = 'tag_pk'
|
||||||
mayan_object_permissions = {
|
object_permission = {
|
||||||
'DELETE': (permission_tag_delete,),
|
'DELETE': permission_tag_delete,
|
||||||
'GET': (permission_tag_view,),
|
'GET': permission_tag_view,
|
||||||
'PATCH': (permission_tag_edit,),
|
'PATCH': permission_tag_edit,
|
||||||
'PUT': (permission_tag_edit,)
|
'PUT': permission_tag_edit
|
||||||
}
|
}
|
||||||
queryset = Tag.objects.all()
|
queryset = Tag.objects.all()
|
||||||
|
serializer_class = TagSerializer
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
##
|
||||||
if not self.request:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return super(APITagView, self).get_serializer(*args, **kwargs)
|
class APITagDocumentListView(ExternalObjectMixin, ListCreateAPIView):
|
||||||
|
|
||||||
def get_serializer_class(self):
|
|
||||||
if self.request.method == 'GET':
|
|
||||||
return TagSerializer
|
|
||||||
else:
|
|
||||||
return WritableTagSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class APITagDocumentListView(ExternalObjectViewMixin, generics.ListAPIView):
|
|
||||||
"""
|
"""
|
||||||
get: Returns a list of all the documents tagged by a particular tag.
|
get: Returns a list of all the documents tagged by a particular tag.
|
||||||
"""
|
"""
|
||||||
external_object_class = Tag
|
external_object_class = Tag
|
||||||
external_object_pk_url_kwarg = 'tag_pk'
|
external_object_pk_url_kwarg = 'tag_pk'
|
||||||
external_object_permission = permission_tag_view
|
external_object_permission = permission_tag_view
|
||||||
filter_backends = (MayanObjectPermissionsFilter,)
|
object_permission = {'GET': permission_document_view}
|
||||||
mayan_object_permissions = {'GET': (permission_document_view,)}
|
serializer_class = TagDocumentSerializer
|
||||||
serializer_class = DocumentSerializer
|
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.get_tag().documents.all()
|
return self.get_tag().get_documents(user=self.request.user).all()
|
||||||
|
|
||||||
def get_tag(self):
|
def get_tag(self):
|
||||||
return self.get_external_object()
|
return self.get_external_object()
|
||||||
|
|
||||||
|
##
|
||||||
|
'''
|
||||||
|
|
||||||
class APIDocumentTagListView(ExternalObjectViewMixin, generics.ListCreateAPIView):
|
|
||||||
|
'''
|
||||||
|
class APITagView(RetrieveDestroyAPIView):
|
||||||
"""
|
"""
|
||||||
get: Returns a list of all the tags attached to a document.
|
delete: Delete the selected tag document.
|
||||||
post: Attach a tag to a document.
|
get: Return the details of the selected tag document.
|
||||||
"""
|
"""
|
||||||
|
lookup_url_kwarg = 'tag_pk'
|
||||||
|
object_permission = {
|
||||||
|
'DELETE': permission_tag_delete,
|
||||||
|
'GET': permission_tag_view,
|
||||||
|
'PATCH': permission_tag_edit,
|
||||||
|
'PUT': permission_tag_edit
|
||||||
|
}
|
||||||
|
queryset = Tag.objects.all()
|
||||||
|
serializer_class = TagSerializer
|
||||||
|
'''
|
||||||
|
##
|
||||||
|
'''
|
||||||
|
class DocumentSourceMixin(ExternalObjectMixin):
|
||||||
external_object_class = Document
|
external_object_class = Document
|
||||||
external_object_pk_url_kwarg = 'document_pk'
|
external_object_pk_url_kwarg = 'document_pk'
|
||||||
filter_backends = (MayanObjectPermissionsFilter,)
|
serializer_class = DocumentTagSerializer
|
||||||
mayan_object_permissions = {
|
|
||||||
'GET': (permission_tag_view,),
|
|
||||||
'POST': (permission_tag_attach,)
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_document(self):
|
def get_document(self):
|
||||||
return self.get_external_object()
|
return self.get_external_object()
|
||||||
|
|
||||||
def get_external_object_permission(self):
|
def get_external_object_permission(self):
|
||||||
if self.request.method == 'POST':
|
permission_dictionary = {
|
||||||
return permission_tag_attach
|
'DELETE': permission_tag_remove,
|
||||||
else:
|
'GET': permission_tag_view,
|
||||||
return permission_tag_view
|
'POST': permission_tag_attach
|
||||||
|
}
|
||||||
|
|
||||||
|
return permission_dictionary.get(self.request.method)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.get_document().get_tags().all()
|
return self.get_document().tags.all()
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
def get_serializer_context(self):
|
||||||
if not self.request:
|
context = super(DocumentSourceMixin, self).get_serializer_context()
|
||||||
return None
|
if self.kwargs:
|
||||||
|
context.update(
|
||||||
|
{
|
||||||
|
'document': self.get_document(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return super(APIDocumentTagListView, self).get_serializer(*args, **kwargs)
|
return context
|
||||||
|
|
||||||
def get_serializer_class(self):
|
|
||||||
return DocumentTagSerializer
|
|
||||||
|
|
||||||
|
class APIDocumentTagListView(DocumentSourceMixin, ListCreateAPIView):
|
||||||
|
"""
|
||||||
|
get: Returns a list of all the tags attached to a document.
|
||||||
|
post: Attach a tag to a document.
|
||||||
|
"""
|
||||||
|
#external_object_class = Document
|
||||||
|
#external_object_pk_url_kwarg = 'document_pk'
|
||||||
|
object_permission = {
|
||||||
|
'GET': permission_tag_view,
|
||||||
|
#'POST': permission_tag_attach
|
||||||
|
}
|
||||||
|
#serializer_class = DocumentTagSerializer
|
||||||
|
|
||||||
|
#def get_document(self):
|
||||||
|
# return self.get_external_object()
|
||||||
|
|
||||||
|
#def get_external_object_permission(self):
|
||||||
|
# if self.request.method == 'POST':
|
||||||
|
# return permission_tag_attach
|
||||||
|
# else:
|
||||||
|
# return permission_tag_view
|
||||||
|
|
||||||
|
#def get_queryset(self):
|
||||||
|
# #if self.request.method == 'POST':
|
||||||
|
# # permission = permission_tag_attach
|
||||||
|
# #else:
|
||||||
|
# # permission = permission_tag_view
|
||||||
|
#
|
||||||
|
# return self.get_document().tags().all()
|
||||||
|
# #return self.get_document().get_tags(
|
||||||
|
## # permission=permission, user=self.request.user
|
||||||
|
# #).all()
|
||||||
|
|
||||||
|
"""
|
||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
"""
|
"""
|
||||||
Extra context provided to the serializer class.
|
Extra context provided to the serializer class.
|
||||||
@@ -140,41 +325,44 @@ class APIDocumentTagListView(ExternalObjectViewMixin, generics.ListCreateAPIView
|
|||||||
)
|
)
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
"""
|
||||||
|
|
||||||
|
class APIDocumentTagView(DocumentSourceMixin, RetrieveDestroyAPIView):
|
||||||
class APIDocumentTagView(ExternalObjectViewMixin, generics.RetrieveDestroyAPIView):
|
|
||||||
"""
|
"""
|
||||||
delete: Remove a tag from the selected document.
|
delete: Remove a tag from the selected document.
|
||||||
get: Returns the details of the selected document tag.
|
get: Returns the details of the selected document tag.
|
||||||
"""
|
"""
|
||||||
external_object_class = Document
|
#external_object_class = Document
|
||||||
external_object_pk_url_kwarg = 'document_pk'
|
#external_object_pk_url_kwarg = 'document_pk'
|
||||||
filter_backends = (MayanObjectPermissionsFilter,)
|
|
||||||
lookup_url_kwarg = 'tag_pk'
|
lookup_url_kwarg = 'tag_pk'
|
||||||
mayan_object_permissions = {
|
mayan_object_permission = {
|
||||||
'GET': (permission_tag_view,),
|
'GET': permission_tag_view,
|
||||||
'DELETE': (permission_tag_remove,)
|
'DELETE': permission_tag_remove
|
||||||
}
|
}
|
||||||
serializer_class = DocumentTagSerializer
|
#serializer_class = DocumentTagSerializer
|
||||||
|
|
||||||
def get_document(self):
|
#def get_document(self):
|
||||||
return self.get_external_object()
|
# return self.get_external_object()
|
||||||
|
|
||||||
def get_external_object_permission(self):
|
#def get_external_object_permission(self):
|
||||||
if self.request.method == 'DELETE':
|
# if self.request.method == 'DELETE':
|
||||||
return permission_tag_remove
|
# return permission_tag_remove
|
||||||
else:
|
# else:
|
||||||
return permission_tag_view
|
# return permission_tag_view
|
||||||
|
|
||||||
|
"""
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.get_document().get_tags().all()
|
if self.request.method == 'DELETE':
|
||||||
|
permission = permission_tag_remove
|
||||||
|
else:
|
||||||
|
permission = permission_tag_view
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
return self.get_document().get_tags(
|
||||||
if not self.request:
|
permission=permission, user=self.request.user
|
||||||
return None
|
).all()
|
||||||
|
"""
|
||||||
return super(APIDocumentTagView, self).get_serializer(*args, **kwargs)
|
|
||||||
|
|
||||||
|
"""
|
||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
"""
|
"""
|
||||||
Extra context provided to the serializer class.
|
Extra context provided to the serializer class.
|
||||||
@@ -188,15 +376,33 @@ class APIDocumentTagView(ExternalObjectViewMixin, generics.RetrieveDestroyAPIVie
|
|||||||
)
|
)
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
"""
|
||||||
|
|
||||||
def perform_destroy(self, instance):
|
def perform_destroy(self, instance):
|
||||||
try:
|
# try:
|
||||||
instance.documents.remove(self.get_document())
|
from mayan.apps.acls.models import AccessControlList
|
||||||
except Exception as exception:
|
from rest_framework.generics import get_object_or_404
|
||||||
raise ValidationError(exception)
|
|
||||||
|
|
||||||
def retrieve(self, request, *args, **kwargs):
|
queryset = AccessControlList.objects.restrict_queryset(
|
||||||
instance = self.get_object()
|
permission=permission_tag_remove, queryset=Tag.objects.all(),
|
||||||
|
user=self.request.user
|
||||||
|
)
|
||||||
|
instance = get_object_or_404(queryset=queryset, pk=instance.pk)
|
||||||
|
#instance.attach_to(
|
||||||
|
# document=self.context['document'],
|
||||||
|
# user=self.context['request'].user
|
||||||
|
#)
|
||||||
|
|
||||||
serializer = self.get_serializer(instance)
|
instance.remove_from(
|
||||||
return Response(serializer.data)
|
document=self.get_document(), user=self.request.user
|
||||||
|
)
|
||||||
|
#instance.documents.remove(self.get_document())
|
||||||
|
# except Exception as exception:
|
||||||
|
# raise ValidationError(exception)
|
||||||
|
|
||||||
|
#def retrieve(self, request, *args, **kwargs):
|
||||||
|
# instance = self.get_object()
|
||||||
|
|
||||||
|
# serializer = self.get_serializer(instance)
|
||||||
|
# return Response(serializer.data)
|
||||||
|
'''
|
||||||
|
|||||||
@@ -24,12 +24,13 @@ from .events import (
|
|||||||
event_tag_attach, event_tag_created, event_tag_edited, event_tag_remove
|
event_tag_attach, event_tag_created, event_tag_edited, event_tag_remove
|
||||||
)
|
)
|
||||||
from .handlers import handler_index_document, handler_tag_pre_delete
|
from .handlers import handler_index_document, handler_tag_pre_delete
|
||||||
|
from .html_widgets import DocumentTagsWidget, TagWidget
|
||||||
from .links import (
|
from .links import (
|
||||||
link_document_tag_list, link_multiple_documents_attach_tag,
|
link_document_tag_list, link_document_multiple_tag_multiple_attach,
|
||||||
link_multiple_documents_tag_remove,
|
link_document_multiple_tag_multiple_remove,
|
||||||
link_single_document_multiple_tag_remove, link_tag_attach,
|
link_document_tag_multiple_remove, link_document_tag_multiple_attach,
|
||||||
link_tag_create, link_tag_delete, link_tag_edit, link_tag_list,
|
link_tag_create, link_tag_delete, link_tag_document_list, link_tag_edit,
|
||||||
link_tag_multiple_delete, link_tag_tagged_item_list
|
link_tag_list, link_tag_multiple_delete
|
||||||
)
|
)
|
||||||
from .menus import menu_tags
|
from .menus import menu_tags
|
||||||
from .methods import method_get_tags
|
from .methods import method_get_tags
|
||||||
@@ -38,7 +39,6 @@ from .permissions import (
|
|||||||
permission_tag_remove, permission_tag_view
|
permission_tag_remove, permission_tag_view
|
||||||
)
|
)
|
||||||
from .search import tag_search # NOQA
|
from .search import tag_search # NOQA
|
||||||
from .widgets import widget_document_tags
|
|
||||||
|
|
||||||
|
|
||||||
class TagsApp(MayanAppConfig):
|
class TagsApp(MayanAppConfig):
|
||||||
@@ -63,13 +63,11 @@ class TagsApp(MayanAppConfig):
|
|||||||
app_label='documents', model_name='DocumentPageSearchResult'
|
app_label='documents', model_name='DocumentPageSearchResult'
|
||||||
)
|
)
|
||||||
|
|
||||||
DocumentTag = self.get_model('DocumentTag')
|
DocumentTag = self.get_model(model_name='DocumentTag')
|
||||||
Tag = self.get_model('Tag')
|
Tag = self.get_model(model_name='Tag')
|
||||||
|
|
||||||
Document.add_to_class(name='get_tags', value=method_get_tags)
|
Document.add_to_class(name='get_tags', value=method_get_tags)
|
||||||
|
|
||||||
ModelAttribute(model=Document, name='get_tags')
|
|
||||||
|
|
||||||
ModelEventType.register(
|
ModelEventType.register(
|
||||||
model=Tag, event_types=(
|
model=Tag, event_types=(
|
||||||
event_tag_attach, event_tag_created, event_tag_edited,
|
event_tag_attach, event_tag_created, event_tag_edited,
|
||||||
@@ -78,10 +76,10 @@ class TagsApp(MayanAppConfig):
|
|||||||
)
|
)
|
||||||
|
|
||||||
ModelField(
|
ModelField(
|
||||||
Document, name='tags__label'
|
model=Document, name='tags__label'
|
||||||
)
|
)
|
||||||
ModelField(
|
ModelField(
|
||||||
Document, name='tags__color'
|
model=Document, name='tags__color'
|
||||||
)
|
)
|
||||||
|
|
||||||
ModelPermission.register(
|
ModelPermission.register(
|
||||||
@@ -96,29 +94,31 @@ class TagsApp(MayanAppConfig):
|
|||||||
permission_acl_edit, permission_acl_view,
|
permission_acl_edit, permission_acl_view,
|
||||||
permission_events_view, permission_tag_attach,
|
permission_events_view, permission_tag_attach,
|
||||||
permission_tag_delete, permission_tag_edit,
|
permission_tag_delete, permission_tag_edit,
|
||||||
permission_tag_remove, permission_tag_view,
|
permission_tag_remove, permission_tag_view
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
attribute='label', is_identifier=True, is_sortable=True,
|
attribute='label', is_identifier=True, is_sortable=True,
|
||||||
source=DocumentTag,
|
source=DocumentTag
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
attribute='get_preview_widget', source=DocumentTag
|
label=_('Preview'), source=DocumentTag, widget=TagWidget
|
||||||
)
|
)
|
||||||
|
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
func=lambda context: widget_document_tags(
|
func=lambda context: context['object'].get_tags(
|
||||||
document=context['object'], user=context['request'].user
|
permission=permission_tag_view,
|
||||||
), label=_('Tags'), source=Document
|
|
||||||
)
|
|
||||||
|
|
||||||
SourceColumn(
|
|
||||||
func=lambda context: widget_document_tags(
|
|
||||||
document=context['object'].document,
|
|
||||||
user=context['request'].user
|
user=context['request'].user
|
||||||
), label=_('Tags'), source=DocumentPageSearchResult
|
), label=_('Tags'), source=Document, widget=DocumentTagsWidget
|
||||||
|
)
|
||||||
|
|
||||||
|
SourceColumn(
|
||||||
|
func=lambda context: context['object'].document.get_tag(
|
||||||
|
permission=permission_tag_view,
|
||||||
|
user=context['request'].user
|
||||||
|
), label=_('Tags'), source=DocumentPageSearchResult,
|
||||||
|
widget=DocumentTagsWidget
|
||||||
)
|
)
|
||||||
|
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
@@ -126,12 +126,12 @@ class TagsApp(MayanAppConfig):
|
|||||||
source=Tag
|
source=Tag
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
attribute='get_preview_widget', source=Tag
|
label=_('Preview'), source=Tag, widget=TagWidget
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
func=lambda context: context['object'].get_document_count(
|
func=lambda context: context['object'].get_document_count(
|
||||||
user=context['request'].user
|
user=context['request'].user
|
||||||
), label=_('Documents'), source=Tag
|
), include_label=True, label=_('Documents'), source=Tag
|
||||||
)
|
)
|
||||||
|
|
||||||
document_page_search.add_model_field(
|
document_page_search.add_model_field(
|
||||||
@@ -147,19 +147,17 @@ class TagsApp(MayanAppConfig):
|
|||||||
links=(
|
links=(
|
||||||
link_acl_list, link_events_for_object,
|
link_acl_list, link_events_for_object,
|
||||||
link_object_event_types_user_subcriptions_list,
|
link_object_event_types_user_subcriptions_list,
|
||||||
link_tag_tagged_item_list,
|
link_tag_document_list,
|
||||||
),
|
), sources=(Tag,)
|
||||||
sources=(Tag,)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
menu_main.bind_links(links=(menu_tags,), position=98)
|
menu_main.bind_links(links=(menu_tags,), position=98)
|
||||||
|
|
||||||
menu_multi_item.bind_links(
|
menu_multi_item.bind_links(
|
||||||
links=(
|
links=(
|
||||||
link_multiple_documents_attach_tag,
|
link_document_multiple_tag_multiple_attach,
|
||||||
link_multiple_documents_tag_remove
|
link_document_multiple_tag_multiple_remove
|
||||||
),
|
), sources=(Document,)
|
||||||
sources=(Document,)
|
|
||||||
)
|
)
|
||||||
menu_multi_item.bind_links(
|
menu_multi_item.bind_links(
|
||||||
links=(link_tag_multiple_delete,), sources=(Tag,)
|
links=(link_tag_multiple_delete,), sources=(Tag,)
|
||||||
@@ -167,14 +165,14 @@ class TagsApp(MayanAppConfig):
|
|||||||
menu_object.bind_links(
|
menu_object.bind_links(
|
||||||
links=(
|
links=(
|
||||||
link_tag_edit, link_tag_delete
|
link_tag_edit, link_tag_delete
|
||||||
),
|
), sources=(Tag,)
|
||||||
sources=(Tag,)
|
|
||||||
)
|
)
|
||||||
menu_sidebar.bind_links(
|
menu_sidebar.bind_links(
|
||||||
links=(link_tag_attach, link_single_document_multiple_tag_remove),
|
links=(
|
||||||
sources=(
|
link_document_tag_multiple_attach, link_document_tag_multiple_remove
|
||||||
'tags:tag_attach', 'tags:document_tags',
|
), sources=(
|
||||||
'tags:single_document_multiple_tag_remove'
|
'tags:document_tag_multiple_attach', 'tags:document_tag_list',
|
||||||
|
'tags:document_tag_multiple_remove'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
menu_tags.bind_links(
|
menu_tags.bind_links(
|
||||||
@@ -188,13 +186,11 @@ class TagsApp(MayanAppConfig):
|
|||||||
# Index update
|
# Index update
|
||||||
|
|
||||||
m2m_changed.connect(
|
m2m_changed.connect(
|
||||||
handler_index_document,
|
|
||||||
dispatch_uid='tags_handler_index_document',
|
dispatch_uid='tags_handler_index_document',
|
||||||
sender=Tag.documents.through
|
receiver=handler_index_document, sender=Tag.documents.through
|
||||||
)
|
)
|
||||||
|
|
||||||
pre_delete.connect(
|
pre_delete.connect(
|
||||||
handler_tag_pre_delete,
|
|
||||||
dispatch_uid='tags_handler_tag_pre_delete',
|
dispatch_uid='tags_handler_tag_pre_delete',
|
||||||
sender=Tag
|
receiver=handler_tag_pre_delete, sender=Tag
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
from mayan.apps.events import EventTypeNamespace
|
from mayan.apps.events import EventTypeNamespace
|
||||||
|
|
||||||
namespace = EventTypeNamespace(name='tags', label=_('Tags'))
|
namespace = EventTypeNamespace(label=_('Tags'), name='tags')
|
||||||
|
|
||||||
event_tag_attach = namespace.add_event_type(
|
event_tag_attach = namespace.add_event_type(
|
||||||
label=_('Tag attached to document'), name='attach'
|
label=_('Tag attached to document'), name='attach'
|
||||||
|
|||||||
@@ -1,37 +1,22 @@
|
|||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from mayan.apps.acls.models import AccessControlList
|
from mayan.apps.acls.models import AccessControlList
|
||||||
|
from mayan.apps.common.forms import FilteredSelectionForm
|
||||||
|
|
||||||
from .models import Tag
|
from .models import Tag
|
||||||
from .permissions import permission_tag_view
|
from .permissions import permission_tag_view
|
||||||
from .widgets import TagFormWidget
|
from .widgets import TagFormWidget
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
class TagMultipleSelectionForm(FilteredSelectionForm):
|
||||||
|
class Media:
|
||||||
|
js = ('tags/js/tags_form.js',)
|
||||||
|
|
||||||
class TagMultipleSelectionForm(forms.Form):
|
class Meta:
|
||||||
def __init__(self, *args, **kwargs):
|
allow_multiple = True
|
||||||
help_text = kwargs.pop('help_text', None)
|
field_name = 'tags'
|
||||||
permission = kwargs.pop('permission', permission_tag_view)
|
label = _('Tags')
|
||||||
queryset = kwargs.pop('queryset', Tag.objects.all())
|
widget_attributes = {'class': 'select2-tags'}
|
||||||
user = kwargs.pop('user', None)
|
|
||||||
|
|
||||||
logger.debug('user: %s', user)
|
|
||||||
super(TagMultipleSelectionForm, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
queryset = AccessControlList.objects.filter_by_access(
|
|
||||||
permission=permission, queryset=queryset, user=user
|
|
||||||
)
|
|
||||||
|
|
||||||
self.fields['tags'] = forms.ModelMultipleChoiceField(
|
|
||||||
label=_('Tags'), help_text=help_text,
|
|
||||||
queryset=queryset, required=False,
|
|
||||||
widget=TagFormWidget(
|
|
||||||
attrs={'class': 'select2-tags'}, queryset=queryset
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|||||||
26
mayan/apps/tags/html_widgets.py
Normal file
26
mayan/apps/tags/html_widgets.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
|
||||||
|
|
||||||
|
class DocumentTagsWidget(object):
|
||||||
|
"""
|
||||||
|
A tag widget that displays the tags for the given document
|
||||||
|
"""
|
||||||
|
def render(self, name, value):
|
||||||
|
return render_to_string(
|
||||||
|
template_name='tags/document_tags_widget.html',
|
||||||
|
context={
|
||||||
|
'tags': value,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TagWidget(object):
|
||||||
|
def render(self, name, value):
|
||||||
|
return render_to_string(
|
||||||
|
template_name='tags/tag_widget.html',
|
||||||
|
context={
|
||||||
|
'tag': value,
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -2,19 +2,22 @@ from __future__ import absolute_import, unicode_literals
|
|||||||
|
|
||||||
from mayan.apps.appearance.classes import Icon
|
from mayan.apps.appearance.classes import Icon
|
||||||
|
|
||||||
icon_menu_tags = Icon(driver_name='fontawesome', symbol='tags')
|
icon_document_multiple_tag_multiple_remove = Icon(
|
||||||
icon_multiple_documents_tag_attach = Icon(
|
|
||||||
driver_name='fontawesome-dual', primary_symbol='tag',
|
|
||||||
secondary_symbol='arrow-right'
|
|
||||||
)
|
|
||||||
icon_multiple_documents_tag_remove = Icon(
|
|
||||||
driver_name='fontawesome-dual', primary_symbol='tag',
|
driver_name='fontawesome-dual', primary_symbol='tag',
|
||||||
secondary_symbol='minus'
|
secondary_symbol='minus'
|
||||||
)
|
)
|
||||||
icon_tag_attach = Icon(
|
icon_document_tag_multiple_attach = Icon(
|
||||||
driver_name='fontawesome-dual', primary_symbol='tag',
|
driver_name='fontawesome-dual', primary_symbol='tag',
|
||||||
secondary_symbol='arrow-right'
|
secondary_symbol='arrow-right'
|
||||||
)
|
)
|
||||||
|
icon_document_tag_multiple_remove = Icon(
|
||||||
|
driver_name='fontawesome-dual', primary_symbol='tag',
|
||||||
|
secondary_symbol='minus'
|
||||||
|
)
|
||||||
|
icon_document_tag_multiple_remove_submit = Icon(
|
||||||
|
driver_name='fontawesome', symbol='minus'
|
||||||
|
)
|
||||||
|
icon_menu_tags = Icon(driver_name='fontawesome', symbol='tags')
|
||||||
icon_tag_create = Icon(
|
icon_tag_create = Icon(
|
||||||
driver_name='fontawesome-dual', primary_symbol='tag',
|
driver_name='fontawesome-dual', primary_symbol='tag',
|
||||||
secondary_symbol='plus'
|
secondary_symbol='plus'
|
||||||
@@ -25,8 +28,3 @@ icon_tag_delete_submit = Icon(driver_name='fontawesome', symbol='times')
|
|||||||
icon_tag_document_list = Icon(driver_name='fontawesome', symbol='tags')
|
icon_tag_document_list = Icon(driver_name='fontawesome', symbol='tags')
|
||||||
icon_tag_list = Icon(driver_name='fontawesome', symbol='tags')
|
icon_tag_list = Icon(driver_name='fontawesome', symbol='tags')
|
||||||
icon_tag_multiple_delete = Icon(driver_name='fontawesome', symbol='times')
|
icon_tag_multiple_delete = Icon(driver_name='fontawesome', symbol='times')
|
||||||
icon_tag_remove = Icon(
|
|
||||||
driver_name='fontawesome-dual', primary_symbol='tag',
|
|
||||||
secondary_symbol='minus'
|
|
||||||
)
|
|
||||||
icon_tag_remove_submit = Icon(driver_name='fontawesome', symbol='minus')
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ from mayan.apps.documents.icons import icon_document_list
|
|||||||
from mayan.apps.navigation import Link, get_cascade_condition
|
from mayan.apps.navigation import Link, get_cascade_condition
|
||||||
|
|
||||||
from .icons import (
|
from .icons import (
|
||||||
icon_document_multiple_tag_multiple_remove, icon_document_multiple_tag_multiple_remove,
|
icon_document_multiple_tag_multiple_remove,
|
||||||
icon_document_tag_multiple_attach, icon_tag_create, icon_tag_delete, icon_tag_edit,
|
icon_document_tag_multiple_attach, icon_tag_create, icon_tag_delete,
|
||||||
icon_tag_document_list, icon_tag_list, icon_tag_multiple_delete,
|
icon_tag_edit, icon_tag_document_list, icon_tag_list,
|
||||||
icon_document_tag_multiple_remove
|
icon_tag_multiple_delete, icon_document_tag_multiple_remove
|
||||||
)
|
)
|
||||||
from .permissions import (
|
from .permissions import (
|
||||||
permission_tag_attach, permission_tag_create, permission_tag_delete,
|
permission_tag_attach, permission_tag_create, permission_tag_delete,
|
||||||
@@ -17,10 +17,6 @@ from .permissions import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
link_document_tag_list = Link(
|
|
||||||
args='resolved_object.pk', icon_class=icon_tag_document_list,
|
|
||||||
permission=permission_tag_view, text=_('Tags'), view='tags:document_tags'
|
|
||||||
)
|
|
||||||
link_document_multiple_tag_multiple_attach = Link(
|
link_document_multiple_tag_multiple_attach = Link(
|
||||||
icon_class=icon_document_multiple_tag_multiple_remove, text=_('Attach tags'),
|
icon_class=icon_document_multiple_tag_multiple_remove, text=_('Attach tags'),
|
||||||
view='tags:document_multiple_tag_multiple_attach'
|
view='tags:document_multiple_tag_multiple_attach'
|
||||||
@@ -29,27 +25,37 @@ link_document_multiple_tag_multiple_remove = Link(
|
|||||||
icon_class=icon_document_multiple_tag_multiple_remove, text=_('Remove tag'),
|
icon_class=icon_document_multiple_tag_multiple_remove, text=_('Remove tag'),
|
||||||
view='tags:document_multiple_tag_multiple_remove'
|
view='tags:document_multiple_tag_multiple_remove'
|
||||||
)
|
)
|
||||||
|
link_document_tag_list = Link(
|
||||||
|
icon_class=icon_tag_document_list,
|
||||||
|
kwargs={'document_id': 'resolved_object.pk'},
|
||||||
|
permission=permission_tag_view, text=_('Tags'),
|
||||||
|
view='tags:document_tag_list'
|
||||||
|
)
|
||||||
link_document_tag_multiple_attach = Link(
|
link_document_tag_multiple_attach = Link(
|
||||||
args='object.pk', icon_class=icon_document_tag_multiple_attach,
|
icon_class=icon_document_tag_multiple_attach,
|
||||||
permission=permission_tag_attach, text=_('Attach tags'),
|
kwargs={'document_id': 'object.pk'}, permission=permission_tag_attach,
|
||||||
view='tags:document_tag_multiple_attach'
|
text=_('Attach tags'), view='tags:document_tag_multiple_attach'
|
||||||
)
|
)
|
||||||
link_document_tag_multiple_remove = Link(
|
link_document_tag_multiple_remove = Link(
|
||||||
args='object.id', icon_class=icon_document_tag_multiple_remove,
|
icon_class=icon_document_tag_multiple_remove,
|
||||||
permission=permission_tag_remove, text=_('Remove tags'),
|
kwargs={'document_id': 'object.pk'}, permission=permission_tag_remove,
|
||||||
view='tags:document_tag_multiple_remove'
|
text=_('Remove tags'), view='tags:document_tag_multiple_remove'
|
||||||
)
|
)
|
||||||
link_tag_create = Link(
|
link_tag_create = Link(
|
||||||
icon_class=icon_tag_create, permission=permission_tag_create,
|
icon_class=icon_tag_create, permission=permission_tag_create,
|
||||||
text=_('Create new tag'), view='tags:tag_create'
|
text=_('Create new tag'), view='tags:tag_create'
|
||||||
)
|
)
|
||||||
link_tag_delete = Link(
|
link_tag_delete = Link(
|
||||||
args='object.id', icon_class=icon_tag_delete,
|
icon_class=icon_tag_delete, kwargs={'tag_id': 'object.pk'},
|
||||||
permission=permission_tag_delete, tags='dangerous', text=_('Delete'),
|
permission=permission_tag_delete, tags='dangerous', text=_('Delete'),
|
||||||
view='tags:tag_delete'
|
view='tags:tag_delete'
|
||||||
)
|
)
|
||||||
|
link_tag_document_list = Link(
|
||||||
|
icon_class=icon_document_list, kwargs={'tag_id': 'object.pk'},
|
||||||
|
text=('Documents'), view='tags:tag_document_list'
|
||||||
|
)
|
||||||
link_tag_edit = Link(
|
link_tag_edit = Link(
|
||||||
args='object.id', icon_class=icon_tag_edit,
|
icon_class=icon_tag_edit, kwargs={'tag_id': 'object.pk'},
|
||||||
permission=permission_tag_edit, text=_('Edit'), view='tags:tag_edit'
|
permission=permission_tag_edit, text=_('Edit'), view='tags:tag_edit'
|
||||||
)
|
)
|
||||||
link_tag_list = Link(
|
link_tag_list = Link(
|
||||||
@@ -62,7 +68,3 @@ link_tag_multiple_delete = Link(
|
|||||||
icon_class=icon_tag_multiple_delete, permission=permission_tag_delete,
|
icon_class=icon_tag_multiple_delete, permission=permission_tag_delete,
|
||||||
text=_('Delete'), view='tags:tag_multiple_delete'
|
text=_('Delete'), view='tags:tag_multiple_delete'
|
||||||
)
|
)
|
||||||
link_tag_tagged_item_list = Link(
|
|
||||||
args='object.id', icon_class=icon_document_list, text=('Documents'),
|
|
||||||
view='tags:tag_tagged_item_list'
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -3,10 +3,18 @@ from __future__ import unicode_literals
|
|||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from .permissions import permission_tag_view
|
||||||
|
|
||||||
def method_get_tags(self):
|
|
||||||
|
def method_get_tags(self, permission, user):
|
||||||
|
AccessControlList = apps.get_model(
|
||||||
|
app_label='acls', model_name='AccessControlList'
|
||||||
|
)
|
||||||
DocumentTag = apps.get_model(app_label='tags', model_name='DocumentTag')
|
DocumentTag = apps.get_model(app_label='tags', model_name='DocumentTag')
|
||||||
return DocumentTag.objects.filter(documents=self)
|
return AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission,
|
||||||
|
queryset=DocumentTag.objects.filter(documents=self), user=user
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
method_get_tags.help_text = _('Return a the tags attached to the document.')
|
method_get_tags.help_text = _('Return a the tags attached to the document.')
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ from .events import (
|
|||||||
event_tag_attach, event_tag_created, event_tag_edited, event_tag_remove
|
event_tag_attach, event_tag_created, event_tag_edited, event_tag_remove
|
||||||
)
|
)
|
||||||
from .managers import DocumentTagManager
|
from .managers import DocumentTagManager
|
||||||
from .widgets import widget_single_tag
|
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
@@ -56,23 +55,22 @@ class Tag(models.Model):
|
|||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse(
|
return reverse(
|
||||||
viewname='tags:tag_tagged_item_list', kwargs={'tag_pk': str(self.pk)}
|
viewname='tags:tag_tagged_item_list', kwargs={
|
||||||
|
'tag_id': self.pk
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_documents(self, user):
|
||||||
|
"""
|
||||||
|
Return a filtered queryset documents that have this tag attached.
|
||||||
|
"""
|
||||||
|
return AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission_document_view, queryset=self.documents,
|
||||||
|
user=user
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_document_count(self, user):
|
def get_document_count(self, user):
|
||||||
"""
|
return self.get_documents(user=user).count()
|
||||||
Return the numeric count of documents that have this tag attached.
|
|
||||||
The count if filtered by access.
|
|
||||||
"""
|
|
||||||
queryset = AccessControlList.objects.filter_by_access(
|
|
||||||
permission_document_view, user, queryset=self.documents
|
|
||||||
)
|
|
||||||
|
|
||||||
return queryset.count()
|
|
||||||
|
|
||||||
def get_preview_widget(self):
|
|
||||||
return widget_single_tag(tag=self)
|
|
||||||
get_preview_widget.short_description = _('Preview')
|
|
||||||
|
|
||||||
def remove_from(self, document, user=None):
|
def remove_from(self, document, user=None):
|
||||||
"""
|
"""
|
||||||
|
|||||||
20
mayan/apps/tags/routers.py
Normal file
20
mayan/apps/tags/routers.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
#from rest_framework import routers
|
||||||
|
|
||||||
|
#router = routers.SimpleRouter()
|
||||||
|
#router.register(r'users', UserViewSet)
|
||||||
|
#router.register(r'accounts', AccountViewSet)
|
||||||
|
#urlpatterns = router.urls
|
||||||
|
|
||||||
|
#router = routers.DefaultRouter()
|
||||||
|
#from mayan.apps.rest_api.api_views import router
|
||||||
|
#from mayan.apps.rest_api.urls import router
|
||||||
|
|
||||||
|
from .api_views import TagViewSet
|
||||||
|
|
||||||
|
router_entries = (
|
||||||
|
{'prefix': r'tags', 'viewset': TagViewSet, 'base_name': 'tag'},
|
||||||
|
)
|
||||||
|
|
||||||
|
#router.register(prefix=r'tags', viewset=TagViewSet, basename='tag')
|
||||||
@@ -7,9 +7,8 @@ from mayan.apps.dynamic_search.classes import SearchModel
|
|||||||
from .permissions import permission_tag_view
|
from .permissions import permission_tag_view
|
||||||
|
|
||||||
tag_search = SearchModel(
|
tag_search = SearchModel(
|
||||||
app_label='tags', model_name='Tag',
|
app_label='tags', model_name='Tag', permission=permission_tag_view,
|
||||||
permission=permission_tag_view,
|
serializer_path='mayan.apps.tags.serializers.TagSerializer'
|
||||||
serializer_string='mayan.apps.tags.serializers.TagSerializer'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
tag_search.add_model_field(
|
tag_search.add_model_field(
|
||||||
|
|||||||
@@ -8,34 +8,42 @@ from rest_framework.reverse import reverse
|
|||||||
|
|
||||||
from mayan.apps.acls.models import AccessControlList
|
from mayan.apps.acls.models import AccessControlList
|
||||||
from mayan.apps.documents.models import Document
|
from mayan.apps.documents.models import Document
|
||||||
|
from mayan.apps.documents.serializers import DocumentSerializer
|
||||||
|
from mayan.apps.rest_api.relations import MultiKwargHyperlinkedIdentityField
|
||||||
|
|
||||||
from .models import Tag
|
from .models import Tag
|
||||||
from .permissions import permission_tag_attach
|
from .permissions import permission_tag_attach
|
||||||
|
|
||||||
|
|
||||||
class TagSerializer(serializers.HyperlinkedModelSerializer):
|
class TagSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
documents_url = serializers.HyperlinkedIdentityField(
|
attach_url = serializers.HyperlinkedIdentityField(
|
||||||
lookup_field='pk', lookup_url_kwarg='tag_pk',
|
lookup_url_kwarg='tag_id', view_name='rest_api:tag-document-attach'
|
||||||
view_name='rest_api:tag-document-list'
|
)
|
||||||
|
|
||||||
|
documents_url = serializers.HyperlinkedIdentityField(
|
||||||
|
lookup_url_kwarg='tag_id', view_name='rest_api:tag-document-list'
|
||||||
|
)
|
||||||
|
|
||||||
|
remove_url = serializers.HyperlinkedIdentityField(
|
||||||
|
lookup_url_kwarg='tag_id', view_name='rest_api:tag-document-remove'
|
||||||
)
|
)
|
||||||
documents_count = serializers.SerializerMethodField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'url': {
|
'url': {
|
||||||
'lookup_field': 'pk', 'lookup_url_kwarg': 'tag_pk',
|
'lookup_url_kwarg': 'tag_id',
|
||||||
'view_name': 'rest_api:tag-detail'
|
'view_name': 'rest_api:tag-detail'
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
fields = (
|
fields = (
|
||||||
'color', 'documents_count', 'documents_url', 'id', 'label', 'url'
|
'attach_url', 'color', 'documents_url', 'label', 'id',
|
||||||
|
'remove_url', 'url'
|
||||||
)
|
)
|
||||||
model = Tag
|
model = Tag
|
||||||
|
|
||||||
def get_documents_count(self, instance):
|
|
||||||
return instance.documents.count()
|
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
class WritableTagSerializer(serializers.ModelSerializer):
|
class WritableTagSerializer(serializers.ModelSerializer):
|
||||||
documents_pk_list = serializers.CharField(
|
documents_pk_list = serializers.CharField(
|
||||||
help_text=_(
|
help_text=_(
|
||||||
@@ -81,37 +89,303 @@ class WritableTagSerializer(serializers.ModelSerializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
"""
|
||||||
|
|
||||||
class DocumentTagSerializer(TagSerializer):
|
class DocumentTagSerializer(TagSerializer):
|
||||||
document_tag_url = serializers.SerializerMethodField(
|
#document_attach_url = serializers.HyperlinkedIdentityField(
|
||||||
help_text=_(
|
# lookup_url_kwarg='document_id', view_name='rest_api:document-tag-attach'
|
||||||
'API URL pointing to a tag in relation to the document '
|
#)
|
||||||
'attached to it. This URL is different than the canonical '
|
|
||||||
'tag URL.'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tag_pk = serializers.IntegerField(
|
|
||||||
help_text=_('Primary key of the tag to be added.'), write_only=True
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta(TagSerializer.Meta):
|
class Meta(TagSerializer.Meta):
|
||||||
fields = TagSerializer.Meta.fields + ('document_tag_url', 'tag_pk')
|
#fields = TagSerializer.Meta.fields + ('document_attach_url',)
|
||||||
read_only_fields = TagSerializer.Meta.fields + ('document_tag_url',)
|
fields = TagSerializer.Meta.fields
|
||||||
|
#fields = TagSerializer.Meta.fields + ('document_tag_url', 'tag_pk')
|
||||||
|
#fields = TagSerializer.Meta.fields + ('tag_pk',)
|
||||||
|
#read_only_fields = TagSerializer.Meta.fields + ('document_attach_url',)
|
||||||
|
read_only_fields = TagSerializer.Meta.fields
|
||||||
|
#read_only_fields = TagSerializer.Meta.fields
|
||||||
|
|
||||||
def get_document_tag_url(self, instance):
|
#related_models = ('tags',)
|
||||||
return reverse(
|
#related_models_kwargs = {
|
||||||
viewname='rest_api:document-tag-detail', kwargs={
|
# 'documents': {
|
||||||
'document_pk': self.context['document'].pk,
|
## #'pk_list': 'tags_pk_list', 'model': Tag,
|
||||||
'tag_pk': instance.pk
|
# #'model': Tag,
|
||||||
}, request=self.context['request'], format=self.context['format']
|
# 'object_permission': {'create': permission_tag_attach},
|
||||||
|
# #'add_method': 'add', 'add_method_kwargs': 'document'
|
||||||
|
# }
|
||||||
|
#}
|
||||||
|
|
||||||
|
'''
|
||||||
|
def create(self, validated_data):
|
||||||
|
"""
|
||||||
|
queryset = Tag.objects.filter(pk__in=validated_data['tags_pk_list'].split(','))
|
||||||
|
|
||||||
|
#permission = self.object_permission.get('create')
|
||||||
|
|
||||||
|
#if permission:
|
||||||
|
queryset = AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission_tag_attach, queryset=queryset,
|
||||||
|
user=self.context['request'].user
|
||||||
)
|
)
|
||||||
|
|
||||||
def create(self, validated_data):
|
for tag in queryset.all():
|
||||||
queryset = AccessControlList.objects.filter_by_access(
|
tag.attach_to(
|
||||||
|
document=self.context['document'],
|
||||||
|
user=self.context['request'].user
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
queryset = AccessControlList.objects.restrict_queryset(
|
||||||
permission=permission_tag_attach, queryset=Tag.objects.all(),
|
permission=permission_tag_attach, queryset=Tag.objects.all(),
|
||||||
user=self.context['request'].user
|
user=self.context['request'].user
|
||||||
)
|
)
|
||||||
tag = get_object_or_404(queryset=queryset, pk=validated_data['tag_pk'])
|
tag = get_object_or_404(queryset=queryset, pk=validated_data['tag_pk'])
|
||||||
tag.documents.add(self.context['document'])
|
tag.attach_to(
|
||||||
|
document=self.context['document'],
|
||||||
|
user=self.context['request'].user
|
||||||
|
)
|
||||||
return tag
|
return tag
|
||||||
|
#return None
|
||||||
|
'''
|
||||||
|
|
||||||
|
def get_document_tag_url(self, instance):
|
||||||
|
return reverse(
|
||||||
|
viewname='rest_api:document-tag-detail', kwargs={
|
||||||
|
'document_id': self.context['document'].pk,
|
||||||
|
'tag_id': instance.pk
|
||||||
|
}, request=self.context['request'], format=self.context['format']
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DocumentTagAttachSerializer(serializers.Serializer):
|
||||||
|
tags_pk_list = serializers.CharField(
|
||||||
|
help_text=_(
|
||||||
|
'Comma separated list of tag primary keys that will be attached '
|
||||||
|
'to this document.'
|
||||||
|
), write_only=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TagAttachSerializer(serializers.Serializer):
|
||||||
|
#class TagAttachSerializer(TagSerializer):
|
||||||
|
documents_pk_list = serializers.CharField(
|
||||||
|
help_text=_(
|
||||||
|
'Comma separated list of document primary keys to which this '
|
||||||
|
'tag will be attached.'
|
||||||
|
), write_only=True
|
||||||
|
)
|
||||||
|
|
||||||
|
#class Meta(TagSerializer.Meta):
|
||||||
|
# fields = TagSerializer.Meta.fields + ('documents_pk_list',)
|
||||||
|
# read_only_fields = TagSerializer.Meta.fields
|
||||||
|
|
||||||
|
def attach(self, instance):
|
||||||
|
queryset = AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission_tag_attach, queryset=Document.objects.all(),
|
||||||
|
user=self.context['request'].user
|
||||||
|
)
|
||||||
|
|
||||||
|
for document in queryset.filter(pk__in=self.validated_data['documents_pk_list'].split(',')):
|
||||||
|
instance.attach_to(document=document, user=self.context['request'].user)
|
||||||
|
|
||||||
|
#print '@@@@@@@', self.validated_data['document_pk_list']
|
||||||
|
#print '@@@@@@@', instance
|
||||||
|
#print '22222', validated_data
|
||||||
|
#print '!!!', self.data['document_pk_list']
|
||||||
|
|
||||||
|
|
||||||
|
class TagRemoveSerializer(serializers.Serializer):
|
||||||
|
documents_pk_list = serializers.CharField(
|
||||||
|
help_text=_(
|
||||||
|
'Comma separated list of document primary keys from which this '
|
||||||
|
'tag will be removed.'
|
||||||
|
), write_only=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def remove(self, instance):
|
||||||
|
queryset = AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission_tag_attach, queryset=Document.objects.all(),
|
||||||
|
user=self.context['request'].user
|
||||||
|
)
|
||||||
|
|
||||||
|
for document in queryset.filter(pk__in=self.validated_data['documents_pk_list'].split(',')):
|
||||||
|
instance.remove_from(document=document, user=self.context['request'].user)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RelatedModel(object):
|
||||||
|
@classmethod
|
||||||
|
def generate(cls, serializer, validated_data):
|
||||||
|
result = []
|
||||||
|
|
||||||
|
kwargs = getattr(serializer.Meta, 'related_model_kwargs', {})
|
||||||
|
kwargs.update({'serializer': serializer})
|
||||||
|
|
||||||
|
for field_name in getattr(serializer.Meta, 'related_models', []):
|
||||||
|
kwargs.update({'field_name': field_name})
|
||||||
|
related_field = cls(**kwargs)
|
||||||
|
related_field.pop_pk_list(validated_data=validated_data)
|
||||||
|
result.append(related_field)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def __init__(self, field_name, serializer, pk_list_field=None, model=None, object_permission=None):
|
||||||
|
self.field_name = field_name
|
||||||
|
self._pk_list_field = pk_list_field
|
||||||
|
self.model = model
|
||||||
|
self.object_permission = object_permission
|
||||||
|
self.serializer = serializer
|
||||||
|
|
||||||
|
def create(self, instance):
|
||||||
|
field = self.get_field(instance=instance)
|
||||||
|
field.clear()
|
||||||
|
#model = self.get_model()
|
||||||
|
|
||||||
|
queryset = self.get_model().objects.filter(pk__in=self.pk_list.split(','))
|
||||||
|
|
||||||
|
permission = self.object_permission.get('create')
|
||||||
|
|
||||||
|
if permission:
|
||||||
|
queryset = AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission,
|
||||||
|
queryset=queryset,
|
||||||
|
user=self.serializer.context['request'].user
|
||||||
|
)
|
||||||
|
|
||||||
|
self.related_add()
|
||||||
|
|
||||||
|
field.add(*queryset)
|
||||||
|
#fieldqueryset=queryset)
|
||||||
|
|
||||||
|
#def related_add(self, queryset):
|
||||||
|
# self.get_field().add(*queryset)
|
||||||
|
|
||||||
|
|
||||||
|
#def _get_m2m_field(self, instance):
|
||||||
|
# getattr(instance, m2m_field_name).all()
|
||||||
|
|
||||||
|
"""
|
||||||
|
def _add_m2m(self, instance, m2m_pk_list, permission):
|
||||||
|
m2m_field = self._get_m2m_field()
|
||||||
|
m2m_field.clear()
|
||||||
|
|
||||||
|
queryset = AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission,
|
||||||
|
queryset=m2m_model.objects.filter(pk__in=m2m_pk_list.split(',')),
|
||||||
|
user=self.context['request'].user
|
||||||
|
)
|
||||||
|
|
||||||
|
#m2m_field.add(*queryset)
|
||||||
|
self._m2m_add(m2m_field=m2m_field, queryset=queryset)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
return self.model or self.get_field.model
|
||||||
|
|
||||||
|
def get_field(self, instance):
|
||||||
|
return getattr(instance, self.field_name)
|
||||||
|
|
||||||
|
def get_pk_list_field_name(self):
|
||||||
|
return self._pk_list_field or '{}_pk_list'.format(self.field_name)
|
||||||
|
|
||||||
|
def pop_pk_list(self, validated_data):
|
||||||
|
self.pk_list = validated_data.pop(self.get_pk_list_field_name(), '')
|
||||||
|
|
||||||
|
|
||||||
|
class RelatedModelSerializerMixin(object):
|
||||||
|
#m2m_pk_list_name = 'documents_pk_list'
|
||||||
|
#m2m_field_name = 'documents'
|
||||||
|
#m2m_model = Document
|
||||||
|
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
extra_kwargs = {
|
||||||
|
'url': {
|
||||||
|
'lookup_field': 'pk', 'lookup_url_kwarg': 'tag_pk',
|
||||||
|
'view_name': 'rest_api:tag-detail'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fields = (
|
||||||
|
'color', 'documents_count', 'documents_pk_list', 'documents_url',
|
||||||
|
'id', 'label', 'url'
|
||||||
|
)
|
||||||
|
model = Tag
|
||||||
|
related_models = ('documents',)
|
||||||
|
related_models_kwargs = {
|
||||||
|
'documents': {
|
||||||
|
'pk_list_field': 'documents_pk_list', 'model': Document,
|
||||||
|
'permissions': {'create': permission_tag_attach}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _get_m2m_field(self, instance):
|
||||||
|
getattr(instance, m2m_field_name).all()
|
||||||
|
|
||||||
|
def _add_m2m(self, instance, m2m_pk_list, permission):
|
||||||
|
m2m_field = self._get_m2m_field()
|
||||||
|
m2m_field.clear()
|
||||||
|
|
||||||
|
queryset = AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission,
|
||||||
|
queryset=m2m_model.objects.filter(pk__in=m2m_pk_list.split(',')),
|
||||||
|
user=self.context['request'].user
|
||||||
|
)
|
||||||
|
|
||||||
|
#m2m_field.add(*queryset)
|
||||||
|
self._m2m_add(m2m_field=m2m_field, queryset=queryset)
|
||||||
|
|
||||||
|
#def _m2m_add(self, m2m_field, queryset):
|
||||||
|
# m2m_field.add(*queryset)
|
||||||
|
|
||||||
|
def _m2m_add(self, m2m_field, queryset):
|
||||||
|
for document in queryset.all():
|
||||||
|
m2m_field.add(document=document, user=self.context['request'].user)
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
related_objects = RelatedModel.generate(
|
||||||
|
serializer=self, validated_data=validated_data
|
||||||
|
)
|
||||||
|
|
||||||
|
instance = super(RelatedModelSerializerMixin, self).create(
|
||||||
|
validated_data=validated_data
|
||||||
|
)
|
||||||
|
|
||||||
|
#TODO: return a container class
|
||||||
|
#TODO:related_objects.create(instance=instance)
|
||||||
|
for related_object in related_objects:
|
||||||
|
related_object.create(instance=instance)
|
||||||
|
|
||||||
|
#if m2m_pk_list:
|
||||||
|
## self._add_m2m(
|
||||||
|
# instance=instance, m2m_pk_list=m2m_pk_list,
|
||||||
|
# permission=permission_tag_add
|
||||||
|
# )
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|
||||||
|
'''
|
||||||
|
# Extract the related field data before calling the superclass
|
||||||
|
# .create() and avoid an error due to unknown field data.
|
||||||
|
|
||||||
|
#related_models = self.Meta.related_models
|
||||||
|
|
||||||
|
#self.Meta.related_models
|
||||||
|
related_models_dictionary = {}
|
||||||
|
for related_model in self.Meta.related_models:
|
||||||
|
|
||||||
|
#if self.m2m_pk_list_name:
|
||||||
|
m2m_pk_list = validated_data.pop(self.get_related_model_pk_list(), '')
|
||||||
|
|
||||||
|
instance = super(RelatedObjectSerializerMixin, self).create(
|
||||||
|
validated_data=validated_data
|
||||||
|
)
|
||||||
|
|
||||||
|
if m2m_pk_list:
|
||||||
|
self._add_m2m(
|
||||||
|
instance=instance, m2m_pk_list=m2m_pk_list,
|
||||||
|
permission=permission_tag_add
|
||||||
|
)
|
||||||
|
|
||||||
|
return instance
|
||||||
|
'''
|
||||||
|
|
||||||
|
|||||||
26
mayan/apps/tags/static/tags/js/tags_form.js
Normal file
26
mayan/apps/tags/static/tags/js/tags_form.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var tagSelectionTemplate = function (tag, container) {
|
||||||
|
var $tag = $(
|
||||||
|
'<span class="label label-tag" style="background: ' + tag.element.dataset.color + ';"> ' + escape(tag.text) + '</span>'
|
||||||
|
);
|
||||||
|
container[0].style.background = tag.element.dataset.color;
|
||||||
|
return $tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tagResultTemplate = function (tag) {
|
||||||
|
if (!tag.element) { return ''; }
|
||||||
|
var $tag = $(
|
||||||
|
'<span class="label label-tag" style="background: ' + tag.element.dataset.color + ';"> ' + escape(tag.text) + '</span>'
|
||||||
|
);
|
||||||
|
return $tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
jQuery(document).ready(function() {
|
||||||
|
$('.select2-tags').select2({
|
||||||
|
templateSelection: tagSelectionTemplate,
|
||||||
|
templateResult: tagResultTemplate,
|
||||||
|
width: '100%'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
5
mayan/apps/tags/templates/tags/document_tags_widget.html
Normal file
5
mayan/apps/tags/templates/tags/document_tags_widget.html
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<div class="tag-container">
|
||||||
|
{% for tag in tags %}
|
||||||
|
{% include 'tags/tag_widget.html' with tag=tag %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
@@ -1,2 +1 @@
|
|||||||
{% include 'django/forms/widgets/select_option.html' %}
|
{% include 'django/forms/widgets/select_option.html' %}
|
||||||
|
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ TEST_TAG_INDEX_HAS_TAG = 'HAS_TAG'
|
|||||||
TEST_TAG_INDEX_NO_TAG = 'NO_TAG'
|
TEST_TAG_INDEX_NO_TAG = 'NO_TAG'
|
||||||
TEST_TAG_INDEX_NODE_TEMPLATE = '''
|
TEST_TAG_INDEX_NODE_TEMPLATE = '''
|
||||||
{{% for tag in document.get_tags().all() %}}
|
{{% for tag in document.get_tags().all() %}}
|
||||||
{{% if tag.label == "{}" %}}
|
{{% if tag.label == "{label}" %}}
|
||||||
{}
|
{has_tag}
|
||||||
|
{{% else %}}
|
||||||
|
{not_tagged}
|
||||||
|
{{% endif %}}
|
||||||
{{% else %}}
|
{{% else %}}
|
||||||
NO_TAG
|
{not_tagged}
|
||||||
{{% endif %}}
|
|
||||||
{{% else %}}
|
|
||||||
NO_TAG
|
|
||||||
{{% endfor %}}
|
{{% endfor %}}
|
||||||
'''.format(
|
'''.format(
|
||||||
TEST_TAG_LABEL, TEST_TAG_INDEX_HAS_TAG, TEST_TAG_INDEX_NO_TAG,
|
label=TEST_TAG_LABEL, has_tag=TEST_TAG_INDEX_HAS_TAG,
|
||||||
TEST_TAG_INDEX_NO_TAG
|
not_tagged=TEST_TAG_INDEX_NO_TAG
|
||||||
).replace('\n', '')
|
).replace('\n', '')
|
||||||
|
|||||||
@@ -9,39 +9,100 @@ from .literals import (
|
|||||||
|
|
||||||
|
|
||||||
class TagTestMixin(object):
|
class TagTestMixin(object):
|
||||||
def _create_tag(self):
|
def _create_test_tag(self):
|
||||||
self.tag = Tag.objects.create(
|
self.test_tag = Tag.objects.create(
|
||||||
color=TEST_TAG_COLOR, label=TEST_TAG_LABEL
|
color=TEST_TAG_COLOR, label=TEST_TAG_LABEL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TagAPITestMixin(object):
|
||||||
def _request_api_tag_create_view(self):
|
def _request_api_tag_create_view(self):
|
||||||
return self.post(
|
return self.post(
|
||||||
viewname='rest_api:tag-list', data={
|
viewname='rest_api:tag-list', data={
|
||||||
'label': TEST_TAG_LABEL, 'color': TEST_TAG_COLOR
|
'color': TEST_TAG_COLOR, 'label': TEST_TAG_LABEL
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def _request_api_tag_create_and_attach_view(self):
|
||||||
|
return self.post(
|
||||||
|
viewname='rest_api:tag-list', data={
|
||||||
|
'color': TEST_TAG_COLOR, 'label': TEST_TAG_LABEL,
|
||||||
|
'document_id_list': self.document.pk
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def _request_api_tag_delete_view(self):
|
def _request_api_tag_delete_view(self):
|
||||||
return self.delete(
|
return self.delete(
|
||||||
viewname='rest_api:tag-detail', kwargs={'tag_pk': self.tag.pk}
|
viewname='rest_api:tag-detail', kwargs={'tag_id': self.test_tag.pk}
|
||||||
)
|
)
|
||||||
|
|
||||||
def _request_api_tag_edit_via_patch_view(self):
|
def _request_api_tag_edit_patch_view(self):
|
||||||
return self.patch(
|
return self.patch(
|
||||||
viewname='rest_api:tag-detail', kwargs={'tag_pk': self.tag.pk}, data={
|
viewname='rest_api:tag-detail', kwargs={
|
||||||
|
'tag_id': self.test_tag.pk
|
||||||
|
}, data={
|
||||||
'label': TEST_TAG_LABEL_EDITED,
|
'label': TEST_TAG_LABEL_EDITED,
|
||||||
'color': TEST_TAG_COLOR_EDITED
|
'color': TEST_TAG_COLOR_EDITED
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def _request_api_tag_edit_via_put_view(self):
|
def _request_api_tag_edit_put_view(self):
|
||||||
return self.put(
|
return self.put(
|
||||||
viewname='rest_api:tag-detail', kwargs={'tag_pk': self.tag.pk}, data={
|
viewname='rest_api:tag-detail', kwargs={
|
||||||
|
'tag_id': self.test_tag.pk
|
||||||
|
}, data={
|
||||||
'label': TEST_TAG_LABEL_EDITED,
|
'label': TEST_TAG_LABEL_EDITED,
|
||||||
'color': TEST_TAG_COLOR_EDITED
|
'color': TEST_TAG_COLOR_EDITED
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _request_api_tag_list_view(self):
|
||||||
|
return self.get(viewname='rest_api:tag-list')
|
||||||
|
|
||||||
|
|
||||||
|
class TagViewTestMixin(object):
|
||||||
|
def _request_document_tag_multiple_attach_view(self):
|
||||||
|
return self.post(
|
||||||
|
viewname='tags:document_tag_multiple_attach',
|
||||||
|
kwargs={'document_id': self.document.pk}, data={
|
||||||
|
'tags': self.test_tag.pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def _request_document_multiple_tag_multiple_attach_view(self):
|
||||||
|
return self.post(
|
||||||
|
viewname='tags:document_multiple_tag_multiple_attach', data={
|
||||||
|
'id_list': self.document.pk, 'tags': self.test_tag.pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def _request_document_tag_multiple_remove_view(self):
|
||||||
|
return self.post(
|
||||||
|
viewname='tags:document_tag_multiple_remove',
|
||||||
|
kwargs={'document_id': self.document.pk}, data={
|
||||||
|
'tags': self.test_tag.pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def _request_document_multiple_tag_multiple_remove_view(self):
|
||||||
|
return self.post(
|
||||||
|
viewname='tags:document_multiple_tag_multiple_remove',
|
||||||
|
data={
|
||||||
|
'id_list': self.document.pk,
|
||||||
|
'tags': self.test_tag.pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def _request_document_tag_list_view(self):
|
||||||
|
return self.get(
|
||||||
|
viewname='tags:document_tag_list',
|
||||||
|
kwargs={
|
||||||
|
'document_id': self.document.pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Normal tag view
|
||||||
|
|
||||||
def _request_tag_create_view(self):
|
def _request_tag_create_view(self):
|
||||||
return self.post(
|
return self.post(
|
||||||
viewname='tags:tag_create', data={
|
viewname='tags:tag_create', data={
|
||||||
@@ -52,68 +113,19 @@ class TagTestMixin(object):
|
|||||||
|
|
||||||
def _request_tag_delete_view(self):
|
def _request_tag_delete_view(self):
|
||||||
return self.post(
|
return self.post(
|
||||||
viewname='tags:tag_delete', kwargs={'tag_pk': self.tag.pk}
|
viewname='tags:tag_delete', kwargs={'tag_id': self.test_tag.pk},
|
||||||
)
|
)
|
||||||
|
|
||||||
def _request_tag_edit_view(self):
|
def _request_tag_edit_view(self):
|
||||||
return self.post(
|
return self.post(
|
||||||
viewname='tags:tag_edit', kwargs={'tag_pk': self.tag.pk}, data={
|
viewname='tags:tag_edit', kwargs={'tag_id': self.test_tag.pk},
|
||||||
|
data={
|
||||||
'label': TEST_TAG_LABEL_EDITED, 'color': TEST_TAG_COLOR_EDITED
|
'label': TEST_TAG_LABEL_EDITED, 'color': TEST_TAG_COLOR_EDITED
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def _request_multiple_delete_view(self):
|
def _request_tag_multiple_delete_view(self):
|
||||||
return self.post(
|
return self.post(
|
||||||
viewname='tags:tag_multiple_delete',
|
viewname='tags:tag_multiple_delete',
|
||||||
data={'id_list': self.tag.pk},
|
data={'id_list': self.test_tag.pk}
|
||||||
)
|
|
||||||
|
|
||||||
def _request_edit_tag_view(self):
|
|
||||||
return self.post(
|
|
||||||
viewname='tags:tag_edit', kwargs={'tag_pk': self.tag.pk}, data={
|
|
||||||
'label': TEST_TAG_LABEL_EDITED, 'color': TEST_TAG_COLOR_EDITED
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
def _request_create_tag_view(self):
|
|
||||||
return self.post(
|
|
||||||
viewname='tags:tag_create', data={
|
|
||||||
'label': TEST_TAG_LABEL,
|
|
||||||
'color': TEST_TAG_COLOR
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
def _request_attach_tag_view(self):
|
|
||||||
return self.post(
|
|
||||||
viewname='tags:tag_attach',
|
|
||||||
kwargs={'document_pk': self.document.pk}, data={
|
|
||||||
'tags': self.tag.pk,
|
|
||||||
'user': self.user.pk
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
def _request_multiple_attach_tag_view(self):
|
|
||||||
return self.post(
|
|
||||||
viewname='tags:multiple_documents_tag_attach', data={
|
|
||||||
'id_list': self.document.pk, 'tags': self.tag.pk,
|
|
||||||
'user': self.user.pk
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
def _request_single_document_multiple_tag_remove_view(self):
|
|
||||||
return self.post(
|
|
||||||
viewname='tags:single_document_multiple_tag_remove',
|
|
||||||
kwargs={'document_pk': self.document.pk}, data={
|
|
||||||
'id_list': self.document.pk,
|
|
||||||
'tags': self.tag.pk,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
def _request_multiple_documents_selection_tag_remove_view(self):
|
|
||||||
return self.post(
|
|
||||||
viewname='tags:multiple_documents_selection_tag_remove',
|
|
||||||
data={
|
|
||||||
'id_list': self.document.pk,
|
|
||||||
'tags': self.tag.pk,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,11 +21,7 @@ from .literals import (
|
|||||||
from .mixins import TagTestMixin
|
from .mixins import TagTestMixin
|
||||||
|
|
||||||
|
|
||||||
class TagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
|
class TagAPITestCase(TagTestMixin, BaseAPITestCase):
|
||||||
def setUp(self):
|
|
||||||
super(TagAPITestCase, self).setUp()
|
|
||||||
self.login_user()
|
|
||||||
|
|
||||||
def test_tag_create_view_no_permission(self):
|
def test_tag_create_view_no_permission(self):
|
||||||
response = self._request_api_tag_create_view()
|
response = self._request_api_tag_create_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||||
@@ -46,284 +42,301 @@ class TagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
|
|||||||
self.assertEqual(tag.color, TEST_TAG_COLOR)
|
self.assertEqual(tag.color, TEST_TAG_COLOR)
|
||||||
|
|
||||||
def test_tag_delete_view_no_access(self):
|
def test_tag_delete_view_no_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
response = self._request_api_tag_delete_view()
|
response = self._request_api_tag_delete_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.assertTrue(self.tag in Tag.objects.all())
|
self.assertTrue(self.test_tag in Tag.objects.all())
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def test_tag_delete_view_with_access(self):
|
def test_tag_delete_view_with_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_delete)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_delete)
|
||||||
response = self._request_api_tag_delete_view()
|
response = self._request_api_tag_delete_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||||
self.assertEqual(Tag.objects.all().count(), 0)
|
self.assertEqual(Tag.objects.all().count(), 0)
|
||||||
|
|
||||||
def test_tag_edit_via_patch_no_access(self):
|
def test_tag_edit_patch_view_no_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
response = self._request_api_tag_edit_via_patch_view()
|
response = self._request_api_tag_edit_patch_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.tag.refresh_from_db()
|
self.test_tag.refresh_from_db()
|
||||||
self.assertEqual(self.tag.label, TEST_TAG_LABEL)
|
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL)
|
||||||
self.assertEqual(self.tag.color, TEST_TAG_COLOR)
|
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR)
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def test_tag_edit_via_patch_with_access(self):
|
def test_tag_edit_patch_view_with_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_edit)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_edit)
|
||||||
response = self._request_api_tag_edit_via_patch_view()
|
response = self._request_api_tag_edit_patch_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.tag.refresh_from_db()
|
self.test_tag.refresh_from_db()
|
||||||
self.assertEqual(self.tag.label, TEST_TAG_LABEL_EDITED)
|
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL_EDITED)
|
||||||
self.assertEqual(self.tag.color, TEST_TAG_COLOR_EDITED)
|
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR_EDITED)
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def test_tag_edit_via_put_no_access(self):
|
def test_tag_edit_put_view_no_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
response = self._request_api_tag_edit_via_put_view()
|
response = self._request_api_tag_edit_put_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.tag.refresh_from_db()
|
self.test_tag.refresh_from_db()
|
||||||
self.assertEqual(self.tag.label, TEST_TAG_LABEL)
|
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL)
|
||||||
self.assertEqual(self.tag.color, TEST_TAG_COLOR)
|
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR)
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def test_tag_edit_via_put_with_access(self):
|
def test_tag_edit_put_view_with_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_edit)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_edit)
|
||||||
response = self._request_api_tag_edit_via_put_view()
|
response = self._request_api_tag_edit_put_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.tag.refresh_from_db()
|
self.test_tag.refresh_from_db()
|
||||||
self.assertEqual(self.tag.label, TEST_TAG_LABEL_EDITED)
|
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL_EDITED)
|
||||||
self.assertEqual(self.tag.color, TEST_TAG_COLOR_EDITED)
|
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR_EDITED)
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
|
def test_tag_list_view_no_access(self):
|
||||||
class DocumentAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
|
self._create_test_tag()
|
||||||
auto_upload_document = False
|
response = self._request_api_tag_list_view()
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(DocumentAPITestCase, self).setUp()
|
|
||||||
self.login_user()
|
|
||||||
|
|
||||||
def _request_api_tag_document_list_view(self):
|
|
||||||
return self.get(
|
|
||||||
viewname='rest_api:tag-document-list',
|
|
||||||
kwargs={'tag_pk': self.tag.pk}
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_tag_document_list_view_no_access(self):
|
|
||||||
self._create_tag()
|
|
||||||
self.document = self.upload_document()
|
|
||||||
self.tag.documents.add(self.document)
|
|
||||||
response = self._request_api_tag_document_list_view()
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
||||||
|
|
||||||
def test_tag_document_list_view_with_tag_access(self):
|
|
||||||
self._create_tag()
|
|
||||||
self.document = self.upload_document()
|
|
||||||
self.tag.documents.add(self.document)
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
|
||||||
response = self._request_api_tag_document_list_view()
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.assertEqual(response.data['count'], 0)
|
self.assertEqual(response.data['count'], 0)
|
||||||
|
|
||||||
def test_tag_document_list_view_with_document_access(self):
|
def test_tag_list_view_with_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
self.tag.documents.add(self.document)
|
response = self._request_api_tag_list_view()
|
||||||
self.grant_access(
|
|
||||||
obj=self.document, permission=permission_document_view
|
|
||||||
)
|
|
||||||
response = self._request_api_tag_document_list_view()
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
||||||
|
|
||||||
def test_tag_document_list_view_with_access(self):
|
|
||||||
self._create_tag()
|
|
||||||
self.document = self.upload_document()
|
|
||||||
self.tag.documents.add(self.document)
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
|
||||||
self.grant_access(
|
|
||||||
obj=self.document, permission=permission_document_view
|
|
||||||
)
|
|
||||||
response = self._request_api_tag_document_list_view()
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.assertEqual(
|
self.assertEqual(response.data['count'], 1)
|
||||||
response.data['results'][0]['uuid'],
|
|
||||||
force_text(self.document.uuid)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _request_api_document_attach_tag_view(self):
|
|
||||||
|
class DocumentTagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
|
||||||
|
auto_upload_document = False
|
||||||
|
|
||||||
|
def _request_api_document_tag_attach_view(self):
|
||||||
return self.post(
|
return self.post(
|
||||||
viewname='rest_api:document-tag-list',
|
viewname='rest_api:document-tag-list',
|
||||||
kwargs={'document_pk': self.document.pk},
|
kwargs={'document_id': self.test_document.pk},
|
||||||
data={'tag_pk': self.tag.pk}
|
data={'tag_id': self.test_tag.pk}
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_document_attach_tag_view_no_access(self):
|
def test_document_tag_attach_view_no_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
response = self._request_api_document_attach_tag_view()
|
response = self._request_api_document_tag_attach_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.assertTrue(self.tag not in self.document.tags.all())
|
self.assertTrue(self.test_tag not in self.test_document.tags.all())
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def test_document_attach_tag_view_with_document_access(self):
|
def test_document_tag_attach_view_with_document_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.grant_access(obj=self.document, permission=permission_tag_attach)
|
self.grant_access(obj=self.test_document, permission=permission_tag_attach)
|
||||||
response = self._request_api_document_attach_tag_view()
|
response = self._request_api_document_tag_attach_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.assertTrue(self.tag not in self.document.tags.all())
|
self.assertTrue(self.test_tag not in self.test_document.tags.all())
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def test_document_attach_tag_view_with_tag_access(self):
|
def test_document_tag_attach_view_with_tag_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_attach)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
|
||||||
response = self._request_api_document_attach_tag_view()
|
response = self._request_api_document_tag_attach_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.assertTrue(self.tag not in self.document.tags.all())
|
self.assertTrue(self.test_tag not in self.test_document.tags.all())
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def test_document_attach_tag_view_with_full_access(self):
|
def test_document_tag_attach_view_with_full_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.grant_access(obj=self.document, permission=permission_tag_attach)
|
self.grant_access(
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_attach)
|
obj=self.test_document, permission=permission_tag_attach
|
||||||
response = self._request_api_document_attach_tag_view()
|
)
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
|
||||||
|
response = self._request_api_document_tag_attach_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||||
self.assertTrue(self.tag in self.document.tags.all())
|
self.assertTrue(self.test_tag in self.test_document.tags.all())
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def _request_api_document_tag_detail_view(self):
|
def _request_api_document_tag_detail_view(self):
|
||||||
return self.get(
|
return self.get(
|
||||||
viewname='rest_api:document-tag-detail', kwargs={
|
viewname='rest_api:document-tag-detail', kwargs={
|
||||||
'document_pk': self.document.pk, 'tag_pk': self.tag.pk
|
'document_id': self.test_document.pk, 'tag_id': self.test_tag.pk
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_document_tag_detail_view_no_permission(self):
|
def test_document_tag_detail_view_no_permission(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
response = self._request_api_document_tag_detail_view()
|
response = self._request_api_document_tag_detail_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
def test_document_tag_detail_view_with_document_access(self):
|
def test_document_tag_detail_view_with_document_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
self.grant_access(
|
self.grant_access(
|
||||||
obj=self.document, permission=permission_document_view
|
obj=self.test_document, permission=permission_document_view
|
||||||
)
|
)
|
||||||
response = self._request_api_document_tag_detail_view()
|
response = self._request_api_document_tag_detail_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
def test_document_tag_detail_view_with_tag_access(self):
|
def test_document_tag_detail_view_with_tag_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
response = self._request_api_document_tag_detail_view()
|
response = self._request_api_document_tag_detail_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
def test_document_tag_detail_view_with_full_access(self):
|
def test_document_tag_detail_view_with_full_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
self.grant_access(
|
self.grant_access(
|
||||||
obj=self.document, permission=permission_tag_view
|
obj=self.test_document, permission=permission_tag_view
|
||||||
)
|
)
|
||||||
response = self._request_api_document_tag_detail_view()
|
response = self._request_api_document_tag_detail_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.assertEqual(response.data['label'], self.tag.label)
|
self.assertEqual(response.data['label'], self.test_tag.label)
|
||||||
|
|
||||||
def _request_api_document_tag_list_view(self):
|
def _request_api_document_tag_list_view(self):
|
||||||
return self.get(
|
return self.get(
|
||||||
viewname='rest_api:document-tag-list',
|
viewname='rest_api:document-tag-list',
|
||||||
kwargs={'document_pk': self.document.pk}
|
kwargs={'document_id': self.test_document.pk}
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_document_tag_list_view_no_access(self):
|
def test_document_tag_list_view_no_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
response = self._request_api_document_tag_list_view()
|
response = self._request_api_document_tag_list_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
def test_document_tag_list_view_with_document_access(self):
|
def test_document_tag_list_view_with_document_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
self.grant_access(obj=self.document, permission=permission_tag_view)
|
self.grant_access(obj=self.test_document, permission=permission_tag_view)
|
||||||
response = self._request_api_document_tag_list_view()
|
response = self._request_api_document_tag_list_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.assertEqual(response.data['count'], 0)
|
self.assertEqual(response.data['count'], 0)
|
||||||
|
|
||||||
def test_document_tag_list_view_with_tag_access(self):
|
def test_document_tag_list_view_with_tag_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
response = self._request_api_document_tag_list_view()
|
response = self._request_api_document_tag_list_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
def test_document_tag_list_view_with_full_access(self):
|
def test_document_tag_list_view_with_full_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
self.grant_access(obj=self.document, permission=permission_tag_view)
|
self.grant_access(obj=self.test_document, permission=permission_tag_view)
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
response = self._request_api_document_tag_list_view()
|
response = self._request_api_document_tag_list_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.assertEqual(response.data['results'][0]['label'], self.tag.label)
|
self.assertEqual(
|
||||||
|
response.data['results'][0]['label'], self.test_tag.label
|
||||||
|
)
|
||||||
|
|
||||||
def _request_api_document_tag_remove_view(self):
|
def _request_api_document_tag_remove_view(self):
|
||||||
return self.delete(
|
return self.delete(
|
||||||
viewname='rest_api:document-tag-detail', kwargs={
|
viewname='rest_api:document-tag-detail', kwargs={
|
||||||
'document_pk': self.document.pk, 'tag_pk': self.tag.pk
|
'document_id': self.test_document.pk, 'tag_id': self.test_tag.pk
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_document_tag_remove_view_no_access(self):
|
def test_document_tag_remove_view_no_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
response = self._request_api_document_tag_remove_view()
|
response = self._request_api_document_tag_remove_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.assertTrue(self.tag in self.document.tags.all())
|
self.assertTrue(self.test_tag in self.test_document.tags.all())
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def test_document_tag_remove_view_with_document_access(self):
|
def test_document_tag_remove_view_with_document_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
self.grant_access(obj=self.document, permission=permission_tag_remove)
|
self.grant_access(obj=self.test_document, permission=permission_tag_remove)
|
||||||
response = self._request_api_document_tag_remove_view()
|
response = self._request_api_document_tag_remove_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.assertTrue(self.tag in self.document.tags.all())
|
self.assertTrue(self.test_tag in self.test_document.tags.all())
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def test_document_tag_remove_view_with_tag_access(self):
|
def test_document_tag_remove_view_with_tag_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_remove)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_remove)
|
||||||
response = self._request_api_document_tag_remove_view()
|
response = self._request_api_document_tag_remove_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.assertTrue(self.tag in self.document.tags.all())
|
self.assertTrue(self.test_tag in self.test_document.tags.all())
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
def test_document_tag_remove_view_with_full_access(self):
|
def test_document_tag_remove_view_with_full_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.document = self.upload_document()
|
self.test_document = self.upload_document()
|
||||||
self.tag.documents.add(self.document)
|
self.test_tag.documents.add(self.test_document)
|
||||||
self.grant_access(
|
self.grant_access(
|
||||||
obj=self.document, permission=permission_tag_remove
|
obj=self.test_document, permission=permission_tag_remove
|
||||||
)
|
)
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_remove)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_remove)
|
||||||
response = self._request_api_document_tag_remove_view()
|
response = self._request_api_document_tag_remove_view()
|
||||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||||
self.assertFalse(self.tag in self.document.tags.all())
|
self.assertFalse(self.test_tag in self.test_document.tags.all())
|
||||||
self.assertEqual(Tag.objects.all().count(), 1)
|
self.assertEqual(Tag.objects.all().count(), 1)
|
||||||
|
|
||||||
|
|
||||||
|
class TagDocumentAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
|
||||||
|
auto_upload_document = False
|
||||||
|
|
||||||
|
def _request_api_tag_document_list_view(self):
|
||||||
|
return self.get(
|
||||||
|
viewname='rest_api:tag-document-list',
|
||||||
|
kwargs={'tag_id': self.test_tag.pk}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_tag_document_list_view_no_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
self.test_document = self.upload_document()
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
response = self._request_api_tag_document_list_view()
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
|
def test_tag_document_list_view_with_tag_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
self.test_document = self.upload_document()
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
|
response = self._request_api_tag_document_list_view()
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
self.assertEqual(response.data['count'], 0)
|
||||||
|
|
||||||
|
def test_tag_document_list_view_with_document_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
self.test_document = self.upload_document()
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_document_view
|
||||||
|
)
|
||||||
|
response = self._request_api_tag_document_list_view()
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
|
def test_tag_document_list_view_with_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
self.test_document = self.upload_document()
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_document_view
|
||||||
|
)
|
||||||
|
response = self._request_api_tag_document_list_view()
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
self.assertEqual(
|
||||||
|
response.data['results'][0]['uuid'],
|
||||||
|
force_text(self.test_document.uuid)
|
||||||
|
)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from ..permissions import permission_tag_create, permission_tag_edit
|
|||||||
|
|
||||||
from .mixins import TagTestMixin
|
from .mixins import TagTestMixin
|
||||||
|
|
||||||
|
#TODO: Add tests for event_tag_remove and event_tag_attach
|
||||||
class TagEventsTestCase(TagTestMixin, GenericDocumentViewTestCase):
|
class TagEventsTestCase(TagTestMixin, GenericDocumentViewTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TagEventsTestCase, self).setUp()
|
super(TagEventsTestCase, self).setUp()
|
||||||
@@ -38,10 +38,10 @@ class TagEventsTestCase(TagTestMixin, GenericDocumentViewTestCase):
|
|||||||
|
|
||||||
self.assertEqual(event.verb, event_tag_created.id)
|
self.assertEqual(event.verb, event_tag_created.id)
|
||||||
self.assertEqual(event.target, tag)
|
self.assertEqual(event.target, tag)
|
||||||
self.assertEqual(event.actor, self.user)
|
self.assertEqual(event.actor, self._test_case_user)
|
||||||
|
|
||||||
def test_tag_edit_event_no_permissions(self):
|
def test_tag_edit_event_no_permissions(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
Action.objects.all().delete()
|
Action.objects.all().delete()
|
||||||
|
|
||||||
response = self._request_tag_edit_view()
|
response = self._request_tag_edit_view()
|
||||||
@@ -49,11 +49,11 @@ class TagEventsTestCase(TagTestMixin, GenericDocumentViewTestCase):
|
|||||||
self.assertEqual(Action.objects.count(), 0)
|
self.assertEqual(Action.objects.count(), 0)
|
||||||
|
|
||||||
def test_tag_edit_event_with_access(self):
|
def test_tag_edit_event_with_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
Action.objects.all().delete()
|
Action.objects.all().delete()
|
||||||
|
|
||||||
self.grant_access(
|
self.grant_access(
|
||||||
permission=permission_tag_edit, obj=self.tag
|
permission=permission_tag_edit, obj=self.test_tag
|
||||||
)
|
)
|
||||||
|
|
||||||
response = self._request_tag_edit_view()
|
response = self._request_tag_edit_view()
|
||||||
@@ -63,5 +63,5 @@ class TagEventsTestCase(TagTestMixin, GenericDocumentViewTestCase):
|
|||||||
event = Action.objects.first()
|
event = Action.objects.first()
|
||||||
|
|
||||||
self.assertEqual(event.verb, event_tag_edited.id)
|
self.assertEqual(event.verb, event_tag_edited.id)
|
||||||
self.assertEqual(event.target, self.tag)
|
self.assertEqual(event.target, self.test_tag)
|
||||||
self.assertEqual(event.actor, self.user)
|
self.assertEqual(event.actor, self._test_case_user)
|
||||||
|
|||||||
@@ -11,9 +11,10 @@ from .literals import (
|
|||||||
TEST_TAG_COLOR, TEST_TAG_LABEL, TEST_TAG_INDEX_HAS_TAG,
|
TEST_TAG_COLOR, TEST_TAG_LABEL, TEST_TAG_INDEX_HAS_TAG,
|
||||||
TEST_TAG_INDEX_NO_TAG, TEST_TAG_INDEX_NODE_TEMPLATE
|
TEST_TAG_INDEX_NO_TAG, TEST_TAG_INDEX_NODE_TEMPLATE
|
||||||
)
|
)
|
||||||
|
from .mixins import TagTestMixin
|
||||||
|
|
||||||
|
|
||||||
class TagSignalIndexingTestCase(DocumentTestMixin, BaseTestCase):
|
class TagSignalIndexingTestCase(TagTestMixin, DocumentTestMixin, BaseTestCase):
|
||||||
auto_upload_document = False
|
auto_upload_document = False
|
||||||
|
|
||||||
def test_tag_indexing(self):
|
def test_tag_indexing(self):
|
||||||
@@ -27,7 +28,8 @@ class TagSignalIndexingTestCase(DocumentTestMixin, BaseTestCase):
|
|||||||
link_documents=True
|
link_documents=True
|
||||||
)
|
)
|
||||||
|
|
||||||
tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL)
|
self._create_test_tag()
|
||||||
|
|
||||||
self.document = self.upload_document()
|
self.document = self.upload_document()
|
||||||
|
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
@@ -36,7 +38,7 @@ class TagSignalIndexingTestCase(DocumentTestMixin, BaseTestCase):
|
|||||||
).documents.all()
|
).documents.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
tag.documents.add(self.document)
|
self.test_tag.documents.add(self.document)
|
||||||
|
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
self.document in IndexInstanceNode.objects.get(
|
self.document in IndexInstanceNode.objects.get(
|
||||||
@@ -44,7 +46,7 @@ class TagSignalIndexingTestCase(DocumentTestMixin, BaseTestCase):
|
|||||||
).documents.all()
|
).documents.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
tag.delete()
|
self.test_tag.delete()
|
||||||
|
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
self.document in IndexInstanceNode.objects.get(
|
self.document in IndexInstanceNode.objects.get(
|
||||||
|
|||||||
41
mayan/apps/tags/tests/test_links.py
Normal file
41
mayan/apps/tags/tests/test_links.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from mayan.apps.documents.tests import GenericDocumentViewTestCase
|
||||||
|
|
||||||
|
from ..links import link_document_tag_list
|
||||||
|
from ..permissions import permission_tag_view
|
||||||
|
|
||||||
|
from .mixins import TagTestMixin
|
||||||
|
|
||||||
|
|
||||||
|
class DocumentLinksTestCase(TagTestMixin, GenericDocumentViewTestCase):
|
||||||
|
def _request_document_tag_list_link(self):
|
||||||
|
self.add_test_view(test_object=self.document)
|
||||||
|
context = self.get_test_view()
|
||||||
|
return link_document_tag_list.resolve(context=context)
|
||||||
|
|
||||||
|
def test_document_tag_list_no_permission(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
resolved_link = self._request_document_tag_list_link()
|
||||||
|
self.assertEqual(resolved_link, None)
|
||||||
|
|
||||||
|
def test_document_tag_list_with_full_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.document, permission=permission_tag_view
|
||||||
|
)
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.test_tag, permission=permission_tag_view
|
||||||
|
)
|
||||||
|
resolved_link = self._request_document_tag_list_link()
|
||||||
|
|
||||||
|
self.assertNotEqual(resolved_link, None)
|
||||||
|
self.assertEqual(
|
||||||
|
resolved_link.url,
|
||||||
|
reverse(
|
||||||
|
viewname='tags:document_tag_list',
|
||||||
|
kwargs={'document_id': self.document.pk}
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
from mayan.apps.common.tests import GenericViewTestCase
|
from mayan.apps.common.tests import GenericViewTestCase
|
||||||
from mayan.apps.documents.permissions import permission_document_view
|
from mayan.apps.documents.permissions import permission_document_view
|
||||||
from mayan.apps.documents.tests import GenericDocumentViewTestCase
|
from mayan.apps.documents.tests import GenericDocumentViewTestCase
|
||||||
@@ -14,21 +16,17 @@ from .literals import (
|
|||||||
TEST_TAG_COLOR, TEST_TAG_COLOR_EDITED, TEST_TAG_LABEL,
|
TEST_TAG_COLOR, TEST_TAG_COLOR_EDITED, TEST_TAG_LABEL,
|
||||||
TEST_TAG_LABEL_EDITED
|
TEST_TAG_LABEL_EDITED
|
||||||
)
|
)
|
||||||
from .mixins import TagTestMixin
|
from .mixins import TagTestMixin, TagViewTestMixin
|
||||||
|
|
||||||
|
|
||||||
class TagViewTestCase(TagTestMixin, GenericViewTestCase):
|
class TagViewTestCase(TagViewTestMixin, TagTestMixin, GenericViewTestCase):
|
||||||
def test_tag_create_view_no_permissions(self):
|
def test_tag_create_view_no_permissions(self):
|
||||||
self.login_user()
|
|
||||||
|
|
||||||
response = self._request_tag_create_view()
|
response = self._request_tag_create_view()
|
||||||
self.assertEqual(response.status_code, 403)
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
self.assertEqual(Tag.objects.count(), 0)
|
self.assertEqual(Tag.objects.count(), 0)
|
||||||
|
|
||||||
def test_tag_create_view_with_permissions(self):
|
def test_tag_create_view_with_permissions(self):
|
||||||
self.login_user()
|
|
||||||
|
|
||||||
self.grant_permission(permission=permission_tag_create)
|
self.grant_permission(permission=permission_tag_create)
|
||||||
response = self._request_tag_create_view()
|
response = self._request_tag_create_view()
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
@@ -39,18 +37,16 @@ class TagViewTestCase(TagTestMixin, GenericViewTestCase):
|
|||||||
self.assertEqual(tag.color, TEST_TAG_COLOR)
|
self.assertEqual(tag.color, TEST_TAG_COLOR)
|
||||||
|
|
||||||
def test_tag_delete_view_no_permissions(self):
|
def test_tag_delete_view_no_permissions(self):
|
||||||
self.login_user()
|
self._create_test_tag()
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
response = self._request_tag_delete_view()
|
response = self._request_tag_delete_view()
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 404)
|
||||||
self.assertEqual(Tag.objects.count(), 1)
|
self.assertEqual(Tag.objects.count(), 1)
|
||||||
|
|
||||||
def test_tag_delete_view_with_access(self):
|
def test_tag_delete_view_with_access(self):
|
||||||
self.login_user()
|
self._create_test_tag()
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_delete)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_delete)
|
||||||
|
|
||||||
response = self._request_tag_delete_view()
|
response = self._request_tag_delete_view()
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
@@ -58,190 +54,295 @@ class TagViewTestCase(TagTestMixin, GenericViewTestCase):
|
|||||||
self.assertEqual(Tag.objects.count(), 0)
|
self.assertEqual(Tag.objects.count(), 0)
|
||||||
|
|
||||||
def test_tag_multiple_delete_view_no_permissions(self):
|
def test_tag_multiple_delete_view_no_permissions(self):
|
||||||
self.login_user()
|
self._create_test_tag()
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
response = self._request_multiple_delete_view()
|
response = self._request_tag_multiple_delete_view()
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 404)
|
||||||
self.assertEqual(Tag.objects.count(), 1)
|
self.assertEqual(Tag.objects.count(), 1)
|
||||||
|
|
||||||
def test_tag_multiple_delete_view_with_access(self):
|
def test_tag_multiple_delete_view_with_access(self):
|
||||||
self.login_user()
|
self._create_test_tag()
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_delete)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_delete)
|
||||||
|
|
||||||
response = self._request_multiple_delete_view()
|
response = self._request_tag_multiple_delete_view()
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
self.assertEqual(Tag.objects.count(), 0)
|
self.assertEqual(Tag.objects.count(), 0)
|
||||||
|
|
||||||
def test_tag_edit_view_no_permissions(self):
|
def test_tag_edit_view_no_permissions(self):
|
||||||
self.login_user()
|
self._create_test_tag()
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
response = self._request_edit_tag_view()
|
response = self._request_tag_edit_view()
|
||||||
self.assertEqual(response.status_code, 404)
|
self.assertEqual(response.status_code, 404)
|
||||||
tag = Tag.objects.get(pk=self.tag.pk)
|
tag = Tag.objects.get(pk=self.test_tag.pk)
|
||||||
self.assertEqual(tag.label, TEST_TAG_LABEL)
|
self.assertEqual(tag.label, TEST_TAG_LABEL)
|
||||||
self.assertEqual(tag.color, TEST_TAG_COLOR)
|
self.assertEqual(tag.color, TEST_TAG_COLOR)
|
||||||
|
|
||||||
def test_tag_edit_view_with_access(self):
|
def test_tag_edit_view_with_access(self):
|
||||||
self.login_user()
|
self._create_test_tag()
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_edit)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_edit)
|
||||||
|
|
||||||
response = self._request_edit_tag_view()
|
response = self._request_tag_edit_view()
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
tag = Tag.objects.get(pk=self.tag.pk)
|
tag = Tag.objects.get(pk=self.test_tag.pk)
|
||||||
self.assertEqual(tag.label, TEST_TAG_LABEL_EDITED)
|
self.assertEqual(tag.label, TEST_TAG_LABEL_EDITED)
|
||||||
self.assertEqual(tag.color, TEST_TAG_COLOR_EDITED)
|
self.assertEqual(tag.color, TEST_TAG_COLOR_EDITED)
|
||||||
|
|
||||||
|
|
||||||
class TagDocumentsViewTestCase(TagTestMixin, GenericDocumentViewTestCase):
|
class TagDocumentsViewTestCase(TagViewTestMixin, TagTestMixin, GenericDocumentViewTestCase):
|
||||||
def _request_document_list_view(self):
|
def test_document_tag_attach_view_no_permission(self):
|
||||||
return self.get(viewname='documents:document_list')
|
self._create_test_tag()
|
||||||
|
|
||||||
def test_document_tags_widget_no_permissions(self):
|
response = self._request_document_tag_multiple_attach_view()
|
||||||
self.login_user()
|
self.assertEqual(response.status_code, 404)
|
||||||
self._create_tag()
|
self.assertEqual(self.test_document.tags.count(), 0)
|
||||||
|
|
||||||
self.tag.documents.add(self.document)
|
def test_document_tag_attach_view_with_document_access(self):
|
||||||
response = self._request_document_list_view()
|
self._create_test_tag()
|
||||||
self.assertNotContains(
|
|
||||||
response=response, text=TEST_TAG_LABEL, status_code=200
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_document_tags_widget_with_access(self):
|
|
||||||
self.login_user()
|
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.tag.documents.add(self.document)
|
|
||||||
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
|
||||||
self.grant_access(
|
self.grant_access(
|
||||||
obj=self.document, permission=permission_document_view
|
obj=self.test_document, permission=permission_tag_attach
|
||||||
)
|
)
|
||||||
|
response = self._request_document_tag_multiple_attach_view()
|
||||||
response = self._request_document_list_view()
|
|
||||||
self.assertContains(
|
self.assertContains(
|
||||||
response=response, text=TEST_TAG_LABEL, status_code=200
|
response=response, text=force_text(self.test_document),
|
||||||
|
status_code=200
|
||||||
|
)
|
||||||
|
self.assertNotContains(
|
||||||
|
response=response, text=force_text(self.test_tag), status_code=200
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_document_attach_tag_view_no_permission(self):
|
self.assertEqual(self.test_document.tags.count(), 0)
|
||||||
self.login_user()
|
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.assertEqual(self.document.tags.count(), 0)
|
def test_document_tag_attach_view_with_tag_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_attach)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
|
||||||
|
response = self._request_document_tag_multiple_attach_view()
|
||||||
|
self.assertEqual(response.status_code, 404)
|
||||||
|
|
||||||
response = self._request_attach_tag_view()
|
self.assertEqual(self.test_document.tags.count(), 0)
|
||||||
# Redirect to previous URL and show warning message about having to
|
|
||||||
# select at least one object.
|
|
||||||
self.assertEqual(response.status_code, 302)
|
|
||||||
self.assertEqual(self.document.tags.count(), 0)
|
|
||||||
|
|
||||||
def test_document_attach_tag_view_with_access(self):
|
def test_document_tag_attach_view_with_full_access(self):
|
||||||
self.login_user()
|
self._create_test_tag()
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.assertEqual(self.document.tags.count(), 0)
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_tag_attach
|
||||||
self.grant_access(obj=self.document, permission=permission_tag_attach)
|
)
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_attach)
|
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
|
||||||
# permission_tag_view is needed because the form filters the
|
response = self._request_document_tag_multiple_attach_view()
|
||||||
# choices
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
|
||||||
|
|
||||||
response = self._request_attach_tag_view()
|
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
self.document.tags.all(), (repr(self.tag),)
|
self.test_document.tags.all(), (repr(self.test_tag),)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_document_multiple_attach_tag_view_no_permission(self):
|
|
||||||
self.login_user()
|
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.grant_permission(permission=permission_tag_view)
|
def test_document_single_tag_attach_view_with_full_access(self):
|
||||||
|
"""
|
||||||
|
Test to make sure only the tag is attached to the selected document
|
||||||
|
"""
|
||||||
|
self._create_test_tag()
|
||||||
|
self.test_document_2 = self.upload_document()
|
||||||
|
|
||||||
response = self._request_multiple_attach_tag_view()
|
self.grant_access(
|
||||||
self.assertEqual(response.status_code, 200)
|
obj=self.test_document, permission=permission_tag_attach
|
||||||
self.assertEqual(self.document.tags.count(), 0)
|
)
|
||||||
|
self.grant_access(
|
||||||
def test_document_multiple_attach_tag_view_with_access(self):
|
obj=self.test_document_2, permission=permission_tag_attach
|
||||||
self.login_user()
|
)
|
||||||
self._create_tag()
|
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
|
||||||
|
response = self._request_document_tag_multiple_attach_view()
|
||||||
self.grant_access(obj=self.document, permission=permission_tag_attach)
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_attach)
|
|
||||||
|
|
||||||
# permission_tag_view is needed because the form filters the
|
|
||||||
# choices
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
|
||||||
|
|
||||||
response = self._request_multiple_attach_tag_view()
|
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
self.document.tags.all(), (repr(self.tag),)
|
self.test_document.tags.all(), (repr(self.test_tag),)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_single_document_multiple_tag_remove_view_no_permissions(self):
|
self.assertEqual(self.test_document_2.tags.count(), 0)
|
||||||
self.login_user()
|
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.document.tags.add(self.tag)
|
def test_document_multiple_tag_attach_view_no_permission(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
response = self._request_document_multiple_tag_multiple_attach_view()
|
||||||
|
self.assertEqual(response.status_code, 404)
|
||||||
|
self.assertEqual(self.test_document.tags.count(), 0)
|
||||||
|
|
||||||
response = self._request_single_document_multiple_tag_remove_view()
|
def test_document_multiple_tag_attach_view_with_document_access(self):
|
||||||
self.assertEqual(response.status_code, 200)
|
self._create_test_tag()
|
||||||
|
|
||||||
self.assertQuerysetEqual(self.document.tags.all(), (repr(self.tag),))
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_tag_attach
|
||||||
|
)
|
||||||
|
|
||||||
def test_single_document_multiple_tag_remove_view_with_access(self):
|
response = self._request_document_multiple_tag_multiple_attach_view()
|
||||||
self.login_user()
|
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.document.tags.add(self.tag)
|
self.assertContains(
|
||||||
|
response=response, text=force_text(self.test_document),
|
||||||
|
status_code=200
|
||||||
|
)
|
||||||
|
self.assertNotContains(
|
||||||
|
response=response, text=force_text(self.test_tag), status_code=200
|
||||||
|
)
|
||||||
|
|
||||||
self.grant_access(obj=self.document, permission=permission_tag_remove)
|
self.assertEqual(self.test_document.tags.count(), 0)
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_remove)
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
|
||||||
|
|
||||||
response = self._request_single_document_multiple_tag_remove_view()
|
def test_document_multiple_tag_attach_view_with_tag_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
|
||||||
|
|
||||||
|
response = self._request_document_multiple_tag_multiple_attach_view()
|
||||||
|
self.assertEqual(response.status_code, 404)
|
||||||
|
self.assertEqual(self.test_document.tags.count(), 0)
|
||||||
|
|
||||||
|
def test_document_multiple_tag_attach_view_with_full_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_tag_attach
|
||||||
|
)
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
|
||||||
|
|
||||||
|
response = self._request_document_multiple_tag_multiple_attach_view()
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
self.assertEqual(self.document.tags.count(), 0)
|
self.assertQuerysetEqual(
|
||||||
|
self.test_document.tags.all(), (repr(self.test_tag),)
|
||||||
|
)
|
||||||
|
|
||||||
def test_multiple_documents_selection_tag_remove_view_no_permissions(self):
|
def test_document_tag_multiple_remove_view_no_permissions(self):
|
||||||
self.login_user()
|
self._create_test_tag()
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.document.tags.add(self.tag)
|
self.test_document.tags.add(self.test_tag)
|
||||||
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
response = self._request_document_tag_multiple_remove_view()
|
||||||
|
self.assertEqual(response.status_code, 404)
|
||||||
|
|
||||||
response = self._request_multiple_documents_selection_tag_remove_view()
|
self.assertQuerysetEqual(
|
||||||
self.assertEqual(response.status_code, 200)
|
self.test_document.tags.all(), (repr(self.test_tag),)
|
||||||
|
)
|
||||||
|
|
||||||
self.assertQuerysetEqual(self.document.tags.all(), (repr(self.tag),))
|
def test_document_tag_multiple_remove_view_with_document_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
def test_multiple_documents_selection_tag_remove_view_with_access(self):
|
self.test_document.tags.add(self.test_tag)
|
||||||
self.login_user()
|
|
||||||
self._create_tag()
|
|
||||||
|
|
||||||
self.document.tags.add(self.tag)
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_tag_remove
|
||||||
|
)
|
||||||
|
response = self._request_document_tag_multiple_remove_view()
|
||||||
|
self.assertNotContains(
|
||||||
|
response=response, text=self.test_tag, status_code=200
|
||||||
|
)
|
||||||
|
self.assertContains(
|
||||||
|
response=response, text=self.test_document, status_code=200
|
||||||
|
)
|
||||||
|
|
||||||
self.grant_access(obj=self.document, permission=permission_tag_remove)
|
self.assertEqual(self.test_document.tags.count(), 1)
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_remove)
|
|
||||||
self.grant_access(obj=self.tag, permission=permission_tag_view)
|
|
||||||
|
|
||||||
response = self._request_multiple_documents_selection_tag_remove_view()
|
def test_document_tag_multiple_remove_view_with_tag_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_document.tags.add(self.test_tag)
|
||||||
|
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_remove)
|
||||||
|
|
||||||
|
response = self._request_document_tag_multiple_remove_view()
|
||||||
|
self.assertEqual(response.status_code, 404)
|
||||||
|
|
||||||
|
self.assertEqual(self.test_document.tags.count(), 1)
|
||||||
|
|
||||||
|
def test_document_tag_multiple_remove_view_with_full_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_document.tags.add(self.test_tag)
|
||||||
|
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_tag_remove
|
||||||
|
)
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_remove)
|
||||||
|
|
||||||
|
response = self._request_document_tag_multiple_remove_view()
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
self.assertEqual(self.document.tags.count(), 0)
|
self.assertEqual(self.test_document.tags.count(), 0)
|
||||||
|
|
||||||
|
def test_document_tags_list_no_permissions(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
|
||||||
|
response = self._request_document_tag_list_view()
|
||||||
|
self.assertNotContains(
|
||||||
|
response=response, text=force_text(self.test_tag), status_code=404
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_document_tags_list_with_document_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_tag_view
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self._request_document_tag_list_view()
|
||||||
|
self.assertNotContains(
|
||||||
|
response=response, text=force_text(self.test_tag), status_code=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_document_tags_list_with_tag_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
|
|
||||||
|
response = self._request_document_tag_list_view()
|
||||||
|
self.assertNotContains(
|
||||||
|
response=response, text=force_text(self.test_tag), status_code=404
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_document_tags_list_with_full_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_tag_view
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self._request_document_tag_list_view()
|
||||||
|
self.assertContains(
|
||||||
|
response=response, text=force_text(self.test_tag), status_code=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_document_multiple_tag_remove_view_no_permissions(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_document.tags.add(self.test_tag)
|
||||||
|
|
||||||
|
response = self._request_document_multiple_tag_multiple_remove_view()
|
||||||
|
self.assertEqual(response.status_code, 404)
|
||||||
|
|
||||||
|
self.assertQuerysetEqual(
|
||||||
|
self.test_document.tags.all(), (repr(self.test_tag),)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_document_multiple_tag_remove_view_with_full_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_document.tags.add(self.test_tag)
|
||||||
|
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_tag_remove
|
||||||
|
)
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_remove)
|
||||||
|
|
||||||
|
response = self._request_document_multiple_tag_multiple_remove_view()
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
|
self.assertEqual(self.test_document.tags.count(), 0)
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ from mayan.apps.sources.tests.literals import (
|
|||||||
from ..models import Tag
|
from ..models import Tag
|
||||||
|
|
||||||
from .literals import TEST_TAG_COLOR, TEST_TAG_LABEL
|
from .literals import TEST_TAG_COLOR, TEST_TAG_LABEL
|
||||||
|
from .mixins import TagTestMixin
|
||||||
|
|
||||||
|
|
||||||
class TaggedDocumentUploadTestCase(GenericDocumentViewTestCase):
|
class TaggedDocumentUploadTestCase(TagTestMixin, GenericDocumentViewTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TaggedDocumentUploadTestCase, self).setUp()
|
super(TaggedDocumentUploadTestCase, self).setUp()
|
||||||
self.login_user()
|
|
||||||
self.source = WebFormSource.objects.create(
|
self.source = WebFormSource.objects.create(
|
||||||
enabled=True, label=TEST_SOURCE_LABEL,
|
enabled=True, label=TEST_SOURCE_LABEL,
|
||||||
uncompress=TEST_SOURCE_UNCOMPRESS_N
|
uncompress=TEST_SOURCE_UNCOMPRESS_N
|
||||||
@@ -34,20 +34,15 @@ class TaggedDocumentUploadTestCase(GenericDocumentViewTestCase):
|
|||||||
data={
|
data={
|
||||||
'document_type_id': self.document_type.pk,
|
'document_type_id': self.document_type.pk,
|
||||||
'source-file': file_object,
|
'source-file': file_object,
|
||||||
'tags': self.tag.pk
|
'tags': self.test_tag.pk
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def _create_tag(self):
|
|
||||||
self.tag = Tag.objects.create(
|
|
||||||
color=TEST_TAG_COLOR, label=TEST_TAG_LABEL
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_upload_interactive_view_with_access(self):
|
def test_upload_interactive_view_with_access(self):
|
||||||
self._create_tag()
|
self._create_test_tag()
|
||||||
self.grant_access(
|
self.grant_access(
|
||||||
permission=permission_document_create, obj=self.document_type
|
permission=permission_document_create, obj=self.document_type
|
||||||
)
|
)
|
||||||
response = self._request_upload_interactive_document_create_view()
|
response = self._request_upload_interactive_document_create_view()
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
self.assertTrue(self.tag in Document.objects.first().tags.all())
|
self.assertTrue(self.test_tag in Document.objects.first().tags.all())
|
||||||
|
|||||||
@@ -2,66 +2,75 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from .api_views import (
|
#from .api_views import (
|
||||||
APIDocumentTagView, APIDocumentTagListView, APITagDocumentListView,
|
# APIDocumentTagView, APIDocumentTagListView, APITagDocumentListView,
|
||||||
APITagListView, APITagView
|
# APITagListView, APITagView
|
||||||
)
|
#)
|
||||||
|
from .api_views import DocumentTagViewSet, TagViewSet
|
||||||
|
|
||||||
from .views import (
|
from .views import (
|
||||||
DocumentTagListView, TagAttachActionView, TagCreateView,
|
DocumentTagListView, TagAttachActionView, TagCreateView,
|
||||||
TagDeleteActionView, TagEditView, TagListView, TagRemoveActionView,
|
TagDeleteActionView, TagDocumentListView, TagEditView, TagListView,
|
||||||
TagTaggedItemListView
|
TagRemoveActionView
|
||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(regex=r'^tags/list/$', name='tag_list', view=TagListView.as_view()),
|
url(
|
||||||
|
regex=r'^documents/(?P<document_id>\d+)/tags/$',
|
||||||
|
name='document_tag_list', view=DocumentTagListView.as_view()
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
regex=r'^documents/(?P<document_id>\d+)/tags/multiple/attach/$',
|
||||||
|
name='document_tag_multiple_attach', view=TagAttachActionView.as_view()
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
regex=r'^documents/(?P<document_id>\d+)/tags/multiple/remove/$',
|
||||||
|
name='document_tag_multiple_remove',
|
||||||
|
view=TagRemoveActionView.as_view()
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
regex=r'^documents/multiple/attach/$',
|
||||||
|
name='document_multiple_tag_multiple_attach',
|
||||||
|
view=TagAttachActionView.as_view()
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
regex=r'^documents/multiple/tags/remove/$',
|
||||||
|
name='document_multiple_tag_multiple_remove',
|
||||||
|
view=TagRemoveActionView.as_view()
|
||||||
|
),
|
||||||
|
url(regex=r'^tags/$', name='tag_list', view=TagListView.as_view()),
|
||||||
url(
|
url(
|
||||||
regex=r'^tags/create/$', name='tag_create',
|
regex=r'^tags/create/$', name='tag_create',
|
||||||
view=TagCreateView.as_view()
|
view=TagCreateView.as_view()
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
regex=r'^tags/(?P<tag_pk>\d+)/delete/$', name='tag_delete',
|
regex=r'^tags/(?P<tag_id>\d+)/delete/$', name='tag_delete',
|
||||||
view=TagDeleteActionView.as_view()
|
view=TagDeleteActionView.as_view()
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
regex=r'^tags/(?P<tag_pk>\d+)/edit/$', name='tag_edit',
|
regex=r'^tags/(?P<tag_id>\d+)/edit/$', name='tag_edit',
|
||||||
view=TagEditView.as_view()
|
view=TagEditView.as_view()
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
regex=r'^tags/(?P<tag_pk>\d+)/documents/$',
|
regex=r'^tags/(?P<tag_id>\d+)/documents/$',
|
||||||
name='tag_tagged_item_list', view=TagTaggedItemListView.as_view()
|
name='tag_document_list', view=TagDocumentListView.as_view()
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
regex=r'^tags/multiple/delete/$', name='tag_multiple_delete',
|
regex=r'^tags/multiple/delete/$', name='tag_multiple_delete',
|
||||||
view=TagDeleteActionView.as_view()
|
view=TagDeleteActionView.as_view()
|
||||||
),
|
)
|
||||||
url(
|
|
||||||
regex=r'^tags/multiple/remove/document/(?P<document_pk>\d+)/$',
|
|
||||||
name='single_document_multiple_tag_remove',
|
|
||||||
view=TagRemoveActionView.as_view()
|
|
||||||
),
|
|
||||||
url(
|
|
||||||
regex=r'^tags/multiple/remove/document/multiple/$',
|
|
||||||
name='multiple_documents_selection_tag_remove',
|
|
||||||
view=TagRemoveActionView.as_view()
|
|
||||||
),
|
|
||||||
|
|
||||||
url(
|
|
||||||
regex=r'^documents/(?P<document_pk>\d+)/attach/$',
|
|
||||||
name='tag_attach', view=TagAttachActionView.as_view()
|
|
||||||
),
|
|
||||||
url(
|
|
||||||
regex=r'^documents/multiple/attach//$',
|
|
||||||
name='multiple_documents_tag_attach',
|
|
||||||
view=TagAttachActionView.as_view()
|
|
||||||
),
|
|
||||||
|
|
||||||
url(
|
|
||||||
regex=r'^documents/(?P<document_pk>\d+)/tags/$', name='document_tags',
|
|
||||||
view=DocumentTagListView.as_view(),
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
api_urls = [
|
|
||||||
|
api_router_entries = (
|
||||||
|
{'prefix': r'tags', 'viewset': TagViewSet, 'basename': 'tag'},
|
||||||
|
{
|
||||||
|
'prefix': r'documents/(?P<document_id>\d+)/tags',
|
||||||
|
'viewset': DocumentTagViewSet, 'basename': 'document_tag'
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
"""
|
||||||
url(
|
url(
|
||||||
regex=r'^tags/(?P<tag_pk>\d+)/documents/$',
|
regex=r'^tags/(?P<tag_pk>\d+)/documents/$',
|
||||||
name='tag-document-list', view=APITagDocumentListView.as_view(),
|
name='tag-document-list', view=APITagDocumentListView.as_view(),
|
||||||
@@ -79,4 +88,4 @@ api_urls = [
|
|||||||
regex=r'^documents/(?P<document_pk>\d+)/tags/(?P<tag_pk>[0-9]+)/$',
|
regex=r'^documents/(?P<document_pk>\d+)/tags/(?P<tag_pk>[0-9]+)/$',
|
||||||
name='document-tag-detail', view=APIDocumentTagView.as_view()
|
name='document-tag-detail', view=APIDocumentTagView.as_view()
|
||||||
),
|
),
|
||||||
]
|
"""
|
||||||
|
|||||||
@@ -9,19 +9,20 @@ from django.urls import reverse_lazy
|
|||||||
from django.utils.translation import ugettext_lazy as _, ungettext
|
from django.utils.translation import ugettext_lazy as _, ungettext
|
||||||
|
|
||||||
from mayan.apps.acls.models import AccessControlList
|
from mayan.apps.acls.models import AccessControlList
|
||||||
from mayan.apps.common.views import (
|
from mayan.apps.common.generics import (
|
||||||
MultipleObjectFormActionView, MultipleObjectConfirmActionView,
|
MultipleObjectFormActionView, MultipleObjectConfirmActionView,
|
||||||
SingleObjectCreateView, SingleObjectEditView, SingleObjectListView
|
SingleObjectCreateView, SingleObjectEditView, SingleObjectListView
|
||||||
)
|
)
|
||||||
|
from mayan.apps.common.mixins import ExternalObjectMixin
|
||||||
from mayan.apps.documents.models import Document
|
from mayan.apps.documents.models import Document
|
||||||
from mayan.apps.documents.views import DocumentListView
|
from mayan.apps.documents.views import DocumentListView
|
||||||
from mayan.apps.documents.permissions import permission_document_view
|
from mayan.apps.documents.permissions import permission_document_view
|
||||||
|
|
||||||
from .forms import TagMultipleSelectionForm
|
from .forms import TagMultipleSelectionForm
|
||||||
from .icons import (
|
from .icons import (
|
||||||
icon_menu_tags, icon_tag_delete_submit, icon_tag_remove_submit
|
icon_menu_tags, icon_tag_delete_submit, icon_document_tag_multiple_remove_submit
|
||||||
)
|
)
|
||||||
from .links import link_tag_attach, link_tag_create
|
from .links import link_document_tag_multiple_attach, link_tag_create
|
||||||
from .models import Tag
|
from .models import Tag
|
||||||
from .permissions import (
|
from .permissions import (
|
||||||
permission_tag_attach, permission_tag_create, permission_tag_delete,
|
permission_tag_attach, permission_tag_create, permission_tag_delete,
|
||||||
@@ -34,7 +35,7 @@ logger = logging.getLogger(__name__)
|
|||||||
class TagAttachActionView(MultipleObjectFormActionView):
|
class TagAttachActionView(MultipleObjectFormActionView):
|
||||||
form_class = TagMultipleSelectionForm
|
form_class = TagMultipleSelectionForm
|
||||||
model = Document
|
model = Document
|
||||||
pk_url_kwarg = 'document_pk'
|
pk_url_kwarg = 'document_id'
|
||||||
object_permission = permission_tag_attach
|
object_permission = permission_tag_attach
|
||||||
success_message = _('Tag attach request performed on %(count)d document')
|
success_message = _('Tag attach request performed on %(count)d document')
|
||||||
success_message_plural = _(
|
success_message_plural = _(
|
||||||
@@ -42,7 +43,7 @@ class TagAttachActionView(MultipleObjectFormActionView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_object_list()
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
'submit_label': _('Attach'),
|
'submit_label': _('Attach'),
|
||||||
@@ -66,7 +67,7 @@ class TagAttachActionView(MultipleObjectFormActionView):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def get_form_extra_kwargs(self):
|
def get_form_extra_kwargs(self):
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_object_list()
|
||||||
result = {
|
result = {
|
||||||
'help_text': _('Tags to be attached.'),
|
'help_text': _('Tags to be attached.'),
|
||||||
'permission': permission_tag_attach,
|
'permission': permission_tag_attach,
|
||||||
@@ -85,44 +86,45 @@ class TagAttachActionView(MultipleObjectFormActionView):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def get_post_action_redirect(self):
|
def get_post_action_redirect(self):
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_object_list()
|
||||||
if queryset.count() == 1:
|
if queryset.count() == 1:
|
||||||
return reverse(
|
return reverse(
|
||||||
viewname='tags:document_tags', kwargs={
|
viewname='tags:document_tag_list', kwargs={
|
||||||
'document_pk': queryset.first().pk
|
'document_id': queryset.first().pk
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return super(TagAttachActionView, self).get_post_action_redirect()
|
return super(TagAttachActionView, self).get_post_action_redirect()
|
||||||
|
|
||||||
def object_action(self, form, instance):
|
def object_action(self, form, instance):
|
||||||
attached_tags = instance.get_tags()
|
attached_tags = instance.get_tags(
|
||||||
|
permission=permission_tag_attach, user=self.request.user
|
||||||
|
)
|
||||||
|
|
||||||
for tag in form.cleaned_data['tags']:
|
tag_list = AccessControlList.objects.restrict_queryset(
|
||||||
AccessControlList.objects.check_access(
|
permission=permission_tag_attach, queryset=form.cleaned_data['tags'],
|
||||||
obj=tag, permissions=permission_tag_attach,
|
user=self.request.user
|
||||||
user=self.request.user
|
)
|
||||||
)
|
|
||||||
|
|
||||||
|
for tag in tag_list:
|
||||||
if tag in attached_tags:
|
if tag in attached_tags:
|
||||||
messages.warning(
|
messages.warning(
|
||||||
self.request, _(
|
message=_(
|
||||||
'Document "%(document)s" is already tagged as '
|
'Document "%(document)s" is already tagged as '
|
||||||
'"%(tag)s"'
|
'"%(tag)s"'
|
||||||
) % {
|
) % {
|
||||||
'document': instance, 'tag': tag
|
'document': instance, 'tag': tag
|
||||||
}
|
}, request=self.request
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
tag.attach_to(document=instance, user=self.request.user)
|
tag.attach_to(document=instance, user=self.request.user)
|
||||||
messages.success(
|
messages.success(
|
||||||
self.request,
|
message=_(
|
||||||
_(
|
|
||||||
'Tag "%(tag)s" attached successfully to document '
|
'Tag "%(tag)s" attached successfully to document '
|
||||||
'"%(document)s".'
|
'"%(document)s".'
|
||||||
) % {
|
) % {
|
||||||
'document': instance, 'tag': tag
|
'document': instance, 'tag': tag
|
||||||
}
|
}, request=self.request
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -130,7 +132,7 @@ class TagCreateView(SingleObjectCreateView):
|
|||||||
extra_context = {'title': _('Create tag')}
|
extra_context = {'title': _('Create tag')}
|
||||||
fields = ('label', 'color')
|
fields = ('label', 'color')
|
||||||
model = Tag
|
model = Tag
|
||||||
post_action_redirect = reverse_lazy('tags:tag_list')
|
post_action_redirect = reverse_lazy(viewname='tags:tag_list')
|
||||||
view_permission = permission_tag_create
|
view_permission = permission_tag_create
|
||||||
|
|
||||||
def get_save_extra_data(self):
|
def get_save_extra_data(self):
|
||||||
@@ -139,8 +141,8 @@ class TagCreateView(SingleObjectCreateView):
|
|||||||
|
|
||||||
class TagDeleteActionView(MultipleObjectConfirmActionView):
|
class TagDeleteActionView(MultipleObjectConfirmActionView):
|
||||||
model = Tag
|
model = Tag
|
||||||
pk_url_kwarg = 'tag_pk'
|
pk_url_kwarg = 'tag_id'
|
||||||
post_action_redirect = reverse_lazy('tags:tag_list')
|
post_action_redirect = reverse_lazy(viewname='tags:tag_list')
|
||||||
object_permission = permission_tag_delete
|
object_permission = permission_tag_delete
|
||||||
success_message = _('Tag delete request performed on %(count)d tag')
|
success_message = _('Tag delete request performed on %(count)d tag')
|
||||||
success_message_plural = _(
|
success_message_plural = _(
|
||||||
@@ -155,9 +157,9 @@ class TagDeleteActionView(MultipleObjectConfirmActionView):
|
|||||||
'submit_icon_class': icon_tag_delete_submit,
|
'submit_icon_class': icon_tag_delete_submit,
|
||||||
'submit_label': _('Delete'),
|
'submit_label': _('Delete'),
|
||||||
'title': ungettext(
|
'title': ungettext(
|
||||||
'Delete the selected tag?',
|
singular='Delete the selected tag?',
|
||||||
'Delete the selected tags?',
|
plural='Delete the selected tags?',
|
||||||
queryset.count()
|
number=queryset.count()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,13 +177,14 @@ class TagDeleteActionView(MultipleObjectConfirmActionView):
|
|||||||
try:
|
try:
|
||||||
instance.delete()
|
instance.delete()
|
||||||
messages.success(
|
messages.success(
|
||||||
self.request, _('Tag "%s" deleted successfully.') % instance
|
message=_('Tag "%s" deleted successfully.') % instance,
|
||||||
|
request=self.request
|
||||||
)
|
)
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
messages.error(
|
messages.error(
|
||||||
self.request, _('Error deleting tag "%(tag)s": %(error)s') % {
|
message=_('Error deleting tag "%(tag)s": %(error)s') % {
|
||||||
'tag': instance, 'error': exception
|
'tag': instance, 'error': exception
|
||||||
}
|
}, request=self.request
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -189,9 +192,8 @@ class TagEditView(SingleObjectEditView):
|
|||||||
fields = ('label', 'color')
|
fields = ('label', 'color')
|
||||||
model = Tag
|
model = Tag
|
||||||
object_permission = permission_tag_edit
|
object_permission = permission_tag_edit
|
||||||
object_permission_raise_404 = True
|
pk_url_kwarg = 'tag_id'
|
||||||
pk_url_kwarg = 'tag_pk'
|
post_action_redirect = reverse_lazy(viewname='tags:tag_list')
|
||||||
post_action_redirect = reverse_lazy('tags:tag_list')
|
|
||||||
|
|
||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
return {
|
return {
|
||||||
@@ -222,22 +224,24 @@ class TagListView(SingleObjectListView):
|
|||||||
'title': _('Tags'),
|
'title': _('Tags'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_object_list(self):
|
def get_source_queryset(self):
|
||||||
return self.get_tag_queryset()
|
#return self.get_tag_queryset()
|
||||||
|
|
||||||
def get_tag_queryset(self):
|
|
||||||
return Tag.objects.all()
|
return Tag.objects.all()
|
||||||
|
|
||||||
|
#def get_tag_queryset(self):
|
||||||
|
# return Tag.objects.all()
|
||||||
|
|
||||||
class TagTaggedItemListView(DocumentListView):
|
|
||||||
def get_tag(self):
|
class TagDocumentListView(ExternalObjectMixin, DocumentListView):
|
||||||
return get_object_or_404(klass=Tag, pk=self.kwargs['tag_pk'])
|
external_object_class = Tag
|
||||||
|
external_object_permission = permission_tag_view
|
||||||
|
external_object_pk_url_kwarg = 'tag_id'
|
||||||
|
|
||||||
def get_document_queryset(self):
|
def get_document_queryset(self):
|
||||||
return self.get_tag().documents.all()
|
return self.get_tag().get_documents(user=self.request.user).all()
|
||||||
|
|
||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
context = super(TagTaggedItemListView, self).get_extra_context()
|
context = super(TagDocumentListView, self).get_extra_context()
|
||||||
context.update(
|
context.update(
|
||||||
{
|
{
|
||||||
'column_class': 'col-xs-12 col-sm-6 col-md-4 col-lg-3',
|
'column_class': 'col-xs-12 col-sm-6 col-md-4 col-lg-3',
|
||||||
@@ -247,57 +251,56 @@ class TagTaggedItemListView(DocumentListView):
|
|||||||
)
|
)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def get_tag(self):
|
||||||
|
return self.get_external_object()
|
||||||
|
|
||||||
class DocumentTagListView(TagListView):
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
|
||||||
self.document = get_object_or_404(
|
|
||||||
klass=Document, pk=self.kwargs['document_pk']
|
|
||||||
)
|
|
||||||
|
|
||||||
AccessControlList.objects.check_access(
|
class DocumentTagListView(ExternalObjectMixin, TagListView):
|
||||||
permissions=permission_document_view, user=request.user,
|
external_object_class = Document
|
||||||
obj=self.document
|
external_object_permission = permission_tag_view
|
||||||
)
|
external_object_pk_url_kwarg = 'document_id'
|
||||||
|
|
||||||
return super(DocumentTagListView, self).dispatch(
|
|
||||||
request, *args, **kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
context = super(DocumentTagListView, self).get_extra_context()
|
context = super(DocumentTagListView, self).get_extra_context()
|
||||||
context.update(
|
context.update(
|
||||||
{
|
{
|
||||||
'hide_link': True,
|
'hide_link': True,
|
||||||
'no_results_main_link': link_tag_attach.resolve(
|
'no_results_main_link': link_document_tag_multiple_attach.resolve(
|
||||||
context=RequestContext(
|
context=RequestContext(
|
||||||
self.request, {'object': self.document}
|
self.request, {'object': self.get_external_object()}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
'no_results_title': _('Document has no tags attached'),
|
'no_results_title': _('Document has no tags attached'),
|
||||||
'object': self.document,
|
'object': self.get_external_object(),
|
||||||
'title': _('Tags for document: %s') % self.document,
|
'title': _(
|
||||||
|
'Tags for document: %s'
|
||||||
|
) % self.get_external_object(),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_tag_queryset(self):
|
#def get_tag_queryset(self):
|
||||||
return self.document.get_tags().all()
|
def get_source_queryset(self):
|
||||||
|
return self.get_external_object().get_tags(
|
||||||
|
permission=permission_tag_view, user=self.request.user
|
||||||
|
).all()
|
||||||
|
|
||||||
|
|
||||||
class TagRemoveActionView(MultipleObjectFormActionView):
|
class TagRemoveActionView(MultipleObjectFormActionView):
|
||||||
form_class = TagMultipleSelectionForm
|
form_class = TagMultipleSelectionForm
|
||||||
model = Document
|
model = Document
|
||||||
object_permission = permission_tag_remove
|
object_permission = permission_tag_remove
|
||||||
|
pk_url_kwarg = 'document_id'
|
||||||
success_message = _('Tag remove request performed on %(count)d document')
|
success_message = _('Tag remove request performed on %(count)d document')
|
||||||
success_message_plural = _(
|
success_message_plural = _(
|
||||||
'Tag remove request performed on %(count)d documents'
|
'Tag remove request performed on %(count)d documents'
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_object_list()
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
'submit_icon_class': icon_tag_remove_submit,
|
'submit_icon_class': icon_document_tag_multiple_remove_submit,
|
||||||
'submit_label': _('Remove'),
|
'submit_label': _('Remove'),
|
||||||
'title': ungettext(
|
'title': ungettext(
|
||||||
singular='Remove tags to %(count)d document',
|
singular='Remove tags to %(count)d document',
|
||||||
@@ -321,7 +324,7 @@ class TagRemoveActionView(MultipleObjectFormActionView):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def get_form_extra_kwargs(self):
|
def get_form_extra_kwargs(self):
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_object_list()
|
||||||
result = {
|
result = {
|
||||||
'help_text': _('Tags to be removed.'),
|
'help_text': _('Tags to be removed.'),
|
||||||
'permission': permission_tag_remove,
|
'permission': permission_tag_remove,
|
||||||
@@ -338,41 +341,43 @@ class TagRemoveActionView(MultipleObjectFormActionView):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def get_post_action_redirect(self):
|
def get_post_action_redirect(self):
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_object_list()
|
||||||
if queryset.count() == 1:
|
if queryset.count() == 1:
|
||||||
return reverse(
|
return reverse(
|
||||||
viewname='tags:document_tags', kwargs={
|
viewname='tags:document_tag_list', kwargs={
|
||||||
'document_pk': queryset.first().pk
|
'document_id': queryset.first().pk
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return super(TagRemoveActionView, self).get_post_action_redirect()
|
return super(TagRemoveActionView, self).get_post_action_redirect()
|
||||||
|
|
||||||
def object_action(self, form, instance):
|
def object_action(self, form, instance):
|
||||||
attached_tags = instance.get_tags()
|
attached_tags = instance.get_tags(
|
||||||
|
permission=permission_tag_remove, user=self.request.user
|
||||||
|
)
|
||||||
|
|
||||||
for tag in form.cleaned_data['tags']:
|
tag_list = AccessControlList.objects.restrict_queryset(
|
||||||
AccessControlList.objects.check_access(
|
permission=permission_tag_remove,
|
||||||
obj=tag, permissions=permission_tag_remove,
|
queryset=form.cleaned_data['tags'],
|
||||||
user=self.request.user
|
user=self.request.user
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for tag in tag_list:
|
||||||
if tag not in attached_tags:
|
if tag not in attached_tags:
|
||||||
messages.warning(
|
messages.warning(
|
||||||
self.request, _(
|
message=_(
|
||||||
'Document "%(document)s" wasn\'t tagged as "%(tag)s'
|
'Document "%(document)s" wasn\'t tagged as "%(tag)s'
|
||||||
) % {
|
) % {
|
||||||
'document': instance, 'tag': tag
|
'document': instance, 'tag': tag
|
||||||
}
|
}, request=self.request
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
tag.remove_from(document=instance, user=self.request.user)
|
tag.remove_from(document=instance, user=self.request.user)
|
||||||
messages.success(
|
messages.success(
|
||||||
self.request,
|
message=_(
|
||||||
_(
|
|
||||||
'Tag "%(tag)s" removed successfully from document '
|
'Tag "%(tag)s" removed successfully from document '
|
||||||
'"%(document)s".'
|
'"%(document)s".'
|
||||||
) % {
|
) % {
|
||||||
'document': instance, 'tag': tag
|
'document': instance, 'tag': tag
|
||||||
}
|
}, request=self.request
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,39 +18,11 @@ class TagFormWidget(forms.SelectMultiple):
|
|||||||
|
|
||||||
def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
|
def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
|
||||||
result = super(TagFormWidget, self).create_option(
|
result = super(TagFormWidget, self).create_option(
|
||||||
name=name, value=value, label='{}'.format(conditional_escape(label)),
|
attrs=attrs, index=index,
|
||||||
selected=selected, index=index, subindex=subindex, attrs=attrs
|
label='{}'.format(conditional_escape(label)), name=name,
|
||||||
|
selected=selected, subindex=subindex, value=value
|
||||||
)
|
)
|
||||||
|
|
||||||
result['attrs']['data-color'] = self.queryset.get(pk=value).color
|
result['attrs']['data-color'] = self.queryset.get(pk=value).color
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def widget_document_tags(document, user):
|
|
||||||
"""
|
|
||||||
A tag widget that displays the tags for the given document
|
|
||||||
"""
|
|
||||||
AccessControlList = apps.get_model(
|
|
||||||
app_label='acls', model_name='AccessControlList'
|
|
||||||
)
|
|
||||||
|
|
||||||
result = ['<div class="tag-container">']
|
|
||||||
|
|
||||||
tags = AccessControlList.objects.filter_by_access(
|
|
||||||
permission_tag_view, user, queryset=document.get_tags().all()
|
|
||||||
)
|
|
||||||
|
|
||||||
for tag in tags:
|
|
||||||
result.append(widget_single_tag(tag))
|
|
||||||
|
|
||||||
result.append('</div>')
|
|
||||||
|
|
||||||
if tags:
|
|
||||||
return mark_safe(''.join(result))
|
|
||||||
else:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
|
|
||||||
def widget_single_tag(tag):
|
|
||||||
return render_to_string('tags/tag_widget.html', {'tag': tag})
|
|
||||||
|
|||||||
@@ -22,17 +22,10 @@ class WizardStepTags(WizardStep):
|
|||||||
Tag = apps.get_model(app_label='tags', model_name='Tag')
|
Tag = apps.get_model(app_label='tags', model_name='Tag')
|
||||||
return Tag.objects.exists()
|
return Tag.objects.exists()
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_form_kwargs(self, wizard):
|
|
||||||
return {
|
|
||||||
'help_text': _('Tags to be attached.'),
|
|
||||||
'user': wizard.request.user
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def done(cls, wizard):
|
def done(cls, wizard):
|
||||||
result = {}
|
result = {}
|
||||||
cleaned_data = wizard.get_cleaned_data_for_step(cls.name)
|
cleaned_data = wizard.get_cleaned_data_for_step(step=cls.name)
|
||||||
if cleaned_data:
|
if cleaned_data:
|
||||||
result['tags'] = [
|
result['tags'] = [
|
||||||
force_text(tag.pk) for tag in cleaned_data['tags']
|
force_text(tag.pk) for tag in cleaned_data['tags']
|
||||||
@@ -40,13 +33,20 @@ class WizardStepTags(WizardStep):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_form_kwargs(self, wizard):
|
||||||
|
return {
|
||||||
|
'help_text': _('Tags to be attached.'),
|
||||||
|
'user': wizard.request.user
|
||||||
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def step_post_upload_process(cls, document, querystring=None):
|
def step_post_upload_process(cls, document, querystring=None):
|
||||||
furl_instance = furl(querystring)
|
furl_instance = furl(args=querystring)
|
||||||
Tag = apps.get_model(app_label='tags', model_name='Tag')
|
Tag = apps.get_model(app_label='tags', model_name='Tag')
|
||||||
|
|
||||||
for tag in Tag.objects.filter(pk__in=furl_instance.args.getlist('tags')):
|
for tag in Tag.objects.filter(pk__in=furl_instance.args.getlist('tags')):
|
||||||
tag.documents.add(document)
|
tag.documents.add(document)
|
||||||
|
|
||||||
|
|
||||||
WizardStep.register(WizardStepTags)
|
WizardStep.register(step=WizardStepTags)
|
||||||
|
|||||||
@@ -38,8 +38,9 @@ class AttachTagAction(WorkflowAction):
|
|||||||
user = request.user
|
user = request.user
|
||||||
logger.debug('user: %s', user)
|
logger.debug('user: %s', user)
|
||||||
|
|
||||||
queryset = AccessControlList.objects.filter_by_access(
|
queryset = AccessControlList.objects.restrict_queryset(
|
||||||
self.permission, user, queryset=Tag.objects.all()
|
permission=self.permission, queryset=Tag.objects.all(),
|
||||||
|
user=user
|
||||||
)
|
)
|
||||||
|
|
||||||
self.fields['tags']['kwargs']['queryset'] = queryset
|
self.fields['tags']['kwargs']['queryset'] = queryset
|
||||||
|
|||||||
Reference in New Issue
Block a user