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:
@@ -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)
|
||||
===================
|
||||
|
||||
@@ -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
|
||||
--------
|
||||
|
||||
@@ -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)
|
||||
|
||||
16
mayan/apps/document_indexing/events.py
Normal file
16
mayan/apps/document_indexing/events.py
Normal 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'
|
||||
)
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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):
|
||||
|
||||
47
mayan/apps/document_indexing/tests/test_events.py
Normal file
47
mayan/apps/document_indexing/tests/test_events.py
Normal 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
|
||||
)
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user