Merge branch 'development' into feature/multi-tenant

This commit is contained in:
Roberto Rosario
2016-05-22 17:47:12 -04:00
10 changed files with 328 additions and 10 deletions

View File

@@ -1,3 +1,9 @@
2.1.2 (2016-05-20)
==================
- Sort document languages and user profile locale language lists. GitLab issue #292.
- Fix metadata lookup for {{ users }} and {{ group }}. Fixes GitLab #290.
- Add Makefile for common development tasks
2.1.1 (2016-05-17)
==================
- Fix navigation issue that make it impossible to add new sources. GitLab issue #288.

113
Makefile Normal file
View File

@@ -0,0 +1,113 @@
.PHONY: clean-pyc clean-build
define BROWSER_PYSCRIPT
import sys, webbrowser
webbrowser.open(sys.argv[1])
endef
export BROWSER_PYSCRIPT
BROWSER := python -c "$$BROWSER_PYSCRIPT"
help:
@echo
@echo "clean-build - Remove build artifacts."
@echo "clean-pyc - Remove Python artifacts."
@echo "clean - Remove Python and build artifacts."
@echo "test MODULE=<python module name> - Run tests for a single App, module or test class."
@echo "test-all - Run all tests."
@echo "docs_serve - Run the livehtml documentation generator."
@echo "translations_make - Refresh all translation files."
@echo "translations_compile - Compile all translation files."
@echo "translations_push - Upload all translation files to Transifex."
@echo "translations_pull - Download all translation files from Transifex."
@echo "requirements_dev - Install development requirements."
@echo "requirements_docs - Install documentation requirements."
@echo "requirements_testing - Install testing requirements."
@echo "sdist - Build the source distribution package."
@echo "wheel - Build the wheel distribution package."
@echo "release - Package (sdist and wheel) and upload a release."
@echo "runserver - Run the development server."
# Cleaning
clean: clean-build clean-pyc
clean-build:
rm -fr build/
rm -fr dist/
rm -fr *.egg-info
clean-pyc:
find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} +
find . -name '*~' -exec rm -f {} +
# Testing
test:
./manage.py test $(MODULE) --settings=mayan.settings.testing --nomigrations
test-all:
./manage.py runtests --settings=mayan.settings.testing --nomigrations
# Documentation
docs_serve:
$(BROWSER) http://127.0.0.1:8000
cd docs;make livehtml
# Translations
translations_make:
contrib/scripts/process_messages.py -m
translations_compile:
contrib/scripts/process_messages.py -c
translations_push:
tx push -s
translations_pull:
tx pull
# Requirements
requirements_dev:
pip install -r requirements/development.txt
requirements_docs:
pip install -r requirements/documentation.txt
requirements_testing:
pip install -r requirements/testing.txt
# Releases
release: clean
python setup.py sdist bdist_wheel upload
sdist: clean
python setup.py sdist
ls -l dist
wheel: clean
python setup.py bdist_wheel
ls -l dist
# Dev server
runserver:
$(BROWSER) http://127.0.0.1:8000
./manage.py runserver

86
docs/releases/2.1.2.rst Normal file
View File

@@ -0,0 +1,86 @@
===============================
Mayan EDMS v2.1.2 release notes
===============================
Released: May 20, 2016
What's new
==========
This is a bugfix release and all users are encouraged to upgrade.
Language list sorting
---------------------
The document language list and the user locale profile language list are now
sorted to make it easier to find the desired language.
Fixed the metadata lookup options: {{ users }} and {{ groups }}
---------------------------------------------------------------
When configuring metadata type lookup options the {{ users }} and {{ groups }}
special options can be used to display a list of users or a list of groups.
These options where producing a list in the wrong format and were updated.
Other changes
-------------
- Add Makefile for common development tasks
Removals
--------
* None
Upgrading from a previous version
---------------------------------
Using PIP
~~~~~~~~~
Type in the console::
$ pip install -U mayan-edms
the requirements will also be updated automatically.
Using Git
~~~~~~~~~
If you installed Mayan EDMS by cloning the Git repository issue the commands::
$ git reset --hard HEAD
$ git pull
otherwise download the compressed archived and uncompress it overriding the
existing installation.
Next upgrade/add the new requirements::
$ pip install --upgrade -r requirements.txt
Common steps
~~~~~~~~~~~~
Migrate existing database schema with::
$ mayan-edms.py performupgrade
Add new static media::
$ mayan-edms.py collectstatic --noinput
The upgrade procedure is now complete.
Backward incompatible changes
=============================
* None
Bugs fixed or issues closed
===========================
* `GitLab issue #290 <https://gitlab.com/mayan-edms/mayan-edms/issues/290>`_ Unicode characters not supported as metadata values
* `GitLab issue #292 <https://gitlab.com/mayan-edms/mayan-edms/issues/292>`_ Sort languages by name not by abbreviation
.. _PyPI: https://pypi.python.org/pypi/mayan-edms/

View File

@@ -22,6 +22,7 @@ versions of the documentation contain the release notes for any later releases.
.. toctree::
:maxdepth: 1
2.1.2
2.1.1
2.1
2.0.2

View File

@@ -1,8 +1,8 @@
from __future__ import unicode_literals
__title__ = 'Mayan EDMS'
__version__ = '2.1.1'
__build__ = 0x020101
__version__ = '2.1.2'
__build__ = 0x020102
__author__ = 'Roberto Rosario'
__author_email__ = 'roberto.rosario@mayan-edms.com'
__description__ = 'Free Open Source Electronic Document Management System'

View File

