Add support for extended templates when there are no results. Add help messages and useful links to several apps when there are no results available.
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -109,6 +109,9 @@
|
||||
- Improve statistics subclassing. Split class module into classes
|
||||
and renderers.
|
||||
- Sort facet link, object, secondady and sidebar actions.
|
||||
- Add support for extended templates when there are no results.
|
||||
- Add help messages and useful links to several apps when there
|
||||
are no results available.
|
||||
|
||||
3.0.3 (2018-08-17)
|
||||
==================
|
||||
|
||||
@@ -6,6 +6,7 @@ import logging
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
@@ -18,6 +19,8 @@ from permissions import PermissionNamespace, Permission
|
||||
from permissions.models import StoredPermission
|
||||
|
||||
from .classes import ModelPermission
|
||||
from .icons import icon_acl_list
|
||||
from .links import link_acl_create
|
||||
from .models import AccessControlList
|
||||
from .permissions import permission_acl_edit, permission_acl_view
|
||||
|
||||
@@ -135,6 +138,19 @@ class ACLListView(SingleObjectListView):
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'hide_object': True,
|
||||
'no_results_icon': icon_acl_list,
|
||||
'no_results_main_link': link_acl_create.resolve(
|
||||
context=RequestContext(
|
||||
self.request, {'resolved_object': self.content_object}
|
||||
)
|
||||
),
|
||||
'no_results_title': _(
|
||||
'There are no ACLs for this object'
|
||||
),
|
||||
'no_results_text': _(
|
||||
'ACL stands for Access Control List and is a precise method '
|
||||
' to control user access to objects in the system.'
|
||||
),
|
||||
'object': self.content_object,
|
||||
'title': _('Access control lists for: %s' % self.content_object),
|
||||
}
|
||||
|
||||
@@ -58,7 +58,11 @@
|
||||
{% include 'appearance/generic_form_instance.html' %}
|
||||
{% empty %}
|
||||
<tr><td class="text-center" colspan=99>
|
||||
{% if form_empty_label %}{{ form_empty_label }}{% else %}{% trans 'No results' %}{% endif %}
|
||||
{% if form_empty_label %}{{ form_empty_label }}{% else %}
|
||||
|
||||
{% include 'appearance/no_results.html' %}
|
||||
|
||||
{% endif %}
|
||||
</td></tr>
|
||||
{% endfor %}
|
||||
|
||||
@@ -72,23 +76,26 @@
|
||||
{% include 'appearance/generic_form_instance.html' %}
|
||||
{% endif %}
|
||||
{% if not read_only %}
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary" name="{% if form.prefix %}{{ form.prefix }}-submit{% else %}submit{% endif %}" type="submit">
|
||||
{% if submit_icon_class %}
|
||||
{{ submit_icon_class.render }}
|
||||
{% elif submit_icon %}
|
||||
<i class="{{ submit_icon }}"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-check"></i>
|
||||
{% if not form.management_form or wizard.management_form or form.forms %}
|
||||
{# Is a normal form, a wizard form, or a formset with at least one form #}
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary" name="{% if form.prefix %}{{ form.prefix }}-submit{% else %}submit{% endif %}" type="submit">
|
||||
{% if submit_icon_class %}
|
||||
{{ submit_icon_class.render }}
|
||||
{% elif submit_icon %}
|
||||
<i class="{{ submit_icon }}"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-check"></i>
|
||||
{% endif %}
|
||||
{% if submit_label %}{{ submit_label }}{% else %}{% if object %}{% trans 'Save' %}{% else %}{% trans 'Submit' %}{% endif %}{% endif %}
|
||||
</button>
|
||||
{% if previous %}
|
||||
<a class="btn btn-default" onclick='history.back();'>
|
||||
<i class="fa fa-times"></i> {% if cancel_label %}{{ cancel_label }}{% else %}{% trans 'Cancel' %}{% endif %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if submit_label %}{{ submit_label }}{% else %}{% if object %}{% trans 'Save' %}{% else %}{% trans 'Submit' %}{% endif %}{% endif %}
|
||||
</button>
|
||||
{% if previous %}
|
||||
<a class="btn btn-default" onclick='history.back();'>
|
||||
<i class="fa fa-times"></i> {% if cancel_label %}{{ cancel_label }}{% else %}{% trans 'Cancel' %}{% endif %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
{% for object_navigation_links in resolved_links %}
|
||||
{% include 'navigation/generic_navigation.html' %}
|
||||
{% empty %}
|
||||
<p class="text-center" colspan=99>{% trans 'No results' %}</p>
|
||||
<p class="text-center" colspan=99>
|
||||
{% include 'appearance/no_results.html' %}
|
||||
</p>
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-xs-12">
|
||||
<p class="text-center">{% trans 'No results' %}</p>
|
||||
{% include 'appearance/no_results.html' %}
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
@@ -108,7 +108,11 @@
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td class="text-center" colspan=99>{% trans 'No results' %}</td></tr>
|
||||
<tr>
|
||||
<td class="text-center" colspan=99>
|
||||
{% include 'appearance/no_results.html' %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
38
mayan/apps/appearance/templates/appearance/no_results.html
Normal file
38
mayan/apps/appearance/templates/appearance/no_results.html
Normal file
@@ -0,0 +1,38 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div class="text-center">
|
||||
<div style="font-size: 150%;">
|
||||
{% if no_results_icon %}
|
||||
{{ no_results_icon.render }}
|
||||
{% else %}
|
||||
<i class="fa fa-times"></i>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% trans 'No results' as default_title %}
|
||||
<h4>{{ no_results_title|default:default_title }}</h4>
|
||||
{% if no_results_text %}
|
||||
<p class="small">{{ no_results_text }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if no_results_main_link %}
|
||||
<div>
|
||||
{% with no_results_main_link as link %}
|
||||
{% with 'btn btn-primary btn-sm' as link_classes %}
|
||||
{% include 'navigation/generic_subnavigation.html' %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if no_results_secondary_links %}
|
||||
<div>
|
||||
{% for link in no_results_secondary_links %}
|
||||
{% with 'btn btn-default btn-sm' as link_classes %}
|
||||
{% include 'navigation/generic_subnavigation.html' %}
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -2,5 +2,6 @@ from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from appearance.classes import Icon
|
||||
|
||||
icon_cabinet = Icon(driver_name='fontawesome', symbol='columns')
|
||||
icon_cabinet_create = Icon(driver_name='fontawesome', symbol='plus')
|
||||
icon_cabinet_list = Icon(driver_name='fontawesome', symbol='columns')
|
||||
|
||||
@@ -4,6 +4,7 @@ import logging
|
||||
|
||||
from django.contrib import messages
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _, ungettext
|
||||
|
||||
@@ -17,6 +18,10 @@ from documents.models import Document
|
||||
from documents.views import DocumentListView
|
||||
|
||||
from .forms import CabinetListForm
|
||||
from .icons import icon_cabinet
|
||||
from .links import (
|
||||
link_cabinet_add_document, link_cabinet_child_add, link_cabinet_create
|
||||
)
|
||||
from .models import Cabinet
|
||||
from .permissions import (
|
||||
permission_cabinet_add_document, permission_cabinet_create,
|
||||
@@ -108,6 +113,18 @@ class CabinetDetailView(DocumentListView):
|
||||
jstree_data(node=cabinet.get_root(), selected_node=cabinet)
|
||||
),
|
||||
'list_as_items': True,
|
||||
'no_results_icon': icon_cabinet,
|
||||
'no_results_main_link': link_cabinet_child_add.resolve(
|
||||
context=RequestContext(
|
||||
request=self.request, dict_={'object': cabinet}
|
||||
)
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Cabinets level can contain documents or other '
|
||||
'cabinet sub levels. Documents can be added from '
|
||||
'the document\'s cabinet section.'
|
||||
),
|
||||
'no_results_title': _('This cabinet level is empty'),
|
||||
'object': cabinet,
|
||||
'title': _('Details of cabinet: %s') % cabinet.get_full_path(),
|
||||
}
|
||||
@@ -151,6 +168,16 @@ class CabinetListView(SingleObjectListView):
|
||||
return {
|
||||
'hide_link': True,
|
||||
'title': _('Cabinets'),
|
||||
'no_results_icon': icon_cabinet,
|
||||
'no_results_main_link': link_cabinet_create.resolve(
|
||||
context=RequestContext(request=self.request)
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Cabinets are a multi-level method to organize '
|
||||
'documents. Each cabinet can contain documents as '
|
||||
'well as other sub level cabinets.'
|
||||
),
|
||||
'no_results_title': _('No cabinets available'),
|
||||
}
|
||||
|
||||
def get_object_list(self):
|
||||
@@ -175,6 +202,18 @@ class DocumentCabinetListView(CabinetListView):
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'hide_link': True,
|
||||
'no_results_icon': icon_cabinet,
|
||||
'no_results_main_link': link_cabinet_add_document.resolve(
|
||||
context=RequestContext(
|
||||
request=self.request, dict_={'object': self.document}
|
||||
)
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Documents can be added to many cabinets.'
|
||||
),
|
||||
'no_results_title': _(
|
||||
'This document is not in any cabinet'
|
||||
),
|
||||
'object': self.document,
|
||||
'title': _('Cabinets containing document: %s') % self.document,
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ from common.utils import encapsulate
|
||||
|
||||
from .exceptions import DocumentAlreadyCheckedOut, DocumentNotCheckedOut
|
||||
from .forms import DocumentCheckoutForm, DocumentCheckoutDefailForm
|
||||
from .icons import icon_checkout_info
|
||||
from .models import DocumentCheckout
|
||||
from .permissions import (
|
||||
permission_document_checkin, permission_document_checkin_override,
|
||||
@@ -103,6 +104,13 @@ class CheckoutListView(DocumentListView):
|
||||
)
|
||||
},
|
||||
),
|
||||
'no_results_icon': icon_checkout_info,
|
||||
'no_results_text': _(
|
||||
'Checking out a document blocks certain document '
|
||||
'operations for a predetermined amount of '
|
||||
'time.'
|
||||
),
|
||||
'no_results_title': _('No documents have been checked out'),
|
||||
}
|
||||
)
|
||||
return context
|
||||
|
||||
@@ -29,6 +29,7 @@ from .generics import ( # NOQA
|
||||
SingleObjectDynamicFormEditView, SingleObjectDownloadView,
|
||||
SingleObjectEditView, SingleObjectListView, SimpleView
|
||||
)
|
||||
from .icons import icon_setup
|
||||
from .menus import menu_tools, menu_setup
|
||||
from .permissions_runtime import permission_error_log_view
|
||||
from .utils import check_version
|
||||
@@ -253,10 +254,18 @@ class SetupListView(TemplateView):
|
||||
data = super(SetupListView, self).get_context_data(**kwargs)
|
||||
context = RequestContext(self.request)
|
||||
context['request'] = self.request
|
||||
data.update({
|
||||
'resolved_links': menu_setup.resolve(context=context),
|
||||
'title': _('Setup items'),
|
||||
})
|
||||
data.update(
|
||||
{
|
||||
'no_results_icon': icon_setup,
|
||||
'no_results_label': _('No setup options available.'),
|
||||
'no_results_text': _(
|
||||
'No results here means that don\'t have the required '
|
||||
'permissions to perform administrative task.'
|
||||
),
|
||||
'resolved_links': menu_setup.resolve(context=context),
|
||||
'title': _('Setup items'),
|
||||
}
|
||||
)
|
||||
return data
|
||||
|
||||
|
||||
|
||||
5
mayan/apps/converter/icons.py
Normal file
5
mayan/apps/converter/icons.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from appearance.classes import Icon
|
||||
|
||||
icon_transformation = Icon(driver_name='fontawesome', symbol='crop')
|
||||
@@ -5,6 +5,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from navigation import Link
|
||||
|
||||
from .icons import icon_transformation
|
||||
from .permissions import (
|
||||
permission_transformation_create, permission_transformation_delete,
|
||||
permission_transformation_edit, permission_transformation_view
|
||||
@@ -43,6 +44,7 @@ link_transformation_edit = Link(
|
||||
text=_('Edit'), view='converter:transformation_edit'
|
||||
)
|
||||
link_transformation_list = Link(
|
||||
icon_class=icon_transformation,
|
||||
kwargs=get_kwargs_factory('resolved_object'),
|
||||
permissions=(permission_transformation_view,), text=_('Transformations'),
|
||||
view='converter:transformation_list'
|
||||
|
||||
@@ -5,6 +5,7 @@ import logging
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
@@ -14,6 +15,8 @@ from common.views import (
|
||||
SingleObjectListView
|
||||
)
|
||||
|
||||
from .icons import icon_transformation
|
||||
from .links import link_transformation_create
|
||||
from .models import Transformation
|
||||
from .permissions import (
|
||||
permission_transformation_create, permission_transformation_delete,
|
||||
@@ -210,6 +213,18 @@ class TransformationListView(SingleObjectListView):
|
||||
'hide_link': True,
|
||||
'hide_object': True,
|
||||
'navigation_object_list': ('content_object',),
|
||||
'no_results_icon': icon_transformation,
|
||||
'no_results_main_link': link_transformation_create.resolve(
|
||||
context=RequestContext(
|
||||
self.request, {'content_object': self.content_object,}
|
||||
)
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Transformations allow changing the visual appearance '
|
||||
'of documents without making permanent changes to the '
|
||||
'document file themselves.'
|
||||
),
|
||||
'no_results_title': _('No transformations'),
|
||||
'title': _('Transformations for: %s') % self.content_object,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
@@ -10,6 +11,8 @@ from common.generics import (
|
||||
)
|
||||
from documents.models import Document
|
||||
|
||||
from .icons import icon_comments_for_document
|
||||
from .links import link_comment_add
|
||||
from .models import Comment
|
||||
from .permissions import (
|
||||
permission_comment_create, permission_comment_delete,
|
||||
@@ -93,6 +96,15 @@ class DocumentCommentListView(SingleObjectListView):
|
||||
return {
|
||||
'hide_link': True,
|
||||
'hide_object': True,
|
||||
'no_results_icon': icon_comments_for_document,
|
||||
'no_results_text': _(
|
||||
'Document comments are timestamped text entries from users. '
|
||||
'They are great for collaboration.'
|
||||
),
|
||||
'no_results_main_link': link_comment_add.resolve(
|
||||
RequestContext(self.request, {'object': self.get_document()})
|
||||
),
|
||||
'no_results_title': _('There are no comments'),
|
||||
'object': self.get_document(),
|
||||
'title': _('Comments for document: %s') % self.get_document(),
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ from django.contrib import messages
|
||||
from django.core.files import File
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
@@ -24,6 +25,12 @@ from .forms import (
|
||||
DocumentVersionSignatureCreateForm,
|
||||
DocumentVersionSignatureDetailForm
|
||||
)
|
||||
from .icons import icon_document_signature_list
|
||||
from .links import (
|
||||
link_document_version_signature_detached_create,
|
||||
link_document_version_signature_embedded_create,
|
||||
link_document_version_signature_upload
|
||||
)
|
||||
from .models import DetachedSignature, SignatureBaseModel
|
||||
from .permissions import (
|
||||
permission_document_version_sign_detached,
|
||||
@@ -294,6 +301,31 @@ class DocumentVersionSignatureListView(SingleObjectListView):
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'hide_object': True,
|
||||
'no_results_icon': icon_document_signature_list,
|
||||
'no_results_text': _(
|
||||
'Signatures help provide authorship evidence and tamper '
|
||||
'detection. They are very secure and hard to '
|
||||
'forge. A signature can be embedded as part of the document '
|
||||
'itself or uploaded as a separate file.'
|
||||
),
|
||||
'no_results_secondary_links': [
|
||||
link_document_version_signature_detached_create.resolve(
|
||||
RequestContext(
|
||||
self.request, {'object': self.get_document_version()}
|
||||
)
|
||||
),
|
||||
link_document_version_signature_embedded_create.resolve(
|
||||
RequestContext(
|
||||
self.request, {'object': self.get_document_version()}
|
||||
)
|
||||
),
|
||||
link_document_version_signature_upload.resolve(
|
||||
RequestContext(
|
||||
self.request, {'object': self.get_document_version()}
|
||||
)
|
||||
),
|
||||
],
|
||||
'no_results_title': _('There are no signatures for this document.'),
|
||||
'object': self.get_document_version(),
|
||||
'title': _(
|
||||
'Signatures for document version: %s'
|
||||
|
||||
@@ -12,3 +12,12 @@ icon_tool_launch_all_workflows = Icon(
|
||||
icon_workflow_list = Icon(
|
||||
driver_name='fontawesome', symbol='sitemap'
|
||||
)
|
||||
icon_workflow_state = Icon(
|
||||
driver_name='fontawesome', symbol='circle'
|
||||
)
|
||||
icon_workflow_state_action = Icon(
|
||||
driver_name='fontawesome', symbol='code'
|
||||
)
|
||||
icon_workflow_transition = Icon(
|
||||
driver_name='fontawesome', symbol='arrows-alt-h'
|
||||
)
|
||||
|
||||
@@ -6,7 +6,8 @@ from navigation import Link
|
||||
|
||||
from .icons import (
|
||||
icon_document_workflow_instance_list, icon_setup_workflow_list,
|
||||
icon_tool_launch_all_workflows, icon_workflow_list
|
||||
icon_tool_launch_all_workflows, icon_workflow_list,
|
||||
icon_workflow_state, icon_workflow_state_action, icon_workflow_transition
|
||||
)
|
||||
from .permissions import (
|
||||
permission_workflow_create, permission_workflow_delete,
|
||||
@@ -20,8 +21,8 @@ link_document_workflow_instance_list = Link(
|
||||
view='document_states:document_workflow_instance_list',
|
||||
)
|
||||
link_setup_workflow_create = Link(
|
||||
permissions=(permission_workflow_create,), text=_('Create workflow'),
|
||||
view='document_states:setup_workflow_create'
|
||||
icon_class=icon_workflow_list, permissions=(permission_workflow_create,),
|
||||
text=_('Create workflow'), view='document_states:setup_workflow_create'
|
||||
)
|
||||
link_setup_workflow_delete = Link(
|
||||
args='resolved_object.pk', permissions=(permission_workflow_delete,),
|
||||
@@ -57,13 +58,13 @@ link_setup_workflow_state_action_list = Link(
|
||||
view='document_states:setup_workflow_state_action_list',
|
||||
)
|
||||
link_setup_workflow_state_action_selection = Link(
|
||||
args='resolved_object.pk', permissions=(permission_workflow_edit,),
|
||||
text=_('Create action'),
|
||||
args='resolved_object.pk', icon_class=icon_workflow_state_action,
|
||||
permissions=(permission_workflow_edit,), text=_('Create action'),
|
||||
view='document_states:setup_workflow_state_action_selection',
|
||||
)
|
||||
link_setup_workflow_state_create = Link(
|
||||
args='resolved_object.pk', permissions=(permission_workflow_edit,),
|
||||
text=_('Create state'),
|
||||
args='resolved_object.pk', icon_class=icon_workflow_state,
|
||||
permissions=(permission_workflow_edit,), text=_('Create state'),
|
||||
view='document_states:setup_workflow_state_create',
|
||||
)
|
||||
link_setup_workflow_state_delete = Link(
|
||||
@@ -76,12 +77,13 @@ link_setup_workflow_state_edit = Link(
|
||||
text=_('Edit'), view='document_states:setup_workflow_state_edit',
|
||||
)
|
||||
link_setup_workflow_states = Link(
|
||||
args='resolved_object.pk', permissions=(permission_workflow_view,),
|
||||
text=_('States'), view='document_states:setup_workflow_state_list',
|
||||
args='resolved_object.pk', icon_class=icon_workflow_state,
|
||||
permissions=(permission_workflow_view,), text=_('States'),
|
||||
view='document_states:setup_workflow_state_list',
|
||||
)
|
||||
link_setup_workflow_transition_create = Link(
|
||||
args='resolved_object.pk', permissions=(permission_workflow_edit,),
|
||||
text=_('Create transition'),
|
||||
args='resolved_object.pk', icon_class=icon_workflow_transition,
|
||||
permissions=(permission_workflow_edit,), text=_('Create transition'),
|
||||
view='document_states:setup_workflow_transition_create',
|
||||
)
|
||||
link_setup_workflow_transition_delete = Link(
|
||||
@@ -94,8 +96,8 @@ link_setup_workflow_transition_edit = Link(
|
||||
text=_('Edit'), view='document_states:setup_workflow_transition_edit',
|
||||
)
|
||||
link_setup_workflow_transitions = Link(
|
||||
args='resolved_object.pk', permissions=(permission_workflow_view,),
|
||||
text=_('Transitions'),
|
||||
args='resolved_object.pk', icon_class=icon_workflow_transition,
|
||||
permissions=(permission_workflow_view,), text=_('Transitions'),
|
||||
view='document_states:setup_workflow_transition_list',
|
||||
)
|
||||
link_tool_launch_all_workflows = Link(
|
||||
|
||||
@@ -6,6 +6,7 @@ from django.db import transaction
|
||||
from django.db.utils import IntegrityError
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
@@ -27,6 +28,15 @@ from .forms import (
|
||||
WorkflowPreviewForm, WorkflowStateActionDynamicForm, WorkflowStateForm,
|
||||
WorkflowTransitionForm, WorkflowTransitionTriggerEventRelationshipFormSet
|
||||
)
|
||||
from .icons import (
|
||||
icon_workflow_list, icon_workflow_state, icon_workflow_state_action,
|
||||
icon_workflow_transition
|
||||
)
|
||||
from .links import (
|
||||
link_setup_workflow_create, link_setup_workflow_state_create,
|
||||
link_setup_workflow_state_action_selection,
|
||||
link_setup_workflow_transition_create
|
||||
)
|
||||
from .models import (
|
||||
Workflow, WorkflowInstance, WorkflowState, WorkflowStateAction,
|
||||
WorkflowTransition, WorkflowRuntimeProxy, WorkflowStateRuntimeProxy,
|
||||
@@ -138,13 +148,27 @@ class WorkflowInstanceTransitionView(FormView):
|
||||
# Setup
|
||||
|
||||
class SetupWorkflowListView(SingleObjectListView):
|
||||
extra_context = {
|
||||
'title': _('Workflows'),
|
||||
'hide_object': True,
|
||||
}
|
||||
model = Workflow
|
||||
object_permission = permission_workflow_view
|
||||
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'hide_object': True,
|
||||
'no_results_icon': icon_workflow_list,
|
||||
'no_results_main_link': link_setup_workflow_create.resolve(
|
||||
context=RequestContext(request=self.request)
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Workflows store a series for states and keep track of the '
|
||||
'current state of a document. Transitions are used to change the '
|
||||
'current state to a new one.'
|
||||
),
|
||||
'no_results_title': _(
|
||||
'No workflows have been defined.'
|
||||
),
|
||||
'title': _('Workflows'),
|
||||
}
|
||||
|
||||
|
||||
class SetupWorkflowCreateView(SingleObjectCreateView):
|
||||
form_class = WorkflowForm
|
||||
@@ -324,6 +348,21 @@ class SetupWorkflowStateActionListView(SingleObjectListView):
|
||||
return {
|
||||
'hide_object': True,
|
||||
'navigation_object_list': ('object', 'workflow'),
|
||||
'no_results_icon': icon_workflow_state_action,
|
||||
'no_results_main_link': link_setup_workflow_state_action_selection.resolve(
|
||||
context=RequestContext(
|
||||
request=self.request, dict_={
|
||||
'object': self.get_workflow_state()
|
||||
}
|
||||
)
|
||||
),
|
||||
'no_results_title': _(
|
||||
'There are no actions for this workflow state.'
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Workflow state actions are macros that get executed when '
|
||||
'enters or leaves the state in which they reside.'
|
||||
),
|
||||
'object': self.get_workflow_state(),
|
||||
'title': _(
|
||||
'Actions for workflow state: %s'
|
||||
@@ -469,6 +508,18 @@ class SetupWorkflowStateListView(SingleObjectListView):
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'hide_link': True,
|
||||
'no_results_icon': icon_workflow_state,
|
||||
'no_results_main_link': link_setup_workflow_state_create.resolve(
|
||||
context=RequestContext(
|
||||
self.request, {'object': self.get_workflow()}
|
||||
)
|
||||
),
|
||||
'no_results_title': _(
|
||||
'This workflow doesn\'t have any states'
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Create states and link them using transitions.'
|
||||
),
|
||||
'object': self.get_workflow(),
|
||||
'title': _('States of workflow: %s') % self.get_workflow()
|
||||
}
|
||||
@@ -584,6 +635,19 @@ class SetupWorkflowTransitionListView(SingleObjectListView):
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'hide_link': True,
|
||||
'no_results_icon': icon_workflow_transition,
|
||||
'no_results_main_link': link_setup_workflow_transition_create.resolve(
|
||||
context=RequestContext(
|
||||
self.request, {'object': self.get_workflow()}
|
||||
)
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Create a transition and use it to move a workflow from '
|
||||
' one state to another.'
|
||||
),
|
||||
'no_results_title': _(
|
||||
'This workflow doesn\'t have any transitions'
|
||||
),
|
||||
'object': self.get_workflow(),
|
||||
'title': _(
|
||||
'Transitions of workflow: %s'
|
||||
@@ -606,7 +670,18 @@ class WorkflowListView(SingleObjectListView):
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'hide_object': True,
|
||||
'title': _('Workflows')
|
||||
'no_results_main_link': link_setup_workflow_create.resolve(
|
||||
context=RequestContext(
|
||||
self.request, {}
|
||||
)
|
||||
),
|
||||
'no_results_title': _('There are no workflows'),
|
||||
'no_results_text': _(
|
||||
'Create some workflows and associated them with a document '
|
||||
'type. Active workflows will be shown here and the documents '
|
||||
'for which they are executing.'
|
||||
),
|
||||
'title': _('Workflows'),
|
||||
}
|
||||
|
||||
def get_object_list(self):
|
||||
@@ -635,6 +710,13 @@ class WorkflowDocumentListView(DocumentListView):
|
||||
context = super(WorkflowDocumentListView, self).get_extra_context()
|
||||
context.update(
|
||||
{
|
||||
'no_results_title': _(
|
||||
'There are documents executing this workflow'
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Associate a workflow with some document types and '
|
||||
'documents of those types will be listed in this view.'
|
||||
),
|
||||
'object': self.workflow,
|
||||
'title': _('Documents with the workflow: %s') % self.workflow
|
||||
}
|
||||
@@ -653,14 +735,17 @@ class WorkflowStateDocumentListView(DocumentListView):
|
||||
{
|
||||
'object': workflow_state,
|
||||
'navigation_object_list': ('object', 'workflow'),
|
||||
'workflow': WorkflowRuntimeProxy.objects.get(
|
||||
pk=workflow_state.workflow.pk
|
||||
'no_results_title': _(
|
||||
'There are documents in this workflow state'
|
||||
),
|
||||
'title': _(
|
||||
'Documents in the workflow "%s", state "%s"'
|
||||
) % (
|
||||
workflow_state.workflow, workflow_state
|
||||
)
|
||||
),
|
||||
'workflow': WorkflowRuntimeProxy.objects.get(
|
||||
pk=workflow_state.workflow.pk
|
||||
),
|
||||
}
|
||||
)
|
||||
return context
|
||||
@@ -693,6 +778,17 @@ class WorkflowStateListView(SingleObjectListView):
|
||||
return {
|
||||
'hide_columns': True,
|
||||
'hide_link': True,
|
||||
'no_results_main_link': link_setup_workflow_state_create.resolve(
|
||||
context=RequestContext(
|
||||
self.request, {'object': self.get_workflow()}
|
||||
)
|
||||
),
|
||||
'no_results_title': _(
|
||||
'This workflow doesn\'t have any state.'
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Create states and link them using transitions.'
|
||||
),
|
||||
'object': self.get_workflow(),
|
||||
'title': _('States of workflow: %s') % self.get_workflow()
|
||||
}
|
||||
@@ -751,6 +847,10 @@ class SetupWorkflowTransitionTriggerEventListView(FormView):
|
||||
'form_display_mode_table': True,
|
||||
'navigation_object_list': ('object', 'workflow'),
|
||||
'object': self.get_object(),
|
||||
'subtitle': _(
|
||||
'Triggers are events that cause this transition to execute '
|
||||
'automatically.'
|
||||
),
|
||||
'title': _(
|
||||
'Workflow transition trigger events for: %s'
|
||||
) % self.get_object(),
|
||||
|
||||
@@ -5,6 +5,7 @@ from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
@@ -19,6 +20,8 @@ from .classes import EventType, ModelEventType
|
||||
from .forms import (
|
||||
EventTypeUserRelationshipFormSet, ObjectEventTypeUserRelationshipFormSet
|
||||
)
|
||||
from .icons import icon_user_notifications_list
|
||||
from .links import link_event_types_subscriptions_list
|
||||
from .models import StoredEventType
|
||||
from .permissions import permission_events_view
|
||||
from .widgets import event_object_link
|
||||
@@ -109,6 +112,17 @@ class NotificationListView(SingleObjectListView):
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'hide_object': True,
|
||||
'no_results_icon': icon_user_notifications_list,
|
||||
'no_results_main_link': link_event_types_subscriptions_list.resolve(
|
||||
context=RequestContext(
|
||||
self.request, {}
|
||||
)
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Subscribe to global or object events to receive '
|
||||
'notifications.'
|
||||
),
|
||||
'no_results_title': _('There are no notifications'),
|
||||
'object': self.request.user,
|
||||
'title': _('Notifications'),
|
||||
}
|
||||
|
||||
@@ -11,4 +11,5 @@ icon_document_metadata_edit_submit = Icon(
|
||||
icon_document_metadata_remove_submit = Icon(
|
||||
driver_name='fontawesome', symbol='minus'
|
||||
)
|
||||
icon_metadata = Icon(driver_name='fontawesome', symbol='pencil-alt')
|
||||
icon_metadata_view = Icon(driver_name='fontawesome', symbol='pencil-alt')
|
||||
|
||||
@@ -5,6 +5,7 @@ from django.contrib import messages
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.http import urlencode
|
||||
@@ -28,7 +29,11 @@ from .forms import (
|
||||
)
|
||||
from .icons import (
|
||||
icon_document_metadata_add_submit, icon_document_metadata_edit_submit,
|
||||
icon_document_metadata_remove_submit
|
||||
icon_document_metadata_remove_submit, icon_metadata
|
||||
)
|
||||
from .links import (
|
||||
link_metadata_add, link_metadata_multiple_add,
|
||||
link_setup_metadata_type_create
|
||||
)
|
||||
from .models import DocumentMetadata, MetadataType
|
||||
from .permissions import (
|
||||
@@ -262,8 +267,29 @@ class DocumentMetadataEditView(MultipleObjectFormActionView):
|
||||
def get_extra_context(self):
|
||||
queryset = self.get_queryset()
|
||||
|
||||
if queryset.count() == 1:
|
||||
no_results_main_link = link_metadata_add.resolve(
|
||||
context=RequestContext(
|
||||
request=self.request, dict_={'object': queryset.first()}
|
||||
)
|
||||
)
|
||||
else:
|
||||
no_results_main_link = link_metadata_multiple_add.resolve(
|
||||
context=RequestContext(request=self.request)
|
||||
)
|
||||
no_results_main_link.url = '{}?id_list={}'.format(
|
||||
no_results_main_link.url, id_list
|
||||
)
|
||||
|
||||
result = {
|
||||
'form_display_mode_table': True,
|
||||
'no_results_icon': icon_metadata,
|
||||
'no_results_main_link': no_results_main_link,
|
||||
'no_results_text': _(
|
||||
'Add metadata types available for this document\'s type '
|
||||
'and assign them corresponding values.'
|
||||
),
|
||||
'no_results_title': _('There is no metadata to edit'),
|
||||
'submit_icon_class': icon_document_metadata_edit_submit,
|
||||
'submit_label': _('Edit'),
|
||||
'title': ungettext(
|
||||
@@ -371,9 +397,23 @@ class DocumentMetadataListView(SingleObjectListView):
|
||||
return {
|
||||
'hide_link': True,
|
||||
'object': document,
|
||||
'no_results_icon': icon_metadata,
|
||||
'no_results_main_link': link_metadata_add.resolve(
|
||||
context=RequestContext(
|
||||
request=self.request, dict_={'object': document}
|
||||
)
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Add metadata types this document\'s type '
|
||||
'to be able to add them to individual documents. '
|
||||
'Once added to individual document, you can then edit their '
|
||||
'values.'
|
||||
),
|
||||
'no_results_title': _('This document doesn\'t have any metadata'),
|
||||
'title': _('Metadata for document: %s') % document,
|
||||
}
|
||||
|
||||
|
||||
def get_object_list(self):
|
||||
return self.get_document().metadata.all()
|
||||
|
||||
@@ -579,6 +619,19 @@ class MetadataTypeListView(SingleObjectListView):
|
||||
},
|
||||
),
|
||||
'hide_link': True,
|
||||
'no_results_icon': icon_metadata,
|
||||
'no_results_main_link': link_setup_metadata_type_create.resolve(
|
||||
context=RequestContext(request=self.request)
|
||||
),
|
||||
'no_results_text': _(
|
||||
'Metadata types are users defined properties that can be '
|
||||
'assigned values. Once created they must be associated to '
|
||||
'document types, either as optional or required, for each. '
|
||||
'Setting a metadata type as required for a document type '
|
||||
'will block the upload of documents of that type until a '
|
||||
'metadata value is provided.'
|
||||
),
|
||||
'no_results_title': _('There are no metadata types'),
|
||||
'title': _('Metadata types'),
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import logging
|
||||
|
||||
from django.contrib import messages
|
||||
from django.shortcuts import get_object_or_404, reverse
|
||||
from django.template import RequestContext
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _, ungettext
|
||||
|
||||
@@ -17,7 +18,10 @@ from documents.views import DocumentListView
|
||||
from documents.permissions import permission_document_view
|
||||
|
||||
from .forms import TagMultipleSelectionForm
|
||||
from .icons import icon_tag_delete_submit, icon_tag_remove_submit
|
||||
from .icons import (
|
||||
icon_menu_tags, icon_tag_delete_submit, icon_tag_remove_submit
|
||||
)
|
||||
from .links import link_tag_attach, link_tag_create
|
||||
from .models import Tag
|
||||
from .permissions import (
|
||||
permission_tag_attach, permission_tag_create, permission_tag_delete,
|
||||
@@ -190,6 +194,17 @@ class TagListView(SingleObjectListView):
|
||||
return {
|
||||
'hide_link': True,
|
||||
'hide_object': True,
|
||||
'no_results_icon': icon_menu_tags,
|
||||
'no_results_text': _(
|
||||
'Tags are color coded properties that can be attached or '
|
||||
'removed from documents.'
|
||||
),
|
||||
'no_results_title': _('No tags available'),
|
||||
'no_results_main_link': link_tag_create.resolve(
|
||||
context=RequestContext(
|
||||
self.request, {}
|
||||
)
|
||||
),
|
||||
'title': _('Tags'),
|
||||
}
|
||||
|
||||
@@ -237,6 +252,12 @@ class DocumentTagListView(TagListView):
|
||||
context.update(
|
||||
{
|
||||
'hide_link': True,
|
||||
'no_results_title': _('Document has no tags attached'),
|
||||
'no_results_main_link': link_tag_attach.resolve(
|
||||
context=RequestContext(
|
||||
self.request, {'object': self.document}
|
||||
)
|
||||
),
|
||||
'object': self.document,
|
||||
'title': _('Tags for document: %s') % self.document,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user