Compare commits

...

23 Commits

Author SHA1 Message Date
Roberto Rosario
9e2ef57e00 Fix document view test mixin
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-13 16:09:54 -04:00
Roberto Rosario
756765ce4a Fix layer imports
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-13 15:40:50 -04:00
Roberto Rosario
53096b8bdd Allow "Execute document tools" permission via ACL
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-13 15:34:32 -04:00
Roberto Rosario
8aa2567a56 Document tests layout tweaks
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-13 15:28:41 -04:00
Roberto Rosario
ce6e568001 Sort documents models methods
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-13 15:21:37 -04:00
Roberto Rosario
d1f0e23c53 Test layout updates
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-11 11:21:05 -04:00
Roberto Rosario
3f33bdd9c2 Sources apps test updates
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-11 10:57:51 -04:00
Roberto Rosario
b2390843ab Update changelog
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-10 17:18:39 -04:00
Roberto Rosario
fc14341d40 Update document version upload to use dropzone
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-10 17:17:09 -04:00
Roberto Rosario
57dd5b1bca Split source multiform template
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-10 17:17:01 -04:00
Roberto Rosario
c731ab7050 Add kwargs and update string formatting
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-10 14:50:26 -04:00
Roberto Rosario
bd0d298be3 New document version improvements from clients/bc
- Comment field help text.
- Remove create_document_form_form.
- Use static NewVersionForm.
- Update sources document upload and new version upload view names.

Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-10 14:34:50 -04:00
Roberto Rosario
cc8147d002 Update requirements and setup
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-08 15:15:50 -04:00
Roberto Rosario
1b327b99f0 Update run_test Docker command name
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-08 15:15:08 -04:00
Roberto Rosario
7b3a83ee39 Update GitLab CI to use Python 3 and virtualenv
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-08 09:48:54 -04:00
Roberto Rosario
4659269349 Invalidate the layer cache in tests
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-08 09:45:28 -04:00
Roberto Rosario
517bb4e9a2 Move Makefile versions to variables
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-08 09:45:20 -04:00
Roberto Rosario
162cd256e7 Merge branch 'versions/minor' of gitlab.com:mayan-edms/mayan-edms into versions/minor 2019-10-07 16:43:15 -04:00
Roberto Rosario
339b7dd836 Add missing dependencies import
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-07 16:43:00 -04:00
Roberto Rosario
949c0ab285 Remove empty ine
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-07 10:43:52 -04:00
Roberto Rosario
cb6cb4121f Fix typos
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-06 03:04:45 -04:00
Roberto Rosario
042727aaa9 Update build string
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-05 15:09:46 -04:00
Roberto Rosario
5b304ea742 Bump version to 3.3 beta 1
Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
2019-10-05 15:08:53 -04:00
42 changed files with 481 additions and 401 deletions

View File

@@ -19,7 +19,7 @@ job_docker_build:
- docker build --pull -t "$CI_REGISTRY_IMAGE" -f docker/Dockerfile . - docker build --pull -t "$CI_REGISTRY_IMAGE" -f docker/Dockerfile .
- VERSION=`cat docker/rootfs/version` - VERSION=`cat docker/rootfs/version`
- docker tag "$CI_REGISTRY_IMAGE" "$CI_REGISTRY_IMAGE:$VERSION" - docker tag "$CI_REGISTRY_IMAGE" "$CI_REGISTRY_IMAGE:$VERSION"
- docker run --rm "$CI_REGISTRY_IMAGE:$VERSION" run-tests - docker run --rm "$CI_REGISTRY_IMAGE:$VERSION" run_tests
- docker push "$CI_REGISTRY_IMAGE:$VERSION" - docker push "$CI_REGISTRY_IMAGE:$VERSION"
- docker push "$CI_REGISTRY_IMAGE:latest" - docker push "$CI_REGISTRY_IMAGE:latest"
- docker tag "$CI_REGISTRY_IMAGE:$VERSION" registry-1.docker.io/mayanedms/mayanedms:"$VERSION" - docker tag "$CI_REGISTRY_IMAGE:$VERSION" registry-1.docker.io/mayanedms/mayanedms:"$VERSION"
@@ -58,7 +58,7 @@ job_docker_nightly:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script: script:
- docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" -f docker/Dockerfile . - docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" -f docker/Dockerfile .
- docker run --rm "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" run-tests - docker run --rm "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" run_tests
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
only: only:
- nightly - nightly
@@ -152,7 +152,9 @@ job_push_python:
- locale-gen en_US.UTF-8 - locale-gen en_US.UTF-8
- update-locale LANG=en_US.UTF-8 - update-locale LANG=en_US.UTF-8
- export LC_ALL=en_US.UTF-8 - export LC_ALL=en_US.UTF-8
- apt-get install -qq curl exiftool gcc ghostscript gnupg1 graphviz libfuse2 libjpeg-dev libmagic1 libpng-dev libtiff-dev poppler-utils libreoffice poppler-utils python-dev python-pip tesseract-ocr tesseract-ocr-deu - apt-get install -qq curl exiftool gcc ghostscript gnupg1 graphviz libfuse2 libjpeg-dev libmagic1 libpng-dev libtiff-dev poppler-utils libreoffice poppler-utils python-dev python-virtualenv python3-dev tesseract-ocr tesseract-ocr-deu
- virtualenv venv -p /usr/bin/python3
- . venv/bin/activate
- pip install -r requirements.txt -r requirements/testing-base.txt - pip install -r requirements.txt -r requirements/testing-base.txt
only: only:
- releases/all - releases/all
@@ -170,6 +172,7 @@ test-mysql:
- mysql:8.0.3 - mysql:8.0.3
script: script:
- apt-get install -qq libmysqlclient-dev mysql-client - apt-get install -qq libmysqlclient-dev mysql-client
- . venv/bin/activate
- pip install mysqlclient - pip install mysqlclient
- mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD" -e "set global character_set_server=utf8mb4;" - mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD" -e "set global character_set_server=utf8mb4;"
- python manage.py test --mayan-apps --settings=mayan.settings.testing.gitlab-ci.db_mysql --nomigrations - python manage.py test --mayan-apps --settings=mayan.settings.testing.gitlab-ci.db_mysql --nomigrations
@@ -185,6 +188,7 @@ test-postgres:
- postgres - postgres
script: script:
- apt-get install -qq libpq-dev - apt-get install -qq libpq-dev
- . venv/bin/activate
- pip install psycopg2 - pip install psycopg2
- python manage.py test --mayan-apps --settings=mayan.settings.testing.gitlab-ci.db_postgres --nomigrations - python manage.py test --mayan-apps --settings=mayan.settings.testing.gitlab-ci.db_postgres --nomigrations
tags: tags:
@@ -193,6 +197,7 @@ test-postgres:
test-sqlite: test-sqlite:
<<: *test_base <<: *test_base
script: script:
- . venv/bin/activate
- python manage.py test --mayan-apps --settings=mayan.settings.testing.gitlab-ci --nomigrations - python manage.py test --mayan-apps --settings=mayan.settings.testing.gitlab-ci --nomigrations
deploy_demo: deploy_demo:

View File

@@ -78,6 +78,11 @@
Support Docker networks and make it the default. Support Docker networks and make it the default.
Delete the containers to allow the script to be idempotent. Delete the containers to allow the script to be idempotent.
Deploy a Redis container. Deploy a Redis container.
- Improve document version upload form.
- Use dropzone for document version upload form.
- Allow the "Execute document tools" permission to be
granted via ACL.
3.2.8 (2019-10-01) 3.2.8 (2019-10-01)
================== ==================

View File