@@ -1,5 +1,6 @@
from __future__ import unicode_literals
from operator import itemgetter
import os
from django import forms
@@ -114,10 +115,44 @@ class LicenseForm(FileDisplayForm):
FILENAME = 'LICENSE'
class LocaleProfileForm(forms.ModelForm):
class ModelForm(forms.ModelForm):
"""
ModelForm subclass that supports field choices sorting
class Meta:
# Dictionary of field names and the key used to sort the field
sorted_fields = None
# Example:
# sorted_fields = {'language': operator.itemgetter(1))}
"""
def __init__(self, *args, **kwargs):
super(ModelForm, self).__init__(*args, **kwargs)
for field, key in getattr(self.Meta, 'sorted_fields', {}).items():
# Would be the cleaner "opts.sorted_fields" if these were addressed
# https://code.djangoproject.com/ticket/5793
# of a get_options_class for Forms/ModelForms
# https://code.djangoproject.com/ticket/18540
choices = self.fields[field].choices
if not self.fields[field].required:
# Remove empty choice before sorting
empty_choice = choices.pop(0)
self.fields[field].choices = sorted(choices, key=key)
if not self.fields[field].required:
# Add empty choice after sorting
self.fields[field].choices.insert(0, empty_choice)
class LocaleProfileForm(ModelForm):
class Meta:
fields = ('language', 'timezone')
model = UserLocaleProfile
sorted_fields = {'language': itemgetter(1)}
class LocaleProfileForm_view(DetailForm):

View File

@@ -1,6 +1,7 @@
from __future__ import absolute_import, unicode_literals
import logging
from operator import itemgetter
from django import forms
from django.core.exceptions import PermissionDenied
@@ -8,7 +9,7 @@ from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext_lazy as _
from acls.models import AccessControlList
from common.forms import DetailForm
from common.forms import DetailForm, ModelForm
from permissions import Permission
from .models import (
@@ -60,13 +61,14 @@ class DocumentPreviewForm(forms.Form):
preview = forms.CharField(widget=DocumentPagesCarouselWidget())
class DocumentForm(forms.ModelForm):
class DocumentForm(ModelForm):
"""
Form sub classes from DocumentForm used only when editing a document
"""
class Meta:
model = Document
fields = ('label', 'description', 'language')
model = Document
sorted_fields = {'language': itemgetter(1)}
def __init__(self, *args, **kwargs):
document_type = kwargs.pop('document_type', None)

View File

@@ -29,7 +29,10 @@ class MetadataLookup(object):
def get_as_context(cls):
result = {}
for entry in cls._registry:
result[entry.name] = entry.value
try:
result[entry.name] = entry.value()
except TypeError:
result[entry.name] = entry.value
return result

View File

@@ -22,6 +22,14 @@ from .links import (
)
def get_groups():
return ','.join([group.name for group in Group.objects.all()])
def get_users():
return ','.join([user.get_full_name() or user.username for user in get_user_model().objects.all()])
class UserManagementApp(MayanAppConfig):
app_url = 'accounts'
name = 'user_management'
@@ -36,12 +44,12 @@ class UserManagementApp(MayanAppConfig):
APIEndPoint(app=self, version_string='1')
MetadataLookup(
description=_('All the groups.'), name='group',
value=Group.objects.all()
description=_('All the groups.'), name='groups',
value=get_groups
)
MetadataLookup(
description=_('All the users.'), name='users',
value=User.objects.all()
value=get_users
)
SourceColumn(

View File

@@ -1,8 +1,17 @@
from __future__ import unicode_literals
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from common.tests.test_views import GenericViewTestCase
from documents.tests.test_views import GenericDocumentViewTestCase
from metadata.models import MetadataType
from metadata.permissions import permission_metadata_document_edit
from metadata.tests.literals import (
TEST_METADATA_TYPE_LABEL, TEST_METADATA_TYPE_NAME,
)
from ..permissions import (
permission_user_delete, permission_user_edit, permission_user_view
@@ -179,3 +188,58 @@ class UserManagementViewTestCase(GenericViewTestCase):
self.assertContains(response, text='deleted', status_code=200)
self.assertEqual(get_user_model().objects.count(), 2)
class MetadataLookupIntegrationTestCase(GenericDocumentViewTestCase):
def setUp(self):
super(MetadataLookupIntegrationTestCase, self).setUp()
self.metadata_type = MetadataType.objects.create(
name=TEST_METADATA_TYPE_NAME, label=TEST_METADATA_TYPE_LABEL
)
self.document_type.metadata.create(metadata_type=self.metadata_type)
def test_user_list_lookup_render(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
self.metadata_type.lookup = '{{ users }}'
self.metadata_type.save()
self.document.metadata.create(metadata_type=self.metadata_type)
self.role.permissions.add(
permission_metadata_document_edit.stored_permission
)
response = self.get(
viewname='metadata:metadata_edit', args=(self.document.pk,)
)
self.assertContains(
response, text='<option value="{}">{}</option>'.format(
TEST_USER_USERNAME, TEST_USER_USERNAME
), status_code=200
)
def test_group_list_lookup_render(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
self.metadata_type.lookup = '{{ groups }}'
self.metadata_type.save()
self.document.metadata.create(metadata_type=self.metadata_type)
self.role.permissions.add(
permission_metadata_document_edit.stored_permission
)
response = self.get(
viewname='metadata:metadata_edit', args=(self.document.pk,)
)
self.assertContains(
response, text='<option value="{}">{}</option>'.format(
Group.objects.first().name, Group.objects.first().name
), status_code=200
)