diff --git a/HISTORY.rst b/HISTORY.rst index d5c54b33bb..389a9ccc5c 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -11,6 +11,7 @@ - Backport workflow context support. - Backport workflow transitions field support. - Backport workflow email action. +- Backport individual index rebuild support. 3.2.5 (2019-07-05) ================== diff --git a/docs/releases/3.3.rst b/docs/releases/3.3.rst index d542585200..ba872b7fdb 100644 --- a/docs/releases/3.3.rst +++ b/docs/releases/3.3.rst @@ -23,6 +23,7 @@ Changes - Backport workflow context support. - Backport workflow transitions field support. - Backport workflow email action. +- Backport individual index rebuild support. Removals -------- diff --git a/mayan/apps/document_indexing/apps.py b/mayan/apps/document_indexing/apps.py index 38a20c153a..52df061a63 100644 --- a/mayan/apps/document_indexing/apps.py +++ b/mayan/apps/document_indexing/apps.py @@ -31,9 +31,10 @@ from .html_widgets import ( ) from .links import ( link_document_index_instance_list, link_document_type_index_templates, - link_index_instance_menu, link_index_template_setup, - link_index_template_create, link_index_template_document_types, - link_index_template_delete, link_index_template_edit, link_index_template_list, + link_index_instance_menu, link_index_instance_rebuild, + link_index_template_setup, link_index_template_create, + link_index_template_document_types, link_index_template_delete, + link_index_template_edit, link_index_template_list, link_index_template_node_tree_view, link_index_instances_rebuild, link_index_template_node_create, link_index_template_node_delete, link_index_template_node_edit @@ -199,6 +200,7 @@ class DocumentIndexingApp(MayanAppConfig): menu_object.bind_links( links=( link_index_template_delete, link_index_template_edit, + link_index_instance_rebuild ), sources=(Index,) ) menu_object.bind_links( diff --git a/mayan/apps/document_indexing/links.py b/mayan/apps/document_indexing/links.py index fc1f832023..a9441e3e9c 100644 --- a/mayan/apps/document_indexing/links.py +++ b/mayan/apps/document_indexing/links.py @@ -49,6 +49,12 @@ link_index_instances_rebuild = Link( ), text=_('Rebuild indexes'), view='indexing:rebuild_index_instances' ) +link_index_instance_rebuild = Link( + args='resolved_object.pk', + icon_class_path='mayan.apps.document_indexing.icons.icon_index_instances_rebuild', + permissions=(permission_document_indexing_rebuild,), + text=_('Rebuild index'), view='indexing:index_setup_rebuild' +) link_index_template_setup = Link( condition=get_cascade_condition( diff --git a/mayan/apps/document_indexing/tests/mixins.py b/mayan/apps/document_indexing/tests/mixins.py index a13b2fa2f4..339982fea7 100644 --- a/mayan/apps/document_indexing/tests/mixins.py +++ b/mayan/apps/document_indexing/tests/mixins.py @@ -50,3 +50,10 @@ class IndexViewTestMixin(object): 'label': TEST_INDEX_LABEL_EDITED, 'slug': TEST_INDEX_SLUG } ) + + def _request_test_index_rebuild_view(self): + return self.post( + viewname='indexing:index_setup_rebuild', kwargs={ + 'pk': self.test_index.pk + } + ) diff --git a/mayan/apps/document_indexing/tests/test_views.py b/mayan/apps/document_indexing/tests/test_views.py index 633939b576..06854039b4 100644 --- a/mayan/apps/document_indexing/tests/test_views.py +++ b/mayan/apps/document_indexing/tests/test_views.py @@ -2,7 +2,7 @@ from __future__ import absolute_import, unicode_literals from mayan.apps.documents.tests import GenericDocumentViewTestCase -from ..models import Index +from ..models import Index, IndexInstanceNode from ..permissions import ( permission_document_indexing_create, permission_document_indexing_delete, permission_document_indexing_edit, @@ -10,11 +10,16 @@ from ..permissions import ( permission_document_indexing_rebuild ) -from .literals import TEST_INDEX_LABEL, TEST_INDEX_LABEL_EDITED +from .literals import ( + TEST_INDEX_LABEL, TEST_INDEX_LABEL_EDITED, + TEST_INDEX_TEMPLATE_DOCUMENT_LABEL_EXPRESSION +) from .mixins import IndexTestMixin, IndexViewTestMixin class IndexViewTestCase(IndexTestMixin, IndexViewTestMixin, GenericDocumentViewTestCase): + auto_upload_document = False + def test_index_create_view_no_permission(self): response = self._request_test_index_create_view() self.assertEqual(response.status_code, 403) @@ -72,6 +77,45 @@ class IndexViewTestCase(IndexTestMixin, IndexViewTestMixin, GenericDocumentViewT self.test_index.refresh_from_db() self.assertEqual(self.test_index.label, TEST_INDEX_LABEL_EDITED) + def test_index_rebuild_view_no_permission(self): + self.upload_document() + self._create_test_index() + + self.test_index.node_templates.create( + parent=self.test_index.template_root, + expression=TEST_INDEX_TEMPLATE_DOCUMENT_LABEL_EXPRESSION, + link_documents=True + ) + + response = self._request_test_index_rebuild_view() + self.assertEqual(response.status_code, 404) + + self.assertEqual(IndexInstanceNode.objects.count(), 0) + + def test_index_rebuild_view_with_access(self): + self.upload_document() + self._create_test_index() + + self.test_index.node_templates.create( + parent=self.test_index.template_root, + expression=TEST_INDEX_TEMPLATE_DOCUMENT_LABEL_EXPRESSION, + link_documents=True + ) + + self.grant_access( + obj=self.test_index, + permission=permission_document_indexing_rebuild + ) + + response = self._request_test_index_rebuild_view() + self.assertEqual(response.status_code, 302) + + self.assertNotEqual(IndexInstanceNode.objects.count(), 0) + + +class IndexInstaceViewTestCase( + IndexTestMixin, IndexViewTestMixin, GenericDocumentViewTestCase +): def _request_index_instance_node_view(self, index_instance_node): return self.get( viewname='indexing:index_instance_node_view', kwargs={ @@ -100,9 +144,13 @@ class IndexViewTestCase(IndexTestMixin, IndexViewTestMixin, GenericDocumentViewT ) self.assertContains(response, text=TEST_INDEX_LABEL, status_code=200) + +class IndexToolsViewTestCase( + IndexTestMixin, IndexViewTestMixin, GenericDocumentViewTestCase +): def _request_index_rebuild_get_view(self): return self.get( - viewname='indexing:rebuild_index_instances', + viewname='indexing:rebuild_index_instances' ) def _request_index_rebuild_post_view(self): @@ -112,7 +160,7 @@ class IndexViewTestCase(IndexTestMixin, IndexViewTestMixin, GenericDocumentViewT } ) - def test_index_rebuild_no_permission(self): + def test_indexes_rebuild_no_permission(self): self._create_test_index(rebuild=False) response = self._request_index_rebuild_get_view() @@ -128,7 +176,7 @@ class IndexViewTestCase(IndexTestMixin, IndexViewTestMixin, GenericDocumentViewT self.test_index.instance_root.get_children_count(), 0 ) - def test_index_rebuild_with_access(self): + def test_indexes_rebuild_with_access(self): self._create_test_index(rebuild=False) self.grant_access( diff --git a/mayan/apps/document_indexing/urls.py b/mayan/apps/document_indexing/urls.py index 380e1d7fdc..d34650c1b5 100644 --- a/mayan/apps/document_indexing/urls.py +++ b/mayan/apps/document_indexing/urls.py @@ -11,8 +11,8 @@ from .views import ( DocumentIndexNodeListView, DocumentTypeIndexesView, IndexInstanceNodeView, IndexListView, IndexesRebuildView, SetupIndexDocumentTypesView, SetupIndexCreateView, SetupIndexDeleteView, SetupIndexEditView, - SetupIndexListView, SetupIndexTreeTemplateListView, TemplateNodeCreateView, - TemplateNodeDeleteView, TemplateNodeEditView + SetupIndexListView, SetupIndexRebuildView, SetupIndexTreeTemplateListView, + TemplateNodeCreateView, TemplateNodeDeleteView, TemplateNodeEditView ) urlpatterns = [ @@ -46,6 +46,10 @@ urlpatterns = [ view=SetupIndexDocumentTypesView.as_view(), name='index_setup_document_types' ), + url( + regex=r'^setup/index/(?P\d+)/rebuild/$', + view=SetupIndexRebuildView.as_view(), name='index_setup_rebuild' + ), url( regex=r'^setup/template/node/(?P\d+)/create/child/$', view=TemplateNodeCreateView.as_view(), name='template_node_create' diff --git a/mayan/apps/document_indexing/views.py b/mayan/apps/document_indexing/views.py index 55e79cc3c3..33d6047d2a 100644 --- a/mayan/apps/document_indexing/views.py +++ b/mayan/apps/document_indexing/views.py @@ -9,8 +9,8 @@ from django.utils.translation import ugettext_lazy as _, ungettext from mayan.apps.acls.models import AccessControlList from mayan.apps.common.generics import ( - AddRemoveView, FormView, SingleObjectCreateView, SingleObjectDeleteView, - SingleObjectEditView, SingleObjectListView + AddRemoveView, ConfirmView, FormView, SingleObjectCreateView, + SingleObjectDeleteView, SingleObjectEditView, SingleObjectListView ) from mayan.apps.documents.events import event_document_type_edited from mayan.apps.documents.models import Document, DocumentType @@ -32,7 +32,7 @@ from .permissions import ( permission_document_indexing_create, permission_document_indexing_delete, permission_document_indexing_edit, permission_document_indexing_instance_view, - permission_document_indexing_view + permission_document_indexing_rebuild, permission_document_indexing_view ) from .tasks import task_rebuild_index @@ -150,6 +150,36 @@ class SetupIndexListView(SingleObjectListView): } +class SetupIndexRebuildView(ConfirmView): + post_action_redirect = reverse_lazy( + viewname='indexing:index_setup_list' + ) + + def get_extra_context(self): + return { + 'object': self.get_object(), + 'title': _('Rebuild index: %s') % self.get_object() + } + + def get_object(self): + return get_object_or_404(klass=self.get_queryset(), pk=self.kwargs['pk']) + + def get_queryset(self): + return AccessControlList.objects.restrict_queryset( + permission=permission_document_indexing_rebuild, + queryset=Index.objects.all(), user=self.request.user + ) + + def view_action(self): + task_rebuild_index.apply_async( + kwargs=dict(index_id=self.get_object().pk) + ) + + messages.success( + message='Index queued for rebuild.', request=self.request + ) + + class SetupIndexDocumentTypesView(AddRemoveView): main_object_method_add = 'document_types_add' main_object_method_remove = 'document_types_remove'