@@ -1,5 +1,15 @@
.PHONY: clean-pyc clean-build .PHONY: clean-pyc clean-build
DOCKER_MYSQL_IMAGE = mysql:8.0
DOCKER_ORACLE_IMAGE = wnameless/oracle-xe-11g
DOCKER_POSTGRES_IMAGE = postgres:9.6-alpine
DOCKER_REDIS_IMAGE = redis:5.0-alpine
PYTHON_MYSQL_VERSION = 1.4.4
PYTHON_PSYCOPG2_VERSION = 2.8.3
PYTHON_RABBITMQ_VERSION = 2.0.0
PYTHON_REDIS_VERSION = 3.2.1
help: help:
@echo "Usage: make <target>\n" @echo "Usage: make <target>\n"
@awk 'BEGIN {FS = ":.*##"} /^[a-zA-Z_-]+:.*?## / { printf " * %-40s -%s\n", $$1, $$2 }' $(MAKEFILE_LIST)|sort @awk 'BEGIN {FS = ":.*##"} /^[a-zA-Z_-]+:.*?## / { printf " * %-40s -%s\n", $$1, $$2 }' $(MAKEFILE_LIST)|sort
@@ -18,7 +28,7 @@ clean-pyc: ## Remove Python artifacts.
find . -name '*.pyc' -exec rm -f {} + find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} + find . -name '*.pyo' -exec rm -f {} +
find . -name '*~' -exec rm -f {} + find . -name '*~' -exec rm -f {} +
find . -name '__pycache__' -exec rm -R -f {} + find . -name '__pycache__' -exec rm -R -f {} +
# Testing # Testing
@@ -33,10 +43,10 @@ test-all: clean-pyc
test-launch-postgres: test-launch-postgres:
@docker rm -f test-postgres || true @docker rm -f test-postgres || true
@docker volume rm test-postgres || true @docker volume rm test-postgres || true
docker run -d --name test-postgres -p 5432:5432 -v test-postgres:/var/lib/postgresql/data healthcheck/postgres docker run -d --name test-postgres -p 5432:5432 -v test-postgres:/var/lib/postgresql/data $(DOCKER_POSTGRES_IMAGE)
sudo apt-get install -q libpq-dev sudo apt-get install -q libpq-dev
pip install psycopg2 pip install psycopg2==$(PYTHON_PSYCOPG2_VERSION)
while ! docker inspect --format='{{json .State.Health}}' test-postgres|grep 'Status":"healthy"'; do sleep 1; done while ! nc -z 127.0.0.1 5432; do sleep 1; done
test-with-postgres: ## MODULE=<python module name> - Run tests for a single app, module or test class against a Postgres database container. test-with-postgres: ## MODULE=<python module name> - Run tests for a single app, module or test class against a Postgres database container.
test-with-postgres: test-launch-postgres test-with-postgres: test-launch-postgres
@@ -53,10 +63,10 @@ test-with-postgres-all: test-launch-postgres
test-launch-mysql: test-launch-mysql:
@docker rm -f test-mysql || true @docker rm -f test-mysql || true
@docker volume rm test-mysql || true @docker volume rm test-mysql || true
docker run -d --name test-mysql -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=True -e MYSQL_DATABASE=mayan -v test-mysql:/var/lib/mysql healthcheck/mysql docker run -d --name test-mysql -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=True -e MYSQL_DATABASE=mayan -v test-mysql:/var/lib/mysql $(DOCKER_MYSQL_IMAGE)
sudo apt-get install -q libmysqlclient-dev mysql-client sudo apt-get install -q libmysqlclient-dev mysql-client
pip install mysqlclient pip install mysqlclient==$(PYTHON_MYSQL_VERSION)
while ! docker inspect --format='{{json .State.Health}}' test-mysql|grep 'Status":"healthy"'; do sleep 1; done while ! nc -z 127.0.0.1 3306; do sleep 1; done
mysql -h 127.0.0.1 -P 3306 -uroot -e "set global character_set_server=utf8mb4;" mysql -h 127.0.0.1 -P 3306 -uroot -e "set global character_set_server=utf8mb4;"
test-with-mysql: ## MODULE=<python module name> - Run tests for a single app, module or test class against a MySQL database container. test-with-mysql: ## MODULE=<python module name> - Run tests for a single app, module or test class against a MySQL database container.
@@ -75,7 +85,7 @@ test-with-mysql-all: test-launch-mysql
test-launch-oracle: test-launch-oracle:
@docker rm -f test-oracle || true @docker rm -f test-oracle || true
@docker volume rm test-oracle || true @docker volume rm test-oracle || true
docker run -d --name test-oracle -p 49160:22 -p 49161:1521 -e ORACLE_ALLOW_REMOTE=true -v test-oracle:/u01/app/oracle wnameless/oracle-xe-11g docker run -d --name test-oracle -p 49160:22 -p 49161:1521 -e ORACLE_ALLOW_REMOTE=true -v test-oracle:/u01/app/oracle $(DOCKER_ORACLE_IMAGE)
# https://gist.github.com/kimus/10012910 # https://gist.github.com/kimus/10012910
pip install cx_Oracle pip install cx_Oracle
while ! nc -z 127.0.0.1 49161; do sleep 1; done while ! nc -z 127.0.0.1 49161; do sleep 1; done
@@ -243,11 +253,12 @@ shell_plus: ## Run the shell_plus command.
./manage.py shell_plus --settings=mayan.settings.development ./manage.py shell_plus --settings=mayan.settings.development
test-with-docker-services-on: ## Launch and initialize production-like services using Docker (Postgres and Redis). test-with-docker-services-on: ## Launch and initialize production-like services using Docker (Postgres and Redis).
docker run -d --name redis -p 6379:6379 redis docker run -d --name redis -p 6379:6379 $(DOCKER_REDIS_IMAGE)
docker run -d --name postgres -p 5432:5432 postgres docker run -d --name postgres -p 5432:5432 $(DOCKER_POSTGRES_IMAGE)
while ! nc -z 127.0.0.1 6379; do sleep 1; done while ! nc -z 127.0.0.1 6379; do sleep 1; done
while ! nc -z 127.0.0.1 5432; do sleep 1; done while ! nc -z 127.0.0.1 5432; do sleep 1; done
sleep 4 sleep 4
pip install psycopg2==$(PYTHON_PSYCOPG2_VERSION) redis==$(PYTHON_REDIS_VERSION)
./manage.py initialsetup --settings=mayan.settings.staging.docker ./manage.py initialsetup --settings=mayan.settings.staging.docker
test-with-docker-services-off: ## Stop and delete the Docker production-like services. test-with-docker-services-off: ## Stop and delete the Docker production-like services.
@@ -261,7 +272,7 @@ test-with-docker-worker: ## Launch a worker instance that uses the production-li
DJANGO_SETTINGS_MODULE=mayan.settings.staging.docker ./manage.py celery worker -A mayan -B -l INFO -O fair DJANGO_SETTINGS_MODULE=mayan.settings.staging.docker ./manage.py celery worker -A mayan -B -l INFO -O fair
docker-mysql-on: ## Launch and initialize a MySQL Docker container. docker-mysql-on: ## Launch and initialize a MySQL Docker container.
docker run -d --name mysql -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=True -e MYSQL_DATABASE=mayan_edms mysql docker run -d --name mysql -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=True -e MYSQL_DATABASE=mayan_edms $(DOCKER_MYSQL_IMAGE)
while ! nc -z 127.0.0.1 3306; do sleep 1; done while ! nc -z 127.0.0.1 3306; do sleep 1; done
docker-mysql-off: ## Stop and delete the MySQL Docker container. docker-mysql-off: ## Stop and delete the MySQL Docker container.
@@ -269,7 +280,7 @@ docker-mysql-off: ## Stop and delete the MySQL Docker container.
docker rm mysql docker rm mysql
docker-postgres-on: ## Launch and initialize a PostgreSQL Docker container. docker-postgres-on: ## Launch and initialize a PostgreSQL Docker container.
docker run -d --name postgres -p 5432:5432 postgres docker run -d --name postgres -p 5432:5432 $(DOCKER_POSTGRES_IMAGE)
while ! nc -z 127.0.0.1 5432; do sleep 1; done while ! nc -z 127.0.0.1 5432; do sleep 1; done
docker-postgres-off: ## Stop and delete the PostgreSQL Docker container. docker-postgres-off: ## Stop and delete the PostgreSQL Docker container.

View File

@@ -1 +1 @@
3.2.8 3.3beta1

View File

@@ -93,7 +93,7 @@ Changes
Removals Removals
-------- --------
- Database conversion. Reason for removal. The database conversions support - Database conversion. Reason for removal: The database conversions support
provided by this feature (SQLite to PostgreSQL) was being confused with provided by this feature (SQLite to PostgreSQL) was being confused with
database migrations and upgrades. database migrations and upgrades.
@@ -108,7 +108,7 @@ Removals
Continued confusion about the purpose of the feature and confusion about Continued confusion about the purpose of the feature and confusion about
how errors with this feature were a reflexion of the code quality of how errors with this feature were a reflexion of the code quality of
Mayannecessitated the removal of the database conversion feature. Mayan necessitated the removal of the database conversion feature.
- Django environ - Django environ

View File

@@ -1,9 +1,9 @@
from __future__ import unicode_literals from __future__ import unicode_literals
__title__ = 'Mayan EDMS' __title__ = 'Mayan EDMS'
__version__ = '3.2.8' __version__ = '3.3beta1'
__build__ = 0x030208 __build__ = 0x030300
__build_string__ = 'v3.2.8_Tue Oct 1 13:31:40 2019 -0400' __build_string__ = 'v3.3beta1-9-g1b327b99f0_Tue Oct 8 15:15:08 2019 -0400'
__django_version__ = '1.11' __django_version__ = '1.11'
__author__ = 'Roberto Rosario' __author__ = 'Roberto Rosario'
__author_email__ = 'roberto.rosario@mayan-edms.com' __author_email__ = 'roberto.rosario@mayan-edms.com'

View File

