From bd041457c9f260ad329f1b9a6bf89c7dcc7b4490 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Mon, 30 Mar 2015 03:42:53 -0400 Subject: [PATCH] Update project to use Django 1.7.7. Issue #33 --- docs/releases/2.0.rst | 2 +- mayan/apps/acls/__init__.py | 32 ----- mayan/apps/acls/apps.py | 40 ++++++ mayan/apps/checkouts/__init__.py | 51 ------- mayan/apps/checkouts/apps.py | 56 ++++++++ mayan/apps/common/__init__.py | 101 -------------- mayan/apps/common/apps.py | 107 +++++++++++++++ mayan/apps/django_gpg/__init__.py | 15 -- mayan/apps/django_gpg/apps.py | 24 ++++ mayan/apps/document_acls/__init__.py | 14 -- mayan/apps/document_acls/apps.py | 24 ++++ mayan/apps/document_comments/__init__.py | 51 ------- mayan/apps/document_comments/apps.py | 57 ++++++++ mayan/apps/document_comments/forms.py | 2 +- mayan/apps/document_indexing/__init__.py | 51 ------- mayan/apps/document_indexing/apps.py | 58 ++++++++ mayan/apps/document_signatures/__init__.py | 63 --------- mayan/apps/document_signatures/apps.py | 72 ++++++++++ mayan/apps/document_states/__init__.py | 104 -------------- mayan/apps/document_states/apps.py | 111 +++++++++++++++ mayan/apps/documents/__init__.py | 140 ------------------- mayan/apps/documents/apps.py | 151 +++++++++++++++++++++ mayan/apps/documents/forms.py | 14 +- mayan/apps/documents/models.py | 4 - mayan/apps/dynamic_search/__init__.py | 10 -- mayan/apps/dynamic_search/apps.py | 20 +++ mayan/apps/events/__init__.py | 6 - mayan/apps/events/apps.py | 16 +++ mayan/apps/folders/__init__.py | 49 ------- mayan/apps/folders/apps.py | 57 ++++++++ mayan/apps/installation/__init__.py | 47 ------- mayan/apps/installation/apps.py | 54 ++++++++ mayan/apps/linking/__init__.py | 34 ----- mayan/apps/linking/apps.py | 43 ++++++ mayan/apps/linking/models.py | 5 +- mayan/apps/lock_manager/apps.py | 9 ++ mayan/apps/mailer/__init__.py | 13 -- mayan/apps/mailer/apps.py | 25 ++++ mayan/apps/mailer/models.py | 3 - mayan/apps/main/__init__.py | 12 -- mayan/apps/main/apps.py | 20 +++ mayan/apps/metadata/__init__.py | 93 ------------- mayan/apps/metadata/apps.py | 100 ++++++++++++++ mayan/apps/ocr/__init__.py | 74 ---------- mayan/apps/ocr/apps.py | 81 +++++++++++ mayan/apps/permissions/__init__.py | 41 ------ mayan/apps/permissions/apps.py | 49 +++++++ mayan/apps/project_setup/__init__.py | 6 - mayan/apps/project_setup/apps.py | 16 +++ mayan/apps/project_tools/__init__.py | 6 +- mayan/apps/project_tools/apps.py | 17 +++ mayan/apps/rest_api/__init__.py | 10 -- mayan/apps/rest_api/apps.py | 20 +++ mayan/apps/smart_settings/__init__.py | 4 - mayan/apps/smart_settings/apps.py | 16 +++ mayan/apps/sources/__init__.py | 46 ------- mayan/apps/sources/apps.py | 54 ++++++++ mayan/apps/sources/forms.py | 6 + mayan/apps/sources/models.py | 4 +- mayan/apps/statistics/__init__.py | 15 -- mayan/apps/statistics/apps.py | 25 ++++ mayan/apps/tags/__init__.py | 62 --------- mayan/apps/tags/apps.py | 70 ++++++++++ mayan/apps/user_management/__init__.py | 26 ---- mayan/apps/user_management/apps.py | 40 ++++++ mayan/apps/user_management/models.py | 7 - mayan/settings/base.py | 63 ++++----- requirements/common.txt | 3 +- 68 files changed, 1485 insertions(+), 1236 deletions(-) create mode 100644 mayan/apps/acls/apps.py create mode 100644 mayan/apps/checkouts/apps.py create mode 100644 mayan/apps/common/apps.py create mode 100644 mayan/apps/django_gpg/apps.py create mode 100644 mayan/apps/document_acls/apps.py create mode 100644 mayan/apps/document_comments/apps.py create mode 100644 mayan/apps/document_indexing/apps.py create mode 100644 mayan/apps/document_signatures/apps.py create mode 100644 mayan/apps/document_states/apps.py create mode 100644 mayan/apps/documents/apps.py create mode 100644 mayan/apps/dynamic_search/apps.py create mode 100644 mayan/apps/events/apps.py create mode 100644 mayan/apps/folders/apps.py create mode 100644 mayan/apps/installation/apps.py create mode 100644 mayan/apps/linking/apps.py create mode 100644 mayan/apps/lock_manager/apps.py create mode 100644 mayan/apps/mailer/apps.py delete mode 100644 mayan/apps/mailer/models.py create mode 100644 mayan/apps/main/apps.py create mode 100644 mayan/apps/metadata/apps.py create mode 100644 mayan/apps/ocr/apps.py create mode 100644 mayan/apps/permissions/apps.py create mode 100644 mayan/apps/project_setup/apps.py create mode 100644 mayan/apps/project_tools/apps.py create mode 100644 mayan/apps/rest_api/apps.py create mode 100644 mayan/apps/smart_settings/apps.py create mode 100644 mayan/apps/sources/apps.py create mode 100644 mayan/apps/statistics/apps.py create mode 100644 mayan/apps/tags/apps.py create mode 100644 mayan/apps/user_management/apps.py delete mode 100644 mayan/apps/user_management/models.py diff --git a/docs/releases/2.0.rst b/docs/releases/2.0.rst index 315054dbac..4f8473f3ff 100644 --- a/docs/releases/2.0.rst +++ b/docs/releases/2.0.rst @@ -55,7 +55,7 @@ Add new static media:: Remove unused dependencies:: - $ pip uninstall XXXXX + $ pip uninstall South The upgrade procedure is now complete. diff --git a/mayan/apps/acls/__init__.py b/mayan/apps/acls/__init__.py index 75944619b7..8b13789179 100644 --- a/mayan/apps/acls/__init__.py +++ b/mayan/apps/acls/__init__.py @@ -1,33 +1 @@ -from __future__ import unicode_literals -from django.dispatch import receiver - -from south.signals import post_migrate - -from navigation.api import register_links -from project_setup.api import register_setup - -from .classes import ( - AccessHolder, AccessObject, AccessObjectClass, ClassAccessHolder -) -from .links import ( - acl_class_acl_detail, acl_class_acl_list, acl_class_grant, acl_class_list, - acl_class_new_holder_for, acl_class_revoke, acl_detail, acl_grant, - acl_holder_new, acl_revoke, acl_setup_valid_classes -) -from .models import CreatorSingleton - -register_links([AccessObject], [acl_holder_new], menu_name='sidebar') -register_links(AccessObjectClass, [acl_class_acl_list, acl_class_new_holder_for]) -register_links(AccessHolder, [acl_detail]) -register_links(['acls:acl_setup_valid_classes', 'acls:acl_class_acl_list', 'acls:acl_class_new_holder_for', 'acls:acl_class_acl_detail', 'acls:acl_class_multiple_grant', 'acls:acl_class_multiple_revoke'], [acl_class_list], menu_name='secondary_menu') -register_links(ClassAccessHolder, [acl_class_acl_detail]) -register_links(['acls:acl_detail'], [acl_grant, acl_revoke], menu_name='multi_item_links') -register_links(['acls:acl_class_acl_detail'], [acl_class_grant, acl_class_revoke], menu_name='multi_item_links') -register_setup(acl_setup_valid_classes) - - -@receiver(post_migrate, dispatch_uid='create_creator_user') -def create_creator_user(sender, **kwargs): - if kwargs['app'] == 'acls': - CreatorSingleton.objects.get_or_create() diff --git a/mayan/apps/acls/apps.py b/mayan/apps/acls/apps.py new file mode 100644 index 0000000000..313d0ab290 --- /dev/null +++ b/mayan/apps/acls/apps.py @@ -0,0 +1,40 @@ +from __future__ import unicode_literals + +from django import apps +from django.db.models.signals import post_migrate +from django.utils.translation import ugettext_lazy as _ + +from navigation.api import register_links +from project_setup.api import register_setup + +from .classes import ( + AccessHolder, AccessObject, AccessObjectClass, ClassAccessHolder +) +from .links import ( + acl_class_acl_detail, acl_class_acl_list, acl_class_grant, acl_class_list, + acl_class_new_holder_for, acl_class_revoke, acl_detail, acl_grant, + acl_holder_new, acl_revoke, acl_setup_valid_classes +) +from .models import CreatorSingleton + + +def create_creator_user(sender, **kwargs): + if kwargs.get('app') == 'acls': + CreatorSingleton.objects.get_or_create() + + +class ACLsApp(apps.AppConfig): + name = 'acls' + verbose_name = _('ACLs') + + def ready(self): + register_links([AccessObject], [acl_holder_new], menu_name='sidebar') + register_links(AccessObjectClass, [acl_class_acl_list, acl_class_new_holder_for]) + register_links(AccessHolder, [acl_detail]) + register_links(['acls:acl_setup_valid_classes', 'acls:acl_class_acl_list', 'acls:acl_class_new_holder_for', 'acls:acl_class_acl_detail', 'acls:acl_class_multiple_grant', 'acls:acl_class_multiple_revoke'], [acl_class_list], menu_name='secondary_menu') + register_links(ClassAccessHolder, [acl_class_acl_detail]) + register_links(['acls:acl_detail'], [acl_grant, acl_revoke], menu_name='multi_item_links') + register_links(['acls:acl_class_acl_detail'], [acl_class_grant, acl_class_revoke], menu_name='multi_item_links') + register_setup(acl_setup_valid_classes) + + post_migrate.connect(create_creator_user, dispatch_uid='create_creator_user') diff --git a/mayan/apps/checkouts/__init__.py b/mayan/apps/checkouts/__init__.py index 032712d7d5..8b13789179 100644 --- a/mayan/apps/checkouts/__init__.py +++ b/mayan/apps/checkouts/__init__.py @@ -1,52 +1 @@ -from __future__ import absolute_import, unicode_literals -from datetime import timedelta - -from acls.api import class_permissions -from documents.models import Document -from mayan.celery import app -from navigation.api import register_links, register_top_menu -from rest_api.classes import APIEndPoint - -from .links import ( - checkin_document, checkout_document, checkout_info, checkout_list -) -from .models import DocumentCheckout -from .permissions import ( - PERMISSION_DOCUMENT_CHECKIN, PERMISSION_DOCUMENT_CHECKIN_OVERRIDE, - PERMISSION_DOCUMENT_CHECKOUT, PERMISSION_DOCUMENT_RESTRICTIONS_OVERRIDE -) - -CHECK_EXPIRED_CHECK_OUTS_INTERVAL = 60 # Lowest check out expiration allowed - - -def initialize_document_checkout_extra_methods(): - Document.add_to_class('is_checked_out', lambda document: DocumentCheckout.objects.is_document_checked_out(document)) - Document.add_to_class('check_in', lambda document, user=None: DocumentCheckout.objects.check_in_document(document, user)) - Document.add_to_class('checkout_info', lambda document: DocumentCheckout.objects.document_checkout_info(document)) - Document.add_to_class('checkout_state', lambda document: DocumentCheckout.objects.document_checkout_state(document)) - Document.add_to_class('is_new_versions_allowed', lambda document, user=None: DocumentCheckout.objects.is_document_new_versions_allowed(document, user)) - - -app.conf.CELERYBEAT_SCHEDULE.update({ - 'check_expired_check_outs': { - 'task': 'checkouts.tasks.task_check_expired_check_outs', - 'schedule': timedelta(seconds=CHECK_EXPIRED_CHECK_OUTS_INTERVAL), - 'options': {'queue': 'checkouts'} - }, -}) - -class_permissions(Document, [ - PERMISSION_DOCUMENT_CHECKOUT, - PERMISSION_DOCUMENT_CHECKIN, - PERMISSION_DOCUMENT_CHECKIN_OVERRIDE, - PERMISSION_DOCUMENT_RESTRICTIONS_OVERRIDE -]) - -initialize_document_checkout_extra_methods() - -register_links(Document, [checkout_info], menu_name='form_header') -register_links(['checkouts:checkout_info', 'checkouts:checkout_document', 'checkouts:checkin_document'], [checkout_document, checkin_document], menu_name="sidebar") -register_top_menu(name='checkouts', link=checkout_list) - -APIEndPoint('checkouts') diff --git a/mayan/apps/checkouts/apps.py b/mayan/apps/checkouts/apps.py new file mode 100644 index 0000000000..6ba089e9b5 --- /dev/null +++ b/mayan/apps/checkouts/apps.py @@ -0,0 +1,56 @@ +from __future__ import absolute_import, unicode_literals + +from datetime import timedelta + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from acls.api import class_permissions +from documents.models import Document +from mayan.celery import app +from navigation.api import register_links, register_top_menu +from rest_api.classes import APIEndPoint + +from .links import ( + checkin_document, checkout_document, checkout_info, checkout_list +) +from .models import DocumentCheckout +from .permissions import ( + PERMISSION_DOCUMENT_CHECKIN, PERMISSION_DOCUMENT_CHECKIN_OVERRIDE, + PERMISSION_DOCUMENT_CHECKOUT, PERMISSION_DOCUMENT_RESTRICTIONS_OVERRIDE +) + +CHECK_EXPIRED_CHECK_OUTS_INTERVAL = 60 # Lowest check out expiration allowed + + +class CheckoutsApp(apps.AppConfig): + name = 'checkouts' + verbose_name = _('Checkouts') + + def ready(self): + Document.add_to_class('is_checked_out', lambda document: DocumentCheckout.objects.is_document_checked_out(document)) + Document.add_to_class('check_in', lambda document, user=None: DocumentCheckout.objects.check_in_document(document, user)) + Document.add_to_class('checkout_info', lambda document: DocumentCheckout.objects.document_checkout_info(document)) + Document.add_to_class('checkout_state', lambda document: DocumentCheckout.objects.document_checkout_state(document)) + Document.add_to_class('is_new_versions_allowed', lambda document, user=None: DocumentCheckout.objects.is_document_new_versions_allowed(document, user)) + + app.conf.CELERYBEAT_SCHEDULE.update({ + 'check_expired_check_outs': { + 'task': 'checkouts.tasks.task_check_expired_check_outs', + 'schedule': timedelta(seconds=CHECK_EXPIRED_CHECK_OUTS_INTERVAL), + 'options': {'queue': 'checkouts'} + }, + }) + + class_permissions(Document, [ + PERMISSION_DOCUMENT_CHECKOUT, + PERMISSION_DOCUMENT_CHECKIN, + PERMISSION_DOCUMENT_CHECKIN_OVERRIDE, + PERMISSION_DOCUMENT_RESTRICTIONS_OVERRIDE + ]) + + register_links(Document, [checkout_info], menu_name='form_header') + register_links(['checkouts:checkout_info', 'checkouts:checkout_document', 'checkouts:checkin_document'], [checkout_document, checkin_document], menu_name="sidebar") + register_top_menu(name='checkouts', link=checkout_list) + + APIEndPoint('checkouts') diff --git a/mayan/apps/common/__init__.py b/mayan/apps/common/__init__.py index da2181dbe1..8b13789179 100644 --- a/mayan/apps/common/__init__.py +++ b/mayan/apps/common/__init__.py @@ -1,102 +1 @@ -from __future__ import absolute_import, unicode_literals -import logging -import tempfile - -from django.conf import settings -from django.contrib.auth import models as auth_models -from django.contrib.auth.models import User -from django.contrib.auth.signals import user_logged_in -from django.db.models.signals import post_save -from django.dispatch import receiver - -from south.signals import post_migrate - -from common import settings as common_settings -from navigation.api import register_links, register_top_menu - -from .links import ( - link_about, link_current_user_details, link_current_user_edit, - link_current_user_locale_profile_details, - link_current_user_locale_profile_edit, link_license, link_logout, - link_password_change -) -from .models import ( - AnonymousUserSingleton, AutoAdminSingleton, UserLocaleProfile -) -from .settings import ( - AUTO_ADMIN_USERNAME, AUTO_ADMIN_PASSWORD, AUTO_CREATE_ADMIN, - TEMPORARY_DIRECTORY -) -from .utils import validate_path - -logger = logging.getLogger(__name__) - -register_links(['common:current_user_details', 'common:current_user_edit', 'common:current_user_locale_profile_details', 'common:current_user_locale_profile_edit', 'common:password_change_view'], [link_current_user_details, link_current_user_edit, link_current_user_locale_profile_details, link_current_user_locale_profile_edit, link_password_change, link_logout], menu_name='secondary_menu') -register_links(['common:about_view', 'common:license_view'], [link_about, link_license], menu_name='secondary_menu') - -register_top_menu('about', link_about, position=-1) - - -@receiver(post_migrate, dispatch_uid='create_superuser_and_anonymous_user') -def create_superuser_and_anonymous_user(sender, **kwargs): - """ - From https://github.com/lambdalisue/django-qwert/blob/master/qwert/autoscript/__init__.py - From http://stackoverflow.com/questions/1466827/ -- - - Prevent interactive question about wanting a superuser created. (This code - has to go in this otherwise empty "models" module so that it gets processed by - the "syncdb" command during database creation.) - - Create our own admin super user automatically. - """ - if kwargs['app'] == 'common': - AutoAdminSingleton.objects.get_or_create() - AnonymousUserSingleton.objects.get_or_create() - - if AUTO_CREATE_ADMIN: - try: - auth_models.User.objects.get(username=AUTO_ADMIN_USERNAME) - except auth_models.User.DoesNotExist: - logger.info('Creating super admin user -- login: %s, password: %s', AUTO_ADMIN_USERNAME, AUTO_ADMIN_PASSWORD) - assert auth_models.User.objects.create_superuser(AUTO_ADMIN_USERNAME, 'autoadmin@autoadmin.com', AUTO_ADMIN_PASSWORD) - admin = auth_models.User.objects.get(username=AUTO_ADMIN_USERNAME) - # Store the auto admin password properties to display the first login message - auto_admin_properties, created = AutoAdminSingleton.objects.get_or_create() - auto_admin_properties.account = admin - auto_admin_properties.password = AUTO_ADMIN_PASSWORD - auto_admin_properties.password_hash = admin.password - auto_admin_properties.save() - else: - logger.info('Super admin user already exists. -- login: %s', AUTO_ADMIN_USERNAME) - - -@receiver(post_save, dispatch_uid='auto_admin_account_passwd_change', sender=User) -def auto_admin_account_passwd_change(sender, instance, **kwargs): - auto_admin_properties = AutoAdminSingleton.objects.get() - if instance == auto_admin_properties.account and instance.password != auto_admin_properties.password_hash: - # Only delete the auto admin properties when the password has been changed - auto_admin_properties.account = None - auto_admin_properties.password = None - auto_admin_properties.password_hash = None - auto_admin_properties.save() - - -@receiver(user_logged_in, dispatch_uid='user_locale_profile_session_config', sender=User) -def user_locale_profile_session_config(sender, request, user, **kwargs): - if hasattr(request, 'session'): - user_locale_profile, created = UserLocaleProfile.objects.get_or_create(user=user) - request.session['django_language'] = user_locale_profile.language - request.session['django_timezone'] = user_locale_profile.timezone - else: - request.set_cookie(settings.LANGUAGE_COOKIE_NAME, user_locale_profile.language) - - -@receiver(post_save, dispatch_uid='user_locale_profile_create', sender=User) -def user_locale_profile_create(sender, instance, created, **kwargs): - if created: - UserLocaleProfile.objects.create(user=instance) - - -if (not validate_path(TEMPORARY_DIRECTORY)) or (not TEMPORARY_DIRECTORY): - setattr(common_settings, 'TEMPORARY_DIRECTORY', tempfile.mkdtemp()) diff --git a/mayan/apps/common/apps.py b/mayan/apps/common/apps.py new file mode 100644 index 0000000000..b2ed2de33b --- /dev/null +++ b/mayan/apps/common/apps.py @@ -0,0 +1,107 @@ +from __future__ import absolute_import, unicode_literals + +import logging +import tempfile + +from django import apps +from django.conf import settings +from django.contrib.auth import models as auth_models +from django.contrib.auth.models import User +from django.contrib.auth.signals import user_logged_in +from django.db.models.signals import post_migrate, post_save +from django.utils.translation import ugettext_lazy as _ + +from common import settings as common_settings +from navigation.api import register_links, register_top_menu + +from .links import ( + link_about, link_current_user_details, link_current_user_edit, + link_current_user_locale_profile_details, + link_current_user_locale_profile_edit, link_license, link_logout, + link_password_change +) +from .models import ( + AnonymousUserSingleton, AutoAdminSingleton, UserLocaleProfile +) +from .settings import ( + AUTO_ADMIN_USERNAME, AUTO_ADMIN_PASSWORD, AUTO_CREATE_ADMIN, + TEMPORARY_DIRECTORY +) +from .utils import validate_path + + +def create_superuser_and_anonymous_user(sender, **kwargs): + """ + From https://github.com/lambdalisue/django-qwert/blob/master/qwert/autoscript/__init__.py + From http://stackoverflow.com/questions/1466827/ -- + + Prevent interactive question about wanting a superuser created. (This code + has to go in this otherwise empty "models" module so that it gets processed by + the "syncdb" command during database creation.) + + Create our own admin super user automatically. + """ + if kwargs['app'] == 'common': + AutoAdminSingleton.objects.get_or_create() + AnonymousUserSingleton.objects.get_or_create() + + if AUTO_CREATE_ADMIN: + try: + auth_models.User.objects.get(username=AUTO_ADMIN_USERNAME) + except auth_models.User.DoesNotExist: + logger.info('Creating super admin user -- login: %s, password: %s', AUTO_ADMIN_USERNAME, AUTO_ADMIN_PASSWORD) + assert auth_models.User.objects.create_superuser(AUTO_ADMIN_USERNAME, 'autoadmin@autoadmin.com', AUTO_ADMIN_PASSWORD) + admin = auth_models.User.objects.get(username=AUTO_ADMIN_USERNAME) + # Store the auto admin password properties to display the first login message + auto_admin_properties, created = AutoAdminSingleton.objects.get_or_create() + auto_admin_properties.account = admin + auto_admin_properties.password = AUTO_ADMIN_PASSWORD + auto_admin_properties.password_hash = admin.password + auto_admin_properties.save() + else: + logger.info('Super admin user already exists. -- login: %s', AUTO_ADMIN_USERNAME) + + +def auto_admin_account_passwd_change(sender, instance, **kwargs): + auto_admin_properties = AutoAdminSingleton.objects.get() + if instance == auto_admin_properties.account and instance.password != auto_admin_properties.password_hash: + # Only delete the auto admin properties when the password has been changed + auto_admin_properties.account = None + auto_admin_properties.password = None + auto_admin_properties.password_hash = None + auto_admin_properties.save() + + +def user_locale_profile_session_config(sender, request, user, **kwargs): + if hasattr(request, 'session'): + user_locale_profile, created = UserLocaleProfile.objects.get_or_create(user=user) + request.session['django_language'] = user_locale_profile.language + request.session['django_timezone'] = user_locale_profile.timezone + else: + request.set_cookie(settings.LANGUAGE_COOKIE_NAME, user_locale_profile.language) + + +def user_locale_profile_create(sender, instance, created, **kwargs): + if created: + UserLocaleProfile.objects.create(user=instance) + + +class CommonApp(apps.AppConfig): + name = 'common' + verbose_name = _('Common') + + def ready(self): + logger = logging.getLogger(__name__) + + register_links(['common:current_user_details', 'common:current_user_edit', 'common:current_user_locale_profile_details', 'common:current_user_locale_profile_edit', 'common:password_change_view'], [link_current_user_details, link_current_user_edit, link_current_user_locale_profile_details, link_current_user_locale_profile_edit, link_password_change, link_logout], menu_name='secondary_menu') + register_links(['common:about_view', 'common:license_view'], [link_about, link_license], menu_name='secondary_menu') + + register_top_menu('about', link_about, position=-1) + + post_migrate.connect(create_superuser_and_anonymous_user, dispatch_uid='create_superuser_and_anonymous_user') + post_save.connect(auto_admin_account_passwd_change, dispatch_uid='auto_admin_account_passwd_change', sender=User) + user_logged_in.connect(user_locale_profile_session_config, dispatch_uid='user_locale_profile_session_config', sender=User) + post_save.connect(user_locale_profile_create, dispatch_uid='user_locale_profile_create', sender=User) + + if (not validate_path(TEMPORARY_DIRECTORY)) or (not TEMPORARY_DIRECTORY): + setattr(common_settings, 'TEMPORARY_DIRECTORY', tempfile.mkdtemp()) diff --git a/mayan/apps/django_gpg/__init__.py b/mayan/apps/django_gpg/__init__.py index 85d4eb840a..8b13789179 100644 --- a/mayan/apps/django_gpg/__init__.py +++ b/mayan/apps/django_gpg/__init__.py @@ -1,16 +1 @@ -from __future__ import unicode_literals -from hkp import Key as KeyServerKey - -from navigation.api import register_links -from project_setup.api import register_setup - -from .api import Key -from .links import ( - key_delete, key_query, key_receive, key_setup, public_keys -) - -register_links(['django_gpg:key_delete', 'django_gpg:key_public_list', 'django_gpg:key_query'], [public_keys, key_query], menu_name='sidebar') -register_links(Key, [key_delete]) -register_links(KeyServerKey, [key_receive]) -register_setup(key_setup) diff --git a/mayan/apps/django_gpg/apps.py b/mayan/apps/django_gpg/apps.py new file mode 100644 index 0000000000..47e2df61da --- /dev/null +++ b/mayan/apps/django_gpg/apps.py @@ -0,0 +1,24 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from hkp import Key as KeyServerKey + +from navigation.api import register_links +from project_setup.api import register_setup + +from .api import Key +from .links import ( + key_delete, key_query, key_receive, key_setup, public_keys +) + +class DjangoGPGApp(apps.AppConfig): + name = 'django_gpg' + verbose_name = _('Django GPG') + + def ready(self): + register_links(['django_gpg:key_delete', 'django_gpg:key_public_list', 'django_gpg:key_query'], [public_keys, key_query], menu_name='sidebar') + register_links(Key, [key_delete]) + register_links(KeyServerKey, [key_receive]) + register_setup(key_setup) diff --git a/mayan/apps/document_acls/__init__.py b/mayan/apps/document_acls/__init__.py index a6fea018cf..8b13789179 100644 --- a/mayan/apps/document_acls/__init__.py +++ b/mayan/apps/document_acls/__init__.py @@ -1,15 +1 @@ -from __future__ import unicode_literals -from acls.api import class_permissions -from acls.permissions import ACLS_VIEW_ACL, ACLS_EDIT_ACL -from documents.models import Document -from navigation.api import register_links - -from .links import acl_list - -register_links(Document, [acl_list], menu_name='form_header') - -class_permissions(Document, [ - ACLS_VIEW_ACL, - ACLS_EDIT_ACL -]) diff --git a/mayan/apps/document_acls/apps.py b/mayan/apps/document_acls/apps.py new file mode 100644 index 0000000000..20fe662ae2 --- /dev/null +++ b/mayan/apps/document_acls/apps.py @@ -0,0 +1,24 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from acls.api import class_permissions +from acls.permissions import ACLS_VIEW_ACL, ACLS_EDIT_ACL +from documents.models import Document +from navigation.api import register_links + +from .links import acl_list + + +class DocumentACLsApp(apps.AppConfig): + name = 'document_acls' + verbose_name = _('Document ACLs') + + def ready(self): + register_links(Document, [acl_list], menu_name='form_header') + + class_permissions(Document, [ + ACLS_VIEW_ACL, + ACLS_EDIT_ACL + ]) diff --git a/mayan/apps/document_comments/__init__.py b/mayan/apps/document_comments/__init__.py index 8e5fe88561..8b13789179 100644 --- a/mayan/apps/document_comments/__init__.py +++ b/mayan/apps/document_comments/__init__.py @@ -1,52 +1 @@ -from __future__ import absolute_import, unicode_literals -from django.contrib.comments.models import Comment -from django.contrib.contenttypes import generic -from django.utils.translation import ugettext_lazy as _ - -from acls.api import class_permissions -from common.classes import ModelAttribute -from common.utils import encapsulate -from documents.models import Document -from navigation.api import register_links, register_model_list_columns - -from .links import comment_add, comment_delete, comments_for_document -from .permissions import ( - PERMISSION_COMMENT_CREATE, PERMISSION_COMMENT_DELETE, - PERMISSION_COMMENT_VIEW -) - - -Document.add_to_class( - 'comments', - generic.GenericRelation( - Comment, - content_type_field='content_type', - object_id_field='object_pk' - ) -) - -class_permissions(Document, [PERMISSION_COMMENT_CREATE, - PERMISSION_COMMENT_DELETE, - PERMISSION_COMMENT_VIEW]) - -register_model_list_columns(Comment, [ - { - 'name': _('Date'), - 'attribute': 'submit_date' - }, - { - 'name': _('User'), - 'attribute': encapsulate(lambda x: x.user.get_full_name() if x.user.get_full_name() else x.user) - }, - { - 'name': _('Comment'), - 'attribute': 'comment' - } -]) - -register_links(['comments:comments_for_document', 'comments:comment_add', 'comments:comment_delete', 'comments:comment_multiple_delete'], [comment_add], menu_name='sidebar') -register_links(Comment, [comment_delete]) -register_links(Document, [comments_for_document], menu_name='form_header') - -ModelAttribute(Document, label=_('Comments'), name='comments', type_name='related') diff --git a/mayan/apps/document_comments/apps.py b/mayan/apps/document_comments/apps.py new file mode 100644 index 0000000000..d9d7ef0cf2 --- /dev/null +++ b/mayan/apps/document_comments/apps.py @@ -0,0 +1,57 @@ +from __future__ import absolute_import, unicode_literals + +from django import apps +from django.contrib.comments.models import Comment +from django.contrib.contenttypes import generic +from django.utils.translation import ugettext_lazy as _ + +from acls.api import class_permissions +from common.classes import ModelAttribute +from common.utils import encapsulate +from documents.models import Document +from navigation.api import register_links, register_model_list_columns + +from .links import comment_add, comment_delete, comments_for_document +from .permissions import ( + PERMISSION_COMMENT_CREATE, PERMISSION_COMMENT_DELETE, + PERMISSION_COMMENT_VIEW +) + +class DocumentCommentsApp(apps.AppConfig): + name = 'document_comments' + verbose_name = _('Document comments') + + def ready(self): + Document.add_to_class( + 'comments', + generic.GenericRelation( + Comment, + content_type_field='content_type', + object_id_field='object_pk' + ) + ) + + class_permissions(Document, [PERMISSION_COMMENT_CREATE, + PERMISSION_COMMENT_DELETE, + PERMISSION_COMMENT_VIEW]) + + register_model_list_columns(Comment, [ + { + 'name': _('Date'), + 'attribute': 'submit_date' + }, + { + 'name': _('User'), + 'attribute': encapsulate(lambda x: x.user.get_full_name() if x.user.get_full_name() else x.user) + }, + { + 'name': _('Comment'), + 'attribute': 'comment' + } + ]) + + register_links(['comments:comments_for_document', 'comments:comment_add', 'comments:comment_delete', 'comments:comment_multiple_delete'], [comment_add], menu_name='sidebar') + register_links(Comment, [comment_delete]) + register_links(Document, [comments_for_document], menu_name='form_header') + + ModelAttribute(Document, label=_('Comments'), name='comments', type_name='related') diff --git a/mayan/apps/document_comments/forms.py b/mayan/apps/document_comments/forms.py index 0d4d0f6d01..064f59d9ad 100644 --- a/mayan/apps/document_comments/forms.py +++ b/mayan/apps/document_comments/forms.py @@ -9,5 +9,5 @@ class CommentForm(forms.ModelForm): A standard model form to allow users to post a comment """ class Meta: - model = Comment fields = ('comment',) + model = Comment diff --git a/mayan/apps/document_indexing/__init__.py b/mayan/apps/document_indexing/__init__.py index 1268d71201..8b13789179 100644 --- a/mayan/apps/document_indexing/__init__.py +++ b/mayan/apps/document_indexing/__init__.py @@ -1,52 +1 @@ -from __future__ import absolute_import, unicode_literals -from django.db.models.signals import post_save, post_delete -from django.dispatch import receiver -from django.utils.translation import ugettext_lazy as _ - -from documents.models import Document -from main.api import register_maintenance_links -from metadata.models import DocumentMetadata -from navigation.api import register_links, register_top_menu -from project_setup.api import register_setup -from rest_api.classes import APIEndPoint - -from .links import ( - document_index_list, document_index_main_menu_link, index_parent, - index_setup, index_setup_create, index_setup_document_types, - index_setup_delete, index_setup_edit, index_setup_list, index_setup_view, - rebuild_index_instances, template_node_create, template_node_delete, - template_node_edit -) -from .models import Index, IndexTemplateNode, IndexInstanceNode -from .tasks import task_delete_empty_index_nodes, task_index_document - - -@receiver(post_delete, dispatch_uid='document_index_delete', sender=Document) -def document_index_delete(sender, **kwargs): - task_delete_empty_index_nodes.apply_async(queue='indexing') - - -@receiver(post_save, dispatch_uid='document_metadata_index_update', sender=DocumentMetadata) -def document_metadata_index_update(sender, **kwargs): - task_index_document.apply_async(kwargs=dict(document_id=kwargs['instance'].document.pk), queue='indexing') - - -@receiver(post_delete, dispatch_uid='document_metadata_index_post_delete', sender=DocumentMetadata) -def document_metadata_index_post_delete(sender, **kwargs): - task_index_document.apply_async(kwargs=dict(document_id=kwargs['instance'].document.pk), queue='indexing') - - -register_maintenance_links([rebuild_index_instances], namespace='document_indexing', title=_('Indexes')) - -register_links(Document, [document_index_list], menu_name='form_header') -register_links([Index, 'indexing:index_setup_list', 'indexing:index_setup_create'], [index_setup_list, index_setup_create], menu_name='secondary_menu') -register_links(Index, [index_setup_edit, index_setup_view, index_setup_document_types, index_setup_delete]) -register_links(IndexInstanceNode, [index_parent]) -register_links(IndexTemplateNode, [template_node_create, template_node_edit, template_node_delete]) - -register_setup(index_setup) - -register_top_menu('indexes', document_index_main_menu_link) - -APIEndPoint('indexes', app_name='document_indexing') diff --git a/mayan/apps/document_indexing/apps.py b/mayan/apps/document_indexing/apps.py new file mode 100644 index 0000000000..b72a2747a2 --- /dev/null +++ b/mayan/apps/document_indexing/apps.py @@ -0,0 +1,58 @@ +from __future__ import absolute_import, unicode_literals + +from django import apps +from django.db.models.signals import post_save, post_delete +from django.utils.translation import ugettext_lazy as _ + +from documents.models import Document +from main.api import register_maintenance_links +from metadata.models import DocumentMetadata +from navigation.api import register_links, register_top_menu +from project_setup.api import register_setup +from rest_api.classes import APIEndPoint + +from .links import ( + document_index_list, document_index_main_menu_link, index_parent, + index_setup, index_setup_create, index_setup_document_types, + index_setup_delete, index_setup_edit, index_setup_list, index_setup_view, + rebuild_index_instances, template_node_create, template_node_delete, + template_node_edit +) +from .models import Index, IndexTemplateNode, IndexInstanceNode +from .tasks import task_delete_empty_index_nodes, task_index_document + + +def document_index_delete(sender, **kwargs): + task_delete_empty_index_nodes.apply_async(queue='indexing') + + +def document_metadata_index_update(sender, **kwargs): + task_index_document.apply_async(kwargs=dict(document_id=kwargs['instance'].document.pk), queue='indexing') + + +def document_metadata_index_post_delete(sender, **kwargs): + task_index_document.apply_async(kwargs=dict(document_id=kwargs['instance'].document.pk), queue='indexing') + + +class DocumentIndexingApp(apps.AppConfig): + name = 'document_indexing' + verbose_name = _('Document indexing') + + def ready(self): + post_delete.connect(document_index_delete, dispatch_uid='document_index_delete', sender=Document) + post_save.connect(document_metadata_index_update, dispatch_uid='document_metadata_index_update', sender=DocumentMetadata) + post_delete.connect(document_metadata_index_post_delete, dispatch_uid='document_metadata_index_post_delete', sender=DocumentMetadata) + + register_maintenance_links([rebuild_index_instances], namespace='document_indexing', title=_('Indexes')) + + register_links(Document, [document_index_list], menu_name='form_header') + register_links([Index, 'indexing:index_setup_list', 'indexing:index_setup_create'], [index_setup_list, index_setup_create], menu_name='secondary_menu') + register_links(Index, [index_setup_edit, index_setup_view, index_setup_document_types, index_setup_delete]) + register_links(IndexInstanceNode, [index_parent]) + register_links(IndexTemplateNode, [template_node_create, template_node_edit, template_node_delete]) + + register_setup(index_setup) + + register_top_menu('indexes', document_index_main_menu_link) + + APIEndPoint('indexes', app_name='document_indexing') diff --git a/mayan/apps/document_signatures/__init__.py b/mayan/apps/document_signatures/__init__.py index 70650a4dd8..8b13789179 100644 --- a/mayan/apps/document_signatures/__init__.py +++ b/mayan/apps/document_signatures/__init__.py @@ -1,64 +1 @@ -from __future__ import unicode_literals -import logging - -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - -from acls.api import class_permissions -from django_gpg.exceptions import GPGDecryptionError -from django_gpg.runtime import gpg -from documents.models import Document, DocumentVersion -from navigation.api import register_links - -from .links import ( - document_signature_delete, document_signature_download, - document_signature_upload, document_verify -) -from .models import DocumentVersionSignature -from .permissions import ( - PERMISSION_DOCUMENT_VERIFY, PERMISSION_SIGNATURE_DELETE, - PERMISSION_SIGNATURE_DOWNLOAD, PERMISSION_SIGNATURE_UPLOAD -) - -logger = logging.getLogger(__name__) - - -def document_pre_open_hook(descriptor, instance): - if DocumentVersionSignature.objects.has_embedded_signature(instance.document): - # If it has an embedded signature decrypt - try: - result = gpg.decrypt_file(descriptor, close_descriptor=False) - # gpg return a string, turn it into a file like object - except GPGDecryptionError: - # At least return the original raw content - descriptor.seek(0) - return descriptor - else: - descriptor.close() - return StringIO(result.data) - else: - return descriptor - - -def document_post_save_hook(instance): - if not instance.pk: - document_signature, created = DocumentVersionSignature.objects.get_or_create( - document_version=instance.latest_version, - ) - - -register_links(Document, [document_verify], menu_name='form_header') -register_links(['signatures:document_verify', 'signatures:document_signature_upload', 'signatures:document_signature_download', 'signatures:document_signature_delete'], [document_signature_upload, document_signature_download, document_signature_delete], menu_name='sidebar') - -DocumentVersion.register_pre_open_hook(1, document_pre_open_hook) -DocumentVersion.register_post_save_hook(1, document_post_save_hook) - -class_permissions(Document, [ - PERMISSION_DOCUMENT_VERIFY, - PERMISSION_SIGNATURE_DELETE, - PERMISSION_SIGNATURE_DOWNLOAD, - PERMISSION_SIGNATURE_UPLOAD, -]) diff --git a/mayan/apps/document_signatures/apps.py b/mayan/apps/document_signatures/apps.py new file mode 100644 index 0000000000..ded4b80fe6 --- /dev/null +++ b/mayan/apps/document_signatures/apps.py @@ -0,0 +1,72 @@ +from __future__ import unicode_literals + +import logging + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from acls.api import class_permissions +from django_gpg.exceptions import GPGDecryptionError +from django_gpg.runtime import gpg +from documents.models import Document, DocumentVersion +from navigation.api import register_links + +from .links import ( + document_signature_delete, document_signature_download, + document_signature_upload, document_verify +) +from .models import DocumentVersionSignature +from .permissions import ( + PERMISSION_DOCUMENT_VERIFY, PERMISSION_SIGNATURE_DELETE, + PERMISSION_SIGNATURE_DOWNLOAD, PERMISSION_SIGNATURE_UPLOAD +) + +logger = logging.getLogger(__name__) + + +def document_pre_open_hook(descriptor, instance): + if DocumentVersionSignature.objects.has_embedded_signature(instance.document): + # If it has an embedded signature decrypt + try: + result = gpg.decrypt_file(descriptor, close_descriptor=False) + # gpg return a string, turn it into a file like object + except GPGDecryptionError: + # At least return the original raw content + descriptor.seek(0) + return descriptor + else: + descriptor.close() + return StringIO(result.data) + else: + return descriptor + + +def document_post_save_hook(instance): + if not instance.pk: + document_signature, created = DocumentVersionSignature.objects.get_or_create( + document_version=instance.latest_version, + ) + + +class DocumentSignaturesApp(apps.AppConfig): + name = 'document_signatures' + verbose_name = _('Document signatures') + + def ready(self): + register_links(Document, [document_verify], menu_name='form_header') + register_links(['signatures:document_verify', 'signatures:document_signature_upload', 'signatures:document_signature_download', 'signatures:document_signature_delete'], [document_signature_upload, document_signature_download, document_signature_delete], menu_name='sidebar') + + DocumentVersion.register_pre_open_hook(1, document_pre_open_hook) + DocumentVersion.register_post_save_hook(1, document_post_save_hook) + + class_permissions(Document, [ + PERMISSION_DOCUMENT_VERIFY, + PERMISSION_SIGNATURE_DELETE, + PERMISSION_SIGNATURE_DOWNLOAD, + PERMISSION_SIGNATURE_UPLOAD, + ]) diff --git a/mayan/apps/document_states/__init__.py b/mayan/apps/document_states/__init__.py index 99962fb99c..8b13789179 100644 --- a/mayan/apps/document_states/__init__.py +++ b/mayan/apps/document_states/__init__.py @@ -1,105 +1 @@ -from __future__ import unicode_literals -from django.db.models.signals import post_save -from django.dispatch import receiver -from django.utils.translation import ugettext_lazy as _ - -from common.utils import encapsulate -from documents.models import Document -from navigation.api import register_links, register_model_list_columns -from project_setup.api import register_setup - -from .models import ( - Workflow, WorkflowInstance, WorkflowInstanceLogEntry, WorkflowState, - WorkflowTransition -) -from .links import ( - link_document_workflow_instance_list, link_setup_workflow_document_types, - link_setup_workflow_create, link_setup_workflow_delete, - link_setup_workflow_edit, link_setup_workflow_list, - link_setup_workflow_states, link_setup_workflow_state_create, - link_setup_workflow_state_delete, link_setup_workflow_state_edit, - link_setup_workflow_transitions, link_setup_workflow_transition_create, - link_setup_workflow_transition_delete, link_setup_workflow_transition_edit, - link_workflow_instance_detail, link_workflow_instance_transition -) - - -@receiver(post_save, dispatch_uid='launch_workflow', sender=Document) -def launch_workflow(sender, instance, created, **kwargs): - if created: - Workflow.objects.launch_for(instance) - - -register_setup(link_setup_workflow_list) - -register_model_list_columns(Workflow, [ - { - 'name': _('Initial state'), - 'attribute': encapsulate(lambda workflow: workflow.get_initial_state() or _('None')) - }, -]) - -register_model_list_columns(WorkflowState, [ - { - 'name': _('Is initial state?'), - 'attribute': 'initial' - }, -]) - -register_model_list_columns(WorkflowInstance, [ - { - 'name': _('Current state'), - 'attribute': 'get_current_state' - }, - { - 'name': _('User'), - 'attribute': encapsulate(lambda workflow: getattr(workflow.get_last_log_entry(), 'user', _('None'))) - }, - { - 'name': _('Last transition'), - 'attribute': 'get_last_transition' - }, - { - 'name': _('Date and time'), - 'attribute': encapsulate(lambda workflow: getattr(workflow.get_last_log_entry(), 'datetime', _('None'))) - }, -]) - -register_model_list_columns(WorkflowTransition, [ - { - 'name': _('Origin state'), - 'attribute': 'origin_state' - }, - { - 'name': _('Destination state'), - 'attribute': 'destination_state' - }, -]) - -register_model_list_columns(WorkflowInstanceLogEntry, [ - { - 'name': _('Date and time'), - 'attribute': 'datetime' - }, - { - 'name': _('User'), - 'attribute': 'user' - }, - { - 'name': _('Transition'), - 'attribute': 'transition' - }, - { - 'name': _('Comment'), - 'attribute': 'comment' - }, -]) - -register_links([Document], [link_document_workflow_instance_list], menu_name='form_header') -register_links([WorkflowInstance], [link_workflow_instance_detail, link_workflow_instance_transition]) -register_links([Workflow, 'document_states:setup_workflow_create', 'document_states:setup_workflow_list'], [link_setup_workflow_list, link_setup_workflow_create], menu_name='secondary_menu') -register_links([Workflow], [link_setup_workflow_states, link_setup_workflow_transitions, link_setup_workflow_document_types, link_setup_workflow_edit, link_setup_workflow_delete]) -register_links([Workflow], [link_setup_workflow_state_create, link_setup_workflow_transition_create], menu_name='sidebar') -register_links([WorkflowState], [link_setup_workflow_state_edit, link_setup_workflow_state_delete]) -register_links([WorkflowTransition], [link_setup_workflow_transition_edit, link_setup_workflow_transition_delete]) diff --git a/mayan/apps/document_states/apps.py b/mayan/apps/document_states/apps.py new file mode 100644 index 0000000000..cd7d569d37 --- /dev/null +++ b/mayan/apps/document_states/apps.py @@ -0,0 +1,111 @@ +from __future__ import unicode_literals + +from django import apps +from django.db.models.signals import post_save +from django.utils.translation import ugettext_lazy as _ + +from common.utils import encapsulate +from documents.models import Document +from navigation.api import register_links, register_model_list_columns +from project_setup.api import register_setup + +from .models import ( + Workflow, WorkflowInstance, WorkflowInstanceLogEntry, WorkflowState, + WorkflowTransition +) +from .links import ( + link_document_workflow_instance_list, link_setup_workflow_document_types, + link_setup_workflow_create, link_setup_workflow_delete, + link_setup_workflow_edit, link_setup_workflow_list, + link_setup_workflow_states, link_setup_workflow_state_create, + link_setup_workflow_state_delete, link_setup_workflow_state_edit, + link_setup_workflow_transitions, link_setup_workflow_transition_create, + link_setup_workflow_transition_delete, link_setup_workflow_transition_edit, + link_workflow_instance_detail, link_workflow_instance_transition +) + + +def launch_workflow(sender, instance, created, **kwargs): + if created: + Workflow.objects.launch_for(instance) + + +class DocumentStatesApp(apps.AppConfig): + name = 'document_states' + verbose_name = _('Document states') + + def ready(self): + post_save.connect(launch_workflow, dispatch_uid='launch_workflow', sender=Document) + + register_setup(link_setup_workflow_list) + + register_model_list_columns(Workflow, [ + { + 'name': _('Initial state'), + 'attribute': encapsulate(lambda workflow: workflow.get_initial_state() or _('None')) + }, + ]) + + register_model_list_columns(WorkflowState, [ + { + 'name': _('Is initial state?'), + 'attribute': 'initial' + }, + ]) + + register_model_list_columns(WorkflowInstance, [ + { + 'name': _('Current state'), + 'attribute': 'get_current_state' + }, + { + 'name': _('User'), + 'attribute': encapsulate(lambda workflow: getattr(workflow.get_last_log_entry(), 'user', _('None'))) + }, + { + 'name': _('Last transition'), + 'attribute': 'get_last_transition' + }, + { + 'name': _('Date and time'), + 'attribute': encapsulate(lambda workflow: getattr(workflow.get_last_log_entry(), 'datetime', _('None'))) + }, + ]) + + register_model_list_columns(WorkflowTransition, [ + { + 'name': _('Origin state'), + 'attribute': 'origin_state' + }, + { + 'name': _('Destination state'), + 'attribute': 'destination_state' + }, + ]) + + register_model_list_columns(WorkflowInstanceLogEntry, [ + { + 'name': _('Date and time'), + 'attribute': 'datetime' + }, + { + 'name': _('User'), + 'attribute': 'user' + }, + { + 'name': _('Transition'), + 'attribute': 'transition' + }, + { + 'name': _('Comment'), + 'attribute': 'comment' + }, + ]) + + register_links([Document], [link_document_workflow_instance_list], menu_name='form_header') + register_links([WorkflowInstance], [link_workflow_instance_detail, link_workflow_instance_transition]) + register_links([Workflow, 'document_states:setup_workflow_create', 'document_states:setup_workflow_list'], [link_setup_workflow_list, link_setup_workflow_create], menu_name='secondary_menu') + register_links([Workflow], [link_setup_workflow_states, link_setup_workflow_transitions, link_setup_workflow_document_types, link_setup_workflow_edit, link_setup_workflow_delete]) + register_links([Workflow], [link_setup_workflow_state_create, link_setup_workflow_transition_create], menu_name='sidebar') + register_links([WorkflowState], [link_setup_workflow_state_edit, link_setup_workflow_state_delete]) + register_links([WorkflowTransition], [link_setup_workflow_transition_edit, link_setup_workflow_transition_delete]) diff --git a/mayan/apps/documents/__init__.py b/mayan/apps/documents/__init__.py index f97ed0eeae..e69de29bb2 100644 --- a/mayan/apps/documents/__init__.py +++ b/mayan/apps/documents/__init__.py @@ -1,140 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import tempfile - -from django.utils.translation import ugettext_lazy as _ - -from acls.api import class_permissions -from common.classes import ModelAttribute -from common.utils import encapsulate, validate_path -from dynamic_search.classes import SearchModel -from events.permissions import PERMISSION_EVENTS_VIEW -from main import FrontPageButton -from main.api import register_maintenance_links -from navigation.api import register_links, register_model_list_columns -from navigation.links import link_spacer -from project_setup.api import register_setup -from rest_api.classes import APIEndPoint -from statistics.classes import StatisticNamespace - -from documents import settings as document_settings -from .links import ( - document_clear_image_cache, document_clear_transformations, - document_content, document_delete, document_document_type_edit, - document_events_view, document_multiple_document_type_edit, - document_download, document_edit, document_list, document_list_recent, - document_multiple_delete, document_multiple_clear_transformations, - document_multiple_download, document_multiple_update_page_count, - document_page_edit, document_page_navigation_first, - document_page_navigation_last, document_page_navigation_next, - document_page_navigation_previous, document_page_rotate_left, - document_page_rotate_right, document_page_text, - document_page_transformation_list, document_page_transformation_create, - document_page_transformation_edit, document_page_transformation_delete, - document_page_view, document_page_view_reset, document_page_zoom_in, - document_page_zoom_out, document_preview, document_print, - document_properties, document_type_create, document_type_delete, - document_type_edit, document_type_filename_create, - document_type_filename_delete, document_type_filename_edit, - document_type_filename_list, document_type_list, document_type_setup, - document_update_page_count, document_version_download, - document_version_list, document_version_revert -) -from .models import ( - Document, DocumentPage, DocumentPageTransformation, DocumentType, - DocumentTypeFilename, DocumentVersion -) -from .permissions import ( - PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, - PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_NEW_VERSION, - PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_TRANSFORM, - PERMISSION_DOCUMENT_VERSION_REVERT, PERMISSION_DOCUMENT_VIEW -) -from .settings import THUMBNAIL_SIZE -from .statistics import DocumentStatistics, DocumentUsageStatistics -from .widgets import document_thumbnail - -# Register document type links -register_links(DocumentType, [document_type_edit, document_type_filename_list, document_type_delete]) -register_links([DocumentType, 'documents:document_type_create', 'documents:document_type_list'], [document_type_list, document_type_create], menu_name='secondary_menu') -register_links(DocumentTypeFilename, [document_type_filename_edit, document_type_filename_delete]) -register_links([DocumentTypeFilename, 'documents:document_type_filename_list', 'documents:document_type_filename_create'], [document_type_filename_create], menu_name='sidebar') - -# Register document links -register_links(Document, [document_edit, document_document_type_edit, document_print, document_delete, document_download, document_clear_transformations, document_update_page_count]) -register_links([Document], [document_multiple_clear_transformations, document_multiple_delete, document_multiple_download, document_multiple_update_page_count, document_multiple_document_type_edit, link_spacer], menu_name='multi_item_links') -register_links(Document, [document_preview], menu_name='form_header', position=0) -register_links(Document, [document_content], menu_name='form_header', position=1) -register_links(Document, [document_properties], menu_name='form_header', position=2) -register_links(Document, [document_events_view, document_version_list], menu_name='form_header') - -# Document Version links -register_links(DocumentVersion, [document_version_revert, document_version_download]) -register_links(['documents:document_list_recent', 'documents:document_list'], [document_list_recent, document_list], menu_name='secondary_menu') -register_links(Document, [document_list_recent, document_list], menu_name='secondary_menu') - -# Document page links -register_links(DocumentPage, [ - document_page_transformation_list, document_page_view, - document_page_text, document_page_edit, -]) - -# Document page navigation links -register_links(DocumentPage, [ - document_page_navigation_first, document_page_navigation_previous, - document_page_navigation_next, document_page_navigation_last -], menu_name='sidebar') - -register_links(['documents:document_page_view'], [document_page_rotate_left, document_page_rotate_right, document_page_zoom_in, document_page_zoom_out, document_page_view_reset], menu_name='form_header') -register_links(DocumentPageTransformation, [document_page_transformation_edit, document_page_transformation_delete]) -register_links('documents:document_page_transformation_list', [document_page_transformation_create], menu_name='sidebar') -register_links('documents:document_page_transformation_create', [document_page_transformation_create], menu_name='sidebar') -register_links(['documents:document_page_transformation_edit', 'documents:document_page_transformation_delete'], [document_page_transformation_create], menu_name='sidebar') - -register_maintenance_links([document_clear_image_cache], namespace='documents', title=_('Documents')) -register_model_list_columns(Document, [ - { - 'name': _('Thumbnail'), 'attribute': - encapsulate(lambda x: document_thumbnail(x, gallery_name='documents:document_list', title=getattr(x, 'filename', None), size=THUMBNAIL_SIZE)) - }, - { - 'name': _('Type'), 'attribute': 'document_type' - } -]) - -if (not validate_path(document_settings.CACHE_PATH)) or (not document_settings.CACHE_PATH): - setattr(document_settings, 'CACHE_PATH', tempfile.mkdtemp()) - -register_setup(document_type_setup) - -class_permissions(Document, [ - PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, - PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_NEW_VERSION, - PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_TRANSFORM, - PERMISSION_DOCUMENT_VERSION_REVERT, PERMISSION_DOCUMENT_VIEW, - PERMISSION_EVENTS_VIEW -]) - -document_search = SearchModel('documents', 'Document', permission=PERMISSION_DOCUMENT_VIEW, serializer_string='documents.serializers.DocumentSerializer') - -# TODO: move these to their respective apps -# Moving these to other apps cause an ImportError; circular import? -document_search.add_model_field('document_type__name', label=_('Document type')) -document_search.add_model_field('versions__mimetype', label=_('MIME type')) -document_search.add_model_field('label', label=_('Label')) -document_search.add_model_field('metadata__metadata_type__name', label=_('Metadata type')) -document_search.add_model_field('metadata__value', label=_('Metadata value')) -document_search.add_model_field('versions__pages__content', label=_('Content')) -document_search.add_model_field('description', label=_('Description')) -document_search.add_model_field('tags__label', label=_('Tags')) - -namespace = StatisticNamespace(name='documents', label=_('Documents')) -namespace.add_statistic(DocumentStatistics(name='document_stats', label=_('Document tendencies'))) -namespace.add_statistic(DocumentUsageStatistics(name='document_usage', label=_('Document usage'))) - -APIEndPoint('documents') - -ModelAttribute(Document, label=_('Label'), name='label', type_name='field') - -FrontPageButton(link=document_list_recent) -FrontPageButton(link=document_list) diff --git a/mayan/apps/documents/apps.py b/mayan/apps/documents/apps.py new file mode 100644 index 0000000000..4ace383b8a --- /dev/null +++ b/mayan/apps/documents/apps.py @@ -0,0 +1,151 @@ +from __future__ import absolute_import, unicode_literals + +import tempfile + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from actstream import registry + +from acls.api import class_permissions +from common.classes import ModelAttribute +from common.utils import encapsulate, validate_path +from dynamic_search.classes import SearchModel +from events.permissions import PERMISSION_EVENTS_VIEW +from main import FrontPageButton +from main.api import register_maintenance_links +from navigation.api import register_links, register_model_list_columns +from navigation.links import link_spacer +from project_setup.api import register_setup +from rest_api.classes import APIEndPoint +from statistics.classes import StatisticNamespace + +from documents import settings as document_settings +from .links import ( + document_clear_image_cache, document_clear_transformations, + document_content, document_delete, document_document_type_edit, + document_events_view, document_multiple_document_type_edit, + document_download, document_edit, document_list, document_list_recent, + document_multiple_delete, document_multiple_clear_transformations, + document_multiple_download, document_multiple_update_page_count, + document_page_edit, document_page_navigation_first, + document_page_navigation_last, document_page_navigation_next, + document_page_navigation_previous, document_page_rotate_left, + document_page_rotate_right, document_page_text, + document_page_transformation_list, document_page_transformation_create, + document_page_transformation_edit, document_page_transformation_delete, + document_page_view, document_page_view_reset, document_page_zoom_in, + document_page_zoom_out, document_preview, document_print, + document_properties, document_type_create, document_type_delete, + document_type_edit, document_type_filename_create, + document_type_filename_delete, document_type_filename_edit, + document_type_filename_list, document_type_list, document_type_setup, + document_update_page_count, document_version_download, + document_version_list, document_version_revert +) +from .models import ( + Document, DocumentPage, DocumentPageTransformation, DocumentType, + DocumentTypeFilename, DocumentVersion +) +from .permissions import ( + PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, + PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_NEW_VERSION, + PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_TRANSFORM, + PERMISSION_DOCUMENT_VERSION_REVERT, PERMISSION_DOCUMENT_VIEW +) +from .settings import THUMBNAIL_SIZE +from .statistics import DocumentStatistics, DocumentUsageStatistics +from .widgets import document_thumbnail + + +class DocumentsApp(apps.AppConfig): + name = 'documents' + verbose_name = _('Documents') + + def ready(self): + # Register document type links + register_links(DocumentType, [document_type_edit, document_type_filename_list, document_type_delete]) + register_links([DocumentType, 'documents:document_type_create', 'documents:document_type_list'], [document_type_list, document_type_create], menu_name='secondary_menu') + register_links(DocumentTypeFilename, [document_type_filename_edit, document_type_filename_delete]) + register_links([DocumentTypeFilename, 'documents:document_type_filename_list', 'documents:document_type_filename_create'], [document_type_filename_create], menu_name='sidebar') + + # Register document links + register_links(Document, [document_edit, document_document_type_edit, document_print, document_delete, document_download, document_clear_transformations, document_update_page_count]) + register_links([Document], [document_multiple_clear_transformations, document_multiple_delete, document_multiple_download, document_multiple_update_page_count, document_multiple_document_type_edit, link_spacer], menu_name='multi_item_links') + register_links(Document, [document_preview], menu_name='form_header', position=0) + register_links(Document, [document_content], menu_name='form_header', position=1) + register_links(Document, [document_properties], menu_name='form_header', position=2) + register_links(Document, [document_events_view, document_version_list], menu_name='form_header') + + # Document Version links + register_links(DocumentVersion, [document_version_revert, document_version_download]) + register_links(['documents:document_list_recent', 'documents:document_list'], [document_list_recent, document_list], menu_name='secondary_menu') + register_links(Document, [document_list_recent, document_list], menu_name='secondary_menu') + + # Document page links + register_links(DocumentPage, [ + document_page_transformation_list, document_page_view, + document_page_text, document_page_edit, + ]) + + # Document page navigation links + register_links(DocumentPage, [ + document_page_navigation_first, document_page_navigation_previous, + document_page_navigation_next, document_page_navigation_last + ], menu_name='sidebar') + + register_links(['documents:document_page_view'], [document_page_rotate_left, document_page_rotate_right, document_page_zoom_in, document_page_zoom_out, document_page_view_reset], menu_name='form_header') + register_links(DocumentPageTransformation, [document_page_transformation_edit, document_page_transformation_delete]) + register_links('documents:document_page_transformation_list', [document_page_transformation_create], menu_name='sidebar') + register_links('documents:document_page_transformation_create', [document_page_transformation_create], menu_name='sidebar') + register_links(['documents:document_page_transformation_edit', 'documents:document_page_transformation_delete'], [document_page_transformation_create], menu_name='sidebar') + + register_maintenance_links([document_clear_image_cache], namespace='documents', title=_('Documents')) + register_model_list_columns(Document, [ + { + 'name': _('Thumbnail'), 'attribute': + encapsulate(lambda x: document_thumbnail(x, gallery_name='documents:document_list', title=getattr(x, 'filename', None), size=THUMBNAIL_SIZE)) + }, + { + 'name': _('Type'), 'attribute': 'document_type' + } + ]) + + if (not validate_path(document_settings.CACHE_PATH)) or (not document_settings.CACHE_PATH): + setattr(document_settings, 'CACHE_PATH', tempfile.mkdtemp()) + + register_setup(document_type_setup) + + class_permissions(Document, [ + PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, + PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_NEW_VERSION, + PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_TRANSFORM, + PERMISSION_DOCUMENT_VERSION_REVERT, PERMISSION_DOCUMENT_VIEW, + PERMISSION_EVENTS_VIEW + ]) + + document_search = SearchModel('documents', 'Document', permission=PERMISSION_DOCUMENT_VIEW, serializer_string='documents.serializers.DocumentSerializer') + + # TODO: move these to their respective apps + # Moving these to other apps cause an ImportError; circular import? + document_search.add_model_field('document_type__name', label=_('Document type')) + document_search.add_model_field('versions__mimetype', label=_('MIME type')) + document_search.add_model_field('label', label=_('Label')) + document_search.add_model_field('metadata__metadata_type__name', label=_('Metadata type')) + document_search.add_model_field('metadata__value', label=_('Metadata value')) + document_search.add_model_field('versions__pages__content', label=_('Content')) + document_search.add_model_field('description', label=_('Description')) + document_search.add_model_field('tags__label', label=_('Tags')) + + namespace = StatisticNamespace(name='documents', label=_('Documents')) + namespace.add_statistic(DocumentStatistics(name='document_stats', label=_('Document tendencies'))) + namespace.add_statistic(DocumentUsageStatistics(name='document_usage', label=_('Document usage'))) + + APIEndPoint('documents') + + ModelAttribute(Document, label=_('Label'), name='label', type_name='field') + + FrontPageButton(link=document_list_recent) + FrontPageButton(link=document_list) + + registry.register(Document) diff --git a/mayan/apps/documents/forms.py b/mayan/apps/documents/forms.py index e1a67e4619..8fa7452b52 100644 --- a/mayan/apps/documents/forms.py +++ b/mayan/apps/documents/forms.py @@ -20,6 +20,7 @@ from .widgets import DocumentPagesCarouselWidget, DocumentPageImageWidget # Document page forms class DocumentPageTransformationForm(forms.ModelForm): class Meta: + fields = ('order', 'transformation', 'arguments') model = DocumentPageTransformation def __init__(self, *args, **kwargs): @@ -29,8 +30,8 @@ class DocumentPageTransformationForm(forms.ModelForm): class DocumentPageForm(DetailForm): class Meta: - model = DocumentPage fields = () + model = DocumentPage def __init__(self, *args, **kwargs): zoom = kwargs.pop('zoom', 100) @@ -49,8 +50,8 @@ class DocumentPageForm(DetailForm): class DocumentPageForm_text(DetailForm): class Meta: - model = DocumentPage fields = ('page_label', 'content') + model = DocumentPage content = forms.CharField( label=_('Contents'), @@ -61,8 +62,8 @@ class DocumentPageForm_text(DetailForm): class DocumentPageForm_edit(forms.ModelForm): class Meta: - model = DocumentPage fields = ('page_label', 'content') + model = DocumentPage def __init__(self, *args, **kwargs): super(DocumentPageForm_edit, self).__init__(*args, **kwargs) @@ -123,8 +124,8 @@ class DocumentPropertiesForm(DetailForm): Detail class form to display a document file based properties """ class Meta: - model = Document fields = ('document_type', 'description', 'language') + model = Document class DocumentContentForm(forms.Form): @@ -172,6 +173,7 @@ class DocumentTypeForm(forms.ModelForm): Model class form to create or edit a document type """ class Meta: + fields = ('name', 'ocr') model = DocumentType @@ -180,8 +182,8 @@ class DocumentTypeFilenameForm(forms.ModelForm): Model class form to edit a document type filename """ class Meta: - model = DocumentTypeFilename fields = ('filename', 'enabled') + model = DocumentTypeFilename class DocumentTypeFilenameForm_create(forms.ModelForm): @@ -189,8 +191,8 @@ class DocumentTypeFilenameForm_create(forms.ModelForm): Model class form to create a new document type filename """ class Meta: - model = DocumentTypeFilename fields = ('filename',) + model = DocumentTypeFilename class DocumentDownloadForm(forms.Form): diff --git a/mayan/apps/documents/models.py b/mayan/apps/documents/models.py index fbb74a9008..8d247aa9ed 100644 --- a/mayan/apps/documents/models.py +++ b/mayan/apps/documents/models.py @@ -14,8 +14,6 @@ from django.core.exceptions import ValidationError from django.utils.translation import ugettext from django.utils.translation import ugettext_lazy as _ -from actstream import registry - from acls.utils import apply_default_acls from common.settings import TEMPORARY_DIRECTORY from converter.api import ( @@ -585,5 +583,3 @@ class RecentDocument(models.Model): # Quick hack to break the DocumentPage and DocumentPageTransformation circular dependency # Can be remove once the transformations are moved to the converter app DocumentPage.add_to_class('get_transformation_list', lambda document_page: DocumentPageTransformation.objects.get_for_document_page_as_list(document_page)) - -registry.register(Document) diff --git a/mayan/apps/dynamic_search/__init__.py b/mayan/apps/dynamic_search/__init__.py index eec3135ea8..8b13789179 100644 --- a/mayan/apps/dynamic_search/__init__.py +++ b/mayan/apps/dynamic_search/__init__.py @@ -1,11 +1 @@ -from __future__ import unicode_literals -from navigation.api import register_links -from rest_api.classes import APIEndPoint - -from .links import search, search_advanced, search_again - -register_links(['search:search', 'search:search_advanced', 'search:results'], [search, search_advanced], menu_name='form_header') -register_links(['search:results'], [search_again], menu_name='sidebar') - -APIEndPoint('search', app_name='dynamic_search') diff --git a/mayan/apps/dynamic_search/apps.py b/mayan/apps/dynamic_search/apps.py new file mode 100644 index 0000000000..f5327a7ce2 --- /dev/null +++ b/mayan/apps/dynamic_search/apps.py @@ -0,0 +1,20 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from navigation.api import register_links +from rest_api.classes import APIEndPoint + +from .links import search, search_advanced, search_again + + +class DynamicSearchApp(apps.AppConfig): + name = 'dynamic_search' + verbose_name = _('Dynamic search') + + def ready(self): + register_links(['search:search', 'search:search_advanced', 'search:results'], [search, search_advanced], menu_name='form_header') + register_links(['search:results'], [search_again], menu_name='sidebar') + + APIEndPoint('search', app_name='dynamic_search') diff --git a/mayan/apps/events/__init__.py b/mayan/apps/events/__init__.py index f3e35f2e05..19ce5788d2 100644 --- a/mayan/apps/events/__init__.py +++ b/mayan/apps/events/__init__.py @@ -1,8 +1,2 @@ -from __future__ import unicode_literals - -from project_tools.api import register_tool - from .classes import Event # NOQA -from .links import events_list -register_tool(events_list) diff --git a/mayan/apps/events/apps.py b/mayan/apps/events/apps.py new file mode 100644 index 0000000000..1002a8936c --- /dev/null +++ b/mayan/apps/events/apps.py @@ -0,0 +1,16 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from project_tools.api import register_tool + +from .links import events_list + + +class EventsApp(apps.AppConfig): + name = 'events' + verbose_name = _('Events') + + def ready(self): + register_tool(events_list) diff --git a/mayan/apps/folders/__init__.py b/mayan/apps/folders/__init__.py index 0e6ccde80a..8b13789179 100644 --- a/mayan/apps/folders/__init__.py +++ b/mayan/apps/folders/__init__.py @@ -1,50 +1 @@ -from __future__ import unicode_literals -from django.utils.translation import ugettext_lazy as _ - -from acls.api import class_permissions -from acls.permissions import ACLS_EDIT_ACL, ACLS_VIEW_ACL -from common.utils import encapsulate -from documents.models import Document -from navigation.api import ( - register_links, register_model_list_columns, register_top_menu -) -from navigation.links import link_spacer -from rest_api.classes import APIEndPoint - -from .links import ( - document_folder_list, folder_acl_list, folder_add_document, - folder_add_multiple_documents, folder_create, folder_delete, - folder_document_multiple_remove, folder_edit, folder_list, folder_view, - folders_main_menu_link -) -from .models import Folder -from .permissions import ( - PERMISSION_FOLDER_ADD_DOCUMENT, PERMISSION_FOLDER_DELETE, - PERMISSION_FOLDER_EDIT, PERMISSION_FOLDER_REMOVE_DOCUMENT, - PERMISSION_FOLDER_VIEW -) - -register_links(Folder, [folder_view, folder_edit, folder_acl_list, folder_delete]) -register_links([Folder, 'folders:folder_list', 'folders:folder_create'], [folder_list, folder_create], menu_name='secondary_menu') -register_links(['folders:document_folder_list', 'folders:folder_add_document'], [folder_add_document], menu_name="sidebar") -register_links(Document, [document_folder_list], menu_name='form_header') -register_links([Document], [folder_add_multiple_documents, folder_document_multiple_remove, link_spacer], menu_name='multi_item_links') - -register_top_menu(name='folders', link=folders_main_menu_link) - -class_permissions(Folder, [ - ACLS_EDIT_ACL, ACLS_VIEW_ACL, PERMISSION_FOLDER_DELETE, - PERMISSION_FOLDER_EDIT, PERMISSION_FOLDER_VIEW -]) - -class_permissions(Document, [ - PERMISSION_FOLDER_ADD_DOCUMENT, PERMISSION_FOLDER_REMOVE_DOCUMENT -]) - -register_model_list_columns(Folder, [ - {'name': _('Created'), 'attribute': 'datetime_created'}, - {'name': _('Documents'), 'attribute': encapsulate(lambda x: x.documents.count())}, -]) - -APIEndPoint('folders') diff --git a/mayan/apps/folders/apps.py b/mayan/apps/folders/apps.py new file mode 100644 index 0000000000..33bc999aef --- /dev/null +++ b/mayan/apps/folders/apps.py @@ -0,0 +1,57 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from acls.api import class_permissions +from acls.permissions import ACLS_EDIT_ACL, ACLS_VIEW_ACL +from common.utils import encapsulate +from documents.models import Document +from navigation.api import ( + register_links, register_model_list_columns, register_top_menu +) +from navigation.links import link_spacer +from rest_api.classes import APIEndPoint + +from .links import ( + document_folder_list, folder_acl_list, folder_add_document, + folder_add_multiple_documents, folder_create, folder_delete, + folder_document_multiple_remove, folder_edit, folder_list, folder_view, + folders_main_menu_link +) +from .models import Folder +from .permissions import ( + PERMISSION_FOLDER_ADD_DOCUMENT, PERMISSION_FOLDER_DELETE, + PERMISSION_FOLDER_EDIT, PERMISSION_FOLDER_REMOVE_DOCUMENT, + PERMISSION_FOLDER_VIEW +) + + +class FoldersApp(apps.AppConfig): + name = 'folders' + verbose_name = _('Folders') + + def ready(self): + register_links(Folder, [folder_view, folder_edit, folder_acl_list, folder_delete]) + register_links([Folder, 'folders:folder_list', 'folders:folder_create'], [folder_list, folder_create], menu_name='secondary_menu') + register_links(['folders:document_folder_list', 'folders:folder_add_document'], [folder_add_document], menu_name="sidebar") + register_links(Document, [document_folder_list], menu_name='form_header') + register_links([Document], [folder_add_multiple_documents, folder_document_multiple_remove, link_spacer], menu_name='multi_item_links') + + register_top_menu(name='folders', link=folders_main_menu_link) + + class_permissions(Folder, [ + ACLS_EDIT_ACL, ACLS_VIEW_ACL, PERMISSION_FOLDER_DELETE, + PERMISSION_FOLDER_EDIT, PERMISSION_FOLDER_VIEW + ]) + + class_permissions(Document, [ + PERMISSION_FOLDER_ADD_DOCUMENT, PERMISSION_FOLDER_REMOVE_DOCUMENT + ]) + + register_model_list_columns(Folder, [ + {'name': _('Created'), 'attribute': 'datetime_created'}, + {'name': _('Documents'), 'attribute': encapsulate(lambda x: x.documents.count())}, + ]) + + APIEndPoint('folders') diff --git a/mayan/apps/installation/__init__.py b/mayan/apps/installation/__init__.py index d88d725880..8b13789179 100644 --- a/mayan/apps/installation/__init__.py +++ b/mayan/apps/installation/__init__.py @@ -1,48 +1 @@ -from __future__ import unicode_literals -from django.db.utils import DatabaseError -from django.dispatch import receiver -from django.utils.translation import ugettext_lazy as _ - -from south.signals import post_migrate - -from common.utils import encapsulate -from navigation.api import register_links, register_model_list_columns -from project_tools.api import register_tool - -from .classes import Property, PropertyNamespace -from .links import link_menu_link, link_namespace_details, link_namespace_list -from .models import Installation - - -@receiver(post_migrate, dispatch_uid='create_installation_instance') -def create_installation_instance(sender, **kwargs): - if kwargs['app'] == 'installation': - Installation.objects.get_or_create() - - -register_model_list_columns(PropertyNamespace, [ - { - 'name': _('Label'), - 'attribute': 'label' - }, - { - 'name': _('Items'), - 'attribute': encapsulate(lambda entry: len(entry.get_properties())) - } -]) - -register_model_list_columns(Property, [ - { - 'name': _('Label'), - 'attribute': 'label' - }, - { - 'name': _('Value'), - 'attribute': 'value' - } -]) - -register_links(PropertyNamespace, [link_namespace_details]) -register_links(['installation:namespace_list', PropertyNamespace], [link_namespace_list], menu_name='secondary_menu') -register_tool(link_menu_link) diff --git a/mayan/apps/installation/apps.py b/mayan/apps/installation/apps.py new file mode 100644 index 0000000000..7d2da50659 --- /dev/null +++ b/mayan/apps/installation/apps.py @@ -0,0 +1,54 @@ +from __future__ import unicode_literals + +from django import apps +from django.db.models.signals import post_migrate +from django.db.utils import DatabaseError +from django.dispatch import receiver +from django.utils.translation import ugettext_lazy as _ + +from common.utils import encapsulate +from navigation.api import register_links, register_model_list_columns +from project_tools.api import register_tool + +from .classes import Property, PropertyNamespace +from .links import link_menu_link, link_namespace_details, link_namespace_list +from .models import Installation + + +def create_installation_instance(sender, **kwargs): + if kwargs['app'] == 'installation': + Installation.objects.get_or_create() + + +class InstallationApp(apps.AppConfig): + name = 'installation' + verbose_name = _('Installation') + + def ready(self): + post_migrate.connect(create_installation_instance, dispatch_uid='create_installation_instance') + + register_model_list_columns(PropertyNamespace, [ + { + 'name': _('Label'), + 'attribute': 'label' + }, + { + 'name': _('Items'), + 'attribute': encapsulate(lambda entry: len(entry.get_properties())) + } + ]) + + register_model_list_columns(Property, [ + { + 'name': _('Label'), + 'attribute': 'label' + }, + { + 'name': _('Value'), + 'attribute': 'value' + } + ]) + + register_links(PropertyNamespace, [link_namespace_details]) + register_links(['installation:namespace_list', PropertyNamespace], [link_namespace_list], menu_name='secondary_menu') + register_tool(link_menu_link) diff --git a/mayan/apps/linking/__init__.py b/mayan/apps/linking/__init__.py index e215691cec..8b13789179 100644 --- a/mayan/apps/linking/__init__.py +++ b/mayan/apps/linking/__init__.py @@ -1,35 +1 @@ -from __future__ import unicode_literals -from acls.api import class_permissions -from acls.permissions import ACLS_EDIT_ACL, ACLS_VIEW_ACL -from documents.models import Document -from navigation.api import register_links -from project_setup.api import register_setup - -from .classes import ResolvedSmartLink -from .links import ( - smart_link_acl_list, smart_link_create, smart_link_condition_create, - smart_link_condition_delete, smart_link_condition_edit, - smart_link_condition_list, smart_link_delete, smart_link_document_types, - smart_link_edit, smart_link_instance_view, - smart_link_instances_for_document, smart_link_list, smart_link_setup -) -from .models import SmartLink, SmartLinkCondition -from .permissions import ( - PERMISSION_SMART_LINK_DELETE, PERMISSION_SMART_LINK_EDIT, - PERMISSION_SMART_LINK_VIEW -) - -register_links(Document, [smart_link_instances_for_document], menu_name='form_header') -register_links(SmartLink, [smart_link_edit, smart_link_document_types, smart_link_condition_list, smart_link_acl_list, smart_link_delete]) -register_links([SmartLink, 'linking:smart_link_list', 'linking:smart_link_create'], [smart_link_list, smart_link_create], menu_name='secondary_menu') -register_links(SmartLinkCondition, [smart_link_condition_edit, smart_link_condition_delete]) -register_links(ResolvedSmartLink, [smart_link_instance_view]) -register_links(['linking:smart_link_condition_list', 'linking:smart_link_condition_create', 'linking:smart_link_condition_edit', 'linking:smart_link_condition_delete'], [smart_link_condition_create], menu_name='sidebar') - -register_setup(smart_link_setup) - -class_permissions(SmartLink, [ - ACLS_EDIT_ACL, ACLS_VIEW_ACL, PERMISSION_SMART_LINK_DELETE, - PERMISSION_SMART_LINK_EDIT, PERMISSION_SMART_LINK_VIEW -]) diff --git a/mayan/apps/linking/apps.py b/mayan/apps/linking/apps.py new file mode 100644 index 0000000000..66f28367aa --- /dev/null +++ b/mayan/apps/linking/apps.py @@ -0,0 +1,43 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from acls.api import class_permissions +from acls.permissions import ACLS_EDIT_ACL, ACLS_VIEW_ACL +from documents.models import Document +from navigation.api import register_links +from project_setup.api import register_setup + +from .classes import ResolvedSmartLink +from .links import ( + smart_link_acl_list, smart_link_create, smart_link_condition_create, + smart_link_condition_delete, smart_link_condition_edit, + smart_link_condition_list, smart_link_delete, smart_link_document_types, + smart_link_edit, smart_link_instance_view, + smart_link_instances_for_document, smart_link_list, smart_link_setup +) +from .models import SmartLink, SmartLinkCondition +from .permissions import ( + PERMISSION_SMART_LINK_DELETE, PERMISSION_SMART_LINK_EDIT, + PERMISSION_SMART_LINK_VIEW +) + +class LinkingApp(apps.AppConfig): + name = 'linking' + verbose_name = _('Linking') + + def ready(self): + register_links(Document, [smart_link_instances_for_document], menu_name='form_header') + register_links(SmartLink, [smart_link_edit, smart_link_document_types, smart_link_condition_list, smart_link_acl_list, smart_link_delete]) + register_links([SmartLink, 'linking:smart_link_list', 'linking:smart_link_create'], [smart_link_list, smart_link_create], menu_name='secondary_menu') + register_links(SmartLinkCondition, [smart_link_condition_edit, smart_link_condition_delete]) + register_links(ResolvedSmartLink, [smart_link_instance_view]) + register_links(['linking:smart_link_condition_list', 'linking:smart_link_condition_create', 'linking:smart_link_condition_edit', 'linking:smart_link_condition_delete'], [smart_link_condition_create], menu_name='sidebar') + + register_setup(smart_link_setup) + + class_permissions(SmartLink, [ + ACLS_EDIT_ACL, ACLS_VIEW_ACL, PERMISSION_SMART_LINK_DELETE, + PERMISSION_SMART_LINK_EDIT, PERMISSION_SMART_LINK_VIEW + ]) diff --git a/mayan/apps/linking/models.py b/mayan/apps/linking/models.py index ccddbaca1b..f03ceb8c55 100644 --- a/mayan/apps/linking/models.py +++ b/mayan/apps/linking/models.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals from django.db import models from django.db.models import Q from django.utils.translation import ugettext_lazy as _ -from django.utils.translation import ugettext from documents.models import Document, DocumentType @@ -14,7 +13,7 @@ from .managers import SmartLinkManager class SmartLink(models.Model): title = models.CharField(max_length=96, verbose_name=_('Title')) - dynamic_title = models.CharField(blank=True, max_length=96, verbose_name=_('Dynamic title'), help_text=ugettext('This expression will be evaluated against the current selected document.')) + dynamic_title = models.CharField(blank=True, max_length=96, verbose_name=_('Dynamic title'), help_text=_('This expression will be evaluated against the current selected document.')) enabled = models.BooleanField(default=True, verbose_name=_('Enabled')) document_types = models.ManyToManyField(DocumentType, verbose_name=_('Document types')) @@ -65,7 +64,7 @@ class SmartLinkCondition(models.Model): inclusion = models.CharField(default=INCLUSION_AND, max_length=16, choices=INCLUSION_CHOICES, help_text=_('The inclusion is ignored for the first item.')) foreign_document_data = models.CharField(max_length=128, verbose_name=_('Foreign document attribute'), help_text=_('This represents the metadata of all other documents.')) operator = models.CharField(max_length=16, choices=OPERATOR_CHOICES) - expression = models.TextField(verbose_name=_('Expression'), help_text=ugettext('This expression will be evaluated against the current document.')) + expression = models.TextField(verbose_name=_('Expression'), help_text=_('This expression will be evaluated against the current document.')) negated = models.BooleanField(default=False, verbose_name=_('Negated'), help_text=_('Inverts the logic of the operator.')) enabled = models.BooleanField(default=True, verbose_name=_('Enabled')) diff --git a/mayan/apps/lock_manager/apps.py b/mayan/apps/lock_manager/apps.py new file mode 100644 index 0000000000..ad38dc1048 --- /dev/null +++ b/mayan/apps/lock_manager/apps.py @@ -0,0 +1,9 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + + +class LockManagerApp(apps.AppConfig): + name = 'lock_manager' + verbose_name = _('Lock manager') diff --git a/mayan/apps/mailer/__init__.py b/mayan/apps/mailer/__init__.py index 96f514d073..8b13789179 100644 --- a/mayan/apps/mailer/__init__.py +++ b/mayan/apps/mailer/__init__.py @@ -1,14 +1 @@ -from acls.api import class_permissions -from documents.models import Document -from navigation.api import register_links -from .links import send_document_link, send_document -from .permissions import ( - PERMISSION_MAILING_LINK, PERMISSION_MAILING_SEND_DOCUMENT -) - -register_links([Document], [send_document_link, send_document]) - -class_permissions(Document, [ - PERMISSION_MAILING_LINK, PERMISSION_MAILING_SEND_DOCUMENT -]) diff --git a/mayan/apps/mailer/apps.py b/mayan/apps/mailer/apps.py new file mode 100644 index 0000000000..1e9fefee99 --- /dev/null +++ b/mayan/apps/mailer/apps.py @@ -0,0 +1,25 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from acls.api import class_permissions +from documents.models import Document +from navigation.api import register_links + +from .links import send_document_link, send_document +from .permissions import ( + PERMISSION_MAILING_LINK, PERMISSION_MAILING_SEND_DOCUMENT +) + + +class MailerApp(apps.AppConfig): + name = 'mailer' + verbose_name = _('Mailer') + + def ready(self): + register_links([Document], [send_document_link, send_document]) + + class_permissions(Document, [ + PERMISSION_MAILING_LINK, PERMISSION_MAILING_SEND_DOCUMENT + ]) diff --git a/mayan/apps/mailer/models.py b/mayan/apps/mailer/models.py deleted file mode 100644 index 71a8362390..0000000000 --- a/mayan/apps/mailer/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/mayan/apps/main/__init__.py b/mayan/apps/main/__init__.py index ddf7f4bf56..cfdc4b8b3f 100644 --- a/mayan/apps/main/__init__.py +++ b/mayan/apps/main/__init__.py @@ -1,14 +1,2 @@ -from __future__ import unicode_literals - -from django.utils.translation import ugettext_lazy as _ - -from navigation.api import register_top_menu -from project_setup.api import register_setup -from project_tools.api import register_tool - -from .links import admin_site, maintenance_menu from .classes import FrontPageButton # NOQA -register_top_menu('home', link={'text': _('Home'), 'view': 'main:home', 'famfam': 'house'}, position=0) -register_setup(admin_site) -register_tool(maintenance_menu) diff --git a/mayan/apps/main/apps.py b/mayan/apps/main/apps.py new file mode 100644 index 0000000000..85d6a3e90a --- /dev/null +++ b/mayan/apps/main/apps.py @@ -0,0 +1,20 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from navigation.api import register_top_menu +from project_setup.api import register_setup +from project_tools.api import register_tool + +from .links import admin_site, maintenance_menu + + +class MainApp(apps.AppConfig): + name = 'main' + verbose_name = _('Main') + + def ready(self): + register_top_menu('home', link={'text': _('Home'), 'view': 'main:home', 'famfam': 'house'}, position=0) + register_setup(admin_site) + register_tool(maintenance_menu) diff --git a/mayan/apps/metadata/__init__.py b/mayan/apps/metadata/__init__.py index 6608d6ec28..8b13789179 100644 --- a/mayan/apps/metadata/__init__.py +++ b/mayan/apps/metadata/__init__.py @@ -1,94 +1 @@ -from __future__ import unicode_literals -import logging - -from django.db.models.signals import post_delete, post_save -from django.dispatch import receiver -from django.utils.translation import ugettext_lazy as _ - -from acls.api import class_permissions -from common.classes import ModelAttribute -from common.utils import encapsulate -from documents.models import Document, DocumentType -from documents.signals import post_document_type_change -from navigation.api import register_links, register_model_list_columns -from navigation.links import link_spacer -from project_setup.api import register_setup -from project_tools.api import register_tool -from rest_api.classes import APIEndPoint - -from .api import get_metadata_string -from .classes import DocumentMetadataHelper -from .links import ( - metadata_add, metadata_edit, metadata_multiple_add, metadata_multiple_edit, - metadata_multiple_remove, metadata_remove, metadata_view, - setup_document_type_metadata, setup_document_type_metadata_required, - setup_metadata_type_create, setup_metadata_type_delete, - setup_metadata_type_edit, setup_metadata_type_list, - link_documents_missing_required_metadata -) -from .models import DocumentMetadata, DocumentTypeMetadataType, MetadataType -from .permissions import ( - PERMISSION_METADATA_DOCUMENT_ADD, PERMISSION_METADATA_DOCUMENT_EDIT, - PERMISSION_METADATA_DOCUMENT_REMOVE, PERMISSION_METADATA_DOCUMENT_VIEW -) -from .tasks import task_add_required_metadata_type, task_remove_metadata_type - -logger = logging.getLogger(__name__) - - -@receiver(post_save, dispatch_uid='post_document_type_metadata_type_add', sender=DocumentTypeMetadataType) -def post_document_type_metadata_type_add(sender, instance, created, **kwargs): - logger.debug('instance: %s', instance) - - if created and instance.required: - task_add_required_metadata_type.apply_async(kwargs={'document_type_id': instance.document_type.pk, 'metadata_type_id': instance.metadata_type.pk}, queue='metadata') - - -@receiver(post_delete, dispatch_uid='post_document_type_metadata_type_delete', sender=DocumentTypeMetadataType) -def post_document_type_metadata_type_delete(sender, instance, **kwargs): - logger.debug('instance: %s', instance) - task_remove_metadata_type.apply_async(kwargs={'document_type_id': instance.document_type.pk, 'metadata_type_id': instance.metadata_type.pk}, queue='metadata') - - -@receiver(post_document_type_change, dispatch_uid='post_post_document_type_change_metadata', sender=Document) -def post_post_document_type_change_metadata(sender, instance, **kwargs): - logger.debug('received post_document_type_change') - logger.debug('instance: %s', instance) - # Delete existing document metadata - for metadata in instance.metadata.all(): - metadata.delete(enforce_required=False) - - # Add new document type metadata types to document - for document_type_metadata_type in instance.document_type.metadata.filter(required=True): - DocumentMetadata.objects.create(document=instance, metadata_type=document_type_metadata_type.metadata_type, value=None) - - -Document.add_to_class('metadata_value_of', DocumentMetadataHelper.constructor) - -register_links(['metadata:metadata_add', 'metadata:metadata_edit', 'metadata:metadata_remove', 'metadata:metadata_view'], [metadata_add, metadata_edit, metadata_remove], menu_name='sidebar') -register_links(Document, [metadata_view], menu_name='form_header') -register_links([Document], [metadata_multiple_add, metadata_multiple_edit, metadata_multiple_remove, link_spacer], menu_name='multi_item_links') -register_links(DocumentType, [setup_document_type_metadata, setup_document_type_metadata_required]) -register_links(MetadataType, [setup_metadata_type_edit, setup_metadata_type_delete]) -register_links([MetadataType, 'metadata:setup_metadata_type_list', 'metadata:setup_metadata_type_create'], [setup_metadata_type_list, setup_metadata_type_create], menu_name='secondary_menu') - -register_setup(setup_metadata_type_list) -register_tool(link_documents_missing_required_metadata) - -class_permissions(Document, [ - PERMISSION_METADATA_DOCUMENT_ADD, PERMISSION_METADATA_DOCUMENT_EDIT, - PERMISSION_METADATA_DOCUMENT_REMOVE, PERMISSION_METADATA_DOCUMENT_VIEW, -]) - -register_model_list_columns(Document, [ - { - 'name': _('Metadata'), 'attribute': encapsulate(lambda x: get_metadata_string(x)) - }, -]) - -APIEndPoint('metadata') -ModelAttribute(Document, 'metadata__metadata_type__name', label=_('Metadata type name'), type_name='query') -ModelAttribute(Document, 'metadata__value', label=_('Metadata type value'), type_name='query') -ModelAttribute(Document, 'metadata', type_name='related', description=_('Queryset containing a MetadataType instance reference and a value for that metadata type')) -ModelAttribute(Document, 'metadata_value_of', label=_('Value of a metadata'), description=_('Return the value of a specific document metadata'), type_name=['property', 'indexing']) diff --git a/mayan/apps/metadata/apps.py b/mayan/apps/metadata/apps.py new file mode 100644 index 0000000000..8c85678d92 --- /dev/null +++ b/mayan/apps/metadata/apps.py @@ -0,0 +1,100 @@ +from __future__ import unicode_literals + +import logging + +from django import apps +from django.db.models.signals import post_delete, post_save +from django.utils.translation import ugettext_lazy as _ + +from acls.api import class_permissions +from common.classes import ModelAttribute +from common.utils import encapsulate +from documents.models import Document, DocumentType +from documents.signals import post_document_type_change +from navigation.api import register_links, register_model_list_columns +from navigation.links import link_spacer +from project_setup.api import register_setup +from project_tools.api import register_tool +from rest_api.classes import APIEndPoint + +from .api import get_metadata_string +from .classes import DocumentMetadataHelper +from .links import ( + metadata_add, metadata_edit, metadata_multiple_add, metadata_multiple_edit, + metadata_multiple_remove, metadata_remove, metadata_view, + setup_document_type_metadata, setup_document_type_metadata_required, + setup_metadata_type_create, setup_metadata_type_delete, + setup_metadata_type_edit, setup_metadata_type_list, + link_documents_missing_required_metadata +) +from .models import DocumentMetadata, DocumentTypeMetadataType, MetadataType +from .permissions import ( + PERMISSION_METADATA_DOCUMENT_ADD, PERMISSION_METADATA_DOCUMENT_EDIT, + PERMISSION_METADATA_DOCUMENT_REMOVE, PERMISSION_METADATA_DOCUMENT_VIEW +) +from .tasks import task_add_required_metadata_type, task_remove_metadata_type + +logger = logging.getLogger(__name__) + + +def post_document_type_metadata_type_add(sender, instance, created, **kwargs): + logger.debug('instance: %s', instance) + + if created and instance.required: + task_add_required_metadata_type.apply_async(kwargs={'document_type_id': instance.document_type.pk, 'metadata_type_id': instance.metadata_type.pk}, queue='metadata') + + +def post_document_type_metadata_type_delete(sender, instance, **kwargs): + logger.debug('instance: %s', instance) + task_remove_metadata_type.apply_async(kwargs={'document_type_id': instance.document_type.pk, 'metadata_type_id': instance.metadata_type.pk}, queue='metadata') + + +def post_post_document_type_change_metadata(sender, instance, **kwargs): + logger.debug('received post_document_type_change') + logger.debug('instance: %s', instance) + # Delete existing document metadata + for metadata in instance.metadata.all(): + metadata.delete(enforce_required=False) + + # Add new document type metadata types to document + for document_type_metadata_type in instance.document_type.metadata.filter(required=True): + DocumentMetadata.objects.create(document=instance, metadata_type=document_type_metadata_type.metadata_type, value=None) + + +class MetadataApp(apps.AppConfig): + name = 'metadata' + verbose_name = _('Metadata') + + def ready(self): + post_save.connect(post_document_type_metadata_type_add, dispatch_uid='post_document_type_metadata_type_add', sender=DocumentTypeMetadataType) + post_delete.connect(post_document_type_metadata_type_delete, dispatch_uid='post_document_type_metadata_type_delete', sender=DocumentTypeMetadataType) + post_document_type_change.connect(post_post_document_type_change_metadata, dispatch_uid='post_post_document_type_change_metadata', sender=Document) + + Document.add_to_class('metadata_value_of', DocumentMetadataHelper.constructor) + + register_links(['metadata:metadata_add', 'metadata:metadata_edit', 'metadata:metadata_remove', 'metadata:metadata_view'], [metadata_add, metadata_edit, metadata_remove], menu_name='sidebar') + register_links(Document, [metadata_view], menu_name='form_header') + register_links([Document], [metadata_multiple_add, metadata_multiple_edit, metadata_multiple_remove, link_spacer], menu_name='multi_item_links') + register_links(DocumentType, [setup_document_type_metadata, setup_document_type_metadata_required]) + register_links(MetadataType, [setup_metadata_type_edit, setup_metadata_type_delete]) + register_links([MetadataType, 'metadata:setup_metadata_type_list', 'metadata:setup_metadata_type_create'], [setup_metadata_type_list, setup_metadata_type_create], menu_name='secondary_menu') + + register_setup(setup_metadata_type_list) + register_tool(link_documents_missing_required_metadata) + + class_permissions(Document, [ + PERMISSION_METADATA_DOCUMENT_ADD, PERMISSION_METADATA_DOCUMENT_EDIT, + PERMISSION_METADATA_DOCUMENT_REMOVE, PERMISSION_METADATA_DOCUMENT_VIEW, + ]) + + register_model_list_columns(Document, [ + { + 'name': _('Metadata'), 'attribute': encapsulate(lambda x: get_metadata_string(x)) + }, + ]) + + APIEndPoint('metadata') + ModelAttribute(Document, 'metadata__metadata_type__name', label=_('Metadata type name'), type_name='query') + ModelAttribute(Document, 'metadata__value', label=_('Metadata type value'), type_name='query') + ModelAttribute(Document, 'metadata', type_name='related', description=_('Queryset containing a MetadataType instance reference and a value for that metadata type')) + ModelAttribute(Document, 'metadata_value_of', label=_('Value of a metadata'), description=_('Return the value of a specific document metadata'), type_name=['property', 'indexing']) diff --git a/mayan/apps/ocr/__init__.py b/mayan/apps/ocr/__init__.py index a42f63c9a6..8b13789179 100644 --- a/mayan/apps/ocr/__init__.py +++ b/mayan/apps/ocr/__init__.py @@ -1,75 +1 @@ -from __future__ import unicode_literals -import logging - -from django.dispatch import receiver -from django.utils.translation import ugettext_lazy as _ - -from acls.api import class_permissions -from common.utils import encapsulate -from documents.models import Document, DocumentVersion -from documents.signals import post_version_upload -from documents.widgets import document_link -from main.api import register_maintenance_links -from navigation.api import register_links, register_model_list_columns -from navigation.links import link_spacer -from project_tools.api import register_tool -from rest_api.classes import APIEndPoint - -from .links import ( - link_document_all_ocr_cleanup, link_document_submit, - link_document_submit_multiple, link_entry_delete, - link_entry_delete_multiple, link_entry_list, link_entry_re_queue, - link_entry_re_queue_multiple -) -from .models import DocumentVersionOCRError -from .permissions import PERMISSION_OCR_DOCUMENT -from .tasks import task_do_ocr - -logger = logging.getLogger(__name__) - -register_links(Document, [link_document_submit]) -register_links([Document], [link_document_submit_multiple, link_spacer], menu_name='multi_item_links') - -register_links([DocumentVersionOCRError], [link_entry_re_queue_multiple, link_entry_delete_multiple], menu_name='multi_item_links') -register_links([DocumentVersionOCRError], [link_entry_re_queue, link_entry_delete]) -register_links(['ocr:entry_list', 'ocr:entry_delete_multiple', 'ocr:entry_re_queue_multiple', DocumentVersionOCRError], [link_entry_list], menu_name='secondary_menu') -register_maintenance_links([link_document_all_ocr_cleanup], namespace='ocr', title=_('OCR')) - - -def document_ocr_submit(self): - task_do_ocr.apply_async(args=[self.latest_version.pk], queue='ocr') - - -def document_version_ocr_submit(self): - task_do_ocr.apply_async(args=[self.pk], queue='ocr') - - -@receiver(post_version_upload, dispatch_uid='post_version_upload_ocr', sender=DocumentVersion) -def post_version_upload_ocr(sender, instance, **kwargs): - logger.debug('received post_version_upload') - logger.debug('instance pk: %s', instance.pk) - if instance.document.document_type.ocr: - instance.submit_for_ocr() - - -Document.add_to_class('submit_for_ocr', document_ocr_submit) -DocumentVersion.add_to_class('submit_for_ocr', document_version_ocr_submit) - -class_permissions(Document, [PERMISSION_OCR_DOCUMENT]) - -register_tool(link_entry_list) - -APIEndPoint('ocr') - -register_model_list_columns(DocumentVersionOCRError, [ - { - 'name': _('Document'), 'attribute': encapsulate(lambda entry: document_link(entry.document_version.document)) - }, - { - 'name': _('Added'), 'attribute': 'datetime_submitted' - }, - { - 'name': _('Result'), 'attribute': 'result' - }, -]) diff --git a/mayan/apps/ocr/apps.py b/mayan/apps/ocr/apps.py new file mode 100644 index 0000000000..f72d1f9775 --- /dev/null +++ b/mayan/apps/ocr/apps.py @@ -0,0 +1,81 @@ +from __future__ import unicode_literals + +import logging + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from acls.api import class_permissions +from common.utils import encapsulate +from documents.models import Document, DocumentVersion +from documents.signals import post_version_upload +from documents.widgets import document_link +from main.api import register_maintenance_links +from navigation.api import register_links, register_model_list_columns +from navigation.links import link_spacer +from project_tools.api import register_tool +from rest_api.classes import APIEndPoint + +from .links import ( + link_document_all_ocr_cleanup, link_document_submit, + link_document_submit_multiple, link_entry_delete, + link_entry_delete_multiple, link_entry_list, link_entry_re_queue, + link_entry_re_queue_multiple +) +from .models import DocumentVersionOCRError +from .permissions import PERMISSION_OCR_DOCUMENT +from .tasks import task_do_ocr + +logger = logging.getLogger(__name__) + + +def document_ocr_submit(self): + task_do_ocr.apply_async(args=[self.latest_version.pk], queue='ocr') + + +def document_version_ocr_submit(self): + task_do_ocr.apply_async(args=[self.pk], queue='ocr') + + +def post_version_upload_ocr(sender, instance, **kwargs): + logger.debug('received post_version_upload') + logger.debug('instance pk: %s', instance.pk) + if instance.document.document_type.ocr: + instance.submit_for_ocr() + + +class OCRApp(apps.AppConfig): + name = 'ocr' + verbose_name = _('OCR') + + def ready(self): + register_links(Document, [link_document_submit]) + register_links([Document], [link_document_submit_multiple, link_spacer], menu_name='multi_item_links') + + register_links([DocumentVersionOCRError], [link_entry_re_queue_multiple, link_entry_delete_multiple], menu_name='multi_item_links') + register_links([DocumentVersionOCRError], [link_entry_re_queue, link_entry_delete]) + register_links(['ocr:entry_list', 'ocr:entry_delete_multiple', 'ocr:entry_re_queue_multiple', DocumentVersionOCRError], [link_entry_list], menu_name='secondary_menu') + register_maintenance_links([link_document_all_ocr_cleanup], namespace='ocr', title=_('OCR')) + + post_version_upload.connect(post_version_upload_ocr, dispatch_uid='post_version_upload_ocr', sender=DocumentVersion) + + Document.add_to_class('submit_for_ocr', document_ocr_submit) + DocumentVersion.add_to_class('submit_for_ocr', document_version_ocr_submit) + + class_permissions(Document, [PERMISSION_OCR_DOCUMENT]) + + register_tool(link_entry_list) + + APIEndPoint('ocr') + + register_model_list_columns(DocumentVersionOCRError, [ + { + 'name': _('Document'), 'attribute': encapsulate(lambda entry: document_link(entry.document_version.document)) + }, + { + 'name': _('Added'), 'attribute': 'datetime_submitted' + }, + { + 'name': _('Result'), 'attribute': 'result' + }, + ]) diff --git a/mayan/apps/permissions/__init__.py b/mayan/apps/permissions/__init__.py index 589c817819..8b13789179 100644 --- a/mayan/apps/permissions/__init__.py +++ b/mayan/apps/permissions/__init__.py @@ -1,42 +1 @@ -from __future__ import unicode_literals -from django.contrib.auth.models import User -from django.core.exceptions import ObjectDoesNotExist -from django.db.models.signals import post_save - -from navigation.api import register_links -from project_setup.api import register_setup -from rest_api.classes import APIEndPoint - -from .models import Permission, Role -from .links import ( - permission_grant, permission_revoke, role_create, role_delete, role_edit, - role_list, role_members, role_permissions -) -from .settings import DEFAULT_ROLES - -register_links(Role, [role_edit, role_members, role_permissions, role_delete]) -register_links([Role, 'permissions:role_create', 'permissions:role_list'], [role_list, role_create], menu_name='secondary_menu') -register_links(['permissions:role_permissions'], [permission_grant, permission_revoke], menu_name='multi_item_links') - - -def user_post_save(sender, instance, **kwargs): - if kwargs.get('created', False): - for default_role in DEFAULT_ROLES: - if isinstance(default_role, Role): - # If a model is passed, execute method - default_role.add_member(instance) - else: - # If a role name is passed, lookup the corresponding model - try: - role = Role.objects.get(name=default_role) - role.add_member(instance) - except ObjectDoesNotExist: - pass - - -post_save.connect(user_post_save, sender=User) - -register_setup(role_list) - -APIEndPoint('permissions') diff --git a/mayan/apps/permissions/apps.py b/mayan/apps/permissions/apps.py new file mode 100644 index 0000000000..7e50715cc3 --- /dev/null +++ b/mayan/apps/permissions/apps.py @@ -0,0 +1,49 @@ +from __future__ import unicode_literals + +from django import apps +from django.contrib.auth.models import User +from django.core.exceptions import ObjectDoesNotExist +from django.db.models.signals import post_save +from django.utils.translation import ugettext_lazy as _ + +from navigation.api import register_links +from project_setup.api import register_setup +from rest_api.classes import APIEndPoint + +from .models import Permission, Role +from .links import ( + permission_grant, permission_revoke, role_create, role_delete, role_edit, + role_list, role_members, role_permissions +) +from .settings import DEFAULT_ROLES + + +def user_post_save(sender, instance, **kwargs): + if kwargs.get('created', False): + for default_role in DEFAULT_ROLES: + if isinstance(default_role, Role): + # If a model is passed, execute method + default_role.add_member(instance) + else: + # If a role name is passed, lookup the corresponding model + try: + role = Role.objects.get(name=default_role) + role.add_member(instance) + except ObjectDoesNotExist: + pass + + +class PermissionsApp(apps.AppConfig): + name = 'permissions' + verbose_name = _('Permissions') + + def ready(self): + register_links(Role, [role_edit, role_members, role_permissions, role_delete]) + register_links([Role, 'permissions:role_create', 'permissions:role_list'], [role_list, role_create], menu_name='secondary_menu') + register_links(['permissions:role_permissions'], [permission_grant, permission_revoke], menu_name='multi_item_links') + + post_save.connect(user_post_save, sender=User) + + register_setup(role_list) + + APIEndPoint('permissions') diff --git a/mayan/apps/project_setup/__init__.py b/mayan/apps/project_setup/__init__.py index 4062089b51..8b13789179 100644 --- a/mayan/apps/project_setup/__init__.py +++ b/mayan/apps/project_setup/__init__.py @@ -1,7 +1 @@ -from __future__ import unicode_literals -from navigation.api import register_top_menu - -from .links import link_setup - -setup_link = register_top_menu('setup_menu', link=link_setup, position=-2) diff --git a/mayan/apps/project_setup/apps.py b/mayan/apps/project_setup/apps.py new file mode 100644 index 0000000000..77c72b6867 --- /dev/null +++ b/mayan/apps/project_setup/apps.py @@ -0,0 +1,16 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from navigation.api import register_top_menu + +from .links import link_setup + + +class ProjectSetupApp(apps.AppConfig): + name = 'project_setup' + verbose_name = _('Project setup') + + def ready(self): + setup_link = register_top_menu('setup_menu', link=link_setup, position=-2) diff --git a/mayan/apps/project_tools/__init__.py b/mayan/apps/project_tools/__init__.py index ce190dd4b5..3f2ff2d6cc 100644 --- a/mayan/apps/project_tools/__init__.py +++ b/mayan/apps/project_tools/__init__.py @@ -1,7 +1,5 @@ -from __future__ import unicode_literals -from navigation.api import register_top_menu -from .links import link_tools -tool_link = register_top_menu('tools', link=link_tools, position=-3) + + diff --git a/mayan/apps/project_tools/apps.py b/mayan/apps/project_tools/apps.py new file mode 100644 index 0000000000..13bf746f20 --- /dev/null +++ b/mayan/apps/project_tools/apps.py @@ -0,0 +1,17 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from navigation.api import register_top_menu + +from .links import link_tools + + +class ProjectToolsApp(apps.AppConfig): + name = 'project_tools' + verbose_name = _('Project tools') + + def ready(self): + tool_link = register_top_menu('tools', link=link_tools, position=-3) + diff --git a/mayan/apps/rest_api/__init__.py b/mayan/apps/rest_api/__init__.py index 0f9ede78e7..8b13789179 100644 --- a/mayan/apps/rest_api/__init__.py +++ b/mayan/apps/rest_api/__init__.py @@ -1,11 +1 @@ -from __future__ import unicode_literals -from project_tools.api import register_tool - -from .classes import APIEndPoint -from .links import link_api, link_api_documentation - -APIEndPoint('rest_api') - -register_tool(link_api) -register_tool(link_api_documentation) diff --git a/mayan/apps/rest_api/apps.py b/mayan/apps/rest_api/apps.py new file mode 100644 index 0000000000..3d1c821128 --- /dev/null +++ b/mayan/apps/rest_api/apps.py @@ -0,0 +1,20 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from project_tools.api import register_tool + +from .classes import APIEndPoint +from .links import link_api, link_api_documentation + + +class RESTAPIApp(apps.AppConfig): + name = 'rest_api' + verbose_name = _('REST API') + + def ready(self): + APIEndPoint('rest_api') + + register_tool(link_api) + register_tool(link_api_documentation) diff --git a/mayan/apps/smart_settings/__init__.py b/mayan/apps/smart_settings/__init__.py index 3515bf79fd..8b13789179 100644 --- a/mayan/apps/smart_settings/__init__.py +++ b/mayan/apps/smart_settings/__init__.py @@ -1,5 +1 @@ -from project_setup.api import register_setup -from .links import check_settings - -register_setup(check_settings) diff --git a/mayan/apps/smart_settings/apps.py b/mayan/apps/smart_settings/apps.py new file mode 100644 index 0000000000..c7bd36ab9f --- /dev/null +++ b/mayan/apps/smart_settings/apps.py @@ -0,0 +1,16 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from project_setup.api import register_setup + +from .links import check_settings + + +class SmartSettingsApp(apps.AppConfig): + name = 'smart_settings' + verbose_name = _('Smart settings') + + def ready(self): + register_setup(check_settings) diff --git a/mayan/apps/sources/__init__.py b/mayan/apps/sources/__init__.py index f18fe5487f..8b13789179 100644 --- a/mayan/apps/sources/__init__.py +++ b/mayan/apps/sources/__init__.py @@ -1,47 +1 @@ -from __future__ import absolute_import, unicode_literals -from django.utils.translation import ugettext_lazy as _ - -from common.utils import encapsulate -from documents.links import document_list_recent, document_list -from documents.models import Document -from main import FrontPageButton -from navigation.api import register_links, register_model_list_columns -from project_setup.api import register_setup -from rest_api.classes import APIEndPoint - -from .classes import StagingFile -from .links import ( - document_create_multiple, document_create_siblings, setup_sources, - setup_source_create_imap_email, setup_source_create_pop3_email, - setup_source_create_watch_folder, setup_source_create_webform, - setup_source_create_staging_folder, setup_source_delete, setup_source_edit, - setup_source_transformation_create, setup_source_transformation_delete, - setup_source_transformation_edit, setup_source_transformation_list, - staging_file_delete, upload_version -) -from .models import Source, SourceTransformation -from .widgets import staging_file_thumbnail - -register_model_list_columns(StagingFile, [ - { - 'name': _('Thumbnail'), 'attribute': - encapsulate(lambda x: staging_file_thumbnail(x, gallery_name='sources:staging_list', title=x.filename, size='100')) - }, -]) - -register_links([StagingFile], [staging_file_delete]) -register_links([Source, 'sources:setup_source_list', 'sources:setup_source_create'], [setup_sources, setup_source_create_webform, setup_source_create_staging_folder, setup_source_create_pop3_email, setup_source_create_imap_email, setup_source_create_watch_folder], menu_name='secondary_menu') -register_links([Source], [setup_source_edit, setup_source_transformation_list, setup_source_delete]) -register_links(SourceTransformation, [setup_source_transformation_edit, setup_source_transformation_delete]) -register_links([SourceTransformation, 'sources:setup_source_transformation_create', 'sources:setup_source_transformation_list'], [setup_source_transformation_create], menu_name='sidebar') -register_links(['documents:document_version_list', 'documents:upload_version', 'documents:document_version_revert'], [upload_version], menu_name='sidebar') -register_links([Document, 'documents:document_list_recent', 'documents:document_list', 'sources:document_create', 'sources:document_create_multiple', 'sources:upload_interactive', 'sources:staging_file_delete'], [document_create_multiple], menu_name='secondary_menu') -register_links(Document, [document_create_siblings]) -register_links(['sources:document_create', 'sources:document_create_multiple', 'sources:upload_interactive', 'sources:staging_file_delete'], [document_list_recent, document_list], menu_name='secondary_menu') - -register_setup(setup_sources) - -APIEndPoint('sources') - -FrontPageButton(link=document_create_multiple) diff --git a/mayan/apps/sources/apps.py b/mayan/apps/sources/apps.py new file mode 100644 index 0000000000..3822a1117a --- /dev/null +++ b/mayan/apps/sources/apps.py @@ -0,0 +1,54 @@ +from __future__ import absolute_import, unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from common.utils import encapsulate +from documents.links import document_list_recent, document_list +from documents.models import Document +from main import FrontPageButton +from navigation.api import register_links, register_model_list_columns +from project_setup.api import register_setup +from rest_api.classes import APIEndPoint + +from .classes import StagingFile +from .links import ( + document_create_multiple, document_create_siblings, setup_sources, + setup_source_create_imap_email, setup_source_create_pop3_email, + setup_source_create_watch_folder, setup_source_create_webform, + setup_source_create_staging_folder, setup_source_delete, setup_source_edit, + setup_source_transformation_create, setup_source_transformation_delete, + setup_source_transformation_edit, setup_source_transformation_list, + staging_file_delete, upload_version +) +from .models import Source, SourceTransformation +from .widgets import staging_file_thumbnail + + +class SourcesApp(apps.AppConfig): + name = 'sources' + verbose_name = _('Sources') + + def ready(self): + register_model_list_columns(StagingFile, [ + { + 'name': _('Thumbnail'), 'attribute': + encapsulate(lambda x: staging_file_thumbnail(x, gallery_name='sources:staging_list', title=x.filename, size='100')) + }, + ]) + + register_links([StagingFile], [staging_file_delete]) + register_links([Source, 'sources:setup_source_list', 'sources:setup_source_create'], [setup_sources, setup_source_create_webform, setup_source_create_staging_folder, setup_source_create_pop3_email, setup_source_create_imap_email, setup_source_create_watch_folder], menu_name='secondary_menu') + register_links([Source], [setup_source_edit, setup_source_transformation_list, setup_source_delete]) + register_links(SourceTransformation, [setup_source_transformation_edit, setup_source_transformation_delete]) + register_links([SourceTransformation, 'sources:setup_source_transformation_create', 'sources:setup_source_transformation_list'], [setup_source_transformation_create], menu_name='sidebar') + register_links(['documents:document_version_list', 'documents:upload_version', 'documents:document_version_revert'], [upload_version], menu_name='sidebar') + register_links([Document, 'documents:document_list_recent', 'documents:document_list', 'sources:document_create', 'sources:document_create_multiple', 'sources:upload_interactive', 'sources:staging_file_delete'], [document_create_multiple], menu_name='secondary_menu') + register_links(Document, [document_create_siblings]) + register_links(['sources:document_create', 'sources:document_create_multiple', 'sources:upload_interactive', 'sources:staging_file_delete'], [document_list_recent, document_list], menu_name='secondary_menu') + + register_setup(setup_sources) + + APIEndPoint('sources') + + FrontPageButton(link=document_create_multiple) diff --git a/mayan/apps/sources/forms.py b/mayan/apps/sources/forms.py index a3c1cfda7f..44de420412 100644 --- a/mayan/apps/sources/forms.py +++ b/mayan/apps/sources/forms.py @@ -76,11 +76,13 @@ class WebFormUploadForm(UploadBaseForm): class WebFormSetupForm(forms.ModelForm): class Meta: + fields = ('title', 'enabled', 'uncompress') model = WebFormSource class StagingFolderSetupForm(forms.ModelForm): class Meta: + fields = ('title', 'enabled', 'folder_path', 'preview_width', 'preview_height', 'uncompress', 'delete_after_upload') model = StagingFolderSource @@ -93,21 +95,25 @@ class EmailSetupBaseForm(forms.ModelForm): class POP3EmailSetupForm(EmailSetupBaseForm): class Meta(EmailSetupBaseForm.Meta): + fields = ('title', 'enabled', 'interval', 'document_type', 'uncompress', 'host', 'ssl', 'port', 'username', 'password', 'timeout') model = POP3Email class IMAPEmailSetupForm(EmailSetupBaseForm): class Meta(EmailSetupBaseForm.Meta): + fields = ('title', 'enabled', 'interval', 'document_type', 'uncompress', 'host', 'ssl', 'port', 'username', 'password', 'mailbox') model = IMAPEmail class WatchFolderSetupForm(forms.ModelForm): class Meta: + fields = ('title', 'enabled', 'interval', 'document_type', 'uncompress', 'folder_path') model = WatchFolderSource class SourceTransformationForm(forms.ModelForm): class Meta: + fields = ('order', 'transformation', 'arguments') model = SourceTransformation def __init__(self, *args, **kwargs): diff --git a/mayan/apps/sources/models.py b/mayan/apps/sources/models.py index 0280cb6303..b54509ecae 100644 --- a/mayan/apps/sources/models.py +++ b/mayan/apps/sources/models.py @@ -210,7 +210,7 @@ class IntervalBaseModel(OutOfProcessSource): class EmailBaseModel(IntervalBaseModel): host = models.CharField(max_length=128, verbose_name=_('Host')) - ssl = models.BooleanField(verbose_name=_('SSL')) + ssl = models.BooleanField(default=True, verbose_name=_('SSL')) port = models.PositiveIntegerField(blank=True, null=True, verbose_name=_('Port'), help_text=_('Typical choices are 110 for POP3, 995 for POP3 over SSL, 143 for IMAP, 993 for IMAP over SSL.')) username = models.CharField(max_length=96, verbose_name=_('Username')) password = models.CharField(max_length=96, verbose_name=_('Password')) @@ -384,7 +384,7 @@ class SourceTransformation(models.Model): content_object = generic.GenericForeignKey('content_type', 'object_id') order = models.PositiveIntegerField(default=0, blank=True, null=True, verbose_name=_('Order'), db_index=True) transformation = models.CharField(choices=get_available_transformations_choices(), max_length=128, verbose_name=_('Transformation')) - arguments = models.TextField(blank=True, null=True, verbose_name=_('Arguments'), help_text=_('Use dictionaries to indentify arguments, example: %s') % '{\'degrees\':90}', validators=[ArgumentsValidator()]) + arguments = models.TextField(blank=True, null=True, verbose_name=_('Arguments'), help_text=_('Use dictionaries to indentify arguments, example: {\'degrees\':90}'), validators=[ArgumentsValidator()]) objects = models.Manager() transformations = SourceTransformationManager() diff --git a/mayan/apps/statistics/__init__.py b/mayan/apps/statistics/__init__.py index 478231745c..8b13789179 100644 --- a/mayan/apps/statistics/__init__.py +++ b/mayan/apps/statistics/__init__.py @@ -1,16 +1 @@ -from __future__ import unicode_literals -from navigation.api import register_links - -from project_tools.api import register_tool - -from .classes import Statistic, StatisticNamespace -from .links import ( - link_execute, link_namespace_details, link_namespace_list, - link_statistics -) - -register_links(StatisticNamespace, [link_namespace_details]) -register_links([StatisticNamespace, 'statistics:namespace_list', 'statistics:execute'], [link_namespace_list], menu_name='secondary_menu') -register_links(Statistic, [link_execute]) -register_tool(link_statistics) diff --git a/mayan/apps/statistics/apps.py b/mayan/apps/statistics/apps.py new file mode 100644 index 0000000000..fe07d88295 --- /dev/null +++ b/mayan/apps/statistics/apps.py @@ -0,0 +1,25 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from navigation.api import register_links + +from project_tools.api import register_tool + +from .classes import Statistic, StatisticNamespace +from .links import ( + link_execute, link_namespace_details, link_namespace_list, + link_statistics +) + + +class StatisticsApp(apps.AppConfig): + name = 'statistics' + verbose_name = _('Statistics') + + def ready(self): + register_links(StatisticNamespace, [link_namespace_details]) + register_links([StatisticNamespace, 'statistics:namespace_list', 'statistics:execute'], [link_namespace_list], menu_name='secondary_menu') + register_links(Statistic, [link_execute]) + register_tool(link_statistics) diff --git a/mayan/apps/tags/__init__.py b/mayan/apps/tags/__init__.py index bb616ca669..8b13789179 100644 --- a/mayan/apps/tags/__init__.py +++ b/mayan/apps/tags/__init__.py @@ -1,63 +1 @@ -from __future__ import unicode_literals -from django.utils.translation import ugettext_lazy as _ - -from acls.api import class_permissions -from common.utils import encapsulate -from documents.models import Document -from navigation.api import ( - register_links, register_model_list_columns, register_top_menu -) -from navigation.links import link_spacer -from rest_api.classes import APIEndPoint - -from .links import ( - multiple_documents_selection_tag_remove, - single_document_multiple_tag_remove, tag_acl_list, tag_attach, tag_create, - tag_delete, tag_document_list, tag_edit, tag_list, tag_multiple_attach, - tag_multiple_delete, tag_tagged_item_list -) -from .models import Tag -from .permissions import ( - PERMISSION_TAG_ATTACH, PERMISSION_TAG_DELETE, PERMISSION_TAG_EDIT, - PERMISSION_TAG_REMOVE, PERMISSION_TAG_VIEW -) -from .widgets import get_tags_inline_widget_simple, single_tag_widget - -class_permissions(Document, [ - PERMISSION_TAG_ATTACH, PERMISSION_TAG_REMOVE, -]) -class_permissions(Tag, [ - PERMISSION_TAG_DELETE, PERMISSION_TAG_EDIT, PERMISSION_TAG_VIEW, -]) - -APIEndPoint('tags') - -register_model_list_columns(Tag, [ - { - 'name': _('Preview'), - 'attribute': encapsulate(lambda x: single_tag_widget(x)) - }, - { - 'name': _('Tagged items'), - 'attribute': encapsulate(lambda x: x.documents.count()) - } -]) - -register_model_list_columns(Document, [ - { - 'name': _('Tags'), 'attribute': - encapsulate(lambda x: get_tags_inline_widget_simple(x)) - }, -]) - -register_top_menu('tags', link={'text': _('Tags'), 'view': 'tags:tag_list', 'famfam': 'tag_blue'}) - -register_links(Tag, [tag_tagged_item_list, tag_edit, tag_acl_list, tag_delete]) -register_links([Tag], [tag_multiple_delete], menu_name='multi_item_links') -register_links([Tag, 'tags:tag_list', 'tags:tag_create'], [tag_list, tag_create], menu_name='secondary_menu') - -register_links(Document, [tag_document_list], menu_name='form_header') -register_links(['tags:document_tags', 'tags:tag_remove', 'tags:tag_multiple_remove', 'tags:tag_attach'], [tag_attach], menu_name='sidebar') -register_links(['tags:document_tags'], [single_document_multiple_tag_remove], menu_name='multi_item_links') -register_links([Document], [tag_multiple_attach, multiple_documents_selection_tag_remove, link_spacer], menu_name='multi_item_links') diff --git a/mayan/apps/tags/apps.py b/mayan/apps/tags/apps.py new file mode 100644 index 0000000000..b5c2830015 --- /dev/null +++ b/mayan/apps/tags/apps.py @@ -0,0 +1,70 @@ +from __future__ import unicode_literals + +from django import apps +from django.utils.translation import ugettext_lazy as _ + +from acls.api import class_permissions +from common.utils import encapsulate +from documents.models import Document +from navigation.api import ( + register_links, register_model_list_columns, register_top_menu +) +from navigation.links import link_spacer +from rest_api.classes import APIEndPoint + +from .links import ( + multiple_documents_selection_tag_remove, + single_document_multiple_tag_remove, tag_acl_list, tag_attach, tag_create, + tag_delete, tag_document_list, tag_edit, tag_list, tag_multiple_attach, + tag_multiple_delete, tag_tagged_item_list +) +from .models import Tag +from .permissions import ( + PERMISSION_TAG_ATTACH, PERMISSION_TAG_DELETE, PERMISSION_TAG_EDIT, + PERMISSION_TAG_REMOVE, PERMISSION_TAG_VIEW +) +from .widgets import get_tags_inline_widget_simple, single_tag_widget + + +class TagsApp(apps.AppConfig): + name = 'tags' + verbose_name = _('Tags') + + def ready(self): + class_permissions(Document, [ + PERMISSION_TAG_ATTACH, PERMISSION_TAG_REMOVE, + ]) + class_permissions(Tag, [ + PERMISSION_TAG_DELETE, PERMISSION_TAG_EDIT, PERMISSION_TAG_VIEW, + ]) + + APIEndPoint('tags') + + register_model_list_columns(Tag, [ + { + 'name': _('Preview'), + 'attribute': encapsulate(lambda x: single_tag_widget(x)) + }, + { + 'name': _('Tagged items'), + 'attribute': encapsulate(lambda x: x.documents.count()) + } + ]) + + register_model_list_columns(Document, [ + { + 'name': _('Tags'), 'attribute': + encapsulate(lambda x: get_tags_inline_widget_simple(x)) + }, + ]) + + register_top_menu('tags', link={'text': _('Tags'), 'view': 'tags:tag_list', 'famfam': 'tag_blue'}) + + register_links(Tag, [tag_tagged_item_list, tag_edit, tag_acl_list, tag_delete]) + register_links([Tag], [tag_multiple_delete], menu_name='multi_item_links') + register_links([Tag, 'tags:tag_list', 'tags:tag_create'], [tag_list, tag_create], menu_name='secondary_menu') + + register_links(Document, [tag_document_list], menu_name='form_header') + register_links(['tags:document_tags', 'tags:tag_remove', 'tags:tag_multiple_remove', 'tags:tag_attach'], [tag_attach], menu_name='sidebar') + register_links(['tags:document_tags'], [single_document_multiple_tag_remove], menu_name='multi_item_links') + register_links([Document], [tag_multiple_attach, multiple_documents_selection_tag_remove, link_spacer], menu_name='multi_item_links') diff --git a/mayan/apps/user_management/__init__.py b/mayan/apps/user_management/__init__.py index b8c598288d..8b13789179 100644 --- a/mayan/apps/user_management/__init__.py +++ b/mayan/apps/user_management/__init__.py @@ -1,27 +1 @@ -from __future__ import unicode_literals -from django.contrib.auth.models import User, Group - -from navigation.api import register_links -from project_setup.api import register_setup -from rest_api.classes import APIEndPoint - -from .links import ( - group_add, group_delete, group_edit, group_list, group_members, - group_multiple_delete, group_setup, user_add, user_delete, user_edit, - user_groups, user_list, user_multiple_delete, user_multiple_set_password, - user_set_password, user_setup -) - -register_links(User, [user_edit, user_set_password, user_groups, user_delete]) -register_links([User, 'user_management:user_multiple_set_password', 'user_management:user_multiple_delete', 'user_management:user_list', 'user_management:user_add'], [user_list, user_add], menu_name='secondary_menu') -register_links(['user_management:user_list'], [user_multiple_set_password, user_multiple_delete], menu_name='multi_item_links') - -register_links(Group, [group_edit, group_members, group_delete]) -register_links(['user_management:group_multiple_delete', 'user_management:group_delete', 'user_management:group_edit', 'user_management:group_list', 'user_management:group_add', 'user_management:group_members'], [group_list, group_add], menu_name='secondary_menu') -register_links(['user_management:group_list'], [group_multiple_delete], menu_name='multi_item_links') - -register_setup(user_setup) -register_setup(group_setup) - -APIEndPoint('users', app_name='user_management') diff --git a/mayan/apps/user_management/apps.py b/mayan/apps/user_management/apps.py new file mode 100644 index 0000000000..22d091b1a8 --- /dev/null +++ b/mayan/apps/user_management/apps.py @@ -0,0 +1,40 @@ +from __future__ import unicode_literals + +from django import apps +from django.contrib.auth.models import User, Group +from django.utils.translation import ugettext_lazy as _ + +from actstream import registry + +from navigation.api import register_links +from project_setup.api import register_setup +from rest_api.classes import APIEndPoint + +from .links import ( + group_add, group_delete, group_edit, group_list, group_members, + group_multiple_delete, group_setup, user_add, user_delete, user_edit, + user_groups, user_list, user_multiple_delete, user_multiple_set_password, + user_set_password, user_setup +) + + +class UserManagementApp(apps.AppConfig): + name = 'user_management' + verbose_name = _('User management') + + def ready(self): + register_links(User, [user_edit, user_set_password, user_groups, user_delete]) + register_links([User, 'user_management:user_multiple_set_password', 'user_management:user_multiple_delete', 'user_management:user_list', 'user_management:user_add'], [user_list, user_add], menu_name='secondary_menu') + register_links(['user_management:user_list'], [user_multiple_set_password, user_multiple_delete], menu_name='multi_item_links') + + register_links(Group, [group_edit, group_members, group_delete]) + register_links(['user_management:group_multiple_delete', 'user_management:group_delete', 'user_management:group_edit', 'user_management:group_list', 'user_management:group_add', 'user_management:group_members'], [group_list, group_add], menu_name='secondary_menu') + register_links(['user_management:group_list'], [group_multiple_delete], menu_name='multi_item_links') + + register_setup(user_setup) + register_setup(group_setup) + + APIEndPoint('users', app_name='user_management') + + registry.register(User) + registry.register(Group) diff --git a/mayan/apps/user_management/models.py b/mayan/apps/user_management/models.py deleted file mode 100644 index 148f268626..0000000000 --- a/mayan/apps/user_management/models.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.db import models -from django.contrib.auth.models import User, Group - -from actstream import registry - -registry.register(User) -registry.register(Group) diff --git a/mayan/settings/base.py b/mayan/settings/base.py index 29f5efdd86..c7a0e1a229 100644 --- a/mayan/settings/base.py +++ b/mayan/settings/base.py @@ -50,6 +50,7 @@ INSTALLED_APPS = ( 'django.contrib.sites', 'django.contrib.staticfiles', # 3rd party + 'actstream', 'compressor', 'corsheaders', 'djcelery', @@ -58,48 +59,44 @@ INSTALLED_APPS = ( 'rest_framework', 'rest_framework.authtoken', 'solo', - 'south', # Base generic - 'acls', - 'common', + 'acls.apps.ACLsApp', + 'common.apps.CommonApp', 'converter', - 'django_gpg', - 'dynamic_search', - 'lock_manager', + 'django_gpg.apps.DjangoGPGApp', + 'dynamic_search.apps.DynamicSearchApp', + 'lock_manager.apps.LockManagerApp', 'mimetype', 'navigation', - 'permissions', - 'project_setup', - 'project_tools', - 'smart_settings', - 'user_management', + 'permissions.apps.PermissionsApp', + 'project_setup.apps.ProjectSetupApp', + 'project_tools.apps.ProjectToolsApp', + 'smart_settings.apps.SmartSettingsApp', + 'user_management.apps.UserManagementApp', # Mayan EDMS 'appearance', - 'checkouts', - 'document_acls', - 'document_comments', - 'document_indexing', - 'document_signatures', - 'document_states', - 'documents', - 'events', - 'folders', - 'installation', - 'linking', - 'mailer', - 'main', - 'metadata', - 'ocr', - 'rest_api', - 'sources', - 'statistics', + 'checkouts.apps.CheckoutsApp', + 'document_acls.apps.DocumentACLsApp', + 'document_comments.apps.DocumentCommentsApp', + 'document_indexing.apps.DocumentIndexingApp', + 'document_signatures.apps.DocumentSignaturesApp', + 'document_states.apps.DocumentStatesApp', + 'documents.apps.DocumentsApp', + 'events.apps.EventsApp', + 'folders.apps.FoldersApp', + 'installation.apps.InstallationApp', + 'linking.apps.LinkingApp', + 'mailer.apps.MailerApp', + 'main.apps.MainApp', + 'metadata.apps.MetadataApp', + 'ocr.apps.OCRApp', + 'rest_api.apps.RESTAPIApp', + 'sources.apps.SourcesApp', + 'statistics.apps.StatisticsApp', 'storage', - 'tags', + 'tags.apps.TagsApp', # Placed after rest_api to allow template overriding 'rest_framework_swagger', - # Must be last on Django < 1.7 as per documentation - # https://django-activity-stream.readthedocs.org/en/latest/installation.html - 'actstream', # Pagination app must go after the main app so that the main app can # override the default pagination template 'pagination', diff --git a/requirements/common.txt b/requirements/common.txt index 8687f7c332..ccfc3d67fb 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -1,7 +1,7 @@ celery==3.1.17 cssmin==0.2.0 -Django==1.6.8 +Django==1.7.7 django-activity-stream==0.5.1 django-celery==3.1.16 django-compressor==1.4 @@ -32,7 +32,6 @@ requests==2.4.3 sh==1.09 slate==0.3 -South==1.0.2 unicode-slugify==0.1.1