Add the document template sandbox feature

Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
This commit is contained in:
Roberto Rosario
2019-11-10 03:35:56 -04:00
parent cf154c46f4
commit cdb1815f49
7 changed files with 123 additions and 18 deletions

View File

@@ -128,6 +128,7 @@
- Support for proxy model permission inheritance. Proxy models
now get the permission inheritance from their base models.
- Update common.http.URL to allow passing a query dictionary.
- Add the document template sandbox feature.
3.2.9 (2019-11-03)
==================

View File

@@ -30,14 +30,14 @@ from .html_widgets import (
get_instance_link, index_instance_item_link, node_level
)
from .links import (
link_document_index_instance_list, link_document_type_index_templates,
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
link_document_index_instance_list, link_document_template_sandbox,
link_document_type_index_templates, 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
)
from .permissions import (
permission_document_indexing_create, permission_document_indexing_delete,
@@ -183,7 +183,10 @@ class DocumentIndexingApp(MayanAppConfig):
)
menu_facet.bind_links(
links=(link_document_index_instance_list,), sources=(Document,)
links=(
link_document_index_instance_list,
link_document_template_sandbox
), sources=(Document,)
)
menu_list_facet.bind_links(
links=(link_document_type_index_templates,),

View File

@@ -12,6 +12,41 @@ from .models import Index, IndexTemplateNode
from .permissions import permission_document_indexing_rebuild
class DocumentTemplateSandboxForm(forms.Form):
template = forms.CharField(
help_text=_(
'The template string to be evaluated. The current document '
'is available as the {{ document }} variable.'
), label=_('Template'), widget=forms.widgets.Textarea(
attrs={'rows': 5}
)
)
result = forms.CharField(
help_text=_('Resulting text from the evaluated template.'),
label=_('Result'), required=False, widget=forms.widgets.Textarea(
attrs={'rows': 5}
)
)
def __init__(self, *args, **kwargs):
super(DocumentTemplateSandboxForm, self).__init__(*args, **kwargs)
self.fields['template'].help_text = ' '.join(
[
force_text(self.fields['template'].help_text),
force_text(
_(
'Use Django\'s default templating language '
'(https://docs.djangoproject.com/en/1.11/ref/templates/builtins/)'
),
),
'<br>',
ModelProperty.get_help_text_for(
model=Document, show_name=True
).replace('\n', '<br>')
]
)
class IndexTemplateFilteredForm(FilteredSelectionForm):
class Meta:
allow_multiple = True

View File

@@ -3,10 +3,13 @@ from __future__ import absolute_import, unicode_literals
from mayan.apps.appearance.classes import Icon
from mayan.apps.documents.icons import icon_document_type
icon_index = 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_document_template_sandbox = Icon(
driver_name='fontawesome', symbol='flask'
)
icon_document_type_index_templates = icon_index
icon_index_level_up = Icon(
driver_name='fontawesomecss', css_classes='fa-level-up-alt fa-rotate-90'

View File

@@ -2,7 +2,6 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from mayan.apps.documents.permissions import permission_document_type_edit
from mayan.apps.navigation.classes import Link
from mayan.apps.navigation.utils import get_cascade_condition
@@ -24,10 +23,17 @@ link_document_index_instance_list = Link(
text=_('Indexes'), view='indexing:document_index_list',
)
link_document_template_sandbox = Link(
args='resolved_object.pk',
icon_class_path='mayan.apps.document_indexing.icons.icon_document_template_sandbox',
permissions=(permission_document_indexing_edit,),
text=_('Sandbox'),
view='indexing:document_template_sandbox',
)
link_document_type_index_templates = Link(
args='resolved_object.pk',
icon_class_path='mayan.apps.document_indexing.icons.icon_document_type_index_templates',
permissions=(permission_document_type_edit,), text=_('Index templates'),
permissions=(permission_document_indexing_create,), text=_('Index templates'),
view='indexing:document_type_index_templates',
)

View File

@@ -8,10 +8,11 @@ from .api_views import (
APIIndexTemplateView, APIIndexView
)
from .views import (
DocumentIndexNodeListView, DocumentTypeIndexesView, IndexInstanceNodeView,
IndexListView, IndexesRebuildView, SetupIndexDocumentTypesView,
SetupIndexCreateView, SetupIndexDeleteView, SetupIndexEditView,
SetupIndexListView, SetupIndexRebuildView, SetupIndexTreeTemplateListView,
DocumentIndexNodeListView, DocumentTemplateSandboxView,
DocumentTypeIndexesView, IndexInstanceNodeView, IndexListView,
IndexesRebuildView, SetupIndexDocumentTypesView, SetupIndexCreateView,
SetupIndexDeleteView, SetupIndexEditView, SetupIndexListView,
SetupIndexRebuildView, SetupIndexTreeTemplateListView,
TemplateNodeCreateView, TemplateNodeDeleteView, TemplateNodeEditView
)
@@ -83,6 +84,11 @@ urlpatterns_tools = [
regex=r'^instances/rebuild/$', view=IndexesRebuildView.as_view(),
name='rebuild_index_instances'
),
url(
regex=r'^documents/(?P<pk>\d+)/sandbox/$',
view=DocumentTemplateSandboxView.as_view(),
name='document_template_sandbox'
),
]
urlpatterns = []

View File

@@ -1,8 +1,11 @@
from __future__ import absolute_import, unicode_literals
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.template import RequestContext
from django.template import (
Context, RequestContext, Template, TemplateSyntaxError
)
from django.urls import reverse, reverse_lazy
from django.utils.html import mark_safe
from django.utils.translation import ugettext_lazy as _, ungettext
@@ -12,6 +15,8 @@ from mayan.apps.common.generics import (
AddRemoveView, ConfirmView, FormView, SingleObjectCreateView,
SingleObjectDeleteView, SingleObjectEditView, SingleObjectListView
)
from mayan.apps.common.http import URL
from mayan.apps.common.mixins import ExternalObjectMixin
from mayan.apps.documents.events import event_document_type_edited
from mayan.apps.documents.models import Document, DocumentType
from mayan.apps.documents.permissions import (
@@ -20,7 +25,9 @@ from mayan.apps.documents.permissions import (
from mayan.apps.documents.views import DocumentListView
from .events import event_index_template_edited
from .forms import IndexTemplateFilteredForm, IndexTemplateNodeForm
from .forms import (
DocumentTemplateSandboxForm, IndexTemplateFilteredForm, IndexTemplateNodeForm
)
from .html_widgets import node_tree
from .icons import icon_index
from .links import link_index_template_create
@@ -474,3 +481,47 @@ class IndexesRebuildView(FormView):
def get_post_action_redirect(self):
return reverse(viewname='common:tools_list')
class DocumentTemplateSandboxView(ExternalObjectMixin, FormView):
external_object_class = Document
external_object_permission = permission_document_indexing_create
form_class = DocumentTemplateSandboxForm
def form_valid(self, form):
path = reverse(
viewname='indexing:document_template_sandbox',
kwargs={'pk': self.external_object.pk}
)
url = URL(
path=path, query={'template': form.cleaned_data['template']}
)
return HttpResponseRedirect(redirect_to=url.to_string())
def get_initial(self):
template_string = self.request.GET.get('template')
try:
context = Context(
{'document': self.external_object}
)
template = Template(template_string=template_string)
result = template.render(context=context)
except TemplateSyntaxError as exception:
result = ''
error_message = _(
'Template error; %(exception)s'
) % {
'exception': exception
}
messages.error(request=self.request, message=error_message)
return {
'template': template_string, 'result': result
}
def get_extra_context(self):
return {
'object': self.external_object,
'title': _('Template sandbox for: %s') % self.external_object
}