@@ -33,7 +33,7 @@ class CabinetDocumentUploadTestCase(CabinetTestMixin, GenericDocumentViewTestCas
def _request_upload_interactive_document_create_view(self): def _request_upload_interactive_document_create_view(self):
with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object: with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object:
return self.post( return self.post(
viewname='sources:upload_interactive', kwargs={ viewname='sources:document_upload_interactive', kwargs={
'source_id': self.test_source.pk 'source_id': self.test_source.pk
}, data={ }, data={
'document_type_id': self.test_document_type.pk, 'document_type_id': self.test_document_type.pk,

View File

@@ -376,7 +376,7 @@ class NewVersionBlockViewTestCase(
self.login_superuser() self.login_superuser()
response = self.post( response = self.post(
viewname='sources:upload_version', kwargs={ viewname='sources:document_version_upload', kwargs={
'document_pk': self.test_document.pk 'document_pk': self.test_document.pk
}, follow=True }, follow=True
) )

View File

@@ -53,8 +53,8 @@ class MultiFormView(DjangoFormView):
template_name = 'appearance/generic_form.html' template_name = 'appearance/generic_form.html'
def _create_form(self, form_name, klass): def _create_form(self, form_name, klass):
form_kwargs = self.get_form_kwargs(form_name) form_kwargs = self.get_form_kwargs(form_name=form_name)
form_create_method = 'create_%s_form' % form_name form_create_method = 'create_{}_form'.format(form_name)
if hasattr(self, form_create_method): if hasattr(self, form_create_method):
form = getattr(self, form_create_method)(**form_kwargs) form = getattr(self, form_create_method)(**form_kwargs)
else: else:
@@ -66,17 +66,17 @@ class MultiFormView(DjangoFormView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
form_classes = self.get_form_classes() form_classes = self.get_form_classes()
self.forms = self.get_forms(form_classes) self.forms = self.get_forms(form_classes=form_classes)
return super(MultiFormView, self).dispatch(request, *args, **kwargs) return super(MultiFormView, self).dispatch(request, *args, **kwargs)
def forms_valid(self, forms): def forms_valid(self, forms):
for form_name, form in forms.items(): for form_name, form in forms.items():
form_valid_method = '%s_form_valid' % form_name form_valid_method = '{}_form_valid'.format(form_name)
if hasattr(self, form_valid_method): if hasattr(self, form_valid_method):
return getattr(self, form_valid_method)(form) return getattr(self, form_valid_method)(form=form)
self.all_forms_valid(forms) self.all_forms_valid(forms=forms)
return HttpResponseRedirect(redirect_to=self.get_success_url()) return HttpResponseRedirect(redirect_to=self.get_success_url())
@@ -98,14 +98,16 @@ class MultiFormView(DjangoFormView):
def get_form_kwargs(self, form_name): def get_form_kwargs(self, form_name):
kwargs = {} kwargs = {}
kwargs.update({'initial': self.get_initial(form_name)}) kwargs.update({'initial': self.get_initial(form_name=form_name)})
kwargs.update({'prefix': self.get_prefix(form_name)}) kwargs.update({'prefix': self.get_prefix(form_name=form_name)})
if self.request.method in ('POST', 'PUT'): if self.request.method in ('POST', 'PUT'):
kwargs.update({ kwargs.update(
'data': self.request.POST, {
'files': self.request.FILES, 'data': self.request.POST,
}) 'files': self.request.FILES,
}
)
kwargs.update(self.get_form_extra_kwargs(form_name=form_name) or {}) kwargs.update(self.get_form_extra_kwargs(form_name=form_name) or {})
@@ -118,13 +120,13 @@ class MultiFormView(DjangoFormView):
return dict( return dict(
[ [
( (
key, self._create_form(key, klass) key, self._create_form(form_name=key, klass=klass)
) for key, klass in form_classes.items() ) for key, klass in form_classes.items()
] ]
) )
def get_initial(self, form_name): def get_initial(self, form_name):
initial_method = 'get_%s_initial' % form_name initial_method = 'get_{}_initial'.format(form_name)
if hasattr(self, initial_method): if hasattr(self, initial_method):
return getattr(self, initial_method)() return getattr(self, initial_method)()
else: else:
@@ -206,9 +208,9 @@ class AddRemoveView(
getattr(self.main_object, self.related_field).add(*queryset) getattr(self.main_object, self.related_field).add(*queryset)
else: else:
raise ImproperlyConfigured( raise ImproperlyConfigured(
'View %s must be called with a main_object_method_add, a ' 'View {} must be called with a main_object_method_add, a '
'related_field, or an action_add ' 'related_field, or an action_add '
'method.' % self.__class__.__name__ 'method.'.format(self.__class__.__name__)
) )
def _action_remove(self, queryset): def _action_remove(self, queryset):
@@ -225,9 +227,9 @@ class AddRemoveView(
getattr(self.main_object, self.related_field).remove(*queryset) getattr(self.main_object, self.related_field).remove(*queryset)
else: else:
raise ImproperlyConfigured( raise ImproperlyConfigured(
'View %s must be called with a main_object_method_remove, a ' 'View {} must be called with a main_object_method_remove, a '
'related_field, or an action_remove ' 'related_field, or an action_remove '
'method.' % self.__class__.__name__ 'method.'.format(self.__class__.__name__)
) )
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
@@ -348,8 +350,10 @@ class AddRemoveView(
def get_list_added_queryset(self): def get_list_added_queryset(self):
if not self.related_field: if not self.related_field:
raise ImproperlyConfigured( raise ImproperlyConfigured(
'View %s must be called with either a related_field or ' 'View {} must be called with either a related_field or '
'override .get_list_added_queryset().' % self.__class__.__name__ 'override .get_list_added_queryset().'.format(
self.__class__.__name__
)
) )
return self.get_secondary_object_list().filter( return self.get_secondary_object_list().filter(

View File

@@ -5,6 +5,7 @@ from django.test import TestCase
from django_downloadview import assert_download_response from django_downloadview import assert_download_response
from mayan.apps.acls.tests.mixins import ACLTestCaseMixin from mayan.apps.acls.tests.mixins import ACLTestCaseMixin
from mayan.apps.converter.tests.mixins import LayerTestCaseMixin
from mayan.apps.permissions.classes import Permission from mayan.apps.permissions.classes import Permission
from mayan.apps.smart_settings.classes import Namespace from mayan.apps.smart_settings.classes import Namespace
from mayan.apps.user_management.tests.mixins import UserTestMixin from mayan.apps.user_management.tests.mixins import UserTestMixin
@@ -19,7 +20,7 @@ from .mixins import (
class BaseTestCase( class BaseTestCase(
SilenceLoggerTestCaseMixin, ConnectionsCheckTestCaseMixin, LayerTestCaseMixin, SilenceLoggerTestCaseMixin, ConnectionsCheckTestCaseMixin,
RandomPrimaryKeyModelMonkeyPatchMixin, ACLTestCaseMixin, RandomPrimaryKeyModelMonkeyPatchMixin, ACLTestCaseMixin,
ModelTestCaseMixin, OpenFileCheckTestCaseMixin, ModelTestCaseMixin, OpenFileCheckTestCaseMixin,
TempfileCheckTestCasekMixin, UserTestMixin, TestCase TempfileCheckTestCasekMixin, UserTestMixin, TestCase

View File

@@ -14,6 +14,12 @@ from .literals import (
) )
class LayerTestCaseMixin(object):
def setUp(self):
super(LayerTestCaseMixin, self).setUp()
Layer.invalidate_cache()
class LayerTestMixin(PermissionTestMixin): class LayerTestMixin(PermissionTestMixin):
test_layer = Layer( test_layer = Layer(
label='Test layer', name='test_layer', order=1000, label='Test layer', name='test_layer', order=1000,
@@ -38,8 +44,6 @@ class LayerTestMixin(PermissionTestMixin):
'select': self.test_layer_permission, 'select': self.test_layer_permission,
'view': self.test_layer_permission, 'view': self.test_layer_permission,
} }
Layer.invalidate_cache()
Layer.update()
class TransformationTestMixin(LayerTestMixin): class TransformationTestMixin(LayerTestMixin):

View File

@@ -5,4 +5,3 @@
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}

View File

@@ -87,10 +87,10 @@ from .permissions import (
permission_document_download, permission_document_edit, permission_document_download, permission_document_edit,
permission_document_new_version, permission_document_print, permission_document_new_version, permission_document_print,
permission_document_properties_edit, permission_document_restore, permission_document_properties_edit, permission_document_restore,
permission_document_trash, permission_document_type_delete, permission_document_tools, permission_document_trash,
permission_document_type_edit, permission_document_type_view, permission_document_type_delete, permission_document_type_edit,
permission_document_version_revert, permission_document_version_view, permission_document_type_view, permission_document_version_revert,
permission_document_view permission_document_version_view, permission_document_view
) )
# Just import to initialize the search models # Just import to initialize the search models
from .search import document_search, document_page_search # NOQA from .search import document_search, document_page_search # NOQA
@@ -191,8 +191,8 @@ class DocumentsApp(MayanAppConfig):
permission_document_delete, permission_document_download, permission_document_delete, permission_document_download,
permission_document_edit, permission_document_new_version, permission_document_edit, permission_document_new_version,
permission_document_print, permission_document_properties_edit, permission_document_print, permission_document_properties_edit,
permission_document_restore, permission_document_trash, permission_document_restore, permission_document_tools,
permission_document_version_revert, permission_document_trash, permission_document_version_revert,
permission_document_version_view, permission_document_view, permission_document_version_view, permission_document_view,
permission_events_view, permission_transformation_create, permission_events_view, permission_transformation_create,
permission_transformation_delete, permission_transformation_delete,

View File

@@ -102,6 +102,14 @@ class Document(models.Model):
) )
return RecentDocument.objects.add_document_for_user(user, self) return RecentDocument.objects.add_document_for_user(user, self)
@property
def checksum(self):
return self.latest_version.checksum
@property
def date_updated(self):
return self.latest_version.timestamp
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
to_trash = kwargs.pop('to_trash', True) to_trash = kwargs.pop('to_trash', True)
@@ -126,6 +134,14 @@ class Document(models.Model):
else: else:
return False return False
@property
def file_mime_encoding(self):
return self.latest_version.encoding
@property
def file_mimetype(self):
return self.latest_version.mimetype
def get_absolute_url(self): def get_absolute_url(self):
return reverse( return reverse(
viewname='documents:document_preview', kwargs={'pk': self.pk} viewname='documents:document_preview', kwargs={'pk': self.pk}
@@ -140,6 +156,10 @@ class Document(models.Model):
def is_in_trash(self): def is_in_trash(self):
return self.in_trash return self.in_trash
@property
def latest_version(self):
return self.versions.order_by('timestamp').last()
def natural_key(self): def natural_key(self):
return (self.uuid,) return (self.uuid,)
natural_key.dependencies = ['documents.DocumentType'] natural_key.dependencies = ['documents.DocumentType']
@@ -165,6 +185,34 @@ class Document(models.Model):
""" """
return self.latest_version.open(*args, **kwargs) return self.latest_version.open(*args, **kwargs)
@property
def page_count(self):
return self.latest_version.page_count
@property
def pages(self):
try:
return self.latest_version.pages
except AttributeError:
# Document has no version yet
DocumentPage = apps.get_model(
app_label='documents', model_name='DocumentPage'
)
return DocumentPage.objects.none()
@property
def pages_all(self):
try:
return self.latest_version.pages_all
except AttributeError:
# Document has no version yet
DocumentPage = apps.get_model(
app_label='documents', model_name='DocumentPage'
)
return DocumentPage.objects.none()
def restore(self): def restore(self):
self.in_trash = False self.in_trash = False
self.save() self.save()
@@ -209,53 +257,3 @@ class Document(models.Model):
@property @property
def size(self): def size(self):
return self.latest_version.size return self.latest_version.size
# Compatibility methods
@property
def checksum(self):
return self.latest_version.checksum
@property
def date_updated(self):
return self.latest_version.timestamp
@property
def file_mime_encoding(self):
return self.latest_version.encoding
@property
def file_mimetype(self):
return self.latest_version.mimetype
@property
def latest_version(self):
return self.versions.order_by('timestamp').last()
@property
def page_count(self):
return self.latest_version.page_count
@property
def pages_all(self):
try:
return self.latest_version.pages_all
except AttributeError:
# Document has no version yet
DocumentPage = apps.get_model(
app_label='documents', model_name='DocumentPage'
)
return DocumentPage.objects.none()
@property
def pages(self):
try:
return self.latest_version.pages
except AttributeError:
# Document has no version yet
DocumentPage = apps.get_model(
app_label='documents', model_name='DocumentPage'
)
return DocumentPage.objects.none()

View File

@@ -253,10 +253,6 @@ class DocumentVersion(models.Model):
) )
return DocumentPage.passthrough.filter(document_version=self) return DocumentPage.passthrough.filter(document_version=self)
@property
def pages(self):
return self.version_pages.all()
@property @property
def page_count(self): def page_count(self):
""" """
@@ -264,6 +260,10 @@ class DocumentVersion(models.Model):
""" """
return self.pages.count() return self.pages.count()
@property
def pages(self):
return self.version_pages.all()
def revert(self, _user=None): def revert(self, _user=None):
""" """
Delete the subsequent versions after this one Delete the subsequent versions after this one

View File

@@ -5,6 +5,7 @@ import os
from django.conf import settings from django.conf import settings
from mayan.apps.converter.classes import Layer from mayan.apps.converter.classes import Layer
from mayan.apps.converter.layers import layer_saved_transformations
from ..literals import PAGE_RANGE_ALL from ..literals import PAGE_RANGE_ALL
from ..models import DocumentType from ..models import DocumentType
@@ -14,6 +15,7 @@ from .literals import (
TEST_DOCUMENT_TYPE_LABEL, TEST_DOCUMENT_TYPE_LABEL_EDITED, TEST_DOCUMENT_TYPE_LABEL, TEST_DOCUMENT_TYPE_LABEL_EDITED,
TEST_DOCUMENT_TYPE_QUICK_LABEL, TEST_DOCUMENT_TYPE_QUICK_LABEL_EDITED, TEST_DOCUMENT_TYPE_QUICK_LABEL, TEST_DOCUMENT_TYPE_QUICK_LABEL_EDITED,
TEST_SMALL_DOCUMENT_FILENAME, TEST_SMALL_DOCUMENT_PATH, TEST_SMALL_DOCUMENT_FILENAME, TEST_SMALL_DOCUMENT_PATH,
TEST_TRANSFORMATION_ARGUMENT, TEST_TRANSFORMATION_CLASS,
TEST_VERSION_COMMENT TEST_VERSION_COMMENT
) )
@@ -69,6 +71,8 @@ class DocumentTestMixin(object):
self.test_document = document self.test_document = document
self.test_documents.append(document) self.test_documents.append(document)
self.test_document_page = document.latest_version.pages.first()
self.test_document_version = document.latest_version
class DocumentTypeViewTestMixin(object): class DocumentTypeViewTestMixin(object):
@@ -149,6 +153,13 @@ class DocumentVersionTestMixin(object):
class DocumentViewTestMixin(object): class DocumentViewTestMixin(object):
def _create_document_transformation(self):
layer_saved_transformations.add_transformation_to(
obj=self.test_document.pages.first(),
transformation_class=TEST_TRANSFORMATION_CLASS,
arguments=TEST_TRANSFORMATION_ARGUMENT
)
def _request_document_properties_view(self): def _request_document_properties_view(self):
return self.get( return self.get(
viewname='documents:document_properties', viewname='documents:document_properties',

View File

@@ -9,10 +9,10 @@ from ..permissions import (
from .base import GenericDocumentViewTestCase from .base import GenericDocumentViewTestCase
class DocumentPageDisableViewTestCase(GenericDocumentViewTestCase): class DocumentPageDisableViewTestMixin(object):
def setUp(self): def _disable_test_document_page(self):
super(DocumentPageDisableViewTestCase, self).setUp() self.test_document_page.enabled = False
self.test_document_page = self.test_document.pages_all.first() self.test_document_page.save()
def _request_test_document_page_disable_view(self): def _request_test_document_page_disable_view(self):
return self.post( return self.post(
@@ -21,6 +21,31 @@ class DocumentPageDisableViewTestCase(GenericDocumentViewTestCase):
} }
) )
def _request_test_document_page_enable_view(self):
return self.post(
viewname='documents:document_page_enable', kwargs={
'pk': self.test_document_page.pk
}
)
def _request_test_document_page_multiple_disable_view(self):
return self.post(
viewname='documents:document_page_multiple_disable', data={
'id_list': self.test_document_page.pk
}
)
def _request_test_document_page_multiple_enable_view(self):
return self.post(
viewname='documents:document_page_multiple_enable', data={
'id_list': self.test_document_page.pk
}
)
class DocumentPageDisableViewTestCase(
DocumentPageDisableViewTestMixin, GenericDocumentViewTestCase
):
def test_document_page_disable_view_no_permission(self): def test_document_page_disable_view_no_permission(self):
test_document_page_count = self.test_document.pages.count() test_document_page_count = self.test_document.pages.count()
@@ -45,13 +70,6 @@ class DocumentPageDisableViewTestCase(GenericDocumentViewTestCase):
test_document_page_count, self.test_document.pages.count() test_document_page_count, self.test_document.pages.count()
) )
def _request_test_document_page_multiple_disable_view(self):
return self.post(
viewname='documents:document_page_multiple_disable', data={
'id_list': self.test_document_page.pk
}
)
def test_document_page_multiple_disable_view_no_permission(self): def test_document_page_multiple_disable_view_no_permission(self):
test_document_page_count = self.test_document.pages.count() test_document_page_count = self.test_document.pages.count()
@@ -76,17 +94,6 @@ class DocumentPageDisableViewTestCase(GenericDocumentViewTestCase):
test_document_page_count, self.test_document.pages.count() test_document_page_count, self.test_document.pages.count()
) )
def _disable_test_document_page(self):
self.test_document_page.enabled = False
self.test_document_page.save()
def _request_test_document_page_enable_view(self):
return self.post(
viewname='documents:document_page_enable', kwargs={
'pk': self.test_document_page.pk
}
)
def test_document_page_enable_view_no_permission(self): def test_document_page_enable_view_no_permission(self):
self._disable_test_document_page() self._disable_test_document_page()
@@ -114,13 +121,6 @@ class DocumentPageDisableViewTestCase(GenericDocumentViewTestCase):
test_document_page_count, self.test_document.pages.count() test_document_page_count, self.test_document.pages.count()
) )
def _request_test_document_page_multiple_enable_view(self):
return self.post(
viewname='documents:document_page_multiple_enable', data={
'id_list': self.test_document_page.pk
}
)
def test_document_page_multiple_enable_view_no_permission(self): def test_document_page_multiple_enable_view_no_permission(self):
self._disable_test_document_page() self._disable_test_document_page()
test_document_page_count = self.test_document.pages.count() test_document_page_count = self.test_document.pages.count()
@@ -148,7 +148,7 @@ class DocumentPageDisableViewTestCase(GenericDocumentViewTestCase):
) )
class DocumentPageViewTestCase(GenericDocumentViewTestCase): class DocumentPageViewTestMixin(object):
def _request_test_document_page_list_view(self): def _request_test_document_page_list_view(self):
return self.get( return self.get(
viewname='documents:document_pages', kwargs={ viewname='documents:document_pages', kwargs={
@@ -156,6 +156,17 @@ class DocumentPageViewTestCase(GenericDocumentViewTestCase):
} }
) )
def _request_test_document_page_view(self, document_page):
return self.get(
viewname='documents:document_page_view', kwargs={
'pk': document_page.pk,
}
)
class DocumentPageViewTestCase(
DocumentPageViewTestMixin, GenericDocumentViewTestCase
):
def test_document_page_list_view_no_permission(self): def test_document_page_list_view_no_permission(self):
response = self._request_test_document_page_list_view() response = self._request_test_document_page_list_view()
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
@@ -170,13 +181,6 @@ class DocumentPageViewTestCase(GenericDocumentViewTestCase):
response=response, text=self.test_document.label, status_code=200 response=response, text=self.test_document.label, status_code=200
) )
def _request_test_document_page_view(self, document_page):
return self.get(
viewname='documents:document_page_view', kwargs={
'pk': document_page.pk,
}
)
def test_document_page_view_no_permissions(self): def test_document_page_view_no_permissions(self):
response = self._request_test_document_page_view( response = self._request_test_document_page_view(
document_page=self.test_document.pages.first() document_page=self.test_document.pages.first()

View File

@@ -203,7 +203,7 @@ class DocumentTypeQuickLabelViewsTestCase(
) )
class DocumentsQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, GenericDocumentViewTestCase): class DocumentsQuickLabelViewTestMixin(object):
def _request_document_quick_label_edit_view(self, extra_data=None): def _request_document_quick_label_edit_view(self, extra_data=None):
data = { data = {
'document_type_available_filenames': self.test_document_type_filename.pk, 'document_type_available_filenames': self.test_document_type_filename.pk,
@@ -219,6 +219,11 @@ class DocumentsQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, GenericD
}, data=data }, data=data
) )
class DocumentsQuickLabelViewTestCase(
DocumentsQuickLabelViewTestMixin, DocumentTypeQuickLabelTestMixin,
GenericDocumentViewTestCase
):
def test_document_quick_label_no_permission(self): def test_document_quick_label_no_permission(self):
self._create_test_quick_label() self._create_test_quick_label()

