diff --git a/mayan/apps/document_indexing/views.py b/mayan/apps/document_indexing/views.py index a5ef1f76ef..0e577eb607 100644 --- a/mayan/apps/document_indexing/views.py +++ b/mayan/apps/document_indexing/views.py @@ -109,7 +109,12 @@ class SetupIndexDocumentTypesView(AssignRemoveView): 'object': self.get_object(), 'title': _( 'Document types linked to index: %s' - ) % self.get_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.' + ), } def get_object(self): @@ -339,6 +344,15 @@ class DocumentIndexNodeListView(SingleObjectListView): 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' diff --git a/mayan/apps/document_states/views.py b/mayan/apps/document_states/views.py index 045747bd5c..e09f717e13 100644 --- a/mayan/apps/document_states/views.py +++ b/mayan/apps/document_states/views.py @@ -66,6 +66,14 @@ class DocumentWorkflowInstanceListView(SingleObjectListView): def get_extra_context(self): return { 'hide_link': True, + 'no_results_icon': icon_workflow_list, + 'no_results_text': _( + 'Assign workflows to the document type of this document ' + 'to have this document execute those workflows. ' + ), + 'no_results_title': _( + 'There are no workflow for this document' + ), 'object': self.get_document(), 'title': _( 'Workflows for document: %s' @@ -164,7 +172,7 @@ class SetupWorkflowListView(SingleObjectListView): 'current state to a new one.' ), 'no_results_title': _( - 'No workflows have been defined.' + 'No workflows have been defined' ), 'title': _('Workflows'), } @@ -356,13 +364,13 @@ class SetupWorkflowStateActionListView(SingleObjectListView): } ) ), - '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.' ), + 'no_results_title': _( + 'There are no actions for this workflow state' + ), 'object': self.get_workflow_state(), 'title': _( 'Actions for workflow state: %s' @@ -710,13 +718,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.' ), + 'no_results_title': _( + 'There are no documents executing this workflow' + ), 'object': self.workflow, 'title': _('Documents with the workflow: %s') % self.workflow } @@ -783,12 +791,12 @@ class WorkflowStateListView(SingleObjectListView): 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.' ), + 'no_results_title': _( + 'This workflow doesn\'t have any state' + ), 'object': self.get_workflow(), 'title': _('States of workflow: %s') % self.get_workflow() } diff --git a/mayan/apps/documents/views/document_views.py b/mayan/apps/documents/views/document_views.py index 26b152ccc4..884ff11361 100644 --- a/mayan/apps/documents/views/document_views.py +++ b/mayan/apps/documents/views/document_views.py @@ -34,6 +34,7 @@ from ..forms import ( ) from ..icons import ( icon_document_list_deleted, icon_document_list_favorites, + icon_document_list_recent_access, icon_document_list_recent_added, icon_duplicated_document_list ) from ..literals import PAGE_RANGE_RANGE, DEFAULT_ZIP_FILENAME @@ -223,11 +224,8 @@ class DocumentDuplicatesListView(DocumentListView): { 'no_results_icon': icon_duplicated_document_list, 'no_results_text': _( - 'Duplicates are documents that are composed of the exact ' - 'same file, down to the last byte. Files that have the ' - 'same text or OCR but are not identical or were saved ' - 'using a different file format will not appear as ' - 'duplicates.' + 'Only exact copies of this document will be shown in the ' + 'this list.' ), 'no_results_title': _( 'There are no duplicates for this document' @@ -835,6 +833,17 @@ class DuplicatedDocumentListView(DocumentListView): ) }, ), + 'no_results_icon': icon_duplicated_document_list, + 'no_results_text': _( + 'Duplicates are documents that are composed of the exact ' + 'same file, down to the last byte. Files that have the ' + 'same text or OCR but are not identical or were saved ' + 'using a different file format will not appear as ' + 'duplicates.' + ), + 'no_results_title': _( + 'There are no duplicated documents' + ), 'title': _('Duplicated documents') } ) @@ -931,6 +940,14 @@ class RecentAccessDocumentListView(DocumentListView): context = super(RecentAccessDocumentListView, self).get_extra_context() context.update( { + 'no_results_icon': icon_document_list_recent_access, + 'no_results_text': _( + 'This view will list the latest documents viewed or ' + 'manipulated in any way by this user account.' + ), + 'no_results_title': _( + 'There are no recently accessed document' + ), 'title': _('Recently accessed'), } ) @@ -947,6 +964,14 @@ class RecentAddedDocumentListView(DocumentListView): context = super(RecentAddedDocumentListView, self).get_extra_context() context.update( { + 'no_results_icon': icon_document_list_recent_added, + 'no_results_text': _( + 'This view will list the latest documents uploaded ' + 'in the system.' + ), + 'no_results_title': _( + 'There are no recently added document' + ), 'title': _('Recently added'), } ) diff --git a/mayan/apps/linking/icons.py b/mayan/apps/linking/icons.py index 8813b94b0a..38722fe6b3 100644 --- a/mayan/apps/linking/icons.py +++ b/mayan/apps/linking/icons.py @@ -2,6 +2,11 @@ from __future__ import absolute_import, unicode_literals from appearance.classes import Icon +icon_smart_link_condition_create = Icon( + driver_name='fontawesome', symbol='plus' +) +icon_smart_link_condition = Icon(driver_name='fontawesome', symbol='code') +icon_smart_link_create = Icon(driver_name='fontawesome', symbol='plus') icon_smart_link_instances_for_document = Icon( driver_name='fontawesome', symbol='link' ) diff --git a/mayan/apps/linking/links.py b/mayan/apps/linking/links.py index 54660027fc..c98fcc9c92 100644 --- a/mayan/apps/linking/links.py +++ b/mayan/apps/linking/links.py @@ -6,6 +6,7 @@ from documents.permissions import permission_document_view from navigation import Link from .icons import ( + icon_smart_link_condition_create, icon_smart_link_create, icon_smart_link_instances_for_document, icon_smart_link_setup ) from .permissions import ( @@ -14,8 +15,9 @@ from .permissions import ( ) link_smart_link_condition_create = Link( - args='object.pk', permissions=(permission_smart_link_edit,), - text=_('Create condition'), view='linking:smart_link_condition_create', + args='object.pk', icon_class=icon_smart_link_condition_create, + permissions=(permission_smart_link_edit,), text=_('Create condition'), + view='linking:smart_link_condition_create', ) link_smart_link_condition_delete = Link( args='resolved_object.pk', permissions=(permission_smart_link_edit,), @@ -31,6 +33,7 @@ link_smart_link_condition_list = Link( text=_('Conditions'), view='linking:smart_link_condition_list', ) link_smart_link_create = Link( + icon_class=icon_smart_link_create, permissions=(permission_smart_link_create,), text=_('Create new smart link'), view='linking:smart_link_create' ) diff --git a/mayan/apps/linking/views.py b/mayan/apps/linking/views.py index 8203fb3fde..11bf4feb73 100644 --- a/mayan/apps/linking/views.py +++ b/mayan/apps/linking/views.py @@ -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, reverse_lazy from django.utils.translation import ugettext_lazy as _ @@ -17,6 +18,8 @@ from documents.permissions import permission_document_view from documents.views import DocumentListView from .forms import SmartLinkConditionForm, SmartLinkForm +from .icons import icon_smart_link_setup, icon_smart_link_condition +from .links import link_smart_link_create, link_smart_link_condition_create from .models import ResolvedSmartLink, SmartLink, SmartLinkCondition from .permissions import ( permission_smart_link_create, permission_smart_link_delete, @@ -129,6 +132,20 @@ class SmartLinkListView(SingleObjectListView): def get_extra_context(self): return { 'hide_link': True, + 'no_results_icon': icon_smart_link_setup, + 'no_results_main_link': link_smart_link_create.resolve( + context=RequestContext(request=self.request) + ), + 'no_results_text': _( + 'Indexes group documents into units, usually with similar ' + 'properties and of equal or similar types. Smart links ' + 'allow defining relationships between documents even ' + 'if they are in different indexes and are of different ' + 'types.' + ), + 'no_results_title': _( + 'There are no smart links' + ), 'title': _('Smart links'), } @@ -157,6 +174,15 @@ class DocumentSmartLinkListView(SmartLinkListView): 'document': self.document, 'hide_link': True, 'hide_object': True, + 'no_results_icon': icon_smart_link_setup, + 'no_results_text': _( + 'Smart links allow defining relationships between ' + 'documents even if they are in different indexes and ' + 'are of different types.' + ), + 'no_results_title': _( + 'There are no smart links for this document' + ), 'object': self.document, 'title': _('Smart links for document: %s') % self.document, } @@ -203,6 +229,21 @@ class SmartLinkConditionListView(SingleObjectListView): def get_extra_context(self): return { 'hide_link': True, + 'no_results_icon': icon_smart_link_condition, + 'no_results_main_link': link_smart_link_condition_create.resolve( + context=RequestContext( + request=self.request, dict_={ + 'object': self.get_smart_link() + } + ) + ), + 'no_results_text': _( + 'Conditions are small logic units that when combined ' + 'define how the smart link will behave.' + ), + 'no_results_title': _( + 'There are no conditions for this smart link' + ), 'object': self.get_smart_link(), 'title': _( 'Conditions for smart link: %s' diff --git a/mayan/apps/permissions/icons.py b/mayan/apps/permissions/icons.py index 83e041435d..8e87a913c6 100644 --- a/mayan/apps/permissions/icons.py +++ b/mayan/apps/permissions/icons.py @@ -2,4 +2,5 @@ from __future__ import absolute_import, unicode_literals from appearance.classes import Icon +icon_role_create = Icon(driver_name='fontawesome', symbol='plus') icon_role_list = Icon(driver_name='fontawesome', symbol='user-secret') diff --git a/mayan/apps/permissions/links.py b/mayan/apps/permissions/links.py index 045b16762b..a9dc6f7988 100644 --- a/mayan/apps/permissions/links.py +++ b/mayan/apps/permissions/links.py @@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _ from navigation import Link from user_management.permissions import permission_group_edit -from .icons import icon_role_list +from .icons import icon_role_create, icon_role_list from .permissions import ( permission_permission_grant, permission_permission_revoke, permission_role_create, permission_role_delete, permission_role_edit, @@ -25,8 +25,8 @@ link_permission_revoke = Link( view='permissions:permission_multiple_revoke' ) link_role_create = Link( - permissions=(permission_role_create,), text=_('Create new role'), - view='permissions:role_create' + icon_class=icon_role_create, permissions=(permission_role_create,), + text=_('Create new role'), view='permissions:role_create' ) link_role_delete = Link( args='object.id', permissions=(permission_role_delete,), tags='dangerous', diff --git a/mayan/apps/permissions/views.py b/mayan/apps/permissions/views.py index 0dc306d441..5f39b2540e 100644 --- a/mayan/apps/permissions/views.py +++ b/mayan/apps/permissions/views.py @@ -4,6 +4,7 @@ import itertools from django.contrib.auth.models import Group from django.shortcuts import get_object_or_404 +from django.template import RequestContext from django.urls import reverse_lazy from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _ @@ -16,6 +17,8 @@ from common.views import ( from user_management.permissions import permission_group_edit from .classes import Permission, PermissionNamespace +from .icons import icon_role_list +from .links import link_role_create from .models import Role, StoredPermission from .permissions import ( permission_permission_grant, permission_permission_revoke, @@ -90,7 +93,11 @@ class SetupRoleMembersView(AssignRemoveView): def get_extra_context(self): return { 'object': self.get_object(), - 'title': _('Groups of role: %s') % self.get_object() + 'title': _('Groups of role: %s') % self.get_object(), + 'subtitle': _( + 'Add groups to be part of a role. They will ' + 'inherit the role\'s permissions and access controls.' + ), } def get_object(self): @@ -187,10 +194,24 @@ class SetupRolePermissionsView(AssignRemoveView): class RoleListView(SingleObjectListView): - extra_context = { - 'hide_link': True, - 'title': _('Roles'), - } - model = Role object_permission = permission_role_view + + def get_extra_context(self): + return { + 'hide_link': True, + 'no_results_icon': icon_role_list, + 'no_results_main_link': link_role_create.resolve( + context=RequestContext(request=self.request) + ), + 'no_results_text': _( + 'Roles are authorization units. They contain ' + 'user groups which inherit the role permissions for the ' + 'entire system. Roles can also part of access ' + 'controls lists. Access controls list are permissions ' + 'granted to a role for specific objects which its group ' + 'members inherit.' + ), + 'no_results_title': _('There are no roles'), + 'title': _('Roles'), + } diff --git a/mayan/apps/user_management/apps.py b/mayan/apps/user_management/apps.py index 07bfa27160..33378050d0 100644 --- a/mayan/apps/user_management/apps.py +++ b/mayan/apps/user_management/apps.py @@ -17,8 +17,8 @@ from rest_api.fields import DynamicSerializerField from .handlers import handler_initialize_new_user_options from .links import ( - link_group_add, link_group_delete, link_group_edit, link_group_list, - link_group_members, link_group_setup, link_user_add, link_user_delete, + link_group_create, link_group_delete, link_group_edit, link_group_list, + link_group_members, link_group_setup, link_user_create, link_user_delete, link_user_edit, link_user_groups, link_user_list, link_user_multiple_delete, link_user_multiple_set_password, link_user_set_options, link_user_set_password, link_user_setup @@ -128,17 +128,17 @@ class UserManagementApp(MayanAppConfig): ), sources=(User,) ) menu_secondary.bind_links( - links=(link_group_list, link_group_add), sources=( + links=(link_group_list, link_group_create), sources=( 'user_management:group_multiple_delete', - 'user_management:group_list', 'user_management:group_add', + 'user_management:group_list', 'user_management:group_create', Group ) ) menu_secondary.bind_links( - links=(link_user_list, link_user_add), sources=( + links=(link_user_list, link_user_create), sources=( User, 'user_management:user_multiple_set_password', 'user_management:user_multiple_delete', - 'user_management:user_list', 'user_management:user_add' + 'user_management:user_list', 'user_management:user_create' ) ) menu_setup.bind_links(links=(link_user_setup, link_group_setup)) diff --git a/mayan/apps/user_management/icons.py b/mayan/apps/user_management/icons.py index 2f3195daf1..2e9b10f881 100644 --- a/mayan/apps/user_management/icons.py +++ b/mayan/apps/user_management/icons.py @@ -2,5 +2,7 @@ from __future__ import absolute_import, unicode_literals from appearance.classes import Icon +icon_group_create = Icon(driver_name='fontawesome', symbol='plus') icon_group_setup = Icon(driver_name='fontawesome', symbol='users') +icon_user_create = Icon(driver_name='fontawesome', symbol='plus') icon_user_setup = Icon(driver_name='fontawesome', symbol='user') diff --git a/mayan/apps/user_management/links.py b/mayan/apps/user_management/links.py index 1de2c1715b..a0edebdd42 100644 --- a/mayan/apps/user_management/links.py +++ b/mayan/apps/user_management/links.py @@ -4,16 +4,18 @@ from django.utils.translation import ugettext_lazy as _ from navigation import Link -from .icons import icon_group_setup, icon_user_setup +from .icons import ( + icon_group_create, icon_group_setup, icon_user_create, icon_user_setup +) from .permissions import ( permission_group_create, permission_group_delete, permission_group_edit, permission_group_view, permission_user_create, permission_user_delete, permission_user_edit, permission_user_view ) -link_group_add = Link( - permissions=(permission_group_create,), text=_('Create new group'), - view='user_management:group_add' +link_group_create = Link( + icon_class=icon_group_create, permissions=(permission_group_create,), + text=_('Create new group'), view='user_management:group_create' ) link_group_delete = Link( args='object.id', permissions=(permission_group_delete,), tags='dangerous', @@ -35,9 +37,9 @@ link_group_setup = Link( icon_class=icon_group_setup, permissions=(permission_group_view,), text=_('Groups'), view='user_management:group_list' ) -link_user_add = Link( - permissions=(permission_user_create,), text=_('Create new user'), - view='user_management:user_add' +link_user_create = Link( + icon_class=icon_user_create, permissions=(permission_user_create,), + text=_('Create new user'), view='user_management:user_create' ) link_user_delete = Link( args='object.id', permissions=(permission_user_delete,), tags='dangerous', diff --git a/mayan/apps/user_management/urls.py b/mayan/apps/user_management/urls.py index bfbc33e12e..ca47b5d69b 100644 --- a/mayan/apps/user_management/urls.py +++ b/mayan/apps/user_management/urls.py @@ -14,7 +14,7 @@ from .views import ( urlpatterns = [ url(r'^group/list/$', GroupListView.as_view(), name='group_list'), - url(r'^group/add/$', GroupCreateView.as_view(), name='group_add'), + url(r'^group/create/$', GroupCreateView.as_view(), name='group_create'), url( r'^group/(?P\d+)/edit/$', GroupEditView.as_view(), name='group_edit' @@ -29,7 +29,7 @@ urlpatterns = [ ), url(r'^user/list/$', UserListView.as_view(), name='user_list'), - url(r'^user/add/$', UserCreateView.as_view(), name='user_add'), + url(r'^user/create/$', UserCreateView.as_view(), name='user_create'), url(r'^user/(?P\d+)/edit/$', UserEditView.as_view(), name='user_edit'), url( r'^user/(?P\d+)/delete/$', UserDeleteView.as_view(), diff --git a/mayan/apps/user_management/views.py b/mayan/apps/user_management/views.py index f1a66635c6..089dffd982 100644 --- a/mayan/apps/user_management/views.py +++ b/mayan/apps/user_management/views.py @@ -8,6 +8,7 @@ from django.contrib.contenttypes.models import ContentType from django.core.exceptions import PermissionDenied 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.translation import ungettext, ugettext_lazy as _ @@ -18,6 +19,8 @@ from common.views import ( ) from .forms import UserForm +from .icons import icon_group_setup, icon_user_setup +from .links import link_group_create, link_user_create from .permissions import ( permission_group_create, permission_group_delete, permission_group_edit, permission_group_view, permission_user_create, permission_user_delete, @@ -47,13 +50,27 @@ class GroupEditView(SingleObjectEditView): class GroupListView(SingleObjectListView): - extra_context = { - 'hide_link': True, - 'title': _('Groups'), - } model = Group object_permission = permission_group_view + def get_extra_context(self): + return { + 'hide_link': True, + 'no_results_icon': icon_group_setup, + 'no_results_main_link': link_group_create.resolve( + context=RequestContext(request=self.request) + ), + 'no_results_text': _( + 'User groups are organizational units. They should ' + 'mirror the organizational units of your organization. ' + 'Groups can\'t be used for access control. Use roles ' + 'for permissions and access control, add groups to ' + 'them.' + ), + 'no_results_title': _('There are no user groups'), + 'title': _('Groups'), + } + class GroupDeleteView(SingleObjectDeleteView): model = Group @@ -244,6 +261,15 @@ class UserListView(SingleObjectListView): def get_extra_context(self): return { 'hide_link': True, + 'no_results_icon': icon_user_setup, + 'no_results_main_link': link_user_create.resolve( + context=RequestContext(request=self.request) + ), + 'no_results_text': _( + 'User accounts can be create from this view. After creating ' + 'an user account you will prompted to set a password for it. ' + ), + 'no_results_title': _('There are no user accounts'), 'title': _('Users'), }