Update index document types view to AddRemoveView

Add index create and edit events.

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2019-04-27 23:01:46 -04:00
parent 8374a66011
commit dda0f0d2af
12 changed files with 196 additions and 87 deletions

View File

@@ -187,6 +187,9 @@
* Add test case mixin that produces ephimeral models.
* Update ACL permissions view to use the new AddRemoveView class.
* Add ACL created and edited events.
* Update index document types view to use the new AddRemoveView
class.
* Add index create and edit events.
3.1.11 (2019-04-XX)
===================

View File

@@ -219,6 +219,9 @@ Other changes
* Add test case mixin that produces ephimeral models.
* Update ACL permissions view to use the new AddRemoveView class.
* Add ACL created and edited events.
* Update index document types view to use the new AddRemoveView
class.
* Add index create and edit events.
Removals
--------

View File

@@ -16,9 +16,14 @@ from mayan.apps.common.menus import (
menu_setup, menu_tools
)
from mayan.apps.documents.signals import post_document_created, post_initial_document_type
from mayan.apps.events.classes import ModelEventType
from mayan.apps.events.links import (
link_events_for_object, link_object_event_types_user_subcriptions_list
)
from mayan.apps.navigation.classes import SourceColumn
from mayan.celery import app
from .events import event_index_template_created, event_index_template_edited
from .handlers import (
handler_create_default_document_index, handler_delete_empty,
handler_index_document, handler_remove_document,
@@ -55,6 +60,7 @@ class DocumentIndexingApp(MayanAppConfig):
def ready(self):
super(DocumentIndexingApp, self).ready()
from actstream import registry
Document = apps.get_model(
app_label='documents', model_name='Document'
@@ -73,6 +79,12 @@ class DocumentIndexingApp(MayanAppConfig):
IndexInstanceNode = self.get_model(model_name='IndexInstanceNode')
IndexTemplateNode = self.get_model(model_name='IndexTemplateNode')
ModelEventType.register(
event_types=(
event_index_template_created, event_index_template_edited
), model=Index
)
ModelPermission.register(
model=Index, permissions=(
permission_acl_edit, permission_acl_view,
@@ -182,8 +194,10 @@ class DocumentIndexingApp(MayanAppConfig):
)
menu_list_facet.bind_links(
links=(
link_acl_list, link_index_template_document_types,
link_acl_list, link_events_for_object,
link_index_template_document_types,
link_index_template_node_tree_view,
link_object_event_types_user_subcriptions_list
), sources=(Index,)
)
menu_object.bind_links(
@@ -233,3 +247,5 @@ class DocumentIndexingApp(MayanAppConfig):
receiver=handler_remove_document,
sender=Document
)
registry.register(Index)

View File

@@ -0,0 +1,16 @@
from __future__ import absolute_import, unicode_literals
from django.utils.translation import ugettext_lazy as _
from mayan.apps.events.classes import EventTypeNamespace
namespace = EventTypeNamespace(
label=_('Document indexing'), name='document_indexing'
)
event_index_template_created = namespace.add_event_type(
label=_('Index created'), name='index_created'
)
event_index_template_edited = namespace.add_event_type(
label=_('Index edited'), name='index_edited'
)

View File

@@ -17,6 +17,7 @@ from mayan.apps.documents.permissions import permission_document_view
from mayan.apps.lock_manager.exceptions import LockError
from mayan.apps.lock_manager.runtime import locking_backend
from .events import event_index_template_created, event_index_template_edited
from .managers import (
DocumentIndexInstanceNodeManager, IndexManager, IndexInstanceNodeManager
)
@@ -60,6 +61,20 @@ class Index(models.Model):
def __str__(self):
return self.label
def document_types_add(self, queryset, _user=None):
with transaction.atomic():
event_index_template_edited.commit(
actor=_user, target=self
)
self.document_types.add(*queryset)
def document_types_remove(self, queryset, _user=None):
with transaction.atomic():
event_index_template_edited.commit(
actor=_user, target=self
)
self.document_types.remove(*queryset)
def get_absolute_url(self):
try:
return reverse(
@@ -131,11 +146,22 @@ class Index(models.Model):
self.index_document(document=document)
def save(self, *args, **kwargs):
"""
Automatically create the root index template node
"""
super(Index, self).save(*args, **kwargs)
IndexTemplateNode.objects.get_or_create(parent=None, index=self)
_user = kwargs.pop('_user', None)
with transaction.atomic():
is_new = not self.pk
super(Index, self).save(*args, **kwargs)
if is_new:
# Automatically create the root index template node
IndexTemplateNode.objects.get_or_create(parent=None, index=self)
event_index_template_created.commit(
actor=_user, target=self
)
else:
event_index_template_edited.commit(
actor=_user, target=self
)
@property
def template_root(self):

View File

@@ -2,10 +2,12 @@ from __future__ import unicode_literals
from ..models import Index
from .literals import TEST_INDEX_LABEL
from .literals import (
TEST_INDEX_LABEL, TEST_INDEX_LABEL_EDITED, TEST_INDEX_SLUG
)
class DocumentIndexingTestMixin(object):
class IndexTestMixin(object):
def _create_test_index(self, rebuild=False):
# Create empty index
self.test_index = Index.objects.create(label=TEST_INDEX_LABEL)
@@ -16,3 +18,35 @@ class DocumentIndexingTestMixin(object):
# Rebuild indexes
if rebuild:
Index.objects.rebuild()
class IndexViewTestMixin(object):
def _request_test_index_create_view(self):
# Typecast to list to force queryset evaluation
values = list(Index.objects.values_list('pk', flat=True))
response = self.post(
viewname='indexing:index_setup_create', data={
'label': TEST_INDEX_LABEL, 'slug': TEST_INDEX_SLUG
}
)
self.test_index = Index.objects.exclude(pk__in=values).first()
return response
def _request_test_index_delete_view(self):
return self.post(
viewname='indexing:index_setup_delete', kwargs={
'pk': self.test_index.pk
}
)
def _request_test_index_edit_view(self):
return self.post(
viewname='indexing:index_setup_edit', kwargs={
'pk': self.test_index.pk
}, data={
'label': TEST_INDEX_LABEL_EDITED, 'slug': TEST_INDEX_SLUG
}
)

View File

@@ -12,10 +12,10 @@ from ..permissions import (
)
from .literals import TEST_INDEX_LABEL, TEST_INDEX_SLUG
from .mixins import DocumentIndexingTestMixin
from .mixins import IndexTestMixin
class DocumentIndexingAPITestCase(DocumentIndexingTestMixin, DocumentTestMixin, BaseAPITestCase):
class DocumentIndexingAPITestCase(IndexTestMixin, DocumentTestMixin, BaseAPITestCase):
auto_upload_document = False
def _request_index_create_api_view(self):

View File

@@ -0,0 +1,47 @@
from __future__ import unicode_literals
from actstream.models import Action
from mayan.apps.common.tests import GenericViewTestCase
from mayan.apps.documents.tests import DocumentTestMixin
from ..permissions import (
permission_document_indexing_create, permission_document_indexing_edit,
)
from ..events import event_index_template_created, event_index_template_edited
from .mixins import IndexTestMixin, IndexViewTestMixin
class IndexTemplateEventsTestCase(DocumentTestMixin, IndexTestMixin, IndexViewTestMixin, GenericViewTestCase):
auto_upload_document = False
def test_index_template_create_event(self):
Action.objects.all().delete()
self.grant_permission(
permission=permission_document_indexing_create
)
self._request_test_index_create_view()
self.assertEqual(Action.objects.last().actor, self._test_case_user)
self.assertEqual(Action.objects.last().target, self.test_index)
self.assertEqual(
Action.objects.last().verb, event_index_template_created.id
)
def test_index_template_edit_event(self):
self._create_test_index()
self.grant_access(
obj=self.test_index, permission=permission_document_indexing_edit
)
Action.objects.all().delete()
self._request_test_index_edit_view()
self.assertEqual(Action.objects.last().target, self.test_index)
self.assertEqual(
Action.objects.last().verb, event_index_template_edited.id
)

View File

@@ -20,10 +20,10 @@ from .literals import (
TEST_INDEX_TEMPLATE_METADATA_EXPRESSION, TEST_METADATA_TYPE_LABEL,
TEST_METADATA_TYPE_NAME
)
from .mixins import DocumentIndexingTestMixin
from .mixins import IndexTestMixin
class IndexTestCase(DocumentIndexingTestMixin, DocumentTestMixin, BaseTestCase):
class IndexTestCase(IndexTestMixin, DocumentTestMixin, BaseTestCase):
def test_document_description_index(self):
self._create_test_index()

View File

@@ -10,22 +10,13 @@ from ..permissions import (
permission_document_indexing_rebuild
)
from .literals import (
TEST_INDEX_LABEL, TEST_INDEX_LABEL_EDITED, TEST_INDEX_SLUG
)
from .mixins import DocumentIndexingTestMixin
from .literals import TEST_INDEX_LABEL, TEST_INDEX_LABEL_EDITED
from .mixins import IndexTestMixin, IndexViewTestMixin
class IndexViewTestCase(DocumentIndexingTestMixin, GenericDocumentViewTestCase):
def _request_index_create_view(self):
return self.post(
viewname='indexing:index_setup_create', data={
'label': TEST_INDEX_LABEL, 'slug': TEST_INDEX_SLUG
}
)
class IndexViewTestCase(IndexTestMixin, IndexViewTestMixin, GenericDocumentViewTestCase):
def test_index_create_view_no_permission(self):
response = self._request_index_create_view()
response = self._request_test_index_create_view()
self.assertEquals(response.status_code, 403)
self.assertEqual(Index.objects.count(), 0)
@@ -35,23 +26,16 @@ class IndexViewTestCase(DocumentIndexingTestMixin, GenericDocumentViewTestCase):
permission=permission_document_indexing_create
)
response = self._request_index_create_view()
response = self._request_test_index_create_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(Index.objects.count(), 1)
self.assertEqual(Index.objects.first().label, TEST_INDEX_LABEL)
def _request_index_delete_view(self):
return self.post(
viewname='indexing:index_setup_delete', kwargs={
'pk': self.test_index.pk
}
)
def test_index_delete_view_no_permission(self):
self._create_test_index()
response = self._request_index_delete_view()
response = self._request_test_index_delete_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(Index.objects.count(), 1)
@@ -61,24 +45,15 @@ class IndexViewTestCase(DocumentIndexingTestMixin, GenericDocumentViewTestCase):
self.grant_permission(permission=permission_document_indexing_delete)
response = self._request_index_delete_view()
response = self._request_test_index_delete_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(Index.objects.count(), 0)
def _request_index_edit_view(self):
return self.post(
viewname='indexing:index_setup_edit', kwargs={
'pk': self.test_index.pk
}, data={
'label': TEST_INDEX_LABEL_EDITED, 'slug': TEST_INDEX_SLUG
}
)
def test_index_edit_view_no_permission(self):
self._create_test_index()
response = self._request_index_edit_view()
response = self._request_test_index_edit_view()
self.assertEqual(response.status_code, 403)
self.test_index.refresh_from_db()
@@ -91,7 +66,7 @@ class IndexViewTestCase(DocumentIndexingTestMixin, GenericDocumentViewTestCase):
obj=self.test_index, permission=permission_document_indexing_edit
)
response = self._request_index_edit_view()
response = self._request_test_index_edit_view()
self.assertEqual(response.status_code, 302)
self.test_index.refresh_from_db()

View File

@@ -9,11 +9,13 @@ from django.utils.translation import ugettext_lazy as _, ungettext
from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.generics import (
AssignRemoveView, FormView, SingleObjectCreateView,
SingleObjectDeleteView, SingleObjectEditView, SingleObjectListView
AddRemoveView, FormView, SingleObjectCreateView, SingleObjectDeleteView,
SingleObjectEditView, SingleObjectListView
)
from mayan.apps.documents.models import Document, DocumentType
from mayan.apps.documents.permissions import permission_document_view
from mayan.apps.documents.permissions import (
permission_document_type_edit, permission_document_view
)
from mayan.apps.documents.views import DocumentListView
from .forms import IndexTemplateFilteredForm, IndexTemplateNodeForm
@@ -43,6 +45,9 @@ class SetupIndexCreateView(SingleObjectCreateView):
)
view_permission = permission_document_indexing_create
def get_save_extra_data(self):
return {'_user': self.request.user}
class SetupIndexDeleteView(SingleObjectDeleteView):
model = Index
@@ -72,6 +77,9 @@ class SetupIndexEditView(SingleObjectEditView):
'title': _('Edit index: %s') % self.get_object(),
}
def get_save_extra_data(self):
return {'_user': self.request.user}
class SetupIndexListView(SingleObjectListView):
model = Index
@@ -95,53 +103,34 @@ class SetupIndexListView(SingleObjectListView):
}
class SetupIndexDocumentTypesView(AssignRemoveView):
decode_content_type = True
left_list_title = _('Available document types')
object_permission = permission_document_indexing_edit
right_list_title = _('Document types linked')
class SetupIndexDocumentTypesView(AddRemoveView):
action_add_method = 'document_types_add'
action_remove_method = 'document_types_remove'
main_object_permission = permission_document_indexing_edit
main_object_model = Index
main_object_pk_url_kwarg = 'pk'
secondary_object_model = DocumentType
secondary_object_permission = permission_document_type_edit
list_available_title = _('Available document types')
# Translators: "User groups" here refer to the group list of a specific
# user.
list_added_title = _('Document types linked')
related_field = 'document_types'
def add(self, item):
self.get_object().document_types.add(item)
def get_document_queryset(self):
return AccessControlList.objects.filter_by_access(
permission=permission_document_view,
queryset=DocumentType.objects.all(),
user=self.request.user
)
def get_actions_extra_kwargs(self):
return {'_user': self.request.user}
def get_extra_context(self):
return {
'object': self.get_object(),
'title': _(
'Document types linked to index: %s'
) % self.get_object(),
'object': self.main_object,
'subtitle': _(
'Only the documents of the types selected will be shown '
'in the index when built. Only the events of the documents '
'of the types select will trigger updates in the index.'
),
'title': _('Document types linked to index: %s') % self.main_object,
}
def get_object(self):
return get_object_or_404(klass=Index, pk=self.kwargs['pk'])
def left_list(self):
return AssignRemoveView.generate_choices(
self.get_document_queryset().exclude(
id__in=self.get_object().document_types.all()
)
)
def remove(self, item):
self.get_object().document_types.remove(item)
def right_list(self):
return AssignRemoveView.generate_choices(
self.get_document_queryset() & self.get_object().document_types.all()
)
class SetupIndexTreeTemplateListView(SingleObjectListView):
object_permission = permission_document_indexing_edit

View File

@@ -7,7 +7,7 @@ from fuse import FuseOSError
from mayan.apps.common.tests import BaseTestCase
from mayan.apps.documents.models import Document
from mayan.apps.documents.tests import DocumentTestMixin
from mayan.apps.document_indexing.tests import DocumentIndexingTestMixin
from mayan.apps.document_indexing.tests import IndexTestMixin
from ..filesystems import IndexFilesystem
@@ -18,7 +18,7 @@ from .literals import (
)
class IndexFilesystemTestCase(DocumentIndexingTestMixin, DocumentTestMixin, BaseTestCase):
class IndexFilesystemTestCase(IndexTestMixin, DocumentTestMixin, BaseTestCase):
auto_upload_document = False
def test_document_access(self):