View File

@@ -9,13 +9,24 @@ from .literals import TEST_VERSION_COMMENT
from .mixins import DocumentVersionTestMixin from .mixins import DocumentVersionTestMixin
class DocumentVersionTestCase(DocumentVersionTestMixin, GenericDocumentViewTestCase): class DocumentVersionViewTestMixin(object):
def _request_document_version_list_view(self): def _request_document_version_list_view(self):
return self.get( return self.get(
viewname='documents:document_version_list', viewname='documents:document_version_list',
kwargs={'pk': self.test_document.pk} kwargs={'pk': self.test_document.pk}
) )
def _request_document_version_revert_view(self, document_version):
return self.post(
viewname='documents:document_version_revert',
kwargs={'pk': document_version.pk}
)
class DocumentVersionViewTestCase(
DocumentVersionTestMixin, DocumentVersionViewTestMixin,
GenericDocumentViewTestCase
):
def test_document_version_list_no_permission(self): def test_document_version_list_no_permission(self):
self._upload_new_version() self._upload_new_version()
@@ -33,12 +44,6 @@ class DocumentVersionTestCase(DocumentVersionTestMixin, GenericDocumentViewTestC
response=response, text=TEST_VERSION_COMMENT, status_code=200 response=response, text=TEST_VERSION_COMMENT, status_code=200
) )
def _request_document_version_revert_view(self, document_version):
return self.post(
viewname='documents:document_version_revert',
kwargs={'pk': document_version.pk}
)
def test_document_version_revert_no_permission(self): def test_document_version_revert_no_permission(self):
first_version = self.test_document.latest_version first_version = self.test_document.latest_version
self._upload_new_version() self._upload_new_version()

