Merge branch 'pfwb' into stable
This commit is contained in:
commit
c6e6f54597
14
README.rst
14
README.rst
|
@ -190,12 +190,24 @@ one is potentially localized, for example to add a link to google, add this line
|
|||
Settings
|
||||
--------
|
||||
|
||||
All settings must be donne in the file ``/etc/docbow/local_settings.py``. Available settings arr:
|
||||
All settings must be donne in the file ``/etc/docbow/local_settings.py``. Available settings are:
|
||||
|
||||
* ``DOCBOW_ORGANIZATION``: an unicode string giving a description of the
|
||||
organization providing the platform. It's used as a signature in mail and
|
||||
sms notifications.
|
||||
* ``DOCBOW_BASE_URL``: the base URL of the application. It's used for building
|
||||
URL in notifications, emails or SMS.
|
||||
* ``DOCBOW_MENU``: description of the left column menu; see previous section
|
||||
for a description and the default value.
|
||||
* ``DOCBOW_MAILBOX_PER_PAGE``: the number of message to show on listing pages.
|
||||
Default is 20.
|
||||
* ``RAVEN_CONFIG_DSN``: the URL of the sentry project for gathering exceptions.
|
||||
* ``DOCBOW_MAX_FILE_SIZE``: the maximum file size for attached files, as
|
||||
bytes. Default is 10 Mo.
|
||||
* ``DOCBOW_TRUNCATE_FILENAME``: the maximum length for filenames. Default is
|
||||
80 unicode characters (codepoints).
|
||||
* ``DOCBOW_TIMESTAMP_PROVIDER``: the timestamp provider to use. Default is certum.
|
||||
Other possibilities are fedit and e_szigno.
|
||||
|
||||
Customizing templates
|
||||
---------------------
|
||||
|
|
|
@ -55,6 +55,9 @@ class MailingListAdmin(admin.ModelAdmin):
|
|||
actions = [ actions.export_as_csv ]
|
||||
|
||||
def get_actions(self, request):
|
||||
'''Show delete actions only if user has delete rights
|
||||
Show activation actions only if user has rights to change mailing lists
|
||||
'''
|
||||
a = super(MailingListAdmin, self).get_actions(request)
|
||||
if request.user.has_perm('docbow.delete_mailinglist'):
|
||||
a['delete_selected'] = self.get_action('delete_selected')
|
||||
|
@ -131,7 +134,7 @@ class DocbowGroupAdmin(auth_admin.GroupAdmin):
|
|||
|
||||
|
||||
class MailboxAdmin(admin.ModelAdmin):
|
||||
list_display = [ 'owner', 'document', 'date', 'seen' ]
|
||||
list_display = [ 'owner', 'document', 'date' ]
|
||||
list_filter = [ 'owner', 'outbox' ]
|
||||
|
||||
def lookup_allowed(self, *args, **kwargs):
|
||||
|
@ -140,9 +143,9 @@ class MailboxAdmin(admin.ModelAdmin):
|
|||
|
||||
|
||||
class InboxAdmin(MailboxAdmin):
|
||||
list_display = [ 'date', 'owner', 'document', 'seen', 'deleted' ]
|
||||
fields = [ 'date', 'owner', 'document', 'seen', 'deleted' ]
|
||||
readonly_fields = [ 'date', 'owner', 'document', 'seen' ]
|
||||
list_display = [ 'date', 'owner', 'document' ]
|
||||
fields = [ 'date', 'owner', 'document' ]
|
||||
readonly_fields = [ 'date', 'owner', 'document' ]
|
||||
|
||||
def queryset(self, request):
|
||||
'''Only show input mailboxes'''
|
||||
|
|
|
@ -36,6 +36,10 @@ class AppSettings(object):
|
|||
def TRUNCATE_FILENAME(self):
|
||||
return getattr(self.settings, 'DOCBOW_TRUNCATE_FILENAME', 80)
|
||||
|
||||
@property
|
||||
def MAX_FILE_SIZE(self):
|
||||
return getattr(self.settings, 'DOCBOW_MAX_FILE_SIZE', 10*1024*1024)
|
||||
|
||||
import sys
|
||||
|
||||
app_settings = AppSettings()
|
||||
|
|
|
@ -13,7 +13,11 @@ def order_choices(choices):
|
|||
|
||||
def order_field_choices(field):
|
||||
'''Order choices of this field'''
|
||||
field.choices = order_choices(field.choices)
|
||||
choices = list(field.choices)
|
||||
|
||||
field.choices = [choice for choice in choices if choice[1].startswith('---')] \
|
||||
+ order_choices([choice for choice in field.choices if not choice[1].startswith('---')])
|
||||
print field.choices
|
||||
|
||||
class Func2Iter(object):
|
||||
'''Transform a generator producing function into an iterator'''
|
||||
|
|
|
@ -30,6 +30,7 @@ from . import notification
|
|||
from .validators import phone_normalize, validate_fr_be_phone
|
||||
from .middleware import get_extra
|
||||
from .utils import mime_types_to_extensions, truncate_filename
|
||||
from . import fields
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -81,7 +82,8 @@ class ForwardingForm(RecipientForm, Form):
|
|||
self.default_sender = self.user
|
||||
delegations = User.objects.filter(
|
||||
Q(id=self.user.id) |
|
||||
Q(delegations_to__to=self.user)).distinct()
|
||||
Q(delegations_to__to=self.user)) \
|
||||
.order_by('last_name', 'first_name', 'username').distinct()
|
||||
super(ForwardingForm, self).__init__(*args, **kwargs)
|
||||
if len(delegations) > 1:
|
||||
self.fields['sender'].queryset = delegations
|
||||
|
@ -173,6 +175,7 @@ class FileForm(RecipientForm, ModelForm):
|
|||
if len(self.delegations) > 1:
|
||||
self.fields['sender'].queryset = self.delegations
|
||||
self.fields['sender'].label_from_instance = lambda y: username(y)
|
||||
fields.order_field_choices(self.fields['sender'])
|
||||
else:
|
||||
self.layout.fields.remove('sender')
|
||||
del self.fields['sender']
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,187 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting field 'Mailbox.seen'
|
||||
db.delete_column(u'docbow_mailbox', 'seen')
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding field 'Mailbox.seen'
|
||||
db.add_column(u'docbow_mailbox', 'seen',
|
||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'auth.user': {
|
||||
'Meta': {'ordering': "['username']", 'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
u'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
u'docbow.attachedfile': {
|
||||
'Meta': {'object_name': 'AttachedFile'},
|
||||
'content': ('django.db.models.fields.files.FileField', [], {'max_length': '300'}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attached_files'", 'to': u"orm['docbow.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'kind': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.FileTypeAttachedFileKind']", 'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '300'})
|
||||
},
|
||||
u'docbow.automaticforwarding': {
|
||||
'Meta': {'object_name': 'AutomaticForwarding'},
|
||||
'filetypes': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'forwarding_rules'", 'symmetrical': 'False', 'to': u"orm['docbow.FileType']"}),
|
||||
'forward_to_list': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'as_recipient_forwarding_rules'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['docbow.MailingList']"}),
|
||||
'forward_to_user': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'as_recipient_forwarding_rules'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'originaly_to_user': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'as_original_recipient_forwarding_rules'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.content': {
|
||||
'Meta': {'ordering': "['description']", 'object_name': 'Content'},
|
||||
'description': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'docbow.delegation': {
|
||||
'Meta': {'ordering': "['by']", 'unique_together': "(('by', 'to'),)", 'object_name': 'Delegation', 'db_table': "'auth_delegation'"},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'delegations_to'", 'to': u"orm['auth.User']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'to': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'delegations_by'", 'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.deleteddocument': {
|
||||
'Meta': {'ordering': "('-document',)", 'object_name': 'DeletedDocument'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.deletedmailbox': {
|
||||
'Meta': {'object_name': 'DeletedMailbox'},
|
||||
'delegate': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.Mailbox']"})
|
||||
},
|
||||
u'docbow.docbowprofile': {
|
||||
'Meta': {'object_name': 'DocbowProfile'},
|
||||
'accept_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_guest': ('django.db.models.fields.BooleanField', [], {}),
|
||||
'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
|
||||
'personal_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
|
||||
},
|
||||
u'docbow.document': {
|
||||
'Meta': {'ordering': "['-date']", 'object_name': 'Document'},
|
||||
'_timestamp': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'filetype': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.FileType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'real_sender': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['docbow.Document']"}),
|
||||
'sender': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents_sent'", 'to': u"orm['auth.User']"}),
|
||||
'to_list': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['docbow.MailingList']", 'null': 'True', 'blank': 'True'}),
|
||||
'to_user': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'directly_received_documents'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.documentforwarded': {
|
||||
'Meta': {'object_name': 'DocumentForwarded'},
|
||||
'automatic': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'from_document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'document_forwarded_to'", 'to': u"orm['docbow.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'to_document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'document_forwarded_from'", 'to': u"orm['docbow.Document']"})
|
||||
},
|
||||
u'docbow.filetype': {
|
||||
'Meta': {'ordering': "['name']", 'object_name': 'FileType'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'})
|
||||
},
|
||||
u'docbow.filetypeattachedfilekind': {
|
||||
'Meta': {'ordering': "('file_type', 'position', 'name')", 'unique_together': "(('name', 'file_type'),)", 'object_name': 'FileTypeAttachedFileKind'},
|
||||
'cardinality': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
|
||||
'file_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.FileType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'mime_types': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'minimum': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {})
|
||||
},
|
||||
u'docbow.mailbox': {
|
||||
'Meta': {'ordering': "['-date']", 'object_name': 'Mailbox'},
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'deleted': ('django.db.models.fields.BooleanField', [], {}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mailboxes'", 'to': u"orm['docbow.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'outbox': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
|
||||
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.mailinglist': {
|
||||
'Meta': {'ordering': "['name']", 'object_name': 'MailingList'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'mailing_list_members': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'members_lists'", 'blank': 'True', 'to': u"orm['docbow.MailingList']"}),
|
||||
'members': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'mailing_lists'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
|
||||
},
|
||||
u'docbow.notification': {
|
||||
'Meta': {'ordering': "('-id',)", 'object_name': 'Notification'},
|
||||
'create_dt': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'ctx': ('picklefield.fields.PickledObjectField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.Document']", 'null': 'True', 'blank': 'True'}),
|
||||
'done': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'failure': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'kind': ('django.db.models.fields.CharField', [], {'default': "'new-document'", 'max_length': '32'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'docbow.seendocument': {
|
||||
'Meta': {'ordering': "('-document',)", 'object_name': 'SeenDocument'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.sendinglimitation': {
|
||||
'Meta': {'object_name': 'SendingLimitation'},
|
||||
'filetypes': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'filetype_limitation'", 'blank': 'True', 'to': u"orm['docbow.FileType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'lists': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'lists_limitation'", 'symmetrical': 'False', 'to': u"orm['docbow.MailingList']"}),
|
||||
'mailing_list': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['docbow.MailingList']", 'unique': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['docbow']
|
|
@ -0,0 +1,186 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting field 'Mailbox.deleted'
|
||||
db.delete_column(u'docbow_mailbox', 'deleted')
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding field 'Mailbox.deleted'
|
||||
db.add_column(u'docbow_mailbox', 'deleted',
|
||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'auth.user': {
|
||||
'Meta': {'ordering': "['username']", 'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
u'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
u'docbow.attachedfile': {
|
||||
'Meta': {'object_name': 'AttachedFile'},
|
||||
'content': ('django.db.models.fields.files.FileField', [], {'max_length': '300'}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attached_files'", 'to': u"orm['docbow.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'kind': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.FileTypeAttachedFileKind']", 'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '300'})
|
||||
},
|
||||
u'docbow.automaticforwarding': {
|
||||
'Meta': {'object_name': 'AutomaticForwarding'},
|
||||
'filetypes': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'forwarding_rules'", 'symmetrical': 'False', 'to': u"orm['docbow.FileType']"}),
|
||||
'forward_to_list': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'as_recipient_forwarding_rules'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['docbow.MailingList']"}),
|
||||
'forward_to_user': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'as_recipient_forwarding_rules'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'originaly_to_user': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'as_original_recipient_forwarding_rules'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.content': {
|
||||
'Meta': {'ordering': "['description']", 'object_name': 'Content'},
|
||||
'description': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'docbow.delegation': {
|
||||
'Meta': {'ordering': "['by']", 'unique_together': "(('by', 'to'),)", 'object_name': 'Delegation', 'db_table': "'auth_delegation'"},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'delegations_to'", 'to': u"orm['auth.User']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'to': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'delegations_by'", 'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.deleteddocument': {
|
||||
'Meta': {'ordering': "('-document',)", 'object_name': 'DeletedDocument'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.deletedmailbox': {
|
||||
'Meta': {'object_name': 'DeletedMailbox'},
|
||||
'delegate': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.Mailbox']"})
|
||||
},
|
||||
u'docbow.docbowprofile': {
|
||||
'Meta': {'object_name': 'DocbowProfile'},
|
||||
'accept_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_guest': ('django.db.models.fields.BooleanField', [], {}),
|
||||
'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
|
||||
'personal_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
|
||||
},
|
||||
u'docbow.document': {
|
||||
'Meta': {'ordering': "['-date']", 'object_name': 'Document'},
|
||||
'_timestamp': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'filetype': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.FileType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'real_sender': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['docbow.Document']"}),
|
||||
'sender': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents_sent'", 'to': u"orm['auth.User']"}),
|
||||
'to_list': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['docbow.MailingList']", 'null': 'True', 'blank': 'True'}),
|
||||
'to_user': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'directly_received_documents'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.documentforwarded': {
|
||||
'Meta': {'object_name': 'DocumentForwarded'},
|
||||
'automatic': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'from_document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'document_forwarded_to'", 'to': u"orm['docbow.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'to_document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'document_forwarded_from'", 'to': u"orm['docbow.Document']"})
|
||||
},
|
||||
u'docbow.filetype': {
|
||||
'Meta': {'ordering': "['name']", 'object_name': 'FileType'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'})
|
||||
},
|
||||
u'docbow.filetypeattachedfilekind': {
|
||||
'Meta': {'ordering': "('file_type', 'position', 'name')", 'unique_together': "(('name', 'file_type'),)", 'object_name': 'FileTypeAttachedFileKind'},
|
||||
'cardinality': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
|
||||
'file_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.FileType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'mime_types': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'minimum': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {})
|
||||
},
|
||||
u'docbow.mailbox': {
|
||||
'Meta': {'ordering': "['-date']", 'object_name': 'Mailbox'},
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mailboxes'", 'to': u"orm['docbow.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'outbox': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
|
||||
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.mailinglist': {
|
||||
'Meta': {'ordering': "['name']", 'object_name': 'MailingList'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'mailing_list_members': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'members_lists'", 'blank': 'True', 'to': u"orm['docbow.MailingList']"}),
|
||||
'members': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'mailing_lists'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
|
||||
},
|
||||
u'docbow.notification': {
|
||||
'Meta': {'ordering': "('-id',)", 'object_name': 'Notification'},
|
||||
'create_dt': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'ctx': ('picklefield.fields.PickledObjectField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.Document']", 'null': 'True', 'blank': 'True'}),
|
||||
'done': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'failure': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'kind': ('django.db.models.fields.CharField', [], {'default': "'new-document'", 'max_length': '32'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'docbow.seendocument': {
|
||||
'Meta': {'ordering': "('-document',)", 'object_name': 'SeenDocument'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['docbow.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
|
||||
},
|
||||
u'docbow.sendinglimitation': {
|
||||
'Meta': {'object_name': 'SendingLimitation'},
|
||||
'filetypes': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'filetype_limitation'", 'blank': 'True', 'to': u"orm['docbow.FileType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'lists': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'lists_limitation'", 'symmetrical': 'False', 'to': u"orm['docbow.MailingList']"}),
|
||||
'mailing_list': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['docbow.MailingList']", 'unique': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['docbow']
|
|
@ -385,9 +385,12 @@ class Document(Model):
|
|||
blob['files'].append(d)
|
||||
return blob
|
||||
|
||||
def sender_display(self):
|
||||
return username(self.sender)
|
||||
|
||||
def url(self):
|
||||
return urlparse.urljoin(app_settings.BASE_URL,
|
||||
reverse('inbox', kwargs=dict(mailbox_id=self.id)))
|
||||
reverse('inbox-message', kwargs=dict(mailbox_id=self.id)))
|
||||
|
||||
|
||||
class DeletedMailbox(Model):
|
||||
|
@ -647,8 +650,6 @@ class Mailbox(Model):
|
|||
related_name='documents')
|
||||
document = ForeignKey(Document, verbose_name=('Document'),
|
||||
related_name='mailboxes')
|
||||
seen = BooleanField(verbose_name=_('Seen'), blank=True)
|
||||
deleted = BooleanField(verbose_name=_('Deleted'), blank=True)
|
||||
outbox = BooleanField(verbose_name=_('Outbox message'), blank=True,
|
||||
default=False, db_index=True)
|
||||
date = DateTimeField(auto_now_add=True)
|
||||
|
@ -659,26 +660,10 @@ class Mailbox(Model):
|
|||
verbose_name_plural = _('Mailboxes')
|
||||
|
||||
def __unicode__(self):
|
||||
if self.seen and self.deleted:
|
||||
return _(u'seen and deleted mailbox entry {id} of user {user}:{user.id} created on '
|
||||
u'{date} for {document}').format(id=self.id, user=self.owner,
|
||||
date=self.date,
|
||||
document=self.document)
|
||||
elif self.deleted:
|
||||
return _(u'deleted mailbox entry {id} of user {user}:{user.id} created on '
|
||||
u'{date} for {document}').format(id=self.id, user=self.owner,
|
||||
date=self.date,
|
||||
document=self.document)
|
||||
elif self.seen:
|
||||
return _(u'seen mailbox entry {id} of user {user}:{user.id} created on '
|
||||
u'{date} for {document}').format(id=self.id, user=self.owner,
|
||||
date=self.date,
|
||||
document=self.document)
|
||||
else:
|
||||
return _(u'mailbox entry {id} of user {user}:{user.id} created on '
|
||||
u'{date} for {document}').format(id=self.id, user=self.owner,
|
||||
date=self.date,
|
||||
document=self.document)
|
||||
return _(u'mailbox entry {id} of user {user}:{user.id} created on '
|
||||
u'{date} for {document}').format(id=self.id, user=self.owner,
|
||||
date=self.date,
|
||||
document=self.document)
|
||||
|
||||
class DocbowUser(User):
|
||||
class Meta:
|
||||
|
@ -734,7 +719,8 @@ class SendingLimitation(Model):
|
|||
class DocbowProfile(Model):
|
||||
'''Hold extra user attributes'''
|
||||
user = OneToOneField(User, unique=True)
|
||||
is_guest = BooleanField(verbose_name=_('Guest user'), blank=True)
|
||||
is_guest = BooleanField(verbose_name=_('Guest user'), blank=True,
|
||||
default=False)
|
||||
mobile_phone = CharField(max_length=32, verbose_name=_('Mobile phone'),
|
||||
blank=True, validators=[validate_phone])
|
||||
personal_email = EmailField(_('personal email address'), blank=True,
|
||||
|
|
|
@ -131,7 +131,8 @@ def get_notifiers():
|
|||
|
||||
def process_notifications():
|
||||
notifiers = get_notifiers()
|
||||
for notification in models.Notification.objects.select_for_update().filter(done=False):
|
||||
for notification in models.Notification.objects.order_by('id') \
|
||||
.select_for_update().filter(done=False):
|
||||
for notifier in notifiers:
|
||||
failures = []
|
||||
try:
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
from django.db import connection
|
||||
|
||||
def get_sql(sql, params):
|
||||
'''
|
||||
Execute an SQL query and return the associated cursor.
|
||||
'''
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(sql, params)
|
||||
return cursor
|
||||
|
||||
def get_sql_count(sql, params):
|
||||
'''
|
||||
Execute a count on SUB-SELECT and return the count.
|
||||
'''
|
||||
cursor = get_sql('''SELECT COUNT(*) FROM (%s) AS CNT''' % sql, params)
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
def get_sql_ids(sql, params):
|
||||
'''
|
||||
Retrieve a list of numerical ids.
|
||||
'''
|
||||
cursor = get_sql(sql, params)
|
||||
return (row[0] for row in cursor.fetchall())
|
||||
|
||||
def get_complex_join(qs, sql, params):
|
||||
ids = list(get_sql_ids(sql, params))
|
||||
return qs.filter(pk__in=ids)
|
||||
|
||||
def get_unseen_documents_count(related_users, user):
|
||||
return get_sql_count(GET_UNSEEN_DOCUMENTS_SQL,
|
||||
(
|
||||
tuple(related_users.values_list('id', flat=True)),
|
||||
user.pk,
|
||||
))
|
||||
|
||||
def get_documents(qs, related_users, user, outbox):
|
||||
qs = get_complex_join(qs,
|
||||
GET_DOCUMENTS_SQL,
|
||||
( outbox, tuple(related_users.values_list('id', flat=True)), ))
|
||||
qs = qs.prefetch_related('to_list', 'to_user', 'mailboxes__owner')
|
||||
qs = qs.extra(select={ 'seen': SEEN_DOCUMENT % user.pk })
|
||||
return qs
|
||||
|
||||
GET_UNSEEN_DOCUMENTS_SQL = '''SELECT d.id
|
||||
FROM docbow_document AS d
|
||||
INNER JOIN docbow_mailbox AS mb
|
||||
ON mb.outbox = FALSE AND mb.document_id = d.id AND mb.owner_id IN %s
|
||||
LEFT JOIN docbow_seendocument as sd
|
||||
ON sd.document_id = d.id AND sd.user_id = %s
|
||||
WHERE sd.id IS NULL
|
||||
GROUP BY d.id, d.date
|
||||
ORDER BY d.date
|
||||
'''
|
||||
|
||||
GET_DOCUMENTS_SQL = '''SELECT d.id
|
||||
FROM docbow_document AS d
|
||||
INNER JOIN docbow_mailbox AS mb ON
|
||||
mb.outbox = %s AND mb.document_id = d.id AND mb.owner_id IN %s
|
||||
GROUP BY d.id, d.date
|
||||
ORDER BY d.date'''
|
||||
|
||||
SEEN_DOCUMENT = '''SELECT COUNT(*) > 0
|
||||
FROM docbow_seendocument
|
||||
WHERE
|
||||
docbow_seendocument.document_id = docbow_document.id
|
||||
and docbow_seendocument.user_id = %s'''
|
|
@ -135,8 +135,8 @@
|
|||
$(this).fadeOut(function () {
|
||||
if (data.errorThrown !== 'abort') {
|
||||
var file = data.files[index];
|
||||
file.error = file.error || data.errorThrown
|
||||
|| true;
|
||||
file.error = file.error || 'httpError'
|
||||
|| 'unknownError';
|
||||
that._renderDownload([file])
|
||||
.css('display', 'none')
|
||||
.replaceAll(this)
|
||||
|
@ -639,4 +639,4 @@
|
|||
|
||||
});
|
||||
|
||||
}(jQuery));
|
||||
}(jQuery));
|
||||
|
|
|
@ -103,7 +103,7 @@ class InboxTable(tables.Table):
|
|||
<span>{{ recipient_user|username }}</span>{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}''', orderable=False, verbose_name=_('recipients_header'))
|
||||
sender = tables.Column(
|
||||
accessor='sender', verbose_name=_('sender_header'))
|
||||
accessor='sender_display', verbose_name=_('sender_header'))
|
||||
#date = tables.Column(
|
||||
# accessor='date', verbose_name=_('date_header'))
|
||||
date = tables.TemplateColumn('{% load humantime %}{{ record.date|humantime }}',
|
||||
|
|
|
@ -24,11 +24,13 @@
|
|||
<td class="name">${name}</td>
|
||||
<td class="size">${sizef}</td>
|
||||
{{open_tv}}if error{{close_tv}}
|
||||
<td class="error" colspan="2">Error:
|
||||
{{open_tv}}if error === 'maxFileSize'{{close_tv}}File is too big
|
||||
{{open_tv}}else error === 'minFileSize'{{close_tv}}File is too small
|
||||
{{open_tv}}else error === 'acceptFileTypes'{{close_tv}}Filetype not allowed
|
||||
{{open_tv}}else error === 'maxNumberOfFiles'{{close_tv}}Max number of files exceeded
|
||||
<td class="error" colspan="2">{% trans "Error" %} :
|
||||
{{open_tv}}if error === 'maxFileSize'{{close_tv}}{% blocktrans %}File is too big, limit is {{ max_file_size }} bytes{% endblocktrans %}
|
||||
{{open_tv}}else error === 'minFileSize'{{close_tv}}{% trans "File is too small" %}
|
||||
{{open_tv}}else error === 'acceptFileTypes'{{close_tv}}{% trans "Filetype not allowed" %}
|
||||
{{open_tv}}else error === 'maxNumberOfFiles'{{close_tv}}{% trans "Max number of files exceeded" %}
|
||||
{{open_tv}}else error === 'httpError'{{close_tv}}{% trans "HTTP Error" %}
|
||||
{{open_tv}}else error === 'unknownError'{{close_tv}}{% trans "Unknown error" %}
|
||||
{{open_tv}}else{{close_tv}}${error}
|
||||
{{open_tv}}/if{{close_tv}}
|
||||
</td>
|
||||
|
@ -83,7 +85,7 @@
|
|||
<script type="text/javascript">
|
||||
$(function () {
|
||||
'use strict';
|
||||
$('#{{name}}-fileupload').fileupload({url: '{{upload_url}}', autoUpload: true, dropZone: $(document)});
|
||||
$('#{{name}}-fileupload').fileupload({url: '{{upload_url}}', maxFileSize: {{max_file_size}}, autoUpload: true, dropZone: $(document)});
|
||||
$.getJSON('{{ upload_url }}', function (files) {
|
||||
var fu = $('#{{name}}-fileupload').data('fileupload');
|
||||
fu._adjustMaxNumberOfFiles(-files.length);
|
||||
|
|
|
@ -4,9 +4,7 @@ from django.core.urlresolvers import reverse
|
|||
from django.utils.translation import ugettext as _
|
||||
|
||||
|
||||
from .. import views
|
||||
from .. import models
|
||||
from .. import app_settings
|
||||
from .. import views, models, app_settings, sql
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
@ -46,9 +44,8 @@ def menu(context):
|
|||
count = 0
|
||||
current = False
|
||||
if view_name == 'inbox':
|
||||
seen_documents = models.SeenDocument.objects.filter(user=request.user) \
|
||||
.values_list('document_id', flat=True)
|
||||
count = views.get_documents(request).exclude(id__in=seen_documents).count()
|
||||
related_users = views.get_related_users(request)
|
||||
count = sql.get_unseen_documents_count(related_users, request.user)
|
||||
# remove delegation view for guest accounts
|
||||
if models.is_guest(context['user']) and 'delegate' in view_name:
|
||||
continue
|
||||
|
|
|
@ -92,13 +92,12 @@ class BaseTestCase(TestCase):
|
|||
User.objects.create(username='user-%s' % i,
|
||||
email='user-%s@example.com' % i))
|
||||
DocbowProfile.objects.create(user=self.users[-1],
|
||||
personal_email='personal-email-user-%s@example.com')
|
||||
personal_email='personal-email-user-%s@example.com' % i)
|
||||
self.filetypes = []
|
||||
for i in range(10):
|
||||
self.filetypes.append(
|
||||
FileType.objects.create(name='filetype-%s' % i))
|
||||
self.documents = []
|
||||
self.files = []
|
||||
for i in range(10):
|
||||
self.documents.append(
|
||||
Document.objects.create(sender=self.users[(i+2) % 10],
|
||||
|
@ -106,7 +105,6 @@ class BaseTestCase(TestCase):
|
|||
self.documents[-1].to_user = [self.users[i % 10],
|
||||
self.users[(i+1) % 10]]
|
||||
for j in range(2):
|
||||
self.files.append(tempfile.NamedTemporaryFile())
|
||||
attached_file = AttachedFile(name='file%s' % j,
|
||||
document=self.documents[-1],
|
||||
kind=None)
|
||||
|
@ -114,6 +112,23 @@ class BaseTestCase(TestCase):
|
|||
attached_file.save()
|
||||
self.documents[-1].post()
|
||||
|
||||
class BasicTestCase(BaseTestCase):
|
||||
def test_notification_mail(self):
|
||||
from django.core import mail
|
||||
from django.core import management
|
||||
import re
|
||||
|
||||
management.call_command('notify')
|
||||
self.assertEquals(len(mail.outbox), 20)
|
||||
outbox = sorted(mail.outbox, key=lambda m: tuple(sorted(m.to)))
|
||||
MAIL_LINK_RE = re.compile('https?://[^/]+/inbox/\d+/')
|
||||
for message, i in zip(outbox, range(20)):
|
||||
recipient = self.users[i / 2]
|
||||
emails = [recipient.docbowprofile.personal_email, recipient.email]
|
||||
self.assertEquals(set(message.to), set(emails))
|
||||
match = MAIL_LINK_RE.search(message.body)
|
||||
self.assertIsNotNone(match)
|
||||
|
||||
class UtilsTestCase(BaseTestCase):
|
||||
def setUp(self):
|
||||
super(UtilsTestCase, self).setUp()
|
||||
|
|
|
@ -11,6 +11,7 @@ from django.shortcuts import get_object_or_404
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .models import FileTypeAttachedFileKind
|
||||
from . import app_settings
|
||||
|
||||
def get_paths_for_id(upload_id):
|
||||
storage = DefaultStorage()
|
||||
|
@ -70,6 +71,11 @@ def upload(request, transaction_id, file_kind=None):
|
|||
if request.method == 'POST' and request.FILES is not None:
|
||||
data = []
|
||||
for uploaded_file in request.FILES.values():
|
||||
if uploaded_file.size > app_settings.MAX_FILE_SIZE:
|
||||
message = _('File is too big, limit is %(max_file_size)s bytes')
|
||||
message = message % {'max_file_size': app_settings.MAX_FILE_SIZE}
|
||||
data.append({'name': uploaded_file.name, 'error': unicode(message) })
|
||||
continue
|
||||
if file_kind:
|
||||
if not file_kind.match_file(uploaded_file):
|
||||
message = _('invalid file type, check required '
|
||||
|
|
|
@ -39,6 +39,7 @@ from . import app_settings
|
|||
from . import unicodecsv
|
||||
from . import profile_views
|
||||
from .utils import date_to_aware_datetime
|
||||
from . import sql
|
||||
|
||||
|
||||
gettext_noop = lambda x: x
|
||||
|
@ -145,11 +146,13 @@ def send_file(request, file_type_id):
|
|||
except KeyError:
|
||||
reply_to = None
|
||||
if hasattr(request.user, 'delegate'):
|
||||
delegators = []
|
||||
delegators = User.objects.none()
|
||||
else:
|
||||
delegators = User.objects.filter(
|
||||
Q(id=request.user.id) |
|
||||
Q(delegations_to__to=request.user)).distinct()
|
||||
Q(delegations_to__to=request.user)) \
|
||||
.order_by('last_name', 'first_name', 'username') \
|
||||
.distinct()
|
||||
real_user = getattr(request.user, 'delegate', request.user)
|
||||
limitations = get_filetype_limitation(request.user)
|
||||
if limitations:
|
||||
|
@ -519,30 +522,16 @@ def get_related_users(request):
|
|||
delegations = request.user.delegations_by.select_related('by')
|
||||
if delegations:
|
||||
users.extend(delegation.by for delegation in delegations)
|
||||
request.session['related_users'] = users
|
||||
return request.session['related_users']
|
||||
|
||||
def get_documents(request, qs=None, outbox=False):
|
||||
'''Retrieve visible documents for the current user'''
|
||||
if qs is None:
|
||||
qs = Document.objects.all()
|
||||
related_users = get_related_users(request)
|
||||
mailboxes = Mailbox.objects.filter(owner__in=related_users,
|
||||
outbox=outbox)
|
||||
qs = qs.filter(mailboxes__in=mailboxes) \
|
||||
.exclude(deleteddocument__user=request.user)
|
||||
qs = qs.distinct()
|
||||
qs = qs.prefetch_related('to_list', 'to_user', 'mailboxes__owner')
|
||||
return qs
|
||||
request.session['related_users'] = [user.pk for user in users]
|
||||
return User.objects.filter(pk__in=request.session['related_users'])
|
||||
|
||||
class MailboxQuerysetMixin(object):
|
||||
def get_queryset(self):
|
||||
qs = super(MailboxQuerysetMixin, self).get_queryset()
|
||||
# manual join using private API, children don't do this at home
|
||||
qs.query.join((None, 'docbow_document', None, None))
|
||||
qs.query.join(('docbow_document', 'docbow_seendocument', 'id', 'document_id'), promote=True)
|
||||
qs = qs.extra(select={'seen': 'docbow_seendocument.id is not null'})
|
||||
return get_documents(self.request, qs=qs, outbox=self.outbox)
|
||||
if not hasattr(self, '_qs'):
|
||||
self._qs = sql.get_documents(qs, get_related_users(self.request),
|
||||
self.request.user, self.outbox).distinct()
|
||||
return self._qs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super(MailboxQuerysetMixin, self).get_context_data(**kwargs)
|
||||
|
|
|
@ -9,6 +9,8 @@ from django.template.loader import render_to_string
|
|||
|
||||
from upload_views import get_files_for_id
|
||||
|
||||
from . import app_settings
|
||||
|
||||
class TextInpuWithPredefinedValues(MultiWidget):
|
||||
CLIENT_CODE = '''
|
||||
<script type="text/javascript">
|
||||
|
@ -71,6 +73,7 @@ class JqueryFileUploadFileInput(MultiFileInput):
|
|||
'open_tv': '{{',
|
||||
'close_tv': '}}',
|
||||
'upload_url': self.url,
|
||||
'max_file_size': app_settings.MAX_FILE_SIZE,
|
||||
'extensions': self.extensions,
|
||||
'attached_file_kind': self.attached_file_kind,
|
||||
'files': self.files,
|
||||
|
|
|
@ -81,7 +81,21 @@ Pour archive dans /opt/archive les documents d'il y a plus d'un an::
|
|||
|
||||
/etc/init.d/docbow manage archive2 /opt/archive 366
|
||||
|
||||
Un répertoire /opt/archive/2013-01-01T16:34:34.343434/doc/ sera créé. Le
|
||||
sous-répertoire doc contiendra les fichiers attachés ainsi que les métadonnées
|
||||
du document tandis que le journal sera sauvegardé dans le fichier
|
||||
Un répertoire, nommé /opt/archive/2013-01-01T16:34:34.343434/doc/ par exemple,
|
||||
sera créé contenant un sous-répertoire par document. Chaque sous répertoire
|
||||
est nommé d'après l'identifiant du document en base il contient au moins 3
|
||||
fichiers:
|
||||
|
||||
Nom Description
|
||||
======================= ==================
|
||||
document.json la sérialisation JSON du modèle du document faite par
|
||||
Django
|
||||
attached_file_<id>.json la sérialisation JSON du modèle d'un fichier attaché
|
||||
<filename>.<ext> le contenu d'un fichier attaché, le même nom de
|
||||
fichier apparait dans le document JSON
|
||||
|
||||
Si plusieurs fichiers sont attachés à un même document, il y aura un fichier
|
||||
JSON et un fichier de contenu pour chacun d'entre eux.
|
||||
|
||||
Les lignes du journal seront sauvegardées dans le fichier
|
||||
/opt/archive/2013-01-01T16:34:34.343434/journal.txt
|
||||
|
|
|
@ -2,21 +2,21 @@ import os.path
|
|||
import json
|
||||
import datetime
|
||||
|
||||
from app_settings import PFWB_GED_DIRECTORY
|
||||
|
||||
from ..docbow.models import AttachedFile
|
||||
import models
|
||||
from . import app_settings, models
|
||||
|
||||
def push_document(signal, sender, instance, **kwargs):
|
||||
'''post-save signal handler, to push new documents inside the GED directory'''
|
||||
attached_file = instance
|
||||
document = attached_file.document
|
||||
if not PFWB_GED_DIRECTORY:
|
||||
if not app_settings.PFWB_GED_DIRECTORY:
|
||||
return
|
||||
try:
|
||||
plone_file_type = document.filetype.plonefiletype
|
||||
except models.PloneFileType.DoesNotExist:
|
||||
return
|
||||
tpl = '{sender.first_name} {sender.last_name} ({sender.username})'
|
||||
tpl = u'{sender.first_name} {sender.last_name} ({sender.username})'
|
||||
sender = tpl.format(sender=document.sender)
|
||||
metadata = {
|
||||
'document_id': document.id,
|
||||
|
@ -31,8 +31,8 @@ def push_document(signal, sender, instance, **kwargs):
|
|||
name = os.path.basename(attached_file.name)
|
||||
name = '%s-%s-%s' % (document.id, datetime.datetime.now().isoformat(), name)
|
||||
json_name = name + '.json'
|
||||
path = os.path.join(PFWB_GED_DIRECTORY, name)
|
||||
path_json = os.path.join(PFWB_GED_DIRECTORY, json_name)
|
||||
path = os.path.join(app_settings.PFWB_GED_DIRECTORY, name)
|
||||
path_json = os.path.join(app_settings.PFWB_GED_DIRECTORY, json_name)
|
||||
with open(path, 'w') as f:
|
||||
f.write(attached_file.content.read())
|
||||
with open(path_json, 'w') as f:
|
||||
|
|
|
@ -1,21 +1,48 @@
|
|||
from django.conf import settings
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# directory where ged files are stored
|
||||
PFWB_GED_DIRECTORY = getattr(settings, 'DOCBOW_PFWB_GED_DIRECTORY', None)
|
||||
|
||||
# default type id for documents received by SMTP when given type does not exist
|
||||
PFWB_SENDMAIL_DEFAULT_TYPE_ID = getattr(settings, 'DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_ID', None)
|
||||
# default type name if default type id does not exist
|
||||
PFWB_SENDMAIL_DEFAULT_TYPE_NAME = getattr(settings, 'DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_NAME', 'Divers')
|
||||
# sender email for document received from tabellio expedition by SMTP
|
||||
PFWB_SENDMAIL_TABELLIO_EXPEDITION_EMAIL = getattr(settings,
|
||||
'DOCBOW_PFWB_SENDMAIL_TABELLIO_EXPEDITION_EMAIL', 'commande.documents@pfwb.be')
|
||||
# user id of senders for document received from tabellio expedition by SMTP
|
||||
PFWB_SENDMAIL_TABELLIO_EXPEDITION_USER_ID = getattr(settings,
|
||||
'DOCBOW_PFWB_SENDMAIL_TABELLIO_EXPEDITION_USER_ID', None)
|
||||
# sender email for document received by SMTP (generic code)
|
||||
PFWB_SENDMAIL_ATTACHED_FILE_EMAIL = getattr(settings,
|
||||
'DOCBOW_PFWB_SENDMAIL_ATTACHED_FILE_EMAIL', None)
|
||||
# user id of senders for document received by SMTP (generic code)
|
||||
PFWB_SENDMAIL_ATTACHED_FILE_USER_ID = getattr(settings,
|
||||
'DOCBOW_PFWB_SENDMAIL_ATTACHED_FILE_USER_ID', None)
|
||||
class AppSettings(object):
|
||||
'''Thanks django-allauth'''
|
||||
__DEFAULTS = dict(
|
||||
# directory where ged files are stored
|
||||
PFWB_GED_DIRECTORY = None,
|
||||
# default type id for documents received by SMTP when given type does
|
||||
# not exist
|
||||
PFWB_SENDMAIL_DEFAULT_TYPE_ID = None,
|
||||
# default type name if default type id does not exist
|
||||
PFWB_SENDMAIL_DEFAULT_TYPE_NAME = 'Divers',
|
||||
# sender email for document received from tabellio expedition by SMTP
|
||||
PFWB_SENDMAIL_TABELLIO_EXPEDITION_EMAIL = 'commande.documents@pfwb.be',
|
||||
# user id of senders for document received from tabellio expedition by SMTP
|
||||
PFWB_SENDMAIL_TABELLIO_EXPEDITION_USER_ID = None,
|
||||
# sender email for document received by SMTP (generic code)
|
||||
PFWB_SENDMAIL_ATTACHED_FILE_EMAIL = None,
|
||||
# user id of senders for document received by SMTP (generic code)
|
||||
PFWB_SENDMAIL_ATTACHED_FILE_USER_ID = None,
|
||||
)
|
||||
|
||||
def __init__(self, prefix):
|
||||
self.prefix = prefix
|
||||
|
||||
@property
|
||||
def settings(self):
|
||||
from django.conf import settings
|
||||
return settings
|
||||
|
||||
def __getattr__(self, key):
|
||||
if key in self.__DEFAULTS:
|
||||
return getattr(self.settings,
|
||||
self.prefix+key, self.__DEFAULTS[key])
|
||||
else:
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
try:
|
||||
return getattr(self.settings, self.prefix+key)
|
||||
except AttributeError:
|
||||
raise ImproperlyConfigured('settings %s is missing' % self.prefix+key)
|
||||
|
||||
|
||||
app_settings = AppSettings('DOCBOW_')
|
||||
app_settings.__name__ = __name__
|
||||
app_settings.__file__ = __file__
|
||||
import sys
|
||||
sys.modules[__name__] = app_settings
|
||||
|
|
|
@ -11,7 +11,6 @@ import urllib2
|
|||
from django.core.management.base import BaseCommand
|
||||
import django.contrib.auth.models as auth_models
|
||||
from django.core.files.base import ContentFile
|
||||
from django.db import transaction
|
||||
from django.core.exceptions import MultipleObjectsReturned
|
||||
from django.utils.timezone import utc, make_aware
|
||||
from django.template.defaultfilters import slugify
|
||||
|
@ -19,6 +18,10 @@ from django.template.defaultfilters import slugify
|
|||
from docbow_project.docbow import models, timestamp, utils
|
||||
from docbow_project.docbow.email_utils import u2u_decode
|
||||
from django_journal import record
|
||||
try:
|
||||
from django.db.transaction import atomic
|
||||
except ImportError:
|
||||
from django.db.transaction import commit_on_success as atomic
|
||||
|
||||
from ... import app_settings
|
||||
|
||||
|
@ -96,7 +99,7 @@ In case of failure the following return value is returned:
|
|||
return None
|
||||
return self.mailing_lists.get(username[len('liste-'):])
|
||||
|
||||
@transaction.commit_on_success
|
||||
@atomic
|
||||
def handle_mail(self, mail, mail_recipients, **options):
|
||||
content_errors = []
|
||||
attachments = []
|
||||
|
|
|
@ -9,6 +9,9 @@ import tempfile
|
|||
import sys
|
||||
from contextlib import contextmanager
|
||||
from StringIO import StringIO
|
||||
from functools import wraps
|
||||
|
||||
MEDIA_ROOT = tempfile.mkdtemp()
|
||||
|
||||
@contextmanager
|
||||
def captured_output():
|
||||
|
@ -25,6 +28,7 @@ class stderr_output(object):
|
|||
self.output = output
|
||||
|
||||
def __call__(self, func):
|
||||
@wraps(func)
|
||||
def f(testcase, *args, **kwargs):
|
||||
with captured_output() as (out, err):
|
||||
ret = func(testcase, *args, **kwargs)
|
||||
|
@ -32,13 +36,27 @@ class stderr_output(object):
|
|||
return ret
|
||||
return f
|
||||
|
||||
class stdout_output(object):
|
||||
def __init__(self, output):
|
||||
self.output = output
|
||||
|
||||
def __call__(self, func):
|
||||
@wraps(func)
|
||||
def f(testcase, *args, **kwargs):
|
||||
with captured_output() as (out, err):
|
||||
ret = func(testcase, *args, **kwargs)
|
||||
testcase.assertEqual(self.output, out.getvalue())
|
||||
return ret
|
||||
return f
|
||||
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
from django.core import management
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from docbow_project.pfwb.models import TabellioDocType
|
||||
from docbow_project.docbow.models import FileType, MailingList, Document
|
||||
from docbow_project.pfwb.models import TabellioDocType, PloneFileType
|
||||
from docbow_project.docbow.models import (FileType, MailingList, Document,
|
||||
AttachedFile)
|
||||
|
||||
import django_journal
|
||||
|
||||
|
@ -50,12 +68,10 @@ RECIPIENT_LIST_EMAIL = 'liste-ma-liste@example.com'
|
|||
@override_settings(DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_NAME='Default')
|
||||
@override_settings(DOCBOW_PFWB_SENDMAIL_TABELLIO_EXPEDITION_EMAIL=EXPEDITION_EMAIL)
|
||||
@override_settings(DOCBOW_PFWB_SENDMAIL_TABELLIO_EXPEDITION_USER_ID=1)
|
||||
@override_settings(PFWB_GED_DIRECTORY='/tmp')
|
||||
@override_settings(DOCBOW_PFWB_GED_DIRECTORY=None)
|
||||
@override_settings(MEDIA_ROOT=MEDIA_ROOT)
|
||||
class SendMailTestCase(TestCase):
|
||||
def setUp(self):
|
||||
import app_settings
|
||||
reload(app_settings)
|
||||
|
||||
self.pjd_filetype = FileType.objects.create(name='PJD', id=2)
|
||||
self.tabellio_doc_type = TabellioDocType.objects.create(filetype=self.pjd_filetype,
|
||||
tabellio_doc_type='PJD')
|
||||
|
@ -174,3 +190,179 @@ Coucou''', EXPEDITION_EMAIL, RECIPIENT_EMAIL, 'PJD', 'Mouais: monfichier.pdf')
|
|||
self.assertEquals(Document.objects.get().to_user.count(), 0)
|
||||
self.assertEquals(Document.objects.get().to_list.count(), 1)
|
||||
self.assertEquals(Document.objects.get().to_list.all()[0], self.to_list)
|
||||
|
||||
@override_settings(DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_ID=1)
|
||||
@override_settings(DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_NAME='Default')
|
||||
@override_settings(DOCBOW_PFWB_SENDMAIL_ATTACHED_FILE_EMAIL=EXPEDITION_EMAIL)
|
||||
@override_settings(DOCBOW_PFWB_SENDMAIL_ATTACHED_FILE_USER_ID=1)
|
||||
@override_settings(DOCBOW_PFWB_GED_DIRECTORY=None)
|
||||
@override_settings(MEDIA_ROOT=MEDIA_ROOT)
|
||||
class SendMailAttachedFileTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.pjd_filetype = FileType.objects.create(name='PJD', id=2)
|
||||
self.tabellio_doc_type = TabellioDocType.objects.create(filetype=self.pjd_filetype,
|
||||
tabellio_doc_type='PJD')
|
||||
self.expedition_user = User.objects.create(username='expedition', id=1)
|
||||
self.to_user = User.objects.create(username='recipient', email=RECIPIENT_EMAIL, id=2)
|
||||
self.to_list = MailingList.objects.create(name='ma liste')
|
||||
self.to_list.members.add(self.to_user)
|
||||
|
||||
def build_message(self, filetype, to_addr, from_addr, content, attached_files):
|
||||
from email import encoders
|
||||
from email.header import Header
|
||||
from email.mime.base import MIMEBase
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
import random
|
||||
|
||||
message = MIMEMultipart()
|
||||
message['Subject'] = Header(unicode(filetype), 'utf-8')
|
||||
message['To'] = Header(to_addr, 'utf-8')
|
||||
message['From'] = Header(from_addr, 'utf-8')
|
||||
message['Message-ID'] = '<%s@example.com>' % random.random()
|
||||
msg = MIMEText(content, _subtype='plain')
|
||||
message.attach(msg)
|
||||
for filename, content in attached_files:
|
||||
msg = MIMEBase('application', 'octet-stream')
|
||||
msg.set_payload(content)
|
||||
msg.add_header('Content-Disposition', 'attachment', filename=filename)
|
||||
encoders.encode_base64(msg)
|
||||
message.attach(msg)
|
||||
return message.as_string()
|
||||
|
||||
@stderr_output('')
|
||||
def test_attached_file1(self):
|
||||
with tempfile.NamedTemporaryFile() as f:
|
||||
f.write(self.build_message(
|
||||
self.pjd_filetype,
|
||||
EXPEDITION_EMAIL,
|
||||
RECIPIENT_EMAIL,
|
||||
'coucou',
|
||||
(('attached-file', 'content'),)))
|
||||
f.flush()
|
||||
management.call_command('sendmail', RECIPIENT_EMAIL, file=f.name,
|
||||
sender=EXPEDITION_EMAIL)
|
||||
self.assertEqual(Document.objects.count(), 1)
|
||||
document = Document.objects.get()
|
||||
self.assertEquals(document.attached_files.count(), 1)
|
||||
self.assertEquals(document.comment, 'coucou')
|
||||
self.assertEquals(document.attached_files.get().name, 'attached-file')
|
||||
self.assertEquals(document.attached_files.get().content.read(),
|
||||
'content')
|
||||
self.assertEquals(document.to_user.count(), 1)
|
||||
self.assertEquals(document.to_list.count(), 0)
|
||||
self.assertEquals(document.to_user.get(), self.to_user)
|
||||
|
||||
@override_settings(MEDIA_ROOT=MEDIA_ROOT)
|
||||
class PushDocumentTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.ged_dir = tempfile.mkdtemp()
|
||||
|
||||
def tearDown(self):
|
||||
import shutil
|
||||
shutil.rmtree(self.ged_dir)
|
||||
|
||||
def test_push_document1(self):
|
||||
from django.core.files.base import ContentFile
|
||||
import os.path
|
||||
from glob import glob
|
||||
|
||||
with self.settings(DOCBOW_PFWB_GED_DIRECTORY=self.ged_dir):
|
||||
FROM_USERNAME = 'from_user'
|
||||
FROM_FIRST_NAME = 'from_first_name'
|
||||
FROM_LAST_NAME = 'from_last_name'
|
||||
self.from_user = User.objects.create(username=FROM_USERNAME,
|
||||
first_name=FROM_FIRST_NAME, last_name=FROM_LAST_NAME)
|
||||
self.to_user = User.objects.create(username='to_user')
|
||||
self.filetype = FileType.objects.create(name='filetype')
|
||||
self.plone_filetype = PloneFileType.objects.create(filetype=self.filetype,
|
||||
plone_portal_type='plone-portal-type')
|
||||
DESCRIPTION = 'description'
|
||||
self.document = Document.objects.create(sender=self.from_user,
|
||||
filetype=self.filetype,
|
||||
comment=DESCRIPTION)
|
||||
self.attached_file = AttachedFile(name='attached-file',
|
||||
document=self.document, kind=None)
|
||||
CONTENT = 'content'
|
||||
self.attached_file.content.save('attached-file',
|
||||
ContentFile(CONTENT))
|
||||
pattern1 = '{0}-*-{1}.json'.format(self.document.id,
|
||||
self.attached_file.name)
|
||||
pattern2 = '{0}-*-{1}'.format(self.document.id,
|
||||
self.attached_file.name)
|
||||
files1 = glob(os.path.join(self.ged_dir, pattern1))
|
||||
files2 = glob(os.path.join(self.ged_dir, pattern2))
|
||||
self.assertEquals(len(files1), 1)
|
||||
self.assertEquals(len(files2), 1)
|
||||
with file(files2[0]) as f:
|
||||
self.assertEquals(f.read(), CONTENT)
|
||||
import json
|
||||
with file(files1[0]) as f:
|
||||
json_content = json.loads(f.read())
|
||||
self.assertIsNotNone(json_content)
|
||||
self.assertEquals(json_content['document_id'], self.document.id)
|
||||
self.assertEquals(json_content['plone_portal_type'],
|
||||
self.plone_filetype.plone_portal_type)
|
||||
self.assertEquals(json_content['title'],
|
||||
unicode(self.filetype))
|
||||
self.assertEquals(json_content['description'], DESCRIPTION)
|
||||
self.assertEquals(json_content['sender'],
|
||||
u'{0} {1} ({2})'.format(FROM_FIRST_NAME,
|
||||
FROM_LAST_NAME, FROM_USERNAME))
|
||||
|
||||
@override_settings(MEDIA_ROOT=MEDIA_ROOT)
|
||||
@override_settings(DOCBOW_PFWB_GED_DIRECTORY=None)
|
||||
class ArchiveTestCase(TestCase):
|
||||
def setUp(self):
|
||||
import datetime
|
||||
from django.core.files.base import ContentFile
|
||||
|
||||
self.archive_dir = tempfile.mkdtemp()
|
||||
FROM_USERNAME = 'from_user'
|
||||
FROM_FIRST_NAME = 'from_first_name'
|
||||
FROM_LAST_NAME = 'from_last_name'
|
||||
self.from_user = User.objects.create(username=FROM_USERNAME,
|
||||
first_name=FROM_FIRST_NAME, last_name=FROM_LAST_NAME)
|
||||
self.to_user = User.objects.create(username='to_user')
|
||||
self.filetype = FileType.objects.create(name='filetype')
|
||||
self.plone_filetype = PloneFileType.objects.create(filetype=self.filetype,
|
||||
plone_portal_type='plone-portal-type')
|
||||
DESCRIPTION = 'description'
|
||||
self.document = Document.objects.create(sender=self.from_user,
|
||||
filetype=self.filetype,
|
||||
comment=DESCRIPTION,
|
||||
date=datetime.date.today()-datetime.timedelta(days=366))
|
||||
self.attached_file = AttachedFile(name='attached-file',
|
||||
document=self.document, kind=None)
|
||||
CONTENT = 'content'
|
||||
self.attached_file.content.save('attached-file',
|
||||
ContentFile(CONTENT))
|
||||
|
||||
def tearDown(self):
|
||||
import shutil
|
||||
|
||||
shutil.rmtree(self.archive_dir)
|
||||
|
||||
def test_archive(self):
|
||||
import os.path
|
||||
import glob
|
||||
import datetime
|
||||
|
||||
with captured_output() as (out, err):
|
||||
management.call_command('archive2', self.archive_dir, 100)
|
||||
l = glob.glob(os.path.join(self.archive_dir, '*'))
|
||||
self.assertEquals(len(l), 1)
|
||||
self.assertTrue(l[0].split('T')[0],
|
||||
datetime.datetime.today().isoformat())
|
||||
archive_dir = os.path.join(self.archive_dir, l[0])
|
||||
self.assertTrue(os.path.exists(os.path.join(archive_dir, 'doc')))
|
||||
self.assertTrue(os.path.exists(os.path.join(archive_dir, 'doc',
|
||||
str(self.document.id))))
|
||||
self.assertTrue(os.path.exists(os.path.join(archive_dir, 'doc',
|
||||
str(self.document.id), 'document.json')))
|
||||
self.assertTrue(os.path.exists(os.path.join(archive_dir, 'doc',
|
||||
str(self.document.id), 'attached_file_%s.json' %
|
||||
self.attached_file.id)))
|
||||
self.assertTrue(os.path.exists(os.path.join(archive_dir,
|
||||
'journal.txt')))
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ __ENVIRONMENT_DEFAULTS = dict(
|
|||
'docbow_project.docbow.notification.MailNotifier',
|
||||
'docbow_project.docbow.notification.SMSNotifier',
|
||||
),
|
||||
DOCBOW_PFWB_GED_DIRECTORY='/var/lib/%s/ged/',
|
||||
DOCBOW_PFWB_GED_DIRECTORY='/var/lib/docbow/ged/',
|
||||
DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_ID=None,
|
||||
DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_NAME=u'Divers',
|
||||
DOCBOW_PFWB_SENDMAIL_TABELLIO_EXPEDITION_EMAIL='commande.documents@pfwb.be',
|
||||
|
@ -79,6 +79,7 @@ __ENVIRONMENT_DEFAULTS = dict(
|
|||
CRISPY_TEMPLATE_PACK='uni_form',
|
||||
DOCBOW_TIMESTAMP_PROVIDER='certum',
|
||||
RAVEN_CONFIG_DSN='',
|
||||
DOCBOW_MAX_FILE_SIZE=10*1024*1024,
|
||||
)
|
||||
|
||||
for key, default in __ENVIRONMENT_DEFAULTS.iteritems():
|
||||
|
@ -98,6 +99,8 @@ for key, default in __ENVIRONMENT_DEFAULTS.iteritems():
|
|||
value = [ unicode(x, 'utf8') for x in value ]
|
||||
elif isinstance(default, unicode):
|
||||
value = unicode(value, 'utf8')
|
||||
elif isinstance(default, int):
|
||||
value = int(value)
|
||||
except KeyError:
|
||||
value = default
|
||||
globals()[key] = value
|
||||
|
@ -129,6 +132,8 @@ else:
|
|||
'django.template.loaders.app_directories.Loader',)),
|
||||
)
|
||||
|
||||
ATOMIC_REQUESTS = True
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
|
@ -265,7 +270,6 @@ else:
|
|||
"email": "mail"
|
||||
}
|
||||
|
||||
DEBUG_TOOLBAR_CONFIG = {}
|
||||
|
||||
try:
|
||||
from local_settings import *
|
||||
|
@ -293,10 +297,7 @@ if DEBUG and 'SECRET_KEY' not in globals():
|
|||
if USE_DEBUG_TOOLBAR:
|
||||
try:
|
||||
import debug_toolbar
|
||||
MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',)
|
||||
INSTALLED_APPS += ('debug_toolbar',)
|
||||
if 'INTERCEPT_REDIRECTS' not in DEBUG_TOOLBAR_CONFIG:
|
||||
DEBUG_TOOLBAR_CONFIG.update({ 'INTERCEPT_REDIRECTS': False })
|
||||
except ImportError:
|
||||
print "Debug toolbar missing, not loaded"
|
||||
|
||||
|
|
|
@ -11,9 +11,10 @@ pyasn1<1.0.0
|
|||
pyasn1-modules<1.0.0
|
||||
rfc3161==0.1.9
|
||||
gunicorn
|
||||
django_journal<2.0.0
|
||||
django_journal>=1.23.0,<2.0.0
|
||||
django-picklefield==0.3.0
|
||||
git+http://repos.entrouvert.org/python-entrouvert.git/#egg=python-entrouvert-99999>=2
|
||||
http://repos.entrouvert.org/python-entrouvert.git/snapshot/python-entrouvert-master.tar.bz2#egg=python-entrouvert-99999>=2
|
||||
django-tables2==0.13.0
|
||||
python-magic<0.5
|
||||
raven
|
||||
pytz
|
||||
|
|
2
setup.py
2
setup.py
|
@ -26,7 +26,7 @@ class compile_translations(Command):
|
|||
continue
|
||||
curdir = os.getcwd()
|
||||
os.chdir(os.path.realpath(path))
|
||||
compile_messages(stderr=sys.stderr)
|
||||
compile_messages(sys.stderr)
|
||||
os.chdir(curdir)
|
||||
|
||||
class build(_build):
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
cd /home/docbow/source/
|
||||
su docbow -c 'git pull'
|
||||
cd docbow_project/docbow
|
||||
su docbow -c '/home/docbow/env/bin/pip install -r ../../requirements.txt'
|
||||
su docbow -c '/home/docbow/env/bin/python ../../docbow-ctl compilemessages'
|
||||
/etc/init.d/docbow manage syncdb --migrate
|
||||
/etc/init.d/docbow manage collectstatic --noinput
|
||||
/etc/init.d/docbow restart
|
|
@ -0,0 +1,98 @@
|
|||
|
||||
<html>
|
||||
<head>
|
||||
<title>Candlestick Chart</title>
|
||||
<script type="text/javascript" src="http://cachedcommons.org/cache/protovis/3.2.0/javascripts/protovis.js"></script>
|
||||
<script type="text/javascript" src="vix.js"></script>
|
||||
<style type="text/css">
|
||||
|
||||
#fig {
|
||||
position: relative;
|
||||
margin: auto;
|
||||
width: 900px;
|
||||
height: 220px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table border="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Path</th>
|
||||
<th>Min</th>
|
||||
<th>Mean</th>
|
||||
<th>Std</th>
|
||||
<th>Max</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<script>
|
||||
for (var i = 0; i < vix.length; i++) {
|
||||
var d = vix[i];
|
||||
document.write("<tr><td>" + d.path + "</td><td>" + d.min + "</td><td>" + d.mean + "</td><td>" + d.std + "</td><td>" + d.max + "</td></tr>");
|
||||
}
|
||||
</script>
|
||||
|
||||
</tbody>
|
||||
<caption>Datas</caption>
|
||||
</table>
|
||||
|
||||
<div id="center"><div id="fig">
|
||||
<script type="text/javascript+protovis">
|
||||
|
||||
/* Scales. */
|
||||
var w = 840,
|
||||
h = 200,
|
||||
x = pv.Scale.ordinal(vix, function(d) d.path).split(20, w-20),
|
||||
y = pv.Scale.linear(vix, function(d) d.min, function(d) d.max).range(0, h).nice();
|
||||
|
||||
var vis = new pv.Panel()
|
||||
.width(w)
|
||||
.height(h)
|
||||
.margin(10)
|
||||
.left(30);
|
||||
|
||||
/* Paths. */
|
||||
vis.add(pv.Rule)
|
||||
.data(vix)
|
||||
.strokeStyle("#eee")
|
||||
.anchor("bottom").add(pv.Label)
|
||||
.left(function (d) x(d.path))
|
||||
.text(function (d) d.path);
|
||||
|
||||
/* Time. */
|
||||
vis.add(pv.Rule)
|
||||
.data(y.ticks(7))
|
||||
.bottom(y)
|
||||
.left(-10)
|
||||
.right(-10)
|
||||
.strokeStyle(function(d) d % 10 ? "#ccc" : "#333")
|
||||
.anchor("left").add(pv.Label)
|
||||
.textStyle(function(d) d % 10 ? "#999" : "#333")
|
||||
.text(y.tickFormat)
|
||||
.anchor("top").add(pv.Label)
|
||||
.top(-12)
|
||||
.left(-20)
|
||||
.font("bold 10px sans-serif")
|
||||
.text("ms");
|
||||
|
||||
/* Candlestick. */
|
||||
vis.add(pv.Rule)
|
||||
.data(vix)
|
||||
.left(function(d) x(d.path))
|
||||
.bottom(function(d) y(d.mean - 2*Math.sqrt(d.std)))
|
||||
.height(function(d) 4*Math.sqrt(d.std))
|
||||
.strokeStyle("#ae13ff")
|
||||
.lineWidth(10)
|
||||
.add(pv.Rule)
|
||||
.bottom(function(d) y(Math.min(d.min, d.max)))
|
||||
.height(function(d) Math.abs(y(d.max) - y(d.min)))
|
||||
.strokeStyle("#ae1325")
|
||||
.lineWidth(3);
|
||||
|
||||
vis.render();
|
||||
|
||||
</script>
|
||||
</div></div></body>
|
||||
</html>
|
|
@ -0,0 +1,99 @@
|
|||
var vix =
|
||||
[
|
||||
{
|
||||
"std": 6.2838809338783808,
|
||||
"min": 48.87890815734863,
|
||||
"max": 117.35892295837402,
|
||||
"median": 51.397800445556641,
|
||||
"path": "/inbox/",
|
||||
"mean": 52.986168217014622
|
||||
},
|
||||
{
|
||||
"std": 5.0712567658069432,
|
||||
"min": 25.820016860961914,
|
||||
"max": 93.6269760131836,
|
||||
"median": 27.652978897094727,
|
||||
"path": "/outbox/",
|
||||
"mean": 28.302782935065192
|
||||
},
|
||||
{
|
||||
"std": 17.959943957167141,
|
||||
"min": 9.320974349975586,
|
||||
"max": 77.15797424316406,
|
||||
"median": 13.239860534667969,
|
||||
"path": "/inbox/66/",
|
||||
"mean": 22.619637927493535
|
||||
},
|
||||
{
|
||||
"std": 16.905766906795069,
|
||||
"min": 9.452104568481445,
|
||||
"max": 104.50601577758789,
|
||||
"median": 55.394887924194336,
|
||||
"path": "/inbox/28/",
|
||||
"mean": 53.443717956542969
|
||||
},
|
||||
{
|
||||
"std": 20.719964490781539,
|
||||
"min": 9.491920471191406,
|
||||
"max": 110.88180541992188,
|
||||
"median": 14.102935791015625,
|
||||
"path": "/inbox/55/",
|
||||
"mean": 24.875629270398939
|
||||
},
|
||||
{
|
||||
"std": 19.056132820228122,
|
||||
"min": 9.421825408935547,
|
||||
"max": 74.40400123596191,
|
||||
"median": 13.787031173706055,
|
||||
"path": "/inbox/73/",
|
||||
"mean": 23.699891889417493
|
||||
},
|
||||
{
|
||||
"std": 19.59120154967297,
|
||||
"min": 9.75489616394043,
|
||||
"max": 70.6789493560791,
|
||||
"median": 14.936923980712891,
|
||||
"path": "/inbox/81/",
|
||||
"mean": 25.634705053793418
|
||||
},
|
||||
{
|
||||
"std": 19.731671888538365,
|
||||
"min": 9.202957153320312,
|
||||
"max": 86.27200126647949,
|
||||
"median": 14.432907104492188,
|
||||
"path": "/inbox/69/",
|
||||
"mean": 24.82308697056126
|
||||
},
|
||||
{
|
||||
"std": 19.466554907855816,
|
||||
"min": 9.569168090820312,
|
||||
"max": 67.42000579833984,
|
||||
"median": 14.648199081420898,
|
||||
"path": "/inbox/45/",
|
||||
"mean": 24.809984258703285
|
||||
},
|
||||
{
|
||||
"std": 20.643612271940331,
|
||||
"min": 10.020017623901367,
|
||||
"max": 77.55303382873535,
|
||||
"median": 15.462160110473633,
|
||||
"path": "/inbox/60/",
|
||||
"mean": 26.355472770897119
|
||||
},
|
||||
{
|
||||
"std": 20.20322737222353,
|
||||
"min": 9.835958480834961,
|
||||
"max": 76.26891136169434,
|
||||
"median": 15.053033828735352,
|
||||
"path": "/inbox/74/",
|
||||
"mean": 25.443387675929714
|
||||
},
|
||||
{
|
||||
"std": 20.45568343764522,
|
||||
"min": 9.819984436035156,
|
||||
"max": 79.49686050415039,
|
||||
"median": 15.069961547851562,
|
||||
"path": "/inbox/62/",
|
||||
"mean": 25.949336387015677
|
||||
}
|
||||
];
|
Loading…
Reference in New Issue