diff --git a/HISTORY.rst b/HISTORY.rst
index 22eb460148..4adcf98872 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -233,6 +233,10 @@
entire converter class is no longer cached and instead loaded
on demand. This allows the garbage collector to clear the memory
used.
+- Update the permission requirements for the index template
+ document type selection screen. The document type view
+ permission is now required in addition to the index
+ template edit permission.
3.1.9 (2018-11-01)
==================
diff --git a/mayan/apps/document_indexing/apps.py b/mayan/apps/document_indexing/apps.py
index b6dc7a35b8..b252b699f7 100644
--- a/mayan/apps/document_indexing/apps.py
+++ b/mayan/apps/document_indexing/apps.py
@@ -27,23 +27,25 @@ from .handlers import (
handler_index_document, handler_post_save_index_document,
handler_remove_document
)
+from .html_widgets import (
+ IndexInstanceNodeWidget, IndexTemplateNodeIndentationWidget,
+ get_instance_link
+)
from .licenses import * # NOQA
from .links import (
- link_document_index_list, link_index_main_menu, link_index_setup,
- link_index_setup_create, link_index_setup_delete,
- link_index_setup_document_types, link_index_setup_edit,
- link_index_setup_list, link_index_setup_view, link_rebuild_index_instances,
- link_template_node_create, link_template_node_delete,
- link_template_node_edit
+ link_document_index_instance_list, link_index_instances_rebuild,
+ link_index_main_menu, link_index_setup, link_index_template_create,
+ link_index_template_delete, link_index_template_document_types,
+ link_index_template_edit, link_index_template_list,
+ link_index_template_view, link_index_template_node_create,
+ link_index_template_node_delete, link_index_template_node_edit
)
from .permissions import (
permission_document_indexing_create, permission_document_indexing_delete,
- permission_document_indexing_edit,
- permission_document_indexing_instance_view,
+ permission_document_indexing_edit, permission_document_indexing_instance_view,
permission_document_indexing_rebuild, permission_document_indexing_view
)
from .queues import * # NOQA
-from .widgets import get_instance_link, index_instance_item_link, node_level
class DocumentIndexingApp(MayanAppConfig):
@@ -86,53 +88,63 @@ class DocumentIndexingApp(MayanAppConfig):
)
)
- SourceColumn(attribute='label', is_identifier=True, source=Index)
- SourceColumn(attribute='slug', source=Index)
+ ModelPermission.register_inheritance(
+ model=IndexTemplateNode, related='index'
+ )
+
+ ModelPermission.register_inheritance(
+ model=IndexInstanceNode, related='index_template_node__index'
+ )
+
SourceColumn(
- attribute='enabled', source=Index, widget=TwoStateWidget
+ attribute='label', is_identifier=True, is_sortable=True, source=Index
+ )
+ SourceColumn(
+ attribute='slug', include_label=True, is_sortable=True, source=Index
+ )
+ SourceColumn(
+ attribute='enabled', include_label=True, is_sortable=True,
+ source=Index, widget=TwoStateWidget
)
SourceColumn(
func=lambda context: context[
'object'
- ].instance_root.get_descendants_count(), label=_('Total levels'),
- source=IndexInstance,
+ ].instance_root.get_descendants_count(), include_label=True,
+ label=_('Total levels'), source=IndexInstance,
)
SourceColumn(
func=lambda context: context[
'object'
].instance_root.get_descendants_document_count(
user=context['request'].user
- ), label=_('Total documents'), source=IndexInstance
+ ), include_label=True, label=_('Total documents'), source=IndexInstance
+ )
+ SourceColumn(
+ label=_('Level'), is_identifier=True, source=IndexTemplateNode,
+ widget=IndexTemplateNodeIndentationWidget
+ )
+ SourceColumn(
+ attribute='enabled', include_label=True, is_sortable=True,
+ source=IndexTemplateNode, widget=TwoStateWidget
+ )
+ SourceColumn(
+ attribute='link_documents', include_label=True,
+ is_sortable=True, source=IndexTemplateNode, widget=TwoStateWidget
)
SourceColumn(
- func=lambda context: node_level(context['object']),
- label=_('Level'), source=IndexTemplateNode
- )
- SourceColumn(
- attribute='enabled', source=IndexTemplateNode,
- widget=TwoStateWidget
- )
- SourceColumn(
- attribute='link_documents', source=IndexTemplateNode,
- widget=TwoStateWidget
+ is_identifier=True, is_sortable=True, label=_('Level'),
+ sort_field='value', source=IndexInstanceNode,
+ widget=IndexInstanceNodeWidget
)
- SourceColumn(
- func=lambda context: index_instance_item_link(context['object']),
- label=_('Level'), source=IndexInstanceNode
- )
- SourceColumn(
- func=lambda context: context['object'].get_descendants_count(),
- label=_('Levels'), source=IndexInstanceNode
- )
SourceColumn(
func=lambda context: context[
'object'
- ].get_descendants_document_count(
+ ].get_item_count(
user=context['request'].user
- ), label=_('Documents'), source=IndexInstanceNode
+ ), include_label=True, label=_('Items'), source=IndexInstanceNode
)
SourceColumn(
@@ -174,35 +186,35 @@ class DocumentIndexingApp(MayanAppConfig):
)
menu_facet.bind_links(
- links=(link_document_index_list,), sources=(Document,)
+ links=(link_document_index_instance_list,), sources=(Document,)
)
menu_list_facet.bind_links(
links=(
- link_acl_list, link_index_setup_document_types,
- link_index_setup_view,
+ link_acl_list, link_index_template_document_types,
+ link_index_template_view,
), sources=(Index,)
)
menu_object.bind_links(
links=(
- link_index_setup_edit, link_index_setup_delete
+ link_index_template_edit, link_index_template_delete
), sources=(Index,)
)
menu_object.bind_links(
links=(
- link_template_node_create, link_template_node_edit,
- link_template_node_delete
+ link_index_template_node_create, link_index_template_node_edit,
+ link_index_template_node_delete
), sources=(IndexTemplateNode,)
)
menu_main.bind_links(links=(link_index_main_menu,), position=98)
menu_secondary.bind_links(
- links=(link_index_setup_list, link_index_setup_create),
+ links=(link_index_template_list, link_index_template_create),
sources=(
- Index, 'indexing:index_setup_list',
- 'indexing:index_setup_create'
+ Index, 'indexing:index_template_list',
+ 'indexing:index_template_create'
)
)
menu_setup.bind_links(links=(link_index_setup,))
- menu_tools.bind_links(links=(link_rebuild_index_instances,))
+ menu_tools.bind_links(links=(link_index_instances_rebuild,))
post_delete.connect(
dispatch_uid='document_indexing_handler_delete_empty',
diff --git a/mayan/apps/document_indexing/forms.py b/mayan/apps/document_indexing/forms.py
index c9e2455d7f..790a5e6e2e 100644
--- a/mayan/apps/document_indexing/forms.py
+++ b/mayan/apps/document_indexing/forms.py
@@ -4,30 +4,23 @@ from django import forms
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
-from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.classes import ModelProperty
+from mayan.apps.common.forms import FilteredSelectionForm
from mayan.apps.documents.models import Document
from .models import Index, IndexTemplateNode
from .permissions import permission_document_indexing_rebuild
-class IndexListForm(forms.Form):
- indexes = forms.ModelMultipleChoiceField(
- help_text=_('Indexes to be queued for rebuilding.'),
- label=_('Indexes'), queryset=Index.objects.none(),
- required=False, widget=forms.widgets.CheckboxSelectMultiple()
- )
-
- def __init__(self, *args, **kwargs):
- user = kwargs.pop('user')
- super(IndexListForm, self).__init__(*args, **kwargs)
- queryset = AccessControlList.objects.restrict_queryset(
- permission=permission_document_indexing_rebuild,
- queryset=Index.objects.filter(enabled=True),
- user=user
- )
- self.fields['indexes'].queryset = queryset
+class IndexTemplateFilteredForm(FilteredSelectionForm):
+ class Meta:
+ allow_multiple = True
+ field_name = 'index_templates'
+ help_text = _('Index templates to be queued for rebuilding.')
+ label = _('Index templates')
+ queryset = Index.objects.filter(enabled=True)
+ permission = permission_document_indexing_rebuild
+ widget_attributes = {'class': 'select2'}
class IndexTemplateNodeForm(forms.ModelForm):
diff --git a/mayan/apps/document_indexing/widgets.py b/mayan/apps/document_indexing/html_widgets.py
similarity index 52%
rename from mayan/apps/document_indexing/widgets.py
rename to mayan/apps/document_indexing/html_widgets.py
index d55f834c27..803810d295 100644
--- a/mayan/apps/document_indexing/widgets.py
+++ b/mayan/apps/document_indexing/html_widgets.py
@@ -1,10 +1,33 @@
from __future__ import unicode_literals
-from django.apps import apps
-from django.utils.encoding import force_text
+from django.template.loader import render_to_string
from django.utils.html import escape, mark_safe
-from .icons import icon_index, icon_index_level_up, icon_node_with_documents
+from .icons import (
+ icon_index, icon_index_level_up,
+ icon_index_instance_node_with_documents
+)
+
+
+class IndexInstanceNodeWidget(object):
+ def render(self, name, value):
+ return render_to_string(
+ template_name='document_indexing/index_instance_node.html',
+ context={
+ 'index_instance_node': value,
+ }
+ )
+
+
+class IndexTemplateNodeIndentationWidget(object):
+ def render(self, name, value):
+ return render_to_string(
+ template_name='document_indexing/index_template_node_indentation.html',
+ context={
+ 'index_template_node': value,
+ 'index_template_node_level': range(value.get_level()),
+ }
+ )
def get_instance_link(index_instance_node):
@@ -19,45 +42,6 @@ def get_instance_link(index_instance_node):
)
-def index_instance_item_link(index_instance_item):
- #TODO: Replace with a file template
- IndexInstanceNode = apps.get_model(
- app_label='document_indexing', model_name='IndexInstanceNode'
- )
-
- if isinstance(index_instance_item, IndexInstanceNode):
- if index_instance_item.index_template_node.link_documents:
- icon = icon_node_with_documents.render()
- else:
- icon = icon_index_level_up.render()
- else:
- icon = ''
-
- return mark_safe(
- s='%(icon)s %(text)s' % {
- 'url': index_instance_item.get_absolute_url(),
- 'icon': icon,
- 'text': index_instance_item
- }
- )
-
-
-def node_level(node):
- """
- Render an indented tree like output for a specific node
- """
- #TODO: Replace with a file template
- return mark_safe(
- s=''.join(
- [
- ' ' * node.get_level(),
- '' if node.is_root_node() else icon_index_level_up.render(),
- force_text(node)
- ]
- )
- )
-
-
def node_tree(node, user):
#TODO: Replace with a file template
result = []
@@ -71,7 +55,7 @@ def node_tree(node, user):
else:
element = ancestor
if element.index_template_node.link_documents:
- icon = icon_node_with_documents
+ icon = icon_index_instance_node_with_documents
else:
icon = icon_index_level_up
diff --git a/mayan/apps/document_indexing/icons.py b/mayan/apps/document_indexing/icons.py
index 9c6724aabb..8041935456 100644
--- a/mayan/apps/document_indexing/icons.py
+++ b/mayan/apps/document_indexing/icons.py
@@ -2,14 +2,37 @@ from __future__ import absolute_import, unicode_literals
from mayan.apps.appearance.classes import Icon
-icon_document_index_list = Icon(driver_name='fontawesome', symbol='list-ul')
+icon_document_index_instance_list = Icon(
+ driver_name='fontawesome', symbol='list-ul'
+)
+icon_index = Icon(driver_name='fontawesome', symbol='list-ul')
icon_index_level_up = Icon(
driver_name='fontawesomecss', css_classes='fa-level-up-alt fa-rotate-90'
)
-icon_index = Icon(driver_name='fontawesome', symbol='list-ul')
-icon_index_create = Icon(driver_name='fontawesome', symbol='plus')
-icon_index_setup_view = Icon(driver_name='fontawesome', symbol='folder-open')
-icon_node_with_documents = Icon(driver_name='fontawesome', symbol='folder')
-icon_rebuild_index_instances = Icon(
+icon_index_instance_node_with_documents = Icon(
+ driver_name='fontawesome', symbol='folder'
+)
+icon_index_instances_rebuild = Icon(
driver_name='fontawesome', symbol='list-ul'
)
+icon_index_template_create = Icon(
+ driver_name='fontawesome-dual', primary_symbol='list-ul',
+ secondary_symbol='plus'
+)
+
+icon_index_template_delete = Icon(driver_name='fontawesome', symbol='times')
+icon_index_template_edit = Icon(driver_name='fontawesome', symbol='pencil-alt')
+icon_index_template_list = Icon(driver_name='fontawesome', symbol='list-ul')
+
+icon_index_template_node_create = Icon(
+ driver_name='fontawesomecss', css_classes='fa-level-up-alt fa-rotate-90'
+)
+
+icon_index_template_node_delete = Icon(
+ driver_name='fontawesome', symbol='times'
+)
+icon_index_template_node_edit = Icon(
+ driver_name='fontawesome', symbol='pencil-alt'
+)
+
+icon_index_template_view = Icon(driver_name='fontawesome', symbol='folder-open')
diff --git a/mayan/apps/document_indexing/links.py b/mayan/apps/document_indexing/links.py
index cde0f1ab43..0ccce73e73 100644
--- a/mayan/apps/document_indexing/links.py
+++ b/mayan/apps/document_indexing/links.py
@@ -6,8 +6,11 @@ from mayan.apps.documents.icons import icon_document_type
from mayan.apps.navigation import Link, get_cascade_condition
from .icons import (
- icon_document_index_list, icon_index, icon_index_create,
- icon_index_setup_view, icon_rebuild_index_instances
+ icon_document_index_instance_list, icon_index, icon_index_template_create,
+ icon_index_template_delete, icon_index_template_edit,
+ icon_index_template_list, icon_index_template_node_create,
+ icon_index_template_node_delete, icon_index_template_node_edit,
+ icon_index_template_view, icon_index_instances_rebuild
)
from .permissions import (
permission_document_indexing_create, permission_document_indexing_delete,
@@ -17,20 +20,30 @@ from .permissions import (
)
-def is_not_root_node(context):
+def condition_is_not_root_node(context):
return not context['resolved_object'].is_root_node()
-link_document_index_list = Link(
- args='resolved_object.pk', icon_class=icon_document_index_list,
- text=_('Indexes'), view='indexing:document_index_list',
+link_document_index_instance_list = Link(
+ icon_class=icon_document_index_instance_list,
+ kwargs={'document_id': 'resolved_object.pk'}, text=_('Indexes'),
+ view='indexing:document_index_instace_list',
+)
+link_index_instances_rebuild = Link(
+ condition=get_cascade_condition(
+ app_label='document_indexing', model_name='Index',
+ object_permission=permission_document_indexing_rebuild,
+ ), icon_class=icon_index_instances_rebuild,
+ description=_(
+ 'Deletes and creates from scratch all the document indexes.'
+ ), text=_('Rebuild indexes'), view='indexing:index_instances_rebuild'
)
link_index_main_menu = Link(
condition=get_cascade_condition(
app_label='document_indexing', model_name='Index',
object_permission=permission_document_indexing_instance_view,
), icon_class=icon_index, text=_('Indexes'),
- view='indexing:index_list'
+ view='indexing:index_instance_list'
)
link_index_setup = Link(
condition=get_cascade_condition(
@@ -38,55 +51,53 @@ link_index_setup = Link(
object_permission=permission_document_indexing_view,
view_permission=permission_document_indexing_create,
), icon_class=icon_index, text=_('Indexes'),
- view='indexing:index_setup_list'
+ view='indexing:index_template_list'
)
-link_index_setup_list = Link(
- text=_('Indexes'), view='indexing:index_setup_list'
+link_index_template_list = Link(
+ icon_class=icon_index_template_list,
+ text=_('Indexes'), view='indexing:index_template_list'
)
-link_index_setup_create = Link(
- icon_class=icon_index_create,
+link_index_template_create = Link(
+ icon_class=icon_index_template_create,
permission=permission_document_indexing_create, text=_('Create index'),
- view='indexing:index_setup_create'
+ view='indexing:index_template_create'
)
-link_index_setup_edit = Link(
- args='resolved_object.pk',
- permission=permission_document_indexing_edit, text=_('Edit'),
- view='indexing:index_setup_edit',
-)
-link_index_setup_delete = Link(
- args='resolved_object.pk',
+link_index_template_delete = Link(
+ icon_class=icon_index_template_delete,
+ kwargs={'index_template_id': 'resolved_object.pk'},
permission=permission_document_indexing_delete, tags='dangerous',
- text=_('Delete'), view='indexing:index_setup_delete',
+ text=_('Delete'), view='indexing:index_template_delete'
)
-link_index_setup_view = Link(
- args='resolved_object.pk', icon_class=icon_index_setup_view,
+link_index_template_edit = Link(
+ icon_class=icon_index_template_edit,
+ kwargs={'index_template_id': 'resolved_object.pk'},
+ permission=permission_document_indexing_edit, text=_('Edit'),
+ view='indexing:index_template_edit'
+)
+link_index_template_view = Link(
+ kwargs={'index_template_id': 'resolved_object.pk'}, icon_class=icon_index_template_view,
permission=permission_document_indexing_edit, text=_('Tree template'),
- view='indexing:index_setup_view',
+ view='indexing:index_template_view'
)
-link_index_setup_document_types = Link(
- args='resolved_object.pk', icon_class=icon_document_type,
+link_index_template_document_types = Link(
+ kwargs={'index_template_id': 'resolved_object.pk'}, icon_class=icon_document_type,
permission=permission_document_indexing_edit, text=_('Document types'),
- view='indexing:index_setup_document_types',
+ view='indexing:index_template_document_types'
)
-link_rebuild_index_instances = Link(
- condition=get_cascade_condition(
- app_label='document_indexing', model_name='Index',
- object_permission=permission_document_indexing_rebuild,
- ), icon_class=icon_rebuild_index_instances,
- description=_(
- 'Deletes and creates from scratch all the document indexes.'
- ),
- text=_('Rebuild indexes'), view='indexing:rebuild_index_instances'
+link_index_template_node_create = Link(
+ icon_class=icon_index_template_node_create,
+ kwargs={'index_template_node_id': 'resolved_object.pk'},
+ text=_('New node'), view='indexing:index_template_node_create'
)
-link_template_node_create = Link(
- args='resolved_object.pk', text=_('New child node'),
- view='indexing:template_node_create',
+link_index_template_node_delete = Link(
+ condition=condition_is_not_root_node,
+ icon_class=icon_index_template_node_delete,
+ kwargs={'index_template_node_id': 'resolved_object.pk'}, tags='dangerous',
+ text=_('Delete'), view='indexing:index_template_node_delete'
)
-link_template_node_edit = Link(
- args='resolved_object.pk', condition=is_not_root_node, text=_('Edit'),
- view='indexing:template_node_edit',
-)
-link_template_node_delete = Link(
- args='resolved_object.pk', condition=is_not_root_node, tags='dangerous',
- text=_('Delete'), view='indexing:template_node_delete',
+link_index_template_node_edit = Link(
+ condition=condition_is_not_root_node,
+ icon_class=icon_index_template_node_edit,
+ kwargs={'index_template_node_id': 'resolved_object.pk'}, text=_('Edit'),
+ view='indexing:index_template_node_edit'
)
diff --git a/mayan/apps/document_indexing/models.py b/mayan/apps/document_indexing/models.py
index ee339d71a1..d5f9fdc5cf 100644
--- a/mayan/apps/document_indexing/models.py
+++ b/mayan/apps/document_indexing/models.py
@@ -66,7 +66,7 @@ class Index(models.Model):
try:
return reverse(
viewname='indexing:index_instance_node_view',
- kwargs={'index_instance_node_pk': self.instance_root.pk}
+ kwargs={'index_instance_node_id': self.instance_root.pk}
)
except IndexInstanceNode.DoesNotExist:
return '#'
@@ -183,7 +183,7 @@ class IndexTemplateNode(MPTTModel):
)
index = models.ForeignKey(
on_delete=models.CASCADE, related_name='node_templates', to=Index,
- verbose_name=_('Index')
+ verbose_name=_('Index template')
)
expression = models.TextField(
help_text=_(
@@ -356,7 +356,7 @@ class IndexInstanceNode(MPTTModel):
def get_absolute_url(self):
return reverse(
viewname='indexing:index_instance_node_view',
- kwargs={'index_instance_node_pk': self.pk}
+ kwargs={'index_instance_node_id': self.pk}
)
def get_children_count(self):
diff --git a/mayan/apps/document_indexing/tasks.py b/mayan/apps/document_indexing/tasks.py
index 506c6e243b..f14db26da6 100644
--- a/mayan/apps/document_indexing/tasks.py
+++ b/mayan/apps/document_indexing/tasks.py
@@ -58,13 +58,13 @@ def task_index_document(self, document_id):
@app.task(bind=True, default_retry_delay=RETRY_DELAY, ignore_result=True)
-def task_rebuild_index(self, index_id):
+def task_rebuild_index(self, index_template_id):
Index = apps.get_model(
app_label='document_indexing', model_name='Index'
)
try:
- index = Index.objects.get(pk=index_id)
+ index = Index.objects.get(pk=index_template_id)
index.rebuild()
except LockError as exception:
# This index is being rebuilt by another task, retry later
diff --git a/mayan/apps/document_indexing/templates/document_indexing/index_instance_node.html b/mayan/apps/document_indexing/templates/document_indexing/index_instance_node.html
new file mode 100644
index 0000000000..edd1b16155
--- /dev/null
+++ b/mayan/apps/document_indexing/templates/document_indexing/index_instance_node.html
@@ -0,0 +1,13 @@
+{% load appearance_tags %}
+
+{% get_icon 'mayan.apps.document_indexing.icons.icon_index_instance_node_with_documents' as icon_index_instance_node_with_documents %}
+{% get_icon 'mayan.apps.document_indexing.icons.icon_index_level_up' as icon_index_level_up %}
+
+
+ {% if index_instance_node.index_template_node.link_documents %}
+ {{ icon_index_instance_node_with_documents }}
+ {% else %}
+ {{ icon_index_level_up }}
+ {% endif %}
+ {{ index_instance_node }}
+
diff --git a/mayan/apps/document_indexing/templates/document_indexing/index_template_node_indentation.html b/mayan/apps/document_indexing/templates/document_indexing/index_template_node_indentation.html
new file mode 100644
index 0000000000..53bd36a9e8
--- /dev/null
+++ b/mayan/apps/document_indexing/templates/document_indexing/index_template_node_indentation.html
@@ -0,0 +1,11 @@
+{% load appearance_tags %}
+
+{% get_icon 'mayan.apps.document_indexing.icons.icon_index_level_up' as icon_index_level_up %}
+
+{% for level in index_template_node_level %}
+
+{% endfor %}
+{% if not index_template_node.is_root_node %}
+ {{ icon_index_level_up }}
+{% endif %}
+{{ index_template_node }}
diff --git a/mayan/apps/document_indexing/templates/document_indexing/node_details.html b/mayan/apps/document_indexing/templates/document_indexing/node_details.html
index a1ac26b6bf..31567ea8da 100644
--- a/mayan/apps/document_indexing/templates/document_indexing/node_details.html
+++ b/mayan/apps/document_indexing/templates/document_indexing/node_details.html
@@ -20,5 +20,4 @@
{% endif %}
-
{% endblock %}
diff --git a/mayan/apps/document_indexing/tests/literals.py b/mayan/apps/document_indexing/tests/literals.py
index e58a75cb4b..96cf041a06 100644
--- a/mayan/apps/document_indexing/tests/literals.py
+++ b/mayan/apps/document_indexing/tests/literals.py
@@ -9,3 +9,5 @@ TEST_METADATA_VALUE = '0001'
TEST_INDEX_TEMPLATE_METADATA_EXPRESSION = '{{{{ document.get_metadata("{}").value }}}}'.format(TEST_METADATA_TYPE_NAME)
TEST_INDEX_TEMPLATE_DOCUMENT_LABEL_EXPRESSION = '{{ document.label }}'
TEST_INDEX_TEMPLATE_DOCUMENT_DESCRIPTION_EXPRESSION = '{{ document.description }}'
+TEST_INDEX_TEMPLATE_DOCUMENT_UUID_EXPRESSION = '{{ document.uuid }}'
+TEST_INDEX_TEMPLATE_NODE_EXPRESSION_EDITED = 'expression edited'
diff --git a/mayan/apps/document_indexing/tests/mixins.py b/mayan/apps/document_indexing/tests/mixins.py
index 239b8de7dd..b0396dab28 100644
--- a/mayan/apps/document_indexing/tests/mixins.py
+++ b/mayan/apps/document_indexing/tests/mixins.py
@@ -2,13 +2,30 @@ from __future__ import unicode_literals
from ..models import Index
-from .literals import TEST_INDEX_LABEL
+from .literals import (
+ TEST_INDEX_LABEL, TEST_INDEX_TEMPLATE_DOCUMENT_LABEL_EXPRESSION
+)
-class DocumentIndexingTestMixin(object):
- def _create_index(self):
+class IndexTemplateTestMixin(object):
+ def _create_index_template(self, add_document_type=False):
# Create empty index
- self.index = Index.objects.create(label=TEST_INDEX_LABEL)
+ self.test_index_template = Index.objects.create(label=TEST_INDEX_LABEL)
- # Add our document type to the new index
- self.index.document_types.add(self.document_type)
+ if add_document_type:
+ # Add our document type to the new index
+ self.test_index_template.document_types.add(self.test_document_type)
+
+ def _create_index_template_node(self, expression=None, rebuild=False):
+ self._create_index_template(add_document_type=True)
+
+ expression = expression or TEST_INDEX_TEMPLATE_DOCUMENT_LABEL_EXPRESSION
+
+ self.test_index_template_node = self.test_index_template.node_templates.create(
+ parent=self.test_index_template.template_root,
+ expression=expression, link_documents=True
+ )
+
+ # Rebuild indexes
+ if rebuild:
+ Index.objects.rebuild()
diff --git a/mayan/apps/document_indexing/tests/test_models.py b/mayan/apps/document_indexing/tests/test_models.py
index 3077e0dce3..acaff8e9a4 100644
--- a/mayan/apps/document_indexing/tests/test_models.py
+++ b/mayan/apps/document_indexing/tests/test_models.py
@@ -3,9 +3,7 @@ from __future__ import unicode_literals
from django.utils.encoding import force_text
from mayan.apps.common.tests import BaseTestCase
-from mayan.apps.documents.tests import (
- TEST_SMALL_DOCUMENT_PATH, DocumentTestMixin
-)
+from mayan.apps.documents.tests import DocumentTestMixin
from mayan.apps.documents.tests.literals import (
TEST_DOCUMENT_DESCRIPTION, TEST_DOCUMENT_DESCRIPTION_EDITED,
TEST_DOCUMENT_LABEL_EDITED
@@ -20,65 +18,54 @@ from .literals import (
TEST_INDEX_TEMPLATE_METADATA_EXPRESSION, TEST_METADATA_TYPE_LABEL,
TEST_METADATA_TYPE_NAME, TEST_METADATA_VALUE
)
-from .mixins import DocumentIndexingTestMixin
+from .mixins import IndexTemplateTestMixin
-class IndexTestCase(DocumentIndexingTestMixin, DocumentTestMixin, BaseTestCase):
+class IndexTestCase(IndexTemplateTestMixin, DocumentTestMixin, BaseTestCase):
def test_document_description_index(self):
- self._create_index()
-
- self.index.node_templates.create(
- parent=self.index.template_root,
+ self.test_document.description = TEST_DOCUMENT_DESCRIPTION
+ self.test_document.save()
+ self._create_index_template_node(
expression=TEST_INDEX_TEMPLATE_DOCUMENT_DESCRIPTION_EXPRESSION,
- link_documents=True
+ rebuild=True
)
- self.document.description = TEST_DOCUMENT_DESCRIPTION
- self.document.save()
-
- self.index.rebuild()
-
self.assertEqual(
- IndexInstanceNode.objects.last().value, self.document.description
+ IndexInstanceNode.objects.last().value, self.test_document.description
)
- self.document.description = TEST_DOCUMENT_DESCRIPTION_EDITED
- self.document.save()
+ self.test_document.description = TEST_DOCUMENT_DESCRIPTION_EDITED
+ self.test_document.save()
self.assertEqual(
- IndexInstanceNode.objects.last().value, self.document.description
+ IndexInstanceNode.objects.last().value, self.test_document.description
)
def test_document_label_index(self):
- self._create_index()
-
- self.index.node_templates.create(
- parent=self.index.template_root,
+ self._create_index_template_node(
expression=TEST_INDEX_TEMPLATE_DOCUMENT_LABEL_EXPRESSION,
- link_documents=True
+ rebuild=True
)
- self.index.rebuild()
-
self.assertEqual(
- IndexInstanceNode.objects.last().value, self.document.label
+ IndexInstanceNode.objects.last().value, self.test_document.label
)
- self.document.label = TEST_DOCUMENT_LABEL_EDITED
- self.document.save()
+ self.test_document.label = TEST_DOCUMENT_LABEL_EDITED
+ self.test_document.save()
self.assertEqual(
- IndexInstanceNode.objects.last().value, self.document.label
+ IndexInstanceNode.objects.last().value, self.test_document.label
)
def test_date_based_index(self):
- self._create_index()
+ self._create_index_template(add_document_type=True)
- level_year = self.index.node_templates.create(
- parent=self.index.template_root,
+ level_year = self.test_index_template.node_templates.create(
+ parent=self.test_index_template.template_root,
expression='{{ document.date_added.year }}',
link_documents=False
)
- self.index.node_templates.create(
+ self.test_index_template.node_templates.create(
parent=level_year,
expression='{{ document.date_added.month }}',
link_documents=True
@@ -89,18 +76,18 @@ class IndexTestCase(DocumentIndexingTestMixin, DocumentTestMixin, BaseTestCase):
self.document.delete()
# Uploading a new should not trigger an error
- document = self.upload_document()
+ self._create_document()
self.assertEqual(
- [instance.value for instance in IndexInstanceNode.objects.all().order_by('index_instance_node_pk')],
+ [instance.value for instance in IndexInstanceNode.objects.all()],
[
- '', force_text(document.date_added.year),
- force_text(document.date_added.month).zfill(2)
+ '', force_text(self.test_document.date_added.year),
+ force_text(self.test_document.date_added.month)
]
)
self.assertTrue(
- document in list(IndexInstanceNode.objects.order_by('index_instance_node_pk').last().documents.all())
+ self.test_document in list(IndexInstanceNode.objects.last().documents.all())
)
def test_dual_level_dual_document_index(self):
@@ -109,33 +96,33 @@ class IndexTestCase(DocumentIndexingTestMixin, DocumentTestMixin, BaseTestCase):
values and two second levels with the same value but as separate
children of each of the first levels. GitLab issue #391
"""
- with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object:
- self.document_2 = self.document_type.new_document(
- file_object=file_object
- )
+ self.document_2 = self.upload_document()
- self._create_index()
+ self._create_index_template(add_document_type=True)
# Create simple index template
- root = self.index.template_root
- level_1 = self.index.node_templates.create(
+ root = self.test_index_template.template_root
+ level_1 = self.test_index_template.node_templates.create(
parent=root, expression='{{ document.uuid }}',
link_documents=False
)
- self.index.node_templates.create(
+ self.test_index_template.node_templates.create(
parent=level_1, expression='{{ document.label }}',
link_documents=True
)
Index.objects.rebuild()
+ # Typecast to sets to make sorting irrelevant in the comparison.
self.assertEqual(
- [instance.value for instance in IndexInstanceNode.objects.all().order_by('index_instance_node_pk')],
- [
- '', force_text(self.document_2.uuid), self.document_2.label,
- force_text(self.document.uuid), self.document.label
- ]
+ set(IndexInstanceNode.objects.values_list('value', flat=True)),
+ set(
+ [
+ '', force_text(self.document_2.uuid), self.document_2.label,
+ force_text(self.document.uuid), self.document.label
+ ]
+ )
)
def test_metadata_indexing(self):
@@ -146,11 +133,11 @@ class IndexTestCase(DocumentIndexingTestMixin, DocumentTestMixin, BaseTestCase):
document_type=self.document_type, metadata_type=metadata_type
)
- self._create_index()
+ self._create_index_template(add_document_type=True)
# Create simple index template
- root = self.index.template_root
- self.index.node_templates.create(
+ root = self.test_index_template.template_root
+ self.test_index_template.node_templates.create(
parent=root, expression=TEST_INDEX_TEMPLATE_METADATA_EXPRESSION,
link_documents=True
)
@@ -231,15 +218,15 @@ class IndexTestCase(DocumentIndexingTestMixin, DocumentTestMixin, BaseTestCase):
On a two level template if the first level doesn't return a result
the indexing should stop. GitLab issue #391.
"""
- self._create_index()
+ self._create_index_template(add_document_type=True)
- level_1 = self.index.node_templates.create(
- parent=self.index.template_root,
+ level_1 = self.test_index_template.node_templates.create(
+ parent=self.test_index_template.template_root,
expression='',
link_documents=True
)
- self.index.node_templates.create(
+ self.test_index_template.node_templates.create(
parent=level_1, expression='{{ document.label }}',
link_documents=True
)
@@ -260,11 +247,11 @@ class IndexTestCase(DocumentIndexingTestMixin, DocumentTestMixin, BaseTestCase):
metadata_type=metadata_type, value=TEST_METADATA_VALUE
)
- self._create_index()
+ self._create_index_template(add_document_type=True)
# Create simple index template
- root = self.index.template_root
- self.index.node_templates.create(
+ root = self.test_index_template.template_root
+ self.test_index_template.node_templates.create(
parent=root, expression=TEST_INDEX_TEMPLATE_METADATA_EXPRESSION,
link_documents=True
)
diff --git a/mayan/apps/document_indexing/tests/test_views.py b/mayan/apps/document_indexing/tests/test_views.py
index 56fcd49c6f..9fee007312 100644
--- a/mayan/apps/document_indexing/tests/test_views.py
+++ b/mayan/apps/document_indexing/tests/test_views.py
@@ -1,5 +1,8 @@
from __future__ import absolute_import, unicode_literals
+from mayan.apps.documents.permissions import (
+ permission_document_view, permission_document_type_view
+)
from mayan.apps.documents.tests import GenericDocumentViewTestCase
from ..models import Index
@@ -7,23 +10,213 @@ from ..permissions import (
permission_document_indexing_create, permission_document_indexing_delete,
permission_document_indexing_edit,
permission_document_indexing_instance_view,
- permission_document_indexing_rebuild
+ permission_document_indexing_rebuild, permission_document_indexing_view
)
from .literals import (
TEST_INDEX_LABEL, TEST_INDEX_LABEL_EDITED, TEST_INDEX_SLUG,
- TEST_INDEX_TEMPLATE_DOCUMENT_LABEL_EXPRESSION
+ TEST_INDEX_TEMPLATE_DOCUMENT_UUID_EXPRESSION,
+ TEST_INDEX_TEMPLATE_NODE_EXPRESSION_EDITED
)
+from .mixins import IndexTemplateTestMixin
-class IndexViewTestCase(GenericDocumentViewTestCase):
- def setUp(self):
- super(IndexViewTestCase, self).setUp()
- self.login_user()
+class IndexInstanceViewTestCase(IndexTemplateTestMixin, GenericDocumentViewTestCase):
+ def _request_index_instance_list_view(self):
+ return self.get(
+ viewname='indexing:index_instance_list',
+ )
+
+ def test_index_instance_list_view_no_permission(self):
+ self._create_index_template_node()
+
+ response = self._request_index_instance_list_view()
+
+ self.assertNotContains(
+ response=response, text=TEST_INDEX_LABEL, status_code=200
+ )
+
+ def test_index_instance_list_view_with_access(self):
+ self._create_index_template_node(rebuild=True)
+
+ self.grant_access(
+ obj=self.test_index_template,
+ permission=permission_document_indexing_instance_view
+ )
+
+ response = self._request_index_instance_list_view()
+
+ self.assertContains(
+ response=response, text=TEST_INDEX_LABEL, status_code=200
+ )
+
+ def _request_index_instance_node_view(self, index_instance_node=None):
+ index_instance_node = index_instance_node or self.test_index_template.instance_root
+
+ return self.get(
+ viewname='indexing:index_instance_node_view',
+ kwargs={
+ 'index_instance_node_id': index_instance_node.pk
+ }
+ )
+
+ def test_index_instance_node_view_no_permission(self):
+ self._create_index_template_node()
+
+ response = self._request_index_instance_node_view()
+
+ self.assertEqual(response.status_code, 404)
+
+ def test_index_instance_node_view_with_access(self):
+ self._create_index_template_node()
+
+ self.grant_access(
+ obj=self.test_index_template,
+ permission=permission_document_indexing_instance_view
+ )
+
+ response = self._request_index_instance_node_view()
+
+ self.assertContains(
+ response=response, text=TEST_INDEX_LABEL, status_code=200
+ )
+
+ def _test_index_instance_node_documents_view_base(self, index_access=False, document_access=False):
+ self._create_index_template_node(
+ expression=TEST_INDEX_TEMPLATE_DOCUMENT_UUID_EXPRESSION,
+ rebuild=True
+ )
+
+ if index_access:
+ self.grant_access(
+ obj=self.test_index_template,
+ permission=permission_document_indexing_instance_view
+ )
+
+ if document_access:
+ self.grant_access(
+ obj=self.test_document,
+ permission=permission_document_view
+ )
+
+ index_instance_node = self.test_index_template.instance_root.get_children().get(
+ value=self.test_document.uuid
+ )
+
+ return self._request_index_instance_node_view(
+ index_instance_node=index_instance_node
+ )
+
+ def test_index_instance_node_documents_view_no_permission(self):
+ response = self._test_index_instance_node_documents_view_base()
+
+ self.assertNotContains(
+ response=response, text=TEST_INDEX_LABEL, status_code=404
+ )
+ self.assertNotContains(
+ response=response, text=self.test_document.label, status_code=404
+ )
+
+ def test_index_instance_node_documents_view_with_index_access(self):
+ response = self._test_index_instance_node_documents_view_base(
+ index_access=True
+ )
+
+ self.assertContains(
+ response=response, text=TEST_INDEX_LABEL, status_code=200
+ )
+ self.assertNotContains(
+ response=response, text=self.test_document.label, status_code=200
+ )
+
+ def test_index_instance_node_documents_view_with_document_access(self):
+ response = self._test_index_instance_node_documents_view_base(
+ document_access=True
+ )
+
+ self.assertNotContains(
+ response=response, text=TEST_INDEX_LABEL, status_code=404
+ )
+ self.assertNotContains(
+ response=response, text=self.test_document.label, status_code=404
+ )
+
+ def test_index_instance_node_documents_view_with_full_access(self):
+ response = self._test_index_instance_node_documents_view_base(
+ index_access=True, document_access=True
+ )
+
+ self.assertContains(
+ response=response, text=TEST_INDEX_LABEL, status_code=200
+ )
+ self.assertContains(
+ response=response, text=self.test_document.label, status_code=200
+ )
+
+ def _request_index_instances_rebuild_get_view(self):
+ return self.get(
+ viewname='indexing:index_instances_rebuild',
+ )
+
+ def _request_index_instances_rebuild_post_view(self):
+ return self.post(
+ viewname='indexing:index_instances_rebuild', data={
+ 'index_templates': self.test_index_template.pk
+ }
+ )
+
+ def test_index_instances_rebuild_get_view_no_permission(self):
+ self._create_index_template_node(rebuild=False)
+
+ response = self._request_index_instances_rebuild_get_view()
+ self.assertNotContains(
+ response=response, text=self.test_index_template.label, status_code=200
+ )
+
+ def test_index_instances_rebuild_get_view_with_access(self):
+ self._create_index_template_node(rebuild=False)
+
+ self.grant_access(
+ obj=self.test_index_template, permission=permission_document_indexing_rebuild
+ )
+
+ response = self._request_index_instances_rebuild_get_view()
+ self.assertContains(
+ response=response, text=self.test_index_template.label, status_code=200
+ )
+
+ def test_index_instances_rebuild_post_view_no_permission(self):
+ self._create_index_template_node(rebuild=False)
+
+ response = self._request_index_instances_rebuild_post_view()
+ # No error since we just don't see the index
+ self.assertEqual(response.status_code, 200)
+
+ self.assertEqual(
+ self.test_index_template.instance_root.get_children_count(), 0
+ )
+
+ def test_index_instances_rebuild_post_view_with_access(self):
+ self._create_index_template_node(rebuild=False)
+
+ self.grant_access(
+ obj=self.test_index_template, permission=permission_document_indexing_rebuild
+ )
+
+ response = self._request_index_instances_rebuild_post_view()
+ self.assertEqual(response.status_code, 302)
+
+ # An instance root exists
+ self.assertTrue(self.test_index_template.instance_root.pk)
+
+
+class IndexTemplateViewTestCase(IndexTemplateTestMixin, GenericDocumentViewTestCase):
+ auto_create_document_type = False
+ auto_upload_document = False
def _request_index_create_view(self):
return self.post(
- 'indexing:index_setup_create', data={
+ 'indexing:index_template_create', data={
'label': TEST_INDEX_LABEL, 'slug': TEST_INDEX_SLUG
}
)
@@ -31,6 +224,7 @@ class IndexViewTestCase(GenericDocumentViewTestCase):
def test_index_create_view_no_permission(self):
response = self._request_index_create_view()
self.assertEquals(response.status_code, 403)
+
self.assertEqual(Index.objects.count(), 0)
def test_index_create_view_with_permission(self):
@@ -41,159 +235,218 @@ class IndexViewTestCase(GenericDocumentViewTestCase):
response = self._request_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, index):
+ def _request_index_template_delete_view(self):
return self.post(
- viewname='indexing:index_setup_delete',
- kwargs={'index_pk': index.pk}
+ viewname='indexing:index_template_delete',
+ kwargs={'index_template_id': self.test_index_template.pk}
)
- def test_index_delete_view_no_permission(self):
- index = Index.objects.create(
- label=TEST_INDEX_LABEL, slug=TEST_INDEX_SLUG
- )
+ def test_index_template_delete_view_no_permission(self):
+ self._create_index_template()
- response = self._request_index_delete_view(index=index)
+ response = self._request_index_template_delete_view()
self.assertEqual(response.status_code, 404)
+
self.assertEqual(Index.objects.count(), 1)
- def test_index_delete_view_with_permission(self):
- self.role.permissions.add(
- permission_document_indexing_delete.stored_permission
+ def test_index_template_delete_view_with_access(self):
+ self._create_index_template()
+
+ self.grant_access(
+ obj=self.test_index_template,
+ permission=permission_document_indexing_delete
)
-
- index = Index.objects.create(
- label=TEST_INDEX_LABEL, slug=TEST_INDEX_SLUG
- )
-
- response = self._request_index_delete_view(index=index)
-
+ response = self._request_index_template_delete_view()
self.assertEqual(response.status_code, 302)
+
self.assertEqual(Index.objects.count(), 0)
- def _request_index_edit_view(self, index):
+ def _request_index_template_document_types_view(self):
return self.post(
- viewname='indexing:index_setup_edit', kwargs={
- 'index_pk': index.pk
+ viewname='indexing:index_template_document_types',
+ kwargs={'index_template_id': self.test_index_template.pk}
+ )
+
+ def test_index_template_document_types_view_no_permission(self):
+ self._create_document_type()
+ self._create_index_template()
+
+ response = self._request_index_template_document_types_view()
+ self.assertEqual(response.status_code, 404)
+
+ def test_index_template_document_types_view_with_index_access(self):
+ self._create_document_type()
+ self._create_index_template()
+
+ self.grant_access(
+ obj=self.test_index_template,
+ permission=permission_document_indexing_edit
+ )
+ response = self._request_index_template_document_types_view()
+ self.assertNotContains(
+ response=response, text=self.document_type.label, status_code=200
+ )
+
+ def test_index_template_document_types_view_with_document_type_access(self):
+ self._create_document_type()
+ self._create_index_template()
+
+ self.grant_access(
+ obj=self.test_document_type,
+ permission=permission_document_type_view
+ )
+ response = self._request_index_template_document_types_view()
+ self.assertEqual(response.status_code, 404)
+
+ def test_index_template_document_types_view_with_full_access(self):
+ self._create_document_type()
+ self._create_index_template()
+
+ self.grant_access(
+ obj=self.test_index_template,
+ permission=permission_document_indexing_edit
+ )
+ self.grant_access(
+ obj=self.test_document_type,
+ permission=permission_document_type_view
+ )
+ response = self._request_index_template_document_types_view()
+ self.assertContains(
+ response=response, text=self.document_type.label, status_code=200
+ )
+
+ def _request_index_edit_view(self):
+ return self.post(
+ viewname='indexing:index_template_edit', kwargs={
+ 'index_template_id': self.test_index_template.pk
}, data={
'label': TEST_INDEX_LABEL_EDITED, 'slug': TEST_INDEX_SLUG
}
)
def test_index_edit_view_no_permission(self):
- index = Index.objects.create(
- label=TEST_INDEX_LABEL, slug=TEST_INDEX_SLUG
- )
+ self._create_index_template()
- response = self._request_index_edit_view(index=index)
+ response = self._request_index_edit_view()
self.assertEqual(response.status_code, 404)
- index = Index.objects.get(pk=index.pk)
- self.assertEqual(index.label, TEST_INDEX_LABEL)
+
+ self.test_index_template.refresh_from_db()
+ self.assertEqual(self.test_index_template.label, TEST_INDEX_LABEL)
def test_index_edit_view_with_access(self):
- index = Index.objects.create(
- label=TEST_INDEX_LABEL, slug=TEST_INDEX_SLUG
- )
+ self._create_index_template()
self.grant_access(
- permission=permission_document_indexing_edit,
- obj=index
+ obj=self.test_index_template,
+ permission=permission_document_indexing_edit
)
- response = self._request_index_edit_view(index=index)
+ response = self._request_index_edit_view()
self.assertEqual(response.status_code, 302)
- index.refresh_from_db()
- self.assertEqual(index.label, TEST_INDEX_LABEL_EDITED)
- def _create_index(self, rebuild=True):
- # Create empty index
- self.index = Index.objects.create(label=TEST_INDEX_LABEL)
+ self.test_index_template.refresh_from_db()
+ self.assertEqual(self.test_index_template.label, TEST_INDEX_LABEL_EDITED)
- # Add our document type to the new index
- self.index.document_types.add(self.document_type)
+ def _request_index_template_list_view(self):
+ return self.get(viewname='indexing:index_template_list')
- # Create simple index template
- root = self.index.template_root
- self.index.node_templates.create(
- parent=root, expression=TEST_INDEX_TEMPLATE_DOCUMENT_LABEL_EXPRESSION,
- link_documents=True
+ def test_index_template_list_view_no_permission(self):
+ self._create_index_template()
+
+ response = self._request_index_template_list_view()
+ self.assertNotContains(
+ response=response, text=self.test_index_template.label, status_code=200
)
- # Rebuild indexes
- if rebuild:
- Index.objects.rebuild()
-
- def _request_index_instance_node_view(self, index_instance_node):
- return self.get(
- viewname='indexing:index_instance_node_view',
- kwargs={'index_instance_node_pk': index_instance_node.pk}
- )
-
- def test_index_instance_node_view_no_permission(self):
- self._create_index()
-
- response = self._request_index_instance_node_view(
- index_instance_node=self.index.instance_root
- )
-
- self.assertEqual(response.status_code, 403)
-
- def test_index_instance_node_view_with_access(self):
- self._create_index()
+ def test_index_template_list_view_with_access(self):
+ self._create_index_template()
self.grant_access(
- permission=permission_document_indexing_instance_view,
- obj=self.index
- )
-
- response = self._request_index_instance_node_view(
- index_instance_node=self.index.instance_root
+ obj=self.test_index_template,
+ permission=permission_document_indexing_view
)
+ response = self._request_index_template_list_view()
self.assertContains(
- response=response, text=TEST_INDEX_LABEL, status_code=200
+ response=response, text=self.test_index_template.label, status_code=200
)
- def _request_index_rebuild_get_view(self):
- return self.get(
- viewname='indexing:rebuild_index_instances',
- )
- def _request_index_rebuild_post_view(self):
+class IndexTemplaceNodeViewTestCase(IndexTemplateTestMixin, GenericDocumentViewTestCase):
+ auto_upload_document = False
+
+ def _request_index_instance_node_delete_view(self):
return self.post(
- viewname='indexing:rebuild_index_instances', data={
- 'indexes': self.index.pk
+ viewname='indexing:index_template_node_delete', kwargs={
+ 'index_template_node_id': self.test_index_template_node.pk
}
)
- def test_index_rebuild_no_permission(self):
- self._create_index(rebuild=False)
+ def test_index_template_node_delete_view_no_permission(self):
+ self._create_index_template_node()
- response = self._request_index_rebuild_get_view()
- self.assertNotContains(response=response, text=self.index.label, status_code=200)
+ response = self._request_index_instance_node_delete_view()
- response = self._request_index_rebuild_post_view()
- # No error since we just don't see the index
- self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.status_code, 404)
- self.assertEqual(
- self.index.instance_root.get_children_count(), 0
- )
+ # Root node plus the defaul test document label node
+ self.assertEqual(self.test_index_template.node_templates.count(), 2)
- def test_index_rebuild_with_access(self):
- self._create_index(rebuild=False)
+ def test_index_template_node_delete_view_with_access(self):
+ self._create_index_template_node()
self.grant_access(
- permission=permission_document_indexing_rebuild, obj=self.index
+ obj=self.test_index_template,
+ permission=permission_document_indexing_edit
)
- response = self._request_index_rebuild_get_view()
- self.assertContains(response=response, text=self.index.label, status_code=200)
+ response = self._request_index_instance_node_delete_view()
- response = self._request_index_rebuild_post_view()
self.assertEqual(response.status_code, 302)
- # An instance root exists
- self.assertTrue(self.index.instance_root.pk)
+ # Root node only
+ self.assertEqual(self.test_index_template.node_templates.count(), 1)
+
+ def _request_index_instance_node_edit_view(self):
+ return self.post(
+ viewname='indexing:index_template_node_edit', kwargs={
+ 'index_template_node_id': self.test_index_template_node.pk
+ }, data={
+ 'expression': TEST_INDEX_TEMPLATE_NODE_EXPRESSION_EDITED,
+ 'index': self.test_index_template.pk,
+ 'parent': self.test_index_template_node.parent.pk,
+
+ }
+ )
+
+ def test_index_template_node_edit_view_no_permission(self):
+ self._create_index_template_node()
+ original_expression = self.test_index_template_node.expression
+
+ response = self._request_index_instance_node_edit_view()
+ self.assertEqual(response.status_code, 404)
+
+ self.test_index_template_node.refresh_from_db()
+ self.assertEqual(
+ self.test_index_template_node.expression, original_expression
+ )
+
+ def test_index_template_node_edit_view_with_access(self):
+ self._create_index_template_node()
+ self.grant_access(
+ obj=self.test_index_template,
+ permission=permission_document_indexing_edit
+ )
+
+ response = self._request_index_instance_node_edit_view()
+ self.assertEqual(response.status_code, 302)
+
+ self.test_index_template_node.refresh_from_db()
+ self.assertEqual(
+ self.test_index_template_node.expression,
+ TEST_INDEX_TEMPLATE_NODE_EXPRESSION_EDITED
+ )
diff --git a/mayan/apps/document_indexing/urls.py b/mayan/apps/document_indexing/urls.py
index 5aa96bed20..0d97e64a6e 100644
--- a/mayan/apps/document_indexing/urls.py
+++ b/mayan/apps/document_indexing/urls.py
@@ -2,101 +2,109 @@ from __future__ import unicode_literals
from django.conf.urls import url
+"""
from .api_views import (
- APIDocumentIndexListView, APIIndexListView,
+ APIDocumentIndexTemplateListView, APIIndexTemplateListView,
APIIndexNodeInstanceDocumentListView, APIIndexTemplateListView,
APIIndexTemplateView, APIIndexView
)
+"""
from .views import (
- DocumentIndexNodeListView, IndexInstanceNodeView, IndexListView,
- RebuildIndexesView, SetupIndexCreateView, SetupIndexDeleteView,
- SetupIndexDocumentTypesView, SetupIndexEditView, SetupIndexListView,
- SetupIndexTreeTemplateListView, TemplateNodeCreateView,
- TemplateNodeDeleteView, TemplateNodeEditView
+ DocumentIndexInstanceNodeListView, IndexInstanceNodeView, IndexInstancesRebuildView,
+ IndexInstanceView, IndexTemplateCreateView, IndexTemplateDeleteView,
+ IndexTemplateDocumentTypesView, IndexTemplateEditView,
+ IndexTemplateListView, IndexTemplateNodeCreateView,
+ IndexTemplateNodeDeleteView, IndexTemplateNodeEditView,
+ IndexTemplateNodeListView
)
urlpatterns = [
url(
- regex=r'^indexes/$', name='index_setup_list',
- view=SetupIndexListView.as_view()
+ regex=r'^documents/(?P\d+)/indexes/$',
+ name='document_index_instance_list',
+ view=DocumentIndexInstanceNodeListView.as_view()
),
url(
- regex=r'^indexes/create/$', name='index_setup_create',
- view=SetupIndexCreateView.as_view()
+ regex=r'^index_instances/$', name='index_instance_list',
+ view=IndexInstanceView.as_view()
),
url(
- regex=r'^indexes/(?P\d+)/delete/$',
- name='index_setup_delete', view=SetupIndexDeleteView.as_view()
- ),
- url(
- regex=r'^indexes/(?P\d+)/edit/$',
- name='index_setup_edit', view=SetupIndexEditView.as_view()
- ),
- url(
- regex=r'^indexes/(?P\d+)/templates/$',
- name='index_setup_view', view=SetupIndexTreeTemplateListView.as_view()
- ),
- url(
- regex=r'^indexes/(?P\d+)/document_types/$',
- name='index_setup_document_types',
- view=SetupIndexDocumentTypesView.as_view()
- ),
- url(
- regex=r'^indexes/templates/nodes/(?P\d+)/create/child/$',
- name='template_node_create', view=TemplateNodeCreateView.as_view()
- ),
- url(
- regex=r'^indexes/templates/nodes/(?P\d+)/edit/$',
- name='template_node_edit', view=TemplateNodeEditView.as_view()
- ),
- url(
- regex=r'^indexes/templates/nodes/(?P\d+)/delete/$',
- name='template_node_delete', view=TemplateNodeDeleteView.as_view()
- ),
- url(
- regex=r'^indexes/instances/list/$', name='index_list',
- view=IndexListView.as_view()
- ),
- url(
- regex=r'^indexes/instances/node/(?P\d+)/$',
+ regex=r'^index_instances/nodes/(?P\d+)/$',
name='index_instance_node_view', view=IndexInstanceNodeView.as_view()
),
-
url(
- regex=r'^indexes/rebuild/$', name='rebuild_index_instances',
- view=RebuildIndexesView.as_view()
+ regex=r'^index_instances/rebuild/$', name='index_instances_rebuild',
+ view=IndexInstancesRebuildView.as_view()
),
url(
- regex=r'^documents/(?P\d+)/indexes/$',
- name='document_index_list', view=DocumentIndexNodeListView.as_view()
+ regex=r'^index_templates/$', name='index_template_list',
+ view=IndexTemplateListView.as_view()
),
+ url(
+ regex=r'^index_templates/create/$', name='index_template_create',
+ view=IndexTemplateCreateView.as_view()
+ ),
+ url(
+ regex=r'^index_templates/(?P\d+)/delete/$',
+ name='index_template_delete', view=IndexTemplateDeleteView.as_view()
+ ),
+ url(
+ regex=r'^index_templates/(?P\d+)/document_types/$',
+ name='index_template_document_types',
+ view=IndexTemplateDocumentTypesView.as_view()
+ ),
+ url(
+ regex=r'^index_templates/(?P\d+)/edit/$',
+ name='index_template_edit', view=IndexTemplateEditView.as_view()
+ ),
+ url(
+ regex=r'^index_templates/(?P\d+)/nodes/$',
+ name='index_template_view', view=IndexTemplateNodeListView.as_view()
+ ),
+ url(
+ regex=r'^index_templates/nodes/(?P\d+)/create/$',
+ name='index_template_node_create',
+ view=IndexTemplateNodeCreateView.as_view()
+ ),
+ url(
+ regex=r'^index_templates/nodes/(?P\d+)/delete/$',
+ name='index_template_node_delete',
+ view=IndexTemplateNodeDeleteView.as_view()
+ ),
+ url(
+ regex=r'^index_templates/nodes/(?P\d+)/edit/$',
+ name='index_template_node_edit',
+ view=IndexTemplateNodeEditView.as_view()
+ )
]
+"""
api_urls = [
url(
- regex=r'^indexes/nodes/(?P[0-9]+)/documents/$',
+ regex=r'^index_templates/nodes/(?P\d+)/documents/$',
name='index-node-documents',
view=APIIndexNodeInstanceDocumentListView.as_view(),
),
url(
- regex=r'^indexes/templates/(?P[0-9]+)/$',
+ regex=r'^index_templates/templates/(?P\d+)/$',
name='index-template-detail', view=APIIndexTemplateView.as_view()
),
url(
- regex=r'^indexes/(?P\d+)/$', name='index-detail',
+ regex=r'^index_templates/(?P\d+)/$', name='index-detail',
view=APIIndexView.as_view()
),
url(
- regex=r'^indexes/(?P\d+)/templates/$',
+ regex=r'^index_templates/(?P\d+)/templates/$',
name='index-template-detail', view=APIIndexTemplateListView.as_view()
),
url(
- regex=r'^indexes/$', name='index-list',
- view=APIIndexListView.as_view()
+ regex=r'^index_templates/$', name='index-list',
+ view=APIIndexTemplateListView.as_view()
),
url(
regex=r'^documents/(?P\d+)/indexes/$',
name='document-index-list',
- view=APIDocumentIndexListView.as_view()
+ view=APIDocumentIndexTemplateListView.as_view()
),
]
+"""
diff --git a/mayan/apps/document_indexing/views.py b/mayan/apps/document_indexing/views.py
index 0de438b29d..57158d956d 100644
--- a/mayan/apps/document_indexing/views.py
+++ b/mayan/apps/document_indexing/views.py
@@ -1,7 +1,6 @@
from __future__ import absolute_import, unicode_literals
from django.contrib import messages
-from django.shortcuts import get_object_or_404
from django.template import RequestContext
from django.urls import reverse, reverse_lazy
from django.utils.html import mark_safe
@@ -13,13 +12,15 @@ from mayan.apps.common.generics import (
AssignRemoveView, FormView, SingleObjectCreateView, SingleObjectDeleteView,
SingleObjectEditView, SingleObjectListView
)
+from mayan.apps.common.mixins import ExternalObjectMixin
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_view
from mayan.apps.documents.views import DocumentListView
-from .forms import IndexListForm, IndexTemplateNodeForm
+from .forms import IndexTemplateFilteredForm, IndexTemplateNodeForm
+from .html_widgets import node_tree
from .icons import icon_index
-from .links import link_index_setup_create
+from .links import link_index_template_create
from .models import (
DocumentIndexInstanceNode, Index, IndexInstance, IndexInstanceNode,
IndexTemplateNode
@@ -31,218 +32,49 @@ from .permissions import (
permission_document_indexing_view
)
from .tasks import task_rebuild_index
-from .widgets import node_tree
-# Setup views
-class SetupIndexCreateView(SingleObjectCreateView):
- extra_context = {'title': _('Create index')}
- fields = ('label', 'slug', 'enabled')
- model = Index
- post_action_redirect = reverse_lazy(viewname='indexing:index_setup_list')
- view_permission = permission_document_indexing_create
-
-
-class SetupIndexDeleteView(SingleObjectDeleteView):
- model = Index
- object_permission = permission_document_indexing_delete
- pk_url_kwarg = 'index_pk'
- post_action_redirect = reverse_lazy(viewname='indexing:index_setup_list')
-
- def get_extra_context(self):
- return {
- 'object': self.get_object(),
- 'title': _('Delete the index: %s?') % self.get_object(),
- }
-
-
-class SetupIndexEditView(SingleObjectEditView):
- fields = ('label', 'slug', 'enabled')
- model = Index
- object_permission = permission_document_indexing_edit
- pk_url_kwarg = 'index_pk'
- post_action_redirect = reverse_lazy(viewname='indexing:index_setup_list')
-
- def get_extra_context(self):
- return {
- 'object': self.get_object(),
- 'title': _('Edit index: %s') % self.get_object(),
- }
-
-
-class SetupIndexListView(SingleObjectListView):
- model = Index
- object_permission = permission_document_indexing_view
+class DocumentIndexInstanceNodeListView(ExternalObjectMixin, SingleObjectListView):
+ """
+ Show a list of indexes where the current document can be found
+ """
+ external_object_class = Document
+ external_object_permission = permission_document_indexing_instance_view
+ external_object_pk_url_kwarg = 'document_id'
+ object_permission = permission_document_indexing_instance_view
def get_extra_context(self):
return {
'hide_object': True,
'no_results_icon': icon_index,
- 'no_results_main_link': link_index_setup_create.resolve(
- context=RequestContext(request=self.request)
- ),
'no_results_text': _(
- 'Indexes group document automatically into levels. Indexe are '
- 'defined using template whose markers are replaced with '
- 'direct properties of documents like label or description, or '
- 'that of extended properties like metadata.'
+ 'Assign the document type of this document '
+ 'to an index to have it appear in instances of '
+ 'those indexes organization units. '
),
- 'no_results_title': _('There are no indexes.'),
- 'title': _('Indexes'),
- }
-
-
-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')
-
- def add(self, item):
- self.get_object().document_types.add(item)
-
- def get_document_queryset(self):
- return AccessControlList.objects.restrict_queryset(
- permission=permission_document_view,
- queryset=DocumentType.objects.all(), user=self.request.user
- )
-
- def get_extra_context(self):
- return {
- 'object': self.get_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.'
+ 'no_results_title': _(
+ 'This document is not in any index instance'
),
+ 'object': self.external_object,
'title': _(
- 'Document types linked to index: %s'
- ) % self.get_object()
+ 'Index instance nodes containing document: %s'
+ ) % self.external_object,
}
- def get_object(self):
- return get_object_or_404(klass=Index, pk=self.kwargs['index_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(
- choices=self.get_document_queryset() & self.get_object().document_types.all()
- )
-
-
-class SetupIndexTreeTemplateListView(SingleObjectListView):
- object_permission = permission_document_indexing_edit
-
- def get_extra_context(self):
- return {
- 'hide_object': True,
- 'index': self.get_index(),
- 'navigation_object_list': ('index',),
- 'title': _('Tree template nodes for index: %s') % self.get_index(),
- }
-
- def get_index(self):
- return get_object_or_404(klass=Index, pk=self.kwargs['index_pk'])
-
def get_source_queryset(self):
- return self.get_index().template_root.get_descendants(
- include_self=True
+ return DocumentIndexInstanceNode.objects.get_for(
+ document=self.external_object
)
-class TemplateNodeCreateView(SingleObjectCreateView):
- form_class = IndexTemplateNodeForm
- model = IndexTemplateNode
-
- def dispatch(self, request, *args, **kwargs):
- AccessControlList.objects.check_access(
- obj=self.get_parent_node().index,
- permission=permission_document_indexing_edit, user=request.user
- )
-
- return super(
- TemplateNodeCreateView, self
- ).dispatch(request=request, *args, **kwargs)
-
- def get_extra_context(self):
- return {
- 'index': self.get_parent_node().index,
- 'navigation_object_list': ('index',),
- 'title': _('Create child node of: %s') % self.get_parent_node(),
- }
-
- def get_initial(self):
- parent_node = self.get_parent_node()
- return {
- 'index': parent_node.index, 'parent': parent_node
- }
-
- def get_parent_node(self):
- return get_object_or_404(
- klass=IndexTemplateNode, pk=self.kwargs['index_template_node_pk']
- )
-
-
-class TemplateNodeDeleteView(SingleObjectDeleteView):
- model = IndexTemplateNode
- object_permission = permission_document_indexing_edit
-
- def get_extra_context(self):
- return {
- 'index': self.get_object().index,
- 'navigation_object_list': ('index', 'node'),
- 'node': self.get_object(),
- 'title': _(
- 'Delete the index template node: %s?'
- ) % self.get_object(),
- }
-
- def get_post_action_redirect(self):
- return reverse(
- viewname='indexing:index_setup_view',
- kwargs={'index_pk': self.get_object().index.pk}
- )
-
-
-class TemplateNodeEditView(SingleObjectEditView):
- form_class = IndexTemplateNodeForm
- model = IndexTemplateNode
- object_permission = permission_document_indexing_edit
-
- def get_extra_context(self):
- return {
- 'index': self.get_object().index,
- 'navigation_object_list': ('index', 'node'),
- 'node': self.get_object(),
- 'title': _(
- 'Edit the index template node: %s?'
- ) % self.get_object(),
- }
-
- def get_post_action_redirect(self):
- return reverse(
- viewname='indexing:index_setup_view',
- kwargs={'index_pk': self.get_object().index.pk}
- )
-
-
-class IndexListView(SingleObjectListView):
+class IndexInstanceView(SingleObjectListView):
object_permission = permission_document_indexing_instance_view
def get_extra_context(self):
return {
'hide_links': True,
'no_results_icon': icon_index,
- 'no_results_main_link': link_index_setup_create.resolve(
+ 'no_results_main_link': link_index_template_create.resolve(
context=RequestContext(request=self.request)
),
'no_results_text': _(
@@ -261,53 +93,33 @@ class IndexListView(SingleObjectListView):
).distinct()
-class IndexInstanceNodeView(DocumentListView):
+class IndexInstanceNodeView(ExternalObjectMixin, DocumentListView):
+ external_object_class = IndexInstanceNode
+ external_object_permission = permission_document_indexing_instance_view
+ external_object_pk_url_kwarg = 'index_instance_node_id'
template_name = 'document_indexing/node_details.html'
- def dispatch(self, request, *args, **kwargs):
- self.index_instance_node = get_object_or_404(
- klass=IndexInstanceNode, pk=self.kwargs['index_instance_node_pk']
- )
-
- AccessControlList.objects.check_access(
- obj=self.index_instance_node.index(),
- permission=permission_document_indexing_instance_view,
- user=request.user
- )
-
- if self.index_instance_node:
- if self.index_instance_node.index_template_node.link_documents:
- return super(IndexInstanceNodeView, self).dispatch(
- request=request, *args, **kwargs
- )
-
- return SingleObjectListView.dispatch(
- self, request=request, *args, **kwargs
- )
-
- def get_document_queryset(self):
- if self.index_instance_node:
- if self.index_instance_node.index_template_node.link_documents:
- return self.index_instance_node.documents.all()
-
def get_extra_context(self):
context = super(IndexInstanceNodeView, self).get_extra_context()
+ if not self.external_object.index_template_node.link_documents:
+ context.pop('table_cell_container_classes', None)
+
context.update(
{
'column_class': 'col-xs-12 col-sm-6 col-md-4 col-lg-3',
- 'object': self.index_instance_node,
+ 'object': self.external_object,
'navigation': mark_safe(
_('Navigation: %s') % node_tree(
- node=self.index_instance_node, user=self.request.user
+ node=self.external_object, user=self.request.user
)
),
'title': _(
- 'Contents for index: %s'
- ) % self.index_instance_node.get_full_path(),
+ 'Contents for index instance: %s'
+ ) % self.external_object.get_full_path(),
}
)
- if self.index_instance_node and not self.index_instance_node.index_template_node.link_documents:
+ if not self.external_object.index_template_node.link_documents:
context.update(
{
'hide_object': True,
@@ -318,89 +130,39 @@ class IndexInstanceNodeView(DocumentListView):
return context
def get_source_queryset(self):
- if self.index_instance_node:
- if self.index_instance_node.index_template_node.link_documents:
- return super(IndexInstanceNodeView, self).get_source_queryset()
- else:
- self.object_permission = None
- return self.index_instance_node.get_children().order_by(
- 'value'
- )
+ if self.external_object.index_template_node.link_documents:
+ return self.external_object.documents.all()
else:
- self.object_permission = None
- return IndexInstanceNode.objects.none()
+ return self.external_object.get_children().order_by(
+ 'value'
+ )
-class DocumentIndexNodeListView(SingleObjectListView):
- """
- Show a list of indexes where the current document can be found
- """
- object_permission = permission_document_indexing_instance_view
-
- def dispatch(self, request, *args, **kwargs):
- AccessControlList.objects.check_access(
- obj=self.get_document(), permission=permission_document_view,
- user=request.user
- )
-
- return super(
- DocumentIndexNodeListView, self
- ).dispatch(request=request, *args, **kwargs)
-
- def get_document(self):
- return get_object_or_404(
- klass=Document, pk=self.kwargs['document_pk']
- )
-
- def get_extra_context(self):
- return {
- 'hide_object': True,
- 'no_results_icon': icon_index,
- 'no_results_text': _(
- 'Assign the document type of this document '
- 'to an index to have it appear in instances of '
- 'those indexes organization units. '
- ),
- 'no_results_title': _(
- 'This document is not in any index'
- ),
- 'object': self.get_document(),
- 'title': _(
- 'Indexes nodes containing document: %s'
- ) % self.get_document(),
- }
-
- def get_source_queryset(self):
- return DocumentIndexInstanceNode.objects.get_for(
- document=self.get_document()
- )
-
-
-class RebuildIndexesView(FormView):
+class IndexInstancesRebuildView(FormView):
extra_context = {
- 'title': _('Rebuild indexes'),
+ 'title': _('Rebuild index instances'),
}
- form_class = IndexListForm
+ form_class = IndexTemplateFilteredForm
def form_valid(self, form):
count = 0
- for index in form.cleaned_data['indexes']:
+ for index_template in form.cleaned_data['index_templates']:
task_rebuild_index.apply_async(
- kwargs=dict(index_id=index.pk)
+ kwargs=dict(index_template_id=index_template.pk)
)
count += 1
messages.success(
request=self.request, message=ungettext(
- singular='%(count)d index queued for rebuild.',
- plural='%(count)d indexes queued for rebuild.',
+ singular='%(count)d index template queued for rebuild.',
+ plural='%(count)d indexes templates queued for rebuild.',
number=count
) % {
'count': count,
}
)
- return super(RebuildIndexesView, self).form_valid(form=form)
+ return super(IndexInstancesRebuildView, self).form_valid(form=form)
def get_form_extra_kwargs(self):
return {
@@ -409,3 +171,191 @@ class RebuildIndexesView(FormView):
def get_post_action_redirect(self):
return reverse(viewname='common:tools_list')
+
+
+class IndexTemplateCreateView(SingleObjectCreateView):
+ extra_context = {'title': _('Create index')}
+ fields = ('label', 'slug', 'enabled')
+ model = Index
+ post_action_redirect = reverse_lazy(viewname='indexing:index_template_list')
+ view_permission = permission_document_indexing_create
+
+
+class IndexTemplateDeleteView(SingleObjectDeleteView):
+ model = Index
+ object_permission = permission_document_indexing_delete
+ pk_url_kwarg = 'index_template_id'
+ post_action_redirect = reverse_lazy(viewname='indexing:index_template_list')
+
+ def get_extra_context(self):
+ return {
+ 'object': self.object,
+ 'title': _('Delete the index template: %s?') % self.object,
+ }
+
+
+class IndexTemplateDocumentTypesView(ExternalObjectMixin, AssignRemoveView):
+ decode_content_type = True
+ external_object_class = Index
+ external_object_permission = permission_document_indexing_edit
+ external_object_pk_url_kwarg = 'index_template_id'
+ left_list_title = _('Available document types')
+ object_permission = permission_document_indexing_edit
+ right_list_title = _('Document types linked')
+
+ def add(self, item):
+ self.external_object.document_types.add(item)
+
+ def get_document_type_queryset(self):
+ return AccessControlList.objects.restrict_queryset(
+ permission=permission_document_type_view,
+ queryset=DocumentType.objects.all(), user=self.request.user
+ )
+
+ def get_extra_context(self):
+ return {
+ 'object': self.external_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 template: %s'
+ ) % self.external_object
+ }
+
+ def left_list(self):
+ return AssignRemoveView.generate_choices(
+ self.get_document_type_queryset().exclude(
+ id__in=self.external_object.document_types.all()
+ )
+ )
+
+ def remove(self, item):
+ self.external_object.document_types.remove(item)
+
+ def right_list(self):
+ return AssignRemoveView.generate_choices(
+ choices=self.get_document_type_queryset() & self.external_object.document_types.all()
+ )
+
+
+class IndexTemplateEditView(SingleObjectEditView):
+ fields = ('label', 'slug', 'enabled')
+ model = Index
+ object_permission = permission_document_indexing_edit
+ pk_url_kwarg = 'index_template_id'
+ post_action_redirect = reverse_lazy(viewname='indexing:index_template_list')
+
+ def get_extra_context(self):
+ return {
+ 'object': self.object,
+ 'title': _('Edit index template: %s') % self.object,
+ }
+
+
+class IndexTemplateListView(SingleObjectListView):
+ model = Index
+ object_permission = permission_document_indexing_view
+
+ def get_extra_context(self):
+ return {
+ 'hide_object': True,
+ 'no_results_icon': icon_index,
+ 'no_results_main_link': link_index_template_create.resolve(
+ context=RequestContext(request=self.request)
+ ),
+ 'no_results_text': _(
+ 'Indexes group document automatically into levels. Indexe are '
+ 'defined using template whose markers are replaced with '
+ 'direct properties of documents like label or description, or '
+ 'that of extended properties like metadata.'
+ ),
+ 'no_results_title': _('There are no index templates.'),
+ 'title': _('Index templates'),
+ }
+
+
+class IndexTemplateNodeCreateView(ExternalObjectMixin, SingleObjectCreateView):
+ external_object_class = IndexTemplateNode
+ external_object_permission = permission_document_indexing_edit
+ external_object_pk_url_kwarg = 'index_template_node_id'
+ form_class = IndexTemplateNodeForm
+ model = IndexTemplateNode
+
+ def get_extra_context(self):
+ return {
+ 'index': self.external_object.index,
+ 'navigation_object_list': ('index',),
+ 'title': _('Create child node of: %s') % self.external_object,
+ }
+
+ def get_initial(self):
+ return {
+ 'index': self.external_object.index, 'parent': self.external_object
+ }
+
+
+class IndexTemplateNodeDeleteView(SingleObjectDeleteView):
+ model = IndexTemplateNode
+ object_permission = permission_document_indexing_edit
+ pk_url_kwarg = 'index_template_node_id'
+
+ def get_extra_context(self):
+ return {
+ 'index': self.object.index,
+ 'navigation_object_list': ('index', 'node'),
+ 'node': self.object,
+ 'title': _(
+ 'Delete the index template node: %s?'
+ ) % self.object,
+ }
+
+ def get_post_action_redirect(self):
+ return reverse(
+ viewname='indexing:index_template_view',
+ kwargs={'index_template_id': self.object.index.pk}
+ )
+
+
+class IndexTemplateNodeEditView(SingleObjectEditView):
+ form_class = IndexTemplateNodeForm
+ model = IndexTemplateNode
+ object_permission = permission_document_indexing_edit
+ pk_url_kwarg = 'index_template_node_id'
+
+ def get_extra_context(self):
+ return {
+ 'index': self.object.index,
+ 'navigation_object_list': ('index', 'node'),
+ 'node': self.object,
+ 'title': _(
+ 'Edit the index template node: %s?'
+ ) % self.object,
+ }
+
+ def get_post_action_redirect(self):
+ return reverse(
+ viewname='indexing:index_template_view',
+ kwargs={'index_template_id': self.object.index.pk}
+ )
+
+
+class IndexTemplateNodeListView(ExternalObjectMixin, SingleObjectListView):
+ external_object_class = Index
+ external_object_permission = permission_document_indexing_edit
+ external_object_pk_url_kwarg = 'index_template_id'
+
+ def get_extra_context(self):
+ return {
+ 'hide_object': True,
+ 'index': self.external_object,
+ 'navigation_object_list': ('index',),
+ 'title': _('Nodes for index template: %s') % self.external_object,
+ }
+
+ def get_source_queryset(self):
+ return self.external_object.template_root.get_descendants(
+ include_self=True
+ )