View File

@@ -16,22 +16,14 @@ from ..permissions import (
from .base import GenericDocumentViewTestCase from .base import GenericDocumentViewTestCase
from .literals import ( from .literals import (
TEST_DOCUMENT_TYPE_2_LABEL, TEST_SMALL_DOCUMENT_FILENAME, TEST_DOCUMENT_TYPE_2_LABEL, TEST_SMALL_DOCUMENT_FILENAME
TEST_TRANSFORMATION_ARGUMENT, TEST_TRANSFORMATION_CLASS
) )
from .mixins import DocumentViewTestMixin from .mixins import DocumentViewTestMixin
class DocumentsViewsTestCase( class DocumentViewTestCase(
LayerTestMixin, DocumentViewTestMixin, GenericDocumentViewTestCase LayerTestMixin, DocumentViewTestMixin, GenericDocumentViewTestCase
): ):
def _create_document_transformation(self):
layer_saved_transformations.add_transformation_to(
obj=self.test_document.pages.first(),
transformation_class=TEST_TRANSFORMATION_CLASS,
arguments=TEST_TRANSFORMATION_ARGUMENT
)
def test_document_view_no_permissions(self): def test_document_view_no_permissions(self):
response = self._request_document_properties_view() response = self._request_document_properties_view()
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
@@ -302,13 +294,13 @@ class DocumentsViewsTestCase(
self.assertEqual(self.test_document.pages.count(), 0) self.assertEqual(self.test_document.pages.count(), 0)
def test_document_update_page_count_view_with_permission(self): def test_document_update_page_count_view_with_permission(self):
# TODO: Revise permission association
page_count = self.test_document.pages.count() page_count = self.test_document.pages.count()
self.test_document.pages.all().delete() self.test_document.pages.all().delete()
self.assertEqual(self.test_document.pages.count(), 0) self.assertEqual(self.test_document.pages.count(), 0)
self.grant_permission(permission=permission_document_tools) self.grant_access(
obj=self.test_document, permission=permission_document_tools
)
response = self._request_document_update_page_count_view() response = self._request_document_update_page_count_view()
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
@@ -329,7 +321,9 @@ class DocumentsViewsTestCase(
self.test_document.pages.all().delete() self.test_document.pages.all().delete()
self.assertEqual(self.test_document.pages.count(), 0) self.assertEqual(self.test_document.pages.count(), 0)
self.grant_permission(permission=permission_document_tools) self.grant_access(
obj=self.test_document, permission=permission_document_tools
)
response = self._request_document_multiple_update_page_count_view() response = self._request_document_multiple_update_page_count_view()
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)

View File

@@ -5,7 +5,7 @@ from ..permissions import permission_document_view
from .base import GenericDocumentViewTestCase from .base import GenericDocumentViewTestCase
class DuplicatedDocumentsViewsTestCase(GenericDocumentViewTestCase): class DuplicatedDocumentsViewsTestMixin(object):
def _upload_duplicate_document(self): def _upload_duplicate_document(self):
self.upload_document() self.upload_document()
@@ -18,6 +18,10 @@ class DuplicatedDocumentsViewsTestCase(GenericDocumentViewTestCase):
kwargs={'pk': self.test_documents[0].pk} kwargs={'pk': self.test_documents[0].pk}
) )
class DuplicatedDocumentsViewsTestCase(
DuplicatedDocumentsViewsTestMixin, GenericDocumentViewTestCase
):
def test_duplicated_document_list_no_permissions(self): def test_duplicated_document_list_no_permissions(self):
self._upload_duplicate_document() self._upload_duplicate_document()

View File

@@ -17,12 +17,23 @@ TEST_TRANSFORMATION_NAME = 'rotate'
TEST_TRANSFORMATION_ARGUMENT = 'degrees: 180' TEST_TRANSFORMATION_ARGUMENT = 'degrees: 180'
class DocumentEventsTestCase(GenericDocumentViewTestCase): class DocumentEventsTestMixin(object):
def _request_test_document_download_view(self): def _request_test_document_download_view(self):
return self.get( return self.get(
'documents:document_download', kwargs={'pk': self.test_document.pk} 'documents:document_download', kwargs={'pk': self.test_document.pk}
) )
def _request_test_document_preview_view(self):
return self.get(
viewname='documents:document_preview', kwargs={
'pk': self.test_document.pk
}
)
class DocumentEventsTestCase(
DocumentEventsTestMixin, GenericDocumentViewTestCase
):
def test_document_download_event_no_permissions(self): def test_document_download_event_no_permissions(self):
Action.objects.all().delete() Action.objects.all().delete()
@@ -55,13 +66,6 @@ class DocumentEventsTestCase(GenericDocumentViewTestCase):
self.assertEqual(event.target, self.test_document) self.assertEqual(event.target, self.test_document)
self.assertEqual(event.verb, event_document_download.id) self.assertEqual(event.verb, event_document_download.id)
def _request_test_document_preview_view(self):
return self.get(
viewname='documents:document_preview', kwargs={
'pk': self.test_document.pk
}
)
def test_document_view_event_no_permissions(self): def test_document_view_event_no_permissions(self):
Action.objects.all().delete() Action.objects.all().delete()

View File

@@ -6,13 +6,34 @@ from ..permissions import permission_document_view
from .base import GenericDocumentViewTestCase from .base import GenericDocumentViewTestCase
class FavoriteDocumentsTestCase(GenericDocumentViewTestCase): class FavoriteDocumentsTestMixin(object):
def _request_document_add_to_favorites_view(self): def _request_document_add_to_favorites_view(self):
return self.post( return self.post(
viewname='documents:document_add_to_favorites', viewname='documents:document_add_to_favorites',
kwargs={'pk': self.test_document.pk} kwargs={'pk': self.test_document.pk}
) )
def _document_add_to_favorites(self):
FavoriteDocument.objects.add_for_user(
document=self.test_document, user=self._test_case_user
)
def _request_document_list_favorites(self):
return self.get(
viewname='documents:document_list_favorites',
)
def _request_document_remove_from_favorites(self):
return self.post(
viewname='documents:document_remove_from_favorites',
kwargs={'pk': self.test_document.pk}
)
class FavoriteDocumentsTestCase(
FavoriteDocumentsTestMixin, GenericDocumentViewTestCase
):
def test_document_add_to_favorites_view_no_permission(self): def test_document_add_to_favorites_view_no_permission(self):
response = self._request_document_add_to_favorites_view() response = self._request_document_add_to_favorites_view()
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
@@ -26,16 +47,6 @@ class FavoriteDocumentsTestCase(GenericDocumentViewTestCase):
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
self.assertEqual(FavoriteDocument.objects.count(), 1) self.assertEqual(FavoriteDocument.objects.count(), 1)
def _document_add_to_favorites(self):
FavoriteDocument.objects.add_for_user(
document=self.test_document, user=self._test_case_user
)
def _request_document_list_favorites(self):
return self.get(
viewname='documents:document_list_favorites',
)
def test_document_list_favorites_view_no_permission(self): def test_document_list_favorites_view_no_permission(self):
self._document_add_to_favorites() self._document_add_to_favorites()
response = self._request_document_list_favorites() response = self._request_document_list_favorites()
@@ -53,12 +64,6 @@ class FavoriteDocumentsTestCase(GenericDocumentViewTestCase):
response=response, text=self.test_document.label, status_code=200 response=response, text=self.test_document.label, status_code=200
) )
def _request_document_remove_from_favorites(self):
return self.post(
viewname='documents:document_remove_from_favorites',
kwargs={'pk': self.test_document.pk}
)
def test_document_remove_from_favorites_view_no_permission(self): def test_document_remove_from_favorites_view_no_permission(self):
self._document_add_to_favorites() self._document_add_to_favorites()
response = self._request_document_remove_from_favorites() response = self._request_document_remove_from_favorites()

View File

@@ -89,7 +89,6 @@ class DocumentsLinksTestCase(GenericDocumentViewTestCase):
class DeletedDocumentsLinksTestCase(GenericDocumentViewTestCase): class DeletedDocumentsLinksTestCase(GenericDocumentViewTestCase):
def setUp(self): def setUp(self):
super(DeletedDocumentsLinksTestCase, self).setUp() super(DeletedDocumentsLinksTestCase, self).setUp()
self.login_user()
self.test_document.delete() self.test_document.delete()
self.test_deleted_document = DeletedDocument.objects.get( self.test_deleted_document = DeletedDocument.objects.get(
pk=self.test_document.pk pk=self.test_document.pk

View File

@@ -1,12 +1,12 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from mayan.apps.common.tests.base import BaseTestCase
from mayan.apps.documents.permissions import permission_document_view from mayan.apps.documents.permissions import permission_document_view
from mayan.apps.documents.search import document_search, document_page_search from mayan.apps.documents.search import document_search, document_page_search
from mayan.apps.documents.tests.mixins import DocumentTestMixin
from .base import GenericDocumentViewTestCase
class DocumentSearchTestCase(DocumentTestMixin, BaseTestCase): class DocumentSearchTestMixin(object):
def _perform_document_page_search(self): def _perform_document_page_search(self):
return document_page_search.search( return document_page_search.search(
query_string={'q': self.test_document.label}, user=self._test_case_user query_string={'q': self.test_document.label}, user=self._test_case_user
@@ -17,6 +17,10 @@ class DocumentSearchTestCase(DocumentTestMixin, BaseTestCase):
query_string={'q': self.test_document.label}, user=self._test_case_user query_string={'q': self.test_document.label}, user=self._test_case_user
) )
class DocumentSearchTestCase(
DocumentSearchTestMixin, GenericDocumentViewTestCase
):
def test_document_page_search_no_access(self): def test_document_page_search_no_access(self):
queryset = self._perform_document_page_search() queryset = self._perform_document_page_search()
self.assertFalse(self.test_document.pages.first() in queryset) self.assertFalse(self.test_document.pages.first() in queryset)

View File

@@ -9,7 +9,7 @@ from ..permissions import (
from .base import GenericDocumentViewTestCase from .base import GenericDocumentViewTestCase
class TrashedDocumentTestCase(GenericDocumentViewTestCase): class TrashedDocumentTestMixin(object):
def _request_document_restore_get_view(self): def _request_document_restore_get_view(self):
return self.get( return self.get(
viewname='documents:document_restore', kwargs={ viewname='documents:document_restore', kwargs={
@@ -17,6 +17,49 @@ class TrashedDocumentTestCase(GenericDocumentViewTestCase):
} }
) )
def _request_document_restore_post_view(self):
return self.post(
viewname='documents:document_restore', kwargs={
'pk': self.test_document.pk
}
)
def _request_document_trash_get_view(self):
return self.get(
viewname='documents:document_trash', kwargs={
'pk': self.test_document.pk
}
)
def _request_document_trash_post_view(self):
return self.post(
viewname='documents:document_trash', kwargs={
'pk': self.test_document.pk
}
)
def _request_document_delete_get_view(self):
return self.get(
viewname='documents:document_delete', kwargs={
'pk': self.test_document.pk
}
)
def _request_document_delete_post_view(self):
return self.post(
viewname='documents:document_delete', kwargs={
'pk': self.test_document.pk
}
)
def _request_document_list_deleted_view(self):
return self.get(viewname='documents:document_list_deleted')
class TrashedDocumentTestCase(
TrashedDocumentTestMixin, GenericDocumentViewTestCase
):
def test_document_restore_get_view_no_permission(self): def test_document_restore_get_view_no_permission(self):
self.test_document.delete() self.test_document.delete()
self.assertEqual(Document.objects.count(), 0) self.assertEqual(Document.objects.count(), 0)
@@ -43,13 +86,6 @@ class TrashedDocumentTestCase(GenericDocumentViewTestCase):
self.assertEqual(Document.objects.count(), document_count) self.assertEqual(Document.objects.count(), document_count)
def _request_document_restore_post_view(self):
return self.post(
viewname='documents:document_restore', kwargs={
'pk': self.test_document.pk
}
)
def test_document_restore_post_view_no_permission(self): def test_document_restore_post_view_no_permission(self):
self.test_document.delete() self.test_document.delete()
self.assertEqual(Document.objects.count(), 0) self.assertEqual(Document.objects.count(), 0)
@@ -74,13 +110,6 @@ class TrashedDocumentTestCase(GenericDocumentViewTestCase):
self.assertEqual(DeletedDocument.objects.count(), 0) self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 1) self.assertEqual(Document.objects.count(), 1)
def _request_document_trash_get_view(self):
return self.get(
viewname='documents:document_trash', kwargs={
'pk': self.test_document.pk
}
)
def test_document_trash_get_view_no_permissions(self): def test_document_trash_get_view_no_permissions(self):
document_count = Document.objects.count() document_count = Document.objects.count()
@@ -101,13 +130,6 @@ class TrashedDocumentTestCase(GenericDocumentViewTestCase):
self.assertEqual(Document.objects.count(), document_count) self.assertEqual(Document.objects.count(), document_count)
def _request_document_trash_post_view(self):
return self.post(
viewname='documents:document_trash', kwargs={
'pk': self.test_document.pk
}
)
def test_document_trash_post_view_no_permissions(self): def test_document_trash_post_view_no_permissions(self):
response = self._request_document_trash_post_view() response = self._request_document_trash_post_view()
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
@@ -126,13 +148,6 @@ class TrashedDocumentTestCase(GenericDocumentViewTestCase):
self.assertEqual(DeletedDocument.objects.count(), 1) self.assertEqual(DeletedDocument.objects.count(), 1)
self.assertEqual(Document.objects.count(), 0) self.assertEqual(Document.objects.count(), 0)
def _request_document_delete_get_view(self):
return self.get(
viewname='documents:document_delete', kwargs={
'pk': self.test_document.pk
}
)
def test_document_delete_get_view_no_permissions(self): def test_document_delete_get_view_no_permissions(self):
self.test_document.delete() self.test_document.delete()
self.assertEqual(Document.objects.count(), 0) self.assertEqual(Document.objects.count(), 0)
@@ -165,13 +180,6 @@ class TrashedDocumentTestCase(GenericDocumentViewTestCase):
DeletedDocument.objects.count(), trashed_document_count DeletedDocument.objects.count(), trashed_document_count
) )
def _request_document_delete_post_view(self):
return self.post(
viewname='documents:document_delete', kwargs={
'pk': self.test_document.pk
}
)
def test_document_delete_post_view_no_permissions(self): def test_document_delete_post_view_no_permissions(self):
self.test_document.delete() self.test_document.delete()
self.assertEqual(Document.objects.count(), 0) self.assertEqual(Document.objects.count(), 0)
@@ -198,9 +206,6 @@ class TrashedDocumentTestCase(GenericDocumentViewTestCase):
self.assertEqual(DeletedDocument.objects.count(), 0) self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 0) self.assertEqual(Document.objects.count(), 0)
def _request_document_list_deleted_view(self):
return self.get(viewname='documents:document_list_deleted')
def test_deleted_document_list_view_no_permissions(self): def test_deleted_document_list_view_no_permissions(self):
self.test_document.delete() self.test_document.delete()

View File

@@ -34,7 +34,7 @@ class DocumentUploadMetadataTestCase(MetadataTypeTestMixin, GenericDocumentViewT
def test_upload_interactive_with_unicode_metadata(self): def test_upload_interactive_with_unicode_metadata(self):
url = URL( url = URL(
path=reverse(viewname='sources:upload_interactive') path=reverse(viewname='sources:document_upload_interactive')
) )
url.args['metadata0_id'] = self.test_metadata_type.pk url.args['metadata0_id'] = self.test_metadata_type.pk
url.args['metadata0_value'] = TEST_METADATA_VALUE_UNICODE url.args['metadata0_value'] = TEST_METADATA_VALUE_UNICODE
@@ -61,7 +61,7 @@ class DocumentUploadMetadataTestCase(MetadataTypeTestMixin, GenericDocumentViewT
def test_upload_interactive_with_ampersand_metadata(self): def test_upload_interactive_with_ampersand_metadata(self):
url = URL( url = URL(
path=reverse(viewname='sources:upload_interactive') path=reverse(viewname='sources:document_upload_interactive')
) )
url.args['metadata0_id'] = self.test_metadata_type.pk url.args['metadata0_id'] = self.test_metadata_type.pk
url.args['metadata0_value'] = TEST_METADATA_VALUE_WITH_AMPERSAND url.args['metadata0_value'] = TEST_METADATA_VALUE_WITH_AMPERSAND

View File

@@ -145,8 +145,9 @@ class SourcesApp(MayanAppConfig):
menu_secondary.bind_links( menu_secondary.bind_links(
links=(link_document_version_upload,), links=(link_document_version_upload,),
sources=( sources=(
'documents:document_version_list', 'documents:upload_version', 'documents:document_version_list',
'documents:document_version_revert' 'documents:document_version_revert',
'sources:document_version_upload'
) )
) )

View File

@@ -23,14 +23,11 @@ class NewDocumentForm(DocumentForm):
class NewVersionForm(forms.Form): class NewVersionForm(forms.Form):
def __init__(self, *args, **kwargs): comment = forms.CharField(
super(NewVersionForm, self).__init__(*args, **kwargs) help_text=_('An optional comment to explain the upload.'),
label=_('Comment'), required=False,
self.fields['comment'] = forms.CharField( widget=forms.widgets.Textarea(attrs={'rows': 4}),
label=_('Comment'), )
required=False,
widget=forms.widgets.Textarea(attrs={'rows': 4}),
)
class UploadBaseForm(forms.Form): class UploadBaseForm(forms.Form):

View File

@@ -117,7 +117,7 @@ link_document_version_upload = Link(
args='resolved_object.pk', condition=document_new_version_not_blocked, args='resolved_object.pk', condition=document_new_version_not_blocked,
icon_class_path='mayan.apps.sources.icons.icon_document_version_upload', icon_class_path='mayan.apps.sources.icons.icon_document_version_upload',
permissions=(permission_document_new_version,), permissions=(permission_document_new_version,),
text=_('Upload new version'), view='sources:upload_version', text=_('Upload new version'), view='sources:document_version_upload',
) )
link_setup_source_logs = Link( link_setup_source_logs = Link(
args=('resolved_object.pk',), args=('resolved_object.pk',),

View File

@@ -0,0 +1,115 @@
{% load i18n %}
{% load static %}
<link href="{% static 'sources/node_modules/dropzone/dist/dropzone.css' %}" media="screen" rel="stylesheet" type="text/css" />
<style>
.dropzone .dz-preview .dz-details {
top: 25px;
}
.dropzone .dz-preview .dz-progress {
top: 60%;
}
.dropzone .dz-preview .dz-error-message {
top: 130px;
}
.dropzone-previews, .dropzone .dz-message {
border: 2px solid rgba(0, 0, 0, 0.3);
padding: 40px 20px;
}
.dropzone .dz-preview .dz-error-message {
overflow-wrap: break-word;
padding: 1.2em;
top: 180px;
}
.dropzone .dz-preview .dz-details .dz-filename span,
.dropzone .dz-preview .dz-details .dz-size span {
padding: 0px;
}
.dropzone {
min-height: 150px;
border: inherit;
background: inherit;
padding: 0px;
}
.dropzone-previews, .dropzone .dz-message {
background: white;
}
}
</style>
<script type="text/x-template" id="previewTemplate">
<div class="dz-preview dz-file-preview">
<i class="far fa-file fa-10x"></i>
<div class="dz-details">
<div class="dz-filename"><span data-dz-name></span></div>
<div class="dz-size" data-dz-size></div>
<img data-dz-thumbnail />
</div>
<div class="dz-progress">
<span class="dz-upload" data-dz-uploadprogress>
<div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" style="width: 100%">
</div>
</span>
</div>
<div class="dz-success-mark">
<span>
<i class="text-success fa fa-4x fa-check-circle"></i>
</span>
</div>
<div class="dz-error-mark">
<span>
<i class="text-danger fa fa-4x fa-times-circle"></i>
</span>
</div>
<div class="dz-error-message">
<span data-dz-errormessage>
</span>
</div>
</div>
</script>
<script>
var messageCancelUpload = "{% trans 'Cancel upload' %}";
var messageCancelUploadConfirmation = "{% trans 'Are you sure you want to cancel this upload?' %}";
var messageDefaultMessage = "{% trans 'Drop files or click here to upload files' %}";
var messageFallbackMessage = "{% trans 'Your browser does not support drag and drop file uploads.' %}";
var messageFallbackText = "{% trans 'Please use the fallback form below to upload your files.' %}";
var messageRemoveFile = "{% trans 'Clear' %}";
var messageResponseError = "{% trans 'Server responded with {{statusCode}} code.' %}";
$.getScript( "{% static 'sources/node_modules/dropzone/dist/dropzone.js' %}" )
.done(function( script, textStatus ) {
Dropzone.autoDiscover = false;
jQuery(document).ready(function() {
var previewTemplate = document.querySelector('#previewTemplate').innerHTML;
{% verbatim %}
$('.dropzone').dropzone({
addRemoveLinks: true,
createImageThumbnails: false,
dictCancelUpload: messageCancelUpload,
dictCancelUploadConfirmation: messageCancelUploadConfirmation,
dictDefaultMessage: '<i class="fa fa-cloud-upload-alt"></i> ' + messageDefaultMessage,
dictFallbackMessage: messageFallbackMessage,
dictFallbackText: messageFallbackText,
dictRemoveFile: messageRemoveFile,
dictResponseError: messageResponseError,
maxFilesize: 2048,
paramName: 'source-file',
previewTemplate: previewTemplate,
timeout: 1200000
});
{% endverbatim %}
});
});
</script>

View File

@@ -1,118 +1,2 @@
{% load i18n %}
{% load static %}
<link href="{% static 'sources/node_modules/dropzone/dist/dropzone.css' %}" media="screen" rel="stylesheet" type="text/css" />
<style>
.dropzone .dz-preview .dz-details {
top: 25px;
}
.dropzone .dz-preview .dz-progress {
top: 60%;
}
.dropzone .dz-preview .dz-error-message {
top: 130px;
}
.dropzone-previews, .dropzone .dz-message {
border: 2px solid rgba(0, 0, 0, 0.3);
padding: 40px 20px;
}
.dropzone .dz-preview .dz-error-message {
overflow-wrap: break-word;
padding: 1.2em;
top: 180px;
}
.dropzone .dz-preview .dz-details .dz-filename span,
.dropzone .dz-preview .dz-details .dz-size span {
padding: 0px;
}
.dropzone {
min-height: 150px;
border: inherit;
background: inherit;
padding: 0px;
}
.dropzone-previews, .dropzone .dz-message {
background: white;
}
}
</style>
{% include 'appearance/generic_multiform_subtemplate.html' %} {% include 'appearance/generic_multiform_subtemplate.html' %}
{% include 'sources/dropzone.html' %}
<script type="text/x-template" id="previewTemplate">
<div class="dz-preview dz-file-preview">
<i class="far fa-file fa-10x"></i>
<div class="dz-details">
<div class="dz-filename"><span data-dz-name></span></div>
<div class="dz-size" data-dz-size></div>
<img data-dz-thumbnail />
</div>
<div class="dz-progress">
<span class="dz-upload" data-dz-uploadprogress>
<div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" style="width: 100%">
</div>
</span>
</div>
<div class="dz-success-mark">
<span>
<i class="text-success fa fa-4x fa-check-circle"></i>
</span>
</div>
<div class="dz-error-mark">
<span>
<i class="text-danger fa fa-4x fa-times-circle"></i>
</span>
</div>
<div class="dz-error-message">
<span data-dz-errormessage>
</span>
</div>
</div>
</script>
<script>
var messageCancelUpload = "{% trans 'Cancel upload' %}";
var messageCancelUploadConfirmation = "{% trans 'Are you sure you want to cancel this upload?' %}";
var messageDefaultMessage = "{% trans 'Drop files or click here to upload files' %}";
var messageFallbackMessage = "{% trans 'Your browser does not support drag and drop file uploads.' %}";
var messageFallbackText = "{% trans 'Please use the fallback form below to upload your files.' %}";
var messageRemoveFile = "{% trans 'Clear' %}";
var messageResponseError = "{% trans 'Server responded with {{statusCode}} code.' %}";
$.getScript( "{% static 'sources/node_modules/dropzone/dist/dropzone.js' %}" )
.done(function( script, textStatus ) {
Dropzone.autoDiscover = false;
jQuery(document).ready(function() {
var previewTemplate = document.querySelector('#previewTemplate').innerHTML;
{% verbatim %}
$('.dropzone').dropzone({
addRemoveLinks: true,
createImageThumbnails: false,
dictCancelUpload: messageCancelUpload,
dictCancelUploadConfirmation: messageCancelUploadConfirmation,
dictDefaultMessage: '<i class="fa fa-cloud-upload-alt"></i> ' + messageDefaultMessage,
dictFallbackMessage: messageFallbackMessage,
dictFallbackText: messageFallbackText,
dictRemoveFile: messageRemoveFile,
dictResponseError: messageResponseError,
maxFilesize: 2048,
paramName: 'source-file',
previewTemplate: previewTemplate,
timeout: 1200000
});
{% endverbatim %}
});
});
</script>

View File

@@ -7,6 +7,13 @@ from .literals import TEST_SOURCE_LABEL, TEST_SOURCE_UNCOMPRESS_N
class SourceTestMixin(object): class SourceTestMixin(object):
auto_create_test_source = True
def setUp(self):
super(SourceTestMixin, self).setUp()
if self.auto_create_test_source:
self._create_test_source()
def _create_test_source(self): def _create_test_source(self):
self.test_source = WebFormSource.objects.create( self.test_source = WebFormSource.objects.create(
enabled=True, label=TEST_SOURCE_LABEL, enabled=True, label=TEST_SOURCE_LABEL,

View File

@@ -39,7 +39,6 @@ class CompressedUploadsTestCase(SourceTestMixin, GenericDocumentTestCase):
auto_upload_document = False auto_upload_document = False
def test_upload_compressed_file(self): def test_upload_compressed_file(self):
self._create_test_source()
self.test_source.uncompress = SOURCE_UNCOMPRESS_CHOICE_Y self.test_source.uncompress = SOURCE_UNCOMPRESS_CHOICE_Y
self.test_source.save() self.test_source.save()

View File

@@ -32,7 +32,7 @@ class DocumentUploadWizardViewTestMixin(object):
def _request_upload_wizard_view(self, document_path=TEST_SMALL_DOCUMENT_PATH): def _request_upload_wizard_view(self, document_path=TEST_SMALL_DOCUMENT_PATH):
with open(document_path, mode='rb') as file_object: with open(document_path, mode='rb') as file_object:
return self.post( return self.post(
viewname='sources:upload_interactive', kwargs={ viewname='sources:document_upload_interactive', kwargs={
'source_id': self.test_source.pk 'source_id': self.test_source.pk
}, data={ }, data={
'source-file': file_object, 'source-file': file_object,
@@ -42,7 +42,7 @@ class DocumentUploadWizardViewTestMixin(object):
def _request_upload_interactive_view(self): def _request_upload_interactive_view(self):
return self.get( return self.get(
viewname='sources:upload_interactive', data={ viewname='sources:document_upload_interactive', data={
'document_type_id': self.test_document_type.pk, 'document_type_id': self.test_document_type.pk,
} }
) )
@@ -54,10 +54,6 @@ class DocumentUploadWizardViewTestCase(
): ):
auto_upload_document = False auto_upload_document = False
def setUp(self):
super(DocumentUploadWizardViewTestCase, self).setUp()
self._create_test_source()
def test_upload_compressed_file(self): def test_upload_compressed_file(self):
self.test_source.uncompress = SOURCE_UNCOMPRESS_CHOICE_Y self.test_source.uncompress = SOURCE_UNCOMPRESS_CHOICE_Y
self.test_source.save() self.test_source.save()
@@ -113,7 +109,7 @@ class DocumentUploadWizardViewTestCase(
with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object: with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object:
response = self.post( response = self.post(
viewname='sources:upload_interactive', kwargs={ viewname='sources:document_upload_interactive', kwargs={
'source_id': self.test_source.pk 'source_id': self.test_source.pk
}, data={ }, data={
'source-file': file_object, 'source-file': file_object,
@@ -157,7 +153,7 @@ class DocumentUploadIssueTestCase(GenericDocumentViewTestCase):
# Upload the test document # Upload the test document
with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object: with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object:
self.post( self.post(
viewname='sources:upload_interactive', data={ viewname='sources:document_upload_interactive', data={
'document-language': 'eng', 'document-language': 'eng',
'source-file': file_object, 'source-file': file_object,
'document_type_id': self.test_document_type.pk 'document_type_id': self.test_document_type.pk
@@ -207,7 +203,7 @@ class NewDocumentVersionViewTestCase(GenericDocumentViewTestCase):
NewVersionBlock.objects.block(self.test_document) NewVersionBlock.objects.block(self.test_document)
response = self.post( response = self.post(
viewname='sources:upload_version', kwargs={ viewname='sources:document_version_upload', kwargs={
'document_pk': self.test_document.pk 'document_pk': self.test_document.pk
}, follow=True }, follow=True
) )
@@ -300,6 +296,8 @@ class StagingFolderViewTestCase(
class SourcesViewTestCase( class SourcesViewTestCase(
SourceTestMixin, SourceViewTestMixin, GenericViewTestCase SourceTestMixin, SourceViewTestMixin, GenericViewTestCase
): ):
auto_create_test_source = False
def test_source_create_view_no_permission(self): def test_source_create_view_no_permission(self):
response = self._request_setup_source_create_view() response = self._request_setup_source_create_view()
self.assertEqual(response.status_code, 403) self.assertEqual(response.status_code, 403)

View File

@@ -9,7 +9,7 @@ from .api_views import (
from .views import ( from .views import (
SetupSourceCheckView, SetupSourceCreateView, SetupSourceDeleteView, SetupSourceCheckView, SetupSourceCreateView, SetupSourceDeleteView,
SetupSourceEditView, SetupSourceListView, SourceLogListView, SetupSourceEditView, SetupSourceListView, SourceLogListView,
StagingFileDeleteView, UploadInteractiveVersionView, UploadInteractiveView StagingFileDeleteView, DocumentVersionUploadInteractiveView, UploadInteractiveView
) )
from .wizards import DocumentCreateWizard from .wizards import DocumentCreateWizard
@@ -27,19 +27,23 @@ urlpatterns = [
), ),
url( url(
regex=r'^documents/upload/new/interactive/(?P<source_id>\d+)/$', regex=r'^documents/upload/new/interactive/(?P<source_id>\d+)/$',
view=UploadInteractiveView.as_view(), name='upload_interactive' view=UploadInteractiveView.as_view(),
name='document_upload_interactive'
), ),
url( url(
regex=r'^documents/upload/new/interactive/$', regex=r'^documents/upload/new/interactive/$',
view=UploadInteractiveView.as_view(), name='upload_interactive' view=UploadInteractiveView.as_view(),
name='document_upload_interactive'
), ),
url( url(
regex=r'^documents/(?P<document_pk>\d+)/versions/upload/interactive/(?P<source_id>\d+)/$', regex=r'^documents/(?P<document_pk>\d+)/versions/upload/interactive/(?P<source_id>\d+)/$',
view=UploadInteractiveVersionView.as_view(), name='upload_version' view=DocumentVersionUploadInteractiveView.as_view(),
name='document_version_upload'
), ),
url( url(
regex=r'^documents/(?P<document_pk>\d+)/versions/upload/interactive/$', regex=r'^documents/(?P<document_pk>\d+)/versions/upload/interactive/$',
view=UploadInteractiveVersionView.as_view(), name='upload_version' view=DocumentVersionUploadInteractiveView.as_view(),
name='document_version_upload'
), ),
# Setup views # Setup views

View File

@@ -84,10 +84,10 @@ class UploadBaseView(MultiFormView):
@staticmethod @staticmethod
def get_tab_link_for_source(source, document=None): def get_tab_link_for_source(source, document=None):
if document: if document:
view = 'sources:upload_version' view = 'sources:document_version_upload'
args = ('"{}"'.format(document.pk), '"{}"'.format(source.pk),) args = ('"{}"'.format(document.pk), '"{}"'.format(source.pk),)
else: else:
view = 'sources:upload_interactive' view = 'sources:document_upload_interactive'
args = ('"{}"'.format(source.pk),) args = ('"{}"'.format(source.pk),)
return Link( return Link(
@@ -180,8 +180,8 @@ class UploadBaseView(MultiFormView):
}, },
}) })
menu_facet.bound_links['sources:upload_interactive'] = self.tab_links menu_facet.bound_links['sources:document_upload_interactive'] = self.tab_links
menu_facet.bound_links['sources:upload_version'] = self.tab_links menu_facet.bound_links['sources:document_version_upload'] = self.tab_links
context.update( context.update(
{ {
@@ -360,7 +360,7 @@ class UploadInteractiveView(UploadBaseView):
return context return context
class UploadInteractiveVersionView(UploadBaseView): class DocumentVersionUploadInteractiveView(UploadBaseView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.subtemplates_list = [] self.subtemplates_list = []
@@ -392,7 +392,7 @@ class UploadInteractiveVersionView(UploadBaseView):
self.tab_links = UploadBaseView.get_active_tab_links(self.document) self.tab_links = UploadBaseView.get_active_tab_links(self.document)
return super( return super(
UploadInteractiveVersionView, self DocumentVersionUploadInteractiveView, self
).dispatch(request, *args, **kwargs) ).dispatch(request, *args, **kwargs)
def forms_valid(self, forms): def forms_valid(self, forms):
@@ -448,27 +448,36 @@ class UploadInteractiveVersionView(UploadBaseView):
files=kwargs.get('files', None), files=kwargs.get('files', None),
) )
def create_document_form_form(self, **kwargs):
return self.get_form_classes()['document_form'](
prefix=kwargs['prefix'],
data=kwargs.get('data', None),
files=kwargs.get('files', None),
)
def get_form_classes(self): def get_form_classes(self):
source_form_class = get_upload_form_class(self.source.source_type)
# Override source form class to enable the HTML5 file uploader
if source_form_class == WebFormUploadForm:
source_form_class = WebFormUploadFormHTML5
return { return {
'document_form': NewVersionForm, 'document_form': NewVersionForm,
'source_form': get_upload_form_class(self.source.source_type) 'source_form': source_form_class
} }
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super( context = super(
UploadInteractiveVersionView, self DocumentVersionUploadInteractiveView, self
).get_context_data(**kwargs) ).get_context_data(**kwargs)
context['object'] = self.document context['object'] = self.document
context['title'] = _( context['title'] = _(
'Upload a new version from source: %s' 'Upload a new version for document "%(document)s" '
) % self.source.label 'from source: %(source)s'
) % {'document': self.document, 'source': self.source.label}
context['submit_label'] = _('Submit')
context['form_css_classes'] = 'dropzone'
context['form_disable_submit'] = True
context['form_action'] = '{}?{}'.format(
reverse(
viewname=self.request.resolver_match.view_name,
kwargs=self.request.resolver_match.kwargs
), self.request.META['QUERY_STRING']
)
return context return context

View File

@@ -201,7 +201,7 @@ class DocumentCreateWizard(SessionWizardView):
for step in WizardStep.get_all(): for step in WizardStep.get_all():
query_dict.update(step.done(wizard=self) or {}) query_dict.update(step.done(wizard=self) or {})
url = furl(reverse(viewname='sources:upload_interactive')) url = furl(reverse(viewname='sources:document_upload_interactive'))
# Use equal and not .update() to get the same result as using # Use equal and not .update() to get the same result as using
# urlencode(doseq=True) # urlencode(doseq=True)
url.args = query_dict url.args = query_dict

View File

@@ -27,7 +27,7 @@ class TaggedDocumentUploadTestCase(TagTestMixin, GenericDocumentViewTestCase):
def _request_upload_interactive_document_create_view(self): def _request_upload_interactive_document_create_view(self):
with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object: with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object:
return self.post( return self.post(
viewname='sources:upload_interactive', kwargs={ viewname='sources:document_upload_interactive', kwargs={
'source_id': self.test_source.pk 'source_id': self.test_source.pk
}, data={ }, data={
'document_type_id': self.test_document_type.pk, 'document_type_id': self.test_document_type.pk,

View File

@@ -8,6 +8,7 @@ from mayan.apps.common.menus import menu_tools
from mayan.apps.navigation.classes import SourceColumn from mayan.apps.navigation.classes import SourceColumn
from .classes import CeleryQueue, Task from .classes import CeleryQueue, Task
from .dependencies import * # NOQA
from .links import link_task_manager from .links import link_task_manager
from .settings import * # NOQA from .settings import * # NOQA

View File

@@ -7,7 +7,6 @@ django-celery-beat==1.5.0
django-colorful==1.3 django-colorful==1.3
django-cors-headers==2.5.2 django-cors-headers==2.5.2
django-downloadview==1.9 django-downloadview==1.9
django-environ==0.4.5
django-formtools==2.1 django-formtools==2.1
django-mathfilters==0.4.0 django-mathfilters==0.4.0
django-model-utils==3.1.2 django-model-utils==3.1.2

View File

@@ -66,7 +66,6 @@ django-celery-beat==1.5.0
django-colorful==1.3 django-colorful==1.3
django-cors-headers==2.5.2 django-cors-headers==2.5.2
django-downloadview==1.9 django-downloadview==1.9
django-environ==0.4.5
django-formtools==2.1 django-formtools==2.1
django-mathfilters==0.4.0 django-mathfilters==0.4.0
django-model-utils==3.1.2 django-model-utils==3